Use C API for creating target machine
All checks were successful
CI / ci (MinSizeRel, ubuntu-latest) (push) Successful in 33s
CI / ci (Release, ubuntu-latest) (push) Successful in 30s
CI / ci (RelWithDebInfo, ubuntu-latest) (push) Successful in 36s
CI / ci (Debug, ubuntu-latest) (push) Successful in 2m26s

This commit is contained in:
David Gonzalez Martin 2025-05-31 07:54:25 -06:00
parent b5f92727b4
commit a74121567a
3 changed files with 123 additions and 37 deletions

View File

@ -579,6 +579,13 @@ target_get_native = fn () Target
return { .cpu = .x86_64, .os = .linux };
}
target_compare = fn (a: Target, b: Target) u1
{
>is_same_cpu = a.cpu == b.cpu;
>is_same_os = a.cpu == b.cpu;
return is_same_cpu and is_same_os;
}
CompileOptions = struct
{
content: []u8,
@ -843,7 +850,7 @@ LLVMIntrinsicIndex = enum
[extern] llvm_host_cpu_name = fn [cc(c)] () []u8;
[extern] llvm_host_cpu_features = fn [cc(c)] () []u8;
host_triple: []u8 = zero;
host_target_triple: []u8 = zero;
host_cpu_model: []u8 = zero;
host_cpu_features: []u8 = zero;
@ -860,7 +867,7 @@ llvm_initialize_targets = fn () void
LLVMInitializeX86AsmParser();
LLVMInitializeX86Disassembler();
host_triple = llvm_default_target_triple();
host_target_triple = llvm_default_target_triple();
host_cpu_model = llvm_host_cpu_name();
host_cpu_features = llvm_host_cpu_features();
@ -868,7 +875,17 @@ llvm_initialize_targets = fn () void
}
}
LLVMCodeGenerationOptimizationLevel = enum
{
none = 0,
less = 1,
default = 2,
aggressive = 3,
}
[extern] LLVMContextCreate = fn [cc(c)] () &LLVMContext;
[extern] llvm_context_create_module = fn (context: &LLVMContext, name: []u8) &LLVMModule;
[extern] LLVMCreateBuilderInContext = fn (context: &LLVMContext) &LLVMBuilder;
ModuleLLVM = struct
{
@ -2650,8 +2667,37 @@ parse = fn (module: &Module) void
emit = fn (module: &Module) void
{
assert(!module.current_function);
assert(!module.current_macro_instantiation);
assert(!module.current_macro_declaration);
llvm_initialize_targets();
>context = LLVMContextCreate();
>m = llvm_context_create_module(context, module.name);
>builder = LLVMCreateBuilderInContext(context);
>target_triple: []u8 = undefined;
>cpu_model: []u8 = undefined;
>cpu_features: []u8 = undefined;
if (target_compare(module.target, target_get_native()))
{
target_triple = host_target_triple;
cpu_model = host_cpu_model;
cpu_features = host_cpu_features;
}
else
{
#trap();
}
>code_generation_optimization_level: LLVMCodeGenerationOptimizationLevel = undefined;
switch (module.build_mode)
{
.debug_none, .debug => { code_generation_optimization_level = .none; },
.soft_optimize => { code_generation_optimization_level = .less; },
.optimize_for_speed, .optimize_for_size => { code_generation_optimization_level = .default; },
.aggressively_optimize_for_speed, .aggressively_optimize_for_size => { code_generation_optimization_level = .aggressive; },
}
}
compile = fn (arena: &Arena, options: CompileOptions) void

View File

@ -249,6 +249,22 @@ struct Target
OperatingSystem os;
};
fn Target target_get_native()
{
return {
.cpu = CPUArchitecture::x86_64,
.os = OperatingSystem::linux_,
};
}
fn bool target_compare(Target a, Target b)
{
auto is_same_cpu = a.cpu == b.cpu;
auto is_same_os = a.os == b.os;
return is_same_cpu && is_same_os;
}
struct Compile
{
String relative_file_path;

View File

@ -349,41 +349,7 @@ fn void llvm_initialize(Module* module)
auto context = LLVMContextCreate();
auto m = llvm_context_create_module(context, module->name);
auto builder = LLVMCreateBuilderInContext(context);
BBLLVMCodeGenerationOptimizationLevel code_generation_optimization_level;
switch (module->build_mode)
{
case BuildMode::debug_none:
case BuildMode::debug:
code_generation_optimization_level = BBLLVMCodeGenerationOptimizationLevel::none;
break;
case BuildMode::soft_optimize:
code_generation_optimization_level = BBLLVMCodeGenerationOptimizationLevel::less;
break;
case BuildMode::optimize_for_speed:
case BuildMode::optimize_for_size:
code_generation_optimization_level = BBLLVMCodeGenerationOptimizationLevel::normal;
break;
case BuildMode::aggressively_optimize_for_speed:
case BuildMode::aggressively_optimize_for_size:
code_generation_optimization_level = BBLLVMCodeGenerationOptimizationLevel::aggressive;
break;
case BuildMode::count:
unreachable();
}
auto triple = llvm_default_target_triple();
BBLLVMTargetMachineCreate target_machine_options = {
.target_triple = triple,
.cpu_model = llvm_host_cpu_name(),
.cpu_features = llvm_host_cpu_features(),
.relocation_model = BBLLVMRelocationModel::default_relocation,
.code_model = BBLLVMCodeModel::none,
.optimization_level = code_generation_optimization_level,
};
String error_message = {};
auto target_machine = llvm_create_target_machine(&target_machine_options, &error_message);
auto target_data = LLVMCreateTargetDataLayout(target_machine);
LLVMSetModuleDataLayout(m, target_data);
LLVMSetTarget(m, (char*)triple.pointer);
LLVMDIBuilderRef di_builder = 0;
LLVMMetadataRef di_compile_unit = 0;
LLVMMetadataRef di_file = 0;
@ -410,6 +376,64 @@ fn void llvm_initialize(Module* module)
module->scope.llvm = di_compile_unit;
}
String target_triple = {};
String cpu_model = {};
String cpu_features = {};
if (target_compare(module->target, target_get_native()))
{
target_triple = llvm_global.host_triple;
cpu_model = llvm_global.host_cpu_model;
cpu_features = llvm_global.host_cpu_features;
}
else
{
// TODO
report_error();
}
auto target_machine_options = LLVMCreateTargetMachineOptions();
LLVMTargetMachineOptionsSetCPU(target_machine_options, (char*)cpu_model.pointer);
LLVMTargetMachineOptionsSetFeatures(target_machine_options, (char*)cpu_features.pointer);
LLVMCodeGenOptLevel code_generation_optimization_level;
switch (module->build_mode)
{
case BuildMode::debug_none:
case BuildMode::debug:
code_generation_optimization_level = LLVMCodeGenLevelNone;
break;
case BuildMode::soft_optimize:
code_generation_optimization_level = LLVMCodeGenLevelLess;
break;
case BuildMode::optimize_for_speed:
case BuildMode::optimize_for_size:
code_generation_optimization_level = LLVMCodeGenLevelDefault;
break;
case BuildMode::aggressively_optimize_for_speed:
case BuildMode::aggressively_optimize_for_size:
code_generation_optimization_level = LLVMCodeGenLevelAggressive;
break;
case BuildMode::count:
unreachable();
}
LLVMTargetMachineOptionsSetCodeGenOptLevel(target_machine_options, code_generation_optimization_level);
LLVMTargetRef target = 0;
char* error_message = 0;
auto result = LLVMGetTargetFromTriple((char*)target_triple.pointer, &target, &error_message);
if (result != 0)
{
report_error();
}
assert(!error_message);
auto target_machine = LLVMCreateTargetMachineWithOptions(target, (char*)target_triple.pointer, target_machine_options);
auto target_data = LLVMCreateTargetDataLayout(target_machine);
LLVMSetModuleDataLayout(m, target_data);
LLVMSetTarget(m, (char*)target_triple.pointer);
module->llvm = {
.context = context,
.module = m,