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:
David Nadlinger 2013-02-18 10:02:32 +01:00
parent 1a132d5d41
commit 3392f70a4e
10 changed files with 109 additions and 43 deletions

View file

@ -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)
{ {

View file

@ -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)
{ {

View file

@ -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();

View file

@ -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

View file

@ -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;

View file

@ -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) {}

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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);