diff --git a/clang/lib/CodeGen/ABIInfo.h b/clang/lib/CodeGen/ABIInfo.h index 2976b605d397..7e7f7fa20679 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 4700c7eef359..6b7826eef5d1 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()->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(Call)->setCallingConv(CGF.CGM.getBuiltinCC()); + cast(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 b6f1f4c97c79..1c0e1f84d76e 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(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 a20d66c4c896..d89123905685 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 fc8e4646e0aa..290f183dea4c 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 diff --git a/clang/test/CodeGen/complex-math.c b/clang/test/CodeGen/complex-math.c index 29172fa6d77f..36ef271b0ae0 100644 --- a/clang/test/CodeGen/complex-math.c +++ b/clang/test/CodeGen/complex-math.c @@ -2,6 +2,7 @@ // RUN: %clang_cc1 %s -O1 -emit-llvm -triple x86_64-pc-win64 -o - | FileCheck %s --check-prefix=X86 // RUN: %clang_cc1 %s -O1 -emit-llvm -triple i686-unknown-unknown -o - | FileCheck %s --check-prefix=X86 // RUN: %clang_cc1 %s -O1 -emit-llvm -triple powerpc-unknown-unknown -o - | FileCheck %s --check-prefix=PPC +// RUN: %clang_cc1 %s -O1 -emit-llvm -triple armv7-none-linux-gnueabihf -o - | FileCheck %s --check-prefix=ARM float _Complex add_float_rr(float a, float b) { // X86-LABEL: @add_float_rr( @@ -471,3 +472,10 @@ _Bool ne_float_cc(float _Complex a, float _Complex b) { // X86: ret return a != b; } + +// Check that the libcall will obtain proper calling convention on ARM +_Complex double foo(_Complex double a, _Complex double b) { + // ARM-LABEL: @foo( + // ARM: call arm_aapcscc { double, double } @__muldc3 + return a*b; +}