diff --git a/src/compiler.bbb b/src/compiler.bbb index 1cc3587..cf68319 100644 --- a/src/compiler.bbb +++ b/src/compiler.bbb @@ -823,14 +823,21 @@ MacroInstantiation = struct LLVMContext = opaque; LLVMModule = opaque; + LLVMBuilder = opaque; -LLVMDIBuilder = opaque; + LLVMValue = opaque; LLVMType = opaque; -LLVMMetadata = opaque; LLVMBasicBlock = opaque; LLVMIntrinsicId = typealias u32; +LLVMMetadata = opaque; +LLVMDIBuilder = opaque; + +LLVMTarget = opaque; +LLVMTargetMachine = opaque; +LLVMTargetMachineOptions = opaque; + LLVMIntrinsicIndex = enum { trap, @@ -887,6 +894,13 @@ LLVMCodeGenerationOptimizationLevel = enum [extern] llvm_context_create_module = fn (context: &LLVMContext, name: []u8) &LLVMModule; [extern] LLVMCreateBuilderInContext = fn (context: &LLVMContext) &LLVMBuilder; +[extern] LLVMCreateTargetMachineOptions = fn () &LLVMTargetMachineOptions; +[extern] LLVMTargetMachineOptionsSetCPU = fn (target_machine_options: &LLVMTargetMachineOptions, cpu: &u8) void; +[extern] LLVMTargetMachineOptionsSetFeatures = fn (target_machine_options: &LLVMTargetMachineOptions, features: &u8) void; +[extern] LLVMTargetMachineOptionsSetCodeGenOptLevel = fn (target_machine_options: &LLVMTargetMachineOptions, optimization_level: LLVMCodeGenerationOptimizationLevel) void; +[extern] LLVMGetTargetFromTriple = fn (target_triple: &u8, target_pointer: &&LLVMTarget, error_message_pointer: &&u8) s32; +[extern] LLVMCreateTargetMachineWithOptions = fn (target: &LLVMTarget, target_triple: &u8, target_machine_options: &LLVMTargetMachineOptions) &LLVMTargetMachine; + ModuleLLVM = struct { context: &LLVMContext, @@ -2690,6 +2704,10 @@ emit = fn (module: &Module) void #trap(); } + >target_machine_options = LLVMCreateTargetMachineOptions(); + LLVMTargetMachineOptionsSetCPU(target_machine_options, cpu_model.pointer); + LLVMTargetMachineOptionsSetFeatures(target_machine_options, cpu_features.pointer); + >code_generation_optimization_level: LLVMCodeGenerationOptimizationLevel = undefined; switch (module.build_mode) { @@ -2698,6 +2716,20 @@ emit = fn (module: &Module) void .optimize_for_speed, .optimize_for_size => { code_generation_optimization_level = .default; }, .aggressively_optimize_for_speed, .aggressively_optimize_for_size => { code_generation_optimization_level = .aggressive; }, } + + LLVMTargetMachineOptionsSetCodeGenOptLevel(target_machine_options, code_generation_optimization_level); + + >target: &LLVMTarget = zero; + >error_message: &u8 = zero; + >result = LLVMGetTargetFromTriple(target_triple.pointer, &target, &error_message); + if (result != 0) + { + report_error(); + } + + assert(!error_message); + + LLVMCreateTargetMachineWithOptions(target, target_triple.pointer, target_machine_options); } compile = fn (arena: &Arena, options: CompileOptions) void diff --git a/src/compiler.cpp b/src/compiler.cpp index 88080c0..0df0659 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -434,6 +434,7 @@ global_variable String names[] = string_literal("enum_array"), string_literal("opaque"), string_literal("basic_struct_passing"), + string_literal("enum_arbitrary_abi"), }; void entry_point(Slice arguments, Slice envp) diff --git a/src/emitter.cpp b/src/emitter.cpp index bfd834e..656b7ef 100644 --- a/src/emitter.cpp +++ b/src/emitter.cpp @@ -4862,7 +4862,7 @@ fn LLVMValueRef emit_call(Module* module, Value* value, LLVMValueRef left_llvm, if (coerce_to_type->id != TypeId::structure && type_is_abi_equal(module, semantic_argument_type, coerce_to_type) && argument_abi.attributes.direct.offset == 0) { - emit_value(module, semantic_call_argument_value, TypeKind::memory, false); + emit_value(module, semantic_call_argument_value, TypeKind::abi, false); auto evaluation_kind = get_evaluation_kind(argument_abi.semantic_type); Value* v; diff --git a/src/llvm.cpp b/src/llvm.cpp index c6243b8..fd6b78d 100644 --- a/src/llvm.cpp +++ b/src/llvm.cpp @@ -879,8 +879,9 @@ EXPORT String llvm_default_target_triple() u8* pointer = 0; if (length) { - pointer = new u8[length]; + pointer = new u8[length + 1]; memcpy(pointer, triple.c_str(), length); + pointer[length] = 0; } return { pointer, length }; @@ -889,7 +890,9 @@ EXPORT String llvm_default_target_triple() EXPORT String llvm_host_cpu_name() { auto cpu = llvm::sys::getHostCPUName(); - return { (u8*)cpu.data(), cpu.size() }; + auto result = String { (u8*)cpu.data(), cpu.size() }; + assert(result.pointer[result.length] == 0); + return result; } EXPORT String llvm_host_cpu_features() @@ -916,7 +919,8 @@ EXPORT String llvm_host_cpu_features() if (length) { result = new u8[length]; - memcpy(result, feature_string.c_str(), length); + memcpy(result, feature_string.c_str(), length + 1); + result[length] = 0; } return { result, length }; diff --git a/tests/enum_arbitrary_abi.bbb b/tests/enum_arbitrary_abi.bbb new file mode 100644 index 0000000..e98d1b7 --- /dev/null +++ b/tests/enum_arbitrary_abi.bbb @@ -0,0 +1,22 @@ +SomeEnum = enum +{ + a, + b, + c, + d, +} + +foo = fn (arg: SomeEnum) SomeEnum +{ + return arg; +} + +[export] main = fn [cc(c)] () s32 +{ + >some_e: SomeEnum = .c; + >a = foo(some_e); + >b = foo(.d); + if (a != .c) #trap(); + if (b != .d) #trap(); + return 0; +}