1//===- RuntimeLibcalls.cpp - Interface for runtime libcalls -----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/IR/RuntimeLibcalls.h"
10#include "llvm/Support/CommandLine.h"
11
12using namespace llvm;
13using namespace RTLIB;
14
15#define GET_INIT_RUNTIME_LIBCALL_UTILS
16#define GET_INIT_RUNTIME_LIBCALL_NAMES
17#include "llvm/IR/RuntimeLibcalls.inc"
18#undef GET_INIT_RUNTIME_LIBCALL_UTILS
19#undef GET_INIT_RUNTIME_LIBCALL_NAMES
20
21static cl::opt<bool>
22 HexagonEnableFastMathRuntimeCalls("hexagon-fast-math", cl::Hidden,
23 cl::desc("Enable Fast Math processing"));
24
25static void setAArch64LibcallNames(RuntimeLibcallsInfo &Info,
26 const Triple &TT) {
27#define LCALLNAMES(A, B, N) \
28 Info.setLibcallImpl(A##N##_RELAX, B##N##_relax); \
29 Info.setLibcallImpl(A##N##_ACQ, B##N##_acq); \
30 Info.setLibcallImpl(A##N##_REL, B##N##_rel); \
31 Info.setLibcallImpl(A##N##_ACQ_REL, B##N##_acq_rel);
32#define LCALLNAME4(A, B) \
33 LCALLNAMES(A, B, 1) \
34 LCALLNAMES(A, B, 2) LCALLNAMES(A, B, 4) LCALLNAMES(A, B, 8)
35#define LCALLNAME5(A, B) \
36 LCALLNAMES(A, B, 1) \
37 LCALLNAMES(A, B, 2) \
38 LCALLNAMES(A, B, 4) LCALLNAMES(A, B, 8) LCALLNAMES(A, B, 16)
39
40 if (TT.isWindowsArm64EC()) {
41 LCALLNAME5(RTLIB::OUTLINE_ATOMIC_CAS, RTLIB::arm64ec___aarch64_cas)
42 LCALLNAME4(RTLIB::OUTLINE_ATOMIC_SWP, RTLIB::arm64ec___aarch64_swp)
43 LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDADD, RTLIB::arm64ec___aarch64_ldadd)
44 LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDSET, RTLIB::arm64ec___aarch64_ldset)
45 LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDCLR, RTLIB::arm64ec___aarch64_ldclr)
46 LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDEOR, RTLIB::arm64ec___aarch64_ldeor)
47 } else {
48 LCALLNAME5(RTLIB::OUTLINE_ATOMIC_CAS, RTLIB::__aarch64_cas)
49 LCALLNAME4(RTLIB::OUTLINE_ATOMIC_SWP, RTLIB::__aarch64_swp)
50 LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDADD, RTLIB::__aarch64_ldadd)
51 LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDSET, RTLIB::__aarch64_ldset)
52 LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDCLR, RTLIB::__aarch64_ldclr)
53 LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDEOR, RTLIB::__aarch64_ldeor)
54 }
55#undef LCALLNAMES
56#undef LCALLNAME4
57#undef LCALLNAME5
58}
59
60static void setARMLibcallNames(RuntimeLibcallsInfo &Info, const Triple &TT,
61 FloatABI::ABIType FloatABIType,
62 EABI EABIVersion) {
63 if (!TT.isOSDarwin() && !TT.isiOS() && !TT.isWatchOS() && !TT.isDriverKit()) {
64 CallingConv::ID DefaultCC = FloatABIType == FloatABI::Hard
65 ? CallingConv::ARM_AAPCS_VFP
66 : CallingConv::ARM_AAPCS;
67 for (RTLIB::Libcall LC : RTLIB::libcalls())
68 Info.setLibcallCallingConv(Call: LC, CC: DefaultCC);
69 }
70
71 // Register based DivRem for AEABI (RTABI 4.2)
72 if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
73 TT.isTargetMuslAEABI() || TT.isOSWindows()) {
74 if (TT.isOSWindows()) {
75 const struct {
76 const RTLIB::Libcall Op;
77 const RTLIB::LibcallImpl Impl;
78 const CallingConv::ID CC;
79 } LibraryCalls[] = {
80 {.Op: RTLIB::SDIVREM_I32, .Impl: RTLIB::__rt_sdiv, .CC: CallingConv::ARM_AAPCS},
81 {.Op: RTLIB::SDIVREM_I64, .Impl: RTLIB::__rt_sdiv64, .CC: CallingConv::ARM_AAPCS},
82 {.Op: RTLIB::UDIVREM_I32, .Impl: RTLIB::__rt_udiv, .CC: CallingConv::ARM_AAPCS},
83 {.Op: RTLIB::UDIVREM_I64, .Impl: RTLIB::__rt_udiv64, .CC: CallingConv::ARM_AAPCS},
84 };
85
86 for (const auto &LC : LibraryCalls) {
87 Info.setLibcallImpl(Call: LC.Op, Impl: LC.Impl);
88 Info.setLibcallCallingConv(Call: LC.Op, CC: LC.CC);
89 }
90 } else {
91 const struct {
92 const RTLIB::Libcall Op;
93 const RTLIB::LibcallImpl Impl;
94 const CallingConv::ID CC;
95 } LibraryCalls[] = {
96 {.Op: RTLIB::SDIVREM_I32, .Impl: RTLIB::__aeabi_idivmod, .CC: CallingConv::ARM_AAPCS},
97 {.Op: RTLIB::SDIVREM_I64, .Impl: RTLIB::__aeabi_ldivmod, .CC: CallingConv::ARM_AAPCS},
98 {.Op: RTLIB::UDIVREM_I32, .Impl: RTLIB::__aeabi_uidivmod, .CC: CallingConv::ARM_AAPCS},
99 {.Op: RTLIB::UDIVREM_I64, .Impl: RTLIB::__aeabi_uldivmod, .CC: CallingConv::ARM_AAPCS},
100 };
101
102 for (const auto &LC : LibraryCalls) {
103 Info.setLibcallImpl(Call: LC.Op, Impl: LC.Impl);
104 Info.setLibcallCallingConv(Call: LC.Op, CC: LC.CC);
105 }
106 }
107 }
108
109 if (TT.isOSWindows()) {
110 static const struct {
111 const RTLIB::Libcall Op;
112 const RTLIB::LibcallImpl Impl;
113 const CallingConv::ID CC;
114 } LibraryCalls[] = {
115 {.Op: RTLIB::FPTOSINT_F32_I64, .Impl: RTLIB::__stoi64, .CC: CallingConv::ARM_AAPCS_VFP},
116 {.Op: RTLIB::FPTOSINT_F64_I64, .Impl: RTLIB::__dtoi64, .CC: CallingConv::ARM_AAPCS_VFP},
117 {.Op: RTLIB::FPTOUINT_F32_I64, .Impl: RTLIB::__stou64, .CC: CallingConv::ARM_AAPCS_VFP},
118 {.Op: RTLIB::FPTOUINT_F64_I64, .Impl: RTLIB::__dtou64, .CC: CallingConv::ARM_AAPCS_VFP},
119 {.Op: RTLIB::SINTTOFP_I64_F32, .Impl: RTLIB::__i64tos, .CC: CallingConv::ARM_AAPCS_VFP},
120 {.Op: RTLIB::SINTTOFP_I64_F64, .Impl: RTLIB::__i64tod, .CC: CallingConv::ARM_AAPCS_VFP},
121 {.Op: RTLIB::UINTTOFP_I64_F32, .Impl: RTLIB::__u64tos, .CC: CallingConv::ARM_AAPCS_VFP},
122 {.Op: RTLIB::UINTTOFP_I64_F64, .Impl: RTLIB::__u64tod, .CC: CallingConv::ARM_AAPCS_VFP},
123 };
124
125 for (const auto &LC : LibraryCalls) {
126 Info.setLibcallImpl(Call: LC.Op, Impl: LC.Impl);
127 Info.setLibcallCallingConv(Call: LC.Op, CC: LC.CC);
128 }
129 }
130
131 // Use divmod compiler-rt calls for iOS 5.0 and later.
132 if (TT.isOSBinFormatMachO() && (!TT.isiOS() || !TT.isOSVersionLT(Major: 5, Minor: 0))) {
133 Info.setLibcallImpl(Call: RTLIB::SDIVREM_I32, Impl: RTLIB::__divmodsi4);
134 Info.setLibcallImpl(Call: RTLIB::UDIVREM_I32, Impl: RTLIB::__udivmodsi4);
135 }
136}
137
138static void setMSP430Libcalls(RuntimeLibcallsInfo &Info, const Triple &TT) {
139 // EABI Libcalls - EABI Section 6.2
140 const struct {
141 const RTLIB::Libcall Op;
142 const RTLIB::LibcallImpl Impl;
143 } LibraryCalls[] = {
144 // Floating point conversions - EABI Table 6
145 {.Op: RTLIB::FPROUND_F64_F32, .Impl: RTLIB::__mspabi_cvtdf},
146 {.Op: RTLIB::FPEXT_F32_F64, .Impl: RTLIB::__mspabi_cvtfd},
147 // The following is NOT implemented in libgcc
148 //{ RTLIB::FPTOSINT_F64_I16, RTLIB::__mspabi_fixdi },
149 {.Op: RTLIB::FPTOSINT_F64_I32, .Impl: RTLIB::__mspabi_fixdli},
150 {.Op: RTLIB::FPTOSINT_F64_I64, .Impl: RTLIB::__mspabi_fixdlli},
151 // The following is NOT implemented in libgcc
152 //{ RTLIB::FPTOUINT_F64_I16, RTLIB::__mspabi_fixdu },
153 {.Op: RTLIB::FPTOUINT_F64_I32, .Impl: RTLIB::__mspabi_fixdul},
154 {.Op: RTLIB::FPTOUINT_F64_I64, .Impl: RTLIB::__mspabi_fixdull},
155 // The following is NOT implemented in libgcc
156 //{ RTLIB::FPTOSINT_F32_I16, RTLIB::__mspabi_fixfi },
157 {.Op: RTLIB::FPTOSINT_F32_I32, .Impl: RTLIB::__mspabi_fixfli},
158 {.Op: RTLIB::FPTOSINT_F32_I64, .Impl: RTLIB::__mspabi_fixflli},
159 // The following is NOT implemented in libgcc
160 //{ RTLIB::FPTOUINT_F32_I16, RTLIB::__mspabi_fixfu },
161 {.Op: RTLIB::FPTOUINT_F32_I32, .Impl: RTLIB::__mspabi_fixful},
162 {.Op: RTLIB::FPTOUINT_F32_I64, .Impl: RTLIB::__mspabi_fixfull},
163 // TODO The following IS implemented in libgcc
164 //{ RTLIB::SINTTOFP_I16_F64, RTLIB::__mspabi_fltid },
165 {.Op: RTLIB::SINTTOFP_I32_F64, .Impl: RTLIB::__mspabi_fltlid},
166 // TODO The following IS implemented in libgcc but is not in the EABI
167 {.Op: RTLIB::SINTTOFP_I64_F64, .Impl: RTLIB::__mspabi_fltllid},
168 // TODO The following IS implemented in libgcc
169 //{ RTLIB::UINTTOFP_I16_F64, RTLIB::__mspabi_fltud },
170 {.Op: RTLIB::UINTTOFP_I32_F64, .Impl: RTLIB::__mspabi_fltuld},
171 // The following IS implemented in libgcc but is not in the EABI
172 {.Op: RTLIB::UINTTOFP_I64_F64, .Impl: RTLIB::__mspabi_fltulld},
173 // TODO The following IS implemented in libgcc
174 //{ RTLIB::SINTTOFP_I16_F32, RTLIB::__mspabi_fltif },
175 {.Op: RTLIB::SINTTOFP_I32_F32, .Impl: RTLIB::__mspabi_fltlif},
176 // TODO The following IS implemented in libgcc but is not in the EABI
177 {.Op: RTLIB::SINTTOFP_I64_F32, .Impl: RTLIB::__mspabi_fltllif},
178 // TODO The following IS implemented in libgcc
179 //{ RTLIB::UINTTOFP_I16_F32, RTLIB::__mspabi_fltuf },
180 {.Op: RTLIB::UINTTOFP_I32_F32, .Impl: RTLIB::__mspabi_fltulf},
181 // The following IS implemented in libgcc but is not in the EABI
182 {.Op: RTLIB::UINTTOFP_I64_F32, .Impl: RTLIB::__mspabi_fltullf},
183
184 // Floating point comparisons - EABI Table 7
185 {.Op: RTLIB::OEQ_F64, .Impl: RTLIB::__mspabi_cmpd__oeq},
186 {.Op: RTLIB::UNE_F64, .Impl: RTLIB::__mspabi_cmpd__une},
187 {.Op: RTLIB::OGE_F64, .Impl: RTLIB::__mspabi_cmpd__oge},
188 {.Op: RTLIB::OLT_F64, .Impl: RTLIB::__mspabi_cmpd__olt},
189 {.Op: RTLIB::OLE_F64, .Impl: RTLIB::__mspabi_cmpd__ole},
190 {.Op: RTLIB::OGT_F64, .Impl: RTLIB::__mspabi_cmpd__ogt},
191 {.Op: RTLIB::OEQ_F32, .Impl: RTLIB::__mspabi_cmpf__oeq},
192 {.Op: RTLIB::UNE_F32, .Impl: RTLIB::__mspabi_cmpf__une},
193 {.Op: RTLIB::OGE_F32, .Impl: RTLIB::__mspabi_cmpf__oge},
194 {.Op: RTLIB::OLT_F32, .Impl: RTLIB::__mspabi_cmpf__olt},
195 {.Op: RTLIB::OLE_F32, .Impl: RTLIB::__mspabi_cmpf__ole},
196 {.Op: RTLIB::OGT_F32, .Impl: RTLIB::__mspabi_cmpf__ogt},
197
198 // Floating point arithmetic - EABI Table 8
199 {.Op: RTLIB::ADD_F64, .Impl: RTLIB::__mspabi_addd},
200 {.Op: RTLIB::ADD_F32, .Impl: RTLIB::__mspabi_addf},
201 {.Op: RTLIB::DIV_F64, .Impl: RTLIB::__mspabi_divd},
202 {.Op: RTLIB::DIV_F32, .Impl: RTLIB::__mspabi_divf},
203 {.Op: RTLIB::MUL_F64, .Impl: RTLIB::__mspabi_mpyd},
204 {.Op: RTLIB::MUL_F32, .Impl: RTLIB::__mspabi_mpyf},
205 {.Op: RTLIB::SUB_F64, .Impl: RTLIB::__mspabi_subd},
206 {.Op: RTLIB::SUB_F32, .Impl: RTLIB::__mspabi_subf},
207 // The following are NOT implemented in libgcc
208 // { RTLIB::NEG_F64, RTLIB::__mspabi_negd },
209 // { RTLIB::NEG_F32, RTLIB::__mspabi_negf },
210
211 // Universal Integer Operations - EABI Table 9
212 {.Op: RTLIB::SDIV_I16, .Impl: RTLIB::__mspabi_divi},
213 {.Op: RTLIB::SDIV_I32, .Impl: RTLIB::__mspabi_divli},
214 {.Op: RTLIB::SDIV_I64, .Impl: RTLIB::__mspabi_divlli},
215 {.Op: RTLIB::UDIV_I16, .Impl: RTLIB::__mspabi_divu},
216 {.Op: RTLIB::UDIV_I32, .Impl: RTLIB::__mspabi_divul},
217 {.Op: RTLIB::UDIV_I64, .Impl: RTLIB::__mspabi_divull},
218 {.Op: RTLIB::SREM_I16, .Impl: RTLIB::__mspabi_remi},
219 {.Op: RTLIB::SREM_I32, .Impl: RTLIB::__mspabi_remli},
220 {.Op: RTLIB::SREM_I64, .Impl: RTLIB::__mspabi_remlli},
221 {.Op: RTLIB::UREM_I16, .Impl: RTLIB::__mspabi_remu},
222 {.Op: RTLIB::UREM_I32, .Impl: RTLIB::__mspabi_remul},
223 {.Op: RTLIB::UREM_I64, .Impl: RTLIB::__mspabi_remull},
224
225 // Bitwise Operations - EABI Table 10
226 // TODO: __mspabi_[srli/srai/slli] ARE implemented in libgcc
227 {.Op: RTLIB::SRL_I32, .Impl: RTLIB::__mspabi_srll},
228 {.Op: RTLIB::SRA_I32, .Impl: RTLIB::__mspabi_sral},
229 {.Op: RTLIB::SHL_I32, .Impl: RTLIB::__mspabi_slll},
230 // __mspabi_[srlll/srall/sllll/rlli/rlll] are NOT implemented in libgcc
231 };
232
233 for (const auto &LC : LibraryCalls)
234 Info.setLibcallImpl(Call: LC.Op, Impl: LC.Impl);
235
236 // Several of the runtime library functions use a special calling conv
237 Info.setLibcallCallingConv(Call: RTLIB::UDIV_I64, CC: CallingConv::MSP430_BUILTIN);
238 Info.setLibcallCallingConv(Call: RTLIB::UREM_I64, CC: CallingConv::MSP430_BUILTIN);
239 Info.setLibcallCallingConv(Call: RTLIB::SDIV_I64, CC: CallingConv::MSP430_BUILTIN);
240 Info.setLibcallCallingConv(Call: RTLIB::SREM_I64, CC: CallingConv::MSP430_BUILTIN);
241 Info.setLibcallCallingConv(Call: RTLIB::ADD_F64, CC: CallingConv::MSP430_BUILTIN);
242 Info.setLibcallCallingConv(Call: RTLIB::SUB_F64, CC: CallingConv::MSP430_BUILTIN);
243 Info.setLibcallCallingConv(Call: RTLIB::MUL_F64, CC: CallingConv::MSP430_BUILTIN);
244 Info.setLibcallCallingConv(Call: RTLIB::DIV_F64, CC: CallingConv::MSP430_BUILTIN);
245 Info.setLibcallCallingConv(Call: RTLIB::OEQ_F64, CC: CallingConv::MSP430_BUILTIN);
246 Info.setLibcallCallingConv(Call: RTLIB::UNE_F64, CC: CallingConv::MSP430_BUILTIN);
247 Info.setLibcallCallingConv(Call: RTLIB::OGE_F64, CC: CallingConv::MSP430_BUILTIN);
248 Info.setLibcallCallingConv(Call: RTLIB::OLT_F64, CC: CallingConv::MSP430_BUILTIN);
249 Info.setLibcallCallingConv(Call: RTLIB::OLE_F64, CC: CallingConv::MSP430_BUILTIN);
250 Info.setLibcallCallingConv(Call: RTLIB::OGT_F64, CC: CallingConv::MSP430_BUILTIN);
251
252 // TODO: __mspabi_srall, __mspabi_srlll, __mspabi_sllll
253}
254
255void RuntimeLibcallsInfo::initSoftFloatCmpLibcallPredicates() {
256 SoftFloatCompareLibcallPredicates[RTLIB::OEQ_F32] = CmpInst::ICMP_EQ;
257 SoftFloatCompareLibcallPredicates[RTLIB::OEQ_F64] = CmpInst::ICMP_EQ;
258 SoftFloatCompareLibcallPredicates[RTLIB::OEQ_F128] = CmpInst::ICMP_EQ;
259 SoftFloatCompareLibcallPredicates[RTLIB::OEQ_PPCF128] = CmpInst::ICMP_EQ;
260 SoftFloatCompareLibcallPredicates[RTLIB::UNE_F32] = CmpInst::ICMP_NE;
261 SoftFloatCompareLibcallPredicates[RTLIB::UNE_F64] = CmpInst::ICMP_NE;
262 SoftFloatCompareLibcallPredicates[RTLIB::UNE_F128] = CmpInst::ICMP_NE;
263 SoftFloatCompareLibcallPredicates[RTLIB::UNE_PPCF128] = CmpInst::ICMP_NE;
264 SoftFloatCompareLibcallPredicates[RTLIB::OGE_F32] = CmpInst::ICMP_SGE;
265 SoftFloatCompareLibcallPredicates[RTLIB::OGE_F64] = CmpInst::ICMP_SGE;
266 SoftFloatCompareLibcallPredicates[RTLIB::OGE_F128] = CmpInst::ICMP_SGE;
267 SoftFloatCompareLibcallPredicates[RTLIB::OGE_PPCF128] = CmpInst::ICMP_SGE;
268 SoftFloatCompareLibcallPredicates[RTLIB::OLT_F32] = CmpInst::ICMP_SLT;
269 SoftFloatCompareLibcallPredicates[RTLIB::OLT_F64] = CmpInst::ICMP_SLT;
270 SoftFloatCompareLibcallPredicates[RTLIB::OLT_F128] = CmpInst::ICMP_SLT;
271 SoftFloatCompareLibcallPredicates[RTLIB::OLT_PPCF128] = CmpInst::ICMP_SLT;
272 SoftFloatCompareLibcallPredicates[RTLIB::OLE_F32] = CmpInst::ICMP_SLE;
273 SoftFloatCompareLibcallPredicates[RTLIB::OLE_F64] = CmpInst::ICMP_SLE;
274 SoftFloatCompareLibcallPredicates[RTLIB::OLE_F128] = CmpInst::ICMP_SLE;
275 SoftFloatCompareLibcallPredicates[RTLIB::OLE_PPCF128] = CmpInst::ICMP_SLE;
276 SoftFloatCompareLibcallPredicates[RTLIB::OGT_F32] = CmpInst::ICMP_SGT;
277 SoftFloatCompareLibcallPredicates[RTLIB::OGT_F64] = CmpInst::ICMP_SGT;
278 SoftFloatCompareLibcallPredicates[RTLIB::OGT_F128] = CmpInst::ICMP_SGT;
279 SoftFloatCompareLibcallPredicates[RTLIB::OGT_PPCF128] = CmpInst::ICMP_SGT;
280 SoftFloatCompareLibcallPredicates[RTLIB::UO_F32] = CmpInst::ICMP_NE;
281 SoftFloatCompareLibcallPredicates[RTLIB::UO_F64] = CmpInst::ICMP_NE;
282 SoftFloatCompareLibcallPredicates[RTLIB::UO_F128] = CmpInst::ICMP_NE;
283 SoftFloatCompareLibcallPredicates[RTLIB::UO_PPCF128] = CmpInst::ICMP_NE;
284}
285
286static void setLongDoubleIsF128Libm(RuntimeLibcallsInfo &Info,
287 bool FiniteOnlyFuncs = false) {
288 Info.setLibcallImpl(Call: RTLIB::REM_F128, Impl: RTLIB::fmodf128);
289 Info.setLibcallImpl(Call: RTLIB::FMA_F128, Impl: RTLIB::fmaf128);
290 Info.setLibcallImpl(Call: RTLIB::SQRT_F128, Impl: RTLIB::sqrtf128);
291 Info.setLibcallImpl(Call: RTLIB::CBRT_F128, Impl: RTLIB::cbrtf128);
292 Info.setLibcallImpl(Call: RTLIB::LOG_F128, Impl: RTLIB::logf128);
293 Info.setLibcallImpl(Call: RTLIB::LOG2_F128, Impl: RTLIB::log2f128);
294 Info.setLibcallImpl(Call: RTLIB::LOG10_F128, Impl: RTLIB::log10f128);
295 Info.setLibcallImpl(Call: RTLIB::EXP_F128, Impl: RTLIB::expf128);
296 Info.setLibcallImpl(Call: RTLIB::EXP2_F128, Impl: RTLIB::exp2f128);
297 Info.setLibcallImpl(Call: RTLIB::EXP10_F128, Impl: RTLIB::exp10f128);
298 Info.setLibcallImpl(Call: RTLIB::SIN_F128, Impl: RTLIB::sinf128);
299 Info.setLibcallImpl(Call: RTLIB::COS_F128, Impl: RTLIB::cosf128);
300 Info.setLibcallImpl(Call: RTLIB::TAN_F128, Impl: RTLIB::tanf128);
301 Info.setLibcallImpl(Call: RTLIB::SINCOS_F128, Impl: RTLIB::sincosf128);
302 Info.setLibcallImpl(Call: RTLIB::ASIN_F128, Impl: RTLIB::asinf128);
303 Info.setLibcallImpl(Call: RTLIB::ACOS_F128, Impl: RTLIB::acosf128);
304 Info.setLibcallImpl(Call: RTLIB::ATAN_F128, Impl: RTLIB::atanf128);
305 Info.setLibcallImpl(Call: RTLIB::ATAN2_F128, Impl: RTLIB::atan2f128);
306 Info.setLibcallImpl(Call: RTLIB::SINH_F128, Impl: RTLIB::sinhf128);
307 Info.setLibcallImpl(Call: RTLIB::COSH_F128, Impl: RTLIB::coshf128);
308 Info.setLibcallImpl(Call: RTLIB::TANH_F128, Impl: RTLIB::tanhf128);
309 Info.setLibcallImpl(Call: RTLIB::POW_F128, Impl: RTLIB::powf128);
310 Info.setLibcallImpl(Call: RTLIB::CEIL_F128, Impl: RTLIB::ceilf128);
311 Info.setLibcallImpl(Call: RTLIB::TRUNC_F128, Impl: RTLIB::truncf128);
312 Info.setLibcallImpl(Call: RTLIB::RINT_F128, Impl: RTLIB::rintf128);
313 Info.setLibcallImpl(Call: RTLIB::NEARBYINT_F128, Impl: RTLIB::nearbyintf128);
314 Info.setLibcallImpl(Call: RTLIB::ROUND_F128, Impl: RTLIB::roundf128);
315 Info.setLibcallImpl(Call: RTLIB::ROUNDEVEN_F128, Impl: RTLIB::roundevenf128);
316 Info.setLibcallImpl(Call: RTLIB::FLOOR_F128, Impl: RTLIB::floorf128);
317 Info.setLibcallImpl(Call: RTLIB::COPYSIGN_F128, Impl: RTLIB::copysignf128);
318 Info.setLibcallImpl(Call: RTLIB::FMIN_F128, Impl: RTLIB::fminf128);
319 Info.setLibcallImpl(Call: RTLIB::FMAX_F128, Impl: RTLIB::fmaxf128);
320 Info.setLibcallImpl(Call: RTLIB::FMINIMUM_F128, Impl: RTLIB::fminimumf128);
321 Info.setLibcallImpl(Call: RTLIB::FMAXIMUM_F128, Impl: RTLIB::fmaximumf128);
322 Info.setLibcallImpl(Call: RTLIB::FMINIMUM_NUM_F128, Impl: RTLIB::fminimum_numf128);
323 Info.setLibcallImpl(Call: RTLIB::FMAXIMUM_NUM_F128, Impl: RTLIB::fmaximum_numf128);
324 Info.setLibcallImpl(Call: RTLIB::LROUND_F128, Impl: RTLIB::lroundf128);
325 Info.setLibcallImpl(Call: RTLIB::LLROUND_F128, Impl: RTLIB::llroundf128);
326 Info.setLibcallImpl(Call: RTLIB::LRINT_F128, Impl: RTLIB::lrintf128);
327 Info.setLibcallImpl(Call: RTLIB::LLRINT_F128, Impl: RTLIB::llrintf128);
328 Info.setLibcallImpl(Call: RTLIB::LDEXP_F128, Impl: RTLIB::ldexpf128);
329 Info.setLibcallImpl(Call: RTLIB::FREXP_F128, Impl: RTLIB::frexpf128);
330 Info.setLibcallImpl(Call: RTLIB::MODF_F128, Impl: RTLIB::modff128);
331
332 if (FiniteOnlyFuncs) {
333 Info.setLibcallImpl(Call: RTLIB::LOG_FINITE_F128, Impl: RTLIB::__logf128_finite);
334 Info.setLibcallImpl(Call: RTLIB::LOG2_FINITE_F128, Impl: RTLIB::__log2f128_finite);
335 Info.setLibcallImpl(Call: RTLIB::LOG10_FINITE_F128, Impl: RTLIB::__log10f128_finite);
336 Info.setLibcallImpl(Call: RTLIB::EXP_FINITE_F128, Impl: RTLIB::__expf128_finite);
337 Info.setLibcallImpl(Call: RTLIB::EXP2_FINITE_F128, Impl: RTLIB::__exp2f128_finite);
338 Info.setLibcallImpl(Call: RTLIB::POW_FINITE_F128, Impl: RTLIB::__powf128_finite);
339 } else {
340 Info.setLibcallImpl(Call: RTLIB::LOG_FINITE_F128, Impl: RTLIB::Unsupported);
341 Info.setLibcallImpl(Call: RTLIB::LOG2_FINITE_F128, Impl: RTLIB::Unsupported);
342 Info.setLibcallImpl(Call: RTLIB::LOG10_FINITE_F128, Impl: RTLIB::Unsupported);
343 Info.setLibcallImpl(Call: RTLIB::EXP_FINITE_F128, Impl: RTLIB::Unsupported);
344 Info.setLibcallImpl(Call: RTLIB::EXP2_FINITE_F128, Impl: RTLIB::Unsupported);
345 Info.setLibcallImpl(Call: RTLIB::POW_FINITE_F128, Impl: RTLIB::Unsupported);
346 }
347}
348
349void RTLIB::RuntimeLibcallsInfo::initDefaultLibCallImpls() {
350 std::memcpy(dest: LibcallImpls, src: DefaultLibcallImpls, n: sizeof(LibcallImpls));
351 static_assert(sizeof(LibcallImpls) == sizeof(DefaultLibcallImpls),
352 "libcall array size should match");
353}
354
355/// Set default libcall names. If a target wants to opt-out of a libcall it
356/// should be placed here.
357void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
358 ExceptionHandling ExceptionModel,
359 FloatABI::ABIType FloatABI,
360 EABI EABIVersion, StringRef ABIName) {
361 // Use the f128 variants of math functions on x86
362 if (TT.isX86() && TT.isGNUEnvironment())
363 setLongDoubleIsF128Libm(Info&: *this, /*FiniteOnlyFuncs=*/true);
364
365 if (TT.isX86() || TT.isVE()) {
366 if (ExceptionModel == ExceptionHandling::SjLj)
367 setLibcallImpl(Call: RTLIB::UNWIND_RESUME, Impl: RTLIB::_Unwind_SjLj_Resume);
368 }
369
370 if (TT.isPPC()) {
371 setPPCLibCallNameOverrides();
372
373 // TODO: Do the finite only functions exist?
374 setLongDoubleIsF128Libm(Info&: *this, /*FiniteOnlyFuncs=*/false);
375
376 // TODO: Tablegen predicate support
377 if (TT.isOSAIX()) {
378 if (TT.isPPC64()) {
379 setLibcallImpl(Call: RTLIB::MEMCPY, Impl: RTLIB::Unsupported);
380 setLibcallImpl(Call: RTLIB::MEMMOVE, Impl: RTLIB::___memmove64);
381 setLibcallImpl(Call: RTLIB::MEMSET, Impl: RTLIB::___memset64);
382 setLibcallImpl(Call: RTLIB::BZERO, Impl: RTLIB::___bzero64);
383 } else {
384 setLibcallImpl(Call: RTLIB::MEMCPY, Impl: RTLIB::Unsupported);
385 setLibcallImpl(Call: RTLIB::MEMMOVE, Impl: RTLIB::___memmove);
386 setLibcallImpl(Call: RTLIB::MEMSET, Impl: RTLIB::___memset);
387 setLibcallImpl(Call: RTLIB::BZERO, Impl: RTLIB::___bzero);
388 }
389 }
390 }
391
392 // A few names are different on particular architectures or environments.
393 if (TT.isOSDarwin()) {
394 // For f16/f32 conversions, Darwin uses the standard naming scheme,
395 // instead of the gnueabi-style __gnu_*_ieee.
396 // FIXME: What about other targets?
397 setLibcallImpl(Call: RTLIB::FPEXT_F16_F32, Impl: RTLIB::__extendhfsf2);
398 setLibcallImpl(Call: RTLIB::FPROUND_F32_F16, Impl: RTLIB::__truncsfhf2);
399
400 // Some darwins have an optimized __bzero/bzero function.
401 if (TT.isX86()) {
402 if (TT.isMacOSX() && !TT.isMacOSXVersionLT(Major: 10, Minor: 6))
403 setLibcallImpl(Call: RTLIB::BZERO, Impl: RTLIB::__bzero);
404 } else if (TT.isAArch64())
405 setLibcallImpl(Call: RTLIB::BZERO, Impl: RTLIB::bzero);
406
407 if (darwinHasSinCosStret(TT)) {
408 setLibcallImpl(Call: RTLIB::SINCOS_STRET_F32, Impl: RTLIB::__sincosf_stret);
409 setLibcallImpl(Call: RTLIB::SINCOS_STRET_F64, Impl: RTLIB::__sincos_stret);
410 if (TT.isWatchABI()) {
411 setLibcallCallingConv(Call: RTLIB::SINCOS_STRET_F32,
412 CC: CallingConv::ARM_AAPCS_VFP);
413 setLibcallCallingConv(Call: RTLIB::SINCOS_STRET_F64,
414 CC: CallingConv::ARM_AAPCS_VFP);
415 }
416 }
417
418 if (darwinHasExp10(TT)) {
419 setLibcallImpl(Call: RTLIB::EXP10_F32, Impl: RTLIB::__exp10f);
420 setLibcallImpl(Call: RTLIB::EXP10_F64, Impl: RTLIB::__exp10);
421 } else {
422 setLibcallImpl(Call: RTLIB::EXP10_F32, Impl: RTLIB::Unsupported);
423 setLibcallImpl(Call: RTLIB::EXP10_F64, Impl: RTLIB::Unsupported);
424 }
425 }
426
427 if (hasSinCos(TT)) {
428 setLibcallImpl(Call: RTLIB::SINCOS_F32, Impl: RTLIB::sincosf);
429 setLibcallImpl(Call: RTLIB::SINCOS_F64, Impl: RTLIB::sincos);
430 setLibcallImpl(Call: RTLIB::SINCOS_F80, Impl: RTLIB::sincos_f80);
431 setLibcallImpl(Call: RTLIB::SINCOS_F128, Impl: RTLIB::sincos_f128);
432 setLibcallImpl(Call: RTLIB::SINCOS_PPCF128, Impl: RTLIB::sincos_ppcf128);
433 }
434
435 if (TT.isPS()) {
436 setLibcallImpl(Call: RTLIB::SINCOS_F32, Impl: RTLIB::sincosf);
437 setLibcallImpl(Call: RTLIB::SINCOS_F64, Impl: RTLIB::sincos);
438 }
439
440 if (TT.isOSOpenBSD()) {
441 setLibcallImpl(Call: RTLIB::STACKPROTECTOR_CHECK_FAIL, Impl: RTLIB::Unsupported);
442 }
443
444 if (TT.isOSWindows() && !TT.isOSCygMing()) {
445 setLibcallImpl(Call: RTLIB::LDEXP_F32, Impl: RTLIB::Unsupported);
446 setLibcallImpl(Call: RTLIB::LDEXP_F80, Impl: RTLIB::Unsupported);
447 setLibcallImpl(Call: RTLIB::LDEXP_F128, Impl: RTLIB::Unsupported);
448 setLibcallImpl(Call: RTLIB::LDEXP_PPCF128, Impl: RTLIB::Unsupported);
449
450 setLibcallImpl(Call: RTLIB::FREXP_F32, Impl: RTLIB::Unsupported);
451 setLibcallImpl(Call: RTLIB::FREXP_F80, Impl: RTLIB::Unsupported);
452 setLibcallImpl(Call: RTLIB::FREXP_F128, Impl: RTLIB::Unsupported);
453 setLibcallImpl(Call: RTLIB::FREXP_PPCF128, Impl: RTLIB::Unsupported);
454 }
455
456 // Disable most libcalls on AMDGPU and NVPTX.
457 if (TT.isAMDGPU() || TT.isNVPTX()) {
458 for (RTLIB::Libcall LC : RTLIB::libcalls()) {
459 if (!isAtomicLibCall(LC))
460 setLibcallImpl(Call: LC, Impl: RTLIB::Unsupported);
461 }
462 }
463
464 if (TT.isOSMSVCRT()) {
465 // MSVCRT doesn't have powi; fall back to pow
466 setLibcallImpl(Call: RTLIB::POWI_F32, Impl: RTLIB::Unsupported);
467 setLibcallImpl(Call: RTLIB::POWI_F64, Impl: RTLIB::Unsupported);
468 }
469
470 // Setup Windows compiler runtime calls.
471 if (TT.getArch() == Triple::x86 &&
472 (TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment())) {
473 static const struct {
474 const RTLIB::Libcall Op;
475 const RTLIB::LibcallImpl Impl;
476 const CallingConv::ID CC;
477 } LibraryCalls[] = {
478 {.Op: RTLIB::SDIV_I64, .Impl: RTLIB::_alldiv, .CC: CallingConv::X86_StdCall},
479 {.Op: RTLIB::UDIV_I64, .Impl: RTLIB::_aulldiv, .CC: CallingConv::X86_StdCall},
480 {.Op: RTLIB::SREM_I64, .Impl: RTLIB::_allrem, .CC: CallingConv::X86_StdCall},
481 {.Op: RTLIB::UREM_I64, .Impl: RTLIB::_aullrem, .CC: CallingConv::X86_StdCall},
482 {.Op: RTLIB::MUL_I64, .Impl: RTLIB::_allmul, .CC: CallingConv::X86_StdCall},
483 };
484
485 for (const auto &LC : LibraryCalls) {
486 setLibcallImpl(Call: LC.Op, Impl: LC.Impl);
487 setLibcallCallingConv(Call: LC.Op, CC: LC.CC);
488 }
489 }
490
491 if (TT.isAArch64()) {
492 if (TT.isWindowsArm64EC()) {
493 setWindowsArm64LibCallNameOverrides();
494 setLibcallImpl(Call: RTLIB::SC_MEMCPY, Impl: RTLIB::arm64ec___arm_sc_memcpy);
495 setLibcallImpl(Call: RTLIB::SC_MEMMOVE, Impl: RTLIB::arm64ec___arm_sc_memmove);
496 setLibcallImpl(Call: RTLIB::SC_MEMSET, Impl: RTLIB::arm64ec___arm_sc_memset);
497 } else {
498 setLibcallImpl(Call: RTLIB::SC_MEMCPY, Impl: RTLIB::__arm_sc_memcpy);
499 setLibcallImpl(Call: RTLIB::SC_MEMMOVE, Impl: RTLIB::__arm_sc_memmove);
500 setLibcallImpl(Call: RTLIB::SC_MEMSET, Impl: RTLIB::__arm_sc_memset);
501 }
502
503 setAArch64LibcallNames(Info&: *this, TT);
504 } else if (TT.isARM() || TT.isThumb()) {
505 setARMLibcallNames(Info&: *this, TT, FloatABIType: FloatABI, EABIVersion);
506 } else if (TT.getArch() == Triple::ArchType::avr) {
507 // Division rtlib functions (not supported), use divmod functions instead
508 setLibcallImpl(Call: RTLIB::SDIV_I8, Impl: RTLIB::Unsupported);
509 setLibcallImpl(Call: RTLIB::SDIV_I16, Impl: RTLIB::Unsupported);
510 setLibcallImpl(Call: RTLIB::SDIV_I32, Impl: RTLIB::Unsupported);
511 setLibcallImpl(Call: RTLIB::UDIV_I8, Impl: RTLIB::Unsupported);
512 setLibcallImpl(Call: RTLIB::UDIV_I16, Impl: RTLIB::Unsupported);
513 setLibcallImpl(Call: RTLIB::UDIV_I32, Impl: RTLIB::Unsupported);
514
515 // Modulus rtlib functions (not supported), use divmod functions instead
516 setLibcallImpl(Call: RTLIB::SREM_I8, Impl: RTLIB::Unsupported);
517 setLibcallImpl(Call: RTLIB::SREM_I16, Impl: RTLIB::Unsupported);
518 setLibcallImpl(Call: RTLIB::SREM_I32, Impl: RTLIB::Unsupported);
519 setLibcallImpl(Call: RTLIB::UREM_I8, Impl: RTLIB::Unsupported);
520 setLibcallImpl(Call: RTLIB::UREM_I16, Impl: RTLIB::Unsupported);
521 setLibcallImpl(Call: RTLIB::UREM_I32, Impl: RTLIB::Unsupported);
522
523 // Division and modulus rtlib functions
524 setLibcallImpl(Call: RTLIB::SDIVREM_I8, Impl: RTLIB::__divmodqi4);
525 setLibcallImpl(Call: RTLIB::SDIVREM_I16, Impl: RTLIB::__divmodhi4);
526 setLibcallImpl(Call: RTLIB::SDIVREM_I32, Impl: RTLIB::__divmodsi4);
527 setLibcallImpl(Call: RTLIB::UDIVREM_I8, Impl: RTLIB::__udivmodqi4);
528 setLibcallImpl(Call: RTLIB::UDIVREM_I16, Impl: RTLIB::__udivmodhi4);
529 setLibcallImpl(Call: RTLIB::UDIVREM_I32, Impl: RTLIB::__udivmodsi4);
530
531 // Several of the runtime library functions use a special calling conv
532 setLibcallCallingConv(Call: RTLIB::SDIVREM_I8, CC: CallingConv::AVR_BUILTIN);
533 setLibcallCallingConv(Call: RTLIB::SDIVREM_I16, CC: CallingConv::AVR_BUILTIN);
534 setLibcallCallingConv(Call: RTLIB::UDIVREM_I8, CC: CallingConv::AVR_BUILTIN);
535 setLibcallCallingConv(Call: RTLIB::UDIVREM_I16, CC: CallingConv::AVR_BUILTIN);
536
537 // Trigonometric rtlib functions
538 setLibcallImpl(Call: RTLIB::SIN_F32, Impl: RTLIB::avr_sin);
539 setLibcallImpl(Call: RTLIB::COS_F32, Impl: RTLIB::avr_cos);
540 }
541
542 if (!TT.isWasm()) {
543 // These libcalls are only available in compiler-rt, not libgcc.
544 if (TT.isArch32Bit()) {
545 setLibcallImpl(Call: RTLIB::SHL_I128, Impl: RTLIB::Unsupported);
546 setLibcallImpl(Call: RTLIB::SRL_I128, Impl: RTLIB::Unsupported);
547 setLibcallImpl(Call: RTLIB::SRA_I128, Impl: RTLIB::Unsupported);
548 setLibcallImpl(Call: RTLIB::MUL_I128, Impl: RTLIB::Unsupported);
549 setLibcallImpl(Call: RTLIB::MULO_I64, Impl: RTLIB::Unsupported);
550 }
551
552 setLibcallImpl(Call: RTLIB::MULO_I128, Impl: RTLIB::Unsupported);
553 } else {
554 // Define the emscripten name for return address helper.
555 // TODO: when implementing other Wasm backends, make this generic or only do
556 // this on emscripten depending on what they end up doing.
557 setLibcallImpl(Call: RTLIB::RETURN_ADDRESS, Impl: RTLIB::emscripten_return_address);
558 }
559
560 if (TT.getArch() == Triple::ArchType::hexagon) {
561 setLibcallImpl(Call: RTLIB::SDIV_I32, Impl: RTLIB::__hexagon_divsi3);
562 setLibcallImpl(Call: RTLIB::SDIV_I64, Impl: RTLIB::__hexagon_divdi3);
563 setLibcallImpl(Call: RTLIB::UDIV_I32, Impl: RTLIB::__hexagon_udivsi3);
564 setLibcallImpl(Call: RTLIB::UDIV_I64, Impl: RTLIB::__hexagon_udivdi3);
565 setLibcallImpl(Call: RTLIB::SREM_I32, Impl: RTLIB::__hexagon_modsi3);
566 setLibcallImpl(Call: RTLIB::SREM_I64, Impl: RTLIB::__hexagon_moddi3);
567 setLibcallImpl(Call: RTLIB::UREM_I32, Impl: RTLIB::__hexagon_umodsi3);
568 setLibcallImpl(Call: RTLIB::UREM_I64, Impl: RTLIB::__hexagon_umoddi3);
569
570 const bool FastMath = HexagonEnableFastMathRuntimeCalls;
571 // This is the only fast library function for sqrtd.
572 if (FastMath)
573 setLibcallImpl(Call: RTLIB::SQRT_F64, Impl: RTLIB::__hexagon_fast2_sqrtdf2);
574
575 // Prefix is: nothing for "slow-math",
576 // "fast2_" for V5+ fast-math double-precision
577 // (actually, keep fast-math and fast-math2 separate for now)
578 if (FastMath) {
579 setLibcallImpl(Call: RTLIB::ADD_F64, Impl: RTLIB::__hexagon_fast_adddf3);
580 setLibcallImpl(Call: RTLIB::SUB_F64, Impl: RTLIB::__hexagon_fast_subdf3);
581 setLibcallImpl(Call: RTLIB::MUL_F64, Impl: RTLIB::__hexagon_fast_muldf3);
582 setLibcallImpl(Call: RTLIB::DIV_F64, Impl: RTLIB::__hexagon_fast_divdf3);
583 setLibcallImpl(Call: RTLIB::DIV_F32, Impl: RTLIB::__hexagon_fast_divsf3);
584 } else {
585 setLibcallImpl(Call: RTLIB::ADD_F64, Impl: RTLIB::__hexagon_adddf3);
586 setLibcallImpl(Call: RTLIB::SUB_F64, Impl: RTLIB::__hexagon_subdf3);
587 setLibcallImpl(Call: RTLIB::MUL_F64, Impl: RTLIB::__hexagon_muldf3);
588 setLibcallImpl(Call: RTLIB::DIV_F64, Impl: RTLIB::__hexagon_divdf3);
589 setLibcallImpl(Call: RTLIB::DIV_F32, Impl: RTLIB::__hexagon_divsf3);
590 }
591
592 if (FastMath)
593 setLibcallImpl(Call: RTLIB::SQRT_F32, Impl: RTLIB::__hexagon_fast2_sqrtf);
594 else
595 setLibcallImpl(Call: RTLIB::SQRT_F32, Impl: RTLIB::__hexagon_sqrtf);
596
597 setLibcallImpl(
598 Call: RTLIB::HEXAGON_MEMCPY_LIKELY_ALIGNED_MIN32BYTES_MULT8BYTES,
599 Impl: RTLIB::__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes);
600 }
601
602 if (TT.getArch() == Triple::ArchType::msp430)
603 setMSP430Libcalls(Info&: *this, TT);
604
605 if (TT.isSystemZ() && TT.isOSzOS())
606 setZOSLibCallNameOverrides();
607
608 if (TT.getArch() == Triple::ArchType::xcore)
609 setLibcallImpl(Call: RTLIB::MEMCPY_ALIGN_4, Impl: RTLIB::__memcpy_4);
610}
611
612bool RuntimeLibcallsInfo::darwinHasExp10(const Triple &TT) {
613 assert(TT.isOSDarwin() && "should be called with darwin triple");
614
615 switch (TT.getOS()) {
616 case Triple::MacOSX:
617 return !TT.isMacOSXVersionLT(Major: 10, Minor: 9);
618 case Triple::IOS:
619 return !TT.isOSVersionLT(Major: 7, Minor: 0);
620 case Triple::DriverKit:
621 case Triple::TvOS:
622 case Triple::WatchOS:
623 case Triple::XROS:
624 case Triple::BridgeOS:
625 return true;
626 default:
627 return false;
628 }
629}
630