blob: 64c9415c54d4db88995aeb211db2b16db90836f0 [file] [log] [blame]
//===- RuntimeLibcalls.cpp - Interface for runtime libcalls -----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/RuntimeLibcalls.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;
using namespace RTLIB;
#define GET_INIT_RUNTIME_LIBCALL_NAMES
#define GET_SET_TARGET_RUNTIME_LIBCALL_SETS
#include "llvm/IR/RuntimeLibcalls.inc"
#undef GET_INIT_RUNTIME_LIBCALL_NAMES
#undef GET_SET_TARGET_RUNTIME_LIBCALL_SETS
static cl::opt<bool>
HexagonEnableFastMathRuntimeCalls("hexagon-fast-math", cl::Hidden,
cl::desc("Enable Fast Math processing"));
static void setARMLibcallNames(RuntimeLibcallsInfo &Info, const Triple &TT,
FloatABI::ABIType FloatABIType,
EABI EABIVersion) {
static const RTLIB::LibcallImpl AAPCS_Libcalls[] = {
RTLIB::__aeabi_dadd, RTLIB::__aeabi_ddiv,
RTLIB::__aeabi_dmul, RTLIB::__aeabi_dsub,
RTLIB::__aeabi_dcmpeq__oeq, RTLIB::__aeabi_dcmpeq__une,
RTLIB::__aeabi_dcmplt, RTLIB::__aeabi_dcmple,
RTLIB::__aeabi_dcmpge, RTLIB::__aeabi_dcmpgt,
RTLIB::__aeabi_dcmpun, RTLIB::__aeabi_fadd,
RTLIB::__aeabi_fdiv, RTLIB::__aeabi_fmul,
RTLIB::__aeabi_fsub, RTLIB::__aeabi_fcmpeq__oeq,
RTLIB::__aeabi_fcmpeq__une, RTLIB::__aeabi_fcmplt,
RTLIB::__aeabi_fcmple, RTLIB::__aeabi_fcmpge,
RTLIB::__aeabi_fcmpgt, RTLIB::__aeabi_fcmpun,
RTLIB::__aeabi_d2iz, RTLIB::__aeabi_d2uiz,
RTLIB::__aeabi_d2lz, RTLIB::__aeabi_d2ulz,
RTLIB::__aeabi_f2iz, RTLIB::__aeabi_f2uiz,
RTLIB::__aeabi_f2lz, RTLIB::__aeabi_f2ulz,
RTLIB::__aeabi_d2f, RTLIB::__aeabi_d2h,
RTLIB::__aeabi_f2d, RTLIB::__aeabi_i2d,
RTLIB::__aeabi_ui2d, RTLIB::__aeabi_l2d,
RTLIB::__aeabi_ul2d, RTLIB::__aeabi_i2f,
RTLIB::__aeabi_ui2f, RTLIB::__aeabi_l2f,
RTLIB::__aeabi_ul2f, RTLIB::__aeabi_lmul,
RTLIB::__aeabi_llsl, RTLIB::__aeabi_llsr,
RTLIB::__aeabi_lasr, RTLIB::__aeabi_idiv__i8,
RTLIB::__aeabi_idiv__i16, RTLIB::__aeabi_idiv__i32,
RTLIB::__aeabi_idivmod, RTLIB::__aeabi_uidivmod,
RTLIB::__aeabi_ldivmod, RTLIB::__aeabi_uidiv__i8,
RTLIB::__aeabi_uidiv__i16, RTLIB::__aeabi_uidiv__i32,
RTLIB::__aeabi_uldivmod, RTLIB::__aeabi_f2h,
RTLIB::__aeabi_d2h, RTLIB::__aeabi_h2f,
RTLIB::__aeabi_memcpy, RTLIB::__aeabi_memmove,
RTLIB::__aeabi_memset, RTLIB::__aeabi_memcpy4,
RTLIB::__aeabi_memcpy8, RTLIB::__aeabi_memmove4,
RTLIB::__aeabi_memmove8, RTLIB::__aeabi_memset4,
RTLIB::__aeabi_memset8, RTLIB::__aeabi_memclr,
RTLIB::__aeabi_memclr4, RTLIB::__aeabi_memclr8};
for (RTLIB::LibcallImpl Impl : AAPCS_Libcalls)
Info.setLibcallImplCallingConv(Impl, CallingConv::ARM_AAPCS);
}
static void setLongDoubleIsF128Libm(RuntimeLibcallsInfo &Info,
bool FiniteOnlyFuncs = false) {
Info.setLibcallImpl(RTLIB::REM_F128, RTLIB::fmodf128);
Info.setLibcallImpl(RTLIB::FMA_F128, RTLIB::fmaf128);
Info.setLibcallImpl(RTLIB::SQRT_F128, RTLIB::sqrtf128);
Info.setLibcallImpl(RTLIB::CBRT_F128, RTLIB::cbrtf128);
Info.setLibcallImpl(RTLIB::LOG_F128, RTLIB::logf128);
Info.setLibcallImpl(RTLIB::LOG2_F128, RTLIB::log2f128);
Info.setLibcallImpl(RTLIB::LOG10_F128, RTLIB::log10f128);
Info.setLibcallImpl(RTLIB::EXP_F128, RTLIB::expf128);
Info.setLibcallImpl(RTLIB::EXP2_F128, RTLIB::exp2f128);
Info.setLibcallImpl(RTLIB::EXP10_F128, RTLIB::exp10f128);
Info.setLibcallImpl(RTLIB::SIN_F128, RTLIB::sinf128);
Info.setLibcallImpl(RTLIB::COS_F128, RTLIB::cosf128);
Info.setLibcallImpl(RTLIB::TAN_F128, RTLIB::tanf128);
Info.setLibcallImpl(RTLIB::SINCOS_F128, RTLIB::sincosf128);
Info.setLibcallImpl(RTLIB::ASIN_F128, RTLIB::asinf128);
Info.setLibcallImpl(RTLIB::ACOS_F128, RTLIB::acosf128);
Info.setLibcallImpl(RTLIB::ATAN_F128, RTLIB::atanf128);
Info.setLibcallImpl(RTLIB::ATAN2_F128, RTLIB::atan2f128);
Info.setLibcallImpl(RTLIB::SINH_F128, RTLIB::sinhf128);
Info.setLibcallImpl(RTLIB::COSH_F128, RTLIB::coshf128);
Info.setLibcallImpl(RTLIB::TANH_F128, RTLIB::tanhf128);
Info.setLibcallImpl(RTLIB::POW_F128, RTLIB::powf128);
Info.setLibcallImpl(RTLIB::CEIL_F128, RTLIB::ceilf128);
Info.setLibcallImpl(RTLIB::TRUNC_F128, RTLIB::truncf128);
Info.setLibcallImpl(RTLIB::RINT_F128, RTLIB::rintf128);
Info.setLibcallImpl(RTLIB::NEARBYINT_F128, RTLIB::nearbyintf128);
Info.setLibcallImpl(RTLIB::ROUND_F128, RTLIB::roundf128);
Info.setLibcallImpl(RTLIB::ROUNDEVEN_F128, RTLIB::roundevenf128);
Info.setLibcallImpl(RTLIB::FLOOR_F128, RTLIB::floorf128);
Info.setLibcallImpl(RTLIB::COPYSIGN_F128, RTLIB::copysignf128);
Info.setLibcallImpl(RTLIB::FMIN_F128, RTLIB::fminf128);
Info.setLibcallImpl(RTLIB::FMAX_F128, RTLIB::fmaxf128);
Info.setLibcallImpl(RTLIB::FMINIMUM_F128, RTLIB::fminimumf128);
Info.setLibcallImpl(RTLIB::FMAXIMUM_F128, RTLIB::fmaximumf128);
Info.setLibcallImpl(RTLIB::FMINIMUM_NUM_F128, RTLIB::fminimum_numf128);
Info.setLibcallImpl(RTLIB::FMAXIMUM_NUM_F128, RTLIB::fmaximum_numf128);
Info.setLibcallImpl(RTLIB::LROUND_F128, RTLIB::lroundf128);
Info.setLibcallImpl(RTLIB::LLROUND_F128, RTLIB::llroundf128);
Info.setLibcallImpl(RTLIB::LRINT_F128, RTLIB::lrintf128);
Info.setLibcallImpl(RTLIB::LLRINT_F128, RTLIB::llrintf128);
Info.setLibcallImpl(RTLIB::LDEXP_F128, RTLIB::ldexpf128);
Info.setLibcallImpl(RTLIB::FREXP_F128, RTLIB::frexpf128);
Info.setLibcallImpl(RTLIB::MODF_F128, RTLIB::modff128);
if (FiniteOnlyFuncs) {
Info.setLibcallImpl(RTLIB::LOG_FINITE_F128, RTLIB::__logf128_finite);
Info.setLibcallImpl(RTLIB::LOG2_FINITE_F128, RTLIB::__log2f128_finite);
Info.setLibcallImpl(RTLIB::LOG10_FINITE_F128, RTLIB::__log10f128_finite);
Info.setLibcallImpl(RTLIB::EXP_FINITE_F128, RTLIB::__expf128_finite);
Info.setLibcallImpl(RTLIB::EXP2_FINITE_F128, RTLIB::__exp2f128_finite);
Info.setLibcallImpl(RTLIB::POW_FINITE_F128, RTLIB::__powf128_finite);
} else {
Info.setLibcallImpl(RTLIB::LOG_FINITE_F128, RTLIB::Unsupported);
Info.setLibcallImpl(RTLIB::LOG2_FINITE_F128, RTLIB::Unsupported);
Info.setLibcallImpl(RTLIB::LOG10_FINITE_F128, RTLIB::Unsupported);
Info.setLibcallImpl(RTLIB::EXP_FINITE_F128, RTLIB::Unsupported);
Info.setLibcallImpl(RTLIB::EXP2_FINITE_F128, RTLIB::Unsupported);
Info.setLibcallImpl(RTLIB::POW_FINITE_F128, RTLIB::Unsupported);
}
}
void RTLIB::RuntimeLibcallsInfo::initDefaultLibCallImpls() {
std::memcpy(LibcallImpls, DefaultLibcallImpls, sizeof(LibcallImpls));
static_assert(sizeof(LibcallImpls) == sizeof(DefaultLibcallImpls),
"libcall array size should match");
}
/// Set default libcall names. If a target wants to opt-out of a libcall it
/// should be placed here.
void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
ExceptionHandling ExceptionModel,
FloatABI::ABIType FloatABI,
EABI EABIVersion, StringRef ABIName) {
setTargetRuntimeLibcallSets(TT, FloatABI);
// Use the f128 variants of math functions on x86
if (TT.isX86() && TT.isGNUEnvironment())
setLongDoubleIsF128Libm(*this, /*FiniteOnlyFuncs=*/true);
if (TT.isX86() || TT.isVE() || TT.isARM() || TT.isThumb()) {
if (ExceptionModel == ExceptionHandling::SjLj)
setLibcallImpl(RTLIB::UNWIND_RESUME, RTLIB::_Unwind_SjLj_Resume);
}
// A few names are different on particular architectures or environments.
if (TT.isOSDarwin()) {
// For f16/f32 conversions, Darwin uses the standard naming scheme,
// instead of the gnueabi-style __gnu_*_ieee.
// FIXME: What about other targets?
setLibcallImpl(RTLIB::FPEXT_F16_F32, RTLIB::__extendhfsf2);
setLibcallImpl(RTLIB::FPROUND_F32_F16, RTLIB::__truncsfhf2);
// Some darwins have an optimized __bzero/bzero function.
if (TT.isX86()) {
if (TT.isMacOSX() && !TT.isMacOSXVersionLT(10, 6))
setLibcallImpl(RTLIB::BZERO, RTLIB::__bzero);
}
if (darwinHasSinCosStret(TT)) {
setLibcallImpl(RTLIB::SINCOS_STRET_F32, RTLIB::__sincosf_stret);
setLibcallImpl(RTLIB::SINCOS_STRET_F64, RTLIB::__sincos_stret);
if (TT.isWatchABI()) {
setLibcallImplCallingConv(RTLIB::__sincosf_stret,
CallingConv::ARM_AAPCS_VFP);
setLibcallImplCallingConv(RTLIB::__sincos_stret,
CallingConv::ARM_AAPCS_VFP);
}
}
if (darwinHasExp10(TT)) {
setLibcallImpl(RTLIB::EXP10_F32, RTLIB::__exp10f);
setLibcallImpl(RTLIB::EXP10_F64, RTLIB::__exp10);
} else {
setLibcallImpl(RTLIB::EXP10_F32, RTLIB::Unsupported);
setLibcallImpl(RTLIB::EXP10_F64, RTLIB::Unsupported);
}
}
if (hasSinCos(TT)) {
setLibcallImpl(RTLIB::SINCOS_F32, RTLIB::sincosf);
setLibcallImpl(RTLIB::SINCOS_F64, RTLIB::sincos);
setLibcallImpl(RTLIB::SINCOS_F80, RTLIB::sincos_f80);
setLibcallImpl(RTLIB::SINCOS_F128, RTLIB::sincos_f128);
setLibcallImpl(RTLIB::SINCOS_PPCF128, RTLIB::sincos_ppcf128);
}
if (TT.isPS()) {
setLibcallImpl(RTLIB::SINCOS_F32, RTLIB::sincosf);
setLibcallImpl(RTLIB::SINCOS_F64, RTLIB::sincos);
}
if (TT.isOSOpenBSD()) {
setLibcallImpl(RTLIB::STACKPROTECTOR_CHECK_FAIL, RTLIB::Unsupported);
}
if (TT.isOSWindows() && !TT.isOSCygMing()) {
setLibcallImpl(RTLIB::LDEXP_F32, RTLIB::Unsupported);
setLibcallImpl(RTLIB::LDEXP_F80, RTLIB::Unsupported);
setLibcallImpl(RTLIB::LDEXP_F128, RTLIB::Unsupported);
setLibcallImpl(RTLIB::LDEXP_PPCF128, RTLIB::Unsupported);
setLibcallImpl(RTLIB::FREXP_F32, RTLIB::Unsupported);
setLibcallImpl(RTLIB::FREXP_F80, RTLIB::Unsupported);
setLibcallImpl(RTLIB::FREXP_F128, RTLIB::Unsupported);
setLibcallImpl(RTLIB::FREXP_PPCF128, RTLIB::Unsupported);
}
if (TT.isOSMSVCRT()) {
// MSVCRT doesn't have powi; fall back to pow
setLibcallImpl(RTLIB::POWI_F32, RTLIB::Unsupported);
setLibcallImpl(RTLIB::POWI_F64, RTLIB::Unsupported);
}
// Setup Windows compiler runtime calls.
if (TT.getArch() == Triple::x86 &&
(TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment())) {
static const struct {
const RTLIB::Libcall Op;
const RTLIB::LibcallImpl Impl;
const CallingConv::ID CC;
} LibraryCalls[] = {
{RTLIB::SDIV_I64, RTLIB::_alldiv, CallingConv::X86_StdCall},
{RTLIB::UDIV_I64, RTLIB::_aulldiv, CallingConv::X86_StdCall},
{RTLIB::SREM_I64, RTLIB::_allrem, CallingConv::X86_StdCall},
{RTLIB::UREM_I64, RTLIB::_aullrem, CallingConv::X86_StdCall},
{RTLIB::MUL_I64, RTLIB::_allmul, CallingConv::X86_StdCall},
};
for (const auto &LC : LibraryCalls) {
setLibcallImpl(LC.Op, LC.Impl);
setLibcallImplCallingConv(LC.Impl, LC.CC);
}
}
if (TT.isARM() || TT.isThumb())
setARMLibcallNames(*this, TT, FloatABI, EABIVersion);
if (!TT.isWasm()) {
// These libcalls are only available in compiler-rt, not libgcc.
if (TT.isArch32Bit()) {
setLibcallImpl(RTLIB::SHL_I128, RTLIB::Unsupported);
setLibcallImpl(RTLIB::SRL_I128, RTLIB::Unsupported);
setLibcallImpl(RTLIB::SRA_I128, RTLIB::Unsupported);
setLibcallImpl(RTLIB::MUL_I128, RTLIB::Unsupported);
setLibcallImpl(RTLIB::MULO_I64, RTLIB::Unsupported);
}
setLibcallImpl(RTLIB::MULO_I128, RTLIB::Unsupported);
}
if (TT.getArch() == Triple::ArchType::hexagon) {
setLibcallImpl(RTLIB::SDIV_I32, RTLIB::__hexagon_divsi3);
setLibcallImpl(RTLIB::SDIV_I64, RTLIB::__hexagon_divdi3);
setLibcallImpl(RTLIB::UDIV_I32, RTLIB::__hexagon_udivsi3);
setLibcallImpl(RTLIB::UDIV_I64, RTLIB::__hexagon_udivdi3);
setLibcallImpl(RTLIB::SREM_I32, RTLIB::__hexagon_modsi3);
setLibcallImpl(RTLIB::SREM_I64, RTLIB::__hexagon_moddi3);
setLibcallImpl(RTLIB::UREM_I32, RTLIB::__hexagon_umodsi3);
setLibcallImpl(RTLIB::UREM_I64, RTLIB::__hexagon_umoddi3);
const bool FastMath = HexagonEnableFastMathRuntimeCalls;
// This is the only fast library function for sqrtd.
if (FastMath)
setLibcallImpl(RTLIB::SQRT_F64, RTLIB::__hexagon_fast2_sqrtdf2);
// Prefix is: nothing for "slow-math",
// "fast2_" for V5+ fast-math double-precision
// (actually, keep fast-math and fast-math2 separate for now)
if (FastMath) {
setLibcallImpl(RTLIB::ADD_F64, RTLIB::__hexagon_fast_adddf3);
setLibcallImpl(RTLIB::SUB_F64, RTLIB::__hexagon_fast_subdf3);
setLibcallImpl(RTLIB::MUL_F64, RTLIB::__hexagon_fast_muldf3);
setLibcallImpl(RTLIB::DIV_F64, RTLIB::__hexagon_fast_divdf3);
setLibcallImpl(RTLIB::DIV_F32, RTLIB::__hexagon_fast_divsf3);
} else {
setLibcallImpl(RTLIB::ADD_F64, RTLIB::__hexagon_adddf3);
setLibcallImpl(RTLIB::SUB_F64, RTLIB::__hexagon_subdf3);
setLibcallImpl(RTLIB::MUL_F64, RTLIB::__hexagon_muldf3);
setLibcallImpl(RTLIB::DIV_F64, RTLIB::__hexagon_divdf3);
setLibcallImpl(RTLIB::DIV_F32, RTLIB::__hexagon_divsf3);
}
if (FastMath)
setLibcallImpl(RTLIB::SQRT_F32, RTLIB::__hexagon_fast2_sqrtf);
else
setLibcallImpl(RTLIB::SQRT_F32, RTLIB::__hexagon_sqrtf);
setLibcallImpl(
RTLIB::HEXAGON_MEMCPY_LIKELY_ALIGNED_MIN32BYTES_MULT8BYTES,
RTLIB::__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes);
}
if (TT.getArch() == Triple::ArchType::msp430) {
setLibcallImplCallingConv(RTLIB::__mspabi_mpyll,
CallingConv::MSP430_BUILTIN);
}
}
bool RuntimeLibcallsInfo::darwinHasExp10(const Triple &TT) {
switch (TT.getOS()) {
case Triple::MacOSX:
return !TT.isMacOSXVersionLT(10, 9);
case Triple::IOS:
return !TT.isOSVersionLT(7, 0);
case Triple::DriverKit:
case Triple::TvOS:
case Triple::WatchOS:
case Triple::XROS:
case Triple::BridgeOS:
return true;
default:
return false;
}
}