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 }