mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-02 08:01:11 +03:00
Move calling convention conversion into TargetABI.
The code is tightly coupled to TargetABI (the transformations there only make sense knowing that the right CC is selected).
This commit is contained in:
parent
1a132d5d41
commit
3392f70a4e
10 changed files with 109 additions and 43 deletions
|
@ -20,6 +20,23 @@
|
||||||
#include "gen/tollvm.h"
|
#include "gen/tollvm.h"
|
||||||
|
|
||||||
struct PPC64TargetABI : TargetABI {
|
struct PPC64TargetABI : TargetABI {
|
||||||
|
llvm::CallingConv::ID callingConv(LINK l)
|
||||||
|
{
|
||||||
|
switch (l)
|
||||||
|
{
|
||||||
|
case LINKc:
|
||||||
|
case LINKcpp:
|
||||||
|
case LINKintrinsic:
|
||||||
|
case LINKpascal:
|
||||||
|
case LINKwindows:
|
||||||
|
return llvm::CallingConv::C;
|
||||||
|
case LINKd:
|
||||||
|
case LINKdefault:
|
||||||
|
return llvm::CallingConv::Fast;
|
||||||
|
default:
|
||||||
|
llvm_unreachable("Unhandled D linkage type.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void newFunctionType(TypeFunction* tf)
|
void newFunctionType(TypeFunction* tf)
|
||||||
{
|
{
|
||||||
|
|
|
@ -91,6 +91,8 @@ struct Win64TargetABI : TargetABI
|
||||||
CfloatToInt cfloatToInt;
|
CfloatToInt cfloatToInt;
|
||||||
X87_complex_swap swapComplex;
|
X87_complex_swap swapComplex;
|
||||||
|
|
||||||
|
llvm::CallingConv::ID callingConv(LINK l);
|
||||||
|
|
||||||
bool returnInArg(TypeFunction* tf);
|
bool returnInArg(TypeFunction* tf);
|
||||||
|
|
||||||
bool passByVal(Type* t);
|
bool passByVal(Type* t);
|
||||||
|
@ -105,6 +107,23 @@ TargetABI* getWin64TargetABI()
|
||||||
return new Win64TargetABI;
|
return new Win64TargetABI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
llvm::CallingConv::ID Win64TargetABI::callingConv(LINK l)
|
||||||
|
{
|
||||||
|
switch (l)
|
||||||
|
{
|
||||||
|
case LINKc:
|
||||||
|
case LINKcpp:
|
||||||
|
case LINKd:
|
||||||
|
case LINKdefault:
|
||||||
|
case LINKintrinsic:
|
||||||
|
case LINKwindows:
|
||||||
|
return llvm::CallingConv::C;
|
||||||
|
case LINKpascal:
|
||||||
|
return llvm::CallingConv::X86_StdCall;
|
||||||
|
default:
|
||||||
|
llvm_unreachable("Unhandled D linkage type.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Win64TargetABI::returnInArg(TypeFunction* tf)
|
bool Win64TargetABI::returnInArg(TypeFunction* tf)
|
||||||
{
|
{
|
||||||
|
|
|
@ -366,6 +366,8 @@ struct X86_64TargetABI : TargetABI {
|
||||||
X87_complex_swap swapComplex;
|
X87_complex_swap swapComplex;
|
||||||
CompositeToInt compositeToInt;
|
CompositeToInt compositeToInt;
|
||||||
|
|
||||||
|
llvm::CallingConv::ID callingConv(LINK l);
|
||||||
|
|
||||||
void newFunctionType(TypeFunction* tf) {
|
void newFunctionType(TypeFunction* tf) {
|
||||||
funcTypeStack.push_back(FuncTypeData(tf->linkage));
|
funcTypeStack.push_back(FuncTypeData(tf->linkage));
|
||||||
}
|
}
|
||||||
|
@ -414,6 +416,24 @@ TargetABI* getX86_64TargetABI() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
llvm::CallingConv::ID X86_64TargetABI::callingConv(LINK l)
|
||||||
|
{
|
||||||
|
switch (l)
|
||||||
|
{
|
||||||
|
case LINKc:
|
||||||
|
case LINKcpp:
|
||||||
|
case LINKd:
|
||||||
|
case LINKdefault:
|
||||||
|
case LINKintrinsic:
|
||||||
|
return llvm::CallingConv::C;
|
||||||
|
case LINKpascal:
|
||||||
|
case LINKwindows: // Doesn't really make sense, user should use Win64 target.
|
||||||
|
return llvm::CallingConv::X86_StdCall;
|
||||||
|
default:
|
||||||
|
llvm_unreachable("Unhandled D linkage type.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool X86_64TargetABI::returnInArg(TypeFunction* tf) {
|
bool X86_64TargetABI::returnInArg(TypeFunction* tf) {
|
||||||
assert(linkage() == tf->linkage);
|
assert(linkage() == tf->linkage);
|
||||||
Type* rt = tf->next->toBasetype();
|
Type* rt = tf->next->toBasetype();
|
||||||
|
|
|
@ -26,6 +26,26 @@ struct X86TargetABI : TargetABI
|
||||||
CfloatToInt cfloatToInt;
|
CfloatToInt cfloatToInt;
|
||||||
CompositeToInt compositeToInt;
|
CompositeToInt compositeToInt;
|
||||||
|
|
||||||
|
llvm::CallingConv::ID callingConv(LINK l)
|
||||||
|
{
|
||||||
|
switch (l)
|
||||||
|
{
|
||||||
|
case LINKc:
|
||||||
|
case LINKcpp:
|
||||||
|
case LINKintrinsic:
|
||||||
|
return llvm::CallingConv::C;
|
||||||
|
case LINKd:
|
||||||
|
case LINKdefault:
|
||||||
|
return global.params.targetTriple.isOSWindows() ?
|
||||||
|
llvm::CallingConv::C : llvm::CallingConv::X86_StdCall;
|
||||||
|
case LINKpascal:
|
||||||
|
case LINKwindows:
|
||||||
|
return llvm::CallingConv::X86_StdCall;
|
||||||
|
default:
|
||||||
|
llvm_unreachable("Unhandled D linkage type.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool returnInArg(TypeFunction* tf)
|
bool returnInArg(TypeFunction* tf)
|
||||||
{
|
{
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
|
|
23
gen/abi.cpp
23
gen/abi.cpp
|
@ -38,6 +38,24 @@ void ABIRewrite::getL(Type* dty, DValue* v, llvm::Value* lval)
|
||||||
// Some reasonable defaults for when we don't know what ABI to use.
|
// Some reasonable defaults for when we don't know what ABI to use.
|
||||||
struct UnknownTargetABI : TargetABI
|
struct UnknownTargetABI : TargetABI
|
||||||
{
|
{
|
||||||
|
llvm::CallingConv::ID callingConv(LINK l)
|
||||||
|
{
|
||||||
|
switch (l)
|
||||||
|
{
|
||||||
|
case LINKc:
|
||||||
|
case LINKcpp:
|
||||||
|
case LINKintrinsic:
|
||||||
|
case LINKpascal:
|
||||||
|
case LINKwindows:
|
||||||
|
return llvm::CallingConv::C;
|
||||||
|
case LINKd:
|
||||||
|
case LINKdefault:
|
||||||
|
return llvm::CallingConv::Fast;
|
||||||
|
default:
|
||||||
|
llvm_unreachable("Unhandled D linkage type.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool returnInArg(TypeFunction* tf)
|
bool returnInArg(TypeFunction* tf)
|
||||||
{
|
{
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
|
@ -91,6 +109,11 @@ struct IntrinsicABI : TargetABI
|
||||||
{
|
{
|
||||||
RemoveStructPadding remove_padding;
|
RemoveStructPadding remove_padding;
|
||||||
|
|
||||||
|
llvm::CallingConv::ID callingConv(LINK l)
|
||||||
|
{
|
||||||
|
return llvm::CallingConv::C;
|
||||||
|
}
|
||||||
|
|
||||||
bool returnInArg(TypeFunction* tf)
|
bool returnInArg(TypeFunction* tf)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#ifndef LDC_GEN_ABI_H
|
#ifndef LDC_GEN_ABI_H
|
||||||
#define LDC_GEN_ABI_H
|
#define LDC_GEN_ABI_H
|
||||||
|
|
||||||
|
#include "mars.h"
|
||||||
|
#include "llvm/CallingConv.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct Type;
|
struct Type;
|
||||||
|
@ -56,6 +58,10 @@ struct TargetABI
|
||||||
/// Returns the ABI for intrinsics
|
/// Returns the ABI for intrinsics
|
||||||
static TargetABI* getIntrinsic();
|
static TargetABI* getIntrinsic();
|
||||||
|
|
||||||
|
/// Returns the LLVM calling convention to be used for the given D linkage
|
||||||
|
/// type on the target.
|
||||||
|
virtual llvm::CallingConv::ID callingConv(enum LINK l) = 0;
|
||||||
|
|
||||||
/// Called if a new function type is resolved
|
/// Called if a new function type is resolved
|
||||||
virtual void newFunctionType(TypeFunction* tf) {}
|
virtual void newFunctionType(TypeFunction* tf) {}
|
||||||
|
|
||||||
|
|
|
@ -779,7 +779,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
||||||
&& !fdecl->isMain()
|
&& !fdecl->isMain()
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
func->setCallingConv(DtoCallingConv(fdecl->loc, f->linkage));
|
func->setCallingConv(gABI->callingConv(f->linkage));
|
||||||
else // fall back to C, it should be the right thing to do
|
else // fall back to C, it should be the right thing to do
|
||||||
func->setCallingConv(llvm::CallingConv::C);
|
func->setCallingConv(llvm::CallingConv::C);
|
||||||
|
|
||||||
|
|
|
@ -194,9 +194,6 @@ void tokToIcmpPred(TOK op, bool isUnsigned, llvm::ICmpInst::Predicate* outPred,
|
||||||
// gen/tocall.cpp stuff below
|
// gen/tocall.cpp stuff below
|
||||||
////////////////////////////////////////////
|
////////////////////////////////////////////
|
||||||
|
|
||||||
/// convert DMD calling conv to LLVM
|
|
||||||
llvm::CallingConv::ID DtoCallingConv(Loc loc, LINK l);
|
|
||||||
|
|
||||||
///
|
///
|
||||||
TypeFunction* DtoTypeFunction(DValue* fnval);
|
TypeFunction* DtoTypeFunction(DValue* fnval);
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ static llvm::Function* build_module_function(const std::string &name, const std:
|
||||||
LLFunctionType* fnTy = LLFunctionType::get(LLType::getVoidTy(gIR->context()),argsTy,false);
|
LLFunctionType* fnTy = LLFunctionType::get(LLType::getVoidTy(gIR->context()),argsTy,false);
|
||||||
assert(gIR->module->getFunction(name) == NULL);
|
assert(gIR->module->getFunction(name) == NULL);
|
||||||
llvm::Function* fn = llvm::Function::Create(fnTy, llvm::GlobalValue::InternalLinkage, name, gIR->module);
|
llvm::Function* fn = llvm::Function::Create(fnTy, llvm::GlobalValue::InternalLinkage, name, gIR->module);
|
||||||
fn->setCallingConv(DtoCallingConv(0, LINKd));
|
fn->setCallingConv(gABI->callingConv(LINKd));
|
||||||
|
|
||||||
llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn);
|
llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn);
|
||||||
IRBuilder<> builder(bb);
|
IRBuilder<> builder(bb);
|
||||||
|
@ -89,7 +89,7 @@ static llvm::Function* build_module_function(const std::string &name, const std:
|
||||||
for (FuncIterator itr = funcs.begin(), end = funcs.end(); itr != end; ++itr) {
|
for (FuncIterator itr = funcs.begin(), end = funcs.end(); itr != end; ++itr) {
|
||||||
llvm::Function* f = (*itr)->ir.irFunc->func;
|
llvm::Function* f = (*itr)->ir.irFunc->func;
|
||||||
llvm::CallInst* call = builder.CreateCall(f,"");
|
llvm::CallInst* call = builder.CreateCall(f,"");
|
||||||
call->setCallingConv(DtoCallingConv(0, LINKd));
|
call->setCallingConv(gABI->callingConv(LINKd));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Increment vgate's
|
// Increment vgate's
|
||||||
|
|
|
@ -54,42 +54,6 @@ TypeFunction* DtoTypeFunction(DValue* fnval)
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
llvm::CallingConv::ID DtoCallingConv(Loc loc, LINK l)
|
|
||||||
{
|
|
||||||
llvm::Triple::ArchType const arch = global.params.targetTriple.getArch();
|
|
||||||
|
|
||||||
if (l == LINKc || l == LINKcpp || l == LINKintrinsic)
|
|
||||||
return llvm::CallingConv::C;
|
|
||||||
else if (l == LINKd || l == LINKdefault)
|
|
||||||
{
|
|
||||||
//TODO: StdCall is not a good base on Windows due to extra name mangling
|
|
||||||
// applied there
|
|
||||||
if (arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64)
|
|
||||||
{
|
|
||||||
return global.params.targetTriple.isOSWindows() ?
|
|
||||||
llvm::CallingConv::C : llvm::CallingConv::X86_StdCall;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return llvm::CallingConv::Fast;
|
|
||||||
}
|
|
||||||
// on the other hand, here, it's exactly what we want!!! TODO: right?
|
|
||||||
// On Windows 64bit, there is only one calling convention!
|
|
||||||
else if (l == LINKwindows)
|
|
||||||
{
|
|
||||||
return (arch == llvm::Triple::x86_64) ?
|
|
||||||
llvm::CallingConv::C : llvm::CallingConv::X86_StdCall;
|
|
||||||
}
|
|
||||||
else if (l == LINKpascal)
|
|
||||||
return llvm::CallingConv::X86_StdCall;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
error(loc, "unsupported calling convention");
|
|
||||||
fatal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
DValue* DtoVaArg(Loc& loc, Type* type, Expression* valistArg)
|
DValue* DtoVaArg(Loc& loc, Type* type, Expression* valistArg)
|
||||||
{
|
{
|
||||||
DValue* expelem = valistArg->toElem(gIR);
|
DValue* expelem = valistArg->toElem(gIR);
|
||||||
|
@ -377,7 +341,7 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
||||||
bool nestedcall = tf->fty.arg_nest;
|
bool nestedcall = tf->fty.arg_nest;
|
||||||
bool dvarargs = (tf->linkage == LINKd && tf->varargs == 1);
|
bool dvarargs = (tf->linkage == LINKd && tf->varargs == 1);
|
||||||
|
|
||||||
llvm::CallingConv::ID callconv = DtoCallingConv(loc, tf->linkage);
|
llvm::CallingConv::ID callconv = gABI->callingConv(tf->linkage);
|
||||||
|
|
||||||
// get callee llvm value
|
// get callee llvm value
|
||||||
LLValue* callable = DtoCallableValue(fnval);
|
LLValue* callable = DtoCallableValue(fnval);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue