mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-03 08:30:47 +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"
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -91,6 +91,8 @@ struct Win64TargetABI : TargetABI
|
|||
CfloatToInt cfloatToInt;
|
||||
X87_complex_swap swapComplex;
|
||||
|
||||
llvm::CallingConv::ID callingConv(LINK l);
|
||||
|
||||
bool returnInArg(TypeFunction* tf);
|
||||
|
||||
bool passByVal(Type* t);
|
||||
|
@ -105,6 +107,23 @@ TargetABI* getWin64TargetABI()
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -366,6 +366,8 @@ struct X86_64TargetABI : TargetABI {
|
|||
X87_complex_swap swapComplex;
|
||||
CompositeToInt compositeToInt;
|
||||
|
||||
llvm::CallingConv::ID callingConv(LINK l);
|
||||
|
||||
void newFunctionType(TypeFunction* tf) {
|
||||
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) {
|
||||
assert(linkage() == tf->linkage);
|
||||
Type* rt = tf->next->toBasetype();
|
||||
|
|
|
@ -26,6 +26,26 @@ struct X86TargetABI : TargetABI
|
|||
CfloatToInt cfloatToInt;
|
||||
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)
|
||||
{
|
||||
#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.
|
||||
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)
|
||||
{
|
||||
#if DMDV2
|
||||
|
@ -91,6 +109,11 @@ struct IntrinsicABI : TargetABI
|
|||
{
|
||||
RemoveStructPadding remove_padding;
|
||||
|
||||
llvm::CallingConv::ID callingConv(LINK l)
|
||||
{
|
||||
return llvm::CallingConv::C;
|
||||
}
|
||||
|
||||
bool returnInArg(TypeFunction* tf)
|
||||
{
|
||||
return false;
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#ifndef LDC_GEN_ABI_H
|
||||
#define LDC_GEN_ABI_H
|
||||
|
||||
#include "mars.h"
|
||||
#include "llvm/CallingConv.h"
|
||||
#include <vector>
|
||||
|
||||
struct Type;
|
||||
|
@ -56,6 +58,10 @@ struct TargetABI
|
|||
/// Returns the ABI for intrinsics
|
||||
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
|
||||
virtual void newFunctionType(TypeFunction* tf) {}
|
||||
|
||||
|
|
|
@ -779,7 +779,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
|||
&& !fdecl->isMain()
|
||||
#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
|
||||
func->setCallingConv(llvm::CallingConv::C);
|
||||
|
||||
|
|
|
@ -194,9 +194,6 @@ void tokToIcmpPred(TOK op, bool isUnsigned, llvm::ICmpInst::Predicate* outPred,
|
|||
// gen/tocall.cpp stuff below
|
||||
////////////////////////////////////////////
|
||||
|
||||
/// convert DMD calling conv to LLVM
|
||||
llvm::CallingConv::ID DtoCallingConv(Loc loc, LINK l);
|
||||
|
||||
///
|
||||
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);
|
||||
assert(gIR->module->getFunction(name) == NULL);
|
||||
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);
|
||||
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) {
|
||||
llvm::Function* f = (*itr)->ir.irFunc->func;
|
||||
llvm::CallInst* call = builder.CreateCall(f,"");
|
||||
call->setCallingConv(DtoCallingConv(0, LINKd));
|
||||
call->setCallingConv(gABI->callingConv(LINKd));
|
||||
}
|
||||
|
||||
// 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* expelem = valistArg->toElem(gIR);
|
||||
|
@ -377,7 +341,7 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
|||
bool nestedcall = tf->fty.arg_nest;
|
||||
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
|
||||
LLValue* callable = DtoCallableValue(fnval);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue