aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/arch/wasm/CodeGen.zig26
1 files changed, 18 insertions, 8 deletions
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig
index c3e8bb7864..85430aa50a 100644
--- a/src/arch/wasm/CodeGen.zig
+++ b/src/arch/wasm/CodeGen.zig
@@ -1886,6 +1886,8 @@ fn valueAsI32(self: Self, val: Value, ty: Type) i32 {
const kv = self.bin_file.base.options.module.?.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function
return @bitCast(i32, kv.value);
},
+ .Bool => return @intCast(i32, val.toSignedInt()),
+ .Pointer => return @intCast(i32, val.toSignedInt()),
else => unreachable, // Programmer called this function for an illegal type
}
}
@@ -2164,8 +2166,8 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
self.gpa.free(case.values);
} else case_list.deinit();
- var lowest: i32 = 0;
- var highest: i32 = 0;
+ var lowest_maybe: ?i32 = null;
+ var highest_maybe: ?i32 = null;
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]);
@@ -2177,11 +2179,11 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
for (items) |ref, i| {
const item_val = self.air.value(ref).?;
const int_val = self.valueAsI32(item_val, target_ty);
- if (int_val < lowest) {
- lowest = int_val;
+ if (lowest_maybe == null or int_val < lowest_maybe.?) {
+ lowest_maybe = int_val;
}
- if (int_val > highest) {
- highest = int_val;
+ if (highest_maybe == null or int_val > highest_maybe.?) {
+ highest_maybe = int_val;
}
values[i] = .{ .integer = int_val, .value = item_val };
}
@@ -2190,6 +2192,9 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
try self.startBlock(.block, blocktype);
}
+ // When highest and lowest are null, we have no cases and can use a jump table
+ const lowest = lowest_maybe orelse 0;
+ const highest = highest_maybe orelse 0;
// When the highest and lowest values are seperated by '50',
// we define it as sparse and use an if/else-chain, rather than a jump table.
// When the target is an integer size larger than u32, we have no way to use the value
@@ -2215,6 +2220,10 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
// we put inside, are atleast 0.
try self.addImm32(lowest * -1);
try self.addTag(.i32_add);
+ } else if (lowest > 0) {
+ // make the index start from 0 by substracting the lowest value
+ try self.addImm32(lowest);
+ try self.addTag(.i32_sub);
}
// Account for default branch so always add '1'
@@ -2223,12 +2232,13 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const table_extra_index = try self.addExtra(jump_table);
try self.addInst(.{ .tag = .br_table, .data = .{ .payload = table_extra_index } });
try self.mir_extra.ensureUnusedCapacity(self.gpa, depth);
- while (lowest <= highest) : (lowest += 1) {
+ var value = lowest;
+ while (value <= highest) : (value += 1) {
// idx represents the branch we jump to
const idx = blk: {
for (case_list.items) |case, idx| {
for (case.values) |case_value| {
- if (case_value.integer == lowest) break :blk @intCast(u32, idx);
+ if (case_value.integer == value) break :blk @intCast(u32, idx);
}
}
break :blk if (has_else_body) case_i else unreachable;