[llvm-branch-commits] [llvm] TableGen: Handle setting runtime libcall calling conventions (PR #144980)
Matt Arsenault via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Jun 19 19:50:43 PDT 2025
https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/144980
Allow associating a non-default CallingConv with a set of library
functions, and applying a default for a SystemLibrary.
I also wanted to be able to apply a default calling conv
to a RuntimeLibcallImpl, but that turned out to be annoying
so leave it for later.
>From f847af321a1fed66af72cd32e48aa3925d74805b Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Fri, 13 Jun 2025 15:54:41 +0900
Subject: [PATCH] TableGen: Handle setting runtime libcall calling conventions
Allow associating a non-default CallingConv with a set of library
functions, and applying a default for a SystemLibrary.
I also wanted to be able to apply a default calling conv
to a RuntimeLibcallImpl, but that turned out to be annoying
so leave it for later.
---
llvm/include/llvm/IR/RuntimeLibcalls.td | 140 +++++++++++++++--
llvm/include/llvm/IR/RuntimeLibcallsImpl.td | 26 +++-
llvm/lib/IR/RuntimeLibcalls.cpp | 141 ------------------
.../RuntimeLibcallEmitter-calling-conv.td | 85 +++++++++++
llvm/test/TableGen/RuntimeLibcallEmitter.td | 19 ++-
.../TableGen/Basic/RuntimeLibcallsEmitter.cpp | 111 +++++++++++---
6 files changed, 344 insertions(+), 178 deletions(-)
create mode 100644 llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td
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<FPEXT_F16_F32>;
//===----------------------------------------------------------------------===//
// Several of the runtime library functions use a special calling conv
-def __divmodqi4 : RuntimeLibcallImpl<SDIVREM_I8>; // CallingConv::AVR_BUILTIN
-def __divmodhi4 : RuntimeLibcallImpl<SDIVREM_I16>; // CallingConv::AVR_BUILTIN
+def __divmodqi4 : RuntimeLibcallImpl<SDIVREM_I8>;
+def __divmodhi4 : RuntimeLibcallImpl<SDIVREM_I16>;
+def __udivmodqi4 : RuntimeLibcallImpl<UDIVREM_I8>;
+def __udivmodhi4 : RuntimeLibcallImpl<UDIVREM_I16>;
+
//def __divmodsi4 : RuntimeLibcallImpl<SDIVREM_I32>;
-def __udivmodqi4 : RuntimeLibcallImpl<UDIVREM_I8>; // CallingConv::AVR_BUILTIN
-def __udivmodhi4 : RuntimeLibcallImpl<UDIVREM_I16>; // CallingConv::AVR_BUILTIN
//def __udivmodsi4 : RuntimeLibcallImpl<UDIVREM_I32>;
// 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<MUL_I64>;
// 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<isMSP430,
+ (add (sub DefaultRuntimeLibcallImpls, MSP430DefaultOptOut),
+
+ // Floating point conversions - EABI Table 6
+ __mspabi_cvtdf,
+ __mspabi_cvtfd,
+ // The following is NOT implemented in libgcc
+ //__mspabi_fixdi,
+ __mspabi_fixdli,
+ __mspabi_fixdlli,
+ // The following is NOT implemented in libgcc
+ // __mspabi_fixdu
+ __mspabi_fixdul,
+ __mspabi_fixdull,
+ // The following is NOT implemented in libgcc
+ //__mspabi_fixfi,
+ __mspabi_fixfli,
+ __mspabi_fixflli,
+ // The following is NOT implemented in libgcc
+ //__mspabi_fixfu,
+ __mspabi_fixful,
+ __mspabi_fixfull,
+ // TODO The following IS implemented in libgcc
+ //__mspabi_fltid
+ __mspabi_fltlid,
+ // TODO The following IS implemented in libgcc but is not in the EABI
+ __mspabi_fltllid,
+ // TODO The following IS implemented in libgcc
+ //__mspabi_fltud,
+ __mspabi_fltuld,
+ // The following IS implemented in libgcc but is not in the EABI
+ __mspabi_fltulld,
+ // TODO The following IS implemented in libgcc
+ //__mspabi_fltif,
+ __mspabi_fltlif,
+ // TODO The following IS implemented in libgcc but is not in the EABI
+ __mspabi_fltllif,
+ // TODO The following IS implemented in libgcc
+ //__mspabi_fltuf,
+ __mspabi_fltulf,
+ // The following IS implemented in libgcc but is not in the EABI
+ __mspabi_fltullf,
+
+ // Floating point comparisons - EABI Table 7
+ LibcallsWithCC<(add __mspabi_cmpd__oeq,
+ __mspabi_cmpd__une,
+ __mspabi_cmpd__oge,
+ __mspabi_cmpd__olt,
+ __mspabi_cmpd__ole,
+ __mspabi_cmpd__ogt), MSP430_BUILTIN>,
+ __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<UINTTOFP_I64_F128>;
//===----------------------------------------------------------------------===//
// TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment()
-def _alldiv : RuntimeLibcallImpl<SDIV_I64>; // CallingConv::X86_StdCall
-def _aulldiv : RuntimeLibcallImpl<UDIV_I64>; // CallingConv::X86_StdCall
-def _allrem : RuntimeLibcallImpl<SREM_I64>; // CallingConv::X86_StdCall
-def _aullrem : RuntimeLibcallImpl<UREM_I64>; // CallingConv::X86_StdCall
-def _allmul : RuntimeLibcallImpl<MUL_I64>; // CallingConv::X86_StdCall
+
+def _alldiv : RuntimeLibcallImpl<SDIV_I64>;
+def _aulldiv : RuntimeLibcallImpl<UDIV_I64>;
+def _allrem : RuntimeLibcallImpl<SREM_I64>;
+def _aullrem : RuntimeLibcallImpl<UREM_I64>;
+def _allmul : RuntimeLibcallImpl<MUL_I64>;
//===----------------------------------------------------------------------===//
// 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> { code Cond = cond; }
def AlwaysAvailable : RuntimeLibcallPredicate<[{}]>;
+class LibcallCallingConv<code CC = [{}]> {
+ // 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 P, string Name = NAME> {
RuntimeLibcall Provides = P;
string LibCallFuncName = Name;
@@ -54,6 +66,10 @@ class LibcallImpls<dag funcList,
// Function of the triple where this applies
RuntimeLibcallPredicate AvailabilityPredicate = Pred;
dag MemberList = funcList;
+
+ // If set, applies calling convention to every entry instead of
+ // taking the system default.
+ LibcallCallingConv CallingConv = ?;
}
/// Convenience wrapper around LibcallImplSet to make a single libcall
@@ -61,8 +77,16 @@ class LibcallImpls<dag funcList,
class AvailableIf<RuntimeLibcallImpl Impl, RuntimeLibcallPredicate Pred>
: LibcallImpls<(add Impl), Pred>;
+class LibcallsWithCC<dag funcList, LibcallCallingConv CC,
+ RuntimeLibcallPredicate Pred = AlwaysAvailable>
+ : LibcallImpls<funcList, Pred> {
+ LibcallCallingConv CallingConv = CC;
+}
+
/// Define a complete top level set of runtime libcalls for a target.
class SystemRuntimeLibrary<RuntimeLibcallPredicate Pred, dag funcList> {
+ /// Set the default calling convention assumed for RuntimeLibcallImpl members.
+ LibcallCallingConv DefaultLibcallCallingConv = DefaultCC;
RuntimeLibcallPredicate TriplePred = Pred;
LibcallImpls MemberList = LibcallImpls<funcList>;
}
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<SDIVREM_I8>;
+def __udivmodhi4 : RuntimeLibcallImpl<UDIVREM_I16>;
+//}
+
+// Test a case where a target wants to set a different calling
+// convention on a generic builtin
+def __target_override_cc : RuntimeLibcallImpl<TARGET_OVERRIDE_CC>;
+
+def malloc : RuntimeLibcallImpl<MALLOC>;
+
+def isAVR : RuntimeLibcallPredicate<[{TT.getArch() == Triple::avr}]>;
+
+def isAVRHurd : RuntimeLibcallPredicate<
+ [{TT.getArch() == Triple::avr && TT.isOSHurd()}]>;
+
+def AVRLibrary : SystemRuntimeLibrary<isAVR,
+ (add malloc, LibcallsWithCC<(add __divmodqi4, __udivmodhi4), AVR_BUILTIN>)
+>;
+
+// Test with default calling convention
+def AVRHurdLibrary : SystemRuntimeLibrary<isAVRHurd,
+ (add malloc, LibcallsWithCC<(add __divmodqi4, __udivmodhi4), AVR_BUILTIN>)> {
+ 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 : SystemRuntimeLibrary<isBlahArch, (add calloc, LibraryWithCondi
// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls) {
// CHECK-NEXT: setLibcallImpl(Func, Impl);
// CHECK-NEXT: }
+// CHECK-EMPTY:
// CHECK-NEXT: if (TT.hasCompilerRT()) {
-// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
+// CHECK-NEXT: static const LibcallImplPair LibraryCalls_hasCompilerRT[] = {
// CHECK-NEXT: {RTLIB::SHL_I32, RTLIB::__ashlsi3}, // __ashlsi3
// CHECK-NEXT: {RTLIB::SRL_I64, RTLIB::__lshrdi3}, // __lshrdi3
// CHECK-NEXT: };
// CHECK-EMPTY:
-// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls) {
+// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls_hasCompilerRT) {
// CHECK-NEXT: setLibcallImpl(Func, Impl);
// CHECK-NEXT: }
+// CHECK-EMPTY:
// CHECK-NEXT: }
// CHECK-EMPTY:
// CHECK-NEXT: if (TT.getOS() == Triple::bar) {
-// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
+// CHECK-NEXT: static const LibcallImplPair LibraryCalls_isBarOS[] = {
// CHECK-NEXT: {RTLIB::MEMSET, RTLIB::___memset}, // ___memset
// CHECK-NEXT: };
// CHECK-EMPTY:
-// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls) {
+// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls_isBarOS) {
// CHECK-NEXT: setLibcallImpl(Func, Impl);
// CHECK-NEXT: }
+// CHECK-EMPTY:
// CHECK-NEXT: }
// CHECK-EMPTY:
// CHECK-NEXT: return;
@@ -196,6 +199,7 @@ def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add calloc, LibraryWithCondi
// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls) {
// CHECK-NEXT: setLibcallImpl(Func, Impl);
// CHECK-NEXT: }
+// CHECK-EMPTY:
// CHECK-NEXT: return;
// CHECK-NEXT: }
// CHECK-EMPTY:
@@ -208,14 +212,16 @@ def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add calloc, LibraryWithCondi
// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls) {
// CHECK-NEXT: setLibcallImpl(Func, Impl);
// CHECK-NEXT: }
+// CHECK-EMPTY:
// CHECK-NEXT: if (TT.getOS() == Triple::bar) {
-// CHECK-NEXT: static const LibcallImplPair LibraryCalls[] = {
+// CHECK-NEXT: static const LibcallImplPair LibraryCalls_isBarOS[] = {
// CHECK-NEXT: {RTLIB::MEMSET, RTLIB::___memset}, // ___memset
// CHECK-NEXT: };
// CHECK-EMPTY:
-// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls) {
+// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls_isBarOS) {
// CHECK-NEXT: setLibcallImpl(Func, Impl);
// CHECK-NEXT: }
+// CHECK-EMPTY:
// CHECK-NEXT: }
// CHECK-EMPTY:
// CHECK-NEXT: return;
@@ -232,6 +238,7 @@ def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add calloc, LibraryWithCondi
// CHECK-NEXT: for (const auto [Func, Impl] : LibraryCalls) {
// CHECK-NEXT: setLibcallImpl(Func, Impl);
// CHECK-NEXT: }
+// CHECK-EMPTY:
// CHECK-NEXT: return;
// CHECK-NEXT: }
// CHECK-NEXT: initDefaultLibCallImpls();
diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
index 30fcca47a4706..6d3d117737f37 100644
--- a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
@@ -37,6 +37,11 @@ class AvailabilityPredicate {
}
void emitEndIf(raw_ostream &OS) const { OS << "}\n"; }
+
+ void emitTableVariableNameSuffix(raw_ostream &OS) const {
+ if (TheDef)
+ OS << '_' << TheDef->getName();
+ }
};
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<const Record *, std::vector<const Record *>> &Func2Preds;
+ DenseMap<const RuntimeLibcallImpl *,
+ std::pair<std::vector<const Record *>, const Record *>> &Func2Preds;
LibcallPredicateExpander(
const RuntimeLibcallEmitter &LibcallEmitter,
- DenseMap<const Record *, std::vector<const Record *>> &Func2Preds)
+ DenseMap<const RuntimeLibcallImpl *,
+ std::pair<std::vector<const Record *>, 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<const RuntimeLibcallImpl *> 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<const Record *, std::vector<const Record *>> Func2Preds;
+ DenseMap<const RuntimeLibcallImpl *,
+ std::pair<std::vector<const Record *>, const Record *>>
+ Func2Preds;
Sets.addExpander(
"LibcallImpls",
std::make_unique<LibcallPredicateExpander>(*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<const Record *> PredicateSorter;
PredicateSorter.insert(nullptr); // No predicate first.
- DenseMap<const Record *, std::vector<const RuntimeLibcallImpl *>>
- Pred2Funcs;
+ DenseMap<const Record *, LibcallsWithCC> 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<const RuntimeLibcallImpl *> &Funcs = It->second;
+ LibcallsWithCC &FuncsWithCC = It->second;
+
+ std::vector<const RuntimeLibcallImpl *> &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;
}
}
}
More information about the llvm-branch-commits
mailing list