mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-12 13:55:57 +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
|
/// Removes padding fields for (non-union-containing!) structs
|
||||||
struct RemoveStructPadding : ABIRewrite {
|
struct RemoveStructPadding : ABIRewrite {
|
||||||
/// get a rewritten value back to its original form
|
/// 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");
|
LLValue* lval = DtoAlloca(dty, ".rewritetmp");
|
||||||
getL(dty, v, lval);
|
getL(dty, v, lval);
|
||||||
return lval;
|
return lval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// get a rewritten value back to its original form and store result in provided lvalue
|
/// 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, LLValue* v, LLValue* lval) {
|
||||||
void getL(Type* dty, DValue* v, LLValue* lval) {
|
|
||||||
// Make sure the padding is zero, so struct comparisons work.
|
// Make sure the padding is zero, so struct comparisons work.
|
||||||
// TODO: Only do this if there's padding, and/or only initialize padding.
|
// TODO: Only do this if there's padding, and/or only initialize padding.
|
||||||
DtoMemSetZero(lval, DtoConstSize_t(getTypePaddedSize(DtoType(dty))));
|
DtoMemSetZero(lval, DtoConstSize_t(getTypePaddedSize(DtoType(dty))));
|
||||||
DtoPaddedStruct(dty->toBasetype(), v->getRVal(), lval);
|
DtoPaddedStruct(dty->toBasetype(), v, lval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// put out rewritten value
|
/// put out rewritten value
|
||||||
LLValue* put(Type* dty, DValue* v) {
|
LLValue* put(DValue* v) {
|
||||||
return DtoUnpaddedStruct(dty->toBasetype(), v->getRVal());
|
return DtoUnpaddedStruct(v->getType()->toBasetype(), v->getRVal());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// return the transformed type for this rewrite
|
/// return the transformed type for this rewrite
|
||||||
|
@ -154,25 +153,22 @@ struct IntegerRewrite : ABIRewrite
|
||||||
return LLTypeMemoryLayout::typesAreEquivalent(llType, integerType);
|
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);
|
LLType* type = DtoType(dty);
|
||||||
return loadFromMemory(integerDump, type, ".IntegerRewrite_getResult");
|
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(v, lval);
|
||||||
storeToMemory(integer, lval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LLValue* put(Type* dty, DValue* dv)
|
LLValue* put(DValue* dv)
|
||||||
{
|
{
|
||||||
assert(dty == dv->getType());
|
|
||||||
LLValue* address = getAddressOf(dv);
|
LLValue* address = getAddressOf(dv);
|
||||||
LLType* integerType = getIntegerType(dty->size());
|
LLType* integerType = getIntegerType(dv->getType()->size());
|
||||||
return loadFromMemory(address, integerType, ".IntegerRewrite_putResult");
|
return loadFromMemory(address, integerType, ".IntegerRewrite_putResult");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,21 +200,19 @@ struct ExplicitByvalRewrite : ABIRewrite
|
||||||
ExplicitByvalRewrite(size_t alignment = 16) : alignment(alignment)
|
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(v, ".ExplicitByvalRewrite_getResult");
|
||||||
return DtoLoad(pointer, ".ExplicitByvalRewrite_getResult");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void getL(Type* dty, DValue* v, LLValue* lval)
|
void getL(Type* dty, LLValue* v, LLValue* lval)
|
||||||
{
|
{
|
||||||
LLValue* pointer = v->getRVal();
|
DtoAggrCopy(lval, v);
|
||||||
DtoAggrCopy(lval, pointer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LLValue* put(Type* dty, DValue* v)
|
LLValue* put(DValue* v)
|
||||||
{
|
{
|
||||||
if (DtoIsPassedByRef(dty))
|
if (DtoIsPassedByRef(v->getType()))
|
||||||
{
|
{
|
||||||
LLValue* originalPointer = v->getRVal();
|
LLValue* originalPointer = v->getRVal();
|
||||||
LLType* type = originalPointer->getType()->getPointerElementType();
|
LLType* type = originalPointer->getType()->getPointerElementType();
|
||||||
|
@ -227,8 +221,7 @@ struct ExplicitByvalRewrite : ABIRewrite
|
||||||
return copyForCallee;
|
return copyForCallee;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLValue* copyForCallee = DtoAllocaDump(v->getRVal(), alignment, ".ExplicitByvalRewrite_putResult");
|
return DtoAllocaDump(v->getRVal(), alignment, ".ExplicitByvalRewrite_putResult");
|
||||||
return copyForCallee;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LLType* type(Type* dty, LLType* t)
|
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).
|
* memory so that it's then readable as the other type (i.e., bit-casting).
|
||||||
*/
|
*/
|
||||||
struct X86_64_C_struct_rewrite : ABIRewrite {
|
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);
|
LLType* type = DtoType(dty);
|
||||||
return loadFromMemory(address, type, ".X86_64_C_struct_rewrite_getResult");
|
return loadFromMemory(address, type, ".X86_64_C_struct_rewrite_getResult");
|
||||||
}
|
}
|
||||||
|
|
||||||
void getL(Type* dty, DValue* v, LLValue* lval) {
|
void getL(Type* dty, LLValue* v, LLValue* lval) {
|
||||||
storeToMemory(v->getRVal(), lval);
|
storeToMemory(v, lval);
|
||||||
}
|
}
|
||||||
|
|
||||||
LLValue* put(Type* dty, DValue* v) {
|
LLValue* put(DValue* v) {
|
||||||
assert(dty == v->getType());
|
|
||||||
LLValue* address = getAddressOf(v);
|
LLValue* address = getAddressOf(v);
|
||||||
|
|
||||||
LLType* abiTy = getAbiType(dty);
|
LLType* abiTy = getAbiType(v->getType());
|
||||||
assert(abiTy && "Why are we rewriting a non-rewritten type?");
|
assert(abiTy && "Why are we rewriting a non-rewritten type?");
|
||||||
|
|
||||||
return loadFromMemory(address, abiTy, ".X86_64_C_struct_rewrite_putResult");
|
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.
|
* the ByVal LLVM attribute.
|
||||||
*/
|
*/
|
||||||
struct ImplicitByvalRewrite : ABIRewrite {
|
struct ImplicitByvalRewrite : ABIRewrite {
|
||||||
LLValue* get(Type* dty, DValue* v) {
|
LLValue* get(Type* dty, LLValue* v) {
|
||||||
LLValue* pointer = v->getRVal();
|
return DtoLoad(v, ".ImplicitByvalRewrite_getResult");
|
||||||
return DtoLoad(pointer, ".ImplicitByvalRewrite_getResult");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void getL(Type* dty, DValue* v, LLValue* lval) {
|
void getL(Type* dty, LLValue* v, LLValue* lval) {
|
||||||
LLValue* pointer = v->getRVal();
|
DtoAggrCopy(lval, v);
|
||||||
DtoAggrCopy(lval, pointer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LLValue* put(Type* dty, DValue* v) {
|
LLValue* put(DValue* v) {
|
||||||
assert(dty == v->getType());
|
|
||||||
return getAddressOf(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);
|
LLValue* rval = get(dty, v);
|
||||||
assert(rval->getType() == lval->getType()->getContainedType(0));
|
assert(rval->getType() == lval->getType()->getContainedType(0));
|
||||||
|
|
|
@ -44,14 +44,14 @@ struct ABIRewrite
|
||||||
virtual ~ABIRewrite() {}
|
virtual ~ABIRewrite() {}
|
||||||
|
|
||||||
/// get a rewritten value back to its original form
|
/// 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
|
/// 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
|
/// 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
|
/// 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
|
/// should return the transformed type for this rewrite
|
||||||
virtual llvm::Type* type(Type* dty, llvm::Type* t) = 0;
|
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());
|
LLValue* mem = DtoAlloca(irparam->arg->type, vd->ident->toChars());
|
||||||
|
|
||||||
// let the abi transform the argument back first
|
// let the abi transform the argument back first
|
||||||
DImValue arg_dval(vd->type, irparam->value);
|
irFty.getParam(vd->type, llArgIdx, irparam->value, mem);
|
||||||
irFty.getParam(vd->type, llArgIdx, &arg_dval, mem);
|
|
||||||
|
|
||||||
// set the arg var value to the alloca
|
// set the arg var value to the alloca
|
||||||
irparam->value = mem;
|
irparam->value = mem;
|
||||||
|
|
|
@ -191,7 +191,7 @@ public:
|
||||||
dval = toElemDtor(ae);
|
dval = toElemDtor(ae);
|
||||||
}
|
}
|
||||||
// do abi specific transformations on the return value
|
// 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";
|
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;
|
llvm::Value* llVal = NULL;
|
||||||
if (isVararg)
|
if (isVararg)
|
||||||
llVal = irFty.putParam(argType, *irArg, argval);
|
llVal = irFty.putParam(*irArg, argval);
|
||||||
else
|
else
|
||||||
llVal = irFty.putParam(argType, i, argval);
|
llVal = irFty.putParam(i, argval);
|
||||||
|
|
||||||
const size_t llArgIdx = implicitLLArgCount +
|
const size_t llArgIdx = implicitLLArgCount +
|
||||||
(irFty.reverseParams ? explicitLLArgCount - i - 1 : i);
|
(irFty.reverseParams ? explicitLLArgCount - i - 1 : i);
|
||||||
|
@ -806,18 +806,17 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
||||||
if (!intrinsic && !retinptr)
|
if (!intrinsic && !retinptr)
|
||||||
{
|
{
|
||||||
// do abi specific return value fixups
|
// do abi specific return value fixups
|
||||||
DImValue dretval(returntype, retllval);
|
|
||||||
if (storeReturnValueOnStack)
|
if (storeReturnValueOnStack)
|
||||||
{
|
{
|
||||||
Logger::println("Storing return value to stack slot");
|
Logger::println("Storing return value to stack slot");
|
||||||
LLValue* mem = DtoAlloca(returntype);
|
LLValue* mem = DtoAlloca(returntype);
|
||||||
irFty.getRet(returntype, &dretval, mem);
|
irFty.getRet(returntype, retllval, mem);
|
||||||
retllval = mem;
|
retllval = mem;
|
||||||
storeReturnValueOnStack = false;
|
storeReturnValueOnStack = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
retllval = irFty.getRet(returntype, &dretval);
|
retllval = irFty.getRet(returntype, retllval);
|
||||||
storeReturnValueOnStack =
|
storeReturnValueOnStack =
|
||||||
(returnTy == Tstruct && !isaPointer(retllval)) ||
|
(returnTy == Tstruct && !isaPointer(retllval)) ||
|
||||||
(returnTy == Tsarray && isaArray(retllval));
|
(returnTy == Tsarray && isaArray(retllval));
|
||||||
|
|
|
@ -19,65 +19,70 @@ IrFuncTyArg::IrFuncTyArg(Type* t, bool bref, const AttrBuilder& a)
|
||||||
: type(t), parametersIdx(0),
|
: type(t), parametersIdx(0),
|
||||||
ltype(t != Type::tvoid && bref ? DtoType(t->pointerTo()) : DtoType(t)),
|
ltype(t != Type::tvoid && bref ? DtoType(t->pointerTo()) : DtoType(t)),
|
||||||
attrs(a), byref(bref), rewrite(0)
|
attrs(a), byref(bref), rewrite(0)
|
||||||
{
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
bool IrFuncTyArg::isInReg() const { return attrs.contains(LDC_ATTRIBUTE(InReg)); }
|
bool IrFuncTyArg::isInReg() const { return attrs.contains(LDC_ATTRIBUTE(InReg)); }
|
||||||
bool IrFuncTyArg::isSRet() const { return attrs.contains(LDC_ATTRIBUTE(StructRet)); }
|
bool IrFuncTyArg::isSRet() const { return attrs.contains(LDC_ATTRIBUTE(StructRet)); }
|
||||||
bool IrFuncTyArg::isByVal() const { return attrs.contains(LDC_ATTRIBUTE(ByVal)); }
|
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);
|
assert(!arg_sret);
|
||||||
|
|
||||||
if (ret->rewrite) {
|
if (ret->rewrite) {
|
||||||
Logger::println("Rewrite: putRet");
|
Logger::println("Rewrite: putRet");
|
||||||
LOG_SCOPE
|
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);
|
assert(!arg_sret);
|
||||||
|
|
||||||
if (ret->rewrite) {
|
if (ret->rewrite) {
|
||||||
Logger::println("Rewrite: getRet");
|
Logger::println("Rewrite: getRet");
|
||||||
LOG_SCOPE
|
LOG_SCOPE
|
||||||
return ret->rewrite->get(dty, val);
|
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);
|
assert(!arg_sret);
|
||||||
|
|
||||||
if (ret->rewrite) {
|
if (ret->rewrite) {
|
||||||
Logger::println("Rewrite: getRet (getL)");
|
Logger::println("Rewrite: getRet (getL)");
|
||||||
LOG_SCOPE
|
LOG_SCOPE
|
||||||
ret->rewrite->getL(dty, val, lval);
|
ret->rewrite->getL(dty, val, address);
|
||||||
return;
|
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");
|
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) {
|
if (arg.rewrite) {
|
||||||
Logger::println("Rewrite: putParam");
|
Logger::println("Rewrite: putParam");
|
||||||
LOG_SCOPE
|
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");
|
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)");
|
Logger::println("Rewrite: getParam (getL)");
|
||||||
LOG_SCOPE
|
LOG_SCOPE
|
||||||
args[idx]->rewrite->getL(dty, val, lval);
|
args[idx]->rewrite->getL(dty, val, address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DtoStoreZextI8(val->getRVal(), lval);
|
DtoStoreZextI8(val, address);
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,13 +133,13 @@ struct IrFuncTy
|
||||||
tag(NULL)
|
tag(NULL)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
llvm::Value* putRet(Type* dty, DValue* dval);
|
llvm::Value* putRet(DValue* dval);
|
||||||
llvm::Value* getRet(Type* dty, DValue* dval);
|
llvm::Value* getRet(Type* dty, llvm::Value* val);
|
||||||
void getRet(Type* dty, DValue* dval, llvm::Value* lval);
|
void getRet(Type* dty, llvm::Value* val, llvm::Value* address);
|
||||||
|
|
||||||
llvm::Value* putParam(Type* dty, size_t idx, DValue* dval);
|
llvm::Value* putParam(size_t idx, DValue* dval);
|
||||||
llvm::Value* putParam(Type* dty, const IrFuncTyArg& arg, DValue* dval);
|
llvm::Value* putParam(const IrFuncTyArg& arg, DValue* dval);
|
||||||
void getParam(Type* dty, size_t idx, DValue* dval, llvm::Value* lval);
|
void getParam(Type* dty, size_t idx, llvm::Value* val, llvm::Value* address);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue