Add new optimizer runner.

This commit is contained in:
Christoffer Lerno
2024-07-21 19:04:18 +02:00
parent bdc9f339c9
commit abdaca08fe
13 changed files with 446 additions and 213 deletions

View File

@@ -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/")

View File

@@ -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

View File

@@ -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,

View File

@@ -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,

View File

@@ -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++)
{

View File

@@ -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)
{

View File

@@ -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
{

View File

@@ -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)

View File

@@ -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,

View File

@@ -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);

View File

@@ -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
View 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

View File

@@ -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
}
}