root/trunk/src/eh.c

Revision 714, 7.0 kB (checked in by walter, 2 years ago)

64 bit WIP

  • Property svn:eol-style set to native
Line 
1 /*
2  * Copyright (c) 1994-1998 by Symantec
3  * Copyright (c) 2000-2010 by Digital Mars
4  * All Rights Reserved
5  * http://www.digitalmars.com
6  * http://www.dsource.org/projects/dmd/browser/branches/dmd-1.x/src/eh.c
7  * http://www.dsource.org/projects/dmd/browser/trunk/src/eh.c
8  * Written by Walter Bright
9  *
10  * This source file is made available for personal use
11  * only. The license is in /dmd/src/dmd/backendlicense.txt
12  * For any other uses, please contact Digital Mars.
13  */
14
15 // Support for D exception handling
16
17 #include        <stdio.h>
18 #include        <string.h>
19 #include        <time.h>
20
21 #include        "cc.h"
22 #include        "el.h"
23 #include        "code.h"
24 #include        "oper.h"
25 #include        "global.h"
26 #include        "type.h"
27 #include        "dt.h"
28
29 static char __file__[] = __FILE__;      /* for tassert.h                */
30 #include        "tassert.h"
31
32 /****************************
33  * Generate and output scope table.
34  */
35
36 symbol *except_gentables()
37 {
38     //printf("except_gentables()\n");
39 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
40     symbol *s;
41     int sz;                     // size so far
42     dt_t **pdt;
43     unsigned fsize;             // target size of function pointer
44     long spoff;
45     block *b;
46     int guarddim;
47     int i;
48
49     // BUG: alloca() changes the stack size, which is not reflected
50     // in the fixed eh tables.
51     assert(!usedalloca);
52
53     s = symbol_generate(SCstatic,tsint);
54     s->Sseg = UNKNOWN;
55     symbol_keep(s);
56     symbol_debug(s);
57
58     fsize = NPTRSIZE;
59     pdt = &s->Sdt;
60     sz = 0;
61
62     /*
63         void*           pointer to start of function
64         unsigned        offset of ESP from EBP
65         unsigned        offset from start of function to return code
66         unsigned nguards;       // dimension of guard[]
67         {   unsigned offset;    // offset of start of guarded section
68             unsigned endoffset; // ending offset of guarded section
69             int last_index;     // previous index (enclosing guarded section)
70             unsigned catchoffset;       // offset to catch block from symbol
71             void *finally;      // finally code to execute
72         } guard[];
73       catchoffset:
74         unsigned ncatches;      // number of catch blocks
75         {   void *type;         // symbol representing type
76             unsigned bpoffset;  // EBP offset of catch variable
77             void *handler;      // catch handler code
78         } catch[];
79      */
80 #define GUARD_SIZE      (I64 ? 3*8 : 5*4)     // number of bytes in one guard
81
82     sz = 0;
83
84     // Address of start of function
85     symbol_debug(funcsym_p);
86     pdt = dtxoff(pdt,funcsym_p,0,TYnptr);
87     sz += fsize;
88
89     //printf("ehtables: func = %s, offset = x%x, startblock->Boffset = x%x\n", funcsym_p->Sident, funcsym_p->Soffset, startblock->Boffset);
90
91     // Get offset of ESP from EBP
92     spoff = cod3_spoff();
93     pdt = dtdword(pdt,spoff);
94     sz += 4;
95
96     // Offset from start of function to return code
97     pdt = dtdword(pdt,retoffset);
98     sz += 4;
99
100     // First, calculate starting catch offset
101     guarddim = 0;                               // max dimension of guard[]
102     for (b = startblock; b; b = b->Bnext)
103     {
104         if (b->BC == BC_try && b->Bscope_index >= guarddim)
105             guarddim = b->Bscope_index + 1;
106 //      printf("b->BC = %2d, Bscope_index = %2d, last_index = %2d, offset = x%x\n",
107 //              b->BC, b->Bscope_index, b->Blast_index, b->Boffset);
108     }
109
110     pdt = dtsize_t(pdt,guarddim);
111     sz += NPTRSIZE;
112
113     unsigned catchoffset = sz + guarddim * GUARD_SIZE;
114
115     // Generate guard[]
116     i = 0;
117     for (b = startblock; b; b = b->Bnext)
118     {
119         //printf("b = %p, b->Btry = %p, b->offset = %x\n", b, b->Btry, b->Boffset);
120         if (b->BC == BC_try)
121         {
122             assert(b->Bscope_index >= i);
123             if (i < b->Bscope_index)
124             {   int fillsize = (b->Bscope_index - i) * GUARD_SIZE;
125                 pdt = dtnzeros(pdt, fillsize);
126                 sz += fillsize;
127             }
128             i = b->Bscope_index + 1;
129
130             int nsucc = list_nitems(b->Bsucc);
131             //printf("DHandlerInfo: offset = %x", (int)(b->Boffset - startblock->Boffset));
132             pdt = dtdword(pdt,b->Boffset - startblock->Boffset);        // offset to start of block
133
134             // Compute ending offset
135             unsigned endoffset;
136             for (block *bn = b->Bnext; 1; bn = bn->Bnext)
137             {
138                 //printf("\tbn = %p, bn->Btry = %p, bn->offset = %x\n", bn, bn->Btry, bn->Boffset);
139                 assert(bn);
140                 if (bn->Btry == b->Btry)
141                 {    endoffset = bn->Boffset - startblock->Boffset;
142                      break;
143                 }
144             }
145             //printf(" endoffset = %x, prev_index = %d\n", endoffset, b->Blast_index);
146             pdt = dtdword(pdt,endoffset);               // offset past end of guarded block
147
148             pdt = dtdword(pdt,b->Blast_index);          // parent index
149
150             if (b->jcatchvar)                           // if try-catch
151             {
152                 pdt = dtdword(pdt,catchoffset);
153                 pdt = dtsize_t(pdt,0);                  // no finally handler
154
155                 catchoffset += NPTRSIZE + (nsucc - 1) * (3 * NPTRSIZE);
156             }
157             else                                        // else try-finally
158             {
159                 assert(nsucc == 2);
160                 pdt = dtdword(pdt,0);           // no catch offset
161                 block *bhandler = list_block(list_next(b->Bsucc));
162                 assert(bhandler->BC == BC_finally);
163                 // To successor of BC_finally block
164                 bhandler = list_block(bhandler->Bsucc);
165                 pdt = dtxoff(pdt,funcsym_p,bhandler->Boffset - startblock->Boffset, TYnptr);    // finally handler address
166                 //pdt = dtcoff(pdt,bhandler->Boffset);  // finally handler address
167             }
168             sz += GUARD_SIZE;
169         }
170     }
171
172     // Generate catch[]
173     for (b = startblock; b; b = b->Bnext)
174     {
175         if (b->BC == BC_try)
176         {   block *bhandler;
177             int nsucc;
178
179             if (b->jcatchvar)                           // if try-catch
180             {   list_t bl;
181
182                 nsucc = list_nitems(b->Bsucc);
183                 pdt = dtsize_t(pdt,nsucc - 1);           // # of catch blocks
184                 sz += NPTRSIZE;
185
186                 for (bl = list_next(b->Bsucc); bl; bl = list_next(bl))
187                 {
188                     block *bcatch = list_block(bl);
189
190                     pdt = dtxoff(pdt,bcatch->Bcatchtype,0,TYjhandle);
191
192                     pdt = dtsize_t(pdt,cod3_bpoffset(b->jcatchvar));     // EBP offset
193
194                     pdt = dtxoff(pdt,funcsym_p,bcatch->Boffset - startblock->Boffset, TYnptr);  // catch handler address
195                     //pdt = dtcoff(pdt,bcatch->Boffset);        // catch handler address
196
197                     sz += 3 * NPTRSIZE;
198                 }
199             }
200         }
201     }
202     assert(sz != 0);
203
204     outdata(s);                 // output the scope table
205
206     obj_ehtables(funcsym_p,funcsym_p->Ssize,s);
207 #endif
208     return NULL;
209 }
Note: See TracBrowser for help on using the browser.