diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td index e24b4c928b421..03ac9f5926f87 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -1254,11 +1254,12 @@ def __gnu_h2f_ieee : RuntimeLibcallImpl; //===----------------------------------------------------------------------===// // Several of the runtime library functions use a special calling conv -def __divmodqi4 : RuntimeLibcallImpl; // CallingConv::AVR_BUILTIN -def __divmodhi4 : RuntimeLibcallImpl; // CallingConv::AVR_BUILTIN +def __divmodqi4 : RuntimeLibcallImpl; +def __divmodhi4 : RuntimeLibcallImpl; +def __udivmodqi4 : RuntimeLibcallImpl; +def __udivmodhi4 : RuntimeLibcallImpl; + //def __divmodsi4 : RuntimeLibcallImpl; -def __udivmodqi4 : RuntimeLibcallImpl; // CallingConv::AVR_BUILTIN -def __udivmodhi4 : RuntimeLibcallImpl; // CallingConv::AVR_BUILTIN //def __udivmodsi4 : RuntimeLibcallImpl; // Standard sinf/cosf name replaced with "sin" and "cos". Define a @@ -1284,9 +1285,12 @@ def AVRSystemLibrary // Standard f64 names are replaced sin, cos, sinf, cosf), - __divmodqi4, __divmodhi4, __divmodsi4, __udivmodqi4, __udivmodhi4, - __udivmodsi4, - + // Several of the runtime library functions use a special calling + // conv + LibcallsWithCC<(add __divmodqi4, __divmodhi4, __udivmodqi4, + __udivmodhi4), + AVR_BUILTIN>, + __divmodsi4, __udivmodsi4, // Trigonometric rtlib functions avr_sin, avr_cos)>; @@ -1509,6 +1513,117 @@ def __mspabi_mpyll : RuntimeLibcallImpl; // setLibcallCallingConv(MUL_I64, CallingConv::MSP430_BUILTIN); +def isMSP430 : RuntimeLibcallPredicate<"TT.getArch() == Triple::msp430">; + +defvar MSP430DefaultOptOut = [ + __addsf3, __divsf3, __extendsfdf2, __truncdfsf2, __fixsfsi, + __fixsfdi, __fixunssfsi, __mulsf3, __eqsf2, __gesf2, __gtsf2, + __divhi3, __divsi3, __ashlsi3, __floatsidf, __floatsisf, + __ashrsi3, __modhi3, __udivsi3, __fixdfsi, __fixunssfdi, + __udivhi3, __umodsi3, __nesf2, __lesf2, __floatundisf, + __fixdfdi, __fixunsdfsi, __modsi3, __floatunsisf, + __fixunsdfdi, __ltsf2, __floatdisf, __floatdidf, + __lshrsi3, __subsf3, __umodhi3, __floatunsidf, + __floatundidf +]; + +// EABI Libcalls - EABI Section 6.2 +def MSP430SystemLibrary + : SystemRuntimeLibrary, + __mspabi_cmpf__oeq, + __mspabi_cmpf__une, + __mspabi_cmpf__oge, + __mspabi_cmpf__olt, + __mspabi_cmpf__ole, + __mspabi_cmpf__ogt, + + // Floating point arithmetic - EABI Table 8 + LibcallsWithCC<(add __mspabi_addd, + __mspabi_subd, + __mspabi_mpyd, + __mspabi_divd), MSP430_BUILTIN>, + + __mspabi_addf, + __mspabi_subf, + __mspabi_mpyf, + __mspabi_divf, + + // The following are NOT implemented in libgcc + // __mspabi_negd, + // __mspabi_negf, + + // Universal Integer Operations - EABI Table 9 + __mspabi_divi, + __mspabi_divli, + LibcallsWithCC<(add __mspabi_divlli), MSP430_BUILTIN>, + __mspabi_divu, + __mspabi_divul, + LibcallsWithCC<(add __mspabi_divull), MSP430_BUILTIN>, + __mspabi_remi, + __mspabi_remli, + LibcallsWithCC<(add __mspabi_remlli), MSP430_BUILTIN>, + __mspabi_remu, + __mspabi_remul, + LibcallsWithCC<(add __mspabi_remull), MSP430_BUILTIN>, + + // Bitwise Operations - EABI Table 10 + // TODO: __mspabi_[srli/srai/slli] ARE implemented in libgcc + __mspabi_srll, + __mspabi_sral, + __mspabi_slll + // __mspabi_[srlll/srall/sllll/rlli/rlll] are NOT implemented in libgcc + ) +>; + //===----------------------------------------------------------------------===// // NVPTX Runtime Libcalls //===----------------------------------------------------------------------===// @@ -1655,11 +1770,12 @@ def _Q_ulltoq : RuntimeLibcallImpl; //===----------------------------------------------------------------------===// // TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment() -def _alldiv : RuntimeLibcallImpl; // CallingConv::X86_StdCall -def _aulldiv : RuntimeLibcallImpl; // CallingConv::X86_StdCall -def _allrem : RuntimeLibcallImpl; // CallingConv::X86_StdCall -def _aullrem : RuntimeLibcallImpl; // CallingConv::X86_StdCall -def _allmul : RuntimeLibcallImpl; // CallingConv::X86_StdCall + +def _alldiv : RuntimeLibcallImpl; +def _aulldiv : RuntimeLibcallImpl; +def _allrem : RuntimeLibcallImpl; +def _aullrem : RuntimeLibcallImpl; +def _allmul : RuntimeLibcallImpl; //===----------------------------------------------------------------------===// // XCore Runtime Libcalls diff --git a/llvm/include/llvm/IR/RuntimeLibcallsImpl.td b/llvm/include/llvm/IR/RuntimeLibcallsImpl.td index d64e0d0adfa75..00c2575b14a6e 100644 --- a/llvm/include/llvm/IR/RuntimeLibcallsImpl.td +++ b/llvm/include/llvm/IR/RuntimeLibcallsImpl.td @@ -23,6 +23,19 @@ class LibcallLoweringPredicate { code Cond = cond; } def AlwaysAvailable : RuntimeLibcallPredicate<[{}]>; +class LibcallCallingConv { + // Enum value for the calling convention. Empty string defaults to + // CallingConv::C. + code CallingConv = CC; +} + +def DefaultCC : LibcallCallingConv; +def MSP430_BUILTIN : LibcallCallingConv<[{CallingConv::MSP430_BUILTIN}]>; +def ARM_AAPCS : LibcallCallingConv<[{CallingConv::ARM_AAPCS}]>; +def ARM_AAPCS_VFP : LibcallCallingConv<[{CallingConv::ARM_AAPCS_VFP}]>; +def X86_STDCALL : LibcallCallingConv<[{CallingConv::X86_StdCall}]>; +def AVR_BUILTIN : LibcallCallingConv<[{CallingConv::AVR_BUILTIN}]>; + /// Abstract definition for functionality the compiler may need to /// emit a call to. Emits the RTLIB::Libcall enum - This enum defines /// all of the runtime library calls the backend can emit. The various @@ -41,7 +54,6 @@ class RuntimeLibcall { // Concrete implementation of a libcall, which may have a different // name and only be valid on some subset of targets. -// TODO: Do we need a way to conditionally select calling convention? class RuntimeLibcallImpl { RuntimeLibcall Provides = P; string LibCallFuncName = Name; @@ -54,6 +66,10 @@ class LibcallImpls : LibcallImpls<(add Impl), Pred>; +class LibcallsWithCC + : LibcallImpls { + LibcallCallingConv CallingConv = CC; +} + /// Define a complete top level set of runtime libcalls for a target. class SystemRuntimeLibrary { + /// Set the default calling convention assumed for RuntimeLibcallImpl members. + LibcallCallingConv DefaultLibcallCallingConv = DefaultCC; RuntimeLibcallPredicate TriplePred = Pred; LibcallImpls MemberList = LibcallImpls; } diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp index 9492aef16e638..1e2ae4a6c69ef 100644 --- a/llvm/lib/IR/RuntimeLibcalls.cpp +++ b/llvm/lib/IR/RuntimeLibcalls.cpp @@ -100,137 +100,6 @@ static void setARMLibcallNames(RuntimeLibcallsInfo &Info, const Triple &TT, } } -static void setMSP430Libcalls(RuntimeLibcallsInfo &Info, const Triple &TT) { - // EABI Libcalls - EABI Section 6.2 - const struct { - const RTLIB::Libcall Op; - const RTLIB::LibcallImpl Impl; - } LibraryCalls[] = { - // Floating point conversions - EABI Table 6 - {RTLIB::FPROUND_F64_F32, RTLIB::__mspabi_cvtdf}, - {RTLIB::FPEXT_F32_F64, RTLIB::__mspabi_cvtfd}, - // The following is NOT implemented in libgcc - //{ RTLIB::FPTOSINT_F64_I16, RTLIB::__mspabi_fixdi }, - {RTLIB::FPTOSINT_F64_I32, RTLIB::__mspabi_fixdli}, - {RTLIB::FPTOSINT_F64_I64, RTLIB::__mspabi_fixdlli}, - // The following is NOT implemented in libgcc - //{ RTLIB::FPTOUINT_F64_I16, RTLIB::__mspabi_fixdu }, - {RTLIB::FPTOUINT_F64_I32, RTLIB::__mspabi_fixdul}, - {RTLIB::FPTOUINT_F64_I64, RTLIB::__mspabi_fixdull}, - // The following is NOT implemented in libgcc - //{ RTLIB::FPTOSINT_F32_I16, RTLIB::__mspabi_fixfi }, - {RTLIB::FPTOSINT_F32_I32, RTLIB::__mspabi_fixfli}, - {RTLIB::FPTOSINT_F32_I64, RTLIB::__mspabi_fixflli}, - // The following is NOT implemented in libgcc - //{ RTLIB::FPTOUINT_F32_I16, RTLIB::__mspabi_fixfu }, - {RTLIB::FPTOUINT_F32_I32, RTLIB::__mspabi_fixful}, - {RTLIB::FPTOUINT_F32_I64, RTLIB::__mspabi_fixfull}, - // TODO The following IS implemented in libgcc - //{ RTLIB::SINTTOFP_I16_F64, RTLIB::__mspabi_fltid }, - {RTLIB::SINTTOFP_I32_F64, RTLIB::__mspabi_fltlid}, - // TODO The following IS implemented in libgcc but is not in the EABI - {RTLIB::SINTTOFP_I64_F64, RTLIB::__mspabi_fltllid}, - // TODO The following IS implemented in libgcc - //{ RTLIB::UINTTOFP_I16_F64, RTLIB::__mspabi_fltud }, - {RTLIB::UINTTOFP_I32_F64, RTLIB::__mspabi_fltuld}, - // The following IS implemented in libgcc but is not in the EABI - {RTLIB::UINTTOFP_I64_F64, RTLIB::__mspabi_fltulld}, - // TODO The following IS implemented in libgcc - //{ RTLIB::SINTTOFP_I16_F32, RTLIB::__mspabi_fltif }, - {RTLIB::SINTTOFP_I32_F32, RTLIB::__mspabi_fltlif}, - // TODO The following IS implemented in libgcc but is not in the EABI - {RTLIB::SINTTOFP_I64_F32, RTLIB::__mspabi_fltllif}, - // TODO The following IS implemented in libgcc - //{ RTLIB::UINTTOFP_I16_F32, RTLIB::__mspabi_fltuf }, - {RTLIB::UINTTOFP_I32_F32, RTLIB::__mspabi_fltulf}, - // The following IS implemented in libgcc but is not in the EABI - {RTLIB::UINTTOFP_I64_F32, RTLIB::__mspabi_fltullf}, - - // Floating point comparisons - EABI Table 7 - {RTLIB::OEQ_F64, RTLIB::__mspabi_cmpd__oeq}, - {RTLIB::UNE_F64, RTLIB::__mspabi_cmpd__une}, - {RTLIB::OGE_F64, RTLIB::__mspabi_cmpd__oge}, - {RTLIB::OLT_F64, RTLIB::__mspabi_cmpd__olt}, - {RTLIB::OLE_F64, RTLIB::__mspabi_cmpd__ole}, - {RTLIB::OGT_F64, RTLIB::__mspabi_cmpd__ogt}, - {RTLIB::OEQ_F32, RTLIB::__mspabi_cmpf__oeq}, - {RTLIB::UNE_F32, RTLIB::__mspabi_cmpf__une}, - {RTLIB::OGE_F32, RTLIB::__mspabi_cmpf__oge}, - {RTLIB::OLT_F32, RTLIB::__mspabi_cmpf__olt}, - {RTLIB::OLE_F32, RTLIB::__mspabi_cmpf__ole}, - {RTLIB::OGT_F32, RTLIB::__mspabi_cmpf__ogt}, - - // Floating point arithmetic - EABI Table 8 - {RTLIB::ADD_F64, RTLIB::__mspabi_addd}, - {RTLIB::ADD_F32, RTLIB::__mspabi_addf}, - {RTLIB::DIV_F64, RTLIB::__mspabi_divd}, - {RTLIB::DIV_F32, RTLIB::__mspabi_divf}, - {RTLIB::MUL_F64, RTLIB::__mspabi_mpyd}, - {RTLIB::MUL_F32, RTLIB::__mspabi_mpyf}, - {RTLIB::SUB_F64, RTLIB::__mspabi_subd}, - {RTLIB::SUB_F32, RTLIB::__mspabi_subf}, - // The following are NOT implemented in libgcc - // { RTLIB::NEG_F64, RTLIB::__mspabi_negd }, - // { RTLIB::NEG_F32, RTLIB::__mspabi_negf }, - - // Universal Integer Operations - EABI Table 9 - {RTLIB::SDIV_I16, RTLIB::__mspabi_divi}, - {RTLIB::SDIV_I32, RTLIB::__mspabi_divli}, - {RTLIB::SDIV_I64, RTLIB::__mspabi_divlli}, - {RTLIB::UDIV_I16, RTLIB::__mspabi_divu}, - {RTLIB::UDIV_I32, RTLIB::__mspabi_divul}, - {RTLIB::UDIV_I64, RTLIB::__mspabi_divull}, - {RTLIB::SREM_I16, RTLIB::__mspabi_remi}, - {RTLIB::SREM_I32, RTLIB::__mspabi_remli}, - {RTLIB::SREM_I64, RTLIB::__mspabi_remlli}, - {RTLIB::UREM_I16, RTLIB::__mspabi_remu}, - {RTLIB::UREM_I32, RTLIB::__mspabi_remul}, - {RTLIB::UREM_I64, RTLIB::__mspabi_remull}, - - // Bitwise Operations - EABI Table 10 - // TODO: __mspabi_[srli/srai/slli] ARE implemented in libgcc - {RTLIB::SRL_I32, RTLIB::__mspabi_srll}, - {RTLIB::SRA_I32, RTLIB::__mspabi_sral}, - {RTLIB::SHL_I32, RTLIB::__mspabi_slll}, - // __mspabi_[srlll/srall/sllll/rlli/rlll] are NOT implemented in libgcc - }; - - for (const auto &LC : LibraryCalls) - Info.setLibcallImpl(LC.Op, LC.Impl); - - // Several of the runtime library functions use a special calling conv - Info.setLibcallImplCallingConv(RTLIB::__mspabi_divull, - CallingConv::MSP430_BUILTIN); - Info.setLibcallImplCallingConv(RTLIB::__mspabi_remull, - CallingConv::MSP430_BUILTIN); - Info.setLibcallImplCallingConv(RTLIB::__mspabi_divlli, - CallingConv::MSP430_BUILTIN); - Info.setLibcallImplCallingConv(RTLIB::__mspabi_remlli, - CallingConv::MSP430_BUILTIN); - Info.setLibcallImplCallingConv(RTLIB::__mspabi_addd, - CallingConv::MSP430_BUILTIN); - Info.setLibcallImplCallingConv(RTLIB::__mspabi_subd, - CallingConv::MSP430_BUILTIN); - Info.setLibcallImplCallingConv(RTLIB::__mspabi_mpyd, - CallingConv::MSP430_BUILTIN); - Info.setLibcallImplCallingConv(RTLIB::__mspabi_divd, - CallingConv::MSP430_BUILTIN); - Info.setLibcallImplCallingConv(RTLIB::__mspabi_cmpd__oeq, - CallingConv::MSP430_BUILTIN); - Info.setLibcallImplCallingConv(RTLIB::__mspabi_cmpd__une, - CallingConv::MSP430_BUILTIN); - Info.setLibcallImplCallingConv(RTLIB::__mspabi_cmpd__oge, - CallingConv::MSP430_BUILTIN); - Info.setLibcallImplCallingConv(RTLIB::__mspabi_cmpd__olt, - CallingConv::MSP430_BUILTIN); - Info.setLibcallImplCallingConv(RTLIB::__mspabi_cmpd__ole, - CallingConv::MSP430_BUILTIN); - Info.setLibcallImplCallingConv(RTLIB::__mspabi_cmpd__ogt, - CallingConv::MSP430_BUILTIN); - - // TODO: __mspabi_srall, __mspabi_srlll, __mspabi_sllll -} - void RuntimeLibcallsInfo::initSoftFloatCmpLibcallPredicates() { SoftFloatCompareLibcallPredicates[RTLIB::OEQ_F32] = CmpInst::ICMP_EQ; SoftFloatCompareLibcallPredicates[RTLIB::OEQ_F64] = CmpInst::ICMP_EQ; @@ -473,13 +342,6 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT, if (TT.isARM() || TT.isThumb()) setARMLibcallNames(*this, TT, FloatABI, EABIVersion); - else if (TT.getArch() == Triple::ArchType::avr) { - // Several of the runtime library functions use a special calling conv - setLibcallImplCallingConv(RTLIB::__divmodqi4, CallingConv::AVR_BUILTIN); - setLibcallImplCallingConv(RTLIB::__divmodhi4, CallingConv::AVR_BUILTIN); - setLibcallImplCallingConv(RTLIB::__udivmodqi4, CallingConv::AVR_BUILTIN); - setLibcallImplCallingConv(RTLIB::__udivmodhi4, CallingConv::AVR_BUILTIN); - } if (!TT.isWasm()) { // These libcalls are only available in compiler-rt, not libgcc. @@ -535,7 +397,4 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT, RTLIB::HEXAGON_MEMCPY_LIKELY_ALIGNED_MIN32BYTES_MULT8BYTES, RTLIB::__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes); } - - if (TT.getArch() == Triple::ArchType::msp430) - setMSP430Libcalls(*this, TT); } diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td b/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td new file mode 100644 index 0000000000000..94c0caa2c2820 --- /dev/null +++ b/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td @@ -0,0 +1,85 @@ +// RUN: llvm-tblgen -gen-runtime-libcalls -I %p/../../include %s | FileCheck %s + +include "llvm/IR/RuntimeLibCallsImpl.td" + +def SDIVREM_I8 : RuntimeLibcall; +def UDIVREM_I16 : RuntimeLibcall; +def MALLOC : RuntimeLibcall; +def TARGET_OVERRIDE_CC : RuntimeLibcall; + +//let CallingConv = AVR_BUILTIN in { +def __divmodqi4 : RuntimeLibcallImpl; +def __udivmodhi4 : RuntimeLibcallImpl; +//} + +// Test a case where a target wants to set a different calling +// convention on a generic builtin +def __target_override_cc : RuntimeLibcallImpl; + +def malloc : RuntimeLibcallImpl; + +def isAVR : RuntimeLibcallPredicate<[{TT.getArch() == Triple::avr}]>; + +def isAVRHurd : RuntimeLibcallPredicate< + [{TT.getArch() == Triple::avr && TT.isOSHurd()}]>; + +def AVRLibrary : SystemRuntimeLibrary) +>; + +// Test with default calling convention +def AVRHurdLibrary : SystemRuntimeLibrary)> { + let DefaultLibcallCallingConv + = LibcallCallingConv<[{isFoo() ? CallingConv::Fast : CallingConv::GHC}]>; +} + +// CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setTargetRuntimeLibcallSets(const llvm::Triple &TT) { +// CHECK: if (TT.getArch() == Triple::avr && TT.isOSHurd()) { +// CHECK-NEXT: const CallingConv::ID DefaultCC = isFoo() ? CallingConv::Fast : CallingConv::GHC; +// CHECK-NEXT: for (CallingConv::ID &Entry : LibcallImplCallingConvs) { +// CHECK-NEXT: Entry = isFoo() ? CallingConv::Fast : CallingConv::GHC; +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = { +// CHECK-NEXT: {RTLIB::MALLOC, RTLIB::malloc}, // malloc +// CHECK-NEXT: }; +// CHECK-EMPTY: +// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls) { +// CHECK-NEXT: setLibcallImpl(Func, Impl); +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: static const LibcallImplPair LibraryCalls_AlwaysAvailable[] = { +// CHECK-NEXT: {RTLIB::SDIVREM_I8, RTLIB::__divmodqi4}, // __divmodqi4 +// CHECK-NEXT: {RTLIB::UDIVREM_I16, RTLIB::__udivmodhi4}, // __udivmodhi4 +// CHECK-NEXT: }; +// CHECK-EMPTY: +// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls_AlwaysAvailable) { +// CHECK-NEXT: setLibcallImpl(Func, Impl); +// CHECK-NEXT: setLibcallImplCallingConv(Impl, CallingConv::AVR_BUILTIN); +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: return; +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: if (TT.getArch() == Triple::avr) { +// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = { +// CHECK-NEXT: {RTLIB::MALLOC, RTLIB::malloc}, // malloc +// CHECK-NEXT: }; +// CHECK-EMPTY: +// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls) { +// CHECK-NEXT: setLibcallImpl(Func, Impl); +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: static const LibcallImplPair LibraryCalls_AlwaysAvailable[] = { +// CHECK-NEXT: {RTLIB::SDIVREM_I8, RTLIB::__divmodqi4}, // __divmodqi4 +// CHECK-NEXT: {RTLIB::UDIVREM_I16, RTLIB::__udivmodhi4}, // __udivmodhi4 +// CHECK-NEXT: }; +// CHECK-EMPTY: +// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls_AlwaysAvailable) { +// CHECK-NEXT: setLibcallImpl(Func, Impl); +// CHECK-NEXT: setLibcallImplCallingConv(Impl, CallingConv::AVR_BUILTIN); +// CHECK-NEXT: } +// CHECK-EMPTY: +// CHECK-NEXT: return; +// CHECK-NEXT: } diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter.td b/llvm/test/TableGen/RuntimeLibcallEmitter.td index d810ce3787703..02974233d04f9 100644 --- a/llvm/test/TableGen/RuntimeLibcallEmitter.td +++ b/llvm/test/TableGen/RuntimeLibcallEmitter.td @@ -162,25 +162,28 @@ def BlahLibrary : SystemRuntimeLibrarygetName(); + } }; class RuntimeLibcallEmitter; @@ -45,11 +50,14 @@ class RuntimeLibcallImpl; /// Used to apply predicates to nested sets of libcalls. struct LibcallPredicateExpander : SetTheory::Expander { const RuntimeLibcallEmitter &LibcallEmitter; - DenseMap> &Func2Preds; + DenseMap, const Record *>> &Func2Preds; LibcallPredicateExpander( const RuntimeLibcallEmitter &LibcallEmitter, - DenseMap> &Func2Preds) + DenseMap, const Record *>> + &Func2Preds) : LibcallEmitter(LibcallEmitter), Func2Preds(Func2Preds) {} void expand(SetTheory &ST, const Record *Def, @@ -109,6 +117,10 @@ class RuntimeLibcallImpl { return TheDef->getValueAsString("LibCallFuncName"); } + const Record *getCallingConv() const { + return TheDef->getValueAsOptionalDef("CallingConv"); + } + void emitQuotedLibcallFuncName(raw_ostream &OS) const { OS << '\"' << getLibcallFuncName() << '\"'; } @@ -134,6 +146,13 @@ class RuntimeLibcallImpl { emitEnumEntry(OS); OS << "}, // " << getLibcallFuncName() << '\n'; } + + void emitSetCallingConv(raw_ostream &OS) const {} +}; + +struct LibcallsWithCC { + std::vector LibcallImpls; + const Record *CallingConv = nullptr; }; class RuntimeLibcallEmitter { @@ -346,32 +365,66 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls( OS << indent(2); TopLevelPredicate.emitIf(OS); + + if (const Record *DefaultCCClass = + R->getValueAsDef("DefaultLibcallCallingConv")) { + StringRef DefaultCC = + DefaultCCClass->getValueAsString("CallingConv").trim(); + + if (!DefaultCC.empty()) { + OS << " const CallingConv::ID DefaultCC = " << DefaultCC << ";\n" + << " for (CallingConv::ID &Entry : LibcallImplCallingConvs) {\n" + " Entry = " + << DefaultCC + << ";\n" + " }\n\n"; + } + } + SetTheory Sets; - DenseMap> Func2Preds; + DenseMap, const Record *>> + Func2Preds; Sets.addExpander( "LibcallImpls", std::make_unique(*this, Func2Preds)); + // Sets.addFieldExpander("LibcallWithCC", "Libcall"); + // Sets.addFieldExpander("LibcallWithCC", "CallingConv"); const SetTheory::RecVec *Elements = Sets.expand(R->getValueAsDef("MemberList")); + // const SetTheory::RecVec *CallingConvElements = + // Sets.expand(R->getValueAsDef("CallingConvList")); + // const SetTheory::RecVec *CallingConvElements = + // Sets.expand(R); + +#if 0 + for (const Record *CCElt : *CallingConvElements) { + dbgs() << "CC Elt: "; + CCElt->dump(); + dbgs() << '\n'; + } +#endif + // Sort to get deterministic output SetVector PredicateSorter; PredicateSorter.insert(nullptr); // No predicate first. - DenseMap> - Pred2Funcs; + DenseMap Pred2Funcs; for (const Record *Elt : *Elements) { const RuntimeLibcallImpl *LibCallImpl = getRuntimeLibcallImpl(Elt); - auto It = Func2Preds.find(Elt); + auto It = Func2Preds.find(LibCallImpl); if (It == Func2Preds.end()) { - Pred2Funcs[nullptr].push_back(LibCallImpl); + Pred2Funcs[nullptr].LibcallImpls.push_back(LibCallImpl); + // Pred2Funcs[nullptr].CallingConv = continue; } - for (const Record *Pred : It->second) { - Pred2Funcs[Pred].push_back(LibCallImpl); + for (const Record *Pred : It->second.first) { + Pred2Funcs[Pred].LibcallImpls.push_back(LibCallImpl); + Pred2Funcs[Pred].CallingConv = It->second.second; PredicateSorter.insert(Pred); } } @@ -402,7 +455,9 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls( SubsetPredicate.emitIf(OS); } - std::vector &Funcs = It->second; + LibcallsWithCC &FuncsWithCC = It->second; + + std::vector &Funcs = FuncsWithCC.LibcallImpls; // Ensure we only emit a unique implementation per libcall in the // selection table. @@ -434,7 +489,9 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls( Funcs.erase(UniqueI, Funcs.end()); OS << indent(IndentDepth + 2) - << "static const LibcallImplPair LibraryCalls[] = {\n"; + << "static const LibcallImplPair LibraryCalls"; + SubsetPredicate.emitTableVariableNameSuffix(OS); + OS << "[] = {\n"; for (const RuntimeLibcallImpl *LibCallImpl : Funcs) { OS << indent(IndentDepth + 6); LibCallImpl->emitTableEntry(OS); @@ -442,9 +499,20 @@ void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls( OS << indent(IndentDepth + 2) << "};\n\n" << indent(IndentDepth + 2) - << "for (const auto [Func, Impl] : LibraryCalls) {\n" - << indent(IndentDepth + 2) << " setLibcallImpl(Func, Impl);\n" - << indent(IndentDepth + 2) << "}\n"; + << "for (const auto [Func, Impl] : LibraryCalls"; + SubsetPredicate.emitTableVariableNameSuffix(OS); + OS << ") {\n" + << indent(IndentDepth + 4) << "setLibcallImpl(Func, Impl);\n"; + + if (FuncsWithCC.CallingConv) { + StringRef CCEnum = + FuncsWithCC.CallingConv->getValueAsString("CallingConv"); + OS << indent(IndentDepth + 4) << "setLibcallImplCallingConv(Impl, " + << CCEnum << ");\n"; + } + + OS << indent(IndentDepth + 2) << "}\n"; + OS << '\n'; if (!SubsetPredicate.isAlwaysAvailable()) { OS << indent(IndentDepth); @@ -490,16 +558,23 @@ void LibcallPredicateExpander::expand(SetTheory &ST, const Record *Def, Elts.insert(TmpElts.begin(), TmpElts.end()); AvailabilityPredicate AP(Def->getValueAsDef("AvailabilityPredicate")); + const Record *CCClass = Def->getValueAsOptionalDef("CallingConv"); + + // This is assuming we aren't conditionally applying a calling convention to + // some subsets, and not another, but this doesn't appear to be used. - for (const Record *LibcallImpl : TmpElts) { - if (!AP.isAlwaysAvailable()) { - auto [It, Inserted] = Func2Preds.insert({LibcallImpl, {}}); + for (const Record *LibcallImplDef : TmpElts) { + const RuntimeLibcallImpl *LibcallImpl = + LibcallEmitter.getRuntimeLibcallImpl(LibcallImplDef); + if (!AP.isAlwaysAvailable() || CCClass) { + auto [It, Inserted] = Func2Preds.insert({LibcallImpl, {{}, CCClass}}); if (!Inserted) { PrintError( Def, "combining nested libcall set predicates currently unhandled"); } - It->second.push_back(AP.getDef()); + It->second.first.push_back(AP.getDef()); + It->second.second = CCClass; } } }