23 changes: 17 additions & 6 deletions src/backend/cdef.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ One and only one of these macros must be set by the makefile:
#if __GNUC__
#define LDOUBLE 0 // no support for true long doubles
#else
#define LDOUBLE (config.exe == EX_NT) // support true long doubles
#define LDOUBLE (config.exe == EX_WIN32) // support true long doubles
#endif

#if _MSC_VER
Expand Down Expand Up @@ -497,7 +497,7 @@ typedef targ_uns targ_size_t; /* size_t for the target machine */
#define NEWTEMPMANGLE (!(config.flags4 & CFG4oldtmangle)) // do new template mangling
#define USEDLLSHELL _WINDLL
#define FARCLASSES 1 // support near/far classes
#define MFUNC (I32) //0 && config.exe == EX_NT) // member functions are TYmfunc
#define MFUNC (I32) //0 && config.exe == EX_WIN32) // member functions are TYmfunc
#define CV3 0 // 1 means support CV3 debug format

/* Object module format
Expand Down Expand Up @@ -608,6 +608,18 @@ typedef enum LINKAGE
LINK_MAXDIM /* array dimension */
} linkage_t;

/**********************************
* Exception handling method
*/

enum EHmethod
{
EH_NONE, // no exception handling
EH_WIN32, // Win32 SEH
EH_WIN64, // Win64 SEH (not supported yet)
EH_DM, // Digital Mars method
EH_DWARF, // Dwarf method
};

// This part of the configuration is saved in the precompiled header for use
// in comparing to make sure it hasn't changed.
Expand Down Expand Up @@ -685,7 +697,7 @@ struct Config
//#define EX_WIN16 0x20 // Windows 3.x 16 bit program
#define EX_OS2 0x40 // OS/2 2.0 32 bit program
#define EX_OS1 0x80 // OS/2 1.x 16 bit program
#define EX_NT 0x100 // NT
#define EX_WIN32 0x100
#define EX_MZ 0x200 // MSDOS real mode program
#define EX_XENIX 0x400
#define EX_SCOUNIX 0x800
Expand All @@ -702,7 +714,7 @@ struct Config
#define EX_OPENBSD 0x400000
#define EX_OPENBSD64 0x800000

#define EX_flat (EX_OS2 | EX_NT | EX_LINUX | EX_WIN64 | EX_LINUX64 | \
#define EX_flat (EX_OS2 | EX_WIN32 | EX_LINUX | EX_WIN64 | EX_LINUX64 | \
EX_OSX | EX_OSX64 | EX_FREEBSD | EX_FREEBSD64 | \
EX_OPENBSD | EX_OPENBSD64 | \
EX_SOLARIS | EX_SOLARIS64)
Expand Down Expand Up @@ -837,6 +849,7 @@ struct Config
#define THRESHMAX 0xFFFF // if threshold == THRESHMAX, all data defaults
// to near
enum LINKAGE linkage; // default function call linkage
enum EHmethod ehmethod; // exception handling method
};

// Configuration that is not saved in precompiled header
Expand Down Expand Up @@ -958,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
18 changes: 16 additions & 2 deletions src/backend/cgcod.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "type.h"
#include "exh.h"
#include "xmm.h"
#include "dwarf.h"

static char __file__[] = __FILE__; /* for tassert.h */
#include "tassert.h"
Expand Down Expand Up @@ -527,10 +528,17 @@ void codgen()
// Do this before code is emitted because we patch some instructions
nteh_gentables();
}
if (usednteh & EHtry)
if (usednteh & EHtry && // saw BCtry or BC_try (test EHcleanup too?)
config.ehmethod == EH_DM)
{
except_gentables();
}
if (config.ehmethod == EH_DWARF)
{
funcsym_p->Sfunc->Fstartblock = startblock;
dwarf_except_gentables(funcsym_p, startoffset, retoffset);
funcsym_p->Sfunc->Fstartblock = NULL;
}
#endif

