Showing with 741 additions and 169 deletions.
  1. +10 −0 src/backend/blockopt.c
  2. +8 −0 src/backend/cc.h
  3. +0 −2 src/backend/cdef.h
  4. +7 −1 src/backend/cgcod.c
  5. +1 −0 src/backend/cgreg.c
  6. +17 −1 src/backend/cod1.c
  7. +71 −58 src/backend/cod2.c
  8. +40 −7 src/backend/cod3.c
  9. +25 −14 src/backend/debug.c
  10. +2 −0 src/backend/dwarf.c
  11. +102 −4 src/backend/el.c
  12. +3 −2 src/backend/el.h
  13. +2 −0 src/backend/gdag.c
  14. +1 −0 src/backend/gother.c
  15. +1 −0 src/backend/rtlsym.h
  16. +9 −7 src/e2ir.c
  17. +2 −0 src/glue.c
  18. +440 −73 src/s2ir.c
10 changes: 10 additions & 0 deletions src/backend/blockopt.c
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,10 @@ void blocklist_hydrate(block **pb)
//(void) ph_hydrate(&b->B_ret);
break;

case BC_lpad:
symbol_hydrate(&b->BS.BI_FINALLY.flag);
break;

case BCasm:
code_hydrate(&b->Bcode);
break;
Expand Down Expand Up @@ -455,6 +459,10 @@ void blocklist_dehydrate(block **pb)
//ph_dehydrate(&b->B_ret);
break;

case BC_lpad:
symbol_dehydrate(&b->BS.BI_FINALLY.flag);
break;

case BCasm:
code_dehydrate(&b->Bcode);
break;
Expand Down Expand Up @@ -1365,6 +1373,7 @@ STATIC void blident()
#endif
case BC_try:
case BC_finally:
case BC_lpad:
case BCasm:
Lcontinue:
continue;
Expand Down Expand Up @@ -1639,6 +1648,7 @@ STATIC void bltailmerge()
#endif
case BC_try:
case BC_finally:
case BC_lpad:
case BCasm:
continue;
}
Expand Down
8 changes: 8 additions & 0 deletions src/backend/cc.h
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,12 @@ typedef struct block
} BI_TRY; // BC_try
#endif

struct
{
Symbol *flag; // EH_DWARF: set to 'flag' symbol that encloses finally
block *b_ret; // EH_DWARF: associated BC_ret block
} BI_FINALLY;

} BS;
Srcpos Bsrcpos; // line number (0 if not known)
unsigned char BC; // exit condition (enum BC)
Expand Down Expand Up @@ -560,6 +566,7 @@ typedef struct block
void prependSucc(block *b) { list_prepend(&this->Bsucc, b); }
int numSucc() { return list_nitems(this->Bsucc); }
block *nthSucc(int n) { return (block *)list_ptr(list_nth(Bsucc, n)); }
void setNthSucc(int n, block *b) { list_ptr(list_nth(Bsucc, n)) = b; }
} block;

#define list_block(l) ((block *) list_ptr(l))
Expand Down Expand Up @@ -599,6 +606,7 @@ enum BC {
BC_ret = 16, // last block of SEH termination-handler or D _finally block
BC_except = 17, // first block of SEH exception-handler
BCjcatch = 18, // D catch block
BC_lpad = 19, // EH_DWARF: landing pad for BC_except
BCMAX
};

Expand Down
2 changes: 0 additions & 2 deletions src/backend/cdef.h
Original file line number Diff line number Diff line change
Expand Up @@ -971,13 +971,11 @@ union eve
elem *Eright; // right child for binary nodes
Symbol *Edtor; // OPctor: destructor
} eop;
#if MARS
struct
{
elem *Eleft; // left child for OPddtor
void *Edecl; // VarDeclaration being constructed
} ed; // OPdctor,OPddtor
#endif
}; // variants for each type of elem

// Symbols
Expand Down
8 changes: 7 additions & 1 deletion src/backend/cgcod.c
Original file line number Diff line number Diff line change
Expand Up @@ -1751,7 +1751,13 @@ int isregvar(elem *e,regm_t *pregm,unsigned *preg)

