| ... | @@ -1886,6 +1886,8 @@ fn valueAsI32(self: Self, val: Value, ty: Type) i32 { | ... | @@ -1886,6 +1886,8 @@ fn valueAsI32(self: Self, val: Value, ty: Type) i32 { |
| 1886 | const kv = self.bin_file.base.options.module.?.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function | 1886 | const kv = self.bin_file.base.options.module.?.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function |
| 1887 | return @bitCast(i32, kv.value); | 1887 | return @bitCast(i32, kv.value); |
| 1888 | }, | 1888 | }, |
| | 1889 | .Bool => return @intCast(i32, val.toSignedInt()), |
| | 1890 | .Pointer => return @intCast(i32, val.toSignedInt()), |
| 1889 | else => unreachable, // Programmer called this function for an illegal type | 1891 | else => unreachable, // Programmer called this function for an illegal type |
| 1890 | } | 1892 | } |
| 1891 | } | 1893 | } |
| ... | @@ -2164,8 +2166,8 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -2164,8 +2166,8 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2164 | self.gpa.free(case.values); | 2166 | self.gpa.free(case.values); |
| 2165 | } else case_list.deinit(); | 2167 | } else case_list.deinit(); |
| 2166 | | 2168 | |
| 2167 | var lowest: i32 = 0; | 2169 | var lowest_maybe: ?i32 = null; |
| 2168 | var highest: i32 = 0; | 2170 | var highest_maybe: ?i32 = null; |
| 2169 | while (case_i < switch_br.data.cases_len) : (case_i += 1) { | 2171 | while (case_i < switch_br.data.cases_len) : (case_i += 1) { |
| 2170 | const case = self.air.extraData(Air.SwitchBr.Case, extra_index); | 2172 | const case = self.air.extraData(Air.SwitchBr.Case, extra_index); |
| 2171 | const items = @bitCast([]const Air.Inst.Ref, self.air.extra[case.end..][0..case.data.items_len]); | 2173 | 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 { | ... | @@ -2177,11 +2179,11 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2177 | for (items) |ref, i| { | 2179 | for (items) |ref, i| { |
| 2178 | const item_val = self.air.value(ref).?; | 2180 | const item_val = self.air.value(ref).?; |
| 2179 | const int_val = self.valueAsI32(item_val, target_ty); | 2181 | const int_val = self.valueAsI32(item_val, target_ty); |
| 2180 | if (int_val < lowest) { | 2182 | if (lowest_maybe == null or int_val < lowest_maybe.?) { |
| 2181 | lowest = int_val; | 2183 | lowest_maybe = int_val; |
| 2182 | } | 2184 | } |
| 2183 | if (int_val > highest) { | 2185 | if (highest_maybe == null or int_val > highest_maybe.?) { |
| 2184 | highest = int_val; | 2186 | highest_maybe = int_val; |
| 2185 | } | 2187 | } |
| 2186 | values[i] = .{ .integer = int_val, .value = item_val }; | 2188 | values[i] = .{ .integer = int_val, .value = item_val }; |
| 2187 | } | 2189 | } |
| ... | @@ -2190,6 +2192,9 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -2190,6 +2192,9 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2190 | try self.startBlock(.block, blocktype); | 2192 | try self.startBlock(.block, blocktype); |
| 2191 | } | 2193 | } |
| 2192 | | 2194 | |
| | 2195 | // When highest and lowest are null, we have no cases and can use a jump table |
| | 2196 | const lowest = lowest_maybe orelse 0; |
| | 2197 | const highest = highest_maybe orelse 0; |
| 2193 | // When the highest and lowest values are seperated by '50', | 2198 | // When the highest and lowest values are seperated by '50', |
| 2194 | // we define it as sparse and use an if/else-chain, rather than a jump table. | 2199 | // we define it as sparse and use an if/else-chain, rather than a jump table. |
| 2195 | // When the target is an integer size larger than u32, we have no way to use the value | 2200 | // 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 { | ... | @@ -2215,6 +2220,10 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2215 | // we put inside, are atleast 0. | 2220 | // we put inside, are atleast 0. |
| 2216 | try self.addImm32(lowest * -1); | 2221 | try self.addImm32(lowest * -1); |
| 2217 | try self.addTag(.i32_add); | 2222 | try self.addTag(.i32_add); |
| | 2223 | } else if (lowest > 0) { |
| | 2224 | // make the index start from 0 by substracting the lowest value |
| | 2225 | try self.addImm32(lowest); |
| | 2226 | try self.addTag(.i32_sub); |
| 2218 | } | 2227 | } |
| 2219 | | 2228 | |
| 2220 | // Account for default branch so always add '1' | 2229 | // Account for default branch so always add '1' |
| ... | @@ -2223,12 +2232,13 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -2223,12 +2232,13 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2223 | const table_extra_index = try self.addExtra(jump_table); | 2232 | const table_extra_index = try self.addExtra(jump_table); |
| 2224 | try self.addInst(.{ .tag = .br_table, .data = .{ .payload = table_extra_index } }); | 2233 | try self.addInst(.{ .tag = .br_table, .data = .{ .payload = table_extra_index } }); |
| 2225 | try self.mir_extra.ensureUnusedCapacity(self.gpa, depth); | 2234 | try self.mir_extra.ensureUnusedCapacity(self.gpa, depth); |
| 2226 | while (lowest <= highest) : (lowest += 1) { | 2235 | var value = lowest; |
| | 2236 | while (value <= highest) : (value += 1) { |
| 2227 | // idx represents the branch we jump to | 2237 | // idx represents the branch we jump to |
| 2228 | const idx = blk: { | 2238 | const idx = blk: { |
| 2229 | for (case_list.items) |case, idx| { | 2239 | for (case_list.items) |case, idx| { |
| 2230 | for (case.values) |case_value| { | 2240 | for (case.values) |case_value| { |
| 2231 | if (case_value.integer == lowest) break :blk @intCast(u32, idx); | 2241 | if (case_value.integer == value) break :blk @intCast(u32, idx); |
| 2232 | } | 2242 | } |
| 2233 | } | 2243 | } |
| 2234 | break :blk if (has_else_body) case_i else unreachable; | 2244 | break :blk if (has_else_body) case_i else unreachable; |