aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/RuntimeLibcalls.cpp
blob: b1864897dafa6816a7c61aadf1f688b9faddf32f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//===- 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/ADT/StringTable.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;
  }
}