| //===- 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" |
| |
| 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 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); |
| } |
| |
| 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); |
| |
| // Early exit for targets that have fully ported to tablegen. |
| if (TT.isAMDGPU() || TT.isNVPTX() || TT.isWasm()) |
| return; |
| |
| 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); |
| |
| if (!darwinHasExp10(TT)) { |
| setLibcallImpl(RTLIB::EXP10_F32, RTLIB::Unsupported); |
| setLibcallImpl(RTLIB::EXP10_F64, RTLIB::Unsupported); |
| } |
| } |
| |
| if (TT.isOSOpenBSD()) { |
| setLibcallImpl(RTLIB::STACKPROTECTOR_CHECK_FAIL, RTLIB::Unsupported); |
| setLibcallImpl(RTLIB::STACK_SMASH_HANDLER, RTLIB::__stack_smash_handler); |
| } |
| |
| // Skip default manual processing for targets that have been fully ported to |
| // tablegen for now. Eventually the rest of this should be deleted. |
| if (TT.isX86() || TT.isAArch64() || TT.isWasm()) |
| return; |
| |
| if (TT.isARM() || TT.isThumb()) { |
| setARMLibcallNames(*this, TT, FloatABI, EABIVersion); |
| return; |
| } |
| |
| if (hasSinCos(TT)) { |
| setLibcallImpl(RTLIB::SINCOS_F32, RTLIB::sincosf); |
| setLibcallImpl(RTLIB::SINCOS_F64, RTLIB::sincos); |
| setLibcallImpl(RTLIB::SINCOS_F128, RTLIB::sincos_f128); |
| } |
| |
| // These libcalls are only available in compiler-rt, not libgcc. |
| if (TT.isArch64Bit()) { |
| setLibcallImpl(RTLIB::SHL_I128, RTLIB::__ashlti3); |
| setLibcallImpl(RTLIB::SRL_I128, RTLIB::__lshrti3); |
| setLibcallImpl(RTLIB::SRA_I128, RTLIB::__ashrti3); |
| setLibcallImpl(RTLIB::MUL_I128, RTLIB::__multi3); |
| setLibcallImpl(RTLIB::MULO_I64, RTLIB::__mulodi4); |
| } |
| |
| 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; |
| } |
| } |