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