Beispiel #1
0
Datei: nteh.c Projekt: spott/dmd
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);
}
Beispiel #3
0
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));
}
Beispiel #4
0
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");
}
Beispiel #5
0
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
}
Beispiel #6
0
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);
        }
    }
}
Beispiel #7
0
Datei: eh.c Projekt: Govelius/dmd
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);
}
Beispiel #8
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");
    }
}
Beispiel #9
0
Datei: eh.c Projekt: Geod24/dnet
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;
}
Beispiel #10
0
Datei: eh.c Projekt: nischu7/dmd
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);
}