mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
Fix #113 - promotion of small static array arguments to registers.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user