xref: /llvm-project/llvm/lib/IR/RuntimeLibcalls.cpp (revision dad9e4a1657b74bc351c1e98ce4774f32fdc77fc)
1615b7eeaSJoseph Huber //===- RuntimeLibcalls.cpp - Interface for runtime libcalls -----*- C++ -*-===//
2615b7eeaSJoseph Huber //
3615b7eeaSJoseph Huber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4615b7eeaSJoseph Huber // See https://llvm.org/LICENSE.txt for license information.
5615b7eeaSJoseph Huber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6615b7eeaSJoseph Huber //
7615b7eeaSJoseph Huber //===----------------------------------------------------------------------===//
8615b7eeaSJoseph Huber 
9615b7eeaSJoseph Huber #include "llvm/IR/RuntimeLibcalls.h"
10615b7eeaSJoseph Huber 
11615b7eeaSJoseph Huber using namespace llvm;
12615b7eeaSJoseph Huber using namespace RTLIB;
13615b7eeaSJoseph Huber 
14615b7eeaSJoseph Huber /// Set default libcall names. If a target wants to opt-out of a libcall it
15615b7eeaSJoseph Huber /// should be placed here.
16615b7eeaSJoseph Huber void RuntimeLibcallsInfo::initLibcalls(const Triple &TT) {
17615b7eeaSJoseph Huber   std::fill(std::begin(LibcallRoutineNames), std::end(LibcallRoutineNames),
18615b7eeaSJoseph Huber             nullptr);
19615b7eeaSJoseph Huber 
20615b7eeaSJoseph Huber #define HANDLE_LIBCALL(code, name) setLibcallName(RTLIB::code, name);
21615b7eeaSJoseph Huber #include "llvm/IR/RuntimeLibcalls.def"
22615b7eeaSJoseph Huber #undef HANDLE_LIBCALL
23615b7eeaSJoseph Huber 
24615b7eeaSJoseph Huber   // Initialize calling conventions to their default.
25615b7eeaSJoseph Huber   for (int LC = 0; LC < RTLIB::UNKNOWN_LIBCALL; ++LC)
26615b7eeaSJoseph Huber     setLibcallCallingConv((RTLIB::Libcall)LC, CallingConv::C);
27615b7eeaSJoseph Huber 
28615b7eeaSJoseph Huber   // Use the f128 variants of math functions on x86_64
29615b7eeaSJoseph Huber   if (TT.getArch() == Triple::ArchType::x86_64 && TT.isGNUEnvironment()) {
30615b7eeaSJoseph Huber     setLibcallName(RTLIB::REM_F128, "fmodf128");
31615b7eeaSJoseph Huber     setLibcallName(RTLIB::FMA_F128, "fmaf128");
32615b7eeaSJoseph Huber     setLibcallName(RTLIB::SQRT_F128, "sqrtf128");
33615b7eeaSJoseph Huber     setLibcallName(RTLIB::CBRT_F128, "cbrtf128");
34615b7eeaSJoseph Huber     setLibcallName(RTLIB::LOG_F128, "logf128");
35615b7eeaSJoseph Huber     setLibcallName(RTLIB::LOG_FINITE_F128, "__logf128_finite");
36615b7eeaSJoseph Huber     setLibcallName(RTLIB::LOG2_F128, "log2f128");
37615b7eeaSJoseph Huber     setLibcallName(RTLIB::LOG2_FINITE_F128, "__log2f128_finite");
38615b7eeaSJoseph Huber     setLibcallName(RTLIB::LOG10_F128, "log10f128");
39615b7eeaSJoseph Huber     setLibcallName(RTLIB::LOG10_FINITE_F128, "__log10f128_finite");
40615b7eeaSJoseph Huber     setLibcallName(RTLIB::EXP_F128, "expf128");
41615b7eeaSJoseph Huber     setLibcallName(RTLIB::EXP_FINITE_F128, "__expf128_finite");
42615b7eeaSJoseph Huber     setLibcallName(RTLIB::EXP2_F128, "exp2f128");
43615b7eeaSJoseph Huber     setLibcallName(RTLIB::EXP2_FINITE_F128, "__exp2f128_finite");
44615b7eeaSJoseph Huber     setLibcallName(RTLIB::EXP10_F128, "exp10f128");
45615b7eeaSJoseph Huber     setLibcallName(RTLIB::SIN_F128, "sinf128");
46615b7eeaSJoseph Huber     setLibcallName(RTLIB::COS_F128, "cosf128");
47615b7eeaSJoseph Huber     setLibcallName(RTLIB::TAN_F128, "tanf128");
48615b7eeaSJoseph Huber     setLibcallName(RTLIB::SINCOS_F128, "sincosf128");
49615b7eeaSJoseph Huber     setLibcallName(RTLIB::ASIN_F128, "asinf128");
50615b7eeaSJoseph Huber     setLibcallName(RTLIB::ACOS_F128, "acosf128");
51615b7eeaSJoseph Huber     setLibcallName(RTLIB::ATAN_F128, "atanf128");
52875afa93STex Riddell     setLibcallName(RTLIB::ATAN2_F128, "atan2f128");
53615b7eeaSJoseph Huber     setLibcallName(RTLIB::SINH_F128, "sinhf128");
54615b7eeaSJoseph Huber     setLibcallName(RTLIB::COSH_F128, "coshf128");
55615b7eeaSJoseph Huber     setLibcallName(RTLIB::TANH_F128, "tanhf128");
56615b7eeaSJoseph Huber     setLibcallName(RTLIB::POW_F128, "powf128");
57615b7eeaSJoseph Huber     setLibcallName(RTLIB::POW_FINITE_F128, "__powf128_finite");
58615b7eeaSJoseph Huber     setLibcallName(RTLIB::CEIL_F128, "ceilf128");
59615b7eeaSJoseph Huber     setLibcallName(RTLIB::TRUNC_F128, "truncf128");
60615b7eeaSJoseph Huber     setLibcallName(RTLIB::RINT_F128, "rintf128");
61615b7eeaSJoseph Huber     setLibcallName(RTLIB::NEARBYINT_F128, "nearbyintf128");
62615b7eeaSJoseph Huber     setLibcallName(RTLIB::ROUND_F128, "roundf128");
63615b7eeaSJoseph Huber     setLibcallName(RTLIB::ROUNDEVEN_F128, "roundevenf128");
64615b7eeaSJoseph Huber     setLibcallName(RTLIB::FLOOR_F128, "floorf128");
65615b7eeaSJoseph Huber     setLibcallName(RTLIB::COPYSIGN_F128, "copysignf128");
66615b7eeaSJoseph Huber     setLibcallName(RTLIB::FMIN_F128, "fminf128");
67615b7eeaSJoseph Huber     setLibcallName(RTLIB::FMAX_F128, "fmaxf128");
68615b7eeaSJoseph Huber     setLibcallName(RTLIB::LROUND_F128, "lroundf128");
69615b7eeaSJoseph Huber     setLibcallName(RTLIB::LLROUND_F128, "llroundf128");
70615b7eeaSJoseph Huber     setLibcallName(RTLIB::LRINT_F128, "lrintf128");
71615b7eeaSJoseph Huber     setLibcallName(RTLIB::LLRINT_F128, "llrintf128");
72615b7eeaSJoseph Huber     setLibcallName(RTLIB::LDEXP_F128, "ldexpf128");
73615b7eeaSJoseph Huber     setLibcallName(RTLIB::FREXP_F128, "frexpf128");
74615b7eeaSJoseph Huber   }
75615b7eeaSJoseph Huber 
76615b7eeaSJoseph Huber   // For IEEE quad-precision libcall names, PPC uses "kf" instead of "tf".
77615b7eeaSJoseph Huber   if (TT.isPPC()) {
78615b7eeaSJoseph Huber     setLibcallName(RTLIB::ADD_F128, "__addkf3");
79615b7eeaSJoseph Huber     setLibcallName(RTLIB::SUB_F128, "__subkf3");
80615b7eeaSJoseph Huber     setLibcallName(RTLIB::MUL_F128, "__mulkf3");
81615b7eeaSJoseph Huber     setLibcallName(RTLIB::DIV_F128, "__divkf3");
82615b7eeaSJoseph Huber     setLibcallName(RTLIB::POWI_F128, "__powikf2");
83615b7eeaSJoseph Huber     setLibcallName(RTLIB::FPEXT_F32_F128, "__extendsfkf2");
84615b7eeaSJoseph Huber     setLibcallName(RTLIB::FPEXT_F64_F128, "__extenddfkf2");
85615b7eeaSJoseph Huber     setLibcallName(RTLIB::FPROUND_F128_F32, "__trunckfsf2");
86615b7eeaSJoseph Huber     setLibcallName(RTLIB::FPROUND_F128_F64, "__trunckfdf2");
87615b7eeaSJoseph Huber     setLibcallName(RTLIB::FPTOSINT_F128_I32, "__fixkfsi");
88615b7eeaSJoseph Huber     setLibcallName(RTLIB::FPTOSINT_F128_I64, "__fixkfdi");
89615b7eeaSJoseph Huber     setLibcallName(RTLIB::FPTOSINT_F128_I128, "__fixkfti");
90615b7eeaSJoseph Huber     setLibcallName(RTLIB::FPTOUINT_F128_I32, "__fixunskfsi");
91615b7eeaSJoseph Huber     setLibcallName(RTLIB::FPTOUINT_F128_I64, "__fixunskfdi");
92615b7eeaSJoseph Huber     setLibcallName(RTLIB::FPTOUINT_F128_I128, "__fixunskfti");
93615b7eeaSJoseph Huber     setLibcallName(RTLIB::SINTTOFP_I32_F128, "__floatsikf");
94615b7eeaSJoseph Huber     setLibcallName(RTLIB::SINTTOFP_I64_F128, "__floatdikf");
95615b7eeaSJoseph Huber     setLibcallName(RTLIB::SINTTOFP_I128_F128, "__floattikf");
96615b7eeaSJoseph Huber     setLibcallName(RTLIB::UINTTOFP_I32_F128, "__floatunsikf");
97615b7eeaSJoseph Huber     setLibcallName(RTLIB::UINTTOFP_I64_F128, "__floatundikf");
98615b7eeaSJoseph Huber     setLibcallName(RTLIB::UINTTOFP_I128_F128, "__floatuntikf");
99615b7eeaSJoseph Huber     setLibcallName(RTLIB::OEQ_F128, "__eqkf2");
100615b7eeaSJoseph Huber     setLibcallName(RTLIB::UNE_F128, "__nekf2");
101615b7eeaSJoseph Huber     setLibcallName(RTLIB::OGE_F128, "__gekf2");
102615b7eeaSJoseph Huber     setLibcallName(RTLIB::OLT_F128, "__ltkf2");
103615b7eeaSJoseph Huber     setLibcallName(RTLIB::OLE_F128, "__lekf2");
104615b7eeaSJoseph Huber     setLibcallName(RTLIB::OGT_F128, "__gtkf2");
105615b7eeaSJoseph Huber     setLibcallName(RTLIB::UO_F128, "__unordkf2");
106615b7eeaSJoseph Huber   }
107615b7eeaSJoseph Huber 
108615b7eeaSJoseph Huber   // A few names are different on particular architectures or environments.
109615b7eeaSJoseph Huber   if (TT.isOSDarwin()) {
110615b7eeaSJoseph Huber     // For f16/f32 conversions, Darwin uses the standard naming scheme,
111615b7eeaSJoseph Huber     // instead of the gnueabi-style __gnu_*_ieee.
112615b7eeaSJoseph Huber     // FIXME: What about other targets?
113615b7eeaSJoseph Huber     setLibcallName(RTLIB::FPEXT_F16_F32, "__extendhfsf2");
114615b7eeaSJoseph Huber     setLibcallName(RTLIB::FPROUND_F32_F16, "__truncsfhf2");
115615b7eeaSJoseph Huber 
116615b7eeaSJoseph Huber     // Some darwins have an optimized __bzero/bzero function.
117615b7eeaSJoseph Huber     switch (TT.getArch()) {
118615b7eeaSJoseph Huber     case Triple::x86:
119615b7eeaSJoseph Huber     case Triple::x86_64:
120615b7eeaSJoseph Huber       if (TT.isMacOSX() && !TT.isMacOSXVersionLT(10, 6))
121615b7eeaSJoseph Huber         setLibcallName(RTLIB::BZERO, "__bzero");
122615b7eeaSJoseph Huber       break;
123615b7eeaSJoseph Huber     case Triple::aarch64:
124615b7eeaSJoseph Huber     case Triple::aarch64_32:
125615b7eeaSJoseph Huber       setLibcallName(RTLIB::BZERO, "bzero");
126615b7eeaSJoseph Huber       break;
127615b7eeaSJoseph Huber     default:
128615b7eeaSJoseph Huber       break;
129615b7eeaSJoseph Huber     }
130615b7eeaSJoseph Huber 
131615b7eeaSJoseph Huber     if (darwinHasSinCos(TT)) {
132615b7eeaSJoseph Huber       setLibcallName(RTLIB::SINCOS_STRET_F32, "__sincosf_stret");
133615b7eeaSJoseph Huber       setLibcallName(RTLIB::SINCOS_STRET_F64, "__sincos_stret");
134615b7eeaSJoseph Huber       if (TT.isWatchABI()) {
135615b7eeaSJoseph Huber         setLibcallCallingConv(RTLIB::SINCOS_STRET_F32,
136615b7eeaSJoseph Huber                               CallingConv::ARM_AAPCS_VFP);
137615b7eeaSJoseph Huber         setLibcallCallingConv(RTLIB::SINCOS_STRET_F64,
138615b7eeaSJoseph Huber                               CallingConv::ARM_AAPCS_VFP);
139615b7eeaSJoseph Huber       }
140615b7eeaSJoseph Huber     }
141615b7eeaSJoseph Huber 
142615b7eeaSJoseph Huber     switch (TT.getOS()) {
143615b7eeaSJoseph Huber     case Triple::MacOSX:
144615b7eeaSJoseph Huber       if (TT.isMacOSXVersionLT(10, 9)) {
145615b7eeaSJoseph Huber         setLibcallName(RTLIB::EXP10_F32, nullptr);
146615b7eeaSJoseph Huber         setLibcallName(RTLIB::EXP10_F64, nullptr);
147615b7eeaSJoseph Huber       } else {
148615b7eeaSJoseph Huber         setLibcallName(RTLIB::EXP10_F32, "__exp10f");
149615b7eeaSJoseph Huber         setLibcallName(RTLIB::EXP10_F64, "__exp10");
150615b7eeaSJoseph Huber       }
151615b7eeaSJoseph Huber       break;
152615b7eeaSJoseph Huber     case Triple::IOS:
153615b7eeaSJoseph Huber       if (TT.isOSVersionLT(7, 0)) {
154615b7eeaSJoseph Huber         setLibcallName(RTLIB::EXP10_F32, nullptr);
155615b7eeaSJoseph Huber         setLibcallName(RTLIB::EXP10_F64, nullptr);
156615b7eeaSJoseph Huber         break;
157615b7eeaSJoseph Huber       }
158615b7eeaSJoseph Huber       [[fallthrough]];
1597b99b1d4SFlorian Hahn     case Triple::DriverKit:
160615b7eeaSJoseph Huber     case Triple::TvOS:
161615b7eeaSJoseph Huber     case Triple::WatchOS:
162615b7eeaSJoseph Huber     case Triple::XROS:
163615b7eeaSJoseph Huber       setLibcallName(RTLIB::EXP10_F32, "__exp10f");
164615b7eeaSJoseph Huber       setLibcallName(RTLIB::EXP10_F64, "__exp10");
165615b7eeaSJoseph Huber       break;
166615b7eeaSJoseph Huber     default:
167615b7eeaSJoseph Huber       break;
168615b7eeaSJoseph Huber     }
1697b99b1d4SFlorian Hahn   } else if (TT.getOS() == Triple::BridgeOS) {
1707b99b1d4SFlorian Hahn     // TODO: BridgeOS should be included in isOSDarwin.
1717b99b1d4SFlorian Hahn     setLibcallName(RTLIB::EXP10_F32, "__exp10f");
1727b99b1d4SFlorian Hahn     setLibcallName(RTLIB::EXP10_F64, "__exp10");
173615b7eeaSJoseph Huber   } else {
174615b7eeaSJoseph Huber     setLibcallName(RTLIB::FPEXT_F16_F32, "__gnu_h2f_ieee");
175615b7eeaSJoseph Huber     setLibcallName(RTLIB::FPROUND_F32_F16, "__gnu_f2h_ieee");
176615b7eeaSJoseph Huber   }
177615b7eeaSJoseph Huber 
178615b7eeaSJoseph Huber   if (TT.isGNUEnvironment() || TT.isOSFuchsia() ||
179615b7eeaSJoseph Huber       (TT.isAndroid() && !TT.isAndroidVersionLT(9))) {
180615b7eeaSJoseph Huber     setLibcallName(RTLIB::SINCOS_F32, "sincosf");
181615b7eeaSJoseph Huber     setLibcallName(RTLIB::SINCOS_F64, "sincos");
182615b7eeaSJoseph Huber     setLibcallName(RTLIB::SINCOS_F80, "sincosl");
183615b7eeaSJoseph Huber     setLibcallName(RTLIB::SINCOS_F128, "sincosl");
184615b7eeaSJoseph Huber     setLibcallName(RTLIB::SINCOS_PPCF128, "sincosl");
185615b7eeaSJoseph Huber   }
186615b7eeaSJoseph Huber 
187615b7eeaSJoseph Huber   if (TT.isPS()) {
188615b7eeaSJoseph Huber     setLibcallName(RTLIB::SINCOS_F32, "sincosf");
189615b7eeaSJoseph Huber     setLibcallName(RTLIB::SINCOS_F64, "sincos");
190615b7eeaSJoseph Huber   }
191615b7eeaSJoseph Huber 
192615b7eeaSJoseph Huber   if (TT.isOSOpenBSD()) {
193615b7eeaSJoseph Huber     setLibcallName(RTLIB::STACKPROTECTOR_CHECK_FAIL, nullptr);
194615b7eeaSJoseph Huber   }
195615b7eeaSJoseph Huber 
196615b7eeaSJoseph Huber   if (TT.isOSWindows() && !TT.isOSCygMing()) {
197615b7eeaSJoseph Huber     setLibcallName(RTLIB::LDEXP_F32, nullptr);
198615b7eeaSJoseph Huber     setLibcallName(RTLIB::LDEXP_F80, nullptr);
199615b7eeaSJoseph Huber     setLibcallName(RTLIB::LDEXP_F128, nullptr);
200615b7eeaSJoseph Huber     setLibcallName(RTLIB::LDEXP_PPCF128, nullptr);
201615b7eeaSJoseph Huber 
202615b7eeaSJoseph Huber     setLibcallName(RTLIB::FREXP_F32, nullptr);
203615b7eeaSJoseph Huber     setLibcallName(RTLIB::FREXP_F80, nullptr);
204615b7eeaSJoseph Huber     setLibcallName(RTLIB::FREXP_F128, nullptr);
205615b7eeaSJoseph Huber     setLibcallName(RTLIB::FREXP_PPCF128, nullptr);
206615b7eeaSJoseph Huber   }
207615b7eeaSJoseph Huber 
208615b7eeaSJoseph Huber   // Disable most libcalls on AMDGPU.
209615b7eeaSJoseph Huber   if (TT.isAMDGPU()) {
210615b7eeaSJoseph Huber     for (int I = 0; I < RTLIB::UNKNOWN_LIBCALL; ++I) {
211615b7eeaSJoseph Huber       if (I < RTLIB::ATOMIC_LOAD || I > RTLIB::ATOMIC_FETCH_NAND_16)
212615b7eeaSJoseph Huber         setLibcallName(static_cast<RTLIB::Libcall>(I), nullptr);
213615b7eeaSJoseph Huber     }
214615b7eeaSJoseph Huber   }
215615b7eeaSJoseph Huber 
216615b7eeaSJoseph Huber   // Disable most libcalls on NVPTX.
217615b7eeaSJoseph Huber   if (TT.isNVPTX()) {
218615b7eeaSJoseph Huber     for (int I = 0; I < RTLIB::UNKNOWN_LIBCALL; ++I)
219615b7eeaSJoseph Huber       if (I < RTLIB::ATOMIC_LOAD || I > RTLIB::ATOMIC_FETCH_NAND_16)
220615b7eeaSJoseph Huber         setLibcallName(static_cast<RTLIB::Libcall>(I), nullptr);
221615b7eeaSJoseph Huber   }
222615b7eeaSJoseph Huber 
223615b7eeaSJoseph Huber   if (TT.isOSMSVCRT()) {
224615b7eeaSJoseph Huber     // MSVCRT doesn't have powi; fall back to pow
225615b7eeaSJoseph Huber     setLibcallName(RTLIB::POWI_F32, nullptr);
226615b7eeaSJoseph Huber     setLibcallName(RTLIB::POWI_F64, nullptr);
227615b7eeaSJoseph Huber   }
228615b7eeaSJoseph Huber 
229615b7eeaSJoseph Huber   if (TT.getArch() == Triple::ArchType::avr) {
230615b7eeaSJoseph Huber     // Division rtlib functions (not supported), use divmod functions instead
231615b7eeaSJoseph Huber     setLibcallName(RTLIB::SDIV_I8, nullptr);
232615b7eeaSJoseph Huber     setLibcallName(RTLIB::SDIV_I16, nullptr);
233615b7eeaSJoseph Huber     setLibcallName(RTLIB::SDIV_I32, nullptr);
234615b7eeaSJoseph Huber     setLibcallName(RTLIB::UDIV_I8, nullptr);
235615b7eeaSJoseph Huber     setLibcallName(RTLIB::UDIV_I16, nullptr);
236615b7eeaSJoseph Huber     setLibcallName(RTLIB::UDIV_I32, nullptr);
237615b7eeaSJoseph Huber 
238615b7eeaSJoseph Huber     // Modulus rtlib functions (not supported), use divmod functions instead
239615b7eeaSJoseph Huber     setLibcallName(RTLIB::SREM_I8, nullptr);
240615b7eeaSJoseph Huber     setLibcallName(RTLIB::SREM_I16, nullptr);
241615b7eeaSJoseph Huber     setLibcallName(RTLIB::SREM_I32, nullptr);
242615b7eeaSJoseph Huber     setLibcallName(RTLIB::UREM_I8, nullptr);
243615b7eeaSJoseph Huber     setLibcallName(RTLIB::UREM_I16, nullptr);
244615b7eeaSJoseph Huber     setLibcallName(RTLIB::UREM_I32, nullptr);
245615b7eeaSJoseph Huber   }
246615b7eeaSJoseph Huber 
247*dad9e4a1SNikita Popov   if (!TT.isWasm()) {
248*dad9e4a1SNikita Popov     // These libcalls are only available in compiler-rt, not libgcc.
249*dad9e4a1SNikita Popov     if (TT.isArch32Bit()) {
250615b7eeaSJoseph Huber       setLibcallName(RTLIB::SHL_I128, nullptr);
251615b7eeaSJoseph Huber       setLibcallName(RTLIB::SRL_I128, nullptr);
252615b7eeaSJoseph Huber       setLibcallName(RTLIB::SRA_I128, nullptr);
253615b7eeaSJoseph Huber       setLibcallName(RTLIB::MUL_I128, nullptr);
254615b7eeaSJoseph Huber       setLibcallName(RTLIB::MULO_I64, nullptr);
255615b7eeaSJoseph Huber     }
256615b7eeaSJoseph Huber     setLibcallName(RTLIB::MULO_I128, nullptr);
257615b7eeaSJoseph Huber   }
258615b7eeaSJoseph Huber }
259