diff --git a/src/compiler.bbb b/src/compiler.bbb index 1a608c1..1cc3587 100644 --- a/src/compiler.bbb +++ b/src/compiler.bbb @@ -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 diff --git a/src/compiler.hpp b/src/compiler.hpp index cf3442b..b85a8ab 100644 --- a/src/compiler.hpp +++ b/src/compiler.hpp @@ -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; diff --git a/src/emitter.cpp b/src/emitter.cpp index 238bdbe..bfd834e 100644 --- a/src/emitter.cpp +++ b/src/emitter.cpp @@ -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,