diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h index 67ce1590cbc82..ea81d878c0ced 100644 --- a/include/swift/AST/IRGenOptions.h +++ b/include/swift/AST/IRGenOptions.h @@ -25,6 +25,7 @@ #include "swift/Basic/OptimizationMode.h" #include "swift/Config.h" #include "clang/Basic/PointerAuthOptions.h" +#include "llvm/IR/CallingConv.h" // FIXME: This include is just for llvm::SanitizerCoverageOptions. We should // split the header upstream so we don't include so much. #include "llvm/Transforms/Instrumentation.h" @@ -477,6 +478,9 @@ class IRGenOptions { /// function instead of to trap instructions. std::string TrapFuncName = ""; + /// The calling convention used to perform non-swift calls. + llvm::CallingConv::ID PlatformCCallingConvention; + IRGenOptions() : DWARFVersion(2), OutputKind(IRGenOutputKind::LLVMAssemblyAfterOptimization), @@ -517,7 +521,8 @@ class IRGenOptions { ColocateTypeDescriptors(true), UseRelativeProtocolWitnessTables(false), CmdArgs(), SanitizeCoverage(llvm::SanitizerCoverageOptions()), - TypeInfoFilter(TypeInfoDumpFilter::All) { + TypeInfoFilter(TypeInfoDumpFilter::All), + PlatformCCallingConvention(llvm::CallingConv::C) { #ifndef NDEBUG DisableRoundTripDebugTypes = false; #else diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index 8e8ed8d5b46bb..b88be4acad09a 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -1224,4 +1224,12 @@ def experimental_spi_only_imports : def enable_ossa_complete_lifetimes : Flag<["-"], "enable-ossa-complete-lifetimes">, HelpText<"Require linear OSSA lifetimes after SILGen">; + +def platform_c_calling_convention : + Separate<["-"], "experimental-platform-c-calling-convention">, + HelpText<"Which calling convention is used to perform non-swift calls. " + "Defaults to llvm's standard C calling convention.">; +def platform_c_calling_convention_EQ : + Joined<["-"], "experimental-platform-c-calling-convention=">, + Alias; } // end let Flags = [FrontendOption, NoDriverOption, HelpHidden] diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 7e4aa57a3c54b..c3182dffc347a 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -2807,6 +2807,16 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, return true; } + if (const Arg *A = Args.getLastArg(options::OPT_platform_c_calling_convention)) { + Opts.PlatformCCallingConvention = + llvm::StringSwitch(A->getValue()) + .Case("c", llvm::CallingConv::C) + .Case("arm_apcs", llvm::CallingConv::ARM_APCS) + .Case("arm_aapcs", llvm::CallingConv::ARM_AAPCS) + .Case("arm_aapcs_vfp", llvm::CallingConv::ARM_AAPCS_VFP) + .Default(llvm::CallingConv::C); + } + return false; } diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index 16fa1bc9e3a39..508fd5f0d1b4e 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -322,7 +322,7 @@ llvm::CallingConv::ID irgen::expandCallingConv(IRGenModule &IGM, case SILFunctionTypeRepresentation::ObjCMethod: case SILFunctionTypeRepresentation::CXXMethod: case SILFunctionTypeRepresentation::Block: - return llvm::CallingConv::C; + return IGM.getOptions().PlatformCCallingConvention; case SILFunctionTypeRepresentation::Method: case SILFunctionTypeRepresentation::WitnessMethod: diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 711c5bd05e108..ed9c67dd2596a 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -3297,7 +3297,7 @@ llvm::Constant *swift::irgen::emitCXXConstructorThunkIfNeeded( llvm::Function *thunk = llvm::Function::Create( assumedFnType, llvm::Function::PrivateLinkage, name, &IGM.Module); - thunk->setCallingConv(llvm::CallingConv::C); + thunk->setCallingConv(IGM.getOptions().PlatformCCallingConvention); llvm::AttrBuilder attrBuilder(IGM.getLLVMContext()); IGM.constructInitialFnAttributes(attrBuilder); diff --git a/lib/IRGen/GenHeap.cpp b/lib/IRGen/GenHeap.cpp index fd6b761dd9e2c..b9657b1955eab 100644 --- a/lib/IRGen/GenHeap.cpp +++ b/lib/IRGen/GenHeap.cpp @@ -1978,7 +1978,7 @@ emitHeapMetadataRefForUnknownHeapObject(IRGenFunction &IGF, auto metadata = IGF.Builder.CreateCall( IGF.IGM.getGetObjectClassFunctionPointer(), object); metadata->setName(object->getName() + ".Type"); - metadata->setCallingConv(llvm::CallingConv::C); + metadata->setCallingConv(IGF.IGM.getOptions().PlatformCCallingConvention); metadata->setDoesNotThrow(); metadata->addFnAttr(llvm::Attribute::ReadOnly); return metadata; diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index 970a555997210..1e01dfdcbb021 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -570,7 +570,7 @@ IRGenModule::IRGenModule(IRGenerator &irgen, InvariantNode = llvm::MDNode::get(getLLVMContext(), {}); DereferenceableID = getLLVMContext().getMDKindID("dereferenceable"); - C_CC = llvm::CallingConv::C; + C_CC = getOptions().PlatformCCallingConvention; // TODO: use "tinycc" on platforms that support it DefaultCC = SWIFT_DEFAULT_LLVM_CC; SwiftCC = llvm::CallingConv::Swift;