mirror of
https://github.com/ziglang/zig.git
synced 2026-02-15 05:48:31 +00:00
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
This commit is contained in:
parent
ac07ddadeb
commit
2f05b1482a
16
src/Air.zig
16
src/Air.zig
@ -925,7 +925,7 @@ pub const Inst = struct {
|
||||
|
||||
/// This Ref does not correspond to any AIR instruction or constant
|
||||
/// value and may instead be used as a sentinel to indicate null.
|
||||
none = std.math.maxInt(u32),
|
||||
none = @enumToInt(InternPool.Index.none),
|
||||
_,
|
||||
};
|
||||
|
||||
@ -1461,11 +1461,12 @@ pub fn deinit(air: *Air, gpa: std.mem.Allocator) void {
|
||||
|
||||
pub const ref_start_index: u32 = InternPool.static_len;
|
||||
|
||||
pub fn indexToRef(inst: Air.Inst.Index) Air.Inst.Ref {
|
||||
return @intToEnum(Air.Inst.Ref, ref_start_index + inst);
|
||||
pub fn indexToRef(inst: Inst.Index) Inst.Ref {
|
||||
return @intToEnum(Inst.Ref, ref_start_index + inst);
|
||||
}
|
||||
|
||||
pub fn refToIndex(inst: Air.Inst.Ref) ?Air.Inst.Index {
|
||||
pub fn refToIndex(inst: Inst.Ref) ?Inst.Index {
|
||||
assert(inst != .none);
|
||||
const ref_int = @enumToInt(inst);
|
||||
if (ref_int >= ref_start_index) {
|
||||
return ref_int - ref_start_index;
|
||||
@ -1474,8 +1475,13 @@ pub fn refToIndex(inst: Air.Inst.Ref) ?Air.Inst.Index {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn refToIndexAllowNone(inst: Inst.Ref) ?Inst.Index {
|
||||
if (inst == .none) return null;
|
||||
return refToIndex(inst);
|
||||
}
|
||||
|
||||
/// Returns `null` if runtime-known.
|
||||
pub fn value(air: Air, inst: Air.Inst.Ref, mod: *const Module) ?Value {
|
||||
pub fn value(air: Air, inst: Inst.Ref, mod: *const Module) ?Value {
|
||||
const ref_int = @enumToInt(inst);
|
||||
if (ref_int < ref_start_index) {
|
||||
const ip_index = @intToEnum(InternPool.Index, ref_int);
|
||||
|
||||
@ -1268,7 +1268,7 @@ fn analyzeOperands(
|
||||
_ = data.live_set.remove(inst);
|
||||
|
||||
for (operands) |op_ref| {
|
||||
const operand = Air.refToIndex(op_ref) orelse continue;
|
||||
const operand = Air.refToIndexAllowNone(op_ref) orelse continue;
|
||||
|
||||
// Don't compute any liveness for constants
|
||||
switch (inst_tags[operand]) {
|
||||
@ -1304,7 +1304,7 @@ fn analyzeOperands(
|
||||
while (i > 0) {
|
||||
i -= 1;
|
||||
const op_ref = operands[i];
|
||||
const operand = Air.refToIndex(op_ref) orelse continue;
|
||||
const operand = Air.refToIndexAllowNone(op_ref) orelse continue;
|
||||
|
||||
// Don't compute any liveness for constants
|
||||
switch (inst_tags[operand]) {
|
||||
|
||||
@ -555,7 +555,7 @@ fn verifyDeath(self: *Verify, inst: Air.Inst.Index, operand: Air.Inst.Index) Err
|
||||
}
|
||||
|
||||
fn verifyOperand(self: *Verify, inst: Air.Inst.Index, op_ref: Air.Inst.Ref, dies: bool) Error!void {
|
||||
const operand = Air.refToIndex(op_ref) orelse return;
|
||||
const operand = Air.refToIndexAllowNone(op_ref) orelse return;
|
||||
switch (self.air.instructions.items(.tag)[operand]) {
|
||||
.constant, .const_ty, .interned => {},
|
||||
else => {
|
||||
|
||||
33
src/Sema.zig
33
src/Sema.zig
@ -968,7 +968,7 @@ fn analyzeBodyInner(
|
||||
.int_big => try sema.zirIntBig(block, inst),
|
||||
.float => try sema.zirFloat(block, inst),
|
||||
.float128 => try sema.zirFloat128(block, inst),
|
||||
.int_type => try sema.zirIntType(block, inst),
|
||||
.int_type => try sema.zirIntType(inst),
|
||||
.is_non_err => try sema.zirIsNonErr(block, inst),
|
||||
.is_non_err_ptr => try sema.zirIsNonErrPtr(block, inst),
|
||||
.ret_is_non_err => try sema.zirRetIsNonErr(block, inst),
|
||||
@ -1694,7 +1694,7 @@ fn analyzeBodyInner(
|
||||
const extra = sema.code.extraData(Zir.Inst.DeferErrCode, inst_data.payload_index).data;
|
||||
const defer_body = sema.code.extra[extra.index..][0..extra.len];
|
||||
const err_code = try sema.resolveInst(inst_data.err_code);
|
||||
sema.inst_map.putAssumeCapacity(extra.remapped_err_code, err_code);
|
||||
map.putAssumeCapacity(extra.remapped_err_code, err_code);
|
||||
const break_inst = sema.analyzeBodyInner(block, defer_body) catch |err| switch (err) {
|
||||
error.ComptimeBreak => sema.comptime_break_inst,
|
||||
else => |e| return e,
|
||||
@ -1730,7 +1730,16 @@ fn analyzeBodyInner(
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
|
||||
if (zir_ref == .none) {
|
||||
return .none;
|
||||
} else {
|
||||
return resolveInst(sema, zir_ref);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
|
||||
assert(zir_ref != .none);
|
||||
const i = @enumToInt(zir_ref);
|
||||
// First section of indexes correspond to a set number of constant values.
|
||||
// We intentionally map the same indexes to the same values between ZIR and AIR.
|
||||
@ -1969,6 +1978,7 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
|
||||
inst: Air.Inst.Ref,
|
||||
make_runtime: *bool,
|
||||
) CompileError!?Value {
|
||||
assert(inst != .none);
|
||||
// First section of indexes correspond to a set number of constant values.
|
||||
const int = @enumToInt(inst);
|
||||
if (int < InternPool.static_len) {
|
||||
@ -1985,17 +1995,17 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
|
||||
}
|
||||
return opv;
|
||||
}
|
||||
const air_datas = sema.air_instructions.items(.data);
|
||||
switch (air_tags[i]) {
|
||||
.constant => {
|
||||
const ty_pl = sema.air_instructions.items(.data)[i].ty_pl;
|
||||
const ty_pl = air_datas[i].ty_pl;
|
||||
const val = sema.air_values.items[ty_pl.payload];
|
||||
if (val.tag() == .runtime_value) make_runtime.* = true;
|
||||
if (val.isPtrToThreadLocal(sema.mod)) make_runtime.* = true;
|
||||
return val;
|
||||
},
|
||||
.const_ty => {
|
||||
return try sema.air_instructions.items(.data)[i].ty.toValue(sema.arena);
|
||||
},
|
||||
.const_ty => return try air_datas[i].ty.toValue(sema.arena),
|
||||
.interned => return air_datas[i].interned.toValue(),
|
||||
else => return null,
|
||||
}
|
||||
}
|
||||
@ -7913,15 +7923,10 @@ fn emitDbgInline(
|
||||
});
|
||||
}
|
||||
|
||||
fn zirIntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
_ = block;
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
fn zirIntType(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
const mod = sema.mod;
|
||||
const int_type = sema.code.instructions.items(.data)[inst].int_type;
|
||||
const ty = try mod.intType(int_type.signedness, int_type.bit_count);
|
||||
|
||||
return sema.addType(ty);
|
||||
}
|
||||
|
||||
@ -17509,7 +17514,7 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const saved_index = if (Zir.refToIndex(inst_data.block)) |zir_block| b: {
|
||||
const saved_index = if (Zir.refToIndexAllowNone(inst_data.block)) |zir_block| b: {
|
||||
var block = start_block;
|
||||
while (true) {
|
||||
if (block.label) |label| {
|
||||
@ -17535,7 +17540,7 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)
|
||||
|
||||
assert(saved_index != .none); // The .error_return_trace_index field was dropped somewhere
|
||||
|
||||
const operand = try sema.resolveInst(inst_data.operand);
|
||||
const operand = try sema.resolveInstAllowNone(inst_data.operand);
|
||||
return sema.popErrorReturnTrace(start_block, src, operand, saved_index);
|
||||
}
|
||||
|
||||
|
||||
10
src/Zir.zig
10
src/Zir.zig
@ -2132,7 +2132,7 @@ pub const Inst = struct {
|
||||
|
||||
/// This Ref does not correspond to any ZIR instruction or constant
|
||||
/// value and may instead be used as a sentinel to indicate null.
|
||||
none = std.math.maxInt(u32),
|
||||
none = @enumToInt(InternPool.Index.none),
|
||||
_,
|
||||
};
|
||||
|
||||
@ -3814,13 +3814,14 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
|
||||
};
|
||||
}
|
||||
|
||||
const ref_start_index: u32 = InternPool.static_len;
|
||||
pub const ref_start_index: u32 = InternPool.static_len;
|
||||
|
||||
pub fn indexToRef(inst: Inst.Index) Inst.Ref {
|
||||
return @intToEnum(Inst.Ref, ref_start_index + inst);
|
||||
}
|
||||
|
||||
pub fn refToIndex(inst: Inst.Ref) ?Inst.Index {
|
||||
assert(inst != .none);
|
||||
const ref_int = @enumToInt(inst);
|
||||
if (ref_int >= ref_start_index) {
|
||||
return ref_int - ref_start_index;
|
||||
@ -3828,3 +3829,8 @@ pub fn refToIndex(inst: Inst.Ref) ?Inst.Index {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn refToIndexAllowNone(inst: Inst.Ref) ?Inst.Index {
|
||||
if (inst == .none) return null;
|
||||
return refToIndex(inst);
|
||||
}
|
||||
|
||||
@ -366,10 +366,12 @@ const Writer = struct {
|
||||
}
|
||||
|
||||
fn writeType(w: *Writer, s: anytype, ty: Type) !void {
|
||||
const t = ty.tag();
|
||||
switch (t) {
|
||||
.inferred_alloc_const => try s.writeAll("(inferred_alloc_const)"),
|
||||
.inferred_alloc_mut => try s.writeAll("(inferred_alloc_mut)"),
|
||||
switch (ty.ip_index) {
|
||||
.none => switch (ty.tag()) {
|
||||
.inferred_alloc_const => try s.writeAll("(inferred_alloc_const)"),
|
||||
.inferred_alloc_mut => try s.writeAll("(inferred_alloc_mut)"),
|
||||
else => try ty.print(s, w.module),
|
||||
},
|
||||
else => try ty.print(s, w.module),
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user