aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-03-24 17:44:37 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-03-24 17:47:39 -0700
commit9a1d5001d4bf1f28bd0f23e8b936d677e0e5aac8 (patch)
tree610bf3b91a5a02521b956fbb3ac7187f6f8449fc /src
parentf5f5b9373deae53a544497147cfd1380df34c000 (diff)
downloadzig-9a1d5001d4bf1f28bd0f23e8b936d677e0e5aac8.tar.gz
zig-9a1d5001d4bf1f28bd0f23e8b936d677e0e5aac8.zip
Sema: fix false negative detecting comptime const
The code for detecting when a local const initialization expression ended up being comptime-known gave up when it encountered dbg_stmt instructions, but such instructions are not supposed to matter.
Diffstat (limited to 'src')
-rw-r--r--src/Sema.zig50
1 files changed, 41 insertions, 9 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 277e4a6ba6..e8ef948abd 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -2731,17 +2731,49 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
// instructions from the block, replacing the inst_map entry
// corresponding to the ZIR alloc instruction with a constant
// decl_ref pointing at our new Decl.
+ // dbg_stmt instructions may be interspersed into this pattern
+ // which must be ignored.
if (block.instructions.items.len < 3) break :ct;
- // zig fmt: off
- const const_inst = block.instructions.items[block.instructions.items.len - 3];
- const bitcast_inst = block.instructions.items[block.instructions.items.len - 2];
- const store_inst = block.instructions.items[block.instructions.items.len - 1];
- const air_tags = sema.air_instructions.items(.tag);
+ var search_index: usize = block.instructions.items.len;
+ const air_tags = sema.air_instructions.items(.tag);
const air_datas = sema.air_instructions.items(.data);
- if (air_tags[const_inst] != .constant) break :ct;
- if (air_tags[bitcast_inst] != .bitcast ) break :ct;
- if (air_tags[store_inst] != .store ) break :ct;
- // zig fmt: on
+
+ const store_inst = while (true) {
+ if (search_index == 0) break :ct;
+ search_index -= 1;
+
+ const candidate = block.instructions.items[search_index];
+ switch (air_tags[candidate]) {
+ .dbg_stmt => continue,
+ .store => break candidate,
+ else => break :ct,
+ }
+ } else unreachable; // TODO shouldn't need this
+
+ const bitcast_inst = while (true) {
+ if (search_index == 0) break :ct;
+ search_index -= 1;
+
+ const candidate = block.instructions.items[search_index];
+ switch (air_tags[candidate]) {
+ .dbg_stmt => continue,
+ .bitcast => break candidate,
+ else => break :ct,
+ }
+ } else unreachable; // TODO shouldn't need this
+
+ const const_inst = while (true) {
+ if (search_index == 0) break :ct;
+ search_index -= 1;
+
+ const candidate = block.instructions.items[search_index];
+ switch (air_tags[candidate]) {
+ .dbg_stmt => continue,
+ .constant => break candidate,
+ else => break :ct,
+ }
+ } else unreachable; // TODO shouldn't need this
+
const store_op = air_datas[store_inst].bin_op;
const store_val = (try sema.resolveMaybeUndefVal(block, src, store_op.rhs)) orelse break :ct;
if (store_op.lhs != Air.indexToRef(bitcast_inst)) break :ct;