mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-10 21:06:33 +03:00
Slightly refactor ABIRewrite interface for clarification
* put(): pass DValue alone, without explicit D type * get(): pass LLValue instead of a faked DValue
This commit is contained in:
parent
9e194bfe2c
commit
80c677be46
9 changed files with 68 additions and 76 deletions
|
@ -82,24 +82,23 @@ struct LLTypeMemoryLayout
|
|||
/// Removes padding fields for (non-union-containing!) structs
|
||||
struct RemoveStructPadding : ABIRewrite {
|
||||
/// get a rewritten value back to its original form
|
||||
LLValue* get(Type* dty, DValue* v) {
|
||||
LLValue* get(Type* dty, LLValue* v) {
|
||||
LLValue* lval = DtoAlloca(dty, ".rewritetmp");
|
||||
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
|
||||
void getL(Type* dty, DValue* v, LLValue* lval) {
|
||||
void getL(Type* dty, LLValue* v, LLValue* 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);
|
||||
DtoPaddedStruct(dty->toBasetype(), v, lval);
|
||||
}
|
||||
|
||||
/// put out rewritten value
|
||||
LLValue* put(Type* dty, DValue* v) {
|
||||
return DtoUnpaddedStruct(dty->toBasetype(), v->getRVal());
|
||||
LLValue* put(DValue* v) {
|
||||
return DtoUnpaddedStruct(v->getType()->toBasetype(), v->getRVal());
|
||||
}
|
||||
|
||||
/// return the transformed type for this rewrite
|
||||
|
@ -154,25 +153,22 @@ struct IntegerRewrite : ABIRewrite
|
|||
return LLTypeMemoryLayout::typesAreEquivalent(llType, integerType);
|
||||
}
|
||||
|
||||
LLValue* get(Type* dty, DValue* dv)
|
||||
LLValue* get(Type* dty, LLValue* v)
|
||||
{
|
||||
LLValue* integerDump = DtoAllocaDump(dv, ".IntegerRewrite_dump");
|
||||
|
||||
LLValue* integerDump = DtoAllocaDump(v, dty, ".IntegerRewrite_dump");
|
||||
LLType* type = DtoType(dty);
|
||||
return loadFromMemory(integerDump, type, ".IntegerRewrite_getResult");
|
||||
}
|
||||
|
||||
void getL(Type* dty, DValue* dv, LLValue* lval)
|
||||
void getL(Type* dty, LLValue* v, LLValue* lval)
|
||||
{
|
||||
LLValue* integer = dv->getRVal();
|
||||
storeToMemory(integer, lval);
|
||||
storeToMemory(v, lval);
|
||||
}
|
||||
|
||||
LLValue* put(Type* dty, DValue* dv)
|
||||
LLValue* put(DValue* dv)
|
||||
{
|
||||
assert(dty == dv->getType());
|
||||
LLValue* address = getAddressOf(dv);
|
||||
LLType* integerType = getIntegerType(dty->size());
|
||||
LLType* integerType = getIntegerType(dv->getType()->size());
|
||||
return loadFromMemory(address, integerType, ".IntegerRewrite_putResult");
|
||||
}
|
||||
|
||||
|
@ -204,21 +200,19 @@ struct ExplicitByvalRewrite : ABIRewrite
|
|||
ExplicitByvalRewrite(size_t alignment = 16) : alignment(alignment)
|
||||
{ }
|
||||
|
||||
LLValue* get(Type* dty, DValue* v)
|
||||
LLValue* get(Type* dty, LLValue* v)
|
||||
{
|
||||
LLValue* pointer = v->getRVal();
|
||||
return DtoLoad(pointer, ".ExplicitByvalRewrite_getResult");
|
||||
return DtoLoad(v, ".ExplicitByvalRewrite_getResult");
|
||||
}
|
||||
|
||||
void getL(Type* dty, DValue* v, LLValue* lval)
|
||||
void getL(Type* dty, LLValue* v, LLValue* lval)
|
||||
{
|
||||
LLValue* pointer = v->getRVal();
|
||||
DtoAggrCopy(lval, pointer);
|
||||
DtoAggrCopy(lval, v);
|
||||
}
|
||||
|
||||
LLValue* put(Type* dty, DValue* v)
|
||||
LLValue* put(DValue* v)
|
||||
{
|
||||
if (DtoIsPassedByRef(dty))
|
||||
if (DtoIsPassedByRef(v->getType()))
|
||||
{
|
||||
LLValue* originalPointer = v->getRVal();
|
||||
LLType* type = originalPointer->getType()->getPointerElementType();
|
||||
|
@ -227,8 +221,7 @@ struct ExplicitByvalRewrite : ABIRewrite
|
|||
return copyForCallee;
|
||||
}
|
||||
|
||||
LLValue* copyForCallee = DtoAllocaDump(v->getRVal(), alignment, ".ExplicitByvalRewrite_putResult");
|
||||
return copyForCallee;
|
||||
return DtoAllocaDump(v->getRVal(), alignment, ".ExplicitByvalRewrite_putResult");
|
||||
}
|
||||
|
||||
LLType* type(Type* dty, LLType* t)
|
||||
|
|
|
@ -160,22 +160,21 @@ namespace {
|
|||
* memory so that it's then readable as the other type (i.e., bit-casting).
|
||||
*/
|
||||
struct X86_64_C_struct_rewrite : ABIRewrite {
|
||||
LLValue* get(Type* dty, DValue* v)
|
||||
LLValue* get(Type* dty, LLValue* v)
|
||||
{
|
||||
LLValue* address = DtoAllocaDump(v, ".X86_64_C_struct_rewrite_dump");
|
||||
LLValue* address = DtoAllocaDump(v, dty, ".X86_64_C_struct_rewrite_dump");
|
||||
LLType* type = DtoType(dty);
|
||||
return loadFromMemory(address, type, ".X86_64_C_struct_rewrite_getResult");
|
||||
}
|
||||
|
||||
void getL(Type* dty, DValue* v, LLValue* lval) {
|
||||
storeToMemory(v->getRVal(), lval);
|
||||
void getL(Type* dty, LLValue* v, LLValue* lval) {
|
||||
storeToMemory(v, lval);
|
||||
}
|
||||
|
||||
LLValue* put(Type* dty, DValue* v) {
|
||||
assert(dty == v->getType());
|
||||
LLValue* put(DValue* v) {
|
||||
LLValue* address = getAddressOf(v);
|
||||
|
||||
LLType* abiTy = getAbiType(dty);
|
||||
LLType* abiTy = getAbiType(v->getType());
|
||||
assert(abiTy && "Why are we rewriting a non-rewritten type?");
|
||||
|
||||
return loadFromMemory(address, abiTy, ".X86_64_C_struct_rewrite_putResult");
|
||||
|
@ -195,18 +194,15 @@ struct X86_64_C_struct_rewrite : ABIRewrite {
|
|||
* the ByVal LLVM attribute.
|
||||
*/
|
||||
struct ImplicitByvalRewrite : ABIRewrite {
|
||||
LLValue* get(Type* dty, DValue* v) {
|
||||
LLValue* pointer = v->getRVal();
|
||||
return DtoLoad(pointer, ".ImplicitByvalRewrite_getResult");
|
||||
LLValue* get(Type* dty, LLValue* v) {
|
||||
return DtoLoad(v, ".ImplicitByvalRewrite_getResult");
|
||||
}
|
||||
|
||||
void getL(Type* dty, DValue* v, LLValue* lval) {
|
||||
LLValue* pointer = v->getRVal();
|
||||
DtoAggrCopy(lval, pointer);
|
||||
void getL(Type* dty, LLValue* v, LLValue* lval) {
|
||||
DtoAggrCopy(lval, v);
|
||||
}
|
||||
|
||||
LLValue* put(Type* dty, DValue* v) {
|
||||
assert(dty == v->getType());
|
||||
LLValue* put(DValue* v) {
|
||||
return getAddressOf(v);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ABIRewrite::getL(Type* dty, DValue* v, LLValue* lval)
|
||||
void ABIRewrite::getL(Type* dty, LLValue* v, LLValue* lval)
|
||||
{
|
||||
LLValue* rval = get(dty, v);
|
||||
assert(rval->getType() == lval->getType()->getContainedType(0));
|
||||
|
|
|
@ -44,14 +44,14 @@ struct ABIRewrite
|
|||
virtual ~ABIRewrite() {}
|
||||
|
||||
/// get a rewritten value back to its original form
|
||||
virtual llvm::Value* get(Type* dty, DValue* v) = 0;
|
||||
virtual llvm::Value* get(Type* dty, llvm::Value* v) = 0;
|
||||
|
||||
/// 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);
|
||||
virtual void getL(Type* dty, llvm::Value* v, llvm::Value* lval);
|
||||
|
||||
/// put out rewritten value
|
||||
virtual llvm::Value* put(Type* dty, DValue* v) = 0;
|
||||
virtual llvm::Value* put(DValue* v) = 0;
|
||||
|
||||
/// should return the transformed type for this rewrite
|
||||
virtual llvm::Type* type(Type* dty, llvm::Type* t) = 0;
|
||||
|
|
|
@ -867,8 +867,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
|
|||
LLValue* mem = DtoAlloca(irparam->arg->type, vd->ident->toChars());
|
||||
|
||||
// let the abi transform the argument back first
|
||||
DImValue arg_dval(vd->type, irparam->value);
|
||||
irFty.getParam(vd->type, llArgIdx, &arg_dval, mem);
|
||||
irFty.getParam(vd->type, llArgIdx, irparam->value, mem);
|
||||
|
||||
// set the arg var value to the alloca
|
||||
irparam->value = mem;
|
||||
|
|
|
@ -191,7 +191,7 @@ public:
|
|||
dval = toElemDtor(ae);
|
||||
}
|
||||
// do abi specific transformations on the return value
|
||||
returnValue = getIrFunc(irs->func()->decl)->irFty.putRet(stmt->exp->type, dval);
|
||||
returnValue = getIrFunc(irs->func()->decl)->irFty.putRet(dval);
|
||||
}
|
||||
|
||||
IF_LOG Logger::cout() << "return value is '" << returnValue << "'\n";
|
||||
|
|
|
@ -166,9 +166,9 @@ static void addExplicitArguments(std::vector<LLValue*>& args, AttrSet& attrs,
|
|||
|
||||
llvm::Value* llVal = NULL;
|
||||
if (isVararg)
|
||||
llVal = irFty.putParam(argType, *irArg, argval);
|
||||
llVal = irFty.putParam(*irArg, argval);
|
||||
else
|
||||
llVal = irFty.putParam(argType, i, argval);
|
||||
llVal = irFty.putParam(i, argval);
|
||||
|
||||
const size_t llArgIdx = implicitLLArgCount +
|
||||
(irFty.reverseParams ? explicitLLArgCount - i - 1 : i);
|
||||
|
@ -806,18 +806,17 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
|||
if (!intrinsic && !retinptr)
|
||||
{
|
||||
// do abi specific return value fixups
|
||||
DImValue dretval(returntype, retllval);
|
||||
if (storeReturnValueOnStack)
|
||||
{
|
||||
Logger::println("Storing return value to stack slot");
|
||||
LLValue* mem = DtoAlloca(returntype);
|
||||
irFty.getRet(returntype, &dretval, mem);
|
||||
irFty.getRet(returntype, retllval, mem);
|
||||
retllval = mem;
|
||||
storeReturnValueOnStack = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
retllval = irFty.getRet(returntype, &dretval);
|
||||
retllval = irFty.getRet(returntype, retllval);
|
||||
storeReturnValueOnStack =
|
||||
(returnTy == Tstruct && !isaPointer(retllval)) ||
|
||||
(returnTy == Tsarray && isaArray(retllval));
|
||||
|
|
|
@ -19,65 +19,70 @@ IrFuncTyArg::IrFuncTyArg(Type* t, bool bref, const AttrBuilder& a)
|
|||
: type(t), parametersIdx(0),
|
||||
ltype(t != Type::tvoid && bref ? DtoType(t->pointerTo()) : DtoType(t)),
|
||||
attrs(a), byref(bref), rewrite(0)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
bool IrFuncTyArg::isInReg() const { return attrs.contains(LDC_ATTRIBUTE(InReg)); }
|
||||
bool IrFuncTyArg::isSRet() const { return attrs.contains(LDC_ATTRIBUTE(StructRet)); }
|
||||
bool IrFuncTyArg::isByVal() const { return attrs.contains(LDC_ATTRIBUTE(ByVal)); }
|
||||
|
||||
llvm::Value* IrFuncTy::putRet(Type* dty, DValue* val)
|
||||
llvm::Value* IrFuncTy::putRet(DValue* dval)
|
||||
{
|
||||
assert(!arg_sret);
|
||||
|
||||
if (ret->rewrite) {
|
||||
Logger::println("Rewrite: putRet");
|
||||
LOG_SCOPE
|
||||
return ret->rewrite->put(dty, val);
|
||||
return ret->rewrite->put(dval);
|
||||
}
|
||||
return val->getRVal();
|
||||
|
||||
return dval->getRVal();
|
||||
}
|
||||
|
||||
llvm::Value* IrFuncTy::getRet(Type* dty, DValue* val)
|
||||
llvm::Value* IrFuncTy::getRet(Type* dty, LLValue* val)
|
||||
{
|
||||
assert(!arg_sret);
|
||||
|
||||
if (ret->rewrite) {
|
||||
Logger::println("Rewrite: getRet");
|
||||
LOG_SCOPE
|
||||
return ret->rewrite->get(dty, val);
|
||||
}
|
||||
return val->getRVal();
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void IrFuncTy::getRet(Type* dty, DValue* val, llvm::Value* lval)
|
||||
void IrFuncTy::getRet(Type* dty, LLValue* val, LLValue* address)
|
||||
{
|
||||
assert(!arg_sret);
|
||||
|
||||
if (ret->rewrite) {
|
||||
Logger::println("Rewrite: getRet (getL)");
|
||||
LOG_SCOPE
|
||||
ret->rewrite->getL(dty, val, lval);
|
||||
ret->rewrite->getL(dty, val, address);
|
||||
return;
|
||||
}
|
||||
|
||||
DtoStoreZextI8(val->getRVal(), lval);
|
||||
DtoStoreZextI8(val, address);
|
||||
}
|
||||
|
||||
llvm::Value* IrFuncTy::putParam(Type* dty, size_t idx, DValue* val)
|
||||
llvm::Value* IrFuncTy::putParam(size_t idx, DValue* dval)
|
||||
{
|
||||
assert(idx < args.size() && "invalid putParam");
|
||||
return putParam(dty, *args[idx], val);
|
||||
return putParam(*args[idx], dval);
|
||||
}
|
||||
|
||||
llvm::Value* IrFuncTy::putParam(Type* dty, const IrFuncTyArg& arg, DValue* val)
|
||||
llvm::Value* IrFuncTy::putParam(const IrFuncTyArg& arg, DValue* dval)
|
||||
{
|
||||
if (arg.rewrite) {
|
||||
Logger::println("Rewrite: putParam");
|
||||
LOG_SCOPE
|
||||
return arg.rewrite->put(dty, val);
|
||||
return arg.rewrite->put(dval);
|
||||
}
|
||||
return val->getRVal();
|
||||
|
||||
return dval->getRVal();
|
||||
}
|
||||
|
||||
void IrFuncTy::getParam(Type* dty, size_t idx, DValue* val, llvm::Value* lval)
|
||||
void IrFuncTy::getParam(Type* dty, size_t idx, LLValue* val, LLValue* address)
|
||||
{
|
||||
assert(idx < args.size() && "invalid getParam");
|
||||
|
||||
|
@ -85,9 +90,9 @@ void IrFuncTy::getParam(Type* dty, size_t idx, DValue* val, llvm::Value* lval)
|
|||
{
|
||||
Logger::println("Rewrite: getParam (getL)");
|
||||
LOG_SCOPE
|
||||
args[idx]->rewrite->getL(dty, val, lval);
|
||||
args[idx]->rewrite->getL(dty, val, address);
|
||||
return;
|
||||
}
|
||||
|
||||
DtoStoreZextI8(val->getRVal(), lval);
|
||||
DtoStoreZextI8(val, address);
|
||||
}
|
||||
|
|
|
@ -133,13 +133,13 @@ struct IrFuncTy
|
|||
tag(NULL)
|
||||
{}
|
||||
|
||||
llvm::Value* putRet(Type* dty, DValue* dval);
|
||||
llvm::Value* getRet(Type* dty, DValue* dval);
|
||||
void getRet(Type* dty, DValue* dval, llvm::Value* lval);
|
||||
llvm::Value* putRet(DValue* dval);
|
||||
llvm::Value* getRet(Type* dty, llvm::Value* val);
|
||||
void getRet(Type* dty, llvm::Value* val, llvm::Value* address);
|
||||
|
||||
llvm::Value* putParam(Type* dty, size_t idx, DValue* dval);
|
||||
llvm::Value* putParam(Type* dty, const IrFuncTyArg& arg, DValue* dval);
|
||||
void getParam(Type* dty, size_t idx, DValue* dval, llvm::Value* lval);
|
||||
llvm::Value* putParam(size_t idx, DValue* dval);
|
||||
llvm::Value* putParam(const IrFuncTyArg& arg, DValue* dval);
|
||||
void getParam(Type* dty, size_t idx, llvm::Value* val, llvm::Value* address);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue