annotate tango/lib/compiler/llvmdc/deh2.d @ 270:d9d5d59873d8 trunk

[svn r291] Fixed a bunch of the old Phobos tests to work with Tango. Branch statements now emit a new block after it. Fixed the _adSort runtime function had a bad signature. Added a missing dot prefix on compiler generated string tables for string switch. Fixed, PTRSIZE seems like it was wrong on 64bit, now it definitely gets set properly.
author lindquist
date Mon, 16 Jun 2008 16:01:19 +0200
parents 5cb946f323d2
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
154
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
1 /*
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
2 * Copyright (C) 1999-2005 by Digital Mars, www.digitalmars.com
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
3 * Written by Walter Bright
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
4 *
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
5 * This software is provided 'as-is', without any express or implied
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
6 * warranty. In no event will the authors be held liable for any damages
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
7 * arising from the use of this software.
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
8 *
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
9 * Permission is granted to anyone to use this software for any purpose,
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
10 * including commercial applications, and to alter it and redistribute it
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
11 * freely, in both source and binary form, subject to the following
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
12 * restrictions:
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
13 *
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
14 * o The origin of this software must not be misrepresented; you must not
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
15 * claim that you wrote the original software. If you use this software
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
16 * in a product, an acknowledgment in the product documentation would be
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
17 * appreciated but is not required.
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
18 * o Altered source versions must be plainly marked as such, and must not
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
19 * be misrepresented as being the original software.
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
20 * o This notice may not be removed or altered from any source
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
21 * distribution.
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
22 */
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
23
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
24 // Exception handling support for linux
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
25
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
26 //debug=1;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
27
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
28 extern (C)
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
29 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
30 extern void* _deh_beg;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
31 extern void* _deh_end;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
32
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
33 int _d_isbaseof(ClassInfo oc, ClassInfo c);
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
34 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
35
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
36 // One of these is generated for each function with try-catch or try-finally
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
37 // all of these structs are located between _deh_beg and _deh_end
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
38 struct FuncTable
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
39 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
40 void *fptr; // pointer to start of function
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
41 DHandlerTable *handlertable; // eh data for this function
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
42 uint fsize; // size of function in bytes
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
43 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
44
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
45 // lists all try-catch and try-finally blocks for a given function
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
46 // searched for by eh_finddata()
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
47 struct DHandlerTable
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
48 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
49 void *fptr; // pointer to start of function, used but seems redundant
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
50 uint espoffset; // offset of ESP from EBP
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
51 uint retoffset; // offset from start of function to return code, unused!
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
52 uint nhandlers; // dimension of handler_info[]
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
53 DHandlerInfo handler_info[1];
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
54 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
55
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
56 // information for a single try-finally or try-catch block
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
57 struct DHandlerInfo
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
58 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
59 uint offset; // offset from function address to start of guarded section
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
60 uint endoffset; // offset of end of guarded section
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
61 int enclosing_index; // enclosing table index, for nested trys
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
62 uint cioffset; // offset to DCatchInfo data from start of DHandlerTable
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
63 // (!=0 if try-catch)
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
64 void *finally_code; // pointer to finally code to execute
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
65 // (!=0 if try-finally)
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
66 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
67
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
68 // Create one of these for each try-catch
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
69 struct DCatchInfo
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
70 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
71 uint ncatches; // number of catch blocks
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
72 DCatchBlock catch_block[1]; // data for each catch block
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
73 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
74
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
75 // one for each catch in try-catch
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
76 struct DCatchBlock
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
77 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
78 ClassInfo type; // catch type
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
79 uint bpoffset; // EBP offset of catch var
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
80 void *code; // catch handler code
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
81 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
82
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
83
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
84 alias int (*fp_t)(); // function pointer in ambient memory model
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
85
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
86 void terminate()
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
87 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
88 asm
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
89 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
90 hlt ;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
91 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
92 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
93
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
94 /*******************************************
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
95 * Given address that is inside a function,
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
96 * figure out which function it is in.
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
97 * Return DHandlerTable if there is one, NULL if not.
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
98 */
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
99
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
100 DHandlerTable *__eh_finddata(void *address)
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
101 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
102 FuncTable *ft;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
103
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
104 // debug printf("__eh_finddata(address = x%x)\n", address);
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
105 // debug printf("_deh_beg = x%x, _deh_end = x%x\n", &_deh_beg, &_deh_end);
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
106 for (ft = cast(FuncTable *)&_deh_beg;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
107 ft < cast(FuncTable *)&_deh_end;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
108 ft++)
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
109 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
110 // debug printf("\tfptr = x%x, fsize = x%03x, handlertable = x%x\n",
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
111 // ft.fptr, ft.fsize, ft.handlertable);
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
112
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
113 if (ft.fptr <= address &&
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
114 address < cast(void *)(cast(char *)ft.fptr + ft.fsize))
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
115 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
116 // debug printf("\tfound handler table\n");
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
117 return ft.handlertable;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
118 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
119 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
120 // debug printf("\tnot found\n");
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
121 return null;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
122 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
123
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
124
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
125 /******************************
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
126 * Given EBP, find return address to caller, and caller's EBP.
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
127 * Input:
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
128 * regbp Value of EBP for current function
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
129 * *pretaddr Return address
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
130 * Output:
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
131 * *pretaddr return address to caller
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
132 * Returns:
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
133 * caller's EBP
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
134 */
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
135
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
136 uint __eh_find_caller(uint regbp, uint *pretaddr)
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
137 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
138 uint bp = *cast(uint *)regbp;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
139
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
140 if (bp) // if not end of call chain
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
141 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
142 // Perform sanity checks on new EBP.
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
143 // If it is screwed up, terminate() hopefully before we do more damage.
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
144 if (bp <= regbp)
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
145 // stack should grow to smaller values
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
146 terminate();
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
147
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
148 *pretaddr = *cast(uint *)(regbp + int.sizeof);
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
149 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
150 return bp;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
151 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
152
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
153 /***********************************
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
154 * Throw a D object.
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
155 */
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
156
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
157 extern (Windows) void _d_throw(Object *h)
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
158 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
159 uint regebp;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
160
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
161 debug
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
162 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
163 printf("_d_throw(h = %p, &h = %p)\n", h, &h);
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
164 printf("\tvptr = %p\n", *cast(void **)h);
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
165 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
166
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
167 asm
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
168 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
169 mov regebp,EBP ;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
170 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
171
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
172 while (1) // for each function on the stack
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
173 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
174 DHandlerTable *handler_table;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
175 FuncTable *pfunc;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
176 DHandlerInfo *handler;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
177 uint calleraddr;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
178 uint funcoffset;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
179 int index;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
180 int dim;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
181 int ndx;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
182 int enclosing_ndx;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
183
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
184 regebp = __eh_find_caller(regebp,&calleraddr);
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
185 if (!regebp)
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
186 { // if end of call chain
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
187 debug printf("end of call chain\n");
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
188 break;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
189 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
190 debug printf("found caller, EBP = x%x, calleraddr = x%x\n", regebp, calleraddr);
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
191
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
192 // find DHandlerTable associated with function
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
193 handler_table = __eh_finddata(cast(void *)calleraddr);
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
194 if (!handler_table) // if no static data
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
195 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
196 debug printf("no handler table\n");
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
197 continue;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
198 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
199 funcoffset = cast(uint)handler_table.fptr;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
200
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
201 debug
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
202 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
203 printf("calleraddr = x%x\n",cast(uint)calleraddr);
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
204 printf("regebp=x%04x, funcoffset=x%04x, spoff=x%x, retoffset=x%x\n",
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
205 regebp,funcoffset,handler_table.espoffset,handler_table.retoffset);
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
206 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
207
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
208 dim = handler_table.nhandlers;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
209
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
210 debug
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
211 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
212 printf("handler_info[]:\n");
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
213 for (int i = 0; i < dim; i++)
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
214 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
215 handler = &handler_table.handler_info[i];
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
216 printf("\t[%d]: offset = x%04x, endoffset = x%04x, enclosing_index = %d, cioffset = x%04x, finally_code = %x\n",
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
217 i, handler.offset, handler.endoffset, handler.enclosing_index, handler.cioffset, handler.finally_code);
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
218 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
219 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
220
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
221 // Find index of DHandlerInfo coresponding to the innermost
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
222 // try block wrapping calleraddr
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
223 index = -1;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
224 for (int i = 0; i < dim; i++)
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
225 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
226 handler = &handler_table.handler_info[i];
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
227
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
228 debug printf("i = %d, handler.offset = %04x\n", i, funcoffset + handler.offset);
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
229 if (cast(uint)calleraddr > funcoffset + handler.offset &&
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
230 cast(uint)calleraddr <= funcoffset + handler.endoffset)
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
231 index = i; // don't break if found, want innermost try
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
232 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
233 debug printf("index = %d\n", index);
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
234
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
235 // walk through handler infos for all try blocks enclosing the call,
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
236 // starting with the innermost one we just found
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
237 for (ndx = index; ndx != -1; ndx = enclosing_ndx)
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
238 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
239 handler = &handler_table.handler_info[ndx];
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
240 enclosing_ndx = handler.enclosing_index;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
241
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
242 if (handler.cioffset)
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
243 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
244 // this is a catch handler (no finally)
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
245 DCatchInfo *pci;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
246 int ncatches;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
247 int i;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
248
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
249 pci = cast(DCatchInfo *)(cast(char *)handler_table + handler.cioffset);
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
250 ncatches = pci.ncatches;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
251 for (i = 0; i < ncatches; i++)
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
252 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
253 DCatchBlock *pcb;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
254 ClassInfo ci = **cast(ClassInfo **)h;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
255
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
256 pcb = &pci.catch_block[i];
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
257
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
258 if (_d_isbaseof(ci, pcb.type))
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
259 { // Matched the catch type, so we've found the handler.
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
260
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
261 // Initialize catch variable
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
262 *cast(void **)(regebp + (pcb.bpoffset)) = h;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
263
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
264 // Jump to catch block. Does not return.
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
265 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
266 uint catch_esp;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
267 fp_t catch_addr;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
268
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
269 catch_addr = cast(fp_t)(pcb.code);
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
270 catch_esp = regebp - handler_table.espoffset - fp_t.sizeof;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
271 asm
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
272 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
273 mov EAX,catch_esp ;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
274 mov ECX,catch_addr ;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
275 mov [EAX],ECX ;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
276 mov EBP,regebp ;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
277 mov ESP,EAX ; // reset stack
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
278 ret ; // jump to catch block
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
279 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
280 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
281 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
282 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
283 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
284 else if (handler.finally_code)
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
285 { // Call finally block
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
286 // Note that it is unnecessary to adjust the ESP, as the finally block
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
287 // accesses all items on the stack as relative to EBP.
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
288
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
289 void *blockaddr = handler.finally_code;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
290
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
291 asm
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
292 {
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
293 push EBX ;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
294 mov EBX,blockaddr ;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
295 push EBP ;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
296 mov EBP,regebp ;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
297 call EBX ;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
298 pop EBP ;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
299 pop EBX ;
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
300 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
301 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
302 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
303 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
304 }
5cb946f323d2 [svn r160] Added cleaned version of dmd's linux exception runtime
ChristianK
parents:
diff changeset
305