ability to disable llvm at compile time (#1433)

ability to disable llvm at compile time
This commit is contained in:
alex_s168
2024-09-12 13:36:00 +02:00
committed by GitHub
parent eaa419a48d
commit d376ee6671
8 changed files with 434 additions and 188 deletions

View File

@@ -484,8 +484,22 @@ static void print_version(void)
#endif
PRINTF("Installed directory: %s", find_executable_path());
PRINTF("Git Hash: %s", GIT_HASH);
#if LLVM_AVAILABLE && TB_AVAILABLE
PRINTF("Backends: LLVM; TB");
#elif LLVM_AVAILABLE
PRINTF("Backends: LLVM");
#elif TB_AVAILABLE
PRINTF("Backends: TB");
#else
PRINTF("No backends available");
#endif
#if LLVM_AVAILABLE
PRINTF("LLVM version: %s", llvm_version);
PRINTF("LLVM default target: %s", llvm_target);
#endif
}
static void add_linker_arg(BuildOptions *options, const char *arg)

View File

@@ -7,8 +7,10 @@
#include "../utils/whereami.h"
#if PLATFORM_POSIX
#include <sys/wait.h>
#endif
#endif
#if LLVM_AVAILABLE
#include "c3_llvm.h"
#endif
#include <errno.h>
#define MAX_OUTPUT_FILES 1000000
@@ -111,11 +113,18 @@ typedef struct CompileData_
Task task;
} CompileData;
#if LLVM_AVAILABLE
void thread_compile_task_llvm(void *compile_data)
{
CompileData *data = compile_data;
data->object_name = llvm_codegen(data->context);
}
#else
void thread_compile_task_llvm(void *compile_data)
{
error_exit("LLVM backend not available.");
}
#endif
void thread_compile_task_tb(void *compile_data)
{
@@ -451,9 +460,13 @@ void compiler_compile(void)
switch (compiler.build.backend)
{
case BACKEND_LLVM:
#if LLVM_AVAILABLE
gen_contexts = llvm_gen(modules, module_count);
task = &thread_compile_task_llvm;
break;
#else
error_exit("C3C compiled without LLVM!");
#endif
break;
case BACKEND_TB:
gen_contexts = tilde_gen(modules, module_count);
task = &thread_compile_task_tb;
@@ -1242,8 +1255,14 @@ void compile()
setup_bool_define("COMPILER_SAFE_MODE", safe_mode_enabled());
setup_bool_define("DEBUG_SYMBOLS", compiler.build.debug_info == DEBUG_INFO_FULL);
setup_bool_define("BACKTRACE", compiler.build.show_backtrace != SHOW_BACKTRACE_OFF);
setup_int_define("LLVM_VERSION", llvm_version_major, type_int);
setup_bool_define("BENCHMARKING", compiler.build.benchmarking);
#if LLVM_AVAILABLE
setup_int_define("LLVM_VERSION", llvm_version_major, type_int);
#else
setup_int_define("LLVM_VERSION", 0, type_int);
#endif
setup_bool_define("BENCHMARKING", compiler.build.benchmarking);
setup_int_define("JMP_BUF_SIZE", jump_buffer_size(), type_int);
setup_bool_define("TESTING", compiler.build.testing);
setup_bool_define("ADDRESS_SANITIZER", compiler.build.feature.sanitize_address);

View File

@@ -1,6 +1,8 @@
#include "compiler_internal.h"
#include "../utils/whereami.h"
#if LLVM_AVAILABLE
#include "c3_llvm.h"
#endif
#if PLATFORM_POSIX
#include <glob.h>
@@ -714,6 +716,7 @@ static bool link_exe(const char *output_file, const char **files_to_link, unsign
// This isn't used in most cases, but its contents should get freed after linking.
bool success;
#if LLVM_AVAILABLE
unsigned count = assemble_link_arguments(args, vec_size(args));
switch (compiler.platform.object_format)
{
@@ -732,6 +735,10 @@ static bool link_exe(const char *output_file, const char **files_to_link, unsign
default:
UNREACHABLE
}
#else
success = false;
error = "linking (.exe) is not implemented for C3C compiled without LLVM";
#endif
if (!success)
{
error_exit("Failed to create an executable: %s", error);
@@ -960,8 +967,9 @@ bool dynamic_lib_linker(const char *output_file, const char **files, unsigned fi
return true;
}
bool success;
const char *error = NULL;
unsigned count = assemble_link_arguments(args, vec_size(args));
const char *error = NULL;
#if LLVM_AVAILABLE
unsigned count = assemble_link_arguments(args, vec_size(args));
switch (compiler.platform.object_format)
{
case OBJ_FORMAT_COFF:
@@ -979,6 +987,10 @@ bool dynamic_lib_linker(const char *output_file, const char **files, unsigned fi
default:
UNREACHABLE
}
#else
success = false;
error = "linking not implemented for c3c compiled without llvm";
#endif
if (!success)
{
error_exit("Failed to create a dynamic library: %s", error);
@@ -989,6 +1001,7 @@ bool dynamic_lib_linker(const char *output_file, const char **files, unsigned fi
bool static_lib_linker(const char *output_file, const char **files, unsigned file_count)
{
#if LLVM_AVAILABLE
ArFormat format;
switch (compiler.platform.os)
{
@@ -1009,6 +1022,9 @@ bool static_lib_linker(const char *output_file, const char **files, unsigned fil
break;
}
return llvm_ar(output_file, files, file_count, format);
#else
return false;
#endif
}
bool linker(const char *output_file, const char **files, unsigned file_count)

View File

@@ -1,8 +1,14 @@
#if LLVM_AVAILABLE
#include <llvm-c/Target.h>
#include <llvm-c/TargetMachine.h>
#include <llvm-c/Core.h>
#endif
#include "compiler_internal.h"
#if LLVM_AVAILABLE
#include "c3_llvm.h"
#else
#include "utils/hostinfo.h"
#endif
static bool x64features_contains(X86Features *cpu_features, X86Feature feature);
static ObjectFormatType object_format_from_os(OsType os, ArchType arch_type);
@@ -782,17 +788,24 @@ static const char *x86_cpu_from_set(X86CpuSet set)
case X86CPU_AVX512:
return "x86-64-v4";
case X86CPU_NATIVE:
#if LLVM_AVAILABLE
return LLVMGetHostCPUName();
}
#else
return hostinfo_x86_cpu_name();
#endif
}
UNREACHABLE
}
static void x86_features_from_host(X86Features *cpu_features)
{
#if LLVM_AVAILABLE
char *features = LLVMGetHostCPUFeatures();
INFO_LOG("Detected the following host features: %s", features);
INFO_LOG("For %s", LLVMGetHostCPUName());
char *tok = strtok(features, ",");
INFO_LOG("For %s",
LLVMGetHostCPUName());
char *tok = strtok(features, ",");
*cpu_features = x86_feature_zero;
while (tok != NULL)
{
@@ -822,6 +835,9 @@ static void x86_features_from_host(X86Features *cpu_features)
tok = strtok(NULL, ",");
}
LLVMDisposeMessage(features);
#else
hostinfo_x86_features(cpu_features);
#endif
}
static void x86features_from_cpu(X86Features *cpu_features, X86CpuSet cpu_set)
@@ -1530,7 +1546,7 @@ static AlignData os_target_alignment_of_int(OsType os, ArchType arch, uint32_t b
case ARCH_TYPE_XTENSA:
return (AlignData) { MIN(64u, bits), MIN(64u, bits) };
case ARCH_TYPE_X86_64:
#if LLVM_VERSION_MAJOR < 18
#if !LLVM_AVAILABLE || LLVM_VERSION_MAJOR < 18
return (AlignData) { MIN(64u, bits), MIN(64u, bits) };
#else
FALLTHROUGH;
@@ -1543,7 +1559,7 @@ static AlignData os_target_alignment_of_int(OsType os, ArchType arch, uint32_t b
return (AlignData) { bits, bits };
case ARCH_TYPE_X86:
if (bits <= 32) return (AlignData) { bits, bits };
#if LLVM_VERSION_MAJOR > 17
#if !LLVM_AVAILABLE || LLVM_VERSION_MAJOR > 17
if (bits == 128) return (AlignData) { 128, 128 };
#endif
if (os == OS_TYPE_ELFIAMCU) return (AlignData) { 32, 32 };
@@ -1718,19 +1734,6 @@ static bool arch_os_pic_default_forced(ArchType arch, OsType os)
UNREACHABLE
}
#define INITIALIZE_TARGET(X) do { \
DEBUG_LOG("Initialize target: %s.", #X); \
LLVMInitialize ## X ## AsmParser(); \
LLVMInitialize ## X ## AsmPrinter(); \
LLVMInitialize ## X ## TargetInfo(); \
LLVMInitialize ## X ## Target(); \
LLVMInitialize ## X ## Disassembler(); \
LLVMInitialize ## X ## TargetMC(); \
} while(0)
INLINE const char *llvm_macos_target_triple(const char *triple)
{
if (compiler.build.macos.min_version)
@@ -1755,6 +1758,17 @@ INLINE const char *llvm_macos_target_triple(const char *triple)
return scratch_buffer_to_string();
}
#if LLVM_AVAILABLE
#define INITIALIZE_TARGET(X) do { \
DEBUG_LOG("Initialize target: %s.", #X); \
LLVMInitialize ## X ## AsmParser(); \
LLVMInitialize ## X ## AsmPrinter(); \
LLVMInitialize ## X ## TargetInfo(); \
LLVMInitialize ## X ## Target(); \
LLVMInitialize ## X ## Disassembler(); \
LLVMInitialize ## X ## TargetMC(); \
} while(0)
#if LLVM_VERSION_MAJOR > 19
#define XTENSA_AVAILABLE 1
#else
@@ -1815,7 +1829,11 @@ void *llvm_target_machine_create(void)
return result;
}
#else
#define XTENSA_AVAILABLE 1
#endif
void target_setup(BuildTarget *target)
@@ -1843,6 +1861,7 @@ void target_setup(BuildTarget *target)
compiler.platform.alloca_address_space = 0;
#if LLVM_AVAILABLE
// Create a specific target machine
LLVMCodeGenOptLevel level;
@@ -1867,8 +1886,15 @@ void target_setup(BuildTarget *target)
}
compiler.platform.llvm_opt_level = (int)level;
#endif
INFO_LOG("Triple picked was %s.", compiler.platform.target_triple);
INFO_LOG("Default was %s.", LLVM_DEFAULT_TARGET_TRIPLE);
#if LLVM_AVAILABLE
INFO_LOG("Default was %s.", LLVM_DEFAULT_TARGET_TRIPLE);
#else
INFO_LOG("Default was %s.", hostinfo_default_triple());
#endif
StringSlice target_triple_string = slice_from_string(compiler.platform.target_triple);
compiler.platform.arch = arch_from_llvm_string(slice_next_token(&target_triple_string, '-'));

View File

@@ -65,7 +65,9 @@ typedef struct
typedef struct
{
const char *target_triple;
int llvm_opt_level;
#if LLVM_AVAILABLE
int llvm_opt_level;
#endif
const char *cpu;
const char *features;
ArchType arch;

121
src/utils/hostinfo.c Normal file
View File

@@ -0,0 +1,121 @@
#include "../compiler/compiler_internal.h"
#include "hostinfo.h"
#include <stdlib.h>
static int is_le(void) {
unsigned int i = 1;
char *c;
c = (char *) &i;
return (*c == 1);
}
ArchType hostinfo_arch_type(void) {
#if defined(__x86_64__) || defined(_M_X64)
return ARCH_TYPE_X86_64;
#elif defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
return ARCH_TYPE_X86;
#elif (defined(__arm__) && !defined(__thumb__)) || (defined(__TARGET_ARCH_ARM) && !defined(__TARGET_ARCH_THUMB)) || defined(__ARM) || defined(_M_ARM) || defined(_M_ARM_T) || defined(__ARM_ARCH)
return is_le() ? ARCH_TYPE_ARM : ARCH_TYPE_ARMB;
#elif defined(__thumb__) || defined(__TARGET_ARCH_THUMB) || defined(__ARM) || defined(_M_ARM) || defined(_M_ARM_T) || defined(__ARM_ARCH)
return is_le() ? ARCH_TYPE_THUMB : ARCH_TYPE_THUMBEB;
#elif defined(__aarch64__) || defined(_M_ARM64)
return is_le() ? ARCH_TYPE_AARCH64 : ARCH_TYPE_AARCH64_BE;
#elif defined(mips) || defined(__mips__) || defined(__mips)
return ARCH_UNSUPPORTED;
#elif defined(__sh__)
return ARCH_UNSUPPORTED;
#elif defined(__riscv) && defined(__riscv32)
return ARCH_TYPE_RISCV32;
#elif defined(__riscv) && defined(__riscv64)
return ARCH_TYPE_RISCV64;
#elif defined(__PPC64__) || defined(__ppc64__) || defined(_ARCH_PPC64) || defined(__powerpc64__)
return is_le() ? ARCH_TYPE_PPC64LE : ARCH_TYPE_PPC64;
#elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) || defined(__ppc__) || defined(__PPC__) || defined(_ARCH_PPC)
return ARCH_TYPE_PPC;
#elif defined(__sparc__) || defined(__sparc)
return ARCH_UNSUPPORTED
#else
return ARCH_UNSUPPORTED
#endif
}
static const char * llvm_arch_name(ArchType ty) {
switch (ty) {
case ARCH_TYPE_X86_64: return "x86_64";
case ARCH_TYPE_X86: return "x86";
case ARCH_TYPE_ARM: return "arm";
case ARCH_TYPE_ARMB: return "armbe";
case ARCH_TYPE_AARCH64: return "aarch64";
case ARCH_TYPE_AARCH64_BE: return "aarch64be";
case ARCH_TYPE_THUMB: return "thumb";
case ARCH_TYPE_THUMBEB: return "thumbeb";
case ARCH_TYPE_WASM64: return "wasm64";
case ARCH_TYPE_WASM32: return "wasm32";
case ARCH_TYPE_XTENSA: return "xtensa";
case ARCH_TYPE_PPC: return "ppc";
case ARCH_TYPE_PPC64: return "ppc64";
case ARCH_TYPE_PPC64LE: return "ppc64le";
case ARCH_TYPE_RISCV32: return "riscv32";
case ARCH_TYPE_RISCV64: return "riscv64";
default:
case ARCH_TYPE_UNKNOWN: return "unknown";
}
}
void hostinfo_x86_features(X86Features *cpu_features) {
#if defined(__x86_64__) || defined(_M_X64)
// TODO
#endif
}
EnvironmentType hostinfo_env_type(void) {
return ENV_TYPE_UNKNOWN;
}
OsType hostinfo_os_type(void) {
if (system("freebsd-version -k") == 0) {
return OS_TYPE_FREE_BSD;
}
if (system("uname -r") == 0) {
return OS_TYPE_LINUX;
}
if (system("cd C:/Windows") == 0) {
return OS_TYPE_WIN32;
}
return OS_TYPE_UNKNOWN;
}
static const char * llvm_os_name(OsType os) {
switch (os) {
case OS_TYPE_FREE_BSD: return "frebsd";
case OS_TYPE_LINUX: return "linux";
case OS_TYPE_WIN32: return "win32";
default: return "unknown";
}
}
VendorType hostinfo_vendor_type(void) {
return VENDOR_UNKNOWN;
}
static char triple[128];
static int triple_init = 0;
const char * hostinfo_default_triple(void) {
if (!triple_init) {
sprintf(triple, "%s-unknown-unknown-%s",
llvm_arch_name(hostinfo_arch_type()),
llvm_os_name(hostinfo_os_type()));
triple_init = 1;
}
return triple;
}
const char * hostinfo_x86_cpu_name(void) {
return "x86";
}

12
src/utils/hostinfo.h Normal file
View File

@@ -0,0 +1,12 @@
#if !defined(HOSTINFO_H) && !LLVM_AVAILABLE
#define HOSTINFO_H
void hostinfo_x86_features(X86Features *cpu_features);
ArchType hostinfo_arch_type(void);
EnvironmentType hostinfo_env_type(void);
OsType hostinfo_os_type(void);
VendorType hostinfo_vendor_type(void);
const char * hostinfo_default_triple(void);
const char * hostinfo_x86_cpu_name(void); // for example: "x86-64", "x86-64-v4"
#endif