authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-06-24 22:21:43+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-27 01:21:32-07:00
logff37ccd298f0ab28a9d0e0ee1110dadc6db4df1e
tree8b7b2ad4bc95f8cbbfd277fbfd7dfd30a7222b3a
parentdae516dbdffaf771e072679a76a6d48f3f0aa182

Air: store interned values in Air.Inst.Ref

Previously, interned values were represented as AIR instructions using the `interned` tag. Now, the AIR ref directly encodes the InternPool index. The encoding works as follows: * If the ref matches one of the static values, it corresponds to the same InternPool index. * Otherwise, if the MSB is 0, the ref corresponds to an InternPool index. * Otherwise, if the MSB is 1, the ref corresponds to an AIR instruction index (after removing the MSB). Note that since most static InternPool indices are low values (the exceptions being `.none` and `.var_args_param_type`), the first rule is almost a nop.

13 files changed, 204 insertions(+), 324 deletions(-)

src/Air.zig+51-46
...@@ -438,9 +438,6 @@ pub const Inst = struct {...@@ -438,9 +438,6 @@ pub const Inst = struct {
438 /// was executed on the operand.438 /// was executed on the operand.
439 /// Uses the `ty_pl` field. Payload is `TryPtr`.439 /// Uses the `ty_pl` field. Payload is `TryPtr`.
440 try_ptr,440 try_ptr,
441 /// A comptime-known value via an index into the InternPool.
442 /// Uses the `interned` field.
443 interned,
444 /// Notes the beginning of a source code statement and marks the line and column.441 /// Notes the beginning of a source code statement and marks the line and column.
445 /// Result type is always void.442 /// Result type is always void.
446 /// Uses the `dbg_stmt` field.443 /// Uses the `dbg_stmt` field.
...@@ -879,6 +876,12 @@ pub const Inst = struct {...@@ -879,6 +876,12 @@ pub const Inst = struct {
879 /// The position of an AIR instruction within the `Air` instructions array.876 /// The position of an AIR instruction within the `Air` instructions array.
880 pub const Index = u32;877 pub const Index = u32;
881878
879 /// Either a reference to a value stored in the InternPool, or a reference to an AIR instruction.
880 /// The most-significant bit of the value is a tag bit. This bit is 1 if the value represents an
881 /// instruction index and 0 if it represents an InternPool index.
882 ///
883 /// The hardcoded refs `none` and `var_args_param_type` are exceptions to this rule: they have
884 /// their tag bit set but refer to the InternPool.
882 pub const Ref = enum(u32) {885 pub const Ref = enum(u32) {
883 u0_type = @intFromEnum(InternPool.Index.u0_type),886 u0_type = @intFromEnum(InternPool.Index.u0_type),
884 i0_type = @intFromEnum(InternPool.Index.i0_type),887 i0_type = @intFromEnum(InternPool.Index.i0_type),
...@@ -979,7 +982,6 @@ pub const Inst = struct {...@@ -979,7 +982,6 @@ pub const Inst = struct {
979 pub const Data = union {982 pub const Data = union {
980 no_op: void,983 no_op: void,
981 un_op: Ref,984 un_op: Ref,
982 interned: InternPool.Index,
983985
984 bin_op: struct {986 bin_op: struct {
985 lhs: Ref,987 lhs: Ref,
...@@ -1216,11 +1218,11 @@ pub fn getMainBody(air: Air) []const Air.Inst.Index {...@@ -1216,11 +1218,11 @@ pub fn getMainBody(air: Air) []const Air.Inst.Index {
1216}1218}
12171219
1218pub fn typeOf(air: *const Air, inst: Air.Inst.Ref, ip: *const InternPool) Type {1220pub fn typeOf(air: *const Air, inst: Air.Inst.Ref, ip: *const InternPool) Type {
1219 const ref_int = @intFromEnum(inst);1221 if (refToInterned(inst)) |ip_index| {
1220 if (ref_int < InternPool.static_keys.len) {1222 return ip.typeOf(ip_index).toType();
1221 return InternPool.static_keys[ref_int].typeOf().toType();1223 } else {
1224 return air.typeOfIndex(refToIndex(inst).?, ip);
1222 }1225 }
1223 return air.typeOfIndex(ref_int - ref_start_index, ip);
1224}1226}
12251227
1226pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) Type {1228pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) Type {
...@@ -1342,8 +1344,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)...@@ -1342,8 +1344,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
1342 .try_ptr,1344 .try_ptr,
1343 => return air.getRefType(datas[inst].ty_pl.ty),1345 => return air.getRefType(datas[inst].ty_pl.ty),
13441346
1345 .interned => return ip.typeOf(datas[inst].interned).toType(),
1346
1347 .not,1347 .not,
1348 .bitcast,1348 .bitcast,
1349 .load,1349 .load,
...@@ -1479,18 +1479,8 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)...@@ -1479,18 +1479,8 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
1479}1479}
14801480
1481pub fn getRefType(air: Air, ref: Air.Inst.Ref) Type {1481pub fn getRefType(air: Air, ref: Air.Inst.Ref) Type {
1482 const ref_int = @intFromEnum(ref);1482 _ = air; // TODO: remove this parameter
1483 if (ref_int < ref_start_index) {1483 return refToInterned(ref).?.toType();
1484 const ip_index = @as(InternPool.Index, @enumFromInt(ref_int));
1485 return ip_index.toType();
1486 }
1487 const inst_index = ref_int - ref_start_index;
1488 const air_tags = air.instructions.items(.tag);
1489 const air_datas = air.instructions.items(.data);
1490 return switch (air_tags[inst_index]) {
1491 .interned => air_datas[inst_index].interned.toType(),
1492 else => unreachable,
1493 };
1494}1484}
14951485
1496/// Returns the requested data, as well as the new index which is at the start of the1486/// Returns the requested data, as well as the new index which is at the start of the
...@@ -1521,40 +1511,56 @@ pub fn deinit(air: *Air, gpa: std.mem.Allocator) void {...@@ -1521,40 +1511,56 @@ pub fn deinit(air: *Air, gpa: std.mem.Allocator) void {
1521 air.* = undefined;1511 air.* = undefined;
1522}1512}
15231513
1524pub const ref_start_index: u32 = InternPool.static_len;1514pub fn refToInternedAllowNone(ref: Inst.Ref) ?InternPool.Index {
1515 return switch (ref) {
1516 .var_args_param_type => .var_args_param_type,
1517 .none => .none,
1518 else => if (@intFromEnum(ref) >> 31 == 0) {
1519 return @as(InternPool.Index, @enumFromInt(@intFromEnum(ref)));
1520 } else null,
1521 };
1522}
15251523
1526pub fn indexToRef(inst: Inst.Index) Inst.Ref {1524pub fn refToInterned(ref: Inst.Ref) ?InternPool.Index {
1527 return @as(Inst.Ref, @enumFromInt(ref_start_index + inst));1525 assert(ref != .none);
1526 return refToInternedAllowNone(ref);
1528}1527}
15291528
1530pub fn refToIndex(inst: Inst.Ref) ?Inst.Index {1529pub fn internedToRef(ip_index: InternPool.Index) Inst.Ref {
1531 assert(inst != .none);1530 assert(@intFromEnum(ip_index) >> 31 == 0);
1532 const ref_int = @intFromEnum(inst);1531 return switch (ip_index) {
1533 if (ref_int >= ref_start_index) {1532 .var_args_param_type => .var_args_param_type,
1534 return ref_int - ref_start_index;1533 .none => .none,
1535 } else {1534 else => @enumFromInt(@as(u31, @intCast(@intFromEnum(ip_index)))),
1536 return null;1535 };
1537 }1536}
1537
1538pub fn refToIndexAllowNone(ref: Inst.Ref) ?Inst.Index {
1539 return switch (ref) {
1540 .var_args_param_type, .none => null,
1541 else => if (@intFromEnum(ref) >> 31 != 0) {
1542 return @as(u31, @truncate(@intFromEnum(ref)));
1543 } else null,
1544 };
1538}1545}
15391546
1540pub fn refToIndexAllowNone(inst: Inst.Ref) ?Inst.Index {1547pub fn refToIndex(ref: Inst.Ref) ?Inst.Index {
1541 if (inst == .none) return null;1548 assert(ref != .none);
1542 return refToIndex(inst);1549 return refToIndexAllowNone(ref);
1550}
1551
1552pub fn indexToRef(inst: Inst.Index) Inst.Ref {
1553 assert(inst >> 31 == 0);
1554 return @enumFromInt((1 << 31) | inst);
1543}1555}
15441556
1545/// Returns `null` if runtime-known.1557/// Returns `null` if runtime-known.
1546pub fn value(air: Air, inst: Inst.Ref, mod: *Module) !?Value {1558pub fn value(air: Air, inst: Inst.Ref, mod: *Module) !?Value {
1547 const ref_int = @intFromEnum(inst);1559 if (refToInterned(inst)) |ip_index| {
1548 if (ref_int < ref_start_index) {
1549 const ip_index = @as(InternPool.Index, @enumFromInt(ref_int));
1550 return ip_index.toValue();1560 return ip_index.toValue();
1551 }1561 }
1552 const inst_index = @as(Air.Inst.Index, @intCast(ref_int - ref_start_index));1562 const index = refToIndex(inst).?;
1553 const air_datas = air.instructions.items(.data);1563 return air.typeOfIndex(index, &mod.intern_pool).onePossibleValue(mod);
1554 switch (air.instructions.items(.tag)[inst_index]) {
1555 .interned => return air_datas[inst_index].interned.toValue(),
1556 else => return air.typeOfIndex(inst_index, &mod.intern_pool).onePossibleValue(mod),
1557 }
1558}1564}
15591565
1560pub fn nullTerminatedString(air: Air, index: usize) [:0]const u8 {1566pub fn nullTerminatedString(air: Air, index: usize) [:0]const u8 {
...@@ -1709,7 +1715,6 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {...@@ -1709,7 +1715,6 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
1709 .cmp_neq_optimized,1715 .cmp_neq_optimized,
1710 .cmp_vector,1716 .cmp_vector,
1711 .cmp_vector_optimized,1717 .cmp_vector_optimized,
1712 .interned,
1713 .is_null,1718 .is_null,
1714 .is_non_null,1719 .is_non_null,
1715 .is_null_ptr,1720 .is_null_ptr,
src/Liveness.zig+1-14
...@@ -324,7 +324,6 @@ pub fn categorizeOperand(...@@ -324,7 +324,6 @@ pub fn categorizeOperand(
324 .inferred_alloc,324 .inferred_alloc,
325 .inferred_alloc_comptime,325 .inferred_alloc_comptime,
326 .ret_ptr,326 .ret_ptr,
327 .interned,
328 .trap,327 .trap,
329 .breakpoint,328 .breakpoint,
330 .dbg_stmt,329 .dbg_stmt,
...@@ -981,7 +980,7 @@ fn analyzeInst(...@@ -981,7 +980,7 @@ fn analyzeInst(
981 .work_group_id,980 .work_group_id,
982 => return analyzeOperands(a, pass, data, inst, .{ .none, .none, .none }),981 => return analyzeOperands(a, pass, data, inst, .{ .none, .none, .none }),
983982
984 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,983 .inferred_alloc, .inferred_alloc_comptime => unreachable,
985984
986 .trap,985 .trap,
987 .unreach,986 .unreach,
...@@ -1264,7 +1263,6 @@ fn analyzeOperands(...@@ -1264,7 +1263,6 @@ fn analyzeOperands(
1264 operands: [bpi - 1]Air.Inst.Ref,1263 operands: [bpi - 1]Air.Inst.Ref,
1265) Allocator.Error!void {1264) Allocator.Error!void {
1266 const gpa = a.gpa;1265 const gpa = a.gpa;
1267 const inst_tags = a.air.instructions.items(.tag);
1268 const ip = a.intern_pool;1266 const ip = a.intern_pool;
12691267
1270 switch (pass) {1268 switch (pass) {
...@@ -1273,10 +1271,6 @@ fn analyzeOperands(...@@ -1273,10 +1271,6 @@ fn analyzeOperands(
12731271
1274 for (operands) |op_ref| {1272 for (operands) |op_ref| {
1275 const operand = Air.refToIndexAllowNone(op_ref) orelse continue;1273 const operand = Air.refToIndexAllowNone(op_ref) orelse continue;
1276
1277 // Don't compute any liveness for constants
1278 if (inst_tags[operand] == .interned) continue;
1279
1280 _ = try data.live_set.put(gpa, operand, {});1274 _ = try data.live_set.put(gpa, operand, {});
1281 }1275 }
1282 },1276 },
...@@ -1307,9 +1301,6 @@ fn analyzeOperands(...@@ -1307,9 +1301,6 @@ fn analyzeOperands(
1307 const op_ref = operands[i];1301 const op_ref = operands[i];
1308 const operand = Air.refToIndexAllowNone(op_ref) orelse continue;1302 const operand = Air.refToIndexAllowNone(op_ref) orelse continue;
13091303
1310 // Don't compute any liveness for constants
1311 if (inst_tags[operand] == .interned) continue;
1312
1313 const mask = @as(Bpi, 1) << @as(OperandInt, @intCast(i));1304 const mask = @as(Bpi, 1) << @as(OperandInt, @intCast(i));
13141305
1315 if ((try data.live_set.fetchPut(gpa, operand, {})) == null) {1306 if ((try data.live_set.fetchPut(gpa, operand, {})) == null) {
...@@ -1837,10 +1828,6 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type {...@@ -1837,10 +1828,6 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type {
18371828
1838 const operand = Air.refToIndex(op_ref) orelse return;1829 const operand = Air.refToIndex(op_ref) orelse return;
18391830
1840 // Don't compute any liveness for constants
1841 const inst_tags = big.a.air.instructions.items(.tag);
1842 if (inst_tags[operand] == .interned) return
1843
1844 // If our result is unused and the instruction doesn't need to be lowered, backends will1831 // If our result is unused and the instruction doesn't need to be lowered, backends will
1845 // skip the lowering of this instruction, so we don't want to record uses of operands.1832 // skip the lowering of this instruction, so we don't want to record uses of operands.
1846 // That way, we can mark as many instructions as possible unused.1833 // That way, we can mark as many instructions as possible unused.
src/Liveness/Verify.zig-6
...@@ -44,7 +44,6 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {...@@ -44,7 +44,6 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
44 .inferred_alloc,44 .inferred_alloc,
45 .inferred_alloc_comptime,45 .inferred_alloc_comptime,
46 .ret_ptr,46 .ret_ptr,
47 .interned,
48 .breakpoint,47 .breakpoint,
49 .dbg_stmt,48 .dbg_stmt,
50 .dbg_inline_begin,49 .dbg_inline_begin,
...@@ -559,10 +558,6 @@ fn verifyOperand(self: *Verify, inst: Air.Inst.Index, op_ref: Air.Inst.Ref, dies...@@ -559,10 +558,6 @@ fn verifyOperand(self: *Verify, inst: Air.Inst.Index, op_ref: Air.Inst.Ref, dies
559 assert(!dies);558 assert(!dies);
560 return;559 return;
561 };560 };
562 if (self.air.instructions.items(.tag)[operand] == .interned) {
563 assert(!dies);
564 return;
565 }
566 if (dies) {561 if (dies) {
567 if (!self.live.remove(operand)) return invalid("%{}: dead operand %{} reused and killed again", .{ inst, operand });562 if (!self.live.remove(operand)) return invalid("%{}: dead operand %{} reused and killed again", .{ inst, operand });
568 } else {563 } else {
...@@ -583,7 +578,6 @@ fn verifyInstOperands(...@@ -583,7 +578,6 @@ fn verifyInstOperands(
583}578}
584579
585fn verifyInst(self: *Verify, inst: Air.Inst.Index) Error!void {580fn verifyInst(self: *Verify, inst: Air.Inst.Index) Error!void {
586 if (self.air.instructions.items(.tag)[inst] == .interned) return;
587 if (self.liveness.isUnused(inst)) {581 if (self.liveness.isUnused(inst)) {
588 assert(!self.live.contains(inst));582 assert(!self.live.contains(inst));
589 } else {583 } else {
src/Sema.zig+58-62
...@@ -2068,28 +2068,26 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(...@@ -2068,28 +2068,26 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
2068) CompileError!?Value {2068) CompileError!?Value {
2069 assert(inst != .none);2069 assert(inst != .none);
2070 // First section of indexes correspond to a set number of constant values.2070 // First section of indexes correspond to a set number of constant values.
2071 const int = @intFromEnum(inst);2071 if (@intFromEnum(inst) < InternPool.static_len) {
2072 if (int < InternPool.static_len) {2072 return @as(InternPool.Index, @enumFromInt(@intFromEnum(inst))).toValue();
2073 return @as(InternPool.Index, @enumFromInt(int)).toValue();
2074 }2073 }
20752074
2076 const i = int - InternPool.static_len;
2077 const air_tags = sema.air_instructions.items(.tag);2075 const air_tags = sema.air_instructions.items(.tag);
2078 if (try sema.typeHasOnePossibleValue(sema.typeOf(inst))) |opv| {2076 if (try sema.typeHasOnePossibleValue(sema.typeOf(inst))) |opv| {
2079 if (air_tags[i] == .interned) {2077 if (Air.refToInterned(inst)) |ip_index| {
2080 const interned = sema.air_instructions.items(.data)[i].interned;2078 const val = ip_index.toValue();
2081 const val = interned.toValue();
2082 if (val.getVariable(sema.mod) != null) return val;2079 if (val.getVariable(sema.mod) != null) return val;
2083 }2080 }
2084 return opv;2081 return opv;
2085 }2082 }
2086 const air_datas = sema.air_instructions.items(.data);2083 const ip_index = Air.refToInterned(inst) orelse {
2087 const val = switch (air_tags[i]) {2084 switch (air_tags[Air.refToIndex(inst).?]) {
2088 .inferred_alloc => unreachable,2085 .inferred_alloc => unreachable,
2089 .inferred_alloc_comptime => unreachable,2086 .inferred_alloc_comptime => unreachable,
2090 .interned => air_datas[i].interned.toValue(),2087 else => return null,
2091 else => return null,2088 }
2092 };2089 };
2090 const val = ip_index.toValue();
2093 if (val.isRuntimeValue(sema.mod)) make_runtime.* = true;2091 if (val.isRuntimeValue(sema.mod)) make_runtime.* = true;
2094 if (val.isPtrToThreadLocal(sema.mod)) make_runtime.* = true;2092 if (val.isPtrToThreadLocal(sema.mod)) make_runtime.* = true;
2095 return val;2093 return val;
...@@ -3868,18 +3866,23 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3868,18 +3866,23 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3868 },3866 },
3869 });3867 });
38703868
3869 if (std.debug.runtime_safety) {
3870 // The inferred_alloc_comptime should never be referenced again
3871 sema.air_instructions.set(ptr_inst, .{ .tag = undefined, .data = undefined });
3872 }
3873
3871 try sema.maybeQueueFuncBodyAnalysis(decl_index);3874 try sema.maybeQueueFuncBodyAnalysis(decl_index);
3872 // Change it to an interned.3875
3873 sema.air_instructions.set(ptr_inst, .{3876 const interned = try mod.intern(.{ .ptr = .{
3874 .tag = .interned,3877 .ty = final_ptr_ty.toIntern(),
3875 .data = .{ .interned = try mod.intern(.{ .ptr = .{3878 .addr = if (!iac.is_const) .{ .mut_decl = .{
3876 .ty = final_ptr_ty.toIntern(),3879 .decl = decl_index,
3877 .addr = if (!iac.is_const) .{ .mut_decl = .{3880 .runtime_index = block.runtime_index,
3878 .decl = decl_index,3881 } } else .{ .decl = decl_index },
3879 .runtime_index = block.runtime_index,3882 } });
3880 } } else .{ .decl = decl_index },3883
3881 } }) },3884 // Remap the ZIR operand to the resolved pointer value
3882 });3885 sema.inst_map.putAssumeCapacity(Zir.refToIndex(inst_data.operand).?, Air.internedToRef(interned));
3883 },3886 },
3884 .inferred_alloc => {3887 .inferred_alloc => {
3885 const ia1 = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc;3888 const ia1 = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc;
...@@ -3966,17 +3969,22 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3966,17 +3969,22 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3966 };3969 };
3967 try mod.declareDeclDependency(sema.owner_decl_index, new_decl_index);3970 try mod.declareDeclDependency(sema.owner_decl_index, new_decl_index);
39683971
3969 // Even though we reuse the constant instruction, we still remove it from the3972 // Remove the instruction from the block so that codegen does not see it.
3970 // block so that codegen does not see it.
3971 block.instructions.shrinkRetainingCapacity(search_index);3973 block.instructions.shrinkRetainingCapacity(search_index);
3972 try sema.maybeQueueFuncBodyAnalysis(new_decl_index);3974 try sema.maybeQueueFuncBodyAnalysis(new_decl_index);
3973 sema.air_instructions.set(ptr_inst, .{3975
3974 .tag = .interned,3976 if (std.debug.runtime_safety) {
3975 .data = .{ .interned = try mod.intern(.{ .ptr = .{3977 // The inferred_alloc should never be referenced again
3976 .ty = final_ptr_ty.toIntern(),3978 sema.air_instructions.set(ptr_inst, .{ .tag = undefined, .data = undefined });
3977 .addr = .{ .decl = new_decl_index },3979 }
3978 } }) },3980
3979 });3981 const interned = try mod.intern(.{ .ptr = .{
3982 .ty = final_ptr_ty.toIntern(),
3983 .addr = .{ .decl = new_decl_index },
3984 } });
3985
3986 // Remap the ZIR oeprand to the resolved pointer value
3987 sema.inst_map.putAssumeCapacity(Zir.refToIndex(inst_data.operand).?, Air.internedToRef(interned));
39803988
3981 // Unless the block is comptime, `alloc_inferred` always produces3989 // Unless the block is comptime, `alloc_inferred` always produces
3982 // a runtime constant. The final inferred type needs to be3990 // a runtime constant. The final inferred type needs to be
...@@ -4404,7 +4412,6 @@ fn validateUnionInit(...@@ -4404,7 +4412,6 @@ fn validateUnionInit(
4404 const air_tags = sema.air_instructions.items(.tag);4412 const air_tags = sema.air_instructions.items(.tag);
4405 const air_datas = sema.air_instructions.items(.data);4413 const air_datas = sema.air_instructions.items(.data);
4406 const field_ptr_air_ref = sema.inst_map.get(field_ptr).?;4414 const field_ptr_air_ref = sema.inst_map.get(field_ptr).?;
4407 const field_ptr_air_inst = Air.refToIndex(field_ptr_air_ref).?;
44084415
4409 // Our task here is to determine if the union is comptime-known. In such case,4416 // Our task here is to determine if the union is comptime-known. In such case,
4410 // we erase the runtime AIR instructions for initializing the union, and replace4417 // we erase the runtime AIR instructions for initializing the union, and replace
...@@ -4434,7 +4441,7 @@ fn validateUnionInit(...@@ -4434,7 +4441,7 @@ fn validateUnionInit(
4434 var make_runtime = false;4441 var make_runtime = false;
4435 while (block_index > 0) : (block_index -= 1) {4442 while (block_index > 0) : (block_index -= 1) {
4436 const store_inst = block.instructions.items[block_index];4443 const store_inst = block.instructions.items[block_index];
4437 if (store_inst == field_ptr_air_inst) break;4444 if (Air.indexToRef(store_inst) == field_ptr_air_ref) break;
4438 switch (air_tags[store_inst]) {4445 switch (air_tags[store_inst]) {
4439 .store, .store_safe => {},4446 .store, .store_safe => {},
4440 else => continue,4447 else => continue,
...@@ -4453,7 +4460,7 @@ fn validateUnionInit(...@@ -4453,7 +4460,7 @@ fn validateUnionInit(
4453 if (air_tags[block_inst] != .dbg_stmt) break;4460 if (air_tags[block_inst] != .dbg_stmt) break;
4454 }4461 }
4455 if (block_index > 0 and4462 if (block_index > 0 and
4456 field_ptr_air_inst == block.instructions.items[block_index - 1])4463 field_ptr_air_ref == Air.indexToRef(block.instructions.items[block_index - 1]))
4457 {4464 {
4458 first_block_index = @min(first_block_index, block_index - 1);4465 first_block_index = @min(first_block_index, block_index - 1);
4459 } else {4466 } else {
...@@ -4622,7 +4629,6 @@ fn validateStructInit(...@@ -4622,7 +4629,6 @@ fn validateStructInit(
4622 }4629 }
46234630
4624 const field_ptr_air_ref = sema.inst_map.get(field_ptr).?;4631 const field_ptr_air_ref = sema.inst_map.get(field_ptr).?;
4625 const field_ptr_air_inst = Air.refToIndex(field_ptr_air_ref).?;
46264632
4627 //std.debug.print("validateStructInit (field_ptr_air_inst=%{d}):\n", .{4633 //std.debug.print("validateStructInit (field_ptr_air_inst=%{d}):\n", .{
4628 // field_ptr_air_inst,4634 // field_ptr_air_inst,
...@@ -4652,7 +4658,7 @@ fn validateStructInit(...@@ -4652,7 +4658,7 @@ fn validateStructInit(
4652 var block_index = block.instructions.items.len - 1;4658 var block_index = block.instructions.items.len - 1;
4653 while (block_index > 0) : (block_index -= 1) {4659 while (block_index > 0) : (block_index -= 1) {
4654 const store_inst = block.instructions.items[block_index];4660 const store_inst = block.instructions.items[block_index];
4655 if (store_inst == field_ptr_air_inst) {4661 if (Air.indexToRef(store_inst) == field_ptr_air_ref) {
4656 struct_is_comptime = false;4662 struct_is_comptime = false;
4657 continue :field;4663 continue :field;
4658 }4664 }
...@@ -4675,7 +4681,7 @@ fn validateStructInit(...@@ -4675,7 +4681,7 @@ fn validateStructInit(
4675 if (air_tags[block_inst] != .dbg_stmt) break;4681 if (air_tags[block_inst] != .dbg_stmt) break;
4676 }4682 }
4677 if (block_index > 0 and4683 if (block_index > 0 and
4678 field_ptr_air_inst == block.instructions.items[block_index - 1])4684 field_ptr_air_ref == Air.indexToRef(block.instructions.items[block_index - 1]))
4679 {4685 {
4680 first_block_index = @min(first_block_index, block_index - 1);4686 first_block_index = @min(first_block_index, block_index - 1);
4681 } else {4687 } else {
...@@ -4865,7 +4871,6 @@ fn zirValidateArrayInit(...@@ -4865,7 +4871,6 @@ fn zirValidateArrayInit(
4865 }4871 }
48664872
4867 const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?;4873 const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?;
4868 const elem_ptr_air_inst = Air.refToIndex(elem_ptr_air_ref).?;
48694874
4870 // We expect to see something like this in the current block AIR:4875 // We expect to see something like this in the current block AIR:
4871 // %a = elem_ptr(...)4876 // %a = elem_ptr(...)
...@@ -4890,7 +4895,7 @@ fn zirValidateArrayInit(...@@ -4890,7 +4895,7 @@ fn zirValidateArrayInit(
4890 var block_index = block.instructions.items.len - 1;4895 var block_index = block.instructions.items.len - 1;
4891 while (block_index > 0) : (block_index -= 1) {4896 while (block_index > 0) : (block_index -= 1) {
4892 const store_inst = block.instructions.items[block_index];4897 const store_inst = block.instructions.items[block_index];
4893 if (store_inst == elem_ptr_air_inst) {4898 if (Air.indexToRef(store_inst) == elem_ptr_air_ref) {
4894 array_is_comptime = false;4899 array_is_comptime = false;
4895 continue :outer;4900 continue :outer;
4896 }4901 }
...@@ -4913,7 +4918,7 @@ fn zirValidateArrayInit(...@@ -4913,7 +4918,7 @@ fn zirValidateArrayInit(
4913 if (air_tags[block_inst] != .dbg_stmt) break;4918 if (air_tags[block_inst] != .dbg_stmt) break;
4914 }4919 }
4915 if (block_index > 0 and4920 if (block_index > 0 and
4916 elem_ptr_air_inst == block.instructions.items[block_index - 1])4921 elem_ptr_air_ref == Air.indexToRef(block.instructions.items[block_index - 1]))
4917 {4922 {
4918 first_block_index = @min(first_block_index, block_index - 1);4923 first_block_index = @min(first_block_index, block_index - 1);
4919 } else {4924 } else {
...@@ -5785,8 +5790,7 @@ fn analyzeBlockBody(...@@ -5785,8 +5790,7 @@ fn analyzeBlockBody(
5785 sema.air_instructions.items(.data)[br].br.operand = coerced_operand;5790 sema.air_instructions.items(.data)[br].br.operand = coerced_operand;
5786 continue;5791 continue;
5787 }5792 }
5788 assert(coerce_block.instructions.items[coerce_block.instructions.items.len - 1] ==5793 assert(Air.indexToRef(coerce_block.instructions.items[coerce_block.instructions.items.len - 1]) == coerced_operand);
5789 Air.refToIndex(coerced_operand).?);
57905794
5791 // Convert the br instruction to a block instruction that has the coercion5795 // Convert the br instruction to a block instruction that has the coercion
5792 // and then a new br inside that returns the coerced instruction.5796 // and then a new br inside that returns the coerced instruction.
...@@ -30397,8 +30401,8 @@ fn analyzeDeclVal(...@@ -30397,8 +30401,8 @@ fn analyzeDeclVal(
30397 }30401 }
30398 const decl_ref = try sema.analyzeDeclRefInner(decl_index, false);30402 const decl_ref = try sema.analyzeDeclRefInner(decl_index, false);
30399 const result = try sema.analyzeLoad(block, src, decl_ref, src);30403 const result = try sema.analyzeLoad(block, src, decl_ref, src);
30400 if (Air.refToIndex(result)) |index| {30404 if (Air.refToInterned(result) != null) {
30401 if (sema.air_instructions.items(.tag)[index] == .interned and !block.is_typeof) {30405 if (!block.is_typeof) {
30402 try sema.decl_val_table.put(sema.gpa, decl_index, result);30406 try sema.decl_val_table.put(sema.gpa, decl_index, result);
30403 }30407 }
30404 }30408 }
...@@ -30720,7 +30724,7 @@ fn analyzeIsNonErrComptimeOnly(...@@ -30720,7 +30724,7 @@ fn analyzeIsNonErrComptimeOnly(
30720 }30724 }
30721 } else if (operand == .undef) {30725 } else if (operand == .undef) {
30722 return sema.addConstUndef(Type.bool);30726 return sema.addConstUndef(Type.bool);
30723 } else {30727 } else if (@intFromEnum(operand) < InternPool.static_len) {
30724 // None of the ref tags can be errors.30728 // None of the ref tags can be errors.
30725 return Air.Inst.Ref.bool_true;30729 return Air.Inst.Ref.bool_true;
30726 }30730 }
...@@ -35494,14 +35498,10 @@ pub fn getTmpAir(sema: Sema) Air {...@@ -35494,14 +35498,10 @@ pub fn getTmpAir(sema: Sema) Air {
35494 };35498 };
35495}35499}
3549635500
35501// TODO: make this non-fallible or remove it entirely
35497pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {35502pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {
35498 if (@intFromEnum(ty.toIntern()) < Air.ref_start_index)35503 _ = sema;
35499 return @as(Air.Inst.Ref, @enumFromInt(@intFromEnum(ty.toIntern())));35504 return Air.internedToRef(ty.toIntern());
35500 try sema.air_instructions.append(sema.gpa, .{
35501 .tag = .interned,
35502 .data = .{ .interned = ty.toIntern() },
35503 });
35504 return Air.indexToRef(@as(u32, @intCast(sema.air_instructions.len - 1)));
35505}35505}
3550635506
35507fn addIntUnsigned(sema: *Sema, ty: Type, int: u64) CompileError!Air.Inst.Ref {35507fn addIntUnsigned(sema: *Sema, ty: Type, int: u64) CompileError!Air.Inst.Ref {
...@@ -35513,14 +35513,10 @@ fn addConstUndef(sema: *Sema, ty: Type) CompileError!Air.Inst.Ref {...@@ -35513,14 +35513,10 @@ fn addConstUndef(sema: *Sema, ty: Type) CompileError!Air.Inst.Ref {
35513 return sema.addConstant((try sema.mod.intern(.{ .undef = ty.toIntern() })).toValue());35513 return sema.addConstant((try sema.mod.intern(.{ .undef = ty.toIntern() })).toValue());
35514}35514}
3551535515
35516pub fn addConstant(sema: *Sema, val: Value) SemaError!Air.Inst.Ref {35516// TODO: make this non-fallible or remove it entirely
35517 if (@intFromEnum(val.toIntern()) < Air.ref_start_index)35517pub fn addConstant(sema: *Sema, val: Value) !Air.Inst.Ref {
35518 return @as(Air.Inst.Ref, @enumFromInt(@intFromEnum(val.toIntern())));35518 _ = sema;
35519 try sema.air_instructions.append(sema.gpa, .{35519 return Air.internedToRef(val.toIntern());
35520 .tag = .interned,
35521 .data = .{ .interned = val.toIntern() },
35522 });
35523 return Air.indexToRef(@as(u32, @intCast(sema.air_instructions.len - 1)));
35524}35520}
3552535521
35526pub fn addExtra(sema: *Sema, extra: anytype) Allocator.Error!u32 {35522pub fn addExtra(sema: *Sema, extra: anytype) Allocator.Error!u32 {
src/arch/aarch64/CodeGen.zig+4-24
...@@ -845,7 +845,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -845,7 +845,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
845 .ptr_elem_val => try self.airPtrElemVal(inst),845 .ptr_elem_val => try self.airPtrElemVal(inst),
846 .ptr_elem_ptr => try self.airPtrElemPtr(inst),846 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
847847
848 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,848 .inferred_alloc, .inferred_alloc_comptime => unreachable,
849 .unreach => self.finishAirBookkeeping(),849 .unreach => self.finishAirBookkeeping(),
850850
851 .optional_payload => try self.airOptionalPayload(inst),851 .optional_payload => try self.airOptionalPayload(inst),
...@@ -920,7 +920,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -920,7 +920,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
920920
921/// Asserts there is already capacity to insert into top branch inst_table.921/// Asserts there is already capacity to insert into top branch inst_table.
922fn processDeath(self: *Self, inst: Air.Inst.Index) void {922fn processDeath(self: *Self, inst: Air.Inst.Index) void {
923 assert(self.air.instructions.items(.tag)[inst] != .interned);
924 // When editing this function, note that the logic must synchronize with `reuseOperand`.923 // When editing this function, note that the logic must synchronize with `reuseOperand`.
925 const prev_value = self.getResolvedInstValue(inst);924 const prev_value = self.getResolvedInstValue(inst);
926 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];925 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
...@@ -953,9 +952,7 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live...@@ -953,9 +952,7 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
953 const dies = @as(u1, @truncate(tomb_bits)) != 0;952 const dies = @as(u1, @truncate(tomb_bits)) != 0;
954 tomb_bits >>= 1;953 tomb_bits >>= 1;
955 if (!dies) continue;954 if (!dies) continue;
956 const op_int = @intFromEnum(op);955 const op_index = Air.refToIndex(op) orelse continue;
957 if (op_int < Air.ref_start_index) continue;
958 const op_index = @as(Air.Inst.Index, @intCast(op_int - Air.ref_start_index));
959 self.processDeath(op_index);956 self.processDeath(op_index);
960 }957 }
961 const is_used = @as(u1, @truncate(tomb_bits)) == 0;958 const is_used = @as(u1, @truncate(tomb_bits)) == 0;
...@@ -4696,9 +4693,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4696,9 +4693,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
4696 // that death now instead of later as this has an effect on4693 // that death now instead of later as this has an effect on
4697 // whether it needs to be spilled in the branches4694 // whether it needs to be spilled in the branches
4698 if (self.liveness.operandDies(inst, 0)) {4695 if (self.liveness.operandDies(inst, 0)) {
4699 const op_int = @intFromEnum(pl_op.operand);4696 if (Air.refToIndex(pl_op.operand)) |op_index| {
4700 if (op_int >= Air.ref_start_index) {
4701 const op_index = @as(Air.Inst.Index, @intCast(op_int - Air.ref_start_index));
4702 self.processDeath(op_index);4697 self.processDeath(op_index);
4703 }4698 }
4704 }4699 }
...@@ -6149,22 +6144,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {...@@ -6149,22 +6144,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
6149 .val = (try self.air.value(inst, mod)).?,6144 .val = (try self.air.value(inst, mod)).?,
6150 });6145 });
61516146
6152 switch (self.air.instructions.items(.tag)[inst_index]) {6147 return self.getResolvedInstValue(inst_index);
6153 .interned => {
6154 // Constants have static lifetimes, so they are always memoized in the outer most table.
6155 const branch = &self.branch_stack.items[0];
6156 const gop = try branch.inst_table.getOrPut(self.gpa, inst_index);
6157 if (!gop.found_existing) {
6158 const interned = self.air.instructions.items(.data)[inst_index].interned;
6159 gop.value_ptr.* = try self.genTypedValue(.{
6160 .ty = inst_ty,
6161 .val = interned.toValue(),
6162 });
6163 }
6164 return gop.value_ptr.*;
6165 },
6166 else => return self.getResolvedInstValue(inst_index),
6167 }
6168}6148}
61696149
6170fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {6150fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
src/arch/arm/CodeGen.zig+4-24
...@@ -829,7 +829,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -829,7 +829,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
829 .ptr_elem_val => try self.airPtrElemVal(inst),829 .ptr_elem_val => try self.airPtrElemVal(inst),
830 .ptr_elem_ptr => try self.airPtrElemPtr(inst),830 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
831831
832 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,832 .inferred_alloc, .inferred_alloc_comptime => unreachable,
833 .unreach => self.finishAirBookkeeping(),833 .unreach => self.finishAirBookkeeping(),
834834
835 .optional_payload => try self.airOptionalPayload(inst),835 .optional_payload => try self.airOptionalPayload(inst),
...@@ -904,7 +904,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -904,7 +904,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
904904
905/// Asserts there is already capacity to insert into top branch inst_table.905/// Asserts there is already capacity to insert into top branch inst_table.
906fn processDeath(self: *Self, inst: Air.Inst.Index) void {906fn processDeath(self: *Self, inst: Air.Inst.Index) void {
907 assert(self.air.instructions.items(.tag)[inst] != .interned);
908 // When editing this function, note that the logic must synchronize with `reuseOperand`.907 // When editing this function, note that the logic must synchronize with `reuseOperand`.
909 const prev_value = self.getResolvedInstValue(inst);908 const prev_value = self.getResolvedInstValue(inst);
910 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];909 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
...@@ -939,9 +938,7 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live...@@ -939,9 +938,7 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
939 const dies = @as(u1, @truncate(tomb_bits)) != 0;938 const dies = @as(u1, @truncate(tomb_bits)) != 0;
940 tomb_bits >>= 1;939 tomb_bits >>= 1;
941 if (!dies) continue;940 if (!dies) continue;
942 const op_int = @intFromEnum(op);941 const op_index = Air.refToIndex(op) orelse continue;
943 if (op_int < Air.ref_start_index) continue;
944 const op_index = @as(Air.Inst.Index, @intCast(op_int - Air.ref_start_index));
945 self.processDeath(op_index);942 self.processDeath(op_index);
946 }943 }
947 const is_used = @as(u1, @truncate(tomb_bits)) == 0;944 const is_used = @as(u1, @truncate(tomb_bits)) == 0;
...@@ -4651,9 +4648,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4651,9 +4648,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
4651 // that death now instead of later as this has an effect on4648 // that death now instead of later as this has an effect on
4652 // whether it needs to be spilled in the branches4649 // whether it needs to be spilled in the branches
4653 if (self.liveness.operandDies(inst, 0)) {4650 if (self.liveness.operandDies(inst, 0)) {
4654 const op_int = @intFromEnum(pl_op.operand);4651 if (Air.refToIndex(pl_op.operand)) |op_index| {
4655 if (op_int >= Air.ref_start_index) {
4656 const op_index = @as(Air.Inst.Index, @intCast(op_int - Air.ref_start_index));
4657 self.processDeath(op_index);4652 self.processDeath(op_index);
4658 }4653 }
4659 }4654 }
...@@ -6102,22 +6097,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {...@@ -6102,22 +6097,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
6102 .val = (try self.air.value(inst, mod)).?,6097 .val = (try self.air.value(inst, mod)).?,
6103 });6098 });
61046099
6105 switch (self.air.instructions.items(.tag)[inst_index]) {6100 return self.getResolvedInstValue(inst_index);
6106 .interned => {
6107 // Constants have static lifetimes, so they are always memoized in the outer most table.
6108 const branch = &self.branch_stack.items[0];
6109 const gop = try branch.inst_table.getOrPut(self.gpa, inst_index);
6110 if (!gop.found_existing) {
6111 const interned = self.air.instructions.items(.data)[inst_index].interned;
6112 gop.value_ptr.* = try self.genTypedValue(.{
6113 .ty = inst_ty,
6114 .val = interned.toValue(),
6115 });
6116 }
6117 return gop.value_ptr.*;
6118 },
6119 else => return self.getResolvedInstValue(inst_index),
6120 }
6121}6101}
61226102
6123fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {6103fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
src/arch/riscv64/CodeGen.zig+3-21
...@@ -664,7 +664,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -664,7 +664,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
664 .ptr_elem_val => try self.airPtrElemVal(inst),664 .ptr_elem_val => try self.airPtrElemVal(inst),
665 .ptr_elem_ptr => try self.airPtrElemPtr(inst),665 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
666666
667 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,667 .inferred_alloc, .inferred_alloc_comptime => unreachable,
668 .unreach => self.finishAirBookkeeping(),668 .unreach => self.finishAirBookkeeping(),
669669
670 .optional_payload => try self.airOptionalPayload(inst),670 .optional_payload => try self.airOptionalPayload(inst),
...@@ -731,7 +731,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -731,7 +731,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
731731
732/// Asserts there is already capacity to insert into top branch inst_table.732/// Asserts there is already capacity to insert into top branch inst_table.
733fn processDeath(self: *Self, inst: Air.Inst.Index) void {733fn processDeath(self: *Self, inst: Air.Inst.Index) void {
734 assert(self.air.instructions.items(.tag)[inst] != .interned);
735 // When editing this function, note that the logic must synchronize with `reuseOperand`.734 // When editing this function, note that the logic must synchronize with `reuseOperand`.
736 const prev_value = self.getResolvedInstValue(inst);735 const prev_value = self.getResolvedInstValue(inst);
737 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];736 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
...@@ -757,9 +756,7 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live...@@ -757,9 +756,7 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
757 const dies = @as(u1, @truncate(tomb_bits)) != 0;756 const dies = @as(u1, @truncate(tomb_bits)) != 0;
758 tomb_bits >>= 1;757 tomb_bits >>= 1;
759 if (!dies) continue;758 if (!dies) continue;
760 const op_int = @intFromEnum(op);759 const op_index = Air.refToIndex(op) orelse continue;
761 if (op_int < Air.ref_start_index) continue;
762 const op_index = @as(Air.Inst.Index, @intCast(op_int - Air.ref_start_index));
763 self.processDeath(op_index);760 self.processDeath(op_index);
764 }761 }
765 const is_used = @as(u1, @truncate(tomb_bits)) == 0;762 const is_used = @as(u1, @truncate(tomb_bits)) == 0;
...@@ -2556,22 +2553,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {...@@ -2556,22 +2553,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
2556 .val = (try self.air.value(inst, mod)).?,2553 .val = (try self.air.value(inst, mod)).?,
2557 });2554 });
25582555
2559 switch (self.air.instructions.items(.tag)[inst_index]) {2556 return self.getResolvedInstValue(inst_index);
2560 .interned => {
2561 // Constants have static lifetimes, so they are always memoized in the outer most table.
2562 const branch = &self.branch_stack.items[0];
2563 const gop = try branch.inst_table.getOrPut(self.gpa, inst_index);
2564 if (!gop.found_existing) {
2565 const interned = self.air.instructions.items(.data)[inst_index].interned;
2566 gop.value_ptr.* = try self.genTypedValue(.{
2567 .ty = inst_ty,
2568 .val = interned.toValue(),
2569 });
2570 }
2571 return gop.value_ptr.*;
2572 },
2573 else => return self.getResolvedInstValue(inst_index),
2574 }
2575}2557}
25762558
2577fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {2559fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
src/arch/sparc64/CodeGen.zig+4-24
...@@ -677,7 +677,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -677,7 +677,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
677 .ptr_elem_val => try self.airPtrElemVal(inst),677 .ptr_elem_val => try self.airPtrElemVal(inst),
678 .ptr_elem_ptr => try self.airPtrElemPtr(inst),678 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
679679
680 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,680 .inferred_alloc, .inferred_alloc_comptime => unreachable,
681 .unreach => self.finishAirBookkeeping(),681 .unreach => self.finishAirBookkeeping(),
682682
683 .optional_payload => try self.airOptionalPayload(inst),683 .optional_payload => try self.airOptionalPayload(inst),
...@@ -1515,9 +1515,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1515,9 +1515,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
1515 // that death now instead of later as this has an effect on1515 // that death now instead of later as this has an effect on
1516 // whether it needs to be spilled in the branches1516 // whether it needs to be spilled in the branches
1517 if (self.liveness.operandDies(inst, 0)) {1517 if (self.liveness.operandDies(inst, 0)) {
1518 const op_int = @intFromEnum(pl_op.operand);1518 if (Air.refToIndex(pl_op.operand)) |op_index| {
1519 if (op_int >= Air.ref_start_index) {
1520 const op_index = @as(Air.Inst.Index, @intCast(op_int - Air.ref_start_index));
1521 self.processDeath(op_index);1519 self.processDeath(op_index);
1522 }1520 }
1523 }1521 }
...@@ -3570,9 +3568,7 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live...@@ -3570,9 +3568,7 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
3570 const dies = @as(u1, @truncate(tomb_bits)) != 0;3568 const dies = @as(u1, @truncate(tomb_bits)) != 0;
3571 tomb_bits >>= 1;3569 tomb_bits >>= 1;
3572 if (!dies) continue;3570 if (!dies) continue;
3573 const op_int = @intFromEnum(op);3571 const op_index = Air.refToIndex(op) orelse continue;
3574 if (op_int < Air.ref_start_index) continue;
3575 const op_index = @as(Air.Inst.Index, @intCast(op_int - Air.ref_start_index));
3576 self.processDeath(op_index);3572 self.processDeath(op_index);
3577 }3573 }
3578 const is_used = @as(u1, @truncate(tomb_bits)) == 0;3574 const is_used = @as(u1, @truncate(tomb_bits)) == 0;
...@@ -4422,7 +4418,6 @@ fn performReloc(self: *Self, inst: Mir.Inst.Index) !void {...@@ -4422,7 +4418,6 @@ fn performReloc(self: *Self, inst: Mir.Inst.Index) !void {
44224418
4423/// Asserts there is already capacity to insert into top branch inst_table.4419/// Asserts there is already capacity to insert into top branch inst_table.
4424fn processDeath(self: *Self, inst: Air.Inst.Index) void {4420fn processDeath(self: *Self, inst: Air.Inst.Index) void {
4425 assert(self.air.instructions.items(.tag)[inst] != .interned);
4426 // When editing this function, note that the logic must synchronize with `reuseOperand`.4421 // When editing this function, note that the logic must synchronize with `reuseOperand`.
4427 const prev_value = self.getResolvedInstValue(inst);4422 const prev_value = self.getResolvedInstValue(inst);
4428 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];4423 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
...@@ -4550,22 +4545,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {...@@ -4550,22 +4545,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
4550 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return .none;4545 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return .none;
45514546
4552 if (Air.refToIndex(ref)) |inst| {4547 if (Air.refToIndex(ref)) |inst| {
4553 switch (self.air.instructions.items(.tag)[inst]) {4548 return self.getResolvedInstValue(inst);
4554 .interned => {
4555 // Constants have static lifetimes, so they are always memoized in the outer most table.
4556 const branch = &self.branch_stack.items[0];
4557 const gop = try branch.inst_table.getOrPut(self.gpa, inst);
4558 if (!gop.found_existing) {
4559 const interned = self.air.instructions.items(.data)[inst].interned;
4560 gop.value_ptr.* = try self.genTypedValue(.{
4561 .ty = ty,
4562 .val = interned.toValue(),
4563 });
4564 }
4565 return gop.value_ptr.*;
4566 },
4567 else => return self.getResolvedInstValue(inst),
4568 }
4569 }4549 }
45704550
4571 return self.genTypedValue(.{4551 return self.genTypedValue(.{
src/arch/wasm/CodeGen.zig+3-4
...@@ -854,9 +854,9 @@ const BigTomb = struct {...@@ -854,9 +854,9 @@ const BigTomb = struct {
854 lbt: Liveness.BigTomb,854 lbt: Liveness.BigTomb,
855855
856 fn feed(bt: *BigTomb, op_ref: Air.Inst.Ref) void {856 fn feed(bt: *BigTomb, op_ref: Air.Inst.Ref) void {
857 _ = Air.refToIndex(op_ref) orelse return; // constants do not have to be freed regardless
858 const dies = bt.lbt.feed();857 const dies = bt.lbt.feed();
859 if (!dies) return;858 if (!dies) return;
859 // This will be a nop for interned constants.
860 processDeath(bt.gen, op_ref);860 processDeath(bt.gen, op_ref);
861 }861 }
862862
...@@ -882,8 +882,7 @@ fn iterateBigTomb(func: *CodeGen, inst: Air.Inst.Index, operand_count: usize) !B...@@ -882,8 +882,7 @@ fn iterateBigTomb(func: *CodeGen, inst: Air.Inst.Index, operand_count: usize) !B
882}882}
883883
884fn processDeath(func: *CodeGen, ref: Air.Inst.Ref) void {884fn processDeath(func: *CodeGen, ref: Air.Inst.Ref) void {
885 const inst = Air.refToIndex(ref) orelse return;885 if (Air.refToIndex(ref) == null) return;
886 assert(func.air.instructions.items(.tag)[inst] != .interned);
887 // Branches are currently only allowed to free locals allocated886 // Branches are currently only allowed to free locals allocated
888 // within their own branch.887 // within their own branch.
889 // TODO: Upon branch consolidation free any locals if needed.888 // TODO: Upon branch consolidation free any locals if needed.
...@@ -1832,7 +1831,7 @@ fn buildPointerOffset(func: *CodeGen, ptr_value: WValue, offset: u64, action: en...@@ -1832,7 +1831,7 @@ fn buildPointerOffset(func: *CodeGen, ptr_value: WValue, offset: u64, action: en
1832fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {1831fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
1833 const air_tags = func.air.instructions.items(.tag);1832 const air_tags = func.air.instructions.items(.tag);
1834 return switch (air_tags[inst]) {1833 return switch (air_tags[inst]) {
1835 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,1834 .inferred_alloc, .inferred_alloc_comptime => unreachable,
18361835
1837 .add => func.airBinOp(inst, .add),1836 .add => func.airBinOp(inst, .add),
1838 .add_sat => func.airSatBinOp(inst, .add),1837 .add_sat => func.airSatBinOp(inst, .add),
src/arch/x86_64/CodeGen.zig+24-32
...@@ -81,7 +81,7 @@ end_di_column: u32,...@@ -81,7 +81,7 @@ end_di_column: u32,
81/// which is a relative jump, based on the address following the reloc.81/// which is a relative jump, based on the address following the reloc.
82exitlude_jump_relocs: std.ArrayListUnmanaged(Mir.Inst.Index) = .{},82exitlude_jump_relocs: std.ArrayListUnmanaged(Mir.Inst.Index) = .{},
8383
84const_tracking: InstTrackingMap = .{},84const_tracking: ConstTrackingMap = .{},
85inst_tracking: InstTrackingMap = .{},85inst_tracking: InstTrackingMap = .{},
8686
87// Key is the block instruction87// Key is the block instruction
...@@ -403,6 +403,7 @@ pub const MCValue = union(enum) {...@@ -403,6 +403,7 @@ pub const MCValue = union(enum) {
403};403};
404404
405const InstTrackingMap = std.AutoArrayHashMapUnmanaged(Air.Inst.Index, InstTracking);405const InstTrackingMap = std.AutoArrayHashMapUnmanaged(Air.Inst.Index, InstTracking);
406const ConstTrackingMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, InstTracking);
406const InstTracking = struct {407const InstTracking = struct {
407 long: MCValue,408 long: MCValue,
408 short: MCValue,409 short: MCValue,
...@@ -1927,7 +1928,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -1927,7 +1928,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1927 .ptr_elem_val => try self.airPtrElemVal(inst),1928 .ptr_elem_val => try self.airPtrElemVal(inst),
1928 .ptr_elem_ptr => try self.airPtrElemPtr(inst),1929 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
19291930
1930 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,1931 .inferred_alloc, .inferred_alloc_comptime => unreachable,
1931 .unreach => if (self.wantSafety()) try self.airTrap() else self.finishAirBookkeeping(),1932 .unreach => if (self.wantSafety()) try self.airTrap() else self.finishAirBookkeeping(),
19321933
1933 .optional_payload => try self.airOptionalPayload(inst),1934 .optional_payload => try self.airOptionalPayload(inst),
...@@ -2099,7 +2100,6 @@ fn feed(self: *Self, bt: *Liveness.BigTomb, operand: Air.Inst.Ref) void {...@@ -2099,7 +2100,6 @@ fn feed(self: *Self, bt: *Liveness.BigTomb, operand: Air.Inst.Ref) void {
20992100
2100/// Asserts there is already capacity to insert into top branch inst_table.2101/// Asserts there is already capacity to insert into top branch inst_table.
2101fn processDeath(self: *Self, inst: Air.Inst.Index) void {2102fn processDeath(self: *Self, inst: Air.Inst.Index) void {
2102 assert(self.air.instructions.items(.tag)[inst] != .interned);
2103 self.inst_tracking.getPtr(inst).?.die(self, inst);2103 self.inst_tracking.getPtr(inst).?.die(self, inst);
2104}2104}
21052105
...@@ -2871,13 +2871,6 @@ fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 {...@@ -2871,13 +2871,6 @@ fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 {
2871 const dst_info = dst_ty.intInfo(mod);2871 const dst_info = dst_ty.intInfo(mod);
2872 if (Air.refToIndex(dst_air)) |inst| {2872 if (Air.refToIndex(dst_air)) |inst| {
2873 switch (air_tag[inst]) {2873 switch (air_tag[inst]) {
2874 .interned => {
2875 const src_val = air_data[inst].interned.toValue();
2876 var space: Value.BigIntSpace = undefined;
2877 const src_int = src_val.toBigInt(&space, mod);
2878 return @as(u16, @intCast(src_int.bitCountTwosComp())) +
2879 @intFromBool(src_int.positive and dst_info.signedness == .signed);
2880 },
2881 .intcast => {2874 .intcast => {
2882 const src_ty = self.typeOf(air_data[inst].ty_op.operand);2875 const src_ty = self.typeOf(air_data[inst].ty_op.operand);
2883 const src_info = src_ty.intInfo(mod);2876 const src_info = src_ty.intInfo(mod);
...@@ -2894,6 +2887,11 @@ fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 {...@@ -2894,6 +2887,11 @@ fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 {
2894 },2887 },
2895 else => {},2888 else => {},
2896 }2889 }
2890 } else if (Air.refToInterned(dst_air)) |ip_index| {
2891 var space: Value.BigIntSpace = undefined;
2892 const src_int = ip_index.toValue().toBigInt(&space, mod);
2893 return @as(u16, @intCast(src_int.bitCountTwosComp())) +
2894 @intFromBool(src_int.positive and dst_info.signedness == .signed);
2897 }2895 }
2898 return dst_info.bits;2896 return dst_info.bits;
2899}2897}
...@@ -11635,32 +11633,26 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {...@@ -11635,32 +11633,26 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
11635 // If the type has no codegen bits, no need to store it.11633 // If the type has no codegen bits, no need to store it.
11636 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return .none;11634 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return .none;
1163711635
11638 if (Air.refToIndex(ref)) |inst| {11636 const mcv = if (Air.refToIndex(ref)) |inst| mcv: {
11639 const mcv = switch (self.air.instructions.items(.tag)[inst]) {11637 break :mcv self.inst_tracking.getPtr(inst).?.short;
11640 .interned => tracking: {11638 } else mcv: {
11641 const gop = try self.const_tracking.getOrPut(self.gpa, inst);11639 const ip_index = Air.refToInterned(ref).?;
11642 if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(try self.genTypedValue(.{11640 const gop = try self.const_tracking.getOrPut(self.gpa, ip_index);
11643 .ty = ty,11641 if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(try self.genTypedValue(.{
11644 .val = self.air.instructions.items(.data)[inst].interned.toValue(),11642 .ty = ty,
11645 }));11643 .val = ip_index.toValue(),
11646 break :tracking gop.value_ptr;11644 }));
11647 },11645 break :mcv gop.value_ptr.short;
11648 else => self.inst_tracking.getPtr(inst).?,11646 };
11649 }.short;
11650 switch (mcv) {
11651 .none, .unreach, .dead => unreachable,
11652 else => return mcv,
11653 }
11654 }
1165511647
11656 return self.genTypedValue(.{ .ty = ty, .val = (try self.air.value(ref, mod)).? });11648 switch (mcv) {
11649 .none, .unreach, .dead => unreachable,
11650 else => return mcv,
11651 }
11657}11652}
1165811653
11659fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) *InstTracking {11654fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) *InstTracking {
11660 const tracking = switch (self.air.instructions.items(.tag)[inst]) {11655 const tracking = self.inst_tracking.getPtr(inst).?;
11661 .interned => &self.const_tracking,
11662 else => &self.inst_tracking,
11663 }.getPtr(inst).?;
11664 return switch (tracking.short) {11656 return switch (tracking.short) {
11665 .none, .unreach, .dead => unreachable,11657 .none, .unreach, .dead => unreachable,
11666 else => tracking,11658 else => tracking,
src/codegen/c.zig+26-29
...@@ -53,7 +53,7 @@ const BlockData = struct {...@@ -53,7 +53,7 @@ const BlockData = struct {
53 result: CValue,53 result: CValue,
54};54};
5555
56pub const CValueMap = std.AutoHashMap(Air.Inst.Index, CValue);56pub const CValueMap = std.AutoHashMap(Air.Inst.Ref, CValue);
5757
58pub const LazyFnKey = union(enum) {58pub const LazyFnKey = union(enum) {
59 tag_name: Decl.Index,59 tag_name: Decl.Index,
...@@ -282,31 +282,29 @@ pub const Function = struct {...@@ -282,31 +282,29 @@ pub const Function = struct {
282 allocs: std.AutoArrayHashMapUnmanaged(LocalIndex, bool) = .{},282 allocs: std.AutoArrayHashMapUnmanaged(LocalIndex, bool) = .{},
283283
284 fn resolveInst(f: *Function, ref: Air.Inst.Ref) !CValue {284 fn resolveInst(f: *Function, ref: Air.Inst.Ref) !CValue {
285 if (Air.refToIndex(ref)) |inst| {285 const gop = try f.value_map.getOrPut(ref);
286 const gop = try f.value_map.getOrPut(inst);286 if (gop.found_existing) return gop.value_ptr.*;
287 if (gop.found_existing) return gop.value_ptr.*;
288287
289 const mod = f.object.dg.module;288 const mod = f.object.dg.module;
290 const val = (try f.air.value(ref, mod)).?;289 const val = (try f.air.value(ref, mod)).?;
291 const ty = f.typeOf(ref);290 const ty = f.typeOf(ref);
292291
293 const result: CValue = if (lowersToArray(ty, mod)) result: {292 const result: CValue = if (lowersToArray(ty, mod)) result: {
294 const writer = f.object.code_header.writer();293 const writer = f.object.code_header.writer();
295 const alignment = 0;294 const alignment = 0;
296 const decl_c_value = try f.allocLocalValue(ty, alignment);295 const decl_c_value = try f.allocLocalValue(ty, alignment);
297 const gpa = f.object.dg.gpa;296 const gpa = f.object.dg.gpa;
298 try f.allocs.put(gpa, decl_c_value.new_local, false);297 try f.allocs.put(gpa, decl_c_value.new_local, false);
299 try writer.writeAll("static ");298 try writer.writeAll("static ");
300 try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, alignment, .complete);299 try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, alignment, .complete);
301 try writer.writeAll(" = ");300 try writer.writeAll(" = ");
302 try f.object.dg.renderValue(writer, ty, val, .StaticInitializer);301 try f.object.dg.renderValue(writer, ty, val, .StaticInitializer);
303 try writer.writeAll(";\n ");302 try writer.writeAll(";\n ");
304 break :result decl_c_value;303 break :result decl_c_value;
305 } else .{ .constant = ref };304 } else .{ .constant = ref };
306305
307 gop.value_ptr.* = result;306 gop.value_ptr.* = result;
308 return result;307 return result;
309 } else return .{ .constant = ref };
310 }308 }
311309
312 fn wantSafety(f: *Function) bool {310 fn wantSafety(f: *Function) bool {
...@@ -2823,7 +2821,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -2823,7 +2821,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
28232821
2824 const result_value = switch (air_tags[inst]) {2822 const result_value = switch (air_tags[inst]) {
2825 // zig fmt: off2823 // zig fmt: off
2826 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,2824 .inferred_alloc, .inferred_alloc_comptime => unreachable,
28272825
2828 .arg => try airArg(f, inst),2826 .arg => try airArg(f, inst),
28292827
...@@ -3091,7 +3089,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -3091,7 +3089,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
3091 if (result_value == .new_local) {3089 if (result_value == .new_local) {
3092 log.debug("map %{d} to t{d}", .{ inst, result_value.new_local });3090 log.debug("map %{d} to t{d}", .{ inst, result_value.new_local });
3093 }3091 }
3094 try f.value_map.putNoClobber(inst, switch (result_value) {3092 try f.value_map.putNoClobber(Air.indexToRef(inst), switch (result_value) {
3095 .none => continue,3093 .none => continue,
3096 .new_local => |i| .{ .local = i },3094 .new_local => |i| .{ .local = i },
3097 else => result_value,3095 else => result_value,
...@@ -7439,7 +7437,7 @@ fn formatIntLiteral(...@@ -7439,7 +7437,7 @@ fn formatIntLiteral(
7439 } else data.val.toBigInt(&int_buf, mod);7437 } else data.val.toBigInt(&int_buf, mod);
7440 assert(int.fitsInTwosComp(data.int_info.signedness, data.int_info.bits));7438 assert(int.fitsInTwosComp(data.int_info.signedness, data.int_info.bits));
74417439
7442 const c_bits = @as(usize, @intCast(data.cty.byteSize(data.dg.ctypes.set, target) * 8));7440 const c_bits: usize = @intCast(data.cty.byteSize(data.dg.ctypes.set, target) * 8);
7443 var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined;7441 var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined;
7444 const one = BigInt.Mutable.init(&one_limbs, 1).toConst();7442 const one = BigInt.Mutable.init(&one_limbs, 1).toConst();
74457443
...@@ -7745,8 +7743,7 @@ fn reap(f: *Function, inst: Air.Inst.Index, operands: []const Air.Inst.Ref) !voi...@@ -7745,8 +7743,7 @@ fn reap(f: *Function, inst: Air.Inst.Index, operands: []const Air.Inst.Ref) !voi
77457743
7746fn die(f: *Function, inst: Air.Inst.Index, ref: Air.Inst.Ref) !void {7744fn die(f: *Function, inst: Air.Inst.Index, ref: Air.Inst.Ref) !void {
7747 const ref_inst = Air.refToIndex(ref) orelse return;7745 const ref_inst = Air.refToIndex(ref) orelse return;
7748 assert(f.air.instructions.items(.tag)[ref_inst] != .interned);7746 const c_value = (f.value_map.fetchRemove(ref) orelse return).value;
7749 const c_value = (f.value_map.fetchRemove(ref_inst) orelse return).value;
7750 const local_index = switch (c_value) {7747 const local_index = switch (c_value) {
7751 .local, .new_local => |l| l,7748 .local, .new_local => |l| l,
7752 else => return,7749 else => return,
src/codegen/llvm.zig+16-13
...@@ -4557,7 +4557,7 @@ pub const FuncGen = struct {...@@ -4557,7 +4557,7 @@ pub const FuncGen = struct {
45574557
4558 .vector_store_elem => try self.airVectorStoreElem(inst),4558 .vector_store_elem => try self.airVectorStoreElem(inst),
45594559
4560 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,4560 .inferred_alloc, .inferred_alloc_comptime => unreachable,
45614561
4562 .unreach => self.airUnreach(inst),4562 .unreach => self.airUnreach(inst),
4563 .dbg_stmt => self.airDbgStmt(inst),4563 .dbg_stmt => self.airDbgStmt(inst),
...@@ -5762,19 +5762,22 @@ pub const FuncGen = struct {...@@ -5762,19 +5762,22 @@ pub const FuncGen = struct {
57625762
5763 return self.loadByRef(elem_ptr, elem_ty, elem_ty.abiAlignment(mod), false);5763 return self.loadByRef(elem_ptr, elem_ty, elem_ty.abiAlignment(mod), false);
5764 } else {5764 } else {
5765 const lhs_index = Air.refToIndex(bin_op.lhs).?;
5766 const elem_llvm_ty = try o.lowerType(elem_ty);5765 const elem_llvm_ty = try o.lowerType(elem_ty);
5767 if (self.air.instructions.items(.tag)[lhs_index] == .load) {5766 if (Air.refToIndex(bin_op.lhs)) |lhs_index| {
5768 const load_data = self.air.instructions.items(.data)[lhs_index];5767 if (self.air.instructions.items(.tag)[lhs_index] == .load) {
5769 const load_ptr = load_data.ty_op.operand;5768 const load_data = self.air.instructions.items(.data)[lhs_index];
5770 const load_ptr_tag = self.air.instructions.items(.tag)[Air.refToIndex(load_ptr).?];5769 const load_ptr = load_data.ty_op.operand;
5771 switch (load_ptr_tag) {5770 if (Air.refToIndex(load_ptr)) |load_ptr_index| {
5772 .struct_field_ptr, .struct_field_ptr_index_0, .struct_field_ptr_index_1, .struct_field_ptr_index_2, .struct_field_ptr_index_3 => {5771 const load_ptr_tag = self.air.instructions.items(.tag)[load_ptr_index];
5773 const load_ptr_inst = try self.resolveInst(load_ptr);5772 switch (load_ptr_tag) {
5774 const gep = self.builder.buildInBoundsGEP(array_llvm_ty, load_ptr_inst, &indices, indices.len, "");5773 .struct_field_ptr, .struct_field_ptr_index_0, .struct_field_ptr_index_1, .struct_field_ptr_index_2, .struct_field_ptr_index_3 => {
5775 return self.builder.buildLoad(elem_llvm_ty, gep, "");5774 const load_ptr_inst = try self.resolveInst(load_ptr);
5776 },5775 const gep = self.builder.buildInBoundsGEP(array_llvm_ty, load_ptr_inst, &indices, indices.len, "");
5777 else => {},5776 return self.builder.buildLoad(elem_llvm_ty, gep, "");
5777 },
5778 else => {},
5779 }
5780 }
5778 }5781 }
5779 }5782 }
5780 const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, array_llvm_val, &indices, indices.len, "");5783 const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, array_llvm_val, &indices, indices.len, "");
src/print_air.zig+10-25
...@@ -49,8 +49,6 @@ pub fn write(stream: anytype, module: *Module, air: Air, liveness: ?Liveness) vo...@@ -49,8 +49,6 @@ pub fn write(stream: anytype, module: *Module, air: Air, liveness: ?Liveness) vo
49 .indent = 2,49 .indent = 2,
50 .skip_body = false,50 .skip_body = false,
51 };51 };
52 writer.writeAllConstants(stream) catch return;
53 stream.writeByte('\n') catch return;
54 writer.writeBody(stream, air.getMainBody()) catch return;52 writer.writeBody(stream, air.getMainBody()) catch return;
55}53}
5654
...@@ -88,15 +86,6 @@ const Writer = struct {...@@ -88,15 +86,6 @@ const Writer = struct {
88 indent: usize,86 indent: usize,
89 skip_body: bool,87 skip_body: bool,
9088
91 fn writeAllConstants(w: *Writer, s: anytype) @TypeOf(s).Error!void {
92 for (w.air.instructions.items(.tag), 0..) |tag, i| {
93 if (tag != .interned) continue;
94 const inst = @as(Air.Inst.Index, @intCast(i));
95 try w.writeInst(s, inst);
96 try s.writeByte('\n');
97 }
98 }
99
100 fn writeBody(w: *Writer, s: anytype, body: []const Air.Inst.Index) @TypeOf(s).Error!void {89 fn writeBody(w: *Writer, s: anytype, body: []const Air.Inst.Index) @TypeOf(s).Error!void {
101 for (body) |inst| {90 for (body) |inst| {
102 try w.writeInst(s, inst);91 try w.writeInst(s, inst);
...@@ -299,7 +288,6 @@ const Writer = struct {...@@ -299,7 +288,6 @@ const Writer = struct {
299 .struct_field_val => try w.writeStructField(s, inst),288 .struct_field_val => try w.writeStructField(s, inst),
300 .inferred_alloc => @panic("TODO"),289 .inferred_alloc => @panic("TODO"),
301 .inferred_alloc_comptime => @panic("TODO"),290 .inferred_alloc_comptime => @panic("TODO"),
302 .interned => try w.writeInterned(s, inst),
303 .assembly => try w.writeAssembly(s, inst),291 .assembly => try w.writeAssembly(s, inst),
304 .dbg_stmt => try w.writeDbgStmt(s, inst),292 .dbg_stmt => try w.writeDbgStmt(s, inst),
305293
...@@ -596,14 +584,6 @@ const Writer = struct {...@@ -596,14 +584,6 @@ const Writer = struct {
596 try s.print(", {d}", .{extra.field_index});584 try s.print(", {d}", .{extra.field_index});
597 }585 }
598586
599 fn writeInterned(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
600 const mod = w.module;
601 const ip_index = w.air.instructions.items(.data)[inst].interned;
602 const ty = mod.intern_pool.indexToKey(ip_index).typeOf().toType();
603 try w.writeType(s, ty);
604 try s.print(", {}", .{ip_index.toValue().fmtValue(ty, mod)});
605 }
606
607 fn writeAssembly(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {587 fn writeAssembly(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
608 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;588 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
609 const extra = w.air.extraData(Air.Asm, ty_pl.payload);589 const extra = w.air.extraData(Air.Asm, ty_pl.payload);
...@@ -956,13 +936,18 @@ const Writer = struct {...@@ -956,13 +936,18 @@ const Writer = struct {
956 operand: Air.Inst.Ref,936 operand: Air.Inst.Ref,
957 dies: bool,937 dies: bool,
958 ) @TypeOf(s).Error!void {938 ) @TypeOf(s).Error!void {
959 const i = @intFromEnum(operand);939 if (@intFromEnum(operand) < InternPool.static_len) {
960
961 if (i < InternPool.static_len) {
962 return s.print("@{}", .{operand});940 return s.print("@{}", .{operand});
941 } else if (Air.refToInterned(operand)) |ip_index| {
942 const mod = w.module;
943 const ty = mod.intern_pool.indexToKey(ip_index).typeOf().toType();
944 try s.print("<{}, {}>", .{
945 ty.fmt(mod),
946 ip_index.toValue().fmtValue(ty, mod),
947 });
948 } else {
949 return w.writeInstIndex(s, Air.refToIndex(operand).?, dies);
963 }950 }
964
965 return w.writeInstIndex(s, i - InternPool.static_len, dies);
966 }951 }
967952
968 fn writeInstIndex(953 fn writeInstIndex(