mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Add new optimizer runner.
This commit is contained in:
@@ -369,11 +369,11 @@ endif()
|
||||
|
||||
|
||||
target_include_directories(c3c PRIVATE
|
||||
"${CMAKE_SOURCE_DIR}/src/")
|
||||
"${CMAKE_SOURCE_DIR}/src/" "${CMAKE_SOURCE_DIR}/wrapper/include/")
|
||||
|
||||
|
||||
target_include_directories(c3c_wrappers PRIVATE
|
||||
"${CMAKE_SOURCE_DIR}/wrapper/src/")
|
||||
"${CMAKE_SOURCE_DIR}/wrapper/include/")
|
||||
|
||||
target_include_directories(miniz PUBLIC
|
||||
"${CMAKE_SOURCE_DIR}/dependencies/miniz/")
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# C3C Release Notes
|
||||
|
||||
## 0.6.2 Change list
|
||||
|
||||
### Changes / improvements
|
||||
- Updated LLVM passes
|
||||
|
||||
### Fixes
|
||||
None
|
||||
|
||||
### Stdlib changes
|
||||
None
|
||||
|
||||
## 0.6.1 Change list
|
||||
|
||||
### Changes / improvements
|
||||
|
||||
@@ -144,7 +144,26 @@ typedef enum
|
||||
SINGLE_MODULE_ON = 1
|
||||
} SingleModule;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNROLL_LOOPS_NOT_SET = -1,
|
||||
UNROLL_LOOPS_OFF = 0,
|
||||
UNROLL_LOOPS_ON = 1
|
||||
} UnrollLoops;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MERGE_FUNCTIONS_NOT_SET = -1,
|
||||
MERGE_FUNCTIONS_OFF = 0,
|
||||
MERGE_FUNCTIONS_ON = 1
|
||||
} MergeFunctions;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VECTORIZATION_NOT_SET = -1,
|
||||
VECTORIZATION_OFF = 0,
|
||||
VECTORIZATION_ON = 1
|
||||
} AutoVectorization;
|
||||
typedef enum
|
||||
{
|
||||
STRIP_UNUSED_NOT_SET = -1,
|
||||
@@ -361,6 +380,10 @@ typedef struct BuildOptions_
|
||||
SafetyLevel safety_level;
|
||||
PanicLevel panic_level;
|
||||
SingleModule single_module;
|
||||
UnrollLoops unroll_loops;
|
||||
MergeFunctions merge_functions;
|
||||
AutoVectorization loop_vectorization;
|
||||
AutoVectorization slp_vectorization;
|
||||
bool emit_llvm;
|
||||
bool emit_asm;
|
||||
bool benchmark_mode;
|
||||
@@ -488,6 +511,7 @@ typedef struct
|
||||
bool print_input;
|
||||
bool print_linking;
|
||||
bool no_entry;
|
||||
bool kernel_build;
|
||||
int build_threads;
|
||||
TrustLevel trust_level;
|
||||
OptimizationSetting optsetting;
|
||||
@@ -500,6 +524,10 @@ typedef struct
|
||||
LinkLibc link_libc;
|
||||
StripUnused strip_unused;
|
||||
DebugInfo debug_info;
|
||||
MergeFunctions merge_functions;
|
||||
UnrollLoops unroll_loops;
|
||||
AutoVectorization loop_vectorization;
|
||||
AutoVectorization slp_vectorization;
|
||||
RelocModel reloc_model;
|
||||
ArchOsTarget arch_os_target;
|
||||
CompilerBackend backend;
|
||||
@@ -573,6 +601,10 @@ static BuildTarget default_build_target = {
|
||||
.emit_stdlib = EMIT_STDLIB_NOT_SET,
|
||||
.linker_type = LINKER_TYPE_NOT_SET,
|
||||
.single_module = SINGLE_MODULE_NOT_SET,
|
||||
.unroll_loops = UNROLL_LOOPS_NOT_SET,
|
||||
.merge_functions = MERGE_FUNCTIONS_NOT_SET,
|
||||
.slp_vectorization = VECTORIZATION_NOT_SET,
|
||||
.loop_vectorization = VECTORIZATION_NOT_SET,
|
||||
.strip_unused = STRIP_UNUSED_NOT_SET,
|
||||
.symtab_size = DEFAULT_SYMTAB_SIZE,
|
||||
.reloc_model = RELOC_DEFAULT,
|
||||
|
||||
@@ -1139,6 +1139,10 @@ BuildOptions parse_arguments(int argc, const char *argv[])
|
||||
.linker_type = LINKER_TYPE_NOT_SET,
|
||||
.strip_unused = STRIP_UNUSED_NOT_SET,
|
||||
.single_module = SINGLE_MODULE_NOT_SET,
|
||||
.unroll_loops = UNROLL_LOOPS_NOT_SET,
|
||||
.merge_functions = MERGE_FUNCTIONS_NOT_SET,
|
||||
.slp_vectorization = VECTORIZATION_NOT_SET,
|
||||
.loop_vectorization = VECTORIZATION_NOT_SET,
|
||||
.files = NULL,
|
||||
.build_dir = NULL,
|
||||
.output_dir = NULL,
|
||||
|
||||
@@ -92,6 +92,7 @@ bool command_accepts_files(CompilerCommand command)
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
|
||||
void update_build_target_with_opt_level(BuildTarget *target, OptimizationSetting level)
|
||||
{
|
||||
if (level == OPT_SETTING_NOT_SET) level = OPT_SETTING_O0;
|
||||
@@ -100,6 +101,10 @@ void update_build_target_with_opt_level(BuildTarget *target, OptimizationSetting
|
||||
DebugInfo debug = DEBUG_INFO_FULL;
|
||||
SafetyLevel safety_level = SAFETY_ON;
|
||||
PanicLevel panic_level = PANIC_ON;
|
||||
UnrollLoops unroll_loops = UNROLL_LOOPS_OFF;
|
||||
AutoVectorization vectorization = VECTORIZATION_OFF;
|
||||
AutoVectorization slp_vectorization = VECTORIZATION_OFF;
|
||||
MergeFunctions merge_functions = MERGE_FUNCTIONS_OFF;
|
||||
bool single_module = false;
|
||||
FpOpt fp_opt = FP_STRICT;
|
||||
switch (level)
|
||||
@@ -108,43 +113,68 @@ void update_build_target_with_opt_level(BuildTarget *target, OptimizationSetting
|
||||
break;
|
||||
case OPT_SETTING_O1:
|
||||
optlevel = OPTIMIZATION_MORE;
|
||||
slp_vectorization = VECTORIZATION_ON;
|
||||
unroll_loops = UNROLL_LOOPS_ON;
|
||||
vectorization = VECTORIZATION_ON;
|
||||
break;
|
||||
case OPT_SETTING_O2:
|
||||
merge_functions = MERGE_FUNCTIONS_ON;
|
||||
optlevel = OPTIMIZATION_MORE;
|
||||
safety_level = SAFETY_OFF;
|
||||
slp_vectorization = VECTORIZATION_ON;
|
||||
unroll_loops = UNROLL_LOOPS_ON;
|
||||
vectorization = VECTORIZATION_ON;
|
||||
break;
|
||||
case OPT_SETTING_O3:
|
||||
merge_functions = MERGE_FUNCTIONS_ON;
|
||||
optlevel = OPTIMIZATION_MORE;
|
||||
safety_level = SAFETY_OFF;
|
||||
single_module = true;
|
||||
slp_vectorization = VECTORIZATION_ON;
|
||||
unroll_loops = UNROLL_LOOPS_ON;
|
||||
vectorization = VECTORIZATION_ON;
|
||||
break;
|
||||
case OPT_SETTING_O4:
|
||||
optlevel = OPTIMIZATION_AGGRESSIVE;
|
||||
safety_level = SAFETY_OFF;
|
||||
panic_level = PANIC_OFF;
|
||||
fp_opt = FP_RELAXED;
|
||||
merge_functions = MERGE_FUNCTIONS_ON;
|
||||
optlevel = OPTIMIZATION_AGGRESSIVE;
|
||||
panic_level = PANIC_OFF;
|
||||
safety_level = SAFETY_OFF;
|
||||
single_module = true;
|
||||
slp_vectorization = VECTORIZATION_ON;
|
||||
unroll_loops = UNROLL_LOOPS_ON;
|
||||
vectorization = VECTORIZATION_ON;
|
||||
break;
|
||||
case OPT_SETTING_O5:
|
||||
optlevel = OPTIMIZATION_AGGRESSIVE;
|
||||
safety_level = SAFETY_OFF;
|
||||
panic_level = PANIC_OFF;
|
||||
fp_opt = FP_FAST;
|
||||
merge_functions = MERGE_FUNCTIONS_ON;
|
||||
optlevel = OPTIMIZATION_AGGRESSIVE;
|
||||
panic_level = PANIC_OFF;
|
||||
safety_level = SAFETY_OFF;
|
||||
single_module = true;
|
||||
slp_vectorization = VECTORIZATION_ON;
|
||||
unroll_loops = UNROLL_LOOPS_ON;
|
||||
vectorization = VECTORIZATION_ON;
|
||||
break;
|
||||
case OPT_SETTING_OSMALL:
|
||||
merge_functions = MERGE_FUNCTIONS_ON;
|
||||
optlevel = OPTIMIZATION_MORE;
|
||||
optsize = SIZE_OPTIMIZATION_SMALL;
|
||||
safety_level = SAFETY_OFF;
|
||||
panic_level = PANIC_OFF;
|
||||
safety_level = SAFETY_OFF;
|
||||
slp_vectorization = VECTORIZATION_ON;
|
||||
vectorization = VECTORIZATION_ON;
|
||||
break;
|
||||
case OPT_SETTING_OTINY:
|
||||
debug = DEBUG_INFO_NONE;
|
||||
merge_functions = MERGE_FUNCTIONS_ON;
|
||||
optlevel = OPTIMIZATION_MORE;
|
||||
optsize = SIZE_OPTIMIZATION_TINY;
|
||||
safety_level = SAFETY_OFF;
|
||||
panic_level = PANIC_OFF;
|
||||
safety_level = SAFETY_OFF;
|
||||
single_module = true;
|
||||
debug = DEBUG_INFO_NONE;
|
||||
slp_vectorization = VECTORIZATION_ON;
|
||||
vectorization = VECTORIZATION_OFF;
|
||||
break;
|
||||
case OPT_SETTING_NOT_SET:
|
||||
default:
|
||||
@@ -157,6 +187,10 @@ void update_build_target_with_opt_level(BuildTarget *target, OptimizationSetting
|
||||
if (target->debug_info == DEBUG_INFO_NOT_SET) target->debug_info = debug;
|
||||
if (target->feature.fp_math == FP_DEFAULT) target->feature.fp_math = fp_opt;
|
||||
if (target->single_module == SINGLE_MODULE_NOT_SET && single_module) target->single_module = SINGLE_MODULE_ON;
|
||||
if (target->unroll_loops == UNROLL_LOOPS_NOT_SET) target->unroll_loops = unroll_loops;
|
||||
if (target->merge_functions == MERGE_FUNCTIONS_NOT_SET) target->merge_functions = merge_functions;
|
||||
if (target->slp_vectorization == VECTORIZATION_NOT_SET) target->slp_vectorization = slp_vectorization;
|
||||
if (target->loop_vectorization == VECTORIZATION_NOT_SET) target->loop_vectorization = vectorization;
|
||||
}
|
||||
static void update_build_target_from_options(BuildTarget *target, BuildOptions *options)
|
||||
{
|
||||
@@ -234,46 +268,23 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
|
||||
|
||||
target->read_stdin = options->read_stdin;
|
||||
|
||||
|
||||
if (options->cc) target->cc = options->cc;
|
||||
if (options->optlevel != OPTIMIZATION_NOT_SET)
|
||||
{
|
||||
target->optlevel = options->optlevel;
|
||||
}
|
||||
if (options->optsize != SIZE_OPTIMIZATION_NOT_SET)
|
||||
{
|
||||
target->optsize = options->optsize;
|
||||
}
|
||||
if (options->single_module != SINGLE_MODULE_NOT_SET)
|
||||
{
|
||||
target->single_module = options->single_module;
|
||||
}
|
||||
if (options->safety_level != SAFETY_NOT_SET)
|
||||
{
|
||||
target->feature.safe_mode = options->safety_level;
|
||||
}
|
||||
if (options->panic_level != PANIC_NOT_SET)
|
||||
{
|
||||
target->feature.panic_level = options->panic_level;
|
||||
}
|
||||
if (options->optlevel != OPTIMIZATION_NOT_SET) target->optlevel = options->optlevel;
|
||||
if (options->optsize != SIZE_OPTIMIZATION_NOT_SET) target->optsize = options->optsize;
|
||||
if (options->single_module != SINGLE_MODULE_NOT_SET) target->single_module = options->single_module;
|
||||
if (options->unroll_loops != UNROLL_LOOPS_NOT_SET) target->unroll_loops = options->unroll_loops;
|
||||
if (options->merge_functions != MERGE_FUNCTIONS_NOT_SET) target->merge_functions = options->merge_functions;
|
||||
if (options->loop_vectorization != VECTORIZATION_NOT_SET) target->loop_vectorization = options->loop_vectorization;
|
||||
if (options->slp_vectorization != VECTORIZATION_NOT_SET) target->slp_vectorization = options->slp_vectorization;
|
||||
if (options->safety_level != SAFETY_NOT_SET) target->feature.safe_mode = options->safety_level;
|
||||
if (options->panic_level != PANIC_NOT_SET) target->feature.panic_level = options->panic_level;
|
||||
if (options->strip_unused != STRIP_UNUSED_NOT_SET) target->strip_unused = options->strip_unused;
|
||||
|
||||
if (options->memory_environment != MEMORY_ENV_NOT_SET)
|
||||
{
|
||||
target->memory_environment = options->memory_environment;
|
||||
}
|
||||
if (options->debug_info_override != DEBUG_INFO_NOT_SET)
|
||||
{
|
||||
target->debug_info = options->debug_info_override;
|
||||
}
|
||||
if (options->arch_os_target_override != ARCH_OS_TARGET_DEFAULT)
|
||||
{
|
||||
target->arch_os_target = options->arch_os_target_override;
|
||||
}
|
||||
target->print_linking = options->print_linking;
|
||||
if (options->memory_environment != MEMORY_ENV_NOT_SET) target->memory_environment = options->memory_environment;
|
||||
if (options->debug_info_override != DEBUG_INFO_NOT_SET) target->debug_info = options->debug_info_override;
|
||||
if (options->arch_os_target_override != ARCH_OS_TARGET_DEFAULT) target->arch_os_target = options->arch_os_target_override;
|
||||
if (options->reloc_model != RELOC_DEFAULT) target->reloc_model = options->reloc_model;
|
||||
|
||||
if (options->symtab_size) target->symtab_size = options->symtab_size;
|
||||
target->print_linking = options->print_linking;
|
||||
|
||||
for (int i = 0; i < options->linker_arg_count; i++)
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#if PLATFORM_POSIX
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
#include "c3_llvm.h"
|
||||
|
||||
#define MAX_OUTPUT_FILES 1000000
|
||||
#define MAX_MODULES 100000
|
||||
@@ -29,7 +30,6 @@ double compiler_link_time;
|
||||
|
||||
const char* c3_suffix_list[3] = { ".c3", ".c3t", ".c3i" };
|
||||
|
||||
extern int llvm_version_major;
|
||||
|
||||
void compiler_init(const char *std_lib_dir)
|
||||
{
|
||||
|
||||
@@ -1,27 +1,10 @@
|
||||
#include "compiler_internal.h"
|
||||
#include "c3_llvm.h"
|
||||
|
||||
#if PLATFORM_POSIX
|
||||
#include <glob.h>
|
||||
#endif
|
||||
|
||||
// Copied from wrapper.cpp
|
||||
typedef enum
|
||||
{
|
||||
AR_GNU,
|
||||
AR_DARWIN,
|
||||
AR_DARWIN64,
|
||||
AR_BSD,
|
||||
AR_GNU64,
|
||||
AR_COFF,
|
||||
} ArFormat;
|
||||
|
||||
extern bool llvm_link_elf(const char **args, int arg_count, const char **error_string);
|
||||
extern bool llvm_link_macho(const char **args, int arg_count, const char **error_string);
|
||||
extern bool llvm_link_coff(const char **args, int arg_count, const char **error_string);
|
||||
extern bool llvm_link_wasm(const char **args, int arg_count, const char **error_string);
|
||||
extern UNUSED bool llvm_link_mingw(const char **args, int arg_count, const char **error_string);
|
||||
extern bool llvm_ar(const char *out_name, const char **args, size_t count, int ArFormat);
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include "llvm_codegen_internal.h"
|
||||
#include "compiler_tests/benchmark.h"
|
||||
|
||||
#include "c3_llvm.h"
|
||||
#include <llvm-c/Error.h>
|
||||
#include <llvm-c/Comdat.h>
|
||||
#include <llvm-c/Linker.h>
|
||||
@@ -83,7 +83,7 @@ static void gencontext_destroy(GenContext *context)
|
||||
LLVMBuilderRef llvm_create_builder(GenContext *c)
|
||||
{
|
||||
LLVMBuilderRef builder = LLVMCreateBuilderInContext(c->context);
|
||||
LLVMBuilderSetFastMathFlags(builder, active_target.feature.fp_math);
|
||||
LLVMBuilderSetFastMathFlags(builder, (FastMathOption)active_target.feature.fp_math);
|
||||
return builder;
|
||||
}
|
||||
|
||||
@@ -946,45 +946,53 @@ static void llvm_emit_type_decls(GenContext *context, Decl *decl)
|
||||
|
||||
static inline void llvm_optimize(GenContext *c)
|
||||
{
|
||||
LLVMPassBuilderOptionsRef options = LLVMCreatePassBuilderOptions();
|
||||
LLVMPassBuilderOptionsSetVerifyEach(options, active_target.emit_llvm);
|
||||
bool should_debug = false;
|
||||
#ifndef NDEBUG
|
||||
LLVMPassBuilderOptionsSetDebugLogging(options, debug_log);
|
||||
should_debug = debug_log;
|
||||
#endif
|
||||
const char *passes = NULL;
|
||||
LLVMOptLevels level;
|
||||
switch (active_target.optsize)
|
||||
{
|
||||
case SIZE_OPTIMIZATION_SMALL:
|
||||
passes = "default<Os>";
|
||||
level = LLVM_Os;
|
||||
break;
|
||||
case SIZE_OPTIMIZATION_TINY:
|
||||
passes = "default<Oz>";
|
||||
level = LLVM_Oz;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (active_target.optlevel)
|
||||
{
|
||||
case OPTIMIZATION_NONE:
|
||||
case OPTIMIZATION_NOT_SET:
|
||||
passes = "default<O0>";
|
||||
level = LLVM_O0;
|
||||
break;
|
||||
case OPTIMIZATION_LESS:
|
||||
if (!passes) passes = "default<O1>";
|
||||
level = LLVM_O1;
|
||||
break;
|
||||
case OPTIMIZATION_MORE:
|
||||
if (!passes) passes = "default<O2>";
|
||||
level = LLVM_O2;
|
||||
break;
|
||||
case OPTIMIZATION_AGGRESSIVE:
|
||||
if (!passes) passes = "default<O3>";
|
||||
level = LLVM_O3;
|
||||
break;
|
||||
}
|
||||
LLVMErrorRef err = LLVMRunPasses(c->module, passes, c->machine, options);
|
||||
if (err)
|
||||
{
|
||||
error_exit("An error occurred: %s.", LLVMGetErrorMessage(err));
|
||||
break;
|
||||
}
|
||||
LLVMPasses passes = {
|
||||
.opt_level = level,
|
||||
.should_verify = active_target.emit_llvm,
|
||||
.should_debug = should_debug,
|
||||
.is_kernel = active_target.kernel_build,
|
||||
.opt.vectorize_loops = active_target.loop_vectorization == VECTORIZATION_ON,
|
||||
.opt.slp_vectorize = active_target.slp_vectorization == VECTORIZATION_ON,
|
||||
.opt.unroll_loops = active_target.unroll_loops == UNROLL_LOOPS_ON,
|
||||
.opt.interleave_loops = active_target.unroll_loops == UNROLL_LOOPS_ON,
|
||||
.opt.merge_functions = active_target.merge_functions == MERGE_FUNCTIONS_ON
|
||||
};
|
||||
if (!llvm_run_passes(c->module, c->machine, &passes))
|
||||
{
|
||||
error_exit("Failed to run passes.");
|
||||
}
|
||||
LLVMDisposePassBuilderOptions(options);
|
||||
}
|
||||
|
||||
const char *llvm_codegen(void *context)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <llvm-c/BitWriter.h>
|
||||
#include <llvm-c/DebugInfo.h>
|
||||
#include "dwarf.h"
|
||||
|
||||
#include "c3_llvm.h"
|
||||
#define SLICE_MAX_UNROLL 4
|
||||
|
||||
extern const char *varargslots_name;
|
||||
@@ -293,10 +293,6 @@ void gencontext_init_file_emit(GenContext *c, CompilationUnit *unit);
|
||||
void gencontext_end_file_emit(GenContext *c, CompilationUnit *ast);
|
||||
void gencontext_end_module(GenContext *context);
|
||||
|
||||
// Patched functions
|
||||
LLVMValueRef LLVMConstBswap(LLVMValueRef ConstantVal);
|
||||
void LLVMBuilderSetFastMathFlags(LLVMBuilderRef Builder, FpOpt option);
|
||||
void LLVMSetDSOLocal(LLVMValueRef Global, bool value);
|
||||
|
||||
#ifndef LLVMCreateTypeAttribute
|
||||
LLVMAttributeRef LLVMCreateTypeAttribute(LLVMContextRef C, unsigned KindID,
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#include <llvm-c/TargetMachine.h>
|
||||
#include <llvm-c/Core.h>
|
||||
#include "compiler_internal.h"
|
||||
#include "c3_llvm.h"
|
||||
|
||||
extern void LLVMSetTargetMachineUseInitArray(LLVMTargetMachineRef ref, bool use_init_array);
|
||||
static bool x64features_contains(X86Features *cpu_features, X86Feature feature);
|
||||
static ObjectFormatType object_format_from_os(OsType os, ArchType arch_type);
|
||||
static unsigned arch_pointer_bit_width(OsType os, ArchType arch);
|
||||
@@ -1798,10 +1798,11 @@ void *llvm_target_machine_create(void)
|
||||
}
|
||||
INFO_LOG("CPU: %s", platform_target.cpu);
|
||||
INFO_LOG("Features: %s", platform_target.features);
|
||||
LLVMCodeModel model = active_target.kernel_build ? LLVMCodeModelKernel : LLVMCodeModelDefault;
|
||||
void *result = LLVMCreateTargetMachine(target, platform_target.target_triple,
|
||||
platform_target.cpu ? platform_target.cpu : "", platform_target.features ? platform_target.features : "",
|
||||
(LLVMCodeGenOptLevel)platform_target.llvm_opt_level,
|
||||
reloc_mode, LLVMCodeModelDefault);
|
||||
reloc_mode, model);
|
||||
LLVMSetTargetMachineUseInitArray(result, true);
|
||||
if (!result) error_exit("Failed to create target machine.");
|
||||
LLVMSetTargetMachineAsmVerbosity(result, 1);
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
#define COMPILER_VERSION "0.6.1"
|
||||
#define COMPILER_VERSION "0.6.2"
|
||||
#define PRERELEASE 1
|
||||
84
wrapper/include/c3_llvm.h
Normal file
84
wrapper/include/c3_llvm.h
Normal file
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
#include <llvm-c/TargetMachine.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int llvm_version_major;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DEFAULT = -1,
|
||||
STRICT,
|
||||
RELAXED,
|
||||
FAST
|
||||
} FastMathOption;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AR_GNU,
|
||||
AR_DARWIN,
|
||||
AR_DARWIN64,
|
||||
AR_BSD,
|
||||
AR_GNU64,
|
||||
AR_COFF,
|
||||
} ArFormat;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LLVM_O0,
|
||||
LLVM_O1,
|
||||
LLVM_O2,
|
||||
LLVM_O3,
|
||||
LLVM_Os,
|
||||
LLVM_Oz
|
||||
} LLVMOptLevels;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool should_debug;
|
||||
bool should_verify;
|
||||
LLVMOptLevels opt_level;
|
||||
bool is_kernel;
|
||||
struct
|
||||
{
|
||||
bool recover;
|
||||
bool mem_sanitize;
|
||||
bool mem_track_origins;
|
||||
bool mem_retval;
|
||||
bool thread_sanitize;
|
||||
bool address_sanitize;
|
||||
bool asan_use_globals_gc;
|
||||
bool asan_use_odr_indicator;
|
||||
bool asan_use_after_scope;
|
||||
bool asan_use_after_return;
|
||||
bool asan_use_global_dstor;
|
||||
bool hwaddress_sanitize;
|
||||
} sanitizer;
|
||||
struct
|
||||
{
|
||||
bool unroll_loops;
|
||||
bool interleave_loops;
|
||||
bool vectorize_loops;
|
||||
bool slp_vectorize;
|
||||
bool merge_functions;
|
||||
} opt;
|
||||
} LLVMPasses;
|
||||
|
||||
bool llvm_run_passes(LLVMModuleRef m, LLVMTargetMachineRef tm, LLVMPasses *passes);
|
||||
bool llvm_link_elf(const char **args, int arg_count, const char **error_string);
|
||||
bool llvm_link_macho(const char **args, int arg_count, const char **error_string);
|
||||
bool llvm_link_coff(const char **args, int arg_count, const char **error_string);
|
||||
bool llvm_link_wasm(const char **args, int arg_count, const char **error_string);
|
||||
bool llvm_link_mingw(const char **args, int arg_count, const char **error_string);
|
||||
bool llvm_ar(const char *out_name, const char **args, size_t count, int ArFormat);
|
||||
|
||||
LLVMValueRef LLVMConstBswap(LLVMValueRef ConstantVal);
|
||||
void LLVMBuilderSetFastMathFlags(LLVMBuilderRef Builder, FastMathOption option);
|
||||
void LLVMSetDSOLocal(LLVMValueRef Global, bool value);
|
||||
void LLVMSetTargetMachineUseInitArray(LLVMTargetMachineRef ref, bool use_init_array);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,14 +1,32 @@
|
||||
|
||||
// For hacking the C API
|
||||
#include <llvm/IR/PassManager.h>
|
||||
#include "c3_llvm.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/Object/Archive.h"
|
||||
#include "llvm/Object/ArchiveWriter.h"
|
||||
#include "llvm/Object/IRObjectFile.h"
|
||||
#include "llvm/Object/SymbolicFile.h"
|
||||
#include "llvm-c/TargetMachine.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "lld/Common/CommonLinkerContext.h"
|
||||
#include "llvm/IR/GlobalValue.h"
|
||||
#include "llvm-c/Transforms/PassBuilder.h"
|
||||
#include "llvm-c/TargetMachine.h"
|
||||
#include "llvm-c/Target.h"
|
||||
#include "llvm/IR/Verifier.h"
|
||||
#include "llvm/Passes/PassBuilder.h"
|
||||
#include "llvm/Passes/StandardInstrumentations.h"
|
||||
#include "llvm/Support/CBindingWrapping.h"
|
||||
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
|
||||
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
|
||||
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
|
||||
#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
|
||||
#include "llvm/Transforms/Scalar/EarlyCSE.h"
|
||||
#include "llvm/Transforms/Scalar/GVN.h"
|
||||
#include "llvm/Transforms/Scalar/JumpThreading.h"
|
||||
#include "llvm/Transforms/InstCombine/InstCombine.h"
|
||||
#include "llvm/TargetParser/Triple.h"
|
||||
#include "llvm/Analysis/GlobalsModRef.h"
|
||||
|
||||
#define LINK_SIG \
|
||||
bool link(llvm::ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS, \
|
||||
@@ -51,23 +69,6 @@ typedef enum
|
||||
MINGW
|
||||
} ObjFormat;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AR_GNU,
|
||||
AR_DARWIN,
|
||||
AR_DARWIN64,
|
||||
AR_BSD,
|
||||
AR_GNU64,
|
||||
AR_COFF,
|
||||
} ArFormat;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STRICT,
|
||||
RELAXED,
|
||||
FAST
|
||||
} FastMathOption;
|
||||
|
||||
static bool llvm_link(ObjFormat format, const char **args, int arg_count, const char** error_string)
|
||||
{
|
||||
std::vector<const char*> arg_vector = std::vector<const char *>();
|
||||
@@ -127,9 +128,131 @@ static bool llvm_link(ObjFormat format, const char **args, int arg_count, const
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
|
||||
bool llvm_run_passes(LLVMModuleRef m, LLVMTargetMachineRef tm,
|
||||
LLVMPasses *passes)
|
||||
{
|
||||
llvm::TargetMachine *Machine = reinterpret_cast<llvm::TargetMachine *>(tm);
|
||||
llvm::Module *Mod = llvm::unwrap(m);
|
||||
llvm::PassInstrumentationCallbacks PIC;
|
||||
llvm::PipelineTuningOptions PTO{};
|
||||
PTO.LoopUnrolling = passes->opt.unroll_loops;
|
||||
PTO.LoopInterleaving = passes->opt.interleave_loops;
|
||||
PTO.LoopVectorization = passes->opt.vectorize_loops;
|
||||
PTO.SLPVectorization = passes->opt.slp_vectorize;
|
||||
PTO.MergeFunctions = passes->opt.merge_functions;
|
||||
PTO.CallGraphProfile = true; // We always use integrated ASM
|
||||
PTO.UnifiedLTO = false;
|
||||
|
||||
llvm::PassBuilder PB(Machine, PTO, std::nullopt, &PIC);
|
||||
|
||||
llvm::LoopAnalysisManager LAM;
|
||||
llvm::FunctionAnalysisManager FAM;
|
||||
llvm::CGSCCAnalysisManager CGAM;
|
||||
llvm::ModuleAnalysisManager MAM;
|
||||
PB.registerLoopAnalyses(LAM);
|
||||
PB.registerFunctionAnalyses(FAM);
|
||||
PB.registerCGSCCAnalyses(CGAM);
|
||||
PB.registerModuleAnalyses(MAM);
|
||||
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
|
||||
|
||||
llvm::StandardInstrumentations SI(Mod->getContext(), passes->should_debug, passes->should_verify);
|
||||
SI.registerCallbacks(PIC, &MAM);
|
||||
|
||||
// Assignment tracking pass is not enabled, but could be added
|
||||
// Skipping TargetLibraryAnalysis
|
||||
|
||||
llvm::OptimizationLevel level;
|
||||
switch (passes->opt_level)
|
||||
{
|
||||
case LLVM_O0:
|
||||
level = llvm::OptimizationLevel::O0;
|
||||
break;
|
||||
case LLVM_O1:
|
||||
level = llvm::OptimizationLevel::O1;
|
||||
break;
|
||||
case LLVM_O2:
|
||||
level = llvm::OptimizationLevel::O2;
|
||||
break;
|
||||
case LLVM_O3:
|
||||
level = llvm::OptimizationLevel::O3;
|
||||
break;
|
||||
case LLVM_Os:
|
||||
level = llvm::OptimizationLevel::Os;
|
||||
break;
|
||||
case LLVM_Oz:
|
||||
level = llvm::OptimizationLevel::Oz;
|
||||
break;
|
||||
default:
|
||||
exit(-1);
|
||||
}
|
||||
llvm::ModulePassManager MPM = PB.buildPerModuleDefaultPipeline(level, false);
|
||||
|
||||
if (passes->should_verify)
|
||||
{
|
||||
MPM.addPass(llvm::VerifierPass());
|
||||
}
|
||||
if (passes->sanitizer.mem_sanitize)
|
||||
{
|
||||
llvm::MemorySanitizerOptions options(passes->sanitizer.mem_track_origins,
|
||||
passes->sanitizer.recover,
|
||||
passes->is_kernel,
|
||||
passes->sanitizer.mem_retval);
|
||||
|
||||
MPM.addPass(llvm::MemorySanitizerPass(options));
|
||||
if (passes->opt_level != LLVM_O0)
|
||||
{
|
||||
// Add another function pass like Clang does.
|
||||
MPM.addPass(llvm::RequireAnalysisPass<llvm::GlobalsAA, llvm::Module>());
|
||||
llvm::FunctionPassManager FPM;
|
||||
FPM.addPass(llvm::EarlyCSEPass(true /* Enable mem-ssa. */));
|
||||
FPM.addPass(llvm::InstCombinePass());
|
||||
FPM.addPass(llvm::JumpThreadingPass());
|
||||
FPM.addPass(llvm::GVNPass());
|
||||
FPM.addPass(llvm::InstCombinePass());
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
|
||||
}
|
||||
}
|
||||
if (passes->sanitizer.thread_sanitize)
|
||||
{
|
||||
MPM.addPass(llvm::ModuleThreadSanitizerPass());
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor(llvm::ThreadSanitizerPass()));
|
||||
}
|
||||
|
||||
if (passes->sanitizer.address_sanitize)
|
||||
{
|
||||
llvm::AddressSanitizerOptions Opts;
|
||||
bool use_globals_gc = false; // No need to add this yet.
|
||||
Opts.CompileKernel = passes->is_kernel;
|
||||
Opts.Recover = passes->sanitizer.recover;
|
||||
Opts.UseAfterScope = passes->sanitizer.asan_use_after_scope;
|
||||
Opts.UseAfterReturn = passes->sanitizer.asan_use_after_return
|
||||
? llvm::AsanDetectStackUseAfterReturnMode::Always
|
||||
: llvm::AsanDetectStackUseAfterReturnMode::Never;
|
||||
bool is_windows = Machine->getTargetTriple().isOSWindows();
|
||||
MPM.addPass(llvm::AddressSanitizerPass(Opts,
|
||||
use_globals_gc,
|
||||
!is_windows,
|
||||
passes->sanitizer.asan_use_global_dstor
|
||||
? llvm::AsanDtorKind::Global
|
||||
: llvm::AsanDtorKind::None));
|
||||
}
|
||||
if (passes->sanitizer.hwaddress_sanitize)
|
||||
{
|
||||
MPM.addPass(llvm::HWAddressSanitizerPass({
|
||||
passes->is_kernel,
|
||||
passes->sanitizer.recover,
|
||||
passes->opt_level == LLVM_O0
|
||||
}));
|
||||
}
|
||||
// MPM.addPass(DataFlowSanitizerPass(LangOpts.NoSanitizeFiles));
|
||||
|
||||
MPM.run(*Mod, MAM);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool llvm_ar(const char *out_name, const char **args, size_t count, int ArFormat)
|
||||
{
|
||||
llvm::object::Archive::Kind kind;
|
||||
@@ -215,25 +338,6 @@ extern "C" {
|
||||
const llvm::APInt &i = Val->getUniqueInteger();
|
||||
return llvm::wrap(llvm::Constant::getIntegerValue(Val->getType(), i.byteSwap()));
|
||||
}
|
||||
#if LLVM_VERSION_MAJOR < 14
|
||||
LLVMValueRef LLVMConstGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal,
|
||||
LLVMValueRef *ConstantIndices, unsigned NumIndices) {
|
||||
llvm::ArrayRef<llvm::Constant *> IdxList(llvm::unwrap<llvm::Constant>(ConstantIndices, NumIndices),
|
||||
NumIndices);
|
||||
llvm::Constant *Val = llvm::unwrap<llvm::Constant>(ConstantVal);
|
||||
return wrap(llvm::ConstantExpr::getGetElementPtr(llvm::unwrap(Ty), Val, IdxList));
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMConstInBoundsGEP2(LLVMTypeRef Ty,
|
||||
LLVMValueRef ConstantVal,
|
||||
LLVMValueRef *ConstantIndices,
|
||||
unsigned NumIndices) {
|
||||
llvm::ArrayRef<llvm::Constant *> IdxList(llvm::unwrap<llvm::Constant>(ConstantIndices, NumIndices),
|
||||
NumIndices);
|
||||
llvm::Constant *Val = llvm::unwrap<llvm::Constant>(ConstantVal);
|
||||
return wrap(llvm::ConstantExpr::getInBoundsGetElementPtr(llvm::unwrap(Ty), Val, IdxList));
|
||||
}
|
||||
#endif
|
||||
|
||||
bool llvm_link_elf(const char **args, int arg_count, const char** error_string)
|
||||
{
|
||||
@@ -261,5 +365,4 @@ bool llvm_link_mingw(const char **args, int arg_count, const char** error_string
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user