annotate tango/lib/compiler/llvmdc/deh2.d @ 154:5cb946f323d2 trunk

[svn r160] Added cleaned version of dmd's linux exception runtime
author ChristianK
date Tue, 25 Mar 2008 18:25:24 +0100
parents
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