diff --git a/gen/abi-generic.h b/gen/abi-generic.h index a33b3d7d..b104c143 100644 --- a/gen/abi-generic.h +++ b/gen/abi-generic.h @@ -55,41 +55,45 @@ struct X87_complex_swap : ABIRewrite ////////////////////////////////////////////////////////////////////////////// -// FIXME: try into eliminating the alloca or if at least check -// if it gets optimized away - -// convert byval struct -// when -struct X86_struct_to_register : ABIRewrite +/** + * Rewrites a composite type parameter to an integer of the same size. + * + * This is needed in order to be able to use LLVM's inreg attribute to put + * struct and static array parameters into registers, because the attribute has + * slightly different semantics. For example, LLVM would store a [4 x i8] inreg + * in four registers (zero-extended), instead of a single 32bit one. + * + * The LLVM value in dv is expected to be a pointer to the parameter, as + * generated when lowering struct/static array paramters to LLVM byval. + */ +struct CompositeToInt : ABIRewrite { - // int -> struct LLValue* get(Type* dty, DValue* dv) { - Logger::println("rewriting int -> struct"); - LLValue* mem = DtoAlloca(dty, ".int_to_struct"); + Logger::println("rewriting integer -> %s", dty->toChars()); + LLValue* mem = DtoAlloca(dty, ".int_to_composite"); LLValue* v = dv->getRVal(); DtoStore(v, DtoBitCast(mem, getPtrToType(v->getType()))); return DtoLoad(mem); } - // int -> struct (with dst lvalue given) + void getL(Type* dty, DValue* dv, llvm::Value* lval) { - Logger::println("rewriting int -> struct"); + Logger::println("rewriting integer -> %s", dty->toChars()); LLValue* v = dv->getRVal(); DtoStore(v, DtoBitCast(lval, getPtrToType(v->getType()))); } - // struct -> int + LLValue* put(Type* dty, DValue* dv) { - Logger::println("rewriting struct -> int"); - assert(dv->isLVal()); - LLValue* mem = dv->getLVal(); - LLType* t = LLIntegerType::get(gIR->context(), dty->size()*8); - return DtoLoad(DtoBitCast(mem, getPtrToType(t))); + Logger::println("rewriting %s -> integer", dty->toChars()); + LLType* t = LLIntegerType::get(gIR->context(), dty->size() * 8); + return DtoLoad(DtoBitCast(dv->getRVal(), getPtrToType(t))); } + LLType* type(Type* t, LLType*) { - size_t sz = t->size()*8; + size_t sz = t->size() * 8; return LLIntegerType::get(gIR->context(), sz); } }; diff --git a/gen/abi-x86-64.cpp b/gen/abi-x86-64.cpp index 81dd8b13..6df721f4 100644 --- a/gen/abi-x86-64.cpp +++ b/gen/abi-x86-64.cpp @@ -348,7 +348,7 @@ struct RegCount { struct X86_64TargetABI : TargetABI { X86_64_C_struct_rewrite struct_rewrite; X87_complex_swap swapComplex; - X86_struct_to_register structToReg; + CompositeToInt compositeToInt; void newFunctionType(TypeFunction* tf) { funcTypeStack.push_back(FuncTypeData(tf->linkage)); @@ -587,25 +587,11 @@ void X86_64TargetABI::rewriteFunctionType(TypeFunction* tf) { else if ((ty->ty == Tstruct || ty->ty == Tsarray) && (sz == 1 || sz == 2 || sz == 4 || sz == 8)) { - if (ty->ty == Tstruct) - { - Logger::println("Putting struct in register"); - arg.rewrite = &structToReg; - arg.ltype = structToReg.type(arg.type, arg.ltype); - arg.byref = false; - // erase previous attributes - arg.attrs = 0; - } - else - { - Logger::println("Putting static array in register"); - // need to make sure type is not pointer - arg.ltype = DtoType(arg.type); - arg.byref = false; - // erase previous attributes - arg.attrs = 0; - } - arg.attrs |= llvm::Attribute::InReg; + Logger::println("Putting struct/sarray in register"); + arg.rewrite = &compositeToInt; + arg.ltype = compositeToInt.type(arg.type, arg.ltype); + arg.byref = false; + arg.attrs = llvm::Attribute::InReg; --regcount; } } diff --git a/gen/abi-x86.cpp b/gen/abi-x86.cpp index e68a400b..edbfd1c3 100644 --- a/gen/abi-x86.cpp +++ b/gen/abi-x86.cpp @@ -69,7 +69,7 @@ struct X86TargetABI : TargetABI { X87_complex_swap swapComplex; X86_cfloat_rewrite cfloatToInt; - X86_struct_to_register structToReg; + CompositeToInt compositeToInt; bool returnInArg(TypeFunction* tf) { @@ -150,19 +150,13 @@ struct X86TargetABI : TargetABI else if (!lastTy->isfloating() && (sz == 1 || sz == 2 || sz == 4)) // right? { // rewrite the struct into an integer to make inreg work - if (lastTy->ty == Tstruct) + if (lastTy->ty == Tstruct || lastTy->ty == Tsarray) { - last->rewrite = &structToReg; - last->ltype = structToReg.type(last->type, last->ltype); + last->rewrite = &compositeToInt; + last->ltype = compositeToInt.type(last->type, last->ltype); last->byref = false; // erase previous attributes - last->attrs = 0; - } - else if (lastTy->ty == Tsarray) - { - last->ltype = DtoType(last->type); - last->byref = false; - last->attrs &= ~llvm::Attribute::ByVal; + last->attrs = llvm::Attribute::None; } last->attrs |= llvm::Attribute::InReg; }