
This usage was hidden in XCoreSelectionDAGInfo and bypassed the usual libcall system, so define these for later use.
621 lines
28 KiB
C++
621 lines
28 KiB
C++
//===- 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_UTILS
|
|
#define GET_INIT_RUNTIME_LIBCALL_NAMES
|
|
#include "llvm/IR/RuntimeLibcalls.inc"
|
|
#undef GET_INIT_RUNTIME_LIBCALL_UTILS
|
|
#undef GET_INIT_RUNTIME_LIBCALL_NAMES
|
|
|
|
static cl::opt<bool>
|
|
HexagonEnableFastMathRuntimeCalls("hexagon-fast-math", cl::Hidden,
|
|
cl::desc("Enable Fast Math processing"));
|
|
|
|
static void setAArch64LibcallNames(RuntimeLibcallsInfo &Info,
|
|
const Triple &TT) {
|
|
#define LCALLNAMES(A, B, N) \
|
|
Info.setLibcallImpl(A##N##_RELAX, B##N##_relax); \
|
|
Info.setLibcallImpl(A##N##_ACQ, B##N##_acq); \
|
|
Info.setLibcallImpl(A##N##_REL, B##N##_rel); \
|
|
Info.setLibcallImpl(A##N##_ACQ_REL, B##N##_acq_rel);
|
|
#define LCALLNAME4(A, B) \
|
|
LCALLNAMES(A, B, 1) \
|
|
LCALLNAMES(A, B, 2) LCALLNAMES(A, B, 4) LCALLNAMES(A, B, 8)
|
|
#define LCALLNAME5(A, B) \
|
|
LCALLNAMES(A, B, 1) \
|
|
LCALLNAMES(A, B, 2) \
|
|
LCALLNAMES(A, B, 4) LCALLNAMES(A, B, 8) LCALLNAMES(A, B, 16)
|
|
|
|
if (TT.isWindowsArm64EC()) {
|
|
LCALLNAME5(RTLIB::OUTLINE_ATOMIC_CAS, RTLIB::arm64ec___aarch64_cas)
|
|
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_SWP, RTLIB::arm64ec___aarch64_swp)
|
|
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDADD, RTLIB::arm64ec___aarch64_ldadd)
|
|
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDSET, RTLIB::arm64ec___aarch64_ldset)
|
|
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDCLR, RTLIB::arm64ec___aarch64_ldclr)
|
|
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDEOR, RTLIB::arm64ec___aarch64_ldeor)
|
|
} else {
|
|
LCALLNAME5(RTLIB::OUTLINE_ATOMIC_CAS, RTLIB::__aarch64_cas)
|
|
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_SWP, RTLIB::__aarch64_swp)
|
|
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDADD, RTLIB::__aarch64_ldadd)
|
|
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDSET, RTLIB::__aarch64_ldset)
|
|
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDCLR, RTLIB::__aarch64_ldclr)
|
|
LCALLNAME4(RTLIB::OUTLINE_ATOMIC_LDEOR, RTLIB::__aarch64_ldeor)
|
|
}
|
|
#undef LCALLNAMES
|
|
#undef LCALLNAME4
|
|
#undef LCALLNAME5
|
|
}
|
|
|
|
static void setARMLibcallNames(RuntimeLibcallsInfo &Info, const Triple &TT,
|
|
FloatABI::ABIType FloatABIType,
|
|
EABI EABIVersion) {
|
|
if (!TT.isOSDarwin() && !TT.isiOS() && !TT.isWatchOS() && !TT.isDriverKit()) {
|
|
CallingConv::ID DefaultCC = FloatABIType == FloatABI::Hard
|
|
? CallingConv::ARM_AAPCS_VFP
|
|
: CallingConv::ARM_AAPCS;
|
|
for (RTLIB::Libcall LC : RTLIB::libcalls())
|
|
Info.setLibcallCallingConv(LC, DefaultCC);
|
|
}
|
|
|
|
// Register based DivRem for AEABI (RTABI 4.2)
|
|
if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
|
|
TT.isTargetMuslAEABI() || TT.isOSWindows()) {
|
|
if (TT.isOSWindows()) {
|
|
const struct {
|
|
const RTLIB::Libcall Op;
|
|
const RTLIB::LibcallImpl Impl;
|
|
const CallingConv::ID CC;
|
|
} LibraryCalls[] = {
|
|
{RTLIB::SDIVREM_I32, RTLIB::__rt_sdiv, CallingConv::ARM_AAPCS},
|
|
{RTLIB::SDIVREM_I64, RTLIB::__rt_sdiv64, CallingConv::ARM_AAPCS},
|
|
{RTLIB::UDIVREM_I32, RTLIB::__rt_udiv, CallingConv::ARM_AAPCS},
|
|
{RTLIB::UDIVREM_I64, RTLIB::__rt_udiv64, CallingConv::ARM_AAPCS},
|
|
};
|
|
|
|
for (const auto &LC : LibraryCalls) {
|
|
Info.setLibcallImpl(LC.Op, LC.Impl);
|
|
Info.setLibcallCallingConv(LC.Op, LC.CC);
|
|
}
|
|
} else {
|
|
const struct {
|
|
const RTLIB::Libcall Op;
|
|
const RTLIB::LibcallImpl Impl;
|
|
const CallingConv::ID CC;
|
|
} LibraryCalls[] = {
|
|
{RTLIB::SDIVREM_I32, RTLIB::__aeabi_idivmod, CallingConv::ARM_AAPCS},
|
|
{RTLIB::SDIVREM_I64, RTLIB::__aeabi_ldivmod, CallingConv::ARM_AAPCS},
|
|
{RTLIB::UDIVREM_I32, RTLIB::__aeabi_uidivmod, CallingConv::ARM_AAPCS},
|
|
{RTLIB::UDIVREM_I64, RTLIB::__aeabi_uldivmod, CallingConv::ARM_AAPCS},
|
|
};
|
|
|
|
for (const auto &LC : LibraryCalls) {
|
|
Info.setLibcallImpl(LC.Op, LC.Impl);
|
|
Info.setLibcallCallingConv(LC.Op, LC.CC);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (TT.isOSWindows()) {
|
|
static const struct {
|
|
const RTLIB::Libcall Op;
|
|
const RTLIB::LibcallImpl Impl;
|
|
const CallingConv::ID CC;
|
|
} LibraryCalls[] = {
|
|
{RTLIB::FPTOSINT_F32_I64, RTLIB::__stoi64, CallingConv::ARM_AAPCS_VFP},
|
|
{RTLIB::FPTOSINT_F64_I64, RTLIB::__dtoi64, CallingConv::ARM_AAPCS_VFP},
|
|
{RTLIB::FPTOUINT_F32_I64, RTLIB::__stou64, CallingConv::ARM_AAPCS_VFP},
|
|
{RTLIB::FPTOUINT_F64_I64, RTLIB::__dtou64, CallingConv::ARM_AAPCS_VFP},
|
|
{RTLIB::SINTTOFP_I64_F32, RTLIB::__i64tos, CallingConv::ARM_AAPCS_VFP},
|
|
{RTLIB::SINTTOFP_I64_F64, RTLIB::__i64tod, CallingConv::ARM_AAPCS_VFP},
|
|
{RTLIB::UINTTOFP_I64_F32, RTLIB::__u64tos, CallingConv::ARM_AAPCS_VFP},
|
|
{RTLIB::UINTTOFP_I64_F64, RTLIB::__u64tod, CallingConv::ARM_AAPCS_VFP},
|
|
};
|
|
|
|
for (const auto &LC : LibraryCalls) {
|
|
Info.setLibcallImpl(LC.Op, LC.Impl);
|
|
Info.setLibcallCallingConv(LC.Op, LC.CC);
|
|
}
|
|
}
|
|
|
|
// Use divmod compiler-rt calls for iOS 5.0 and later.
|
|
if (TT.isOSBinFormatMachO() && (!TT.isiOS() || !TT.isOSVersionLT(5, 0))) {
|
|
Info.setLibcallImpl(RTLIB::SDIVREM_I32, RTLIB::__divmodsi4);
|
|
Info.setLibcallImpl(RTLIB::UDIVREM_I32, RTLIB::__udivmodsi4);
|
|
}
|
|
}
|
|
|
|
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.setLibcallCallingConv(RTLIB::UDIV_I64, CallingConv::MSP430_BUILTIN);
|
|
Info.setLibcallCallingConv(RTLIB::UREM_I64, CallingConv::MSP430_BUILTIN);
|
|
Info.setLibcallCallingConv(RTLIB::SDIV_I64, CallingConv::MSP430_BUILTIN);
|
|
Info.setLibcallCallingConv(RTLIB::SREM_I64, CallingConv::MSP430_BUILTIN);
|
|
Info.setLibcallCallingConv(RTLIB::ADD_F64, CallingConv::MSP430_BUILTIN);
|
|
Info.setLibcallCallingConv(RTLIB::SUB_F64, CallingConv::MSP430_BUILTIN);
|
|
Info.setLibcallCallingConv(RTLIB::MUL_F64, CallingConv::MSP430_BUILTIN);
|
|
Info.setLibcallCallingConv(RTLIB::DIV_F64, CallingConv::MSP430_BUILTIN);
|
|
Info.setLibcallCallingConv(RTLIB::OEQ_F64, CallingConv::MSP430_BUILTIN);
|
|
Info.setLibcallCallingConv(RTLIB::UNE_F64, CallingConv::MSP430_BUILTIN);
|
|
Info.setLibcallCallingConv(RTLIB::OGE_F64, CallingConv::MSP430_BUILTIN);
|
|
Info.setLibcallCallingConv(RTLIB::OLT_F64, CallingConv::MSP430_BUILTIN);
|
|
Info.setLibcallCallingConv(RTLIB::OLE_F64, CallingConv::MSP430_BUILTIN);
|
|
Info.setLibcallCallingConv(RTLIB::OGT_F64, 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;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::OEQ_F128] = CmpInst::ICMP_EQ;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::OEQ_PPCF128] = CmpInst::ICMP_EQ;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::UNE_F32] = CmpInst::ICMP_NE;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::UNE_F64] = CmpInst::ICMP_NE;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::UNE_F128] = CmpInst::ICMP_NE;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::UNE_PPCF128] = CmpInst::ICMP_NE;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::OGE_F32] = CmpInst::ICMP_SGE;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::OGE_F64] = CmpInst::ICMP_SGE;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::OGE_F128] = CmpInst::ICMP_SGE;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::OGE_PPCF128] = CmpInst::ICMP_SGE;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::OLT_F32] = CmpInst::ICMP_SLT;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::OLT_F64] = CmpInst::ICMP_SLT;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::OLT_F128] = CmpInst::ICMP_SLT;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::OLT_PPCF128] = CmpInst::ICMP_SLT;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::OLE_F32] = CmpInst::ICMP_SLE;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::OLE_F64] = CmpInst::ICMP_SLE;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::OLE_F128] = CmpInst::ICMP_SLE;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::OLE_PPCF128] = CmpInst::ICMP_SLE;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::OGT_F32] = CmpInst::ICMP_SGT;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::OGT_F64] = CmpInst::ICMP_SGT;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::OGT_F128] = CmpInst::ICMP_SGT;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::OGT_PPCF128] = CmpInst::ICMP_SGT;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::UO_F32] = CmpInst::ICMP_NE;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::UO_F64] = CmpInst::ICMP_NE;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::UO_F128] = CmpInst::ICMP_NE;
|
|
SoftFloatCompareLibcallPredicates[RTLIB::UO_PPCF128] = CmpInst::ICMP_NE;
|
|
}
|
|
|
|
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) {
|
|
// Use the f128 variants of math functions on x86
|
|
if (TT.isX86() && TT.isGNUEnvironment())
|
|
setLongDoubleIsF128Libm(*this, /*FiniteOnlyFuncs=*/true);
|
|
|
|
if (TT.isX86() || TT.isVE()) {
|
|
if (ExceptionModel == ExceptionHandling::SjLj)
|
|
setLibcallImpl(RTLIB::UNWIND_RESUME, RTLIB::_Unwind_SjLj_Resume);
|
|
}
|
|
|
|
if (TT.isPPC()) {
|
|
setPPCLibCallNameOverrides();
|
|
|
|
// TODO: Do the finite only functions exist?
|
|
setLongDoubleIsF128Libm(*this, /*FiniteOnlyFuncs=*/false);
|
|
|
|
// TODO: Tablegen predicate support
|
|
if (TT.isOSAIX()) {
|
|
if (TT.isPPC64()) {
|
|
setLibcallImpl(RTLIB::MEMCPY, RTLIB::Unsupported);
|
|
setLibcallImpl(RTLIB::MEMMOVE, RTLIB::___memmove64);
|
|
setLibcallImpl(RTLIB::MEMSET, RTLIB::___memset64);
|
|
setLibcallImpl(RTLIB::BZERO, RTLIB::___bzero64);
|
|
} else {
|
|
setLibcallImpl(RTLIB::MEMCPY, RTLIB::Unsupported);
|
|
setLibcallImpl(RTLIB::MEMMOVE, RTLIB::___memmove);
|
|
setLibcallImpl(RTLIB::MEMSET, RTLIB::___memset);
|
|
setLibcallImpl(RTLIB::BZERO, RTLIB::___bzero);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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);
|
|
} else if (TT.isAArch64())
|
|
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()) {
|
|
setLibcallCallingConv(RTLIB::SINCOS_STRET_F32,
|
|
CallingConv::ARM_AAPCS_VFP);
|
|
setLibcallCallingConv(RTLIB::SINCOS_STRET_F64,
|
|
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);
|
|
}
|
|
|
|
// Disable most libcalls on AMDGPU and NVPTX.
|
|
if (TT.isAMDGPU() || TT.isNVPTX()) {
|
|
for (RTLIB::Libcall LC : RTLIB::libcalls()) {
|
|
if (!isAtomicLibCall(LC))
|
|
setLibcallImpl(LC, 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);
|
|
setLibcallCallingConv(LC.Op, LC.CC);
|
|
}
|
|
}
|
|
|
|
if (TT.isAArch64()) {
|
|
if (TT.isWindowsArm64EC())
|
|
setWindowsArm64LibCallNameOverrides();
|
|
setAArch64LibcallNames(*this, TT);
|
|
} else if (TT.isARM() || TT.isThumb()) {
|
|
setARMLibcallNames(*this, TT, FloatABI, EABIVersion);
|
|
} else if (TT.getArch() == Triple::ArchType::avr) {
|
|
// Division rtlib functions (not supported), use divmod functions instead
|
|
setLibcallImpl(RTLIB::SDIV_I8, RTLIB::Unsupported);
|
|
setLibcallImpl(RTLIB::SDIV_I16, RTLIB::Unsupported);
|
|
setLibcallImpl(RTLIB::SDIV_I32, RTLIB::Unsupported);
|
|
setLibcallImpl(RTLIB::UDIV_I8, RTLIB::Unsupported);
|
|
setLibcallImpl(RTLIB::UDIV_I16, RTLIB::Unsupported);
|
|
setLibcallImpl(RTLIB::UDIV_I32, RTLIB::Unsupported);
|
|
|
|
// Modulus rtlib functions (not supported), use divmod functions instead
|
|
setLibcallImpl(RTLIB::SREM_I8, RTLIB::Unsupported);
|
|
setLibcallImpl(RTLIB::SREM_I16, RTLIB::Unsupported);
|
|
setLibcallImpl(RTLIB::SREM_I32, RTLIB::Unsupported);
|
|
setLibcallImpl(RTLIB::UREM_I8, RTLIB::Unsupported);
|
|
setLibcallImpl(RTLIB::UREM_I16, RTLIB::Unsupported);
|
|
setLibcallImpl(RTLIB::UREM_I32, RTLIB::Unsupported);
|
|
|
|
// Division and modulus rtlib functions
|
|
setLibcallImpl(RTLIB::SDIVREM_I8, RTLIB::__divmodqi4);
|
|
setLibcallImpl(RTLIB::SDIVREM_I16, RTLIB::__divmodhi4);
|
|
setLibcallImpl(RTLIB::SDIVREM_I32, RTLIB::__divmodsi4);
|
|
setLibcallImpl(RTLIB::UDIVREM_I8, RTLIB::__udivmodqi4);
|
|
setLibcallImpl(RTLIB::UDIVREM_I16, RTLIB::__udivmodhi4);
|
|
setLibcallImpl(RTLIB::UDIVREM_I32, RTLIB::__udivmodsi4);
|
|
|
|
// Several of the runtime library functions use a special calling conv
|
|
setLibcallCallingConv(RTLIB::SDIVREM_I8, CallingConv::AVR_BUILTIN);
|
|
setLibcallCallingConv(RTLIB::SDIVREM_I16, CallingConv::AVR_BUILTIN);
|
|
setLibcallCallingConv(RTLIB::UDIVREM_I8, CallingConv::AVR_BUILTIN);
|
|
setLibcallCallingConv(RTLIB::UDIVREM_I16, CallingConv::AVR_BUILTIN);
|
|
|
|
// Trigonometric rtlib functions
|
|
setLibcallImpl(RTLIB::SIN_F32, RTLIB::avr_sin);
|
|
setLibcallImpl(RTLIB::COS_F32, RTLIB::avr_cos);
|
|
}
|
|
|
|
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);
|
|
} else {
|
|
// Define the emscripten name for return address helper.
|
|
// TODO: when implementing other Wasm backends, make this generic or only do
|
|
// this on emscripten depending on what they end up doing.
|
|
setLibcallImpl(RTLIB::RETURN_ADDRESS, RTLIB::emscripten_return_address);
|
|
}
|
|
|
|
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)
|
|
setMSP430Libcalls(*this, TT);
|
|
|
|
if (TT.isSystemZ() && TT.isOSzOS())
|
|
setZOSLibCallNameOverrides();
|
|
|
|
if (TT.getArch() == Triple::ArchType::xcore)
|
|
setLibcallImpl(RTLIB::MEMCPY_ALIGN_4, RTLIB::__memcpy_4);
|
|
}
|
|
|
|
bool RuntimeLibcallsInfo::darwinHasExp10(const Triple &TT) {
|
|
assert(TT.isOSDarwin() && "should be called with darwin triple");
|
|
|
|
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;
|
|
}
|
|
}
|