#if SCPP
Expand Down Expand Up @@ -1751,7 +1759,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
6 changes: 3 additions & 3 deletions src/backend/cgobj.c
Original file line number Diff line number Diff line change
Expand Up @@ -1209,7 +1209,7 @@ STATIC void obj_defaultlib()
case EX_OS1:
library[1] = 'O';
break;
case EX_NT:
case EX_WIN32:
#if MARS
library[1] = 'M';
#else
Expand Down Expand Up @@ -1383,7 +1383,7 @@ STATIC void objheader(char *csegname)
comment[2] = config.target_cpu + '0';
comment[3] = model[config.memmodel];
if (I32)
{ if (config.exe == EX_NT)
{ if (config.exe == EX_WIN32)
comment[3] = 'n';
else if (config.exe == EX_OS2)
comment[3] = 'f';
Expand Down Expand Up @@ -2301,7 +2301,7 @@ size_t Obj::mangle(Symbol *s,char *dest)
#endif
case mTYman_std:
if (!(config.flags4 & CFG4oldstdmangle) &&
config.exe == EX_NT && tyfunc(s->ty()) &&
config.exe == EX_WIN32 && tyfunc(s->ty()) &&
!variadic(s->Stype))
{
dest[1] = '_';
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
137 changes: 75 additions & 62 deletions src/backend/cod2.c
Original file line number Diff line number Diff line change
Expand Up @@ -5038,13 +5038,13 @@ code *cdinfo(elem *e,regm_t *pretregs)
c = cat(c,codelem(e->E1,&retregs,FALSE));
break;
case OPmark:
if (0 && config.exe == EX_NT)
if (0 && config.exe == EX_WIN32)
{ unsigned idx;

idx = except_index_get();
except_mark();
c = codelem(e->E2,pretregs,FALSE);
if (config.exe == EX_NT && idx != except_index_get())
if (config.exe == EX_WIN32 && idx != except_index_get())
{ usednteh |= NTEHcleanup;
c = cat(c,nteh_gensindex(idx - 1));
}
Expand Down 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_NT)
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_NT)
{ 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 All @@ -5185,7 +5198,7 @@ code *cdctor(elem *e,regm_t *pretregs)
code *c;

usednteh |= EHcleanup;
if (config.exe == EX_NT)
if (config.exe == EX_WIN32)
usednteh |= NTEHcleanup;
assert(*pretregs == 0);
cs.Iop = ESCAPE | ESCctor;
Expand All @@ -5207,7 +5220,7 @@ code *cddtor(elem *e,regm_t *pretregs)
code *c;

usednteh |= EHcleanup;
if (config.exe == EX_NT)
if (config.exe == EX_WIN32)
usednteh |= NTEHcleanup;
assert(*pretregs == 0);
cs.Iop = ESCAPE | ESCdtor;
Expand Down
186 changes: 102 additions & 84 deletions src/backend/cod3.c
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,34 @@ void cgreg_set_priorities(tym_t ty, char **pseq, char **pseqmsw)
}
}

/*******************************************
* Call finally block.
* Params:
* bf = block to call
* retregs = registers to preserve across call
* Returns:
* code generated
*/
static code *callFinallyBlock(block *bf, regm_t retregs)
{
code *cs;
code *cr;
int nalign = 0;

unsigned npush = gensaverestore(retregs,&cs,&cr);
if (STACKALIGN == 16)
{ npush += REGSIZE;
if (npush & (STACKALIGN - 1))
{ nalign = STACKALIGN - (npush & (STACKALIGN - 1));
cs = cod3_stackadj(cs, nalign);
}
}
cs = genc(cs,0xE8,0,0,0,FLblock,(targ_size_t)bf);
regcon.immed.mval = 0;
if (nalign)
cs = cod3_stackadj(cs, -nalign);
return cat(cs, cr);
}

/*******************************
* Generate block exit code
Expand Down Expand Up @@ -790,25 +818,25 @@ void outblkexitcode(block *bl, code*& c, int& anyspill, const char* sflsave, sym
#endif
case BCgoto:
nextb = list_block(bl->Bsucc);
if (((MARS /*&& config.flags2 & CFG2seh*/) ||
if ((MARS ||
funcsym_p->Sfunc->Fflags3 & Fnteh) &&
config.ehmethod != EH_DWARF &&
bl->Btry != nextb->Btry &&
nextb->BC != BC_finally)
{ int toindex;
int fromindex;

{
bl->Bcode = NULL;
retregs = 0;
c = gencodelem(c,e,&retregs,TRUE);
toindex = nextb->Btry ? nextb->Btry->Bscope_index : -1;
int toindex = nextb->Btry ? nextb->Btry->Bscope_index : -1;
assert(bl->Btry);
fromindex = bl->Btry->Bscope_index;
int fromindex = bl->Btry->Bscope_index;
#if MARS
if (toindex + 1 == fromindex)
{ // Simply call __finally
if (bl->Btry &&
list_block(list_next(bl->Btry->Bsucc))->BC == BCjcatch)
{
goto L2;
goto L2; // it's a try-catch, not a try-finally
}
}
#endif
Expand Down Expand Up @@ -844,29 +872,14 @@ void outblkexitcode(block *bl, code*& c, int& anyspill, const char* sflsave, sym
continue;

// call __finally
code *cs;
code *cr;
int nalign = 0;

unsigned npush = gensaverestore(retregs,&cs,&cr);
if (STACKALIGN == 16)
{ npush += REGSIZE;
if (npush & (STACKALIGN - 1))
{ nalign = STACKALIGN - (npush & (STACKALIGN - 1));
cs = cod3_stackadj(cs, nalign);
}
}
cs = genc(cs,0xE8,0,0,0,FLblock,(targ_size_t)list_block(bf->Bsucc));
regcon.immed.mval = 0;
if (nalign)
cs = cod3_stackadj(cs, -nalign);
c = cat3(c,cs,cr);
c = cat(c, callFinallyBlock(bf->nthSucc(0), retregs));
}
}
#endif
goto L2;
}
case_goto:
retregs = 0;
c = gencodelem(c,e,&retregs,TRUE);
if (anyspill)
{ // Add in the epilog code
Expand Down Expand Up @@ -907,39 +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);
#if 1
{ // Generate CALL to finalizer code
int nalign = 0;
if (STACKALIGN == 16)
{ nalign = STACKALIGN - REGSIZE;
c = cod3_stackadj(c, nalign);
}
// CALL bl->Bsucc
c = genc(c,0xE8,0,0,0,FLblock,(targ_size_t)list_block(bl->Bsucc));
regcon.immed.mval = 0;
if (nalign)
c = cod3_stackadj(c, -nalign);
// JMP list_next(bl->Bsucc)
nextb = list_block(list_next(bl->Bsucc));
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 // Not so good because altering return addr always causes branch misprediction
else
{
// Generate a PUSH of the address of the successor to the
// corresponding BC_ret
//assert(list_block(list_next(bl->Bsucc))->BC == BC_ret);
// PUSH &succ
c = genc(c,0x68,0,0,0,FLblock,(targ_size_t)list_block(list_next(bl->Bsucc)));
nextb = list_block(bl->Bsucc);
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;
}
#endif

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 Expand Up @@ -991,10 +1016,15 @@ void outblkexitcode(block *bl, code*& c, int& anyspill, const char* sflsave, sym
}
else
{
case BCret:
case BCexit:
c = gencodelem(c,e,&retregs,TRUE);
}
goto L4;

case BCret:
case BCexit:
retregs = 0;
c = gencodelem(c,e,&retregs,TRUE);
L4:
bl->Bcode = c;
if (retregs == mST0)
{ assert(stackused == 1);
Expand All @@ -1005,16 +1035,17 @@ void outblkexitcode(block *bl, code*& c, int& anyspill, const char* sflsave, sym
pop87();
pop87(); // account for return value
}
if (bl->BC == BCexit && config.flags4 & CFG4optimized)
mfuncreg = mfuncregsave;
if (MARS || usednteh & NTEH_try)
{ block *bt;

bt = bl;
if (bl->BC == BCexit)
{
if (config.flags4 & CFG4optimized)
mfuncreg = mfuncregsave;
}
else if (MARS || usednteh & NTEH_try)
{
block *bt = bl;
while ((bt = bt->Btry) != NULL)
{ block *bf;

bf = list_block(list_next(bt->Bsucc));
{
block *bf = bt->nthSucc(1);
#if MARS
// Only look at try-finally blocks
if (bf->BC == BCjcatch)
Expand All @@ -1032,7 +1063,7 @@ void outblkexitcode(block *bl, code*& c, int& anyspill, const char* sflsave, sym

c = cat(c,nteh_gensindex(-1));
gensaverestore(retregs,&cs,&cr);
cs = genc(cs,0xE8,0,0,0,FLblock,(targ_size_t)list_block(bf->Bsucc));
cs = genc(cs,0xE8,0,0,0,FLblock,(targ_size_t)bf->nthSucc(0));
regcon.immed.mval = 0;
bl->Bcode = cat3(c,cs,cr);
}
Expand All @@ -1043,24 +1074,8 @@ void outblkexitcode(block *bl, code*& c, int& anyspill, const char* sflsave, sym
else
{
// call __finally
code *cs;
code *cr;
int nalign = 0;

unsigned npush = gensaverestore(retregs,&cs,&cr);
if (STACKALIGN == 16)
{ npush += REGSIZE;
if (npush & (STACKALIGN - 1))
{ nalign = STACKALIGN - (npush & (STACKALIGN - 1));
cs = cod3_stackadj(cs, nalign);
}
}
// CALL bf->Bsucc
cs = genc(cs,0xE8,0,0,0,FLblock,(targ_size_t)list_block(bf->Bsucc));
regcon.immed.mval = 0;
if (nalign)
cs = cod3_stackadj(cs, -nalign);
bl->Bcode = c = cat3(c,cs,cr);
c = cat(c, callFinallyBlock(bf->nthSucc(0), retregs));
bl->Bcode = c;
}
}
}
Expand Down Expand Up @@ -2982,7 +2997,8 @@ code* prolog_frame(unsigned farfunc, unsigned* xlocalsize, bool* enter)
// by nteh_prolog()
}
#endif
if (config.fulltypes == CVDWARF_C || config.fulltypes == CVDWARF_D)
if (config.fulltypes == CVDWARF_C || config.fulltypes == CVDWARF_D ||
config.ehmethod == EH_DWARF)
{ int off = 2 * REGSIZE;
dwarf_CFA_set_loc(1); // address after PUSH EBP
dwarf_CFA_set_reg_offset(SP, off); // CFA is now 8[ESP]
Expand Down Expand Up @@ -3154,7 +3170,8 @@ code* prolog_saveregs(code *c, regm_t topush)
}
if (I64)
code_orrex(c, REX_W);
if (config.fulltypes == CVDWARF_C || config.fulltypes == CVDWARF_D)
if (config.fulltypes == CVDWARF_C || config.fulltypes == CVDWARF_D ||
config.ehmethod == EH_DWARF)
{ // Emit debug_frame data giving location of saved register
pinholeopt(c, NULL);
dwarf_CFA_set_loc(calcblksize(c)); // address after save
Expand Down Expand Up @@ -3184,7 +3201,8 @@ code* prolog_saveregs(code *c, regm_t topush)
c = genpush(c, reg);
EBPtoESP += REGSIZE;
spoff += REGSIZE;
if (config.fulltypes == CVDWARF_C || config.fulltypes == CVDWARF_D)
if (config.fulltypes == CVDWARF_C || config.fulltypes == CVDWARF_D ||
config.ehmethod == EH_DWARF)
{ // Emit debug_frame data giving location of saved register
// relative to 0[EBP]
pinholeopt(c, NULL);
Expand Down Expand Up @@ -3812,7 +3830,7 @@ void epilog(block *b)
useregs((ALLREGS | mBP | mES) & ~s->Sregsaved);
}

if (usednteh & ~NTEHjmonitor && (config.exe == EX_NT || MARS))
if (usednteh & ~NTEHjmonitor && (config.exe == EX_WIN32 || MARS))
c = cat(c,nteh_epilog());

cpopds = CNIL;
Expand Down Expand Up @@ -6029,7 +6047,7 @@ unsigned codout(code *c)
case ESCctor:
case ESCdtor:
case ESCoffset:
if (config.exe != EX_NT)
if (config.exe != EX_WIN32)
except_pair_setoffset(c,ggen.getOffset() - funcoffset);
break;
case ESCmark:
Expand Down
4 changes: 2 additions & 2 deletions src/backend/code.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ extern unsigned usednteh;
#define NTEHcleanup 8 // destructors need to be called
#define NTEHtry 0x10 // had C++ try statement
#define NTEHcpp (NTEHexcspec | NTEHcleanup | NTEHtry)
#define EHcleanup 0x20
#define EHtry 0x40
#define EHcleanup 0x20 // has destructors in the 'code' instructions
#define EHtry 0x40 // has BCtry or BC_try blocks
#define NTEHjmonitor 0x80 // uses Mars monitor
#define NTEHpassthru 0x100

Expand Down
39 changes: 25 additions & 14 deletions src/backend/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ void WRBC(unsigned bc)
"exit ","asm ","switch","ifthen","jmptab",
"try ","catch ","jump ",
"_try ","_filte","_final","_ret ","_excep",
"jcatch"
"jcatch","_lpad ",
};

assert(sizeof(bcs) / sizeof(bcs[0]) == BCMAX);
Expand Down Expand Up @@ -323,24 +323,30 @@ void WRblock(block *b)
{
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: ");
printf("%p %d ", b, b->BC);
printf("***** block %p ", b);
WRBC(b->BC);
dbg_printf(" Btry=%p Bindex=%d",b->Btry,b->Bindex);
if (b->Btry)
printf(" Btry=%p",b->Btry);
if (b->Bindex)
printf(" Bindex=%d",b->Bindex);
if (b->BC == BC_finally)
printf(" b_ret=%p", b->BS.BI_FINALLY.b_ret);
#if MARS
if (b->Bsrcpos.Sfilename)
dbg_printf(" %s(%u)", b->Bsrcpos.Sfilename, b->Bsrcpos.Slinnum);
#endif
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;
if (b->Belem) elem_print(b->Belem);
if (b->Bpred)
{
printf("\tBpred:");
for (list_t bl = b->Bpred; bl; bl = list_next(bl))
printf(" %p",list_block(bl));
printf("\n");
}
list_t bl = b->Bsucc;
switch (b->BC)
{
case BCswitch:
Expand All @@ -365,13 +371,18 @@ printf("%p %d ", b, b->BC);
case BC_try:
case BC_filter:
case BC_finally:
case BC_lpad:
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));
if (bl)
{
dbg_printf("\tBsucc:");
for ( ; bl; bl = list_next(bl))
dbg_printf(" %p",list_block(bl));
printf("\n");
}
break;
case BCret:
case BCretexp:
Expand Down
14 changes: 7 additions & 7 deletions src/backend/dt.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,25 +175,25 @@ dt_t ** dtnbytes(dt_t **pdtend,unsigned size,const char *ptr)
* Construct a DTabytes record, and return it.
*/

dt_t **dtabytes(dt_t **pdtend, unsigned offset, unsigned size, const char *ptr, unsigned nbytes)
dt_t **dtabytes(dt_t **pdtend, unsigned offset, unsigned size, const char *ptr, unsigned nzeros)
{
return dtabytes(pdtend, TYnptr, offset, size, ptr, nbytes);
return dtabytes(pdtend, TYnptr, offset, size, ptr, nzeros);
}

dt_t **dtabytes(dt_t **pdtend,tym_t ty, unsigned offset, unsigned size, const char *ptr, unsigned nbytes)
dt_t **dtabytes(dt_t **pdtend, tym_t ty, unsigned offset, unsigned size, const char *ptr, unsigned nzeros)
{ dt_t *dt;

while (*pdtend)
pdtend = &((*pdtend)->DTnext);

dt = dt_calloc(DT_abytes);
dt->DTnbytes = size + nbytes;
dt->DTpbytes = (char *) MEM_PH_MALLOC(size + nbytes);
dt->DTnbytes = size + nzeros;
dt->DTpbytes = (char *) MEM_PH_MALLOC(size + nzeros);
dt->Dty = ty;
dt->DTabytes = offset;
memcpy(dt->DTpbytes,ptr,size);
if (size)
memset(dt->DTpbytes + size, 0, nbytes);
if (nzeros)
memset(dt->DTpbytes + size, 0, nzeros);

*pdtend = dt;
pdtend = &dt->DTnext;
Expand Down
418 changes: 311 additions & 107 deletions src/backend/dwarf.c

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/backend/dwarf.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ unsigned dwarf_abbrev_code(unsigned char *data, size_t nbytes);

int dwarf_regno(int reg);

void dwarf_addrel(int seg, targ_size_t offset, int targseg, targ_size_t val = 0);
void dwarf_except_gentables(Funcsym *sfunc, unsigned startoffset, unsigned retoffset);
void genDwarfEh(Funcsym *sfunc, int seg, Outbuffer *et, bool scancode, unsigned startoffset, unsigned retoffset);

#endif
24 changes: 24 additions & 0 deletions src/backend/dwarf2.h
Original file line number Diff line number Diff line change
Expand Up @@ -500,4 +500,28 @@ enum
DW_CFA_hi_user = 0x3f,
};

enum
{
DW_EH_PE_FORMAT_MASK = 0x0F,
DW_EH_PE_APPL_MASK = 0x70,
DW_EH_PE_indirect = 0x80,

DW_EH_PE_omit = 0xFF,
DW_EH_PE_ptr = 0x00,
DW_EH_PE_uleb128 = 0x01,
DW_EH_PE_udata2 = 0x02,
DW_EH_PE_udata4 = 0x03,
DW_EH_PE_udata8 = 0x04,
DW_EH_PE_sleb128 = 0x09,
DW_EH_PE_sdata2 = 0x0A,
DW_EH_PE_sdata4 = 0x0B,
DW_EH_PE_sdata8 = 0x0C,

DW_EH_PE_absptr = 0x00,
DW_EH_PE_pcrel = 0x10,
DW_EH_PE_textrel = 0x20,
DW_EH_PE_datarel = 0x30,
DW_EH_PE_funcrel = 0x40,
DW_EH_PE_aligned = 0x50,
};

531 changes: 531 additions & 0 deletions src/backend/dwarfeh.c

Large diffs are not rendered by default.

106 changes: 102 additions & 4 deletions src/backend/el.c
Original file line number Diff line number Diff line change
Expand Up @@ -2238,11 +2238,13 @@ elem * el_const(tym_t ty,union eve *pconst)

/**************************
* Insert constructor information into tree.
* e code to construct the object
* decl VarDeclaration of variable being constructed
* A corresponding el_ddtor() must be called later.
* Params:
* e = code to construct the object
* decl = VarDeclaration of variable being constructed
*/

#if MARS
#if 0
elem *el_dctor(elem *e,void *decl)
{
elem *ector = el_calloc();
Expand All @@ -2267,7 +2269,7 @@ elem *el_dctor(elem *e,void *decl)
* (must match decl for corresponding OPctor)
*/

#if MARS
#if 0
elem *el_ddtor(elem *e,void *decl)
{
/* A destructor always executes code, or we wouldn't need
Expand All @@ -2283,6 +2285,102 @@ elem *el_ddtor(elem *e,void *decl)
}
#endif

/*********************************************
* Create constructor/destructor pair of elems.
* Params:
* ec = code to construct (may be NULL)
* ed = code to destruct
* pedtor = set to destructor node
* Returns:
* constructor node
*/

elem *el_ctor_dtor(elem *ec, elem *ed, elem **pedtor)
{
elem *er;
if (config.ehmethod == EH_DWARF)
{
/* Construct (note that OPinfo is evaluated RTOL):
* er = (OPdctor OPinfo (__flag = 0, ec))
* edtor = __flag = 1, (OPddtor ((__exception_object = _EAX), ed, (!__flag && _Unsafe_Resume(__exception_object))))
*/

/* Declare __flag, __EAX, __exception_object variables.
* Use volatile to prevent optimizer from messing them up, since optimizer doesn't know about
* landing pads (the landing pad will be on the OPddtor's EV.ed.Eleft)
*/
symbol *sflag = symbol_name("__flag", SCauto, type_fake(mTYvolatile | TYbool));
symbol *sreg = symbol_name("__EAX", SCpseudo, type_fake(mTYvolatile | TYnptr));
sreg->Sreglsw = 0; // EAX, RAX, whatevs
symbol *seo = symbol_name("__exception_object", SCauto, tspvoid);

symbol_add(sflag);
symbol_add(sreg);
symbol_add(seo);

elem *ector = el_calloc();
ector->Eoper = OPdctor;
ector->Ety = TYvoid;
// ector->EV.ed.Edecl = decl;

union eve c;
memset(&c, 0, sizeof(c));
elem *e_flag_0 = el_bin(OPeq, TYvoid, el_var(sflag), el_const(TYbool, &c)); // __flag = 0
er = el_bin(OPinfo, ec ? ec->Ety : TYvoid, ector, el_combine(e_flag_0, ec));

/* A destructor always executes code, or we wouldn't need
* eh for it.
* An OPddtor must match 1:1 with an OPdctor
*/
elem *edtor = el_calloc();
edtor->Eoper = OPddtor;
edtor->Ety = TYvoid;
// edtor->EV.ed.Edecl = decl;
// edtor->EV.ed.Eleft = e;

c.Vint = 1;
elem *e_flag_1 = el_bin(OPeq, TYvoid, el_var(sflag), el_const(TYbool, &c)); // __flag = 1
elem *e_eax = el_bin(OPeq, TYvoid, el_var(seo), el_var(sreg)); // __exception_object = __EAX
elem *eu = el_bin(OPcall, TYvoid, el_var(getRtlsym(RTLSYM_UNWIND_RESUME)), el_var(seo));
eu = el_bin(OPandand, TYvoid, el_una(OPnot, TYbool, el_var(sflag)), eu);

edtor->EV.ed.Eleft = el_combine(el_combine(e_eax, ed), eu);

*pedtor = el_combine(e_flag_1, edtor);
}
else
{
/* Construct (note that OPinfo is evaluated RTOL):
* er = (OPdctor OPinfo ec)
* edtor = (OPddtor ed)
*/
elem *ector = el_calloc();
ector->Eoper = OPdctor;
ector->Ety = TYvoid;
// ector->EV.ed.Edecl = decl;
if (ec)
er = el_bin(OPinfo,ec->Ety,ector,ec);
else
/* Remember that a "constructor" may execute no code, hence
* the need for OPinfo if there is code to execute.
*/
er = ector;

/* A destructor always executes code, or we wouldn't need
* eh for it.
* An OPddtor must match 1:1 with an OPdctor
*/
elem *edtor = el_calloc();
edtor->Eoper = OPddtor;
edtor->Ety = TYvoid;
// edtor->EV.ed.Edecl = decl;
edtor->EV.ed.Eleft = ed;
*pedtor = edtor;
}

return er;
}

/**************************
* Insert constructor information into tree.
* ector pointer to object being constructed
Expand Down
5 changes: 3 additions & 2 deletions src/backend/el.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,9 @@ elem_p el_long(tym_t,targ_llong);

int ERTOL(elem_p);
int el_noreturn(elem_p);
elem *el_dctor(elem *e,void *decl);
elem *el_ddtor(elem *e,void *decl);
//elem *el_dctor(elem *e,void *decl);
//elem *el_ddtor(elem *e,void *decl);
elem *el_ctor_dtor(elem *ec, elem *ed, elem **pedtor);
elem *el_ctor(elem *ector,elem *e,symbol *sdtor);
elem *el_dtor(elem *edtor,elem *e);
elem *el_zero(type *t);
Expand Down
File renamed without changes.
2 changes: 2 additions & 0 deletions src/backend/gdag.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ void builddags()
list_next(b->Bpred) != NULL))
|| b->BC == BCasm
|| b->BC == BC_finally
|| b->BC == BC_lpad
#if SCPP
|| b->BC == BCcatch
#endif
Expand Down Expand Up @@ -616,6 +617,7 @@ void boolopt()
list_next(b->Bpred) != NULL))
|| b->BC == BCasm
|| b->BC == BC_finally
|| b->BC == BC_lpad
#if SCPP
|| b->BC == BCcatch
#endif
Expand Down
1 change: 1 addition & 0 deletions src/backend/gother.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ STATIC void rd_compute()
case BCjcatch:
#endif
case BC_finally:
case BC_lpad:
case BCasm:
case BCcatch:
block_visit(b);
Expand Down
2 changes: 1 addition & 1 deletion src/backend/machobj.c
Original file line number Diff line number Diff line change
Expand Up @@ -1938,7 +1938,7 @@ char *obj_mangle2(Symbol *s,char *dest)
if (tyfunc(s->ty()) && !variadic(s->Stype))
#else
if (!(config.flags4 & CFG4oldstdmangle) &&
config.exe == EX_NT && tyfunc(s->ty()) &&
config.exe == EX_WIN32 && tyfunc(s->ty()) &&
!variadic(s->Stype))
#endif
{
Expand Down
4 changes: 4 additions & 0 deletions src/backend/melf.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ typedef struct
#define STT_LOPROC 13 /* Start of processor-specific */
#define STT_HIPROC 15 /* End of processor-specific */

#define STV_DEFAULT 0 /* Default symbol visibility rules */
#define STV_INTERNAL 1 /* Processor specific hidden class */
#define STV_HIDDEN 2 /* Sym unavailable in other modules */
#define STV_PROTECTED 3 /* Not preemptible, not exported */

unsigned char st_other; /* Currently not defined */
Elf32_Half st_shndx; /* SHT index for symbol definition */
Expand Down
2 changes: 1 addition & 1 deletion src/backend/mscoffobj.c
Original file line number Diff line number Diff line change
Expand Up @@ -1819,7 +1819,7 @@ char *obj_mangle2(Symbol *s,char *dest)
if (tyfunc(s->ty()) && !variadic(s->Stype))
#else
if (!(config.flags4 & CFG4oldstdmangle) &&
config.exe == EX_NT && tyfunc(s->ty()) &&
config.exe == EX_WIN32 && tyfunc(s->ty()) &&
!variadic(s->Stype))
#endif
{
Expand Down
2 changes: 1 addition & 1 deletion src/backend/nteh.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ code *nteh_prolog()
}
c = gen(NULL,&cs); // PUSH &__except_handler3

if (config.exe == EX_NT)
if (config.exe == EX_WIN32)
{
makeitextern(getRtlsym(RTLSYM_EXCEPT_LIST));
#if 0
Expand Down
10 changes: 5 additions & 5 deletions src/backend/out.c
Original file line number Diff line number Diff line change
Expand Up @@ -1231,15 +1231,15 @@ STATIC void writefunc2(symbol *sfunc)
{
case 'D': if (strcmp(id,"DllMain"))
break;
if (config.exe == EX_NT)
if (config.exe == EX_WIN32)
{ i = 2;
goto L2;
}
break;

case 'm': if (strcmp(id,"main"))
break;
if (config.exe == EX_NT)
if (config.exe == EX_WIN32)
i = 3;
else if (config.wflags & WFwindows)
i = 1;
Expand All @@ -1249,7 +1249,7 @@ STATIC void writefunc2(symbol *sfunc)

case 'w': if (strcmp(id,"wmain") == 0)
{
if (config.exe == EX_NT)
if (config.exe == EX_WIN32)
{ i = 5;
goto L2;
}
Expand All @@ -1262,7 +1262,7 @@ STATIC void writefunc2(symbol *sfunc)
}
if (stricmp(id,"wWinMain") == 0)
{
if (config.exe == EX_NT)
if (config.exe == EX_WIN32)
{ i = 4;
goto L2;
}
Expand All @@ -1272,7 +1272,7 @@ STATIC void writefunc2(symbol *sfunc)
case 'L':
case 'l': if (stricmp(id,"LibMain"))
break;
if (config.exe != EX_NT && config.wflags & WFwindows)
if (config.exe != EX_WIN32 && config.wflags & WFwindows)
{ i = 2;
goto L2;
}
Expand Down
3 changes: 3 additions & 0 deletions src/backend/rtlsym.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
\
SYMBOL_MARS(THROW, FLfunc,(mES | mBP),"_d_throw@4", SFLexit, tw) /* D1 only */ \
SYMBOL_MARS(THROWC, FLfunc,(mES | mBP),"_d_throwc", SFLexit, t) \
SYMBOL_MARS(THROWDWARF, FLfunc,(mES | mBP),"_d_throwdwarf", SFLexit, t) \
SYMBOL_MARS(MONITOR_HANDLER, FLfunc,FREGSAVED,"_d_monitor_handler", 0, tsclib) \
SYMBOL_MARS(MONITOR_PROLOG, FLfunc,FREGSAVED,"_d_monitor_prolog",0,t) \
SYMBOL_MARS(MONITOR_EPILOG, FLfunc,FREGSAVED,"_d_monitor_epilog",0,t) \
Expand Down Expand Up @@ -141,6 +142,8 @@ SYMBOL_SCPP(CPP_HANDLER, FLfunc,FREGSAVED,"_cpp_framehandler", 0, tsclib) \
SYMBOL_MARS(D_HANDLER, FLfunc,FREGSAVED,"_d_framehandler", 0, tsclib) \
SYMBOL_MARS(D_LOCAL_UNWIND2, FLfunc,FREGSAVED,"_d_local_unwind2", 0, tsclib) \
SYMBOL_SCPP(LOCAL_UNWIND2, FLfunc,FREGSAVED,"_local_unwind2", 0, tsclib) \
SYMBOL_Z(UNWIND_RESUME, FLfunc,FREGSAVED,"_Unwind_Resume", SFLexit, tsclib) \
SYMBOL_Z(PERSONALITY, FLfunc,FREGSAVED,"__dmd_personality_v0", 0, tsclib) \
\
SYMBOL_Z(TLS_INDEX, FLextern,0,"_tls_index",0,tsint) \
SYMBOL_Z(TLS_ARRAY, FLextern,0,"_tls_array",0,tspvoid) \
Expand Down
1 change: 1 addition & 0 deletions src/backend/symbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,7 @@ void symbol_free(symbol *s)
list_free(&f->Fthunks,(list_free_fp)symbol_free);
}
list_free(&f->Fsymtree,(list_free_fp)symbol_free);
free(f->typesTable);
func_free(f);
}
switch (s->Sclass)
Expand Down
13 changes: 8 additions & 5 deletions src/posix.mak
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,13 @@ DMD_OBJS = \
man.o arrayop.o port.o response.o async.o json.o speller.o aav.o unittests.o \
imphint.o argtypes.o ti_pvoid.o apply.o sapply.o sideeffect.o \
html.o unialpha.o target.o \
pdata.o cv8.o backconfig.o divcoeff.o \
pdata.o cv8.o backconfig.o divcoeff.o dwarfeh.o \
$(TARGET_OBJS)

ifeq (OSX,$(TARGET))
DMD_OBJS += libmach.o scanmach.o machobj.o
else
DMD_OBJS += libelf.o scanelf.o elfobj.o
DMD_OBJS += libelf.o scanelf.o elfobj1.o
endif

SRC = win32.mak posix.mak \
Expand Down Expand Up @@ -158,10 +158,10 @@ SRC = win32.mak posix.mak \
$C/nteh.c $C/os.c $C/out.c $C/outbuf.c $C/ptrntab.c $C/rtlsym.c \
$C/type.c $C/melf.h $C/mach.h $C/mscoff.h $C/bcomplex.h \
$C/cdeflnx.h $C/outbuf.h $C/token.h $C/tassert.h \
$C/elfobj.c $C/cv4.h $C/dwarf2.h $C/exh.h $C/go.h \
$C/elfobj1.c $C/cv4.h $C/dwarf2.h $C/exh.h $C/go.h \
$C/dwarf.c $C/dwarf.h $C/aa.h $C/aa.c $C/tinfo.h $C/ti_achar.c \
$C/ti_pvoid.c $C/platform_stub.c $C/code_x86.h $C/code_stub.h \
$C/machobj.c $C/mscoffobj.c \
$C/machobj.c $C/mscoffobj.c $C/dwarfeh.c \
$C/xmm.h $C/obj.h $C/pdata.c $C/cv8.c $C/backconfig.c $C/divcoeff.c \
$C/html.h $C/html.c $C/unialpha.c \
$C/ph2.c $C/util2.c \
Expand Down Expand Up @@ -392,6 +392,9 @@ dump.o: dump.c
dwarf.o: $C/dwarf.c $C/dwarf.h
$(CC) -c $(MFLAGS) -I. $<

dwarfeh.o: $C/dwarfeh.c $C/dwarf.h
$(CC) -c $(MFLAGS) -I. $<

e2ir.o: e2ir.c $C/rtlsym.h expression.h toir.h
$(CC) -c $(MFLAGS) -I$(ROOT) $<

Expand All @@ -404,7 +407,7 @@ eh.o: eh.c $C/cc.h $C/code.h $C/type.h $C/dt.h
el.o: $C/el.c $C/rtlsym.h $C/el.h
$(CC) -c $(MFLAGS) $<

elfobj.o: $C/elfobj.c
elfobj1.o: $C/elfobj1.c
$(CC) -c $(MFLAGS) $<

entity.o: entity.c
Expand Down
7 changes: 5 additions & 2 deletions src/win32.mak
Original file line number Diff line number Diff line change
Expand Up @@ -230,12 +230,12 @@ BACKSRC= $C\cdef.h $C\cc.h $C\oper.h $C\ty.h $C\optabgen.c \
$C\nteh.c $C\os.c $C\out.c $C\outbuf.c $C\ptrntab.c $C\rtlsym.c \
$C\type.c $C\melf.h $C\mach.h $C\mscoff.h $C\bcomplex.h \
$C\cdeflnx.h $C\outbuf.h $C\token.h $C\tassert.h \
$C\elfobj.c $C\cv4.h $C\dwarf2.h $C\exh.h $C\go.h \
$C\elfobj1.c $C\cv4.h $C\dwarf2.h $C\exh.h $C\go.h \
$C\dwarf.c $C\dwarf.h $C\cppman.c $C\machobj.c \
$C\strtold.c $C\aa.h $C\aa.c $C\tinfo.h $C\ti_achar.c \
$C\md5.h $C\md5.c $C\ti_pvoid.c $C\xmm.h $C\ph2.c $C\util2.c \
$C\mscoffobj.c $C\obj.h $C\pdata.c $C\cv8.c $C\backconfig.c \
$C\divcoeff.c \
$C\divcoeff.c $C\dwarfeh.c \
$C\backend.txt \
$C\html.h $C\html.c

Expand Down Expand Up @@ -463,6 +463,9 @@ dt.obj : $C\dt.h $C\dt.c
dwarf.obj : $C\dwarf.h $C\dwarf.c
$(CC) -c $(MFLAGS) $C\dwarf

dwarfeh.obj : $C\dwarf.h $C\dwarfeh.c
$(CC) -c $(MFLAGS) $C\dwarfeh

ee.obj : $C\ee.c
$(CC) -c $(MFLAGS) $C\ee

Expand Down