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 {
438438 /// was executed on the operand.
439439 /// Uses the `ty_pl` field. Payload is `TryPtr`.
440440 try_ptr,
441 /// A comptime-known value via an index into the InternPool.
442 /// Uses the `interned` field.
443 interned,
444441 /// Notes the beginning of a source code statement and marks the line and column.
445442 /// Result type is always void.
446443 /// Uses the `dbg_stmt` field.
......@@ -879,6 +876,12 @@ pub const Inst = struct {
879876 /// The position of an AIR instruction within the `Air` instructions array.
880877 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.
882885 pub const Ref = enum(u32) {
883886 u0_type = @intFromEnum(InternPool.Index.u0_type),
884887 i0_type = @intFromEnum(InternPool.Index.i0_type),
......@@ -979,7 +982,6 @@ pub const Inst = struct {
979982 pub const Data = union {
980983 no_op: void,
981984 un_op: Ref,
982 interned: InternPool.Index,
983985
984986 bin_op: struct {
985987 lhs: Ref,
......@@ -1216,11 +1218,11 @@ pub fn getMainBody(air: Air) []const Air.Inst.Index {
12161218}
12171219
12181220pub fn typeOf(air: *const Air, inst: Air.Inst.Ref, ip: *const InternPool) Type {
1219 const ref_int = @intFromEnum(inst);
1220 if (ref_int < InternPool.static_keys.len) {
1221 return InternPool.static_keys[ref_int].typeOf().toType();
1221 if (refToInterned(inst)) |ip_index| {
1222 return ip.typeOf(ip_index).toType();
1223 } else {
1224 return air.typeOfIndex(refToIndex(inst).?, ip);
12221225 }
1223 return air.typeOfIndex(ref_int - ref_start_index, ip);
12241226}
12251227
12261228pub 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)
13421344 .try_ptr,
13431345 => return air.getRefType(datas[inst].ty_pl.ty),
13441346
1345 .interned => return ip.typeOf(datas[inst].interned).toType(),
1346
13471347 .not,
13481348 .bitcast,
13491349 .load,
......@@ -1479,18 +1479,8 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
14791479}
14801480
14811481pub fn getRefType(air: Air, ref: Air.Inst.Ref) Type {
1482 const ref_int = @intFromEnum(ref);
1483 if (ref_int < ref_start_index) {
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 };
1482 _ = air; // TODO: remove this parameter
1483 return refToInterned(ref).?.toType();
14941484}
14951485
14961486/// 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 {
15211511 air.* = undefined;
15221512}
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 {
1527 return @as(Inst.Ref, @enumFromInt(ref_start_index + inst));
1524pub fn refToInterned(ref: Inst.Ref) ?InternPool.Index {
1525 assert(ref != .none);
1526 return refToInternedAllowNone(ref);
15281527}
15291528
1530pub fn refToIndex(inst: Inst.Ref) ?Inst.Index {
1531 assert(inst != .none);
1532 const ref_int = @intFromEnum(inst);
1533 if (ref_int >= ref_start_index) {
1534 return ref_int - ref_start_index;
1535 } else {
1536 return null;
1537 }
1529pub fn internedToRef(ip_index: InternPool.Index) Inst.Ref {
1530 assert(@intFromEnum(ip_index) >> 31 == 0);
1531 return switch (ip_index) {
1532 .var_args_param_type => .var_args_param_type,
1533 .none => .none,
1534 else => @enumFromInt(@as(u31, @intCast(@intFromEnum(ip_index)))),
1535 };
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 };
15381545}
15391546
1540pub fn refToIndexAllowNone(inst: Inst.Ref) ?Inst.Index {
1541 if (inst == .none) return null;
1542 return refToIndex(inst);
1547pub fn refToIndex(ref: Inst.Ref) ?Inst.Index {
1548 assert(ref != .none);
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);
15431555}
15441556
15451557/// Returns `null` if runtime-known.
15461558pub fn value(air: Air, inst: Inst.Ref, mod: *Module) !?Value {
1547 const ref_int = @intFromEnum(inst);
1548 if (ref_int < ref_start_index) {
1549 const ip_index = @as(InternPool.Index, @enumFromInt(ref_int));
1559 if (refToInterned(inst)) |ip_index| {
15501560 return ip_index.toValue();
15511561 }
1552 const inst_index = @as(Air.Inst.Index, @intCast(ref_int - ref_start_index));
1553 const air_datas = air.instructions.items(.data);
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 }
1562 const index = refToIndex(inst).?;
1563 return air.typeOfIndex(index, &mod.intern_pool).onePossibleValue(mod);
15581564}
15591565
15601566pub 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 {
17091715 .cmp_neq_optimized,
17101716 .cmp_vector,
17111717 .cmp_vector_optimized,
1712 .interned,
17131718 .is_null,
17141719 .is_non_null,
17151720 .is_null_ptr,
src/Liveness.zig+1-14
......@@ -324,7 +324,6 @@ pub fn categorizeOperand(
324324 .inferred_alloc,
325325 .inferred_alloc_comptime,
326326 .ret_ptr,
327 .interned,
328327 .trap,
329328 .breakpoint,
330329 .dbg_stmt,
......@@ -981,7 +980,7 @@ fn analyzeInst(
981980 .work_group_id,
982981 => 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
986985 .trap,
987986 .unreach,
......@@ -1264,7 +1263,6 @@ fn analyzeOperands(
12641263 operands: [bpi - 1]Air.Inst.Ref,
12651264) Allocator.Error!void {
12661265 const gpa = a.gpa;
1267 const inst_tags = a.air.instructions.items(.tag);
12681266 const ip = a.intern_pool;
12691267
12701268 switch (pass) {
......@@ -1273,10 +1271,6 @@ fn analyzeOperands(
12731271
12741272 for (operands) |op_ref| {
12751273 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
12801274 _ = try data.live_set.put(gpa, operand, {});
12811275 }
12821276 },
......@@ -1307,9 +1301,6 @@ fn analyzeOperands(
13071301 const op_ref = operands[i];
13081302 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
13131304 const mask = @as(Bpi, 1) << @as(OperandInt, @intCast(i));
13141305
13151306 if ((try data.live_set.fetchPut(gpa, operand, {})) == null) {
......@@ -1837,10 +1828,6 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type {
18371828
18381829 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
18441831 // If our result is unused and the instruction doesn't need to be lowered, backends will
18451832 // skip the lowering of this instruction, so we don't want to record uses of operands.
18461833 // 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 {
4444 .inferred_alloc,
4545 .inferred_alloc_comptime,
4646 .ret_ptr,
47 .interned,
4847 .breakpoint,
4948 .dbg_stmt,
5049 .dbg_inline_begin,
......@@ -559,10 +558,6 @@ fn verifyOperand(self: *Verify, inst: Air.Inst.Index, op_ref: Air.Inst.Ref, dies
559558 assert(!dies);
560559 return;
561560 };
562 if (self.air.instructions.items(.tag)[operand] == .interned) {
563 assert(!dies);
564 return;
565 }
566561 if (dies) {
567562 if (!self.live.remove(operand)) return invalid("%{}: dead operand %{} reused and killed again", .{ inst, operand });
568563 } else {
......@@ -583,7 +578,6 @@ fn verifyInstOperands(
583578}
584579
585580fn verifyInst(self: *Verify, inst: Air.Inst.Index) Error!void {
586 if (self.air.instructions.items(.tag)[inst] == .interned) return;
587581 if (self.liveness.isUnused(inst)) {
588582 assert(!self.live.contains(inst));
589583 } else {
src/Sema.zig+58-62
......@@ -2068,28 +2068,26 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
20682068) CompileError!?Value {
20692069 assert(inst != .none);
20702070 // First section of indexes correspond to a set number of constant values.
2071 const int = @intFromEnum(inst);
2072 if (int < InternPool.static_len) {
2073 return @as(InternPool.Index, @enumFromInt(int)).toValue();
2071 if (@intFromEnum(inst) < InternPool.static_len) {
2072 return @as(InternPool.Index, @enumFromInt(@intFromEnum(inst))).toValue();
20742073 }
20752074
2076 const i = int - InternPool.static_len;
20772075 const air_tags = sema.air_instructions.items(.tag);
20782076 if (try sema.typeHasOnePossibleValue(sema.typeOf(inst))) |opv| {
2079 if (air_tags[i] == .interned) {
2080 const interned = sema.air_instructions.items(.data)[i].interned;
2081 const val = interned.toValue();
2077 if (Air.refToInterned(inst)) |ip_index| {
2078 const val = ip_index.toValue();
20822079 if (val.getVariable(sema.mod) != null) return val;
20832080 }
20842081 return opv;
20852082 }
2086 const air_datas = sema.air_instructions.items(.data);
2087 const val = switch (air_tags[i]) {
2088 .inferred_alloc => unreachable,
2089 .inferred_alloc_comptime => unreachable,
2090 .interned => air_datas[i].interned.toValue(),
2091 else => return null,
2083 const ip_index = Air.refToInterned(inst) orelse {
2084 switch (air_tags[Air.refToIndex(inst).?]) {
2085 .inferred_alloc => unreachable,
2086 .inferred_alloc_comptime => unreachable,
2087 else => return null,
2088 }
20922089 };
2090 const val = ip_index.toValue();
20932091 if (val.isRuntimeValue(sema.mod)) make_runtime.* = true;
20942092 if (val.isPtrToThreadLocal(sema.mod)) make_runtime.* = true;
20952093 return val;
......@@ -3868,18 +3866,23 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
38683866 },
38693867 });
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
38713874 try sema.maybeQueueFuncBodyAnalysis(decl_index);
3872 // Change it to an interned.
3873 sema.air_instructions.set(ptr_inst, .{
3874 .tag = .interned,
3875 .data = .{ .interned = try mod.intern(.{ .ptr = .{
3876 .ty = final_ptr_ty.toIntern(),
3877 .addr = if (!iac.is_const) .{ .mut_decl = .{
3878 .decl = decl_index,
3879 .runtime_index = block.runtime_index,
3880 } } else .{ .decl = decl_index },
3881 } }) },
3882 });
3875
3876 const interned = try mod.intern(.{ .ptr = .{
3877 .ty = final_ptr_ty.toIntern(),
3878 .addr = if (!iac.is_const) .{ .mut_decl = .{
3879 .decl = decl_index,
3880 .runtime_index = block.runtime_index,
3881 } } else .{ .decl = decl_index },
3882 } });
3883
3884 // Remap the ZIR operand to the resolved pointer value
3885 sema.inst_map.putAssumeCapacity(Zir.refToIndex(inst_data.operand).?, Air.internedToRef(interned));
38833886 },
38843887 .inferred_alloc => {
38853888 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
39663969 };
39673970 try mod.declareDeclDependency(sema.owner_decl_index, new_decl_index);
39683971
3969 // Even though we reuse the constant instruction, we still remove it from the
3970 // block so that codegen does not see it.
3972 // Remove the instruction from the block so that codegen does not see it.
39713973 block.instructions.shrinkRetainingCapacity(search_index);
39723974 try sema.maybeQueueFuncBodyAnalysis(new_decl_index);
3973 sema.air_instructions.set(ptr_inst, .{
3974 .tag = .interned,
3975 .data = .{ .interned = try mod.intern(.{ .ptr = .{
3976 .ty = final_ptr_ty.toIntern(),
3977 .addr = .{ .decl = new_decl_index },
3978 } }) },
3979 });
3975
3976 if (std.debug.runtime_safety) {
3977 // The inferred_alloc should never be referenced again
3978 sema.air_instructions.set(ptr_inst, .{ .tag = undefined, .data = undefined });
3979 }
3980
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
39813989 // Unless the block is comptime, `alloc_inferred` always produces
39823990 // a runtime constant. The final inferred type needs to be
......@@ -4404,7 +4412,6 @@ fn validateUnionInit(
44044412 const air_tags = sema.air_instructions.items(.tag);
44054413 const air_datas = sema.air_instructions.items(.data);
44064414 const field_ptr_air_ref = sema.inst_map.get(field_ptr).?;
4407 const field_ptr_air_inst = Air.refToIndex(field_ptr_air_ref).?;
44084415
44094416 // Our task here is to determine if the union is comptime-known. In such case,
44104417 // we erase the runtime AIR instructions for initializing the union, and replace
......@@ -4434,7 +4441,7 @@ fn validateUnionInit(
44344441 var make_runtime = false;
44354442 while (block_index > 0) : (block_index -= 1) {
44364443 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;
44384445 switch (air_tags[store_inst]) {
44394446 .store, .store_safe => {},
44404447 else => continue,
......@@ -4453,7 +4460,7 @@ fn validateUnionInit(
44534460 if (air_tags[block_inst] != .dbg_stmt) break;
44544461 }
44554462 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]))
44574464 {
44584465 first_block_index = @min(first_block_index, block_index - 1);
44594466 } else {
......@@ -4622,7 +4629,6 @@ fn validateStructInit(
46224629 }
46234630
46244631 const field_ptr_air_ref = sema.inst_map.get(field_ptr).?;
4625 const field_ptr_air_inst = Air.refToIndex(field_ptr_air_ref).?;
46264632
46274633 //std.debug.print("validateStructInit (field_ptr_air_inst=%{d}):\n", .{
46284634 // field_ptr_air_inst,
......@@ -4652,7 +4658,7 @@ fn validateStructInit(
46524658 var block_index = block.instructions.items.len - 1;
46534659 while (block_index > 0) : (block_index -= 1) {
46544660 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) {
46564662 struct_is_comptime = false;
46574663 continue :field;
46584664 }
......@@ -4675,7 +4681,7 @@ fn validateStructInit(
46754681 if (air_tags[block_inst] != .dbg_stmt) break;
46764682 }
46774683 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]))
46794685 {
46804686 first_block_index = @min(first_block_index, block_index - 1);
46814687 } else {
......@@ -4865,7 +4871,6 @@ fn zirValidateArrayInit(
48654871 }
48664872
48674873 const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?;
4868 const elem_ptr_air_inst = Air.refToIndex(elem_ptr_air_ref).?;
48694874
48704875 // We expect to see something like this in the current block AIR:
48714876 // %a = elem_ptr(...)
......@@ -4890,7 +4895,7 @@ fn zirValidateArrayInit(
48904895 var block_index = block.instructions.items.len - 1;
48914896 while (block_index > 0) : (block_index -= 1) {
48924897 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) {
48944899 array_is_comptime = false;
48954900 continue :outer;
48964901 }
......@@ -4913,7 +4918,7 @@ fn zirValidateArrayInit(
49134918 if (air_tags[block_inst] != .dbg_stmt) break;
49144919 }
49154920 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]))
49174922 {
49184923 first_block_index = @min(first_block_index, block_index - 1);
49194924 } else {
......@@ -5785,8 +5790,7 @@ fn analyzeBlockBody(
57855790 sema.air_instructions.items(.data)[br].br.operand = coerced_operand;
57865791 continue;
57875792 }
5788 assert(coerce_block.instructions.items[coerce_block.instructions.items.len - 1] ==
5789 Air.refToIndex(coerced_operand).?);
5793 assert(Air.indexToRef(coerce_block.instructions.items[coerce_block.instructions.items.len - 1]) == coerced_operand);
57905794
57915795 // Convert the br instruction to a block instruction that has the coercion
57925796 // and then a new br inside that returns the coerced instruction.
......@@ -30397,8 +30401,8 @@ fn analyzeDeclVal(
3039730401 }
3039830402 const decl_ref = try sema.analyzeDeclRefInner(decl_index, false);
3039930403 const result = try sema.analyzeLoad(block, src, decl_ref, src);
30400 if (Air.refToIndex(result)) |index| {
30401 if (sema.air_instructions.items(.tag)[index] == .interned and !block.is_typeof) {
30404 if (Air.refToInterned(result) != null) {
30405 if (!block.is_typeof) {
3040230406 try sema.decl_val_table.put(sema.gpa, decl_index, result);
3040330407 }
3040430408 }
......@@ -30720,7 +30724,7 @@ fn analyzeIsNonErrComptimeOnly(
3072030724 }
3072130725 } else if (operand == .undef) {
3072230726 return sema.addConstUndef(Type.bool);
30723 } else {
30727 } else if (@intFromEnum(operand) < InternPool.static_len) {
3072430728 // None of the ref tags can be errors.
3072530729 return Air.Inst.Ref.bool_true;
3072630730 }
......@@ -35494,14 +35498,10 @@ pub fn getTmpAir(sema: Sema) Air {
3549435498 };
3549535499}
3549635500
35501// TODO: make this non-fallible or remove it entirely
3549735502pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {
35498 if (@intFromEnum(ty.toIntern()) < Air.ref_start_index)
35499 return @as(Air.Inst.Ref, @enumFromInt(@intFromEnum(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)));
35503 _ = sema;
35504 return Air.internedToRef(ty.toIntern());
3550535505}
3550635506
3550735507fn 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 {
3551335513 return sema.addConstant((try sema.mod.intern(.{ .undef = ty.toIntern() })).toValue());
3551435514}
3551535515
35516pub fn addConstant(sema: *Sema, val: Value) SemaError!Air.Inst.Ref {
35517 if (@intFromEnum(val.toIntern()) < Air.ref_start_index)
35518 return @as(Air.Inst.Ref, @enumFromInt(@intFromEnum(val.toIntern())));
35519 try sema.air_instructions.append(sema.gpa, .{
35520 .tag = .interned,
35521 .data = .{ .interned = val.toIntern() },
35522 });
35523 return Air.indexToRef(@as(u32, @intCast(sema.air_instructions.len - 1)));
35516// TODO: make this non-fallible or remove it entirely
35517pub fn addConstant(sema: *Sema, val: Value) !Air.Inst.Ref {
35518 _ = sema;
35519 return Air.internedToRef(val.toIntern());
3552435520}
3552535521
3552635522pub 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 {
845845 .ptr_elem_val => try self.airPtrElemVal(inst),
846846 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
847847
848 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
848 .inferred_alloc, .inferred_alloc_comptime => unreachable,
849849 .unreach => self.finishAirBookkeeping(),
850850
851851 .optional_payload => try self.airOptionalPayload(inst),
......@@ -920,7 +920,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
920920
921921/// Asserts there is already capacity to insert into top branch inst_table.
922922fn processDeath(self: *Self, inst: Air.Inst.Index) void {
923 assert(self.air.instructions.items(.tag)[inst] != .interned);
924923 // When editing this function, note that the logic must synchronize with `reuseOperand`.
925924 const prev_value = self.getResolvedInstValue(inst);
926925 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
953952 const dies = @as(u1, @truncate(tomb_bits)) != 0;
954953 tomb_bits >>= 1;
955954 if (!dies) continue;
956 const op_int = @intFromEnum(op);
957 if (op_int < Air.ref_start_index) continue;
958 const op_index = @as(Air.Inst.Index, @intCast(op_int - Air.ref_start_index));
955 const op_index = Air.refToIndex(op) orelse continue;
959956 self.processDeath(op_index);
960957 }
961958 const is_used = @as(u1, @truncate(tomb_bits)) == 0;
......@@ -4696,9 +4693,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
46964693 // that death now instead of later as this has an effect on
46974694 // whether it needs to be spilled in the branches
46984695 if (self.liveness.operandDies(inst, 0)) {
4699 const op_int = @intFromEnum(pl_op.operand);
4700 if (op_int >= Air.ref_start_index) {
4701 const op_index = @as(Air.Inst.Index, @intCast(op_int - Air.ref_start_index));
4696 if (Air.refToIndex(pl_op.operand)) |op_index| {
47024697 self.processDeath(op_index);
47034698 }
47044699 }
......@@ -6149,22 +6144,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
61496144 .val = (try self.air.value(inst, mod)).?,
61506145 });
61516146
6152 switch (self.air.instructions.items(.tag)[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 }
6147 return self.getResolvedInstValue(inst_index);
61686148}
61696149
61706150fn 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 {
829829 .ptr_elem_val => try self.airPtrElemVal(inst),
830830 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
831831
832 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
832 .inferred_alloc, .inferred_alloc_comptime => unreachable,
833833 .unreach => self.finishAirBookkeeping(),
834834
835835 .optional_payload => try self.airOptionalPayload(inst),
......@@ -904,7 +904,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
904904
905905/// Asserts there is already capacity to insert into top branch inst_table.
906906fn processDeath(self: *Self, inst: Air.Inst.Index) void {
907 assert(self.air.instructions.items(.tag)[inst] != .interned);
908907 // When editing this function, note that the logic must synchronize with `reuseOperand`.
909908 const prev_value = self.getResolvedInstValue(inst);
910909 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
939938 const dies = @as(u1, @truncate(tomb_bits)) != 0;
940939 tomb_bits >>= 1;
941940 if (!dies) continue;
942 const op_int = @intFromEnum(op);
943 if (op_int < Air.ref_start_index) continue;
944 const op_index = @as(Air.Inst.Index, @intCast(op_int - Air.ref_start_index));
941 const op_index = Air.refToIndex(op) orelse continue;
945942 self.processDeath(op_index);
946943 }
947944 const is_used = @as(u1, @truncate(tomb_bits)) == 0;
......@@ -4651,9 +4648,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
46514648 // that death now instead of later as this has an effect on
46524649 // whether it needs to be spilled in the branches
46534650 if (self.liveness.operandDies(inst, 0)) {
4654 const op_int = @intFromEnum(pl_op.operand);
4655 if (op_int >= Air.ref_start_index) {
4656 const op_index = @as(Air.Inst.Index, @intCast(op_int - Air.ref_start_index));
4651 if (Air.refToIndex(pl_op.operand)) |op_index| {
46574652 self.processDeath(op_index);
46584653 }
46594654 }
......@@ -6102,22 +6097,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
61026097 .val = (try self.air.value(inst, mod)).?,
61036098 });
61046099
6105 switch (self.air.instructions.items(.tag)[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 }
6100 return self.getResolvedInstValue(inst_index);
61216101}
61226102
61236103fn 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 {
664664 .ptr_elem_val => try self.airPtrElemVal(inst),
665665 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
666666
667 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
667 .inferred_alloc, .inferred_alloc_comptime => unreachable,
668668 .unreach => self.finishAirBookkeeping(),
669669
670670 .optional_payload => try self.airOptionalPayload(inst),
......@@ -731,7 +731,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
731731
732732/// Asserts there is already capacity to insert into top branch inst_table.
733733fn processDeath(self: *Self, inst: Air.Inst.Index) void {
734 assert(self.air.instructions.items(.tag)[inst] != .interned);
735734 // When editing this function, note that the logic must synchronize with `reuseOperand`.
736735 const prev_value = self.getResolvedInstValue(inst);
737736 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
757756 const dies = @as(u1, @truncate(tomb_bits)) != 0;
758757 tomb_bits >>= 1;
759758 if (!dies) continue;
760 const op_int = @intFromEnum(op);
761 if (op_int < Air.ref_start_index) continue;
762 const op_index = @as(Air.Inst.Index, @intCast(op_int - Air.ref_start_index));
759 const op_index = Air.refToIndex(op) orelse continue;
763760 self.processDeath(op_index);
764761 }
765762 const is_used = @as(u1, @truncate(tomb_bits)) == 0;
......@@ -2556,22 +2553,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
25562553 .val = (try self.air.value(inst, mod)).?,
25572554 });
25582555
2559 switch (self.air.instructions.items(.tag)[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 }
2556 return self.getResolvedInstValue(inst_index);
25752557}
25762558
25772559fn 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 {
677677 .ptr_elem_val => try self.airPtrElemVal(inst),
678678 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
679679
680 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
680 .inferred_alloc, .inferred_alloc_comptime => unreachable,
681681 .unreach => self.finishAirBookkeeping(),
682682
683683 .optional_payload => try self.airOptionalPayload(inst),
......@@ -1515,9 +1515,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
15151515 // that death now instead of later as this has an effect on
15161516 // whether it needs to be spilled in the branches
15171517 if (self.liveness.operandDies(inst, 0)) {
1518 const op_int = @intFromEnum(pl_op.operand);
1519 if (op_int >= Air.ref_start_index) {
1520 const op_index = @as(Air.Inst.Index, @intCast(op_int - Air.ref_start_index));
1518 if (Air.refToIndex(pl_op.operand)) |op_index| {
15211519 self.processDeath(op_index);
15221520 }
15231521 }
......@@ -3570,9 +3568,7 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
35703568 const dies = @as(u1, @truncate(tomb_bits)) != 0;
35713569 tomb_bits >>= 1;
35723570 if (!dies) continue;
3573 const op_int = @intFromEnum(op);
3574 if (op_int < Air.ref_start_index) continue;
3575 const op_index = @as(Air.Inst.Index, @intCast(op_int - Air.ref_start_index));
3571 const op_index = Air.refToIndex(op) orelse continue;
35763572 self.processDeath(op_index);
35773573 }
35783574 const is_used = @as(u1, @truncate(tomb_bits)) == 0;
......@@ -4422,7 +4418,6 @@ fn performReloc(self: *Self, inst: Mir.Inst.Index) !void {
44224418
44234419/// Asserts there is already capacity to insert into top branch inst_table.
44244420fn processDeath(self: *Self, inst: Air.Inst.Index) void {
4425 assert(self.air.instructions.items(.tag)[inst] != .interned);
44264421 // When editing this function, note that the logic must synchronize with `reuseOperand`.
44274422 const prev_value = self.getResolvedInstValue(inst);
44284423 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 {
45504545 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return .none;
45514546
45524547 if (Air.refToIndex(ref)) |inst| {
4553 switch (self.air.instructions.items(.tag)[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 }
4548 return self.getResolvedInstValue(inst);
45694549 }
45704550
45714551 return self.genTypedValue(.{
src/arch/wasm/CodeGen.zig+3-4
......@@ -854,9 +854,9 @@ const BigTomb = struct {
854854 lbt: Liveness.BigTomb,
855855
856856 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
858857 const dies = bt.lbt.feed();
859858 if (!dies) return;
859 // This will be a nop for interned constants.
860860 processDeath(bt.gen, op_ref);
861861 }
862862
......@@ -882,8 +882,7 @@ fn iterateBigTomb(func: *CodeGen, inst: Air.Inst.Index, operand_count: usize) !B
882882}
883883
884884fn processDeath(func: *CodeGen, ref: Air.Inst.Ref) void {
885 const inst = Air.refToIndex(ref) orelse return;
886 assert(func.air.instructions.items(.tag)[inst] != .interned);
885 if (Air.refToIndex(ref) == null) return;
887886 // Branches are currently only allowed to free locals allocated
888887 // within their own branch.
889888 // TODO: Upon branch consolidation free any locals if needed.
......@@ -1832,7 +1831,7 @@ fn buildPointerOffset(func: *CodeGen, ptr_value: WValue, offset: u64, action: en
18321831fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
18331832 const air_tags = func.air.instructions.items(.tag);
18341833 return switch (air_tags[inst]) {
1835 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
1834 .inferred_alloc, .inferred_alloc_comptime => unreachable,
18361835
18371836 .add => func.airBinOp(inst, .add),
18381837 .add_sat => func.airSatBinOp(inst, .add),
src/arch/x86_64/CodeGen.zig+24-32
......@@ -81,7 +81,7 @@ end_di_column: u32,
8181/// which is a relative jump, based on the address following the reloc.
8282exitlude_jump_relocs: std.ArrayListUnmanaged(Mir.Inst.Index) = .{},
8383
84const_tracking: InstTrackingMap = .{},
84const_tracking: ConstTrackingMap = .{},
8585inst_tracking: InstTrackingMap = .{},
8686
8787// Key is the block instruction
......@@ -403,6 +403,7 @@ pub const MCValue = union(enum) {
403403};
404404
405405const InstTrackingMap = std.AutoArrayHashMapUnmanaged(Air.Inst.Index, InstTracking);
406const ConstTrackingMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, InstTracking);
406407const InstTracking = struct {
407408 long: MCValue,
408409 short: MCValue,
......@@ -1927,7 +1928,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
19271928 .ptr_elem_val => try self.airPtrElemVal(inst),
19281929 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
19291930
1930 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
1931 .inferred_alloc, .inferred_alloc_comptime => unreachable,
19311932 .unreach => if (self.wantSafety()) try self.airTrap() else self.finishAirBookkeeping(),
19321933
19331934 .optional_payload => try self.airOptionalPayload(inst),
......@@ -2099,7 +2100,6 @@ fn feed(self: *Self, bt: *Liveness.BigTomb, operand: Air.Inst.Ref) void {
20992100
21002101/// Asserts there is already capacity to insert into top branch inst_table.
21012102fn processDeath(self: *Self, inst: Air.Inst.Index) void {
2102 assert(self.air.instructions.items(.tag)[inst] != .interned);
21032103 self.inst_tracking.getPtr(inst).?.die(self, inst);
21042104}
21052105
......@@ -2871,13 +2871,6 @@ fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 {
28712871 const dst_info = dst_ty.intInfo(mod);
28722872 if (Air.refToIndex(dst_air)) |inst| {
28732873 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 },
28812874 .intcast => {
28822875 const src_ty = self.typeOf(air_data[inst].ty_op.operand);
28832876 const src_info = src_ty.intInfo(mod);
......@@ -2894,6 +2887,11 @@ fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 {
28942887 },
28952888 else => {},
28962889 }
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);
28972895 }
28982896 return dst_info.bits;
28992897}
......@@ -11635,32 +11633,26 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
1163511633 // If the type has no codegen bits, no need to store it.
1163611634 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return .none;
1163711635
11638 if (Air.refToIndex(ref)) |inst| {
11639 const mcv = switch (self.air.instructions.items(.tag)[inst]) {
11640 .interned => tracking: {
11641 const gop = try self.const_tracking.getOrPut(self.gpa, inst);
11642 if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(try self.genTypedValue(.{
11643 .ty = ty,
11644 .val = self.air.instructions.items(.data)[inst].interned.toValue(),
11645 }));
11646 break :tracking gop.value_ptr;
11647 },
11648 else => self.inst_tracking.getPtr(inst).?,
11649 }.short;
11650 switch (mcv) {
11651 .none, .unreach, .dead => unreachable,
11652 else => return mcv,
11653 }
11654 }
11636 const mcv = if (Air.refToIndex(ref)) |inst| mcv: {
11637 break :mcv self.inst_tracking.getPtr(inst).?.short;
11638 } else mcv: {
11639 const ip_index = Air.refToInterned(ref).?;
11640 const gop = try self.const_tracking.getOrPut(self.gpa, ip_index);
11641 if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(try self.genTypedValue(.{
11642 .ty = ty,
11643 .val = ip_index.toValue(),
11644 }));
11645 break :mcv gop.value_ptr.short;
11646 };
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 }
1165711652}
1165811653
1165911654fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) *InstTracking {
11660 const tracking = switch (self.air.instructions.items(.tag)[inst]) {
11661 .interned => &self.const_tracking,
11662 else => &self.inst_tracking,
11663 }.getPtr(inst).?;
11655 const tracking = self.inst_tracking.getPtr(inst).?;
1166411656 return switch (tracking.short) {
1166511657 .none, .unreach, .dead => unreachable,
1166611658 else => tracking,
src/codegen/c.zig+26-29
......@@ -53,7 +53,7 @@ const BlockData = struct {
5353 result: CValue,
5454};
5555
56pub const CValueMap = std.AutoHashMap(Air.Inst.Index, CValue);
56pub const CValueMap = std.AutoHashMap(Air.Inst.Ref, CValue);
5757
5858pub const LazyFnKey = union(enum) {
5959 tag_name: Decl.Index,
......@@ -282,31 +282,29 @@ pub const Function = struct {
282282 allocs: std.AutoArrayHashMapUnmanaged(LocalIndex, bool) = .{},
283283
284284 fn resolveInst(f: *Function, ref: Air.Inst.Ref) !CValue {
285 if (Air.refToIndex(ref)) |inst| {
286 const gop = try f.value_map.getOrPut(inst);
287 if (gop.found_existing) return gop.value_ptr.*;
285 const gop = try f.value_map.getOrPut(ref);
286 if (gop.found_existing) return gop.value_ptr.*;
288287
289 const mod = f.object.dg.module;
290 const val = (try f.air.value(ref, mod)).?;
291 const ty = f.typeOf(ref);
292
293 const result: CValue = if (lowersToArray(ty, mod)) result: {
294 const writer = f.object.code_header.writer();
295 const alignment = 0;
296 const decl_c_value = try f.allocLocalValue(ty, alignment);
297 const gpa = f.object.dg.gpa;
298 try f.allocs.put(gpa, decl_c_value.new_local, false);
299 try writer.writeAll("static ");
300 try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, alignment, .complete);
301 try writer.writeAll(" = ");
302 try f.object.dg.renderValue(writer, ty, val, .StaticInitializer);
303 try writer.writeAll(";\n ");
304 break :result decl_c_value;
305 } else .{ .constant = ref };
288 const mod = f.object.dg.module;
289 const val = (try f.air.value(ref, mod)).?;
290 const ty = f.typeOf(ref);
291
292 const result: CValue = if (lowersToArray(ty, mod)) result: {
293 const writer = f.object.code_header.writer();
294 const alignment = 0;
295 const decl_c_value = try f.allocLocalValue(ty, alignment);
296 const gpa = f.object.dg.gpa;
297 try f.allocs.put(gpa, decl_c_value.new_local, false);
298 try writer.writeAll("static ");
299 try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, alignment, .complete);
300 try writer.writeAll(" = ");
301 try f.object.dg.renderValue(writer, ty, val, .StaticInitializer);
302 try writer.writeAll(";\n ");
303 break :result decl_c_value;
304 } else .{ .constant = ref };
306305
307 gop.value_ptr.* = result;
308 return result;
309 } else return .{ .constant = ref };
306 gop.value_ptr.* = result;
307 return result;
310308 }
311309
312310 fn wantSafety(f: *Function) bool {
......@@ -2823,7 +2821,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
28232821
28242822 const result_value = switch (air_tags[inst]) {
28252823 // zig fmt: off
2826 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
2824 .inferred_alloc, .inferred_alloc_comptime => unreachable,
28272825
28282826 .arg => try airArg(f, inst),
28292827
......@@ -3091,7 +3089,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
30913089 if (result_value == .new_local) {
30923090 log.debug("map %{d} to t{d}", .{ inst, result_value.new_local });
30933091 }
3094 try f.value_map.putNoClobber(inst, switch (result_value) {
3092 try f.value_map.putNoClobber(Air.indexToRef(inst), switch (result_value) {
30953093 .none => continue,
30963094 .new_local => |i| .{ .local = i },
30973095 else => result_value,
......@@ -7439,7 +7437,7 @@ fn formatIntLiteral(
74397437 } else data.val.toBigInt(&int_buf, mod);
74407438 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);
74437441 var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined;
74447442 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
77457743
77467744fn die(f: *Function, inst: Air.Inst.Index, ref: Air.Inst.Ref) !void {
77477745 const ref_inst = Air.refToIndex(ref) orelse return;
7748 assert(f.air.instructions.items(.tag)[ref_inst] != .interned);
7749 const c_value = (f.value_map.fetchRemove(ref_inst) orelse return).value;
7746 const c_value = (f.value_map.fetchRemove(ref) orelse return).value;
77507747 const local_index = switch (c_value) {
77517748 .local, .new_local => |l| l,
77527749 else => return,
src/codegen/llvm.zig+16-13
......@@ -4557,7 +4557,7 @@ pub const FuncGen = struct {
45574557
45584558 .vector_store_elem => try self.airVectorStoreElem(inst),
45594559
4560 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
4560 .inferred_alloc, .inferred_alloc_comptime => unreachable,
45614561
45624562 .unreach => self.airUnreach(inst),
45634563 .dbg_stmt => self.airDbgStmt(inst),
......@@ -5762,19 +5762,22 @@ pub const FuncGen = struct {
57625762
57635763 return self.loadByRef(elem_ptr, elem_ty, elem_ty.abiAlignment(mod), false);
57645764 } else {
5765 const lhs_index = Air.refToIndex(bin_op.lhs).?;
57665765 const elem_llvm_ty = try o.lowerType(elem_ty);
5767 if (self.air.instructions.items(.tag)[lhs_index] == .load) {
5768 const load_data = self.air.instructions.items(.data)[lhs_index];
5769 const load_ptr = load_data.ty_op.operand;
5770 const load_ptr_tag = self.air.instructions.items(.tag)[Air.refToIndex(load_ptr).?];
5771 switch (load_ptr_tag) {
5772 .struct_field_ptr, .struct_field_ptr_index_0, .struct_field_ptr_index_1, .struct_field_ptr_index_2, .struct_field_ptr_index_3 => {
5773 const load_ptr_inst = try self.resolveInst(load_ptr);
5774 const gep = self.builder.buildInBoundsGEP(array_llvm_ty, load_ptr_inst, &indices, indices.len, "");
5775 return self.builder.buildLoad(elem_llvm_ty, gep, "");
5776 },
5777 else => {},
5766 if (Air.refToIndex(bin_op.lhs)) |lhs_index| {
5767 if (self.air.instructions.items(.tag)[lhs_index] == .load) {
5768 const load_data = self.air.instructions.items(.data)[lhs_index];
5769 const load_ptr = load_data.ty_op.operand;
5770 if (Air.refToIndex(load_ptr)) |load_ptr_index| {
5771 const load_ptr_tag = self.air.instructions.items(.tag)[load_ptr_index];
5772 switch (load_ptr_tag) {
5773 .struct_field_ptr, .struct_field_ptr_index_0, .struct_field_ptr_index_1, .struct_field_ptr_index_2, .struct_field_ptr_index_3 => {
5774 const load_ptr_inst = try self.resolveInst(load_ptr);
5775 const gep = self.builder.buildInBoundsGEP(array_llvm_ty, load_ptr_inst, &indices, indices.len, "");
5776 return self.builder.buildLoad(elem_llvm_ty, gep, "");
5777 },
5778 else => {},
5779 }
5780 }
57785781 }
57795782 }
57805783 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
4949 .indent = 2,
5050 .skip_body = false,
5151 };
52 writer.writeAllConstants(stream) catch return;
53 stream.writeByte('\n') catch return;
5452 writer.writeBody(stream, air.getMainBody()) catch return;
5553}
5654
......@@ -88,15 +86,6 @@ const Writer = struct {
8886 indent: usize,
8987 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
10089 fn writeBody(w: *Writer, s: anytype, body: []const Air.Inst.Index) @TypeOf(s).Error!void {
10190 for (body) |inst| {
10291 try w.writeInst(s, inst);
......@@ -299,7 +288,6 @@ const Writer = struct {
299288 .struct_field_val => try w.writeStructField(s, inst),
300289 .inferred_alloc => @panic("TODO"),
301290 .inferred_alloc_comptime => @panic("TODO"),
302 .interned => try w.writeInterned(s, inst),
303291 .assembly => try w.writeAssembly(s, inst),
304292 .dbg_stmt => try w.writeDbgStmt(s, inst),
305293
......@@ -596,14 +584,6 @@ const Writer = struct {
596584 try s.print(", {d}", .{extra.field_index});
597585 }
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
607587 fn writeAssembly(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
608588 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
609589 const extra = w.air.extraData(Air.Asm, ty_pl.payload);
......@@ -956,13 +936,18 @@ const Writer = struct {
956936 operand: Air.Inst.Ref,
957937 dies: bool,
958938 ) @TypeOf(s).Error!void {
959 const i = @intFromEnum(operand);
960
961 if (i < InternPool.static_len) {
939 if (@intFromEnum(operand) < InternPool.static_len) {
962940 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);
963950 }
964
965 return w.writeInstIndex(s, i - InternPool.static_len, dies);
966951 }
967952
968953 fn writeInstIndex(