Skip to content

Commit

Permalink
Win64 struct passing
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Aug 25, 2012
1 parent e69ff99 commit 665048a
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 23 deletions.
18 changes: 11 additions & 7 deletions src/backend/cod1.c
Expand Up @@ -2538,12 +2538,13 @@ code *cdfunc(elem *e,regm_t *pretregs)
for (int i = np; --i >= 0;)
{
elem *ep = parameters[i].e;
//printf("[%d] size = %u, numpara = %d ", i, paramsize(ep, stackalign), numpara); WRTYxx(ep->Ety); printf("\n");
unsigned psize = paramsize(ep, stackalign);
//printf("[%d] size = %u, numpara = %d ", i, psize, numpara); WRTYxx(ep->Ety); printf("\n");
if (fpr.alloc(ep->ET, ep->Ety, &parameters[i].reg, &parameters[i].reg2))
{
if (config.exe == EX_WIN64)
{ numpara += REGSIZE; // allocate stack space for it anyway
assert(paramsize(ep, stackalign) <= REGSIZE);
{ assert(psize <= REGSIZE);
numpara += REGSIZE; // allocate stack space for it anyway
}
continue; // goes in register, not stack
}
Expand All @@ -2557,7 +2558,7 @@ code *cdfunc(elem *e,regm_t *pretregs)
parameters[i].numalign = newnumpara - numpara;
numpara = newnumpara;
}
numpara += paramsize(ep,stackalign);
numpara += psize;
}

if (config.exe == EX_WIN64)
Expand Down Expand Up @@ -2587,6 +2588,11 @@ code *cdfunc(elem *e,regm_t *pretregs)
stackpushsave += numalign;
}
assert(stackpush == stackpushsave);
if (config.exe == EX_WIN64)
{
//printf("np = %d, numpara = %d, stackpush = %d\n", np, numpara, stackpush);
assert(numpara == ((np < 4) ? 4 * REGSIZE : np * REGSIZE));
}

int regsaved[XMM7 + 1];
memset(regsaved, -1, sizeof(regsaved));
Expand Down Expand Up @@ -2749,9 +2755,7 @@ code *cdfunc(elem *e,regm_t *pretregs)
if (config.exe == EX_WIN64)
{ // Allocate stack space for four entries anyway
// http://msdn.microsoft.com/en-US/library/ew5tede7(v=vs.80)
unsigned sz = 4 * REGSIZE;
if (stackpush - stackpushsave < sz)
{ sz -= stackpush - stackpushsave;
{ unsigned sz = 4 * REGSIZE;
c = cod3_stackadj(c, sz);
c = genadjesp(c, sz);
stackpush += sz;
Expand Down
40 changes: 24 additions & 16 deletions src/e2ir.c
Expand Up @@ -46,7 +46,7 @@ static char __file__[] = __FILE__; /* for tassert.h */

typedef ArrayBase<elem> Elems;

elem *addressElem(elem *e, Type *t);
elem *addressElem(elem *e, Type *t, bool alwaysCopy = false);
elem *array_toPtr(Type *t, elem *e);
elem *appendDtors(IRState *irs, elem *er, size_t starti, size_t endi);

Expand All @@ -55,11 +55,16 @@ elem *appendDtors(IRState *irs, elem *er, size_t starti, size_t endi);

/* If variable var of type typ is a reference
*/
bool ISREF(Declaration *var, Type *tb)
{
#if SARRAYVALUE
#define ISREF(var, tb) (var->isOut() || var->isRef())
return (var->isParameter() && config.exe == EX_WIN64 && var->type->size(0) > REGSIZE)
|| var->isOut() || var->isRef();
#else
#define ISREF(var, tb) ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
return (var->isParameter() && (var->type->toBasetype()->ty == Tsarray || (config.exe == EX_WIN64 && var->type->size(0) > REGSIZE)))
|| var->isOut() || var->isRef();
#endif
}

/************************************
* Call a function.
Expand Down Expand Up @@ -146,6 +151,14 @@ elem *callfunc(Loc loc,
goto L1;
}
}
if (config.exe == EX_WIN64 && arg->type->size(arg->loc) > REGSIZE)
{ /* Copy to a temporary, and make the argument a pointer
* to that temporary.
*/
ea = arg->toElem(irs);
ea = addressElem(ea, arg->type, true);
goto L1;
}
ea = arg->toElem(irs);
L1:
if (tybasic(ea->Ety) == TYstruct || tybasic(ea->Ety) == TYarray)
Expand Down Expand Up @@ -232,13 +245,10 @@ elem *callfunc(Loc loc,
else
{
// make virtual call
elem *ev;
unsigned vindex;

assert(ethis);
ev = el_same(&ethis);
elem *ev = el_same(&ethis);
ev = el_una(OPind, TYnptr, ev);
vindex = fd->vtblIndex;
unsigned vindex = fd->vtblIndex;
assert((int)vindex >= 0);

// Build *(ev + vindex * 4)
Expand Down Expand Up @@ -336,17 +346,15 @@ if (I32) assert(tysize[TYnptr] == 4);
* Take address of an elem.
*/

elem *addressElem(elem *e, Type *t)
elem *addressElem(elem *e, Type *t, bool alwaysCopy)
{
elem **pe;

//printf("addressElem()\n");

elem **pe;
for (pe = &e; (*pe)->Eoper == OPcomma; pe = &(*pe)->E2)
;
if ((*pe)->Eoper != OPvar && (*pe)->Eoper != OPind)
{ Symbol *stmp;
elem *eeq;
if (alwaysCopy || ((*pe)->Eoper != OPvar && (*pe)->Eoper != OPind))
{
elem *e2 = *pe;
type *tx;

Expand All @@ -356,8 +364,8 @@ elem *addressElem(elem *e, Type *t)
tx = t->toCtype();
else
tx = type_fake(e2->Ety);
stmp = symbol_genauto(tx);
eeq = el_bin(OPeq,e2->Ety,el_var(stmp),e2);
Symbol *stmp = symbol_genauto(tx);
elem *eeq = el_bin(OPeq,e2->Ety,el_var(stmp),e2);
if (tybasic(e2->Ety) == TYstruct)
{
eeq->Eoper = OPstreq;
Expand Down

0 comments on commit 665048a

Please sign in to comment.