#include "IceOperand.h"
#include "IceTargetLowering.h"
#include "IceTimerTree.h"
+#include "IceTypes.def"
#include "IceTypes.h"
#ifdef __clang__
case FT_Iasm:
break;
}
+// Cache up front common constants.
+#define X(tag, sizeLog2, align, elts, elty, str, rcstr) \
+ ConstZeroForType[IceType_##tag] = getConstantZeroInternal(IceType_##tag);
+ ICETYPE_TABLE;
+#undef X
+ ConstantTrue = getConstantInt1Internal(1);
+// Define runtime helper functions.
+#define X(Tag, Name) \
+ RuntimeHelperFunc[static_cast<size_t>(RuntimeHelper::H_##Tag)] = \
+ getConstantExternSym(Name);
+ RUNTIME_HELPER_FUNCTIONS_TABLE
+#undef X
TargetLowering::staticInit(this);
}
return nullptr;
}
-Constant *GlobalContext::getConstantInt1(int8_t ConstantInt1) {
+Constant *GlobalContext::getConstantInt1Internal(int8_t ConstantInt1) {
ConstantInt1 &= INT8_C(1);
return getConstPool()->Integers1.getOrAdd(this, ConstantInt1);
}
-Constant *GlobalContext::getConstantInt8(int8_t ConstantInt8) {
+Constant *GlobalContext::getConstantInt8Internal(int8_t ConstantInt8) {
return getConstPool()->Integers8.getOrAdd(this, ConstantInt8);
}
-Constant *GlobalContext::getConstantInt16(int16_t ConstantInt16) {
+Constant *GlobalContext::getConstantInt16Internal(int16_t ConstantInt16) {
return getConstPool()->Integers16.getOrAdd(this, ConstantInt16);
}
-Constant *GlobalContext::getConstantInt32(int32_t ConstantInt32) {
+Constant *GlobalContext::getConstantInt32Internal(int32_t ConstantInt32) {
return getConstPool()->Integers32.getOrAdd(this, ConstantInt32);
}
-Constant *GlobalContext::getConstantInt64(int64_t ConstantInt64) {
+Constant *GlobalContext::getConstantInt64Internal(int64_t ConstantInt64) {
return getConstPool()->Integers64.getOrAdd(this, ConstantInt64);
}
return getConstPool()->Undefs.getOrAdd(this, Ty);
}
-// All locking is done by the getConstant*() target function.
Constant *GlobalContext::getConstantZero(Type Ty) {
+ Constant *Zero = ConstZeroForType[Ty];
+ if (Zero == nullptr)
+ llvm::report_fatal_error("Unsupported constant type: " + typeIceString(Ty));
+ return Zero;
+}
+
+// All locking is done by the getConstant*() target function.
+Constant *GlobalContext::getConstantZeroInternal(Type Ty) {
switch (Ty) {
case IceType_i1:
- return getConstantInt1(0);
+ return getConstantInt1Internal(0);
case IceType_i8:
- return getConstantInt8(0);
+ return getConstantInt8Internal(0);
case IceType_i16:
- return getConstantInt16(0);
+ return getConstantInt16Internal(0);
case IceType_i32:
- return getConstantInt32(0);
+ return getConstantInt32Internal(0);
case IceType_i64:
- return getConstantInt64(0);
+ return getConstantInt64Internal(0);
case IceType_f32:
return getConstantFloat(0);
case IceType_f64:
return getConstantDouble(0);
- case IceType_v4i1:
- case IceType_v8i1:
- case IceType_v16i1:
- case IceType_v16i8:
- case IceType_v8i16:
- case IceType_v4i32:
- case IceType_v4f32: {
- IceString Str;
- llvm::raw_string_ostream BaseOS(Str);
- BaseOS << "Unsupported constant type: " << Ty;
- llvm_unreachable(BaseOS.str().c_str());
- } break;
- case IceType_void:
- case IceType_NUM:
- break;
+ default:
+ return nullptr;
}
- llvm_unreachable("Unknown type");
}
ConstantList GlobalContext::getConstantPool(Type Ty) {
#include "IceIntrinsics.h"
#include "IceRNG.h"
#include "IceSwitchLowering.h"
+#include "IceTargetLowering.def"
#include "IceThreading.h"
#include "IceTimerTree.h"
#include "IceTypes.h"
#include "IceUtils.h"
#include <array>
+#include <cassert>
#include <functional>
#include <memory>
#include <mutex>
class EmitterWorkItem;
class FuncSigType;
+// Runtime helper function IDs
+
+enum class RuntimeHelper {
+#define X(Tag, Name) H_##Tag,
+ RUNTIME_HELPER_FUNCTIONS_TABLE
+#undef X
+ H_Num
+};
+
/// LockedPtr is a way to provide automatically locked access to some object.
template <typename T> class LockedPtr {
LockedPtr() = delete;
// getConstant*() functions are not const because they might add something to
// the constant pool.
Constant *getConstantInt(Type Ty, int64_t Value);
- Constant *getConstantInt1(int8_t ConstantInt1);
- Constant *getConstantInt8(int8_t ConstantInt8);
- Constant *getConstantInt16(int16_t ConstantInt16);
- Constant *getConstantInt32(int32_t ConstantInt32);
- Constant *getConstantInt64(int64_t ConstantInt64);
+ Constant *getConstantInt1(int8_t ConstantInt1) {
+ ConstantInt1 &= INT8_C(1);
+ switch (ConstantInt1) {
+ case 0:
+ return getConstantZero(IceType_i1);
+ case 1:
+ return ConstantTrue;
+ default:
+ assert(false && "getConstantInt1 not on true/false");
+ return getConstantInt1Internal(ConstantInt1);
+ }
+ }
+ Constant *getConstantInt8(int8_t ConstantInt8) {
+ switch (ConstantInt8) {
+ case 0:
+ return getConstantZero(IceType_i8);
+ default:
+ return getConstantInt8Internal(ConstantInt8);
+ }
+ }
+ Constant *getConstantInt16(int16_t ConstantInt16) {
+ switch (ConstantInt16) {
+ case 0:
+ return getConstantZero(IceType_i16);
+ default:
+ return getConstantInt16Internal(ConstantInt16);
+ }
+ }
+ Constant *getConstantInt32(int32_t ConstantInt32) {
+ switch (ConstantInt32) {
+ case 0:
+ return getConstantZero(IceType_i32);
+ default:
+ return getConstantInt32Internal(ConstantInt32);
+ }
+ }
+ Constant *getConstantInt64(int64_t ConstantInt64) {
+ switch (ConstantInt64) {
+ case 0:
+ return getConstantZero(IceType_i64);
+ default:
+ return getConstantInt64Internal(ConstantInt64);
+ }
+ }
Constant *getConstantFloat(float Value);
Constant *getConstantDouble(double Value);
/// Returns a symbolic constant.
/// Returns a copy of the list of external symbols.
ConstantList getConstantExternSyms();
/// @}
+ Constant *getRuntimeHelperFunc(RuntimeHelper FuncID) const {
+ assert(FuncID < RuntimeHelper::H_Num);
+ Constant *Result = RuntimeHelperFunc[static_cast<size_t>(FuncID)];
+ assert(Result != nullptr && "No such runtime helper function");
+ return Result;
+ }
/// Return a locked pointer to the registered jump tables.
JumpTableDataList getJumpTables();
/// Indicates if global variable declarations can be disposed of right after
/// lowering.
bool DisposeGlobalVariablesAfterLowering = true;
-
+ Constant *ConstZeroForType[IceType_NUM];
+ Constant *ConstantTrue;
+ // Holds the constants representing each runtime helper function.
+ Constant *RuntimeHelperFunc[static_cast<size_t>(RuntimeHelper::H_Num)];
+
+ Constant *getConstantZeroInternal(Type Ty);
+ Constant *getConstantIntInternal(Type Ty, int64_t Value);
+ Constant *getConstantInt1Internal(int8_t ConstantInt1);
+ Constant *getConstantInt8Internal(int8_t ConstantInt8);
+ Constant *getConstantInt16Internal(int16_t ConstantInt16);
+ Constant *getConstantInt32Internal(int32_t ConstantInt32);
+ Constant *getConstantInt64Internal(int64_t ConstantInt64);
LockedPtr<ArenaAllocator> getAllocator() {
return LockedPtr<ArenaAllocator>(&Allocator, &AllocLock);
}
}
}
-InstCall *TargetLowering::makeHelperCall(const IceString &Name, Variable *Dest,
+InstCall *TargetLowering::makeHelperCall(RuntimeHelper FuncID, Variable *Dest,
SizeT MaxSrcs) {
constexpr bool HasTailCall = false;
- Constant *CallTarget = Ctx->getConstantExternSym(Name);
+ Constant *CallTarget = Ctx->getRuntimeHelperFunc(FuncID);
InstCall *Call =
InstCall::create(Func, MaxSrcs, Dest, CallTarget, HasTailCall);
return Call;
--- /dev/null
+//===- subzero/src/IceTargetLowering.def - Target X-macros ------*- C++ -*-===//
+//
+// The Subzero Code Generator
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines certain platform independent patterns for lowering target
+// instructions, in the form of x-macros.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SUBZERO_SRC_ICETARGETLOWERING_DEF
+#define SUBZERO_SRC_ICETARGETLOWERING_DEF
+
+// Pattern for runtime helper functions
+#define RUNTIME_HELPER_FUNCTIONS_TABLE \
+ /* tag , name */ \
+ X(bitcast_16xi1_i16, "__Sz_bitcast_16xi1_i16") \
+ X(bitcast_8xi1_i8, "__Sz_bitcast_8xi1_i8") \
+ X(bitcast_i16_16xi1, "__Sz_bitcast_i16_16xi1") \
+ X(bitcast_i8_8xi1, "__Sz_bitcast_i8_8xi1") \
+ X(call_ctpop_i32, "__popcountsi2") \
+ X(call_ctpop_i64, "__popcountdi2") \
+ X(call_longjmp, "longjmp") \
+ X(call_memcpy, "memcpy") \
+ X(call_memmove, "memmove") \
+ X(call_memset, "memset") \
+ X(call_read_tp, "__nacl_read_tp") \
+ X(call_setjmp, "setjmp") \
+ X(fptosi_f32_i64, "__Sz_fptosi_f32_i64") \
+ X(fptosi_f64_i64, "__Sz_fptosi_f64_i64") \
+ X(fptoui_4xi32_f32, "__Sz_fptoui_4xi32_f32") \
+ X(fptoui_f32_i32, "__Sz_fptoui_f32_i32") \
+ X(fptoui_f32_i64, "__Sz_fptoui_f32_i64") \
+ X(fptoui_f64_i32, "__Sz_fptoui_f64_i32") \
+ X(fptoui_f64_i64, "__Sz_fptoui_f64_i64") \
+ X(frem_f32, "fmodf") \
+ X(frem_f64, "fmod") \
+ X(sdiv_i32, "__divsi3") \
+ X(sdiv_i64, "__divdi3") \
+ X(sitofp_i64_f32, "__Sz_sitofp_i64_f32") \
+ X(sitofp_i64_f64, "__Sz_sitofp_i64_f64") \
+ X(srem_i32, "__modsi3") \
+ X(srem_i64, "__moddi3") \
+ X(udiv_i32, "__udivsi3") \
+ X(udiv_i64, "__udivdi3") \
+ X(uitofp_4xi32_4xf32, "__Sz_uitofp_4xi32_4xf32") \
+ X(uitofp_i32_f32, "__Sz_uitofp_i32_f32") \
+ X(uitofp_i32_f64, "__Sz_uitofp_i32_f64") \
+ X(uitofp_i64_f32, "__Sz_uitofp_i64_f32") \
+ X(uitofp_i64_f64, "__Sz_uitofp_i64_f64") \
+ X(urem_i32, "__umodsi3") \
+ X(urem_i64, "__umoddi3")
+//#define X(Tag, Name)
+
+#endif // SUBZERO_SRC_ICETARGETLOWERING_DEF
/// with the largest alignment need are placed in the front of the Dest list.
void sortVarsByAlignment(VarList &Dest, const VarList &Source) const;
- /// Make a call to an external helper function.
- InstCall *makeHelperCall(const IceString &Name, Variable *Dest,
- SizeT MaxSrcs);
+ InstCall *makeHelperCall(RuntimeHelper FuncID, Variable *Dest, SizeT MaxSrcs);
void _set_dest_redefined() { Context.getLastInserted()->setDestRedefined(); }
LoweringContext Context;
const SandboxType SandboxingType = ST_None;
- // Runtime helper function names
- const static constexpr char *H_bitcast_16xi1_i16 = "__Sz_bitcast_16xi1_i16";
- const static constexpr char *H_bitcast_8xi1_i8 = "__Sz_bitcast_8xi1_i8";
- const static constexpr char *H_bitcast_i16_16xi1 = "__Sz_bitcast_i16_16xi1";
- const static constexpr char *H_bitcast_i8_8xi1 = "__Sz_bitcast_i8_8xi1";
- const static constexpr char *H_call_ctpop_i32 = "__popcountsi2";
- const static constexpr char *H_call_ctpop_i64 = "__popcountdi2";
- const static constexpr char *H_call_longjmp = "longjmp";
- const static constexpr char *H_call_memcpy = "memcpy";
- const static constexpr char *H_call_memmove = "memmove";
- const static constexpr char *H_call_memset = "memset";
- const static constexpr char *H_call_read_tp = "__nacl_read_tp";
- const static constexpr char *H_call_setjmp = "setjmp";
- const static constexpr char *H_fptosi_f32_i64 = "__Sz_fptosi_f32_i64";
- const static constexpr char *H_fptosi_f64_i64 = "__Sz_fptosi_f64_i64";
- const static constexpr char *H_fptoui_4xi32_f32 = "__Sz_fptoui_4xi32_f32";
- const static constexpr char *H_fptoui_f32_i32 = "__Sz_fptoui_f32_i32";
- const static constexpr char *H_fptoui_f32_i64 = "__Sz_fptoui_f32_i64";
- const static constexpr char *H_fptoui_f64_i32 = "__Sz_fptoui_f64_i32";
- const static constexpr char *H_fptoui_f64_i64 = "__Sz_fptoui_f64_i64";
- const static constexpr char *H_frem_f32 = "fmodf";
- const static constexpr char *H_frem_f64 = "fmod";
const static constexpr char *H_getIP_prefix = "__Sz_getIP_";
- const static constexpr char *H_sdiv_i32 = "__divsi3";
- const static constexpr char *H_sdiv_i64 = "__divdi3";
- const static constexpr char *H_sitofp_i64_f32 = "__Sz_sitofp_i64_f32";
- const static constexpr char *H_sitofp_i64_f64 = "__Sz_sitofp_i64_f64";
- const static constexpr char *H_srem_i32 = "__modsi3";
- const static constexpr char *H_srem_i64 = "__moddi3";
- const static constexpr char *H_udiv_i32 = "__udivsi3";
- const static constexpr char *H_udiv_i64 = "__udivdi3";
- const static constexpr char *H_uitofp_4xi32_4xf32 = "__Sz_uitofp_4xi32_4xf32";
- const static constexpr char *H_uitofp_i32_f32 = "__Sz_uitofp_i32_f32";
- const static constexpr char *H_uitofp_i32_f64 = "__Sz_uitofp_i32_f64";
- const static constexpr char *H_uitofp_i64_f32 = "__Sz_uitofp_i64_f32";
- const static constexpr char *H_uitofp_i64_f64 = "__Sz_uitofp_i64_f64";
- const static constexpr char *H_urem_i32 = "__umodsi3";
- const static constexpr char *H_urem_i64 = "__umoddi3";
};
/// TargetDataLowering is used for "lowering" data including initializers for
// Technically, ARM has its own aeabi routines, but we can use the
// non-aeabi routine as well. LLVM uses __aeabi_ldivmod for div, but uses
// the more standard __moddi3 for rem.
- Operand *TargetHelper = nullptr;
+ RuntimeHelper HelperID = RuntimeHelper::H_Num;
switch (Op) {
default:
return;
case InstArithmetic::Udiv:
- TargetHelper = Ctx->getConstantExternSym(H_udiv_i64);
+ HelperID = RuntimeHelper::H_udiv_i64;
break;
case InstArithmetic::Sdiv:
- TargetHelper = Ctx->getConstantExternSym(H_sdiv_i64);
+ HelperID = RuntimeHelper::H_sdiv_i64;
break;
case InstArithmetic::Urem:
- TargetHelper = Ctx->getConstantExternSym(H_urem_i64);
+ HelperID = RuntimeHelper::H_urem_i64;
break;
case InstArithmetic::Srem:
- TargetHelper = Ctx->getConstantExternSym(H_srem_i64);
+ HelperID = RuntimeHelper::H_srem_i64;
break;
}
- assert(TargetHelper != nullptr);
+ Operand *TargetHelper = Ctx->getRuntimeHelperFunc(HelperID);
ARM32HelpersPreamble[TargetHelper] = &TargetARM32::preambleDivRem;
constexpr SizeT MaxArgs = 2;
auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
case IceType_i8: {
const bool HasHWDiv = hasCPUFeature(TargetARM32Features::HWDivArm);
InstCast::OpKind CastKind;
- Operand *TargetHelper;
+ RuntimeHelper HelperID = RuntimeHelper::H_Num;
switch (Op) {
default:
return;
case InstArithmetic::Udiv:
- TargetHelper =
- HasHWDiv ? nullptr : Ctx->getConstantExternSym(H_udiv_i32);
+ HelperID = HasHWDiv ? RuntimeHelper::H_Num : RuntimeHelper::H_udiv_i32;
CastKind = InstCast::Zext;
break;
case InstArithmetic::Sdiv:
- TargetHelper =
- HasHWDiv ? nullptr : Ctx->getConstantExternSym(H_sdiv_i32);
+ HelperID = HasHWDiv ? RuntimeHelper::H_Num : RuntimeHelper::H_sdiv_i32;
CastKind = InstCast::Sext;
break;
case InstArithmetic::Urem:
- TargetHelper =
- HasHWDiv ? nullptr : Ctx->getConstantExternSym(H_urem_i32);
+ HelperID = HasHWDiv ? RuntimeHelper::H_Num : RuntimeHelper::H_urem_i32;
CastKind = InstCast::Zext;
break;
case InstArithmetic::Srem:
- TargetHelper =
- HasHWDiv ? nullptr : Ctx->getConstantExternSym(H_srem_i32);
+ HelperID = HasHWDiv ? RuntimeHelper::H_Num : RuntimeHelper::H_srem_i32;
CastKind = InstCast::Sext;
break;
}
- if (TargetHelper == nullptr) {
- // TargetHelper should only ever be nullptr when the processor does not
+ if (HelperID == RuntimeHelper::H_Num) {
+ // HelperID should only ever be undefined when the processor does not
// have a hardware divider. If any other helpers are ever introduced,
// the following assert will have to be modified.
assert(HasHWDiv);
Src1 = Src1_32;
}
}
- assert(TargetHelper != nullptr);
+ Operand *TargetHelper = Ctx->getRuntimeHelperFunc(HelperID);
ARM32HelpersPreamble[TargetHelper] = &TargetARM32::preambleDivRem;
constexpr SizeT MaxArgs = 2;
auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
return;
}
constexpr SizeT MaxArgs = 2;
- Operand *TargetHelper = Ctx->getConstantExternSym(
- DestTy == IceType_f32 ? H_frem_f32 : H_frem_f64);
+ Operand *TargetHelper = Ctx->getRuntimeHelperFunc(
+ DestTy == IceType_f32 ? RuntimeHelper::H_frem_f32
+ : RuntimeHelper::H_frem_f64);
auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
NoTailCall, IsTargetHelperCall);
Call->addArg(Instr->getSrc(0));
}
const bool DestIsSigned = CastKind == InstCast::Fptosi;
const bool Src0IsF32 = isFloat32Asserting32Or64(SrcTy);
- Operand *TargetHelper = Ctx->getConstantExternSym(
- Src0IsF32 ? (DestIsSigned ? H_fptosi_f32_i64 : H_fptoui_f32_i64)
- : (DestIsSigned ? H_fptosi_f64_i64 : H_fptoui_f64_i64));
+ Operand *TargetHelper = Ctx->getRuntimeHelperFunc(
+ Src0IsF32 ? (DestIsSigned ? RuntimeHelper::H_fptosi_f32_i64
+ : RuntimeHelper::H_fptoui_f32_i64)
+ : (DestIsSigned ? RuntimeHelper::H_fptosi_f64_i64
+ : RuntimeHelper::H_fptoui_f64_i64));
static constexpr SizeT MaxArgs = 1;
auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
NoTailCall, IsTargetHelperCall);
}
const bool SourceIsSigned = CastKind == InstCast::Sitofp;
const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType());
- Operand *TargetHelper = Ctx->getConstantExternSym(
- DestIsF32 ? (SourceIsSigned ? H_sitofp_i64_f32 : H_uitofp_i64_f32)
- : (SourceIsSigned ? H_sitofp_i64_f64 : H_uitofp_i64_f64));
+ Operand *TargetHelper = Ctx->getRuntimeHelperFunc(
+ DestIsF32 ? (SourceIsSigned ? RuntimeHelper::H_sitofp_i64_f32
+ : RuntimeHelper::H_uitofp_i64_f32)
+ : (SourceIsSigned ? RuntimeHelper::H_sitofp_i64_f64
+ : RuntimeHelper::H_uitofp_i64_f64));
static constexpr SizeT MaxArgs = 1;
auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
NoTailCall, IsTargetHelperCall);
return;
}
Variable *CallDest = Dest;
- const char *HelperName = nullptr;
+ RuntimeHelper HelperID = RuntimeHelper::H_Num;
switch (DestTy) {
default:
return;
case IceType_i8:
assert(SrcTy == IceType_v8i1);
- HelperName = H_bitcast_8xi1_i8;
+ HelperID = RuntimeHelper::H_bitcast_8xi1_i8;
CallDest = Func->makeVariable(IceType_i32);
break;
case IceType_i16:
assert(SrcTy == IceType_v16i1);
- HelperName = H_bitcast_16xi1_i16;
+ HelperID = RuntimeHelper::H_bitcast_16xi1_i16;
CallDest = Func->makeVariable(IceType_i32);
break;
case IceType_v8i1: {
assert(SrcTy == IceType_i8);
- HelperName = H_bitcast_i8_8xi1;
+ HelperID = RuntimeHelper::H_bitcast_i8_8xi1;
Variable *Src0AsI32 = Func->makeVariable(stackSlotType());
// Arguments to functions are required to be at least 32 bits wide.
Context.insert<InstCast>(InstCast::Zext, Src0AsI32, Src0);
} break;
case IceType_v16i1: {
assert(SrcTy == IceType_i16);
- HelperName = H_bitcast_i16_16xi1;
+ HelperID = RuntimeHelper::H_bitcast_i16_16xi1;
Variable *Src0AsI32 = Func->makeVariable(stackSlotType());
// Arguments to functions are required to be at least 32 bits wide.
Context.insert<InstCast>(InstCast::Zext, Src0AsI32, Src0);
Src0 = Src0AsI32;
} break;
}
- assert(HelperName != nullptr);
constexpr SizeT MaxSrcs = 1;
- InstCall *Call = makeHelperCall(HelperName, CallDest, MaxSrcs);
+ InstCall *Call = makeHelperCall(HelperID, CallDest, MaxSrcs);
Call->addArg(Src0);
Context.insert(Call);
// The PNaCl ABI disallows i8/i16 return types, so truncate the helper
return;
case Intrinsics::Ctpop: {
Operand *Src0 = IntrinsicCall->getArg(0);
- Operand *TargetHelper = Ctx->getConstantExternSym(
- isInt32Asserting32Or64(Src0->getType()) ? H_call_ctpop_i32
- : H_call_ctpop_i64);
+ Operand *TargetHelper =
+ Ctx->getRuntimeHelperFunc(isInt32Asserting32Or64(Src0->getType())
+ ? RuntimeHelper::H_call_ctpop_i32
+ : RuntimeHelper::H_call_ctpop_i64);
static constexpr SizeT MaxArgs = 1;
auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
NoTailCall, IsTargetHelperCall);
case Intrinsics::Longjmp: {
static constexpr SizeT MaxArgs = 2;
static constexpr Variable *NoDest = nullptr;
- Operand *TargetHelper = Ctx->getConstantExternSym(H_call_longjmp);
+ Operand *TargetHelper =
+ Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_longjmp);
auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper,
NoTailCall, IsTargetHelperCall);
Call->addArg(IntrinsicCall->getArg(0));
// for intrinsic calls w/ a known length.
static constexpr SizeT MaxArgs = 3;
static constexpr Variable *NoDest = nullptr;
- Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memcpy);
+ Operand *TargetHelper =
+ Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_memcpy);
auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper,
NoTailCall, IsTargetHelperCall);
Call->addArg(IntrinsicCall->getArg(0));
case Intrinsics::Memmove: {
static constexpr SizeT MaxArgs = 3;
static constexpr Variable *NoDest = nullptr;
- Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memmove);
+ Operand *TargetHelper =
+ Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_memmove);
auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper,
NoTailCall, IsTargetHelperCall);
Call->addArg(IntrinsicCall->getArg(0));
// decide to use __aeabi_memset.
static constexpr SizeT MaxArgs = 3;
static constexpr Variable *NoDest = nullptr;
- Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memset);
+ Operand *TargetHelper =
+ Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_memset);
auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper,
NoTailCall, IsTargetHelperCall);
Call->addArg(IntrinsicCall->getArg(0));
return;
}
static constexpr SizeT MaxArgs = 0;
- const char *ReadTP =
- SandboxingType == ST_Nonsfi ? "__aeabi_read_tp" : H_call_read_tp;
- Operand *TargetHelper = Ctx->getConstantExternSym(ReadTP);
+ Operand *TargetHelper =
+ SandboxingType == ST_Nonsfi
+ ? Ctx->getConstantExternSym("__aeabi_read_tp")
+ : Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_read_tp);
Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, NoTailCall,
IsTargetHelperCall);
Instr->setDeleted();
}
case Intrinsics::Setjmp: {
static constexpr SizeT MaxArgs = 1;
- Operand *TargetHelper = Ctx->getConstantExternSym(H_call_setjmp);
+ Operand *TargetHelper =
+ Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_setjmp);
auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
NoTailCall, IsTargetHelperCall);
Call->addArg(IntrinsicCall->getArg(0));
return;
}
case Intrinsics::Longjmp: {
- InstCall *Call = makeHelperCall(H_call_longjmp, nullptr, 2);
+ InstCall *Call = makeHelperCall(RuntimeHelper::H_call_longjmp, nullptr, 2);
Call->addArg(Instr->getArg(0));
Call->addArg(Instr->getArg(1));
lowerCall(Call);
case Intrinsics::Memcpy: {
// In the future, we could potentially emit an inline memcpy/memset, etc.
// for intrinsic calls w/ a known length.
- InstCall *Call = makeHelperCall(H_call_memcpy, nullptr, 3);
+ InstCall *Call = makeHelperCall(RuntimeHelper::H_call_memcpy, nullptr, 3);
Call->addArg(Instr->getArg(0));
Call->addArg(Instr->getArg(1));
Call->addArg(Instr->getArg(2));
return;
}
case Intrinsics::Memmove: {
- InstCall *Call = makeHelperCall(H_call_memmove, nullptr, 3);
+ InstCall *Call = makeHelperCall(RuntimeHelper::H_call_memmove, nullptr, 3);
Call->addArg(Instr->getArg(0));
Call->addArg(Instr->getArg(1));
Call->addArg(Instr->getArg(2));
assert(ValOp->getType() == IceType_i8);
Variable *ValExt = Func->makeVariable(stackSlotType());
lowerCast(InstCast::create(Func, InstCast::Zext, ValExt, ValOp));
- InstCall *Call = makeHelperCall(H_call_memset, nullptr, 3);
+ InstCall *Call = makeHelperCall(RuntimeHelper::H_call_memset, nullptr, 3);
Call->addArg(Instr->getArg(0));
Call->addArg(ValExt);
Call->addArg(Instr->getArg(2));
if (Ctx->getFlags().getUseSandboxing()) {
UnimplementedLoweringError(this, Instr);
} else {
- InstCall *Call = makeHelperCall(H_call_read_tp, Instr->getDest(), 0);
+ InstCall *Call =
+ makeHelperCall(RuntimeHelper::H_call_read_tp, Instr->getDest(), 0);
lowerCall(Call);
}
return;
}
case Intrinsics::Setjmp: {
- InstCall *Call = makeHelperCall(H_call_setjmp, Instr->getDest(), 1);
+ InstCall *Call =
+ makeHelperCall(RuntimeHelper::H_call_setjmp, Instr->getDest(), 1);
Call->addArg(Instr->getArg(0));
lowerCall(Call);
return;
Operand *createNaClReadTPSrcOperand() {
Variable *TDB = makeReg(IceType_i32);
- InstCall *Call = makeHelperCall(H_call_read_tp, TDB, 0);
+ InstCall *Call = makeHelperCall(RuntimeHelper::H_call_read_tp, TDB, 0);
lowerCall(Call);
return TDB;
}
ValTy = IceType_i64;
}
- InstCall *Call = makeHelperCall(
- ValTy == IceType_i32 ? H_call_ctpop_i32 : H_call_ctpop_i64, T, 1);
+ InstCall *Call =
+ makeHelperCall(ValTy == IceType_i32 ? RuntimeHelper::H_call_ctpop_i32
+ : RuntimeHelper::H_call_ctpop_i64,
+ T, 1);
Call->addArg(Val);
lowerCall(Call);
// The popcount helpers always return 32-bit values, while the intrinsic's
return;
}
case Intrinsics::Longjmp: {
- InstCall *Call = makeHelperCall(H_call_longjmp, nullptr, 2);
+ InstCall *Call = makeHelperCall(RuntimeHelper::H_call_longjmp, nullptr, 2);
Call->addArg(Instr->getArg(0));
Call->addArg(Instr->getArg(1));
lowerCall(Call);
_mov(T, Src);
_mov(Dest, T);
} else {
- InstCall *Call = makeHelperCall(H_call_read_tp, Instr->getDest(), 0);
+ InstCall *Call =
+ makeHelperCall(RuntimeHelper::H_call_read_tp, Instr->getDest(), 0);
lowerCall(Call);
}
return;
}
case Intrinsics::Setjmp: {
- InstCall *Call = makeHelperCall(H_call_setjmp, Instr->getDest(), 1);
+ InstCall *Call =
+ makeHelperCall(RuntimeHelper::H_call_setjmp, Instr->getDest(), 1);
Call->addArg(Instr->getArg(0));
lowerCall(Call);
return;
}
// Fall back on a function call
- InstCall *Call = makeHelperCall(H_call_memcpy, nullptr, 3);
+ InstCall *Call = makeHelperCall(RuntimeHelper::H_call_memcpy, nullptr, 3);
Call->addArg(Dest);
Call->addArg(Src);
Call->addArg(Count);
}
// Fall back on a function call
- InstCall *Call = makeHelperCall(H_call_memmove, nullptr, 3);
+ InstCall *Call = makeHelperCall(RuntimeHelper::H_call_memmove, nullptr, 3);
Call->addArg(Dest);
Call->addArg(Src);
Call->addArg(Count);
lowerCast(InstCast::create(Func, InstCast::Zext, ValExtVar, Val));
ValExt = ValExtVar;
}
- InstCall *Call = makeHelperCall(H_call_memset, nullptr, 3);
+ InstCall *Call = makeHelperCall(RuntimeHelper::H_call_memset, nullptr, 3);
Call->addArg(Dest);
Call->addArg(ValExt);
Call->addArg(Count);
void TargetX86Base<TraitsType>::genTargetHelperCallFor(Inst *Instr) {
uint32_t StackArgumentsSize = 0;
if (auto *Arith = llvm::dyn_cast<InstArithmetic>(Instr)) {
- const char *HelperName = nullptr;
+ RuntimeHelper HelperID = RuntimeHelper::H_Num;
Variable *Dest = Arith->getDest();
Type DestTy = Dest->getType();
if (!Traits::Is64Bit && DestTy == IceType_i64) {
default:
return;
case InstArithmetic::Udiv:
- HelperName = H_udiv_i64;
+ HelperID = RuntimeHelper::H_udiv_i64;
break;
case InstArithmetic::Sdiv:
- HelperName = H_sdiv_i64;
+ HelperID = RuntimeHelper::H_sdiv_i64;
break;
case InstArithmetic::Urem:
- HelperName = H_urem_i64;
+ HelperID = RuntimeHelper::H_urem_i64;
break;
case InstArithmetic::Srem:
- HelperName = H_srem_i64;
+ HelperID = RuntimeHelper::H_srem_i64;
break;
}
} else if (isVectorType(DestTy)) {
return;
case InstArithmetic::Frem:
if (isFloat32Asserting32Or64(DestTy))
- HelperName = H_frem_f32;
+ HelperID = RuntimeHelper::H_frem_f32;
else
- HelperName = H_frem_f64;
+ HelperID = RuntimeHelper::H_frem_f64;
}
}
constexpr SizeT MaxSrcs = 2;
- InstCall *Call = makeHelperCall(HelperName, Dest, MaxSrcs);
+ InstCall *Call = makeHelperCall(HelperID, Dest, MaxSrcs);
Call->addArg(Arith->getSrc(0));
Call->addArg(Arith->getSrc(1));
StackArgumentsSize = getCallStackArgumentsSizeBytes(Call);
const Type SrcType = Src0->getType();
Variable *Dest = Cast->getDest();
const Type DestTy = Dest->getType();
- const char *HelperName = nullptr;
+ RuntimeHelper HelperID = RuntimeHelper::H_Num;
Variable *CallDest = Dest;
switch (CastKind) {
default:
return;
case InstCast::Fptosi:
if (!Traits::Is64Bit && DestTy == IceType_i64) {
- HelperName = isFloat32Asserting32Or64(SrcType) ? H_fptosi_f32_i64
- : H_fptosi_f64_i64;
+ HelperID = isFloat32Asserting32Or64(SrcType)
+ ? RuntimeHelper::H_fptosi_f32_i64
+ : RuntimeHelper::H_fptosi_f64_i64;
} else {
return;
}
case InstCast::Fptoui:
if (isVectorType(DestTy)) {
assert(DestTy == IceType_v4i32 && SrcType == IceType_v4f32);
- HelperName = H_fptoui_4xi32_f32;
+ HelperID = RuntimeHelper::H_fptoui_4xi32_f32;
} else if (DestTy == IceType_i64 ||
(!Traits::Is64Bit && DestTy == IceType_i32)) {
if (Traits::Is64Bit) {
- HelperName = isFloat32Asserting32Or64(SrcType) ? H_fptoui_f32_i64
- : H_fptoui_f64_i64;
+ HelperID = isFloat32Asserting32Or64(SrcType)
+ ? RuntimeHelper::H_fptoui_f32_i64
+ : RuntimeHelper::H_fptoui_f64_i64;
} else if (isInt32Asserting32Or64(DestTy)) {
- HelperName = isFloat32Asserting32Or64(SrcType) ? H_fptoui_f32_i32
- : H_fptoui_f64_i32;
+ HelperID = isFloat32Asserting32Or64(SrcType)
+ ? RuntimeHelper::H_fptoui_f32_i32
+ : RuntimeHelper::H_fptoui_f64_i32;
} else {
- HelperName = isFloat32Asserting32Or64(SrcType) ? H_fptoui_f32_i64
- : H_fptoui_f64_i64;
+ HelperID = isFloat32Asserting32Or64(SrcType)
+ ? RuntimeHelper::H_fptoui_f32_i64
+ : RuntimeHelper::H_fptoui_f64_i64;
}
} else {
return;
break;
case InstCast::Sitofp:
if (!Traits::Is64Bit && SrcType == IceType_i64) {
- HelperName = isFloat32Asserting32Or64(DestTy) ? H_sitofp_i64_f32
- : H_sitofp_i64_f64;
+ HelperID = isFloat32Asserting32Or64(DestTy)
+ ? RuntimeHelper::H_sitofp_i64_f32
+ : RuntimeHelper::H_sitofp_i64_f64;
} else {
return;
}
case InstCast::Uitofp:
if (isVectorType(SrcType)) {
assert(DestTy == IceType_v4f32 && SrcType == IceType_v4i32);
- HelperName = H_uitofp_4xi32_4xf32;
+ HelperID = RuntimeHelper::H_uitofp_4xi32_4xf32;
} else if (SrcType == IceType_i64 ||
(!Traits::Is64Bit && SrcType == IceType_i32)) {
if (isInt32Asserting32Or64(SrcType)) {
- HelperName = isFloat32Asserting32Or64(DestTy) ? H_uitofp_i32_f32
- : H_uitofp_i32_f64;
+ HelperID = isFloat32Asserting32Or64(DestTy)
+ ? RuntimeHelper::H_uitofp_i32_f32
+ : RuntimeHelper::H_uitofp_i32_f64;
} else {
- HelperName = isFloat32Asserting32Or64(DestTy) ? H_uitofp_i64_f32
- : H_uitofp_i64_f64;
+ HelperID = isFloat32Asserting32Or64(DestTy)
+ ? RuntimeHelper::H_uitofp_i64_f32
+ : RuntimeHelper::H_uitofp_i64_f64;
}
} else {
return;
return;
case IceType_i8:
assert(Src0->getType() == IceType_v8i1);
- HelperName = H_bitcast_8xi1_i8;
+ HelperID = RuntimeHelper::H_bitcast_8xi1_i8;
CallDest = Func->makeVariable(IceType_i32);
break;
case IceType_i16:
assert(Src0->getType() == IceType_v16i1);
- HelperName = H_bitcast_16xi1_i16;
+ HelperID = RuntimeHelper::H_bitcast_16xi1_i16;
CallDest = Func->makeVariable(IceType_i32);
break;
case IceType_v8i1: {
assert(Src0->getType() == IceType_i8);
- HelperName = H_bitcast_i8_8xi1;
+ HelperID = RuntimeHelper::H_bitcast_i8_8xi1;
Variable *Src0AsI32 = Func->makeVariable(stackSlotType());
// Arguments to functions are required to be at least 32 bits wide.
Context.insert<InstCast>(InstCast::Zext, Src0AsI32, Src0);
} break;
case IceType_v16i1: {
assert(Src0->getType() == IceType_i16);
- HelperName = H_bitcast_i16_16xi1;
+ HelperID = RuntimeHelper::H_bitcast_i16_16xi1;
Variable *Src0AsI32 = Func->makeVariable(stackSlotType());
// Arguments to functions are required to be at least 32 bits wide.
Context.insert<InstCast>(InstCast::Zext, Src0AsI32, Src0);
} break;
}
constexpr SizeT MaxSrcs = 1;
- InstCall *Call = makeHelperCall(HelperName, CallDest, MaxSrcs);
+ InstCall *Call = makeHelperCall(HelperID, CallDest, MaxSrcs);
Call->addArg(Src0);
StackArgumentsSize = getCallStackArgumentsSizeBytes(Call);
Context.insert(Call);