summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorAnton Korobeynikov <asl@math.spbu.ru>2014-12-02 16:04:58 +0000
committerAnton Korobeynikov <asl@math.spbu.ru>2014-12-02 16:04:58 +0000
commitd90dd7977e2d25a4f190c833114d97d354ce0590 (patch)
tree62459a8646ce57164c8f687edfeb4665580f5455 /clang/lib/CodeGen
parent870e7909243e0e7c02d40ce363aaf6bd53c28d21 (diff)
downloadbcm5719-llvm-d90dd7977e2d25a4f190c833114d97d354ce0590.tar.gz
bcm5719-llvm-d90dd7977e2d25a4f190c833114d97d354ce0590.zip
Fix invalid calling convention used for libcalls on ARM.
ARM ABI specifies that all the libcalls use soft FP ABI (even hard FP binaries). These days clang emits _mulsc3 / _muldc3 calls with default (C) calling convention which would be translated into AAPCS_VFP LLVM calling and thus the result of complex multiplication will be bogus. Introduce a way for a target to specify explicitly calling convention for libcalls. Right now this is temporary correctness fix. Ultimately, we'll end with intrinsic for complex multiplication and all calling convention decisions for libcalls will be put into backend. llvm-svn: 223123
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/ABIInfo.h10
-rw-r--r--clang/lib/CodeGen/CGExprComplex.cpp19
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp16
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h7
-rw-r--r--clang/lib/CodeGen/TargetInfo.cpp9
5 files changed, 52 insertions, 9 deletions
diff --git a/clang/lib/CodeGen/ABIInfo.h b/clang/lib/CodeGen/ABIInfo.h
index 2976b605d39..7e7f7fa2067 100644
--- a/clang/lib/CodeGen/ABIInfo.h
+++ b/clang/lib/CodeGen/ABIInfo.h
@@ -44,9 +44,12 @@ namespace clang {
CodeGen::CodeGenTypes &CGT;
protected:
llvm::CallingConv::ID RuntimeCC;
+ llvm::CallingConv::ID BuiltinCC;
public:
ABIInfo(CodeGen::CodeGenTypes &cgt)
- : CGT(cgt), RuntimeCC(llvm::CallingConv::C) {}
+ : CGT(cgt),
+ RuntimeCC(llvm::CallingConv::C),
+ BuiltinCC(llvm::CallingConv::C) {}
virtual ~ABIInfo();
@@ -62,6 +65,11 @@ namespace clang {
return RuntimeCC;
}
+ /// Return the calling convention to use for compiler builtins
+ llvm::CallingConv::ID getBuiltinCC() const {
+ return BuiltinCC;
+ }
+
virtual void computeInfo(CodeGen::CGFunctionInfo &FI) const = 0;
/// EmitVAArg - Emit the target dependent code to load a value of
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index 4700c7eef35..6b7826eef5d 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -582,13 +582,22 @@ ComplexPairTy ComplexExprEmitter::EmitComplexBinOpLibCall(StringRef LibCallName,
Op.Ty->castAs<ComplexType>()->getElementType());
// We *must* use the full CG function call building logic here because the
- // complex type has special ABI handling.
- const CGFunctionInfo &FuncInfo = CGF.CGM.getTypes().arrangeFreeFunctionCall(
- Op.Ty, Args, FunctionType::ExtInfo(), RequiredArgs::All);
+ // complex type has special ABI handling. We also should not forget about
+ // special calling convention which may be used for compiler builtins.
+ const CGFunctionInfo &FuncInfo =
+ CGF.CGM.getTypes().arrangeFreeFunctionCall(
+ Op.Ty, Args, FunctionType::ExtInfo(/* No CC here - will be added later */),
+ RequiredArgs::All);
llvm::FunctionType *FTy = CGF.CGM.getTypes().GetFunctionType(FuncInfo);
- llvm::Constant *Func = CGF.CGM.CreateRuntimeFunction(FTy, LibCallName);
+ llvm::Constant *Func = CGF.CGM.CreateBuiltinFunction(FTy, LibCallName);
+ llvm::Instruction *Call;
- return CGF.EmitCall(FuncInfo, Func, ReturnValueSlot(), Args).getComplexVal();
+ RValue Res = CGF.EmitCall(FuncInfo, Func, ReturnValueSlot(), Args,
+ nullptr, &Call);
+ cast<llvm::CallInst>(Call)->setCallingConv(CGF.CGM.getBuiltinCC());
+ cast<llvm::CallInst>(Call)->setDoesNotThrow();
+
+ return Res.getComplexVal();
}
/// \brief Lookup the libcall name for a given floating point type complex
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index b6f1f4c97c7..1c0e1f84d76 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -109,6 +109,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
Int8PtrPtrTy = Int8PtrTy->getPointerTo(0);
RuntimeCC = getTargetCodeGenInfo().getABIInfo().getRuntimeCC();
+ BuiltinCC = getTargetCodeGenInfo().getABIInfo().getBuiltinCC();
if (LangOpts.ObjC1)
createObjCRuntime();
@@ -1656,6 +1657,21 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy,
return C;
}
+/// CreateBuiltinFunction - Create a new builtin function with the specified
+/// type and name.
+llvm::Constant *
+CodeGenModule::CreateBuiltinFunction(llvm::FunctionType *FTy,
+ StringRef Name,
+ llvm::AttributeSet ExtraAttrs) {
+ llvm::Constant *C =
+ GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false,
+ /*DontDefer=*/false, /*IsThunk=*/false, ExtraAttrs);
+ if (auto *F = dyn_cast<llvm::Function>(C))
+ if (F->empty())
+ F->setCallingConv(getBuiltinCC());
+ return C;
+}
+
/// isTypeConstant - Determine whether an object of this type can be emitted
/// as a constant.
///
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index a20d66c4c89..d8912390568 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -150,6 +150,8 @@ struct CodeGenTypeCache {
llvm::CallingConv::ID RuntimeCC;
llvm::CallingConv::ID getRuntimeCC() const { return RuntimeCC; }
+ llvm::CallingConv::ID BuiltinCC;
+ llvm::CallingConv::ID getBuiltinCC() const { return BuiltinCC; }
};
struct RREntrypoints {
@@ -874,6 +876,11 @@ public:
StringRef Name,
llvm::AttributeSet ExtraAttrs =
llvm::AttributeSet());
+ /// Create a new compiler builtin function with the specified type and name.
+ llvm::Constant *CreateBuiltinFunction(llvm::FunctionType *Ty,
+ StringRef Name,
+ llvm::AttributeSet ExtraAttrs =
+ llvm::AttributeSet());
/// Create a new runtime global variable with the specified type and name.
llvm::Constant *CreateRuntimeVariable(llvm::Type *Ty,
StringRef Name);
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index fc8e4646e0a..290f183dea4 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -4330,7 +4330,7 @@ private:
public:
ARMABIInfo(CodeGenTypes &CGT, ABIKind _Kind) : ABIInfo(CGT), Kind(_Kind),
NumVFPs(16), NumGPRs(4) {
- setRuntimeCC();
+ setCCs();
resetAllocatedRegs();
}
@@ -4376,7 +4376,7 @@ private:
llvm::CallingConv::ID getLLVMDefaultCC() const;
llvm::CallingConv::ID getABIDefaultCC() const;
- void setRuntimeCC();
+ void setCCs();
void markAllocatedGPRs(unsigned Alignment, unsigned NumRequired) const;
void markAllocatedVFPs(unsigned Alignment, unsigned NumRequired) const;
@@ -4535,7 +4535,7 @@ llvm::CallingConv::ID ARMABIInfo::getABIDefaultCC() const {
llvm_unreachable("bad ABI kind");
}
-void ARMABIInfo::setRuntimeCC() {
+void ARMABIInfo::setCCs() {
assert(getRuntimeCC() == llvm::CallingConv::C);
// Don't muddy up the IR with a ton of explicit annotations if
@@ -4543,6 +4543,9 @@ void ARMABIInfo::setRuntimeCC() {
llvm::CallingConv::ID abiCC = getABIDefaultCC();
if (abiCC != getLLVMDefaultCC())
RuntimeCC = abiCC;
+
+ BuiltinCC = (getABIKind() == APCS ?
+ llvm::CallingConv::ARM_APCS : llvm::CallingConv::ARM_AAPCS);
}
/// markAllocatedVFPs - update VFPRegs according to the alignment and
OpenPOWER on IntegriCloud