Commit 72149ae7e4

Luuk de Gram <luuk@degram.dev>
2021-07-23 22:31:45
Allow negative values
1 parent cb41f0e
Changed files (1)
src
codegen
src/codegen/wasm.zig
@@ -1281,15 +1281,15 @@ pub const Context = struct {
         var case_i: u32 = 0;
 
         // a map that maps each value with its index and body
-        var map = std.AutoArrayHashMap(u32, struct {
+        var map = std.AutoArrayHashMap(i32, struct {
             index: u32,
             body: []const Air.Inst.Index,
             value: Value,
         }).init(self.gpa);
         defer map.deinit();
 
-        var lowest: u32 = 0;
-        var highest: u32 = 0;
+        var lowest: i32 = 0;
+        var highest: i32 = 0;
         while (case_i < switch_br.data.cases_len) : (case_i += 1) {
             const case = self.air.extraData(Air.SwitchBr.Case, extra_index);
             const items = @bitCast([]const Air.Inst.Ref, self.air.extra[case.end..][0..case.data.items_len]);
@@ -1298,9 +1298,15 @@ pub const Context = struct {
 
             for (items) |ref| {
                 const item_val = self.air.value(ref).?;
-                // safe to truncate the values as we only use them when
-                // the target's bits is 32 or lower.
-                const int_val = @truncate(u32, item_val.toUnsignedInt());
+                const int_val: i32 = blk: {
+                    if (target_ty.intInfo(self.target).signedness == .signed) {
+                        // safe to truncate the values as we only use them when
+                        // the target's bits is 32 or lower.
+                        break :blk @truncate(i32, item_val.toSignedInt());
+                    }
+
+                    break :blk @intCast(i32, @truncate(u31, item_val.toUnsignedInt()) - 1);
+                };
                 if (int_val < lowest) {
                     lowest = int_val;
                 }
@@ -1333,9 +1339,16 @@ pub const Context = struct {
             // to jump to.
             try self.startBlock(.block, blocktype, null);
             try self.emitWValue(target);
+            if (lowest < 0) {
+                // since br_table works using indexes, starting from '0', we must ensure all values
+                // we put inside, are atleast 0.
+                try self.code.append(wasm.opcode(.i32_const));
+                try leb.writeILEB128(self.code.writer(), lowest * -1);
+                try self.code.append(wasm.opcode(.i32_add));
+            }
             try self.code.append(wasm.opcode(.br_table));
             const depth = highest - lowest + @boolToInt(has_else_body);
-            try leb.writeULEB128(self.code.writer(), depth);
+            try leb.writeILEB128(self.code.writer(), depth);
             while (lowest <= highest) : (lowest += 1) {
                 const idx = if (map.get(lowest)) |value| blk: {
                     break :blk value.index;