authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-05-05 14:57:23-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:42:28-07:00
log2f05b1482a6f62658cc70c252d48a24a40404aa8
tree17384a9a13b9cb993918ded8c83b8d7a123e6b47
parentac07ddadeb36019c262b4f28a4fa3884f6f50b32

Sema: update core comptime detection logic to be InternPool aware

* Add some assertions to make sure instructions are not none. I tested all these with master branch as well and made sure the behavior tests still passed with the assertions intact (along with a handful of callsite updates). * Fix Sema.resolveMaybeUndefValAllowVariablesMaybeRuntime not noticing that interned values are comptime-known. This was causing all kinds of chaos. * Fix print_air writeType calling tag() without checking for ip_index

6 files changed, 47 insertions(+), 28 deletions(-)

src/Air.zig+11-5
...@@ -925,7 +925,7 @@ pub const Inst = struct {...@@ -925,7 +925,7 @@ pub const Inst = struct {
925925
926 /// This Ref does not correspond to any AIR instruction or constant926 /// This Ref does not correspond to any AIR instruction or constant
927 /// value and may instead be used as a sentinel to indicate null.927 /// value and may instead be used as a sentinel to indicate null.
928 none = std.math.maxInt(u32),928 none = @enumToInt(InternPool.Index.none),
929 _,929 _,
930 };930 };
931931
...@@ -1461,11 +1461,12 @@ pub fn deinit(air: *Air, gpa: std.mem.Allocator) void {...@@ -1461,11 +1461,12 @@ pub fn deinit(air: *Air, gpa: std.mem.Allocator) void {
14611461
1462pub const ref_start_index: u32 = InternPool.static_len;1462pub const ref_start_index: u32 = InternPool.static_len;
14631463
1464pub fn indexToRef(inst: Air.Inst.Index) Air.Inst.Ref {1464pub fn indexToRef(inst: Inst.Index) Inst.Ref {
1465 return @intToEnum(Air.Inst.Ref, ref_start_index + inst);1465 return @intToEnum(Inst.Ref, ref_start_index + inst);
1466}1466}
14671467
1468pub fn refToIndex(inst: Air.Inst.Ref) ?Air.Inst.Index {1468pub fn refToIndex(inst: Inst.Ref) ?Inst.Index {
1469 assert(inst != .none);
1469 const ref_int = @enumToInt(inst);1470 const ref_int = @enumToInt(inst);
1470 if (ref_int >= ref_start_index) {1471 if (ref_int >= ref_start_index) {
1471 return ref_int - ref_start_index;1472 return ref_int - ref_start_index;
...@@ -1474,8 +1475,13 @@ pub fn refToIndex(inst: Air.Inst.Ref) ?Air.Inst.Index {...@@ -1474,8 +1475,13 @@ pub fn refToIndex(inst: Air.Inst.Ref) ?Air.Inst.Index {
1474 }1475 }
1475}1476}
14761477
1478pub fn refToIndexAllowNone(inst: Inst.Ref) ?Inst.Index {
1479 if (inst == .none) return null;
1480 return refToIndex(inst);
1481}
1482
1477/// Returns `null` if runtime-known.1483/// Returns `null` if runtime-known.
1478pub fn value(air: Air, inst: Air.Inst.Ref, mod: *const Module) ?Value {1484pub fn value(air: Air, inst: Inst.Ref, mod: *const Module) ?Value {
1479 const ref_int = @enumToInt(inst);1485 const ref_int = @enumToInt(inst);
1480 if (ref_int < ref_start_index) {1486 if (ref_int < ref_start_index) {
1481 const ip_index = @intToEnum(InternPool.Index, ref_int);1487 const ip_index = @intToEnum(InternPool.Index, ref_int);
src/Liveness.zig+2-2
...@@ -1268,7 +1268,7 @@ fn analyzeOperands(...@@ -1268,7 +1268,7 @@ fn analyzeOperands(
1268 _ = data.live_set.remove(inst);1268 _ = data.live_set.remove(inst);
12691269
1270 for (operands) |op_ref| {1270 for (operands) |op_ref| {
1271 const operand = Air.refToIndex(op_ref) orelse continue;1271 const operand = Air.refToIndexAllowNone(op_ref) orelse continue;
12721272
1273 // Don't compute any liveness for constants1273 // Don't compute any liveness for constants
1274 switch (inst_tags[operand]) {1274 switch (inst_tags[operand]) {
...@@ -1304,7 +1304,7 @@ fn analyzeOperands(...@@ -1304,7 +1304,7 @@ fn analyzeOperands(
1304 while (i > 0) {1304 while (i > 0) {
1305 i -= 1;1305 i -= 1;
1306 const op_ref = operands[i];1306 const op_ref = operands[i];
1307 const operand = Air.refToIndex(op_ref) orelse continue;1307 const operand = Air.refToIndexAllowNone(op_ref) orelse continue;
13081308
1309 // Don't compute any liveness for constants1309 // Don't compute any liveness for constants
1310 switch (inst_tags[operand]) {1310 switch (inst_tags[operand]) {
src/Liveness/Verify.zig+1-1
...@@ -555,7 +555,7 @@ fn verifyDeath(self: *Verify, inst: Air.Inst.Index, operand: Air.Inst.Index) Err...@@ -555,7 +555,7 @@ fn verifyDeath(self: *Verify, inst: Air.Inst.Index, operand: Air.Inst.Index) Err
555}555}
556556
557fn verifyOperand(self: *Verify, inst: Air.Inst.Index, op_ref: Air.Inst.Ref, dies: bool) Error!void {557fn verifyOperand(self: *Verify, inst: Air.Inst.Index, op_ref: Air.Inst.Ref, dies: bool) Error!void {
558 const operand = Air.refToIndex(op_ref) orelse return;558 const operand = Air.refToIndexAllowNone(op_ref) orelse return;
559 switch (self.air.instructions.items(.tag)[operand]) {559 switch (self.air.instructions.items(.tag)[operand]) {
560 .constant, .const_ty, .interned => {},560 .constant, .const_ty, .interned => {},
561 else => {561 else => {
src/Sema.zig+19-14
...@@ -968,7 +968,7 @@ fn analyzeBodyInner(...@@ -968,7 +968,7 @@ fn analyzeBodyInner(
968 .int_big => try sema.zirIntBig(block, inst),968 .int_big => try sema.zirIntBig(block, inst),
969 .float => try sema.zirFloat(block, inst),969 .float => try sema.zirFloat(block, inst),
970 .float128 => try sema.zirFloat128(block, inst),970 .float128 => try sema.zirFloat128(block, inst),
971 .int_type => try sema.zirIntType(block, inst),971 .int_type => try sema.zirIntType(inst),
972 .is_non_err => try sema.zirIsNonErr(block, inst),972 .is_non_err => try sema.zirIsNonErr(block, inst),
973 .is_non_err_ptr => try sema.zirIsNonErrPtr(block, inst),973 .is_non_err_ptr => try sema.zirIsNonErrPtr(block, inst),
974 .ret_is_non_err => try sema.zirRetIsNonErr(block, inst),974 .ret_is_non_err => try sema.zirRetIsNonErr(block, inst),
...@@ -1694,7 +1694,7 @@ fn analyzeBodyInner(...@@ -1694,7 +1694,7 @@ fn analyzeBodyInner(
1694 const extra = sema.code.extraData(Zir.Inst.DeferErrCode, inst_data.payload_index).data;1694 const extra = sema.code.extraData(Zir.Inst.DeferErrCode, inst_data.payload_index).data;
1695 const defer_body = sema.code.extra[extra.index..][0..extra.len];1695 const defer_body = sema.code.extra[extra.index..][0..extra.len];
1696 const err_code = try sema.resolveInst(inst_data.err_code);1696 const err_code = try sema.resolveInst(inst_data.err_code);
1697 sema.inst_map.putAssumeCapacity(extra.remapped_err_code, err_code);1697 map.putAssumeCapacity(extra.remapped_err_code, err_code);
1698 const break_inst = sema.analyzeBodyInner(block, defer_body) catch |err| switch (err) {1698 const break_inst = sema.analyzeBodyInner(block, defer_body) catch |err| switch (err) {
1699 error.ComptimeBreak => sema.comptime_break_inst,1699 error.ComptimeBreak => sema.comptime_break_inst,
1700 else => |e| return e,1700 else => |e| return e,
...@@ -1730,7 +1730,16 @@ fn analyzeBodyInner(...@@ -1730,7 +1730,16 @@ fn analyzeBodyInner(
1730 return result;1730 return result;
1731}1731}
17321732
1733pub fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
1734 if (zir_ref == .none) {
1735 return .none;
1736 } else {
1737 return resolveInst(sema, zir_ref);
1738 }
1739}
1740
1733pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {1741pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
1742 assert(zir_ref != .none);
1734 const i = @enumToInt(zir_ref);1743 const i = @enumToInt(zir_ref);
1735 // First section of indexes correspond to a set number of constant values.1744 // First section of indexes correspond to a set number of constant values.
1736 // We intentionally map the same indexes to the same values between ZIR and AIR.1745 // We intentionally map the same indexes to the same values between ZIR and AIR.
...@@ -1969,6 +1978,7 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(...@@ -1969,6 +1978,7 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
1969 inst: Air.Inst.Ref,1978 inst: Air.Inst.Ref,
1970 make_runtime: *bool,1979 make_runtime: *bool,
1971) CompileError!?Value {1980) CompileError!?Value {
1981 assert(inst != .none);
1972 // First section of indexes correspond to a set number of constant values.1982 // First section of indexes correspond to a set number of constant values.
1973 const int = @enumToInt(inst);1983 const int = @enumToInt(inst);
1974 if (int < InternPool.static_len) {1984 if (int < InternPool.static_len) {
...@@ -1985,17 +1995,17 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(...@@ -1985,17 +1995,17 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
1985 }1995 }
1986 return opv;1996 return opv;
1987 }1997 }
1998 const air_datas = sema.air_instructions.items(.data);
1988 switch (air_tags[i]) {1999 switch (air_tags[i]) {
1989 .constant => {2000 .constant => {
1990 const ty_pl = sema.air_instructions.items(.data)[i].ty_pl;2001 const ty_pl = air_datas[i].ty_pl;
1991 const val = sema.air_values.items[ty_pl.payload];2002 const val = sema.air_values.items[ty_pl.payload];
1992 if (val.tag() == .runtime_value) make_runtime.* = true;2003 if (val.tag() == .runtime_value) make_runtime.* = true;
1993 if (val.isPtrToThreadLocal(sema.mod)) make_runtime.* = true;2004 if (val.isPtrToThreadLocal(sema.mod)) make_runtime.* = true;
1994 return val;2005 return val;
1995 },2006 },
1996 .const_ty => {2007 .const_ty => return try air_datas[i].ty.toValue(sema.arena),
1997 return try sema.air_instructions.items(.data)[i].ty.toValue(sema.arena);2008 .interned => return air_datas[i].interned.toValue(),
1998 },
1999 else => return null,2009 else => return null,
2000 }2010 }
2001}2011}
...@@ -7913,15 +7923,10 @@ fn emitDbgInline(...@@ -7913,15 +7923,10 @@ fn emitDbgInline(
7913 });7923 });
7914}7924}
79157925
7916fn zirIntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {7926fn zirIntType(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
7917 _ = block;
7918 const tracy = trace(@src());
7919 defer tracy.end();
7920
7921 const mod = sema.mod;7927 const mod = sema.mod;
7922 const int_type = sema.code.instructions.items(.data)[inst].int_type;7928 const int_type = sema.code.instructions.items(.data)[inst].int_type;
7923 const ty = try mod.intType(int_type.signedness, int_type.bit_count);7929 const ty = try mod.intType(int_type.signedness, int_type.bit_count);
7924
7925 return sema.addType(ty);7930 return sema.addType(ty);
7926}7931}
79277932
...@@ -17509,7 +17514,7 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)...@@ -17509,7 +17514,7 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)
17509 const tracy = trace(@src());17514 const tracy = trace(@src());
17510 defer tracy.end();17515 defer tracy.end();
1751117516
17512 const saved_index = if (Zir.refToIndex(inst_data.block)) |zir_block| b: {17517 const saved_index = if (Zir.refToIndexAllowNone(inst_data.block)) |zir_block| b: {
17513 var block = start_block;17518 var block = start_block;
17514 while (true) {17519 while (true) {
17515 if (block.label) |label| {17520 if (block.label) |label| {
...@@ -17535,7 +17540,7 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)...@@ -17535,7 +17540,7 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)
1753517540
17536 assert(saved_index != .none); // The .error_return_trace_index field was dropped somewhere17541 assert(saved_index != .none); // The .error_return_trace_index field was dropped somewhere
1753717542
17538 const operand = try sema.resolveInst(inst_data.operand);17543 const operand = try sema.resolveInstAllowNone(inst_data.operand);
17539 return sema.popErrorReturnTrace(start_block, src, operand, saved_index);17544 return sema.popErrorReturnTrace(start_block, src, operand, saved_index);
17540}17545}
1754117546
src/Zir.zig+8-2
...@@ -2132,7 +2132,7 @@ pub const Inst = struct {...@@ -2132,7 +2132,7 @@ pub const Inst = struct {
21322132
2133 /// This Ref does not correspond to any ZIR instruction or constant2133 /// This Ref does not correspond to any ZIR instruction or constant
2134 /// value and may instead be used as a sentinel to indicate null.2134 /// value and may instead be used as a sentinel to indicate null.
2135 none = std.math.maxInt(u32),2135 none = @enumToInt(InternPool.Index.none),
2136 _,2136 _,
2137 };2137 };
21382138
...@@ -3814,13 +3814,14 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {...@@ -3814,13 +3814,14 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
3814 };3814 };
3815}3815}
38163816
3817const ref_start_index: u32 = InternPool.static_len;3817pub const ref_start_index: u32 = InternPool.static_len;
38183818
3819pub fn indexToRef(inst: Inst.Index) Inst.Ref {3819pub fn indexToRef(inst: Inst.Index) Inst.Ref {
3820 return @intToEnum(Inst.Ref, ref_start_index + inst);3820 return @intToEnum(Inst.Ref, ref_start_index + inst);
3821}3821}
38223822
3823pub fn refToIndex(inst: Inst.Ref) ?Inst.Index {3823pub fn refToIndex(inst: Inst.Ref) ?Inst.Index {
3824 assert(inst != .none);
3824 const ref_int = @enumToInt(inst);3825 const ref_int = @enumToInt(inst);
3825 if (ref_int >= ref_start_index) {3826 if (ref_int >= ref_start_index) {
3826 return ref_int - ref_start_index;3827 return ref_int - ref_start_index;
...@@ -3828,3 +3829,8 @@ pub fn refToIndex(inst: Inst.Ref) ?Inst.Index {...@@ -3828,3 +3829,8 @@ pub fn refToIndex(inst: Inst.Ref) ?Inst.Index {
3828 return null;3829 return null;
3829 }3830 }
3830}3831}
3832
3833pub fn refToIndexAllowNone(inst: Inst.Ref) ?Inst.Index {
3834 if (inst == .none) return null;
3835 return refToIndex(inst);
3836}
src/print_air.zig+6-4
...@@ -366,10 +366,12 @@ const Writer = struct {...@@ -366,10 +366,12 @@ const Writer = struct {
366 }366 }
367367
368 fn writeType(w: *Writer, s: anytype, ty: Type) !void {368 fn writeType(w: *Writer, s: anytype, ty: Type) !void {
369 const t = ty.tag();369 switch (ty.ip_index) {
370 switch (t) {370 .none => switch (ty.tag()) {
371 .inferred_alloc_const => try s.writeAll("(inferred_alloc_const)"),371 .inferred_alloc_const => try s.writeAll("(inferred_alloc_const)"),
372 .inferred_alloc_mut => try s.writeAll("(inferred_alloc_mut)"),372 .inferred_alloc_mut => try s.writeAll("(inferred_alloc_mut)"),
373 else => try ty.print(s, w.module),
374 },
373 else => try ty.print(s, w.module),375 else => try ty.print(s, w.module),
374 }376 }
375 }377 }