Skip to content

Commit e0ac824

Browse files
committed
Refactor and simplify target ABI system.
The big changes in abi-x86-64.cpp are an UNTESTED attempt to clean things up. The simplifications may be too daring, but I hope LLVM gets it right without too much help from our side.
1 parent 483626d commit e0ac824

File tree

6 files changed

+242
-769
lines changed

6 files changed

+242
-769
lines changed

gen/abi-generic.h

+88-91
Original file line numberDiff line numberDiff line change
@@ -24,143 +24,86 @@
2424
/// Removes padding fields for (non-union-containing!) structs
2525
struct RemoveStructPadding : ABIRewrite {
2626
/// get a rewritten value back to its original form
27-
virtual LLValue* get(Type* dty, DValue* v) {
27+
LLValue* get(Type* dty, DValue* v) {
2828
LLValue* lval = DtoAlloca(dty, ".rewritetmp");
2929
getL(dty, v, lval);
3030
return lval;
3131
}
3232

3333
/// get a rewritten value back to its original form and store result in provided lvalue
3434
/// this one is optional and defaults to calling the one above
35-
virtual void getL(Type* dty, DValue* v, llvm::Value* lval) {
35+
void getL(Type* dty, DValue* v, LLValue* lval) {
3636
// Make sure the padding is zero, so struct comparisons work.
3737
// TODO: Only do this if there's padding, and/or only initialize padding.
3838
DtoMemSetZero(lval, DtoConstSize_t(getTypePaddedSize(DtoType(dty))));
3939
DtoPaddedStruct(dty->toBasetype(), v->getRVal(), lval);
4040
}
4141

4242
/// put out rewritten value
43-
virtual LLValue* put(Type* dty, DValue* v) {
43+
LLValue* put(Type* dty, DValue* v) {
4444
return DtoUnpaddedStruct(dty->toBasetype(), v->getRVal());
4545
}
4646

4747
/// return the transformed type for this rewrite
48-
virtual LLType* type(Type* dty, LLType* t) {
48+
LLType* type(Type* dty, LLType* t) {
4949
return DtoUnpaddedStructType(dty->toBasetype());
5050
}
5151
};
5252

5353
//////////////////////////////////////////////////////////////////////////////
5454

55-
// simply swap of real/imag parts for proper x87 complex abi
56-
struct X87_complex_swap : ABIRewrite
57-
{
58-
LLValue* get(Type*, DValue* v)
59-
{
60-
return DtoAggrPairSwap(v->getRVal());
61-
}
62-
LLValue* put(Type*, DValue* v)
63-
{
64-
return DtoAggrPairSwap(v->getRVal());
65-
}
66-
LLType* type(Type*, LLType* t)
67-
{
68-
return t;
69-
}
70-
};
71-
72-
//////////////////////////////////////////////////////////////////////////////
73-
74-
// Rewrites a cfloat (2x32 bits) as 64-bit integer.
75-
// Assumes a little-endian byte order.
76-
struct CfloatToInt : ABIRewrite
77-
{
78-
// i64 -> {float,float}
79-
LLValue* get(Type*, DValue* dv)
80-
{
81-
LLValue* in = dv->getRVal();
82-
83-
// extract real part
84-
LLValue* rpart = gIR->ir->CreateTrunc(in, LLType::getInt32Ty(gIR->context()));
85-
rpart = gIR->ir->CreateBitCast(rpart, LLType::getFloatTy(gIR->context()), ".re");
86-
87-
// extract imag part
88-
LLValue* ipart = gIR->ir->CreateLShr(in, LLConstantInt::get(LLType::getInt64Ty(gIR->context()), 32, false));
89-
ipart = gIR->ir->CreateTrunc(ipart, LLType::getInt32Ty(gIR->context()));
90-
ipart = gIR->ir->CreateBitCast(ipart, LLType::getFloatTy(gIR->context()), ".im");
91-
92-
// return {float,float} aggr pair with same bits
93-
return DtoAggrPair(rpart, ipart, ".final_cfloat");
94-
}
95-
96-
// {float,float} -> i64
97-
LLValue* put(Type*, DValue* dv)
98-
{
99-
LLValue* v = dv->getRVal();
100-
101-
// extract real
102-
LLValue* r = gIR->ir->CreateExtractValue(v, 0);
103-
// cast to i32
104-
r = gIR->ir->CreateBitCast(r, LLType::getInt32Ty(gIR->context()));
105-
// zext to i64
106-
r = gIR->ir->CreateZExt(r, LLType::getInt64Ty(gIR->context()));
107-
108-
// extract imag
109-
LLValue* i = gIR->ir->CreateExtractValue(v, 1);
110-
// cast to i32
111-
i = gIR->ir->CreateBitCast(i, LLType::getInt32Ty(gIR->context()));
112-
// zext to i64
113-
i = gIR->ir->CreateZExt(i, LLType::getInt64Ty(gIR->context()));
114-
// shift up
115-
i = gIR->ir->CreateShl(i, LLConstantInt::get(LLType::getInt64Ty(gIR->context()), 32, false));
116-
117-
// combine and return
118-
return v = gIR->ir->CreateOr(r, i);
119-
}
120-
121-
// {float,float} -> i64
122-
LLType* type(Type*, LLType* t)
123-
{
124-
return LLType::getInt64Ty(gIR->context());
125-
}
126-
};
127-
128-
//////////////////////////////////////////////////////////////////////////////
129-
13055
/**
13156
* Rewrites a composite type parameter to an integer of the same size.
13257
*
13358
* This is needed in order to be able to use LLVM's inreg attribute to put
13459
* struct and static array parameters into registers, because the attribute has
13560
* slightly different semantics. For example, LLVM would store a [4 x i8] inreg
13661
* in four registers (zero-extended), instead of a single 32bit one.
137-
*
138-
* The LLVM value in dv is expected to be a pointer to the parameter, as
139-
* generated when lowering struct/static array paramters to LLVM byval.
14062
*/
14163
struct CompositeToInt : ABIRewrite
14264
{
14365
LLValue* get(Type* dty, DValue* dv)
14466
{
14567
Logger::println("rewriting integer -> %s", dty->toChars());
146-
LLValue* mem = DtoAlloca(dty, ".int_to_composite");
147-
LLValue* v = dv->getRVal();
148-
DtoStore(v, DtoBitCast(mem, getPtrToType(v->getType())));
149-
return DtoLoad(mem);
68+
69+
LLValue* address = 0; // of passed Int
70+
71+
if (dv->isLVal()) // dv is already in memory:
72+
address = dv->getLVal(); // address = &<passed Int>
73+
else { // dump dv to memory:
74+
LLValue* v = dv->getRVal(); // v = <passed Int>
75+
address = DtoRawAlloca(v->getType(), 0, ".int_to_composite"); // address = new Int
76+
DtoStore(v, address); // *address = v
77+
}
78+
79+
LLType* pTy = getPtrToType(DtoType(dty));
80+
return DtoLoad(DtoBitCast(address, pTy), "get-result"); // *(Type*)address
15081
}
15182

152-
void getL(Type* dty, DValue* dv, llvm::Value* lval)
83+
void getL(Type* dty, DValue* dv, LLValue* lval)
15384
{
15485
Logger::println("rewriting integer -> %s", dty->toChars());
155-
LLValue* v = dv->getRVal();
156-
DtoStore(v, DtoBitCast(lval, getPtrToType(v->getType())));
86+
LLValue* v = dv->getRVal(); // v = <passed Int>
87+
DtoStore(v, DtoBitCast(lval, getPtrToType(v->getType()))); // *(Int*)lval = v
15788
}
15889

15990
LLValue* put(Type* dty, DValue* dv)
16091
{
16192
Logger::println("rewriting %s -> integer", dty->toChars());
162-
LLType* t = LLIntegerType::get(gIR->context(), dty->size() * 8);
163-
return DtoLoad(DtoBitCast(dv->getRVal(), getPtrToType(t)));
93+
94+
LLValue* address = 0; // of original parameter dv
95+
96+
if (dv->getRVal()->getType()->isPointerTy()) // dv has been lowered to a pointer to the struct/static array:
97+
address = dv->getRVal(); // address = dv
98+
else if (dv->isLVal()) // dv is already in memory:
99+
address = dv->getLVal(); // address = &dv
100+
else { // dump dv to memory:
101+
address = DtoAlloca(dty, ".composite_to_int"); // address = new Type
102+
DtoStore(dv->getRVal(), address); // *address = dv
103+
}
104+
105+
LLType* intType = type(dty, 0);
106+
return DtoLoad(DtoBitCast(address, getPtrToType(intType)), "put-result"); // *(Int*)address
164107
}
165108

166109
LLType* type(Type* t, LLType*)
@@ -170,4 +113,58 @@ struct CompositeToInt : ABIRewrite
170113
}
171114
};
172115

116+
//////////////////////////////////////////////////////////////////////////////
117+
118+
// FIXME: This should actually be handled by LLVM and the ByVal arg attribute.
119+
struct byval_rewrite : ABIRewrite
120+
{
121+
const size_t alignment;
122+
123+
byval_rewrite(size_t alignment = 16) : alignment(alignment)
124+
{ }
125+
126+
// Get instance from pointer.
127+
LLValue* get(Type* dty, DValue* v)
128+
{
129+
LLValue* ptr = v->getRVal();
130+
return DtoLoad(ptr); // *ptr
131+
}
132+
133+
// Convert the caller's instance to a pointer for the callee.
134+
// The pointer points to a dedicated copy for the callee which
135+
// is allocated by the caller.
136+
LLValue* put(Type* dty, DValue* v)
137+
{
138+
/* NOTE: probably not safe
139+
// optimization: do not copy if parameter is not mutable
140+
if (!dty->isMutable() && v->isLVal())
141+
return v->getLVal();
142+
*/
143+
144+
LLValue* original = v->getRVal();
145+
LLValue* copy;
146+
147+
LLType* type = original->getType();
148+
if (type->isPointerTy())
149+
{
150+
type = type->getPointerElementType();
151+
copy = DtoRawAlloca(type, alignment, "copy_for_callee");
152+
DtoStore(DtoLoad(original), copy); // *copy = *original
153+
}
154+
else
155+
{
156+
copy = DtoRawAlloca(type, alignment, "copy_for_callee");
157+
DtoStore(original, copy); // *copy = original
158+
}
159+
160+
return copy;
161+
}
162+
163+
// T => T*
164+
LLType* type(Type* dty, LLType* t)
165+
{
166+
return getPtrToType(DtoType(dty));
167+
}
168+
};
169+
173170
#endif

gen/abi-ppc64.cpp

+23-59
Original file line numberDiff line numberDiff line change
@@ -20,48 +20,8 @@
2020
#include "gen/llvmhelpers.h"
2121
#include "gen/tollvm.h"
2222

23-
// Implements byval argument passing for scalar non-struct types.
24-
struct PPC64_byval_rewrite : ABIRewrite
25-
{
26-
// Get instance from pointer.
27-
LLValue* get(Type* dty, DValue* v)
28-
{
29-
LLValue* ptr = v->getRVal();
30-
return DtoLoad(ptr); // *ptr
31-
}
32-
33-
// Get instance from pointer, and store in the provided location.
34-
void getL(Type* dty, DValue* v, llvm::Value* lval)
35-
{
36-
LLValue* ptr = v->getRVal();
37-
DtoStore(DtoLoad(ptr), lval); // *lval = *ptr
38-
}
39-
40-
// Turn an instance into a pointer (to a private copy for the callee,
41-
// allocated by the caller).
42-
LLValue* put(Type* dty, DValue* v)
43-
{
44-
/* NOTE: probably not safe
45-
// optimization: do not copy if parameter is not mutable
46-
if (!dty->isMutable() && v->isLVal())
47-
return v->getLVal();
48-
*/
49-
50-
LLValue* original = v->getRVal();
51-
LLValue* copy = DtoRawAlloca(original->getType(), 16, "copy_for_callee");
52-
DtoStore(original, copy); // *copy = *original
53-
return copy;
54-
}
55-
56-
/// should return the transformed type for this rewrite
57-
LLType* type(Type* dty, LLType* t)
58-
{
59-
return getPtrToType(DtoType(dty));
60-
}
61-
};
62-
6323
struct PPC64TargetABI : TargetABI {
64-
PPC64_byval_rewrite byval_rewrite;
24+
byval_rewrite byval_rewrite;
6525
CompositeToInt compositeToInt;
6626
const bool Is64Bit;
6727

@@ -114,40 +74,44 @@ struct PPC64TargetABI : TargetABI {
11474
void rewriteFunctionType(TypeFunction* tf, IrFuncTy &fty)
11575
{
11676
// EXPLICIT PARAMETERS
117-
118-
for (IrFuncTy::ArgRIter I = fty.args.rbegin(), E = fty.args.rend(); I != E; ++I)
77+
for (IrFuncTy::ArgIter I = fty.args.begin(), E = fty.args.end(); I != E; ++I)
11978
{
12079
IrFuncTyArg& arg = **I;
12180

12281
if (arg.byref)
12382
continue;
12483

125-
Type* ty = arg.type->toBasetype();
84+
rewriteArgument(arg);
85+
}
86+
}
12687

127-
if ((ty->ty == Tstruct || ty->ty == Tsarray))
88+
void rewriteArgument(IrFuncTyArg& arg)
89+
{
90+
Type* ty = arg.type->toBasetype();
91+
92+
if (ty->ty == Tstruct || ty->ty == Tsarray)
93+
{
94+
if (canRewriteAsInt(ty))
95+
{
96+
arg.rewrite = &compositeToInt;
97+
arg.ltype = compositeToInt.type(arg.type, arg.ltype);
98+
}
99+
else
128100
{
129-
if (canRewriteAsInt(ty))
130-
{
131-
arg.rewrite = &compositeToInt;
132-
arg.ltype = compositeToInt.type(arg.type, arg.ltype);
133-
}
134-
else
135-
{
136-
// these types are passed byval:
137-
// the caller allocates a copy and then passes a pointer to the copy
138-
arg.rewrite = &byval_rewrite;
139-
arg.ltype = byval_rewrite.type(arg.type, arg.ltype);
140-
}
101+
// these types are passed byval:
102+
// the caller allocates a copy and then passes a pointer to the copy
103+
arg.rewrite = &byval_rewrite;
104+
arg.ltype = byval_rewrite.type(arg.type, arg.ltype);
141105

142106
// the copy is treated as a local variable of the callee
143107
// hence add the NoAlias and NoCapture attributes
144108
#if LDC_LLVM_VER >= 303
145109
arg.attrs.clear();
146110
arg.attrs.addAttribute(llvm::Attribute::NoAlias)
147-
.addAttribute(llvm::Attribute::NoCapture);
111+
.addAttribute(llvm::Attribute::NoCapture);
148112
#elif LDC_LLVM_VER == 302
149113
arg.attrs = llvm::Attributes::get(gIR->context(), llvm::AttrBuilder().addAttribute(llvm::Attributes::NoAlias)
150-
.addAttribute(llvm::Attributes::NoCapture));
114+
.addAttribute(llvm::Attributes::NoCapture));
151115
#else
152116
arg.attrs = llvm::Attribute::NoAlias | llvm::Attribute::NoCapture;
153117
#endif

0 commit comments

Comments
 (0)