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