mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
1280 lines
34 KiB
C
1280 lines
34 KiB
C
#include <llvm-c/Target.h>
|
|
#include <llvm-c/TargetMachine.h>
|
|
#include <llvm-c/Core.h>
|
|
#include <target_info/target_info.h>
|
|
#include "compiler_internal.h"
|
|
|
|
static unsigned arch_pointer_bit_width(OsType os, ArchType arch);
|
|
static ArchType arch_from_llvm_string(const char *string);
|
|
static EnvironmentType environment_type_from_llvm_string(const char *string);
|
|
static bool arch_is_supported(ArchType arch);
|
|
static unsigned os_target_c_type_bits(OsType os, ArchType arch, CType type);
|
|
static unsigned os_target_alignment_of_int(OsType os, ArchType arch, int bits);
|
|
static unsigned os_target_alignment_of_float(OsType os, ArchType arch, int bits);
|
|
static OsType os_from_llvm_string(const char *string);
|
|
static VendorType vendor_from_llvm_string(const char *string);
|
|
static ObjectFormatType object_format_from_os(OsType os);
|
|
static unsigned os_target_supports_int128(OsType os, ArchType arch);
|
|
static unsigned os_target_supports_float16(OsType os, ArchType arch);
|
|
static unsigned os_target_supports_float128(OsType os, ArchType arch);
|
|
static unsigned os_target_supports_vec(OsType os, ArchType arch, int bits, bool is_int);
|
|
static bool os_requires_libc(OsType os);
|
|
|
|
|
|
PlatformTarget platform_target = {};
|
|
|
|
int target_alloca_addr_space()
|
|
{
|
|
return platform_target.alloca_address_space;
|
|
}
|
|
|
|
static void type_dump(LLVMTargetDataRef llvm_target_data, LLVMTypeRef type)
|
|
{
|
|
unsigned size = LLVMSizeOfTypeInBits(llvm_target_data, type);
|
|
unsigned abialign = LLVMABIAlignmentOfType(llvm_target_data, type) * 8;
|
|
unsigned prefalign = LLVMPreferredAlignmentOfType(llvm_target_data, type) * 8;
|
|
|
|
printf(" | %-3d %-3d %-3d", size, abialign, prefalign);
|
|
}
|
|
|
|
|
|
|
|
void llvm_dump(void)
|
|
{
|
|
static char* archs[] = {
|
|
"unknown",
|
|
"i386",
|
|
"aarch64",
|
|
"arm64",
|
|
"aarch64_be",
|
|
"aarch64_32",
|
|
"arm64_32",
|
|
"arm",
|
|
"xscale",
|
|
"armeb",
|
|
"xscaleeb",
|
|
"arc",
|
|
"avr",
|
|
"bpfeb",
|
|
"bpfel",
|
|
"hexagon",
|
|
"mips",
|
|
"mipseb",
|
|
"mipsallegrex",
|
|
"mipsisa32r6",
|
|
"mipsr6",
|
|
"mipsel",
|
|
"mipsallegrexel",
|
|
"mipsisa32r6el",
|
|
"mipsr6el",
|
|
"mips64",
|
|
"mips64eb",
|
|
"mipsn32",
|
|
"mipsisa64r6",
|
|
"mips64r6",
|
|
"mipsn32r6",
|
|
"mips64el",
|
|
"mipsn32el",
|
|
"mipsisa64r6el",
|
|
"mips64r6el",
|
|
"mipsn32r6el",
|
|
"msp430",
|
|
"powerpc64",
|
|
"ppu",
|
|
"ppc64",
|
|
"powerpc64le",
|
|
"ppc64le",
|
|
"powerpc",
|
|
"ppc",
|
|
"ppc32",
|
|
"r600",
|
|
"amdgcn",
|
|
"riscv32",
|
|
"riscv64",
|
|
"sparc",
|
|
"sparcel",
|
|
"sparcv9",
|
|
"sparc64",
|
|
"systemz",
|
|
"s390x",
|
|
"tce",
|
|
"tcele",
|
|
"thumb",
|
|
"thumbeb",
|
|
"x86_64",
|
|
"amd64",
|
|
"x86_64h",
|
|
"xcore",
|
|
"nvptx",
|
|
"nvptx64",
|
|
"le32",
|
|
"le64",
|
|
"amdil",
|
|
"amdil64",
|
|
"hsail",
|
|
"hsail64",
|
|
"spir",
|
|
"spir64",
|
|
"kalimba",
|
|
"lanai",
|
|
"shave",
|
|
"wasm32",
|
|
"wasm64",
|
|
"renderscript32",
|
|
"renderscript64",
|
|
};
|
|
static char* os[] = {
|
|
"unknown",
|
|
"ananas",
|
|
"cloudabi",
|
|
"darwin",
|
|
"dragonfly",
|
|
"freebsd",
|
|
"fuchsia",
|
|
"ios",
|
|
"kfreebsd",
|
|
"linux",
|
|
"lv2",
|
|
"macosx",
|
|
"netbsd",
|
|
"openbsd",
|
|
"solaris",
|
|
"windows",
|
|
"haiku",
|
|
"minix",
|
|
"rtems",
|
|
"nacl",
|
|
"cnk",
|
|
"aix",
|
|
"cuda",
|
|
"nvcl",
|
|
"amdhsa",
|
|
"ps4",
|
|
"elfiamcu",
|
|
"tvos",
|
|
"watchos",
|
|
"mesa3d",
|
|
"contiki",
|
|
"amdpal",
|
|
"hermit",
|
|
"hurd",
|
|
"wasi",
|
|
"emscripten",
|
|
};
|
|
for (unsigned i = 0; i < sizeof(archs) / sizeof(void*); i++)
|
|
{
|
|
printf("----%s---\n", archs[i]);
|
|
printf("os end | ptr | i8 | i16 | i32 | i64 | i128 "
|
|
"| f16 | f32 | f64 | f128 "
|
|
"\n");
|
|
for (unsigned j = 0; j < sizeof(os) / sizeof(void*); j++)
|
|
{
|
|
if ((i >= 37 && i <= 44) && (j == 3 || j == 7 || j == 11 || j == 27 || j == 28))
|
|
{
|
|
continue; // Skip darwin on PowerPC
|
|
}
|
|
LLVMTargetRef target;
|
|
char *error;
|
|
char *triplet = NULL;
|
|
(void)asprintf(&triplet, "%s-unknown-%s-unknown", archs[i], os[j]);
|
|
if (LLVMGetTargetFromTriple(triplet, &target, &error)) continue;
|
|
LLVMTargetMachineRef machine = NULL;
|
|
if (!(machine = LLVMCreateTargetMachine(target, triplet, "", "", 0, LLVMRelocDefault, LLVMCodeModelDefault))) {
|
|
error_exit("Failed to create target machine.");
|
|
}
|
|
LLVMTargetDataRef llvm_target_data = LLVMCreateTargetDataLayout(machine);
|
|
|
|
|
|
printf("%-10s %-3s ", os[j],LLVMByteOrder(llvm_target_data) == LLVMBigEndian ? "BE" : "LE");
|
|
type_dump(llvm_target_data, LLVMPointerType(LLVMInt8Type(), 0));
|
|
type_dump(llvm_target_data, LLVMInt8Type());
|
|
type_dump(llvm_target_data, LLVMInt16Type());
|
|
type_dump(llvm_target_data, LLVMInt32Type());
|
|
type_dump(llvm_target_data, LLVMInt64Type());
|
|
type_dump(llvm_target_data, LLVMInt128Type());
|
|
type_dump(llvm_target_data, LLVMHalfType());
|
|
type_dump(llvm_target_data, LLVMFloatType());
|
|
type_dump(llvm_target_data, LLVMDoubleType());
|
|
type_dump(llvm_target_data, LLVMFP128Type());
|
|
printf("\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static inline bool os_is_apple(OsType os_type)
|
|
{
|
|
return os_type == OS_TYPE_TVOS || os_type == OS_TYPE_WATCHOS ||
|
|
os_type == OS_TYPE_MACOSX || os_type == OS_TYPE_IOS;
|
|
}
|
|
|
|
static inline void target_setup_arm_abi(void)
|
|
{
|
|
platform_target.abi = ABI_ARM;
|
|
if (platform_target.os)
|
|
{
|
|
platform_target.arm.is_win32 = true;
|
|
platform_target.arm.variant = ARM_AAPCS;
|
|
platform_target.arm.abi_variant = ARM_ABI_AAPCS16_VFP;
|
|
return;
|
|
}
|
|
if (platform_target.object_format == OBJ_FORMAT_MACHO)
|
|
{
|
|
if (platform_target.environment_type == ENV_TYPE_EABI
|
|
|| platform_target.os == OS_TYPE_UNKNOWN /* or is M */)
|
|
{
|
|
platform_target.arm.variant = ARM_AAPCS;
|
|
return;
|
|
}
|
|
// TODO
|
|
if (/* is watch abi */ false)
|
|
{
|
|
platform_target.arm.variant = ARM_AAPCS16;
|
|
goto SET_ABI;
|
|
}
|
|
platform_target.arm.variant = ARM_APCS_GNU;
|
|
goto SET_ABI;
|
|
}
|
|
switch (platform_target.environment_type)
|
|
{
|
|
case ENV_TYPE_ANDROID:
|
|
case ENV_TYPE_GNUEABI:
|
|
case ENV_TYPE_GNUEABIHF:
|
|
case ENV_TYPE_MUSLEABI:
|
|
case ENV_TYPE_MUSLEABIHF:
|
|
platform_target.arm.variant = ARM_AAPCS_LINUX;
|
|
goto SET_ABI;
|
|
case ENV_TYPE_EABI:
|
|
case ENV_TYPE_EABIHF:
|
|
platform_target.arm.variant = ARM_AAPCS;
|
|
goto SET_ABI;
|
|
case ENV_TYPE_GNU:
|
|
platform_target.arm.variant = ARM_APCS_GNU;
|
|
goto SET_ABI;
|
|
default:
|
|
break;
|
|
}
|
|
switch (platform_target.os)
|
|
{
|
|
case OS_TYPE_NETBSD:
|
|
platform_target.arm.variant = ARM_APCS_GNU;
|
|
break;
|
|
case OS_TYPE_OPENBSD:
|
|
platform_target.arm.variant = ARM_AAPCS_LINUX;
|
|
break;
|
|
default:
|
|
platform_target.arm.variant = ARM_AAPCS;
|
|
break;
|
|
}
|
|
SET_ABI:
|
|
switch (platform_target.arm.variant)
|
|
{
|
|
case ARM_APCS_GNU:
|
|
platform_target.arm.abi_variant = ARM_ABI_APCS;
|
|
return;
|
|
case ARM_AAPCS16:
|
|
platform_target.arm.abi_variant = ARM_ABI_AAPCS16_VFP;
|
|
return;
|
|
case ARM_AAPCS:
|
|
case ARM_AAPCS_LINUX:
|
|
if (platform_target.float_abi == FLOAT_ABI_HARD ||
|
|
(platform_target.float_abi != FLOAT_ABI_SOFT &&
|
|
(platform_target.environment_type == ENV_TYPE_GNUEABIHF ||
|
|
platform_target.environment_type == ENV_TYPE_MUSLEABIHF ||
|
|
platform_target.environment_type == ENV_TYPE_EABIHF)))
|
|
{
|
|
platform_target.arm.abi_variant = ARM_ABI_AAPCS_VFP;
|
|
return;
|
|
}
|
|
platform_target.arm.abi_variant = ARM_ABI_AAPCS;
|
|
break;
|
|
}
|
|
UNREACHABLE
|
|
}
|
|
|
|
static inline void target_setup_x86_abi(BuildTarget *target)
|
|
{
|
|
platform_target.abi = ABI_X86;
|
|
platform_target.x86.is_win_api = platform_target.os == OS_TYPE_WIN32;
|
|
if (os_is_apple(platform_target.os))
|
|
{
|
|
platform_target.x86.is_darwin_vector_abi = true;
|
|
}
|
|
platform_target.x86.use_soft_float = platform_target.float_abi == FLOAT_ABI_SOFT;
|
|
// Build target override.
|
|
if (target->feature.soft_float != SOFT_FLOAT_DEFAULT)
|
|
{
|
|
platform_target.x86.use_soft_float = target->feature.soft_float == SOFT_FLOAT_YES;
|
|
}
|
|
|
|
platform_target.x86.is_win32_float_struct_abi = platform_target.os == OS_TYPE_WIN32;
|
|
platform_target.x86.is_mcu_api = platform_target.os == OS_TYPE_ELFIAMCU;
|
|
if (platform_target.environment_type == ENV_TYPE_CYGNUS
|
|
|| platform_target.environment_type == ENV_TYPE_GNU)
|
|
{
|
|
platform_target.x86.is_win32_float_struct_abi = false;
|
|
}
|
|
switch (platform_target.os)
|
|
{
|
|
case OS_TYPE_MACOSX:
|
|
case OS_TYPE_IOS:
|
|
case OS_TYPE_WATCHOS:
|
|
case OS_TYPE_TVOS:
|
|
case OS_TYPE_DRAGON_FLY:
|
|
case OS_TYPE_FREE_BSD:
|
|
case OS_TYPE_ELFIAMCU:
|
|
case OS_TYPE_OPENBSD:
|
|
case OS_TYPE_WIN32:
|
|
platform_target.x86.return_small_struct_in_reg_abi = true;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (target->feature.struct_return != STRUCT_RETURN_DEFAULT)
|
|
{
|
|
platform_target.x86.return_small_struct_in_reg_abi = target->feature.struct_return == STRUCT_RETURN_REG;
|
|
}
|
|
}
|
|
|
|
|
|
static inline void target_setup_x64_abi(void)
|
|
{
|
|
platform_target.abi = ABI_X64;
|
|
platform_target.x64.avx_level = AVX;
|
|
platform_target.x64.is_win64 = platform_target.os == OS_TYPE_WIN32;
|
|
if (platform_target.environment_type == ENV_TYPE_GNU)
|
|
{
|
|
platform_target.x64.is_mingw64 = platform_target.x64.is_win64;
|
|
}
|
|
if (platform_target.os == OS_TYPE_LINUX || platform_target.os == OS_TYPE_NETBSD)
|
|
{
|
|
platform_target.x64.pass_int128_vector_in_mem = true;
|
|
}
|
|
}
|
|
|
|
static char *arch_to_target_triple[ARCH_OS_TARGET_LAST + 1] = {
|
|
[X86_FREEBSD] = "i386-unknown-freebsd",
|
|
[X86_OPENBSD] = "i386-unknown-openbsd",
|
|
[X86_MCU] = "i386-pc-elfiamcu",
|
|
[X86_WINDOWS] = "i386-pc-win32",
|
|
[X86_LINUX] = "i386-unknown-linux",
|
|
[X64_DARWIN] = "x86_64-apple-darwin",
|
|
[X64_LINUX] = "x86_64-unknown-linux-gnu",
|
|
[X64_WINDOWS] = "x86_64-pc-windows-msvc",
|
|
[X64_WINDOWS_GNU] = "x86_64-pc-windows-gnu",
|
|
[X64_NETBSD] = "x86_64-unknown-netbsd",
|
|
[AARCH64_LINUX] = "aarch64-unknown-linux-gnu",
|
|
[AARCH64_DARWIN] = "aarch64-apple-darwin",
|
|
[RISCV32_LINUX] = "riscv32-unknown-linux",
|
|
[RISCV64_LINUX] = "riscv32-unknown-linux",
|
|
[WASM32] = "wasm32-unknown-unknown",
|
|
[WASM64] = "wasm64-unknown-unknown",
|
|
};
|
|
|
|
|
|
|
|
void target_destroy()
|
|
{
|
|
assert(platform_target.machine);
|
|
LLVMDisposeTargetMachine(platform_target.machine);
|
|
}
|
|
|
|
void *target_target()
|
|
{
|
|
return platform_target.target;
|
|
}
|
|
|
|
void *target_machine()
|
|
{
|
|
return platform_target.machine;
|
|
}
|
|
void *target_data_layout()
|
|
{
|
|
return platform_target.llvm_data_layout;
|
|
}
|
|
|
|
static bool arch_is_supported(ArchType arch)
|
|
{
|
|
switch (arch)
|
|
{
|
|
case ARCH_TYPE_X86_64:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
static ArchType arch_from_llvm_string(const char *string)
|
|
{
|
|
#define STRCASE(_str, _arch) if (strcmp(string, _str) == 0) return _arch;
|
|
STRCASE("i386", ARCH_TYPE_X86)
|
|
STRCASE("i486", ARCH_TYPE_X86)
|
|
STRCASE("i586", ARCH_TYPE_X86)
|
|
STRCASE("i686", ARCH_TYPE_X86)
|
|
STRCASE("i786", ARCH_TYPE_X86)
|
|
STRCASE("i886", ARCH_TYPE_X86)
|
|
STRCASE("i986", ARCH_TYPE_X86)
|
|
STRCASE("aarch64", ARCH_TYPE_AARCH64)
|
|
STRCASE("arm64", ARCH_TYPE_AARCH64)
|
|
STRCASE("aarch64_be", ARCH_TYPE_AARCH64_BE)
|
|
STRCASE("aarch64_32", ARCH_TYPE_AARCH64_32)
|
|
STRCASE("arm64_32", ARCH_TYPE_AARCH64_32)
|
|
STRCASE("arm", ARCH_TYPE_ARM)
|
|
STRCASE("xscale", ARCH_TYPE_ARM)
|
|
STRCASE("armeb", ARCH_TYPE_ARMB)
|
|
STRCASE("xscaleeb", ARCH_TYPE_ARMB)
|
|
STRCASE("arc", ARCH_TYPE_ARC)
|
|
STRCASE("avr", ARCH_TYPE_AVR)
|
|
STRCASE("bpfeb", ARCH_TYPE_BPFEB)
|
|
STRCASE("bpfel", ARCH_TYPE_BPFEL)
|
|
STRCASE("hexagon", ARCH_TYPE_HEXAGON)
|
|
STRCASE("mips", ARCH_TYPE_MIPS)
|
|
STRCASE("mipseb", ARCH_TYPE_MIPS)
|
|
STRCASE("mipsallegrex", ARCH_TYPE_MIPS)
|
|
STRCASE("mipsisa32r6", ARCH_TYPE_MIPS)
|
|
STRCASE("mipsr6", ARCH_TYPE_MIPS)
|
|
STRCASE("mipsel", ARCH_TYPE_MIPSEL)
|
|
STRCASE("mipsallegrexel", ARCH_TYPE_MIPSEL)
|
|
STRCASE("mipsisa32r6el", ARCH_TYPE_MIPSEL)
|
|
STRCASE("mipsr6el", ARCH_TYPE_MIPSEL)
|
|
STRCASE("mips64", ARCH_TYPE_MIPS64)
|
|
STRCASE("mips64eb", ARCH_TYPE_MIPS64)
|
|
STRCASE("mipsn32", ARCH_TYPE_MIPS64)
|
|
STRCASE("mipsisa64r6", ARCH_TYPE_MIPS64)
|
|
STRCASE("mips64r6", ARCH_TYPE_MIPS64)
|
|
STRCASE("mipsn32r6", ARCH_TYPE_MIPS64)
|
|
STRCASE("mips64el", ARCH_TYPE_MIPS64EL)
|
|
STRCASE("mipsn32el", ARCH_TYPE_MIPS64EL)
|
|
STRCASE("mipsisa64r6el", ARCH_TYPE_MIPS64EL)
|
|
STRCASE("mips64r6el", ARCH_TYPE_MIPS64EL)
|
|
STRCASE("mipsn32r6el", ARCH_TYPE_MIPS64EL)
|
|
STRCASE("msp430", ARCH_TYPE_MSP430)
|
|
STRCASE("powerpc64", ARCH_TYPE_PPC64)
|
|
STRCASE("ppu", ARCH_TYPE_PPC64)
|
|
STRCASE("ppc64", ARCH_TYPE_PPC64)
|
|
STRCASE("powerpc64le", ARCH_TYPE_PPC64LE)
|
|
STRCASE("ppc64le", ARCH_TYPE_PPC64LE)
|
|
STRCASE("powerpc", ARCH_TYPE_PPC)
|
|
STRCASE("ppc", ARCH_TYPE_PPC)
|
|
STRCASE("ppc32", ARCH_TYPE_PPC)
|
|
STRCASE("r600", ARCH_TYPE_R600)
|
|
STRCASE("amdgcn", ARCH_TYPE_AMDGCN)
|
|
STRCASE("riscv32", ARCH_TYPE_RISCV32)
|
|
STRCASE("riscv64", ARCH_TYPE_RISCV64)
|
|
STRCASE("sparc", ARCH_TYPE_SPARC)
|
|
STRCASE("sparcel", ARCH_TYPE_SPARCEL)
|
|
STRCASE("sparcv9", ARCH_TYPE_SPARCV9)
|
|
STRCASE("sparc64", ARCH_TYPE_SPARCV9)
|
|
STRCASE("systemz", ARCH_TYPE_SYSTEMZ)
|
|
STRCASE("s390x", ARCH_TYPE_SYSTEMZ)
|
|
STRCASE("tce", ARCH_TYPE_TCE)
|
|
STRCASE("tcele", ARCH_TYPE_TCELE)
|
|
STRCASE("thumb", ARCH_TYPE_THUMB)
|
|
STRCASE("thumbeb", ARCH_TYPE_THUMBEB)
|
|
STRCASE("x86_64", ARCH_TYPE_X86_64)
|
|
STRCASE("amd64", ARCH_TYPE_X86_64)
|
|
STRCASE("x86_64h", ARCH_TYPE_X86_64)
|
|
STRCASE("xcore", ARCH_TYPE_XCORE)
|
|
STRCASE("nvptx", ARCH_TYPE_NVPTX)
|
|
STRCASE("nvptx64", ARCH_TYPE_NVPTX64)
|
|
STRCASE("le32", ARCH_TYPE_LE32)
|
|
STRCASE("le64", ARCH_TYPE_LE64)
|
|
STRCASE("amdil", ARCH_TYPE_AMDIL)
|
|
STRCASE("amdil64", ARCH_TYPE_AMDIL64)
|
|
STRCASE("hsail", ARCH_TYPE_HSAIL)
|
|
STRCASE("hsail64", ARCH_TYPE_HSAIL64)
|
|
STRCASE("spir", ARCH_TYPE_SPIR)
|
|
STRCASE("spir64", ARCH_TYPE_SPIR64)
|
|
STRCASE("kalimba", ARCH_TYPE_KALIMBA)
|
|
STRCASE("lanai", ARCH_TYPE_LANAI)
|
|
STRCASE("shave", ARCH_TYPE_SHAVE)
|
|
STRCASE("wasm32", ARCH_TYPE_WASM32)
|
|
STRCASE("wasm64", ARCH_TYPE_WASM64)
|
|
STRCASE("renderscript32", ARCH_TYPE_RSCRIPT32)
|
|
STRCASE("renderscript64", ARCH_TYPE_RSCRIPT64)
|
|
return ARCH_TYPE_UNKNOWN;
|
|
#undef STRCASE
|
|
// TODO parse arm & bpf names
|
|
}
|
|
|
|
static EnvironmentType environment_type_from_llvm_string(const char *string)
|
|
{
|
|
#define STRCASE(_str, _arch) if (strcmp(string, _str) == 0) return _arch;
|
|
STRCASE("gnu", ENV_TYPE_GNU)
|
|
STRCASE("gnuabin32", ENV_TYPE_GNUABIN32)
|
|
STRCASE("gnuabi64", ENV_TYPE_GNUABI64)
|
|
STRCASE("gnueabihf", ENV_TYPE_GNUEABIHF)
|
|
STRCASE("gnueabi", ENV_TYPE_GNUEABI)
|
|
STRCASE("gnux32", ENV_TYPE_GNUX32)
|
|
STRCASE("code16", ENV_TYPE_CODE16)
|
|
STRCASE("eabi", ENV_TYPE_EABI)
|
|
STRCASE("eabihf", ENV_TYPE_EABIHF)
|
|
STRCASE("elfv1", ENV_TYPE_ELFV1)
|
|
STRCASE("elfv2", ENV_TYPE_ELFV2)
|
|
STRCASE("android", ENV_TYPE_ANDROID)
|
|
STRCASE("musl", ENV_TYPE_MUSL)
|
|
STRCASE("musleabi", ENV_TYPE_MUSLEABI)
|
|
STRCASE("musleabihf", ENV_TYPE_MUSLEABIHF)
|
|
STRCASE("msvc", ENV_TYPE_MSVC)
|
|
STRCASE("itanium", ENV_TYPE_ITANIUM)
|
|
STRCASE("cygnus", ENV_TYPE_CYGNUS)
|
|
STRCASE("coreclr", ENV_TYPE_CORECLR)
|
|
STRCASE("simulator", ENV_TYPE_SIMULATOR)
|
|
STRCASE("macabi", ENV_TYPE_MACABI)
|
|
return ENV_TYPE_UNKNOWN;
|
|
#undef STRCASE
|
|
}
|
|
|
|
static OsType os_from_llvm_string(const char *os_string)
|
|
{
|
|
char *string = strdup(os_string);
|
|
int len = 0;
|
|
while (string[len] >= 'A') len++;
|
|
string[len] = '\0';
|
|
#define STRCASE(_str, _os) if (strncmp(string, _str, sizeof(_str)) == 0) { free(string); return _os; }
|
|
STRCASE("ananas", OS_TYPE_ANANAS)
|
|
STRCASE("cloudabi", OS_TYPE_CLOUD_ABI)
|
|
STRCASE("darwin", OS_TYPE_MACOSX)
|
|
STRCASE("dragonfly", OS_TYPE_DRAGON_FLY)
|
|
STRCASE("freebsd", OS_TYPE_FREE_BSD)
|
|
STRCASE("fuchsia", OS_TYPE_FUCHSIA)
|
|
STRCASE("ios", OS_TYPE_IOS)
|
|
STRCASE("kfreebsd", OS_TYPE_KFREEBSD)
|
|
STRCASE("linux", OS_TYPE_LINUX)
|
|
STRCASE("lv2", OS_TYPE_PS3)
|
|
STRCASE("macosx", OS_TYPE_MACOSX)
|
|
STRCASE("netbsd", OS_TYPE_NETBSD)
|
|
STRCASE("openbsd", OS_TYPE_OPENBSD)
|
|
STRCASE("solaris", OS_TYPE_SOLARIS)
|
|
STRCASE("windows", OS_TYPE_WIN32)
|
|
STRCASE("haiku", OS_TYPE_HAIKU)
|
|
STRCASE("minix", OS_TYPE_MINIX)
|
|
STRCASE("rtems", OS_TYPE_RTEMS)
|
|
STRCASE("nacl", OS_TYPE_NACL)
|
|
STRCASE("cnk", OS_TYPE_CNK)
|
|
STRCASE("aix", OS_TYPE_AIX)
|
|
STRCASE("cuda", OS_TYPE_CUDA)
|
|
STRCASE("nvcl", OS_TYPE_NVOPENCL)
|
|
STRCASE("amdhsa", OS_TYPE_AMDHSA)
|
|
STRCASE("ps4", OS_TYPE_PS4)
|
|
STRCASE("elfiamcu", OS_TYPE_ELFIAMCU)
|
|
STRCASE("tvos", OS_TYPE_TVOS)
|
|
STRCASE("watchos", OS_TYPE_WATCHOS)
|
|
STRCASE("mesa3d", OS_TYPE_MESA3D)
|
|
STRCASE("contiki", OS_TYPE_CONTIKI)
|
|
STRCASE("amdpal", OS_TYPE_AMDPAL)
|
|
STRCASE("hermit", OS_TYPE_HERMITCORE)
|
|
STRCASE("hurd", OS_TYPE_HURD)
|
|
STRCASE("wasi", OS_TYPE_WASI)
|
|
STRCASE("emscripten", OS_TYPE_EMSCRIPTEN)
|
|
free(string);
|
|
return OS_TYPE_UNKNOWN;
|
|
#undef STRCASE
|
|
}
|
|
|
|
static VendorType vendor_from_llvm_string(const char *string)
|
|
{
|
|
#define STRCASE(_str, _vendor) if (strcmp(string, _str) == 0) return _vendor;
|
|
STRCASE("apple", VENDOR_APPLE)
|
|
STRCASE("pc", VENDOR_PC)
|
|
STRCASE("scei", VENDOR_SCEI)
|
|
STRCASE("bgp", VENDOR_BGP)
|
|
STRCASE("bgq", VENDOR_BGQ)
|
|
STRCASE("fsl", VENDOR_FREESCALE)
|
|
STRCASE("ibm", VENDOR_IBM)
|
|
STRCASE("img", VENDOR_IMAGINATION_TECHNOLOGIES)
|
|
STRCASE("mti", VENDOR_MIPS_TECHNOLOGIES)
|
|
STRCASE("nvidia", VENDOR_NVIDIA)
|
|
STRCASE("csr", VENDOR_CSR)
|
|
STRCASE("myriad", VENDOR_MYRIAD)
|
|
STRCASE("amd", VENDOR_AMD)
|
|
STRCASE("mesa", VENDOR_MESA)
|
|
STRCASE("suse", VENDOR_SUSE)
|
|
STRCASE("oe", VENDOR_OPEN_EMBEDDED)
|
|
return VENDOR_UNKNOWN;
|
|
#undef STRCASE
|
|
}
|
|
|
|
|
|
static unsigned arch_pointer_bit_width(OsType os, ArchType arch)
|
|
{
|
|
switch (arch)
|
|
{
|
|
case ARCH_TYPE_UNKNOWN:
|
|
case ARCH_UNSUPPORTED:
|
|
return 0;
|
|
case ARCH_TYPE_ARM:
|
|
case ARCH_TYPE_ARMB:
|
|
case ARCH_TYPE_PPC:
|
|
case ARCH_TYPE_RISCV32:
|
|
case ARCH_TYPE_THUMB:
|
|
case ARCH_TYPE_THUMBEB:
|
|
case ARCH_TYPE_X86:
|
|
case ARCH_TYPE_WASM32:
|
|
return 32;
|
|
case ARCH_TYPE_WASM64:
|
|
case ARCH_TYPE_AARCH64:
|
|
case ARCH_TYPE_AARCH64_BE:
|
|
case ARCH_TYPE_RISCV64:
|
|
return 64;
|
|
case ARCH_TYPE_PPC64:
|
|
case ARCH_TYPE_PPC64LE:
|
|
if (os == OS_TYPE_PS3) return 32;
|
|
return 64;
|
|
case ARCH_TYPE_X86_64:
|
|
if (os == OS_TYPE_NACL) return 32;
|
|
return 64;
|
|
default:
|
|
UNREACHABLE
|
|
}
|
|
}
|
|
|
|
static unsigned os_target_supports_float16(OsType os, ArchType arch)
|
|
{
|
|
switch (arch)
|
|
{
|
|
case ARCH_TYPE_AARCH64:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static unsigned os_target_supports_float128(OsType os, ArchType arch)
|
|
{
|
|
switch (arch)
|
|
{
|
|
case ARCH_TYPE_AARCH64:
|
|
return true;
|
|
case ARCH_TYPE_PPC64:
|
|
if (os == OS_TYPE_MACOSX) return true;
|
|
return false;
|
|
case ARCH_TYPE_PPC:
|
|
if (os == OS_TYPE_MACOSX) return false; // Only for later OS X 10.4+
|
|
return false;
|
|
case ARCH_TYPE_X86:
|
|
if (os == OS_TYPE_MACOSX) return true;
|
|
return false;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static unsigned os_target_supports_vec(OsType os, ArchType arch, int bits, bool is_int)
|
|
{
|
|
if (bits != 64 && bits != 128) return false;
|
|
switch (arch)
|
|
{
|
|
case ARCH_TYPE_AARCH64:
|
|
case ARCH_TYPE_PPC64:
|
|
case ARCH_TYPE_PPC:
|
|
return true;
|
|
case ARCH_TYPE_X86:
|
|
if (os == OS_TYPE_MACOSX)
|
|
{
|
|
// 64i 128f 128i
|
|
return bits == 128 || is_int;
|
|
}
|
|
return false;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static ObjectFormatType object_format_from_os(OsType os)
|
|
{
|
|
switch (os)
|
|
{
|
|
case OS_UNSUPPORTED:
|
|
return OBJ_FORMAT_UNSUPPORTED;
|
|
case OS_TYPE_LINUX:
|
|
case OS_TYPE_UNKNOWN:
|
|
case OS_TYPE_NETBSD:
|
|
case OS_TYPE_OPENBSD:
|
|
case OS_TYPE_FREE_BSD:
|
|
return OBJ_FORMAT_ELF;
|
|
case OS_TYPE_MACOSX:
|
|
case OS_TYPE_IOS:
|
|
case OS_TYPE_TVOS:
|
|
case OS_TYPE_WATCHOS:
|
|
return OBJ_FORMAT_MACHO;
|
|
case OS_TYPE_WIN32:
|
|
return OBJ_FORMAT_COFF;
|
|
case OS_TYPE_WASI:
|
|
return OBJ_FORMAT_WASM;
|
|
}
|
|
UNREACHABLE
|
|
}
|
|
static unsigned os_target_supports_int128(OsType os, ArchType arch)
|
|
{
|
|
switch (arch)
|
|
{
|
|
case ARCH_TYPE_AARCH64:
|
|
return true;
|
|
case ARCH_TYPE_PPC:
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static unsigned os_target_c_type_bits(OsType os, ArchType arch, CType type)
|
|
{
|
|
switch (os)
|
|
{
|
|
case OS_UNSUPPORTED:
|
|
UNREACHABLE
|
|
case OS_TYPE_UNKNOWN:
|
|
if (arch == ARCH_TYPE_MSP430)
|
|
{
|
|
switch (type)
|
|
{
|
|
case CTYPE_SHORT:
|
|
case CTYPE_INT:
|
|
return 16;
|
|
case CTYPE_LONG:
|
|
return 32;
|
|
case CTYPE_LONG_LONG:
|
|
return 64;
|
|
default:
|
|
UNREACHABLE
|
|
}
|
|
}
|
|
// Use default
|
|
break;
|
|
case OS_TYPE_MACOSX:
|
|
case OS_TYPE_LINUX:
|
|
case OS_TYPE_FREE_BSD:
|
|
case OS_TYPE_NETBSD:
|
|
case OS_TYPE_OPENBSD:
|
|
case OS_TYPE_WASI:
|
|
// Use default
|
|
break;
|
|
case OS_TYPE_WIN32:
|
|
switch (type)
|
|
{
|
|
case CTYPE_SHORT:
|
|
return 16;
|
|
case CTYPE_INT:
|
|
case CTYPE_LONG:
|
|
return 32;
|
|
case CTYPE_LONG_LONG:
|
|
return 64;
|
|
default:
|
|
UNREACHABLE
|
|
}
|
|
case OS_TYPE_IOS:
|
|
case OS_TYPE_TVOS:
|
|
case OS_TYPE_WATCHOS:
|
|
switch (type)
|
|
{
|
|
case CTYPE_SHORT:
|
|
return 16;
|
|
case CTYPE_INT:
|
|
return 32;
|
|
case CTYPE_LONG:
|
|
case CTYPE_LONG_LONG:
|
|
return 64;
|
|
default:
|
|
UNREACHABLE
|
|
}
|
|
}
|
|
switch (type)
|
|
{
|
|
case CTYPE_SHORT:
|
|
return 16;
|
|
case CTYPE_INT:
|
|
return 32;
|
|
case CTYPE_LONG:
|
|
return arch_pointer_bit_width(os, arch);
|
|
case CTYPE_LONG_LONG:
|
|
return 64;
|
|
default:
|
|
UNREACHABLE
|
|
}
|
|
|
|
}
|
|
|
|
static unsigned os_target_alignment_of_int(OsType os, ArchType arch, int bits)
|
|
{
|
|
switch (arch)
|
|
{
|
|
case ARCH_TYPE_UNKNOWN:
|
|
case ARCH_UNSUPPORTED:
|
|
UNREACHABLE
|
|
case ARCH_TYPE_ARM:
|
|
case ARCH_TYPE_THUMB:
|
|
if ((os_is_apple(os) || os == OS_TYPE_NETBSD) && bits > 32) return 4;
|
|
return bits > 64 ? 8 : bits / 8;
|
|
case ARCH_TYPE_ARMB:
|
|
case ARCH_TYPE_THUMBEB:
|
|
if (os == OS_TYPE_NETBSD && bits > 32) return 4;
|
|
return bits > 64 ? 8 : bits / 8;
|
|
case ARCH_TYPE_PPC64:
|
|
case ARCH_TYPE_PPC:
|
|
case ARCH_TYPE_PPC64LE:
|
|
case ARCH_TYPE_RISCV32:
|
|
case ARCH_TYPE_X86_64:
|
|
case ARCH_TYPE_WASM32:
|
|
case ARCH_TYPE_WASM64:
|
|
return bits > 64 ? 8 : bits / 8;
|
|
return bits > 32 ? 4 : bits / 8;
|
|
case ARCH_TYPE_AARCH64:
|
|
case ARCH_TYPE_AARCH64_BE:
|
|
case ARCH_TYPE_RISCV64:
|
|
return bits / 8;
|
|
case ARCH_TYPE_X86:
|
|
if (bits >= 64)
|
|
{
|
|
return (os == OS_TYPE_WIN32 || os == OS_TYPE_NACL) ? 8 : 4;
|
|
}
|
|
return bits / 8;
|
|
}
|
|
UNREACHABLE
|
|
}
|
|
|
|
static unsigned arch_little_endian(ArchType arch)
|
|
{
|
|
switch (arch)
|
|
{
|
|
case ARCH_TYPE_UNKNOWN:
|
|
case ARCH_TYPE_X86:
|
|
case ARCH_TYPE_AARCH64:
|
|
case ARCH_TYPE_ARM:
|
|
case ARCH_TYPE_THUMB:
|
|
case ARCH_TYPE_PPC64LE:
|
|
case ARCH_TYPE_X86_64:
|
|
case ARCH_TYPE_RISCV32:
|
|
case ARCH_TYPE_RISCV64:
|
|
case ARCH_TYPE_WASM32:
|
|
case ARCH_TYPE_WASM64:
|
|
return true;
|
|
case ARCH_TYPE_ARMB:
|
|
case ARCH_TYPE_THUMBEB:
|
|
case ARCH_TYPE_AARCH64_BE:
|
|
case ARCH_TYPE_PPC64:
|
|
case ARCH_TYPE_PPC:
|
|
return false;
|
|
case ARCH_UNSUPPORTED:
|
|
UNREACHABLE
|
|
}
|
|
UNREACHABLE
|
|
}
|
|
|
|
static unsigned os_target_pref_alignment_of_int(OsType os, ArchType arch, int bits)
|
|
{
|
|
switch (arch)
|
|
{
|
|
case ARCH_TYPE_UNKNOWN:
|
|
case ARCH_UNSUPPORTED:
|
|
UNREACHABLE
|
|
case ARCH_TYPE_X86:
|
|
if (os == OS_TYPE_ELFIAMCU && bits > 32) return 4;
|
|
return bits > 64 ? 8 : bits / 8;
|
|
case ARCH_TYPE_AARCH64:
|
|
if (bits < 32 && !os_is_apple(os) && os != OS_TYPE_WIN32) return 4;
|
|
return bits / 8;
|
|
case ARCH_TYPE_AARCH64_BE:
|
|
return bits < 32 ? 4 : bits / 8;
|
|
case ARCH_TYPE_ARM:
|
|
case ARCH_TYPE_ARMB:
|
|
case ARCH_TYPE_PPC:
|
|
case ARCH_TYPE_PPC64LE:
|
|
case ARCH_TYPE_PPC64:
|
|
case ARCH_TYPE_RISCV32:
|
|
case ARCH_TYPE_THUMB:
|
|
case ARCH_TYPE_THUMBEB:
|
|
case ARCH_TYPE_X86_64:
|
|
case ARCH_TYPE_WASM32:
|
|
case ARCH_TYPE_WASM64:
|
|
return bits < 64 ? bits / 8 : 8;
|
|
case ARCH_TYPE_RISCV64:
|
|
return bits / 8;
|
|
}
|
|
UNREACHABLE
|
|
}
|
|
|
|
static unsigned os_target_alignment_of_float(OsType os, ArchType arch, int bits)
|
|
{
|
|
switch (arch)
|
|
{
|
|
case ARCH_TYPE_UNKNOWN:
|
|
case ARCH_UNSUPPORTED:
|
|
UNREACHABLE
|
|
case ARCH_TYPE_X86:
|
|
if (os == OS_TYPE_ELFIAMCU && bits >= 32) return 4;
|
|
if (os == OS_TYPE_WIN32 || os == OS_TYPE_NACL)
|
|
{
|
|
return bits / 8;
|
|
}
|
|
return bits == 64 ? 4 : bits / 8;
|
|
case ARCH_TYPE_AARCH64:
|
|
case ARCH_TYPE_AARCH64_BE:
|
|
case ARCH_TYPE_PPC64:
|
|
case ARCH_TYPE_PPC64LE:
|
|
case ARCH_TYPE_PPC:
|
|
case ARCH_TYPE_RISCV32:
|
|
case ARCH_TYPE_RISCV64:
|
|
case ARCH_TYPE_WASM32:
|
|
case ARCH_TYPE_WASM64:
|
|
return bits / 8;
|
|
case ARCH_TYPE_ARM:
|
|
case ARCH_TYPE_THUMB:
|
|
if ((os_is_apple(os) || os == OS_TYPE_NETBSD) && bits == 64)
|
|
{
|
|
return 4;
|
|
}
|
|
return bits / 8;
|
|
case ARCH_TYPE_THUMBEB:
|
|
case ARCH_TYPE_ARMB:
|
|
if (os == OS_TYPE_NETBSD && bits == 64)
|
|
{
|
|
return 4;
|
|
}
|
|
return bits / 8;
|
|
case ARCH_TYPE_X86_64:
|
|
if (bits == 128 && os == OS_TYPE_ELFIAMCU) return 4;
|
|
return bits / 8;
|
|
}
|
|
UNREACHABLE
|
|
}
|
|
|
|
static const char *os_dynamic_library_suffix(OsType os)
|
|
{
|
|
if (os_is_apple(os)) return ".dylib";
|
|
if (os == OS_TYPE_WIN32) return ".dll";
|
|
return ".so";
|
|
}
|
|
|
|
static PicGeneration arch_os_pic_default(ArchType arch, OsType os)
|
|
{
|
|
switch (os)
|
|
{
|
|
case OS_UNSUPPORTED:
|
|
UNREACHABLE
|
|
case OS_TYPE_OPENBSD:
|
|
case OS_DARWIN_TYPES:
|
|
return PIC_SMALL;
|
|
case OS_TYPE_WIN32:
|
|
return ARCH_TYPE_X86_64 == arch;
|
|
case OS_TYPE_WASI:
|
|
return PIC_NONE;
|
|
case OS_TYPE_UNKNOWN:
|
|
case OS_TYPE_FREE_BSD:
|
|
case OS_TYPE_LINUX:
|
|
case OS_TYPE_NETBSD:
|
|
switch (arch)
|
|
{
|
|
case ARCH_TYPE_MIPS64:
|
|
case ARCH_TYPE_MIPS64EL:
|
|
return PIC_SMALL;
|
|
default:
|
|
return PIC_NONE;
|
|
}
|
|
}
|
|
UNREACHABLE
|
|
}
|
|
static bool arch_os_pic_default_forced(ArchType arch, OsType os)
|
|
{
|
|
switch (os)
|
|
{
|
|
case OS_TYPE_WIN32:
|
|
return arch == ARCH_TYPE_X86_64;
|
|
case OS_DARWIN_TYPES:
|
|
return arch == ARCH_TYPE_AARCH64 || arch == ARCH_TYPE_X86_64;
|
|
case OS_TYPE_WASI:
|
|
case OS_TYPE_UNKNOWN:
|
|
case OS_TYPE_FREE_BSD:
|
|
case OS_TYPE_LINUX:
|
|
case OS_TYPE_NETBSD:
|
|
case OS_TYPE_OPENBSD:
|
|
return false;
|
|
case OS_UNSUPPORTED:
|
|
UNREACHABLE
|
|
}
|
|
UNREACHABLE
|
|
}
|
|
|
|
static PieGeneration arch_os_pie_default(ArchType arch, OsType os, EnvironmentType env)
|
|
{
|
|
switch (os)
|
|
{
|
|
case OS_TYPE_UNKNOWN:
|
|
return PIE_NONE;
|
|
case OS_TYPE_OPENBSD:
|
|
return PIE_SMALL;
|
|
case OS_TYPE_WIN32:
|
|
case OS_DARWIN_TYPES:
|
|
case OS_TYPE_WASI:
|
|
case OS_TYPE_FREE_BSD:
|
|
case OS_TYPE_NETBSD:
|
|
return PIE_SMALL;
|
|
case OS_TYPE_LINUX:
|
|
return env == ENV_TYPE_MUSLEABI || env == ENV_TYPE_MUSLEABIHF || env == ENV_TYPE_ANDROID ? PIE_SMALL : PIE_NONE;
|
|
case OS_UNSUPPORTED:
|
|
UNREACHABLE
|
|
}
|
|
UNREACHABLE
|
|
}
|
|
|
|
static unsigned os_target_pref_alignment_of_float(OsType os, ArchType arch, int bits)
|
|
{
|
|
switch (arch)
|
|
{
|
|
case ARCH_TYPE_UNKNOWN:
|
|
case ARCH_UNSUPPORTED:
|
|
UNREACHABLE
|
|
case ARCH_TYPE_X86:
|
|
if (os == OS_TYPE_ELFIAMCU && bits >= 32) return 4;
|
|
return bits / 8;
|
|
case ARCH_TYPE_AARCH64:
|
|
case ARCH_TYPE_AARCH64_BE:
|
|
case ARCH_TYPE_PPC64:
|
|
case ARCH_TYPE_PPC64LE:
|
|
case ARCH_TYPE_PPC:
|
|
case ARCH_TYPE_RISCV32:
|
|
case ARCH_TYPE_RISCV64:
|
|
case ARCH_TYPE_WASM32:
|
|
case ARCH_TYPE_WASM64:
|
|
case ARCH_TYPE_ARM:
|
|
case ARCH_TYPE_THUMB:
|
|
case ARCH_TYPE_THUMBEB:
|
|
case ARCH_TYPE_ARMB:
|
|
return bits / 8;
|
|
case ARCH_TYPE_X86_64:
|
|
if (bits == 128 && os == OS_TYPE_ELFIAMCU) return 4;
|
|
return bits / 8;
|
|
}
|
|
UNREACHABLE
|
|
}
|
|
|
|
void target_setup(BuildTarget *target)
|
|
{
|
|
assert(!platform_target.target);
|
|
|
|
LLVMInitializeAllTargetInfos();
|
|
LLVMInitializeAllTargetMCs();
|
|
LLVMInitializeAllTargets();
|
|
LLVMInitializeAllAsmPrinters();
|
|
LLVMInitializeAllAsmParsers();
|
|
|
|
platform_target.target = NULL;
|
|
|
|
const char *triple;
|
|
if (target->arch_os_target == ARCH_OS_TARGET_DEFAULT)
|
|
{
|
|
triple = LLVMGetDefaultTargetTriple();
|
|
}
|
|
else
|
|
{
|
|
triple = arch_to_target_triple[target->arch_os_target];
|
|
}
|
|
|
|
char *err = NULL;
|
|
if (LLVMGetTargetFromTriple(triple, ((LLVMTargetRef *)&platform_target.target), &err) != 0)
|
|
{
|
|
error_exit("Could not create target: %s", err);
|
|
// Usually we would dispose of err, but no need to do it due to exit.
|
|
}
|
|
|
|
platform_target.alloca_address_space = 0;
|
|
|
|
DEBUG_LOG("Target set to %s.", triple);
|
|
// Create a specific target machine
|
|
LLVMCodeGenOptLevel level;
|
|
LLVMRelocMode reloc_mode = LLVMRelocDefault;
|
|
|
|
switch (target->optimization_level)
|
|
{
|
|
case OPTIMIZATION_NOT_SET:
|
|
UNREACHABLE;
|
|
case OPTIMIZATION_AGGRESSIVE:
|
|
level = LLVMCodeGenLevelAggressive;
|
|
break;
|
|
case OPTIMIZATION_DEFAULT:
|
|
level = LLVMCodeGenLevelDefault;
|
|
break;
|
|
case OPTIMIZATION_LESS:
|
|
level = LLVMCodeGenLevelLess;
|
|
break;
|
|
case OPTIMIZATION_NONE:
|
|
level = LLVMCodeGenLevelNone;
|
|
break;
|
|
default:
|
|
UNREACHABLE;
|
|
}
|
|
|
|
// Override PIE if needed.
|
|
if (target->pie != PIE_DEFAULT) platform_target.pie = target->pie;
|
|
// Override PIC, but only if the platform does not require PIC
|
|
if (target->pic != PIC_DEFAULT && (target->pic != PIC_NONE || !platform_target.pic_required))
|
|
{
|
|
platform_target.pic = target->pic;
|
|
}
|
|
|
|
assert(platform_target.pic != PIC_DEFAULT && platform_target.pie != PIE_DEFAULT && "PIC and PIE must have been set.");
|
|
|
|
reloc_mode = LLVMRelocDefault;
|
|
if (platform_target.pic != PIC_NONE || platform_target.pie != PIE_NONE)
|
|
{
|
|
reloc_mode = LLVMRelocPIC;
|
|
}
|
|
else
|
|
{
|
|
assert(platform_target.pic == PIC_NONE);
|
|
reloc_mode = LLVMRelocStatic;
|
|
}
|
|
|
|
/*
|
|
if (!opt->features)
|
|
{
|
|
opt->features = "";
|
|
}*/
|
|
if (!(platform_target.machine = LLVMCreateTargetMachine(platform_target.target, triple, "", "", level, reloc_mode,
|
|
LLVMCodeModelDefault))) {
|
|
error_exit("Failed to create target machine.");
|
|
}
|
|
|
|
platform_target.llvm_data_layout = LLVMCreateTargetDataLayout(platform_target.machine);
|
|
|
|
char *target_triple = LLVMGetTargetMachineTriple(platform_target.machine);
|
|
|
|
platform_target.target_triple = strdup(target_triple);
|
|
platform_target.arch = arch_from_llvm_string(strtok(target_triple, "-"));
|
|
if (!arch_is_supported(platform_target.arch))
|
|
{
|
|
printf("WARNING! This architecture is not supported.\n");
|
|
}
|
|
platform_target.vendor = vendor_from_llvm_string(strtok(NULL, "-"));
|
|
platform_target.os = os_from_llvm_string(strtok(NULL, "-"));
|
|
char *env = strtok(NULL, "0123456789");
|
|
platform_target.environment_type = env ? environment_type_from_llvm_string(env) : ENV_TYPE_UNKNOWN;
|
|
|
|
LLVMDisposeMessage(target_triple);
|
|
|
|
platform_target.float_abi = false;
|
|
platform_target.little_endian = arch_little_endian(platform_target.arch);
|
|
platform_target.width_pointer = arch_pointer_bit_width(platform_target.os, platform_target.arch);
|
|
assert(platform_target.width_pointer == LLVMPointerSize(platform_target.llvm_data_layout) * 8);
|
|
platform_target.alloca_address_space = 0;
|
|
|
|
// Todo PIC or no PIC depending on architecture.
|
|
switch (platform_target.arch)
|
|
{
|
|
case ARCH_TYPE_X86_64:
|
|
case ARCH_TYPE_X86:
|
|
case ARCH_TYPE_PPC64LE:
|
|
case ARCH_TYPE_ARM:
|
|
case ARCH_TYPE_RISCV32:
|
|
case ARCH_TYPE_RISCV64:
|
|
platform_target.max_size_for_return = platform_target.width_pointer * 2 / 8;
|
|
break;
|
|
case ARCH_TYPE_PPC64:
|
|
platform_target.max_size_for_return = 0;
|
|
break;
|
|
default:
|
|
FATAL_ERROR("Unsupported architecture.");
|
|
}
|
|
|
|
platform_target.object_format = object_format_from_os(platform_target.os);
|
|
|
|
platform_target.int128 = os_target_supports_int128(platform_target.os, platform_target.arch);
|
|
platform_target.vec128f = os_target_supports_vec(platform_target.os, platform_target.arch, 128, false);
|
|
platform_target.vec128i = os_target_supports_vec(platform_target.os, platform_target.arch, 128, true);
|
|
platform_target.vec64f = os_target_supports_vec(platform_target.os, platform_target.arch, 64, false);
|
|
platform_target.vec64i = os_target_supports_vec(platform_target.os, platform_target.arch, 64, true);
|
|
platform_target.float128 = os_target_supports_float128(platform_target.os, platform_target.arch);
|
|
platform_target.float16 = os_target_supports_float16(platform_target.os, platform_target.arch);
|
|
platform_target.align_byte = os_target_alignment_of_int(platform_target.os, platform_target.arch, 8);
|
|
platform_target.align_short = os_target_alignment_of_int(platform_target.os, platform_target.arch, 16);
|
|
platform_target.align_int = os_target_alignment_of_int(platform_target.os, platform_target.arch, 32);
|
|
platform_target.align_long = os_target_alignment_of_int(platform_target.os, platform_target.arch, 64);
|
|
platform_target.align_i128 = os_target_alignment_of_int(platform_target.os, platform_target.arch, 128);
|
|
platform_target.align_half = os_target_alignment_of_float(platform_target.os, platform_target.arch, 16);
|
|
platform_target.align_float = os_target_alignment_of_float(platform_target.os, platform_target.arch, 32);
|
|
platform_target.align_double = os_target_alignment_of_float(platform_target.os, platform_target.arch, 64);
|
|
platform_target.align_f128 = os_target_alignment_of_float(platform_target.os, platform_target.arch, 128);
|
|
platform_target.align_int = os_target_alignment_of_int(platform_target.os, platform_target.arch, 32);
|
|
platform_target.align_pointer = platform_target.width_pointer / 8;
|
|
platform_target.width_c_short = os_target_c_type_bits(platform_target.os, platform_target.arch, CTYPE_SHORT);
|
|
platform_target.width_c_int = os_target_c_type_bits(platform_target.os, platform_target.arch, CTYPE_INT);
|
|
platform_target.width_c_long = os_target_c_type_bits(platform_target.os, platform_target.arch, CTYPE_LONG);
|
|
platform_target.width_c_long_long = os_target_c_type_bits(platform_target.os, platform_target.arch, CTYPE_LONG_LONG);
|
|
|
|
/**
|
|
* x86-64: CMOV, CMPXCHG8B, FPU, FXSR, MMX, FXSR, SCE, SSE, SSE2
|
|
* x86-64-v2: (close to Nehalem) CMPXCHG16B, LAHF-SAHF, POPCNT, SSE3, SSE4.1, SSE4.2, SSSE3
|
|
* x86-64-v3: (close to Haswell) AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE
|
|
* x86-64-v4: AVX512F, AVX512BW, AVX512CD, AVX512DQ, AVX512VL
|
|
*/
|
|
switch (platform_target.arch)
|
|
{
|
|
case ARCH_UNSUPPORTED:
|
|
UNREACHABLE
|
|
break;
|
|
case ARCH_TYPE_AARCH64:
|
|
case ARCH_TYPE_AARCH64_BE:
|
|
platform_target.aarch.is_darwin = os_is_apple(platform_target.os);
|
|
platform_target.aarch.is_win32 = platform_target.os == OS_TYPE_WIN32;
|
|
platform_target.abi = ABI_AARCH64;
|
|
break;
|
|
case ARCH_TYPE_WASM32:
|
|
case ARCH_TYPE_WASM64:
|
|
platform_target.abi = ABI_WASM;
|
|
break;
|
|
case ARCH_TYPE_ARMB:
|
|
case ARCH_TYPE_ARM:
|
|
case ARCH_TYPE_THUMBEB:
|
|
case ARCH_TYPE_THUMB:
|
|
target_setup_arm_abi();
|
|
break;
|
|
case ARCH_TYPE_PPC:
|
|
FATAL_ERROR("PPC32 is not supported.");
|
|
case ARCH_TYPE_PPC64:
|
|
case ARCH_TYPE_PPC64LE:
|
|
if (platform_target.object_format != OBJ_FORMAT_ELF)
|
|
{
|
|
if (platform_target.arch == ARCH_TYPE_PPC64LE)
|
|
{
|
|
FATAL_ERROR("PPC64 LE non-ELF not supported.");
|
|
}
|
|
FATAL_ERROR("PPC64 not supported");
|
|
}
|
|
/** Here we need to have different codegen depending on elf version :( */
|
|
platform_target.abi = ABI_PPC64_SVR4;
|
|
platform_target.ppc64.is_softfp = platform_target.float_abi == FLOAT_ABI_SOFT;
|
|
/* todo enable if elfv2 */
|
|
platform_target.ppc64.is_elfv2 = platform_target.arch == ARCH_TYPE_PPC64LE;
|
|
/* todo enable if elfv1-qpx */
|
|
platform_target.ppc64.has_qpx = false;
|
|
break;
|
|
case ARCH_TYPE_RISCV64:
|
|
case ARCH_TYPE_RISCV32:
|
|
platform_target.riscv.xlen = 0; // pointer width
|
|
platform_target.riscv.flen = 32; // ends with f / d (64)
|
|
platform_target.abi = ABI_RISCV;
|
|
TODO
|
|
case ARCH_TYPE_X86:
|
|
target_setup_x86_abi(target);
|
|
break;
|
|
case ARCH_TYPE_X86_64:
|
|
target_setup_x64_abi();
|
|
platform_target.x64.avx_level = 0; /* TODO */
|
|
if (platform_target.os == OS_TYPE_WIN32)
|
|
{
|
|
platform_target.abi = ABI_WIN64;
|
|
break;
|
|
}
|
|
platform_target.abi = ABI_X64;
|
|
break;
|
|
case ARCH_TYPE_UNKNOWN:
|
|
platform_target.abi = ABI_UNKNOWN;
|
|
break;
|
|
}
|
|
|
|
platform_target.pic = arch_os_pic_default(platform_target.arch, platform_target.os);
|
|
platform_target.pie = arch_os_pie_default(platform_target.arch, platform_target.os, platform_target.environment_type);
|
|
platform_target.pic_required = arch_os_pic_default_forced(platform_target.arch, platform_target.os);
|
|
|
|
// TODO remove
|
|
builtin_setup(&platform_target);
|
|
}
|