void nteh_gentables() { symbol *s = s_table; symbol_debug(s); #if MARS //except_fillInEHTable(s); #else /* NTEH table for C. * The table consists of triples: * parent index * filter address * handler address */ unsigned fsize = 4; // target size of function pointer dt_t **pdt = &s->Sdt; int sz = 0; // size so far for (block *b = startblock; b; b = b->Bnext) { if (b->BC == BC_try) { dt_t *dt; block *bhandler; pdt = dtdword(pdt,b->Blast_index); // parent index // If try-finally if (list_nitems(b->Bsucc) == 2) { pdt = dtdword(pdt,0); // filter address bhandler = list_block(list_next(b->Bsucc)); assert(bhandler->BC == BC_finally); // To successor of BC_finally block bhandler = list_block(bhandler->Bsucc); } else // try-except { bhandler = list_block(list_next(b->Bsucc)); assert(bhandler->BC == BC_filter); pdt = dtcoff(pdt,bhandler->Boffset); // filter address bhandler = list_block(list_next(list_next(b->Bsucc))); assert(bhandler->BC == BC_except); } pdt = dtcoff(pdt,bhandler->Boffset); // handler address sz += 4 + fsize * 2; } } assert(sz != 0); #endif outdata(s); // output the scope table #if MARS nteh_framehandler(s); #endif s_table = NULL; }
static void list_block(char *path, int rec) { ERROR("Listing %s", path); DIR *d = opendir(path); if(!d) { ERROR("Failed to open %s", path); return; } struct dirent *dr; struct stat info; while((dr = readdir(d))) { if(dr->d_name[0] == '.') continue; ERROR("%s/%s (%d)", path, dr->d_name, dr->d_type); if(dr->d_type == 4 && rec) { char name[256]; sprintf(name, "%s/%s", path, dr->d_name); list_block(name, 1); } } closedir(d); }
STATIC void pe_add(block *b) { list_t bl; if (b->Bflags & BFLoutsideprolog || need_prolog(b)) return; b->Bflags |= BFLoutsideprolog; for (bl = b->Bsucc; bl; bl = list_next(bl)) pe_add(list_block(bl)); }
void WRblocklist(list_t bl) { for (; bl; bl = list_next(bl)) { register block *b = list_block(bl); if (b && b->Bweight) dbg_printf("B%d (%p) ",b->Bdfoidx,b); else dbg_printf("%p ",b); } ferr("\n"); }
void comsubs() { register block *bl,*blc,*bln; register int n; /* # of blocks to treat as one */ //static int xx; //printf("comsubs() %d\n", ++xx); //debugx = (xx == 37); #ifdef DEBUG if (debugx) dbg_printf("comsubs(%p)\n",startblock); #endif // No longer do we just compute Bcount. We now eliminate unreachable // blocks. block_compbcount(); // eliminate unreachable blocks #if SCPP if (errcnt) return; #endif if (!csvec) { csvec = vec_calloc(CSVECDIM); } for (bl = startblock; bl; bl = bln) { bln = bl->Bnext; if (!bl->Belem) continue; /* if no expression or no parents */ // Count up n, the number of blocks in this extended basic block (EBB) n = 1; // always at least one block in EBB blc = bl; while (bln && list_nitems(bln->Bpred) == 1 && ((blc->BC == BCiftrue && list_block(list_next(blc->Bsucc)) == bln) || (blc->BC == BCgoto && list_block(blc->Bsucc) == bln) ) && bln->BC != BCasm // no CSE's extending across ASM blocks ) { n++; // add block to EBB blc = bln; bln = blc->Bnext; } vec_clear(csvec); hcstop = 0; touchstari = 0; touchfunci[0] = 0; touchfunci[1] = 0; bln = bl; while (n--) // while more blocks in EBB { #ifdef DEBUG if (debugx) dbg_printf("cses for block %p\n",bln); #endif if (bln->Belem) ecom(&bln->Belem); // do the tree bln = bln->Bnext; } } #ifdef DEBUG if (debugx) dbg_printf("done with comsubs()\n"); #endif }
void WRblock(block *b) { if (OPTIMIZER) { if (b && b->Bweight) dbg_printf("B%d: (%p), weight=%d",b->Bdfoidx,b,b->Bweight); else dbg_printf("block %p",b); if (!b) { ferr("\n"); return; } dbg_printf(" flags=x%x weight=%d",b->Bflags,b->Bweight); #if 0 dbg_printf("\tfile %p, line %d",b->Bfilptr,b->Blinnum); #endif dbg_printf(" "); WRBC(b->BC); dbg_printf(" Btry=%p Bindex=%d",b->Btry,b->Bindex); #if SCPP if (b->BC == BCtry) dbg_printf(" catchvar = %p",b->catchvar); #endif dbg_printf("\n"); dbg_printf("\tBpred: "); WRblocklist(b->Bpred); dbg_printf("\tBsucc: "); WRblocklist(b->Bsucc); if (b->Belem) { if (debugf) /* if full output */ elem_print(b->Belem); else { ferr("\t"); WReqn(b->Belem); dbg_printf(";\n"); } } if (b->Bcode) b->Bcode->print(); ferr("\n"); } else { targ_llong *pu; int ncases; list_t bl; assert(b); dbg_printf("********* Basic Block %p ************\n",b); if (b->Belem) elem_print(b->Belem); dbg_printf("block: "); WRBC(b->BC); dbg_printf(" Btry=%p Bindex=%d",b->Btry,b->Bindex); dbg_printf("\n"); dbg_printf("\tBpred:\n"); for (bl = b->Bpred; bl; bl = list_next(bl)) dbg_printf("\t%p\n",list_block(bl)); bl = b->Bsucc; switch (b->BC) { case BCswitch: pu = b->BS.Bswitch; assert(pu); ncases = *pu; dbg_printf("\tncases = %d\n",ncases); dbg_printf("\tdefault: %p\n",list_block(bl)); while (ncases--) { bl = list_next(bl); dbg_printf("\tcase %lld: %p\n",*++pu,list_block(bl)); } break; case BCiftrue: case BCgoto: case BCasm: #if SCPP case BCtry: case BCcatch: #endif case BCjcatch: case BC_try: case BC_filter: case BC_finally: case BC_ret: case BC_except: Lsucc: dbg_printf("\tBsucc:\n"); for ( ; bl; bl = list_next(bl)) dbg_printf("\t%p\n",list_block(bl)); break; case BCret: case BCretexp: case BCexit: break; default: assert(0); } } }
void except_fillInEHTable(symbol *s) { unsigned fsize = NPTRSIZE; // target size of function pointer dt_t **pdt = &s->Sdt; /* void* pointer to start of function (Windows) unsigned offset of ESP from EBP unsigned offset from start of function to return code unsigned nguards; // dimension of guard[] (Linux) Guard guard[]; // sorted such that the enclosing guarded sections come first catchoffset: unsigned ncatches; // number of catch blocks { void *type; // symbol representing type unsigned bpoffset; // EBP offset of catch variable void *handler; // catch handler code } catch[]; */ /* Be careful of this, as we need the sizeof Guard on the target, not * in the compiler. */ unsigned GUARD_SIZE; if (OUREH) GUARD_SIZE = (I64 ? 3*8 : 5*4); else GUARD_SIZE = 3*4; int sz = 0; // Address of start of function if (OUREH) { } else { symbol_debug(funcsym_p); pdt = dtxoff(pdt,funcsym_p,0,TYnptr); sz += fsize; } //printf("ehtables: func = %s, offset = x%x, startblock->Boffset = x%x\n", funcsym_p->Sident, funcsym_p->Soffset, startblock->Boffset); // Get offset of ESP from EBP long spoff = cod3_spoff(); pdt = dtdword(pdt,spoff); sz += 4; // Offset from start of function to return code pdt = dtdword(pdt,retoffset); sz += 4; // First, calculate starting catch offset int guarddim = 0; // max dimension of guard[] int ndctors = 0; // number of ESCdctor's for (block *b = startblock; b; b = b->Bnext) { if (b->BC == BC_try && b->Bscope_index >= guarddim) guarddim = b->Bscope_index + 1; // printf("b->BC = %2d, Bscope_index = %2d, last_index = %2d, offset = x%x\n", // b->BC, b->Bscope_index, b->Blast_index, b->Boffset); if (usednteh & EHcleanup) for (code *c = b->Bcode; c; c = code_next(c)) { if (c->Iop == (ESCAPE | ESCddtor)) ndctors++; } } //printf("guarddim = %d, ndctors = %d\n", guarddim, ndctors); if (OUREH) { pdt = dtsize_t(pdt,guarddim + ndctors); sz += NPTRSIZE; } unsigned catchoffset = sz + (guarddim + ndctors) * GUARD_SIZE; // Generate guard[] int i = 0; for (block *b = startblock; b; b = b->Bnext) { //printf("b = %p, b->Btry = %p, b->offset = %x\n", b, b->Btry, b->Boffset); if (b->BC == BC_try) { assert(b->Bscope_index >= i); if (i < b->Bscope_index) { int fillsize = (b->Bscope_index - i) * GUARD_SIZE; pdt = dtnzeros(pdt, fillsize); sz += fillsize; } i = b->Bscope_index + 1; int nsucc = list_nitems(b->Bsucc); if (OUREH) { //printf("DHandlerInfo: offset = %x", (int)(b->Boffset - startblock->Boffset)); pdt = dtdword(pdt,b->Boffset - startblock->Boffset); // offset to start of block // Compute ending offset unsigned endoffset; for (block *bn = b->Bnext; 1; bn = bn->Bnext) { //printf("\tbn = %p, bn->Btry = %p, bn->offset = %x\n", bn, bn->Btry, bn->Boffset); assert(bn); if (bn->Btry == b->Btry) { endoffset = bn->Boffset - startblock->Boffset; break; } } //printf(" endoffset = %x, prev_index = %d\n", endoffset, b->Blast_index); pdt = dtdword(pdt,endoffset); // offset past end of guarded block } pdt = dtdword(pdt,b->Blast_index); // parent index if (b->jcatchvar) // if try-catch { assert(catchoffset); pdt = dtdword(pdt,catchoffset); pdt = dtsize_t(pdt,0); // no finally handler catchoffset += NPTRSIZE + (nsucc - 1) * (3 * NPTRSIZE); } else // else try-finally { assert(nsucc == 2); pdt = dtdword(pdt,0); // no catch offset block *bhandler = list_block(list_next(b->Bsucc)); assert(bhandler->BC == BC_finally); // To successor of BC_finally block bhandler = list_block(bhandler->Bsucc); // finally handler address if (OUREH) { assert(bhandler->Boffset > startblock->Boffset); pdt = dtsize_t(pdt,bhandler->Boffset - startblock->Boffset); // finally handler offset } else pdt = dtcoff(pdt,bhandler->Boffset); } sz += GUARD_SIZE; } } /* Append to guard[] the guard blocks for temporaries that are created and destroyed * within a single expression. These are marked by the special instruction pairs * (ESCAPE | ESCdctor) and (ESCAPE | ESCddtor). */ if (usednteh & EHcleanup) { int scopeindex = guarddim; for (block *b = startblock; b; b = b->Bnext) { /* Set up stack of scope indices */ #define STACKINC 16 int stackbuf[STACKINC]; int *stack = stackbuf; int stackmax = STACKINC; stack[0] = b->Btry ? b->Btry->Bscope_index : -1; int stacki = 1; unsigned boffset = b->Boffset; for (code *c = b->Bcode; c; c = code_next(c)) { if (c->Iop == (ESCAPE | ESCdctor)) { code *c2 = code_next(c); if (config.flags2 & CFG2seh) nteh_patchindex(c2, scopeindex); if (OUREH) pdt = dtdword(pdt,boffset - startblock->Boffset); // guard offset // Find corresponding ddtor instruction int n = 0; unsigned eoffset = boffset; unsigned foffset; for (; 1; c2 = code_next(c2)) { assert(c2); if (c2->Iop == (ESCAPE | ESCddtor)) { if (n) n--; else { foffset = eoffset; code *cf = code_next(c2); if (config.flags2 & CFG2seh) { nteh_patchindex(cf, stack[stacki - 1]); foffset += calccodsize(cf); cf = code_next(cf); } foffset += calccodsize(cf); while (!cf->isJumpOP()) { cf = code_next(cf); foffset += calccodsize(cf); } cf = code_next(cf); foffset += calccodsize(cf); if (OUREH) pdt = dtdword(pdt,eoffset - startblock->Boffset); // guard offset break; } } else if (c2->Iop == (ESCAPE | ESCdctor)) { n++; } else eoffset += calccodsize(c2); } //printf("boffset = %x, eoffset = %x, foffset = %x\n", boffset, eoffset, foffset); pdt = dtdword(pdt,stack[stacki - 1]); // parent index pdt = dtdword(pdt,0); // no catch offset if (OUREH) { assert(foffset > startblock->Boffset); pdt = dtsize_t(pdt,foffset - startblock->Boffset); // finally handler offset } else pdt = dtcoff(pdt,foffset); // finally handler address if (stacki == stackmax) { // stack[] is out of space; enlarge it int *pi = (int *)alloca((stackmax + STACKINC) * sizeof(int)); assert(pi); memcpy(pi, stack, stackmax * sizeof(int)); stack = pi; stackmax += STACKINC; } stack[stacki++] = scopeindex; ++scopeindex; sz += GUARD_SIZE; } else if (c->Iop == (ESCAPE | ESCddtor)) { stacki--; assert(stacki != 0); } boffset += calccodsize(c); } } } // Generate catch[] for (block *b = startblock; b; b = b->Bnext) { if (b->BC == BC_try && b->jcatchvar) // if try-catch { int nsucc = list_nitems(b->Bsucc); pdt = dtsize_t(pdt,nsucc - 1); // # of catch blocks sz += NPTRSIZE; for (list_t bl = list_next(b->Bsucc); bl; bl = list_next(bl)) { block *bcatch = list_block(bl); pdt = dtxoff(pdt,bcatch->Bcatchtype,0,TYjhandle); pdt = dtsize_t(pdt,cod3_bpoffset(b->jcatchvar)); // EBP offset // catch handler address if (OUREH) { assert(bcatch->Boffset > startblock->Boffset); pdt = dtsize_t(pdt,bcatch->Boffset - startblock->Boffset); // catch handler offset } else pdt = dtcoff(pdt,bcatch->Boffset); sz += 3 * NPTRSIZE; } } } assert(sz != 0); }
void cod5_prol_epi() { tym_t tym; tym_t tyf; block *b; block *bp; list_t bl; int nepis; tyf = funcsym_p->ty(); tym = tybasic(tyf); goto L1; if (!(config.flags4 & CFG4optimized) || anyiasm || usedalloca || usednteh || tyf & (mTYnaked | mTYloadds) || tym == TYifunc || tym == TYmfunc || // can't yet handle ECX passed as parameter tym == TYjfunc || // can't yet handle EAX passed as parameter config.flags & (CFGalwaysframe | CFGtrace) || // config.fulltypes || (config.wflags & WFwindows && tyfarfunc(tym)) || need_prolog(startblock) ) { // First block gets the prolog, all return blocks // get the epilog. //printf("not even a candidate\n"); L1: cod5_noprol(); return; } // Turn on BFLoutsideprolog for all blocks outside the ones needing the prolog. for (b = startblock; b; b = b->Bnext) b->Bflags &= ~BFLoutsideprolog; // start with them all off pe_add(startblock); // Look for only one block (bp) that will hold the prolog bp = NULL; nepis = 0; for (b = startblock; b; b = b->Bnext) { int mark; if (b->Bflags & BFLoutsideprolog) continue; // If all predecessors are marked mark = 0; assert(b->Bpred); for (bl = b->Bpred; bl; bl = list_next(bl)) { if (list_block(bl)->Bflags & BFLoutsideprolog) { if (mark == 2) goto L1; mark = 1; } else { if (mark == 1) goto L1; mark = 2; } } if (mark == 1) { if (bp) // if already have one goto L1; bp = b; } // See if b is an epilog mark = 0; for (bl = b->Bsucc; bl; bl = list_next(bl)) { if (list_block(bl)->Bflags & BFLoutsideprolog) { if (mark == 2) goto L1; mark = 1; } else { if (mark == 1) goto L1; mark = 2; } } if (mark == 1 || b->BC == BCret || b->BC == BCretexp) { b->Bflags |= BFLepilog; nepis++; if (nepis > 1 && config.flags4 & CFG4space) goto L1; } } if (bp) { bp->Bflags |= BFLprolog; //printf("=============== prolog opt\n"); } }
symbol *except_gentables() { //printf("except_gentables()\n"); #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS symbol *s; int sz; // size so far dt_t **pdt; unsigned fsize; // target size of function pointer long spoff; block *b; int guarddim; int i; // BUG: alloca() changes the stack size, which is not reflected // in the fixed eh tables. assert(!usedalloca); s = symbol_generate(SCstatic,tsint); s->Sseg = UNKNOWN; symbol_keep(s); symbol_debug(s); fsize = 4; pdt = &s->Sdt; sz = 0; /* void* pointer to start of function unsigned offset of ESP from EBP unsigned offset from start of function to return code unsigned nguards; // dimension of guard[] { unsigned offset; // offset of start of guarded section unsigned endoffset; // ending offset of guarded section int last_index; // previous index (enclosing guarded section) unsigned catchoffset; // offset to catch block from symbol void *finally; // finally code to execute } guard[]; catchoffset: unsigned ncatches; // number of catch blocks { void *type; // symbol representing type unsigned bpoffset; // EBP offset of catch variable void *handler; // catch handler code } catch[]; */ #define GUARD_SIZE 5 // number of 4 byte values in one guard sz = 0; // Address of start of function symbol_debug(funcsym_p); pdt = dtxoff(pdt,funcsym_p,0,TYnptr); sz += fsize; //printf("ehtables: func = %s, offset = x%x, startblock->Boffset = x%x\n", funcsym_p->Sident, funcsym_p->Soffset, startblock->Boffset); // Get offset of ESP from EBP spoff = cod3_spoff(); pdt = dtdword(pdt,spoff); sz += 4; // Offset from start of function to return code pdt = dtdword(pdt,retoffset); sz += 4; // First, calculate starting catch offset guarddim = 0; // max dimension of guard[] for (b = startblock; b; b = b->Bnext) { if (b->BC == BC_try && b->Bscope_index >= guarddim) guarddim = b->Bscope_index + 1; // printf("b->BC = %2d, Bscope_index = %2d, last_index = %2d, offset = x%x\n", // b->BC, b->Bscope_index, b->Blast_index, b->Boffset); } pdt = dtdword(pdt,guarddim); sz += 4; unsigned catchoffset = sz + guarddim * (GUARD_SIZE * 4); // Generate guard[] i = 0; for (b = startblock; b; b = b->Bnext) { //printf("b = %p, b->Btry = %p, b->offset = %x\n", b, b->Btry, b->Boffset); if (b->BC == BC_try) { dt_t *dt; block *bhandler; int nsucc; unsigned endoffset; block *bn; assert(b->Bscope_index >= i); if (i < b->Bscope_index) { int fillsize = (b->Bscope_index - i) * (GUARD_SIZE * 4); pdt = dtnzeros(pdt, fillsize); sz += fillsize; } i = b->Bscope_index + 1; nsucc = list_nitems(b->Bsucc); pdt = dtdword(pdt,b->Boffset - startblock->Boffset); // offset to start of block // Compute ending offset for (bn = b->Bnext; 1; bn = bn->Bnext) { //printf("\tbn = %p, bn->Btry = %p, bn->offset = %x\n", bn, bn->Btry, bn->Boffset); assert(bn); if (bn->Btry == b->Btry) { endoffset = bn->Boffset - startblock->Boffset; break; } } pdt = dtdword(pdt,endoffset); // offset past end of guarded block pdt = dtdword(pdt,b->Blast_index); // parent index if (b->jcatchvar) // if try-catch { pdt = dtdword(pdt,catchoffset); pdt = dtdword(pdt,0); // no finally handler catchoffset += 4 + (nsucc - 1) * (3 * 4); } else // else try-finally { assert(nsucc == 2); pdt = dtdword(pdt,0); // no catch offset bhandler = list_block(list_next(b->Bsucc)); assert(bhandler->BC == BC_finally); // To successor of BC_finally block bhandler = list_block(bhandler->Bsucc); pdt = dtxoff(pdt,funcsym_p,bhandler->Boffset - startblock->Boffset, TYnptr); // finally handler address //pdt = dtcoff(pdt,bhandler->Boffset); // finally handler address } sz += GUARD_SIZE + 4; } } // Generate catch[] for (b = startblock; b; b = b->Bnext) { if (b->BC == BC_try) { block *bhandler; int nsucc; if (b->jcatchvar) // if try-catch { list_t bl; nsucc = list_nitems(b->Bsucc); pdt = dtdword(pdt,nsucc - 1); // # of catch blocks sz += 4; for (bl = list_next(b->Bsucc); bl; bl = list_next(bl)) { block *bcatch = list_block(bl); pdt = dtxoff(pdt,bcatch->Bcatchtype,0,TYjhandle); pdt = dtdword(pdt,cod3_bpoffset(b->jcatchvar)); // EBP offset pdt = dtxoff(pdt,funcsym_p,bcatch->Boffset - startblock->Boffset, TYnptr); // catch handler address //pdt = dtcoff(pdt,bcatch->Boffset); // catch handler address sz += 3 * 4; } } } } assert(sz != 0); outdata(s); // output the scope table obj_ehtables(funcsym_p,funcsym_p->Ssize,s); #endif return NULL; }
void except_fillInEHTable(symbol *s) { unsigned fsize = NPTRSIZE; // target size of function pointer dt_t **pdt = &s->Sdt; /* void* pointer to start of function unsigned offset of ESP from EBP unsigned offset from start of function to return code unsigned nguards; // dimension of guard[] (Linux) Guard guard[]; catchoffset: unsigned ncatches; // number of catch blocks { void *type; // symbol representing type unsigned bpoffset; // EBP offset of catch variable void *handler; // catch handler code } catch[]; */ /* Be careful of this, as we need the sizeof Guard on the target, not * in the compiler. */ #if OUREH #define GUARD_SIZE (I64 ? 3*8 : 5*4) // sizeof(Guard) #else #define GUARD_SIZE (sizeof(Guard)) #endif int sz = 0; // Address of start of function symbol_debug(funcsym_p); pdt = dtxoff(pdt,funcsym_p,0,TYnptr); sz += fsize; //printf("ehtables: func = %s, offset = x%x, startblock->Boffset = x%x\n", funcsym_p->Sident, funcsym_p->Soffset, startblock->Boffset); // Get offset of ESP from EBP long spoff = cod3_spoff(); pdt = dtdword(pdt,spoff); sz += 4; // Offset from start of function to return code pdt = dtdword(pdt,retoffset); sz += 4; // First, calculate starting catch offset int guarddim = 0; // max dimension of guard[] for (block *b = startblock; b; b = b->Bnext) { if (b->BC == BC_try && b->Bscope_index >= guarddim) guarddim = b->Bscope_index + 1; // printf("b->BC = %2d, Bscope_index = %2d, last_index = %2d, offset = x%x\n", // b->BC, b->Bscope_index, b->Blast_index, b->Boffset); } #if OUREH pdt = dtsize_t(pdt,guarddim); sz += NPTRSIZE; #endif unsigned catchoffset = sz + guarddim * GUARD_SIZE; // Generate guard[] int i = 0; for (block *b = startblock; b; b = b->Bnext) { //printf("b = %p, b->Btry = %p, b->offset = %x\n", b, b->Btry, b->Boffset); if (b->BC == BC_try) { assert(b->Bscope_index >= i); if (i < b->Bscope_index) { int fillsize = (b->Bscope_index - i) * GUARD_SIZE; pdt = dtnzeros(pdt, fillsize); sz += fillsize; } i = b->Bscope_index + 1; int nsucc = list_nitems(b->Bsucc); #if OUREH //printf("DHandlerInfo: offset = %x", (int)(b->Boffset - startblock->Boffset)); pdt = dtdword(pdt,b->Boffset - startblock->Boffset); // offset to start of block // Compute ending offset unsigned endoffset; for (block *bn = b->Bnext; 1; bn = bn->Bnext) { //printf("\tbn = %p, bn->Btry = %p, bn->offset = %x\n", bn, bn->Btry, bn->Boffset); assert(bn); if (bn->Btry == b->Btry) { endoffset = bn->Boffset - startblock->Boffset; break; } } //printf(" endoffset = %x, prev_index = %d\n", endoffset, b->Blast_index); pdt = dtdword(pdt,endoffset); // offset past end of guarded block #endif pdt = dtdword(pdt,b->Blast_index); // parent index if (b->jcatchvar) // if try-catch { pdt = dtdword(pdt,catchoffset); pdt = dtsize_t(pdt,0); // no finally handler catchoffset += NPTRSIZE + (nsucc - 1) * (3 * NPTRSIZE); } else // else try-finally { assert(nsucc == 2); pdt = dtdword(pdt,0); // no catch offset block *bhandler = list_block(list_next(b->Bsucc)); assert(bhandler->BC == BC_finally); // To successor of BC_finally block bhandler = list_block(bhandler->Bsucc); #if OUREH pdt = dtxoff(pdt,funcsym_p,bhandler->Boffset - startblock->Boffset, TYnptr); // finally handler address #else pdt = dtcoff(pdt,bhandler->Boffset); // finally handler address #endif } sz += GUARD_SIZE; } } // Generate catch[] for (block *b = startblock; b; b = b->Bnext) { if (b->BC == BC_try) { block *bhandler; int nsucc; if (b->jcatchvar) // if try-catch { list_t bl; nsucc = list_nitems(b->Bsucc); pdt = dtsize_t(pdt,nsucc - 1); // # of catch blocks sz += NPTRSIZE; for (bl = list_next(b->Bsucc); bl; bl = list_next(bl)) { block *bcatch = list_block(bl); pdt = dtxoff(pdt,bcatch->Bcatchtype,0,TYjhandle); pdt = dtsize_t(pdt,cod3_bpoffset(b->jcatchvar)); // EBP offset #if OUREH pdt = dtxoff(pdt,funcsym_p,bcatch->Boffset - startblock->Boffset, TYnptr); // catch handler address #else pdt = dtcoff(pdt,bcatch->Boffset); // catch handler address #endif sz += 3 * NPTRSIZE; } } } } assert(sz != 0); }