# HG changeset patch # User Christian Kamm # Date 1233769173 -3600 # Node ID a904cc9bc064fd151c351125fcda129815ebb13e # Parent b6647328d11e2ec7972be23185db696a6106fafe Convert struct arg to integer when passing inreg to make sure LLVM doesn't ignore the attribute! diff -r b6647328d11e -r a904cc9bc064 dmd/mtype.c --- a/dmd/mtype.c Tue Feb 03 21:46:54 2009 +0100 +++ b/dmd/mtype.c Wed Feb 04 18:39:33 2009 +0100 @@ -2691,7 +2691,7 @@ this->retInPtr = false; this->usesThis = false; this->usesNest = false; - this->structInregArg = false; + this->structInregArg = NULL; this->retAttrs = 0; this->thisAttrs = 0; this->reverseParams = false; diff -r b6647328d11e -r a904cc9bc064 dmd/mtype.h --- a/dmd/mtype.h Tue Feb 03 21:46:54 2009 +0100 +++ b/dmd/mtype.h Wed Feb 04 18:39:33 2009 +0100 @@ -23,6 +23,7 @@ // llvm #include "../ir/irtype.h" +namespace llvm { class Type; } struct Scope; struct Identifier; @@ -438,7 +439,8 @@ bool retInPtr; bool usesThis; bool usesNest; - bool structInregArg; + // when the last arg is a struct and passed in EAX, this holds its real type + const llvm::Type* structInregArg; unsigned retAttrs; unsigned thisAttrs; // also used for nest // parameter index in the llvm function that contains the first not-implicit arg diff -r b6647328d11e -r a904cc9bc064 gen/functions.cpp --- a/gen/functions.cpp Tue Feb 03 21:46:54 2009 +0100 +++ b/gen/functions.cpp Wed Feb 04 18:39:33 2009 +0100 @@ -220,15 +220,15 @@ arg->llvmAttrs |= llvm::Attribute::InReg; assert((f->thisAttrs & llvm::Attribute::InReg) == 0 && "can't have two inreg args!"); - // structs need to go from {...}* byval to {...} inreg + // structs need to go from {...}* byval to i8/i16/i32 inreg if ((arg->storageClass & STCin) && t->ty == Tstruct) { int n_param = f->reverseParams ? f->firstRealArg + n - 1 - n_inreg : f->firstRealArg + n_inreg; assert(isaPointer(paramvec[n_param]) && (arg->llvmAttrs & llvm::Attribute::ByVal) && "struct parameter expected to be {...}* byval before inreg is applied"); - paramvec[n_param] = paramvec[n_param]->getContainedType(0); + f->structInregArg = paramvec[n_param]->getContainedType(0); + paramvec[n_param] = LLIntegerType::get(8*t->size()); arg->llvmAttrs &= ~llvm::Attribute::ByVal; - f->structInregArg = true; } } } @@ -759,11 +759,14 @@ if (f->structInregArg && i == (f->reverseParams ? n - 1 : 0)) { int n_param = f->reverseParams ? f->firstRealArg + n - 1 - i : f->firstRealArg + i; - assert(!f->usesNest && !f->usesThis && isaStruct(functype->getParamType(n_param)) + const LLType* paramty = functype->getParamType(n_param); + assert(!f->usesNest && !f->usesThis && + llvm::isa(paramty) && isaStruct(f->structInregArg) && "Preconditions for inreg struct arg not met!"); - LLValue* mem = DtoAlloca(functype->getParamType(n_param), "inregstructarg"); - DtoStore(irloc->value, mem); + LLValue* mem = DtoAlloca(f->structInregArg, "inregstructarg"); + + DtoStore(irloc->value, DtoBitCast(mem, getPtrToType(paramty))); irloc->value = mem; } diff -r b6647328d11e -r a904cc9bc064 gen/tocall.cpp --- a/gen/tocall.cpp Tue Feb 03 21:46:54 2009 +0100 +++ b/gen/tocall.cpp Wed Feb 04 18:39:33 2009 +0100 @@ -370,15 +370,16 @@ DValue* argval = DtoArgument(fnarg, (Expression*)arguments->data[i]); LLValue* arg = argval->getRVal(); + int j = tf->reverseParams ? beg + n - i - 1 : beg + i; + // if it's a struct inreg arg, load first to pass as first-class value if (tf->structInregArg && i == (tf->reverseParams ? n - 1 : 0)) { - assert(fnarg->llvmAttrs & llvm::Attribute::InReg); + assert((fnarg->llvmAttrs & llvm::Attribute::InReg) && isaStruct(tf->structInregArg)); + arg = DtoBitCast(arg, getPtrToType(callableTy->getParamType(j))); arg = DtoLoad(arg); } - int j = tf->reverseParams ? beg + n - i - 1 : beg + i; - // parameter type mismatch, this is hard to get rid of if (arg->getType() != callableTy->getParamType(j)) {