From 852f312471b6b67476276ef60353a075c7e2b49c Mon Sep 17 00:00:00 2001 From: David Gonzalez Martin Date: Mon, 24 Mar 2025 10:02:57 +0100 Subject: [PATCH] Select --- src/LLVM.zig | 4 ++++ src/compiler.bbb | 18 ++++++++++++++++- src/converter.zig | 45 ++++++++++++++++++++++++++++++++++++++++++ src/converter_test.zig | 4 ++++ src/llvm_api.zig | 1 + tests/select.bbb | 7 +++++++ 6 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 tests/select.bbb diff --git a/src/LLVM.zig b/src/LLVM.zig index e0b7808..4068b12 100644 --- a/src/LLVM.zig +++ b/src/LLVM.zig @@ -960,6 +960,10 @@ pub const Builder = opaque { pub fn create_phi(builder: *Builder, ty: *Type) *Instruction.Phi { return api.LLVMBuildPhi(builder, ty, ""); } + + pub fn create_select(builder: *Builder, condition: *Value, true_value: *Value, false_value: *Value) *Value { + return api.LLVMBuildSelect(builder, condition, true_value, false_value, ""); + } }; pub const GlobalValue = opaque { diff --git a/src/compiler.bbb b/src/compiler.bbb index 94746cb..f1456f8 100644 --- a/src/compiler.bbb +++ b/src/compiler.bbb @@ -2,7 +2,7 @@ OS_Linux_PROT = bits u32 { read: u1, write: u1, - exec: u1, + execute: u1, sem: u1, _: u28, } @@ -53,8 +53,24 @@ OS_MapFlags = bits populate: u1, } +os_linux_protection_flags = fn(map_flags: OS_ProtectionFlags) OS_Linux_PROT +{ + return { + .read = map_flags.read, + .write = map_flags.write, + .execute = map_flags.execute, + zero, + }; +} + os_linux_map_flags = fn(map_flags: OS_MapFlags) OS_Linux_MAP { + return { + .type = #select(map_flags.private, .private, .shared), + .anonymous = map_flags.anonymous, + .no_reserve = map_flags.no_reserve, + .populate = map_flags.populate, + }; } os_reserve = fn (base: u64, protection: OS_ProtectionFlags, map: OS_MapFlags) &u8 diff --git a/src/converter.zig b/src/converter.zig index b41a59e..3d1cbc3 100644 --- a/src/converter.zig +++ b/src/converter.zig @@ -2636,6 +2636,7 @@ const Converter = struct { cast_to, extend, int_from_enum, + select, trap, truncate, va_start, @@ -2755,6 +2756,50 @@ const Converter = struct { value.type = target_type; return value; }, + .select => { + const condition_value = converter.parse_value(module, null, .value); + if (condition_value.type.bb != .integer) { + converter.report_error(); + } + if (condition_value.type.bb.integer.bit_count != 1) { + converter.report_error(); + } + + converter.skip_space(); + converter.expect_character(','); + converter.skip_space(); + + const true_value = converter.parse_value(module, expected_type, .value); + + converter.skip_space(); + converter.expect_character(','); + converter.skip_space(); + + const expected_ty = expected_type orelse true_value.type; + + const false_value = converter.parse_value(module, expected_ty, .value); + + converter.skip_space(); + converter.expect_character(right_parenthesis); + + if (true_value.type != expected_ty) { + converter.report_error(); + } + + if (false_value.type != expected_ty) { + converter.report_error(); + } + + const value = module.values.add(); + value.* = .{ + .llvm = module.llvm.builder.create_select(condition_value.llvm, true_value.llvm, false_value.llvm), + .bb = .instruction, + .type = expected_ty, + .lvalue = false, + .dereference_to_assign = false, + }; + return value; + }, .trap => { converter.expect_character(right_parenthesis); diff --git a/src/converter_test.zig b/src/converter_test.zig index a8bd918..5a51a1e 100644 --- a/src/converter_test.zig +++ b/src/converter_test.zig @@ -392,3 +392,7 @@ test "bits_zero" { test "struct_zero" { try invsrc(@src()); } + +test "select" { + try invsrc(@src()); +} diff --git a/src/llvm_api.zig b/src/llvm_api.zig index 8fc09cc..0b92417 100644 --- a/src/llvm_api.zig +++ b/src/llvm_api.zig @@ -92,6 +92,7 @@ pub extern fn LLVMBuildUnreachable(builder: *llvm.Builder) *llvm.Value; pub extern fn LLVMBuildMemCpy(builder: *llvm.Builder, destination: *llvm.Value, destination_alignment: c_uint, source: *llvm.Value, source_alignment: c_uint, size: *llvm.Value) *llvm.Value; pub extern fn LLVMBuildPhi(builder: *llvm.Builder, ty: *llvm.Type, name: [*:0]const u8) *llvm.Instruction.Phi; pub extern fn LLVMAddIncoming(phi: *llvm.Instruction.Phi, incoming_value_pointer: [*]const *llvm.Value, incoming_basic_block_pointer: [*]const *llvm.BasicBlock, incoming_count: c_uint) void; +pub extern fn LLVMBuildSelect(builder: *llvm.Builder, condition: *llvm.Value, true_value: *llvm.Value, false_value: *llvm.Value, name: [*:0]const u8) *llvm.Value; pub extern fn LLVMBuildVAArg(builder: *llvm.Builder, va_list: *llvm.Value, arg_type: *llvm.Type, name: [*:0]const u8) *llvm.Value; diff --git a/tests/select.bbb b/tests/select.bbb new file mode 100644 index 0000000..75a609b --- /dev/null +++ b/tests/select.bbb @@ -0,0 +1,7 @@ +[export] main = fn [cc(c)] () s32 +{ + >boolean: u1 = 1; + >true_value: s32 = 0; + >false_value: s32 = 1; + return #select(boolean, true_value, false_value); +}