diff --git a/src/LLVM.zig b/src/LLVM.zig index 0ba09f4..22f6377 100644 --- a/src/LLVM.zig +++ b/src/LLVM.zig @@ -568,6 +568,18 @@ pub const Builder = opaque { return api.LLVMBuildURem(builder, left, right, ""); } + pub fn create_shl(builder: *Builder, left: *Value, right: *Value) *Value { + return api.LLVMBuildShl(builder, left, right, ""); + } + + pub fn create_ashr(builder: *Builder, left: *Value, right: *Value) *Value { + return api.LLVMBuildAShr(builder, left, right, ""); + } + + pub fn create_lshr(builder: *Builder, left: *Value, right: *Value) *Value { + return api.LLVMBuildLShr(builder, left, right, ""); + } + pub fn create_ret_void(builder: *Builder) void { builder.create_ret(null); } diff --git a/src/converter.zig b/src/converter.zig index 168afb2..5d9b10f 100644 --- a/src/converter.zig +++ b/src/converter.zig @@ -302,6 +302,9 @@ const Converter = struct { sdiv, urem, srem, + shl, + ashr, + lshr, }; fn parse_value(noalias converter: *Converter, noalias thread: *llvm.Thread, expected_type: Type) *llvm.Value { @@ -330,6 +333,9 @@ const Converter = struct { .udiv => thread.builder.create_udiv(left, right), .srem => thread.builder.create_srem(left, right), .urem => thread.builder.create_urem(left, right), + .shl => thread.builder.create_shl(left, right), + .ashr => thread.builder.create_ashr(left, right), + .lshr => thread.builder.create_lshr(left, right), }; const ch = converter.content[converter.offset]; @@ -349,10 +355,10 @@ const Converter = struct { }, '/' => blk: { converter.offset += 1; - switch (expected_type.signedness) { - true => break :blk .sdiv, - false => break :blk .udiv, - } + break :blk switch (expected_type.signedness) { + true => .sdiv, + false => .udiv, + }; }, '%' => blk: { converter.offset += 1; @@ -361,6 +367,31 @@ const Converter = struct { false => break :blk .urem, } }, + '<' => blk: { + converter.offset += 1; + + break :blk switch (converter.content[converter.offset]) { + '<' => b: { + converter.offset += 1; + break :b .shl; + }, + else => os.abort(), + }; + }, + '>' => blk: { + converter.offset += 1; + + break :blk switch (converter.content[converter.offset]) { + '>' => b: { + converter.offset += 1; + break :b switch (expected_type.signedness) { + true => .ashr, + false => .lshr, + }; + }, + else => os.abort(), + }; + }, else => os.abort(), }; diff --git a/src/converter_test.zig b/src/converter_test.zig index b0ba68f..a18e68d 100644 --- a/src/converter_test.zig +++ b/src/converter_test.zig @@ -102,3 +102,11 @@ test "constant div" { test "constant rem" { try invoke("constant_rem"); } + +test "constant shift left" { + try invoke("constant_shift_left"); +} + +test "constant shift right" { + try invoke("constant_shift_right"); +} diff --git a/src/llvm_api.zig b/src/llvm_api.zig index a7903ba..ae312fd 100644 --- a/src/llvm_api.zig +++ b/src/llvm_api.zig @@ -26,6 +26,9 @@ pub extern fn LLVMBuildSDiv(builder: *llvm.Builder, left: *llvm.Value, right: *l pub extern fn LLVMBuildUDiv(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value; pub extern fn LLVMBuildSRem(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value; pub extern fn LLVMBuildURem(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value; +pub extern fn LLVMBuildShl(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value; +pub extern fn LLVMBuildAShr(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value; +pub extern fn LLVMBuildLShr(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value; pub extern fn LLVMTypeOf(value: *llvm.Value) *llvm.Type; pub extern fn LLVMGlobalGetValueType(value: *llvm.GlobalValue) *llvm.Type; diff --git a/tests/constant_shift_left.bbb b/tests/constant_shift_left.bbb new file mode 100644 index 0000000..8a3c197 --- /dev/null +++ b/tests/constant_shift_left.bbb @@ -0,0 +1,4 @@ +[export] main = fn [cc(c)] () s32 +{ + return 0 << 1; +} diff --git a/tests/constant_shift_right.bbb b/tests/constant_shift_right.bbb new file mode 100644 index 0000000..af22c4b --- /dev/null +++ b/tests/constant_shift_right.bbb @@ -0,0 +1,4 @@ +[export] main = fn [cc(c)] () s32 +{ + return 0 >> 1; +}