Fix passing of a padded struct to a function

This commit is contained in:
Alexey Prokhin
2011-02-26 20:16:01 +03:00
parent 20e6c65200
commit 70aee84c70
4 changed files with 22 additions and 18 deletions

View File

@@ -10,18 +10,16 @@ struct RemoveStructPadding : ABIRewrite {
/// get a rewritten value back to its original form
virtual LLValue* get(Type* dty, DValue* v) {
LLValue* lval = DtoAlloca(dty, ".rewritetmp");
// Make sure the padding is zero, so struct comparisons work.
// TODO: Only do this if there's padding, and/or only initialize padding.
DtoMemSetZero(lval, DtoConstSize_t(getTypePaddedSize(DtoType(dty))));
DtoPaddedStruct(dty->toBasetype(), v->getRVal(), lval);
getL(dty, v, lval);
return lval;
}
/// get a rewritten value back to its original form and store result in provided lvalue
/// this one is optional and defaults to calling the one above
virtual void getL(Type* dty, DValue* v, llvm::Value* lval) {
// Make sure the padding is zero, so struct comparisons work.
// TODO: Only do this if there's padding, and/or only initialize padding.
DtoMemSetZero(lval, DtoConstSize_t(getTypePaddedSize(DtoType(dty))));
DtoPaddedStruct(dty->toBasetype(), v->getRVal(), lval);
}

View File

@@ -653,10 +653,12 @@ bool X86_64TargetABI::passByVal(Type* t) {
// Structs passed or returned in registers are passed here
// to get their padding removed (if necessary).
void X86_64TargetABI::fixup_D(IrFuncTyArg& arg) {
assert(arg.type->toBasetype()->ty == Tstruct);
LLType* abiTy = DtoUnpaddedStructType(arg.type->toBasetype());
if (abiTy && abiTy != arg.ltype) {
TypeStruct *type = (TypeStruct*)arg.type->toBasetype();
assert(type->ty == Tstruct);
if (type->alignsize() != 1) {
// TODO: don't do this transformation if there's no padding
LLType* abiTy = DtoUnpaddedStructType(type);
assert(abiTy);
arg.ltype = abiTy;
arg.rewrite = &remove_padding;
}

View File

@@ -258,9 +258,11 @@ LLValue* DtoResolveNestedContext(Loc loc, ClassDeclaration *decl, LLValue *value
LLValue* nest = DtoNestedContext(loc, decl);
// store into right location
size_t idx = decl->vthis->ir.irField->index;
LLValue* gep = DtoGEPi(value,0,idx,"tmp");
DtoStore(DtoBitCast(nest, gep->getType()->getContainedType(0)), gep);
if (!llvm::dyn_cast<llvm::UndefValue>(nest)) {
size_t idx = decl->vthis->ir.irField->index;
LLValue* gep = DtoGEPi(value,0,idx,".vthis");
DtoStore(DtoBitCast(nest, gep->getType()->getContainedType(0)), gep);
}
}
LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)

View File

@@ -115,22 +115,24 @@ void ReturnStatement::toIR(IRState* p)
else
{
LLValue* v;
DValue* dval = exp->toElem(p);
// call postblit if necessary
callPostblitHelper(loc, exp, dval->getRVal());
if (!exp && (p->topfunc() == p->mainFunc))
v = LLConstant::getNullValue(p->mainFunc->getReturnType());
else
// do abi specific transformations on the return value
#if DMDV2
v = p->func()->type->fty.putRet(exp->type, exp->toElem(p), p->func()->type->isref);
v = p->func()->type->fty.putRet(exp->type, dval, p->func()->type->isref);
#else
v = p->func()->type->fty.putRet(exp->type, exp->toElem(p));
v = p->func()->type->fty.putRet(exp->type, dval);
#endif
if (Logger::enabled())
Logger::cout() << "return value is '" <<*v << "'\n";
// call postblit if necessary
callPostblitHelper(loc, exp, v);
IrFunction* f = p->func();
// Hack around LDC assuming structs and static arrays are in memory:
// If the function returns a struct or a static array, and the return