case FLpseudo:
#if MARS
assert(0);
u = s->Sreglsw;
m = mask[u];
if (m & ALLREGS && (u & ~3) != 4) // if not BP,SP,EBP,ESP,or ?H
{ reg = u & 7;
regm = m;
goto Lreg;
}
#else
u = s->Sreglsw;
m = pseudomask[u];
Expand Down
1 change: 1 addition & 0 deletions src/backend/cgreg.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ int cgreg_benefit(Symbol *s,int reg, Symbol *retsym)
case BCcatch:
case BC_except:
case BC_finally:
case BC_lpad:
case BC_ret:
s->Sflags &= ~GTregcand;
goto Lcant; // can't assign to register
Expand Down
18 changes: 17 additions & 1 deletion src/backend/cod1.c
Original file line number Diff line number Diff line change
Expand Up @@ -1390,7 +1390,23 @@ code *getlvalue(code *pcs,elem *e,regm_t keepmsk)
break;
case FLpseudo:
#if MARS
assert(0);
{
c = getregs(mask[s->Sreglsw]);
pcs->Irm = modregrm(3,0,s->Sreglsw & 7);
if (s->Sreglsw & 8)
pcs->Irex |= REX_B;
if (e->EV.sp.Voffset == 1 && sz == 1)
{ assert(s->Sregm & BYTEREGS);
assert(s->Sreglsw < 4);
pcs->Irm |= 4; // use 2nd byte of register
}
else
{ assert(!e->EV.sp.Voffset);
if (I64 && sz == 1 && s->Sreglsw >= 4)
pcs->Irex |= REX;
}
break;
}
#else
{
unsigned u = s->Sreglsw;
Expand Down
129 changes: 71 additions & 58 deletions src/backend/cod2.c
Original file line number Diff line number Diff line change
Expand Up @@ -5076,19 +5076,18 @@ code *cdinfo(elem *e,regm_t *pretregs)

code *cddctor(elem *e,regm_t *pretregs)
{
#if MARS
/* Generate:
ESCAPE | ESCdctor
MOV sindex[BP],index
*/
usednteh |= EHcleanup;
if (config.exe == EX_WIN32)
if (config.ehmethod == EH_WIN32)
{ usednteh |= NTEHcleanup | NTEH_try;
nteh_usevars();
}
assert(*pretregs == 0);
code cs;
cs.Iop = ESCAPE | ESCdctor;
cs.Iop = ESCAPE | ESCdctor; // mark start of EH range
cs.Iflags = 0;
cs.Irex = 0;
cs.IFL1 = FLctor;
Expand All @@ -5097,9 +5096,6 @@ code *cddctor(elem *e,regm_t *pretregs)
c = cat(c, nteh_gensindex(0)); // the actual index will be patched in later
// by except_fillInEHTable()
return c;
#else
return NULL;
#endif
}

/*******************************************
Expand All @@ -5108,69 +5104,86 @@ code *cddctor(elem *e,regm_t *pretregs)

code *cdddtor(elem *e,regm_t *pretregs)
{
#if MARS
/* Generate:
ESCAPE | ESCddtor
MOV sindex[BP],index
CALL dtor
JMP L1
Ldtor:
... e->E1 ...
RET
L1: NOP
*/
usednteh |= EHcleanup;
if (config.exe == EX_WIN32)
{ usednteh |= NTEHcleanup | NTEH_try;
nteh_usevars();
}

code cs;
cs.Iop = ESCAPE | ESCddtor;
cs.Iflags = 0;
cs.Irex = 0;
cs.IFL1 = FLdtor;
cs.IEV1.Vtor = e;
code *cd = gen(CNIL,&cs);
if (config.ehmethod == EH_DWARF)
{
usednteh |= EHcleanup;

cd = cat(cd, nteh_gensindex(0)); // the actual index will be patched in later
// by except_fillInEHTable()
code cs;
cs.Iop = ESCAPE | ESCddtor; // mark end of EH range and where landing pad is
cs.Iflags = 0;
cs.Irex = 0;
cs.IFL1 = FLdtor;
cs.IEV1.Vtor = e;
code *cd = gen(CNIL,&cs);

// Mark all registers as destroyed
{
// Mark all registers as destroyed
code *cy = getregs(allregs);
assert(!cy);

assert(*pretregs == 0);
code *c = codelem(e->E1,pretregs,FALSE);
return c;
}
else
{
/* Generate:
ESCAPE | ESCddtor
MOV sindex[BP],index
CALL dtor
JMP L1
Ldtor:
... e->E1 ...
RET
L1: NOP
*/
usednteh |= EHcleanup;
if (config.ehmethod == EH_WIN32)
{ usednteh |= NTEHcleanup | NTEH_try;
nteh_usevars();
}

assert(*pretregs == 0);
code *c = codelem(e->E1,pretregs,FALSE);
gen1(c,0xC3); // RET
code cs;
cs.Iop = ESCAPE | ESCddtor;
cs.Iflags = 0;
cs.Irex = 0;
cs.IFL1 = FLdtor;
cs.IEV1.Vtor = e;
code *cd = gen(CNIL,&cs);

#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
if (config.flags3 & CFG3pic)
{
int nalign = 0;
if (STACKALIGN == 16)
{ nalign = STACKALIGN - REGSIZE;
cd = cod3_stackadj(cd, nalign);
cd = cat(cd, nteh_gensindex(0)); // the actual index will be patched in later
// by except_fillInEHTable()

// Mark all registers as destroyed
{
code *cy = getregs(allregs);
assert(!cy);
}
calledafunc = 1;
genjmp(cd,0xE8,FLcode,(block *)c); // CALL Ldtor
if (nalign)
cd = cod3_stackadj(cd, -nalign);
}
else
#endif
genjmp(cd,0xE8,FLcode,(block *)c); // CALL Ldtor

code *cnop = gennop(CNIL);
assert(*pretregs == 0);
code *c = codelem(e->E1,pretregs,FALSE);
gen1(c,0xC3); // RET

genjmp(cd,JMP,FLcode,(block *)cnop);
if (config.flags3 & CFG3pic)
{
int nalign = 0;
if (STACKALIGN == 16)
{ nalign = STACKALIGN - REGSIZE;
cd = cod3_stackadj(cd, nalign);
}
calledafunc = 1;
genjmp(cd,0xE8,FLcode,(block *)c); // CALL Ldtor
if (nalign)
cd = cod3_stackadj(cd, -nalign);
}
else
genjmp(cd,0xE8,FLcode,(block *)c); // CALL Ldtor

return cat4(cd, c, cnop, NULL);
#else
return NULL;
#endif
code *cnop = gennop(CNIL);

genjmp(cd,JMP,FLcode,(block *)cnop);

return cat4(cd, c, cnop, NULL);
}
}


Expand Down
47 changes: 40 additions & 7 deletions src/backend/cod3.c
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,7 @@ void outblkexitcode(block *bl, code*& c, int& anyspill, const char* sflsave, sym
nextb = list_block(bl->Bsucc);
if ((MARS ||
funcsym_p->Sfunc->Fflags3 & Fnteh) &&
config.ehmethod != EH_DWARF &&
bl->Btry != nextb->Btry &&
nextb->BC != BC_finally)
{
Expand Down Expand Up @@ -919,19 +920,51 @@ void outblkexitcode(block *bl, code*& c, int& anyspill, const char* sflsave, sym
code *cy = getregs(allregs);
assert(!cy);
}
assert(!e);
assert(!bl->Bcode);
// Generate CALL to finalizer code
c = cat(c, callFinallyBlock(bl->nthSucc(0), 0));
if (config.ehmethod == EH_DWARF)
{
retregs = 0;
bl->Bcode = gencodelem(NULL,bl->Belem,&retregs,TRUE);

// JMP bl->nthSucc(1)
nextb = bl->nthSucc(1);
goto L2;
}
else
{
assert(!e);
assert(!bl->Bcode);
// Generate CALL to finalizer code
c = cat(c, callFinallyBlock(bl->nthSucc(0), 0));

// JMP bl->nthSucc(1)
nextb = bl->nthSucc(1);
goto L2;
}

// JMP bl->nthSucc(1)
nextb = bl->nthSucc(1);
case BC_lpad:
{
assert(config.ehmethod == EH_DWARF);
// Mark all registers as destroyed. This will prevent
// register assignments to variables used in finally blocks.
code *cy = getregs(allregs);
assert(!cy);

retregs = 0;
bl->Bcode = gencodelem(c,bl->Belem,&retregs,TRUE);

// JMP bl->nthSucc(0)
nextb = bl->nthSucc(0);
goto L2;
}

case BC_ret:
retregs = 0;
c = gencodelem(c,e,&retregs,TRUE);
bl->Bcode = gen1(c,0xC3); // RET
if (config.ehmethod == EH_DWARF)
{
}
else
bl->Bcode = gen1(c,0xC3); // RET
break;

#if NTEXCEPTIONS
Expand Down
Loading