authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-05-25 22:28:02-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:55-07:00
logf37c0a459382fa033cefc9bb139277436a78b25e
tree6860bcc6f0d95190cb68fb43fc7da6d593322b1c
parent5d0d5893fd39047e4fdbb6623e4d69babf0b2ed4

Sema: inferred allocations no longer abuse type/value system

Previously, there were types and values for inferred allocations and a lot of special-case handling. Now, instead, the special casing is limited to AIR instructions for these use cases. Instead of storing data in Value payloads, the data is now stored in AIR instruction data as well as the previously `void` value type of the `unresolved_inferred_allocs` hash map.

7 files changed, 160 insertions(+), 264 deletions(-)

src/Air.zig+26-10
......@@ -186,13 +186,17 @@ pub const Inst = struct {
186186 /// Allocates stack local memory.
187187 /// Uses the `ty` field.
188188 alloc,
189 /// This is a special value that tracks a set of types that have been stored
190 /// to an inferred allocation. It does not support any of the normal value queries.
191 /// Uses the `ty_pl` field, payload is an index of `values` array.
189 /// This special instruction only exists temporarily during semantic
190 /// analysis and is guaranteed to be unreachable in machine code
191 /// backends. It tracks a set of types that have been stored to an
192 /// inferred allocation.
193 /// Uses the `inferred_alloc` field.
192194 inferred_alloc,
193 /// Used to coordinate alloc_inferred, store_to_inferred_ptr, and resolve_inferred_alloc
194 /// instructions for comptime code.
195 /// Uses the `ty_pl` field, payload is an index of `values` array.
195 /// This special instruction only exists temporarily during semantic
196 /// analysis and is guaranteed to be unreachable in machine code
197 /// backends. Used to coordinate alloc_inferred, store_to_inferred_ptr,
198 /// and resolve_inferred_alloc instructions for comptime code.
199 /// Uses the `inferred_alloc_comptime` field.
196200 inferred_alloc_comptime,
197201 /// If the function will pass the result by-ref, this instruction returns the
198202 /// result pointer. Otherwise it is equivalent to `alloc`.
......@@ -908,8 +912,6 @@ pub const Inst = struct {
908912 slice_const_u8_sentinel_0_type = @enumToInt(InternPool.Index.slice_const_u8_sentinel_0_type),
909913 anyerror_void_error_union_type = @enumToInt(InternPool.Index.anyerror_void_error_union_type),
910914 generic_poison_type = @enumToInt(InternPool.Index.generic_poison_type),
911 inferred_alloc_const_type = @enumToInt(InternPool.Index.inferred_alloc_const_type),
912 inferred_alloc_mut_type = @enumToInt(InternPool.Index.inferred_alloc_mut_type),
913915 empty_struct_type = @enumToInt(InternPool.Index.empty_struct_type),
914916 undef = @enumToInt(InternPool.Index.undef),
915917 zero = @enumToInt(InternPool.Index.zero),
......@@ -997,6 +999,19 @@ pub const Inst = struct {
997999 // Index into a different array.
9981000 payload: u32,
9991001 },
1002 inferred_alloc_comptime: InferredAllocComptime,
1003 inferred_alloc: InferredAlloc,
1004
1005 pub const InferredAllocComptime = struct {
1006 decl_index: Module.Decl.Index,
1007 alignment: InternPool.Alignment,
1008 is_const: bool,
1009 };
1010
1011 pub const InferredAlloc = struct {
1012 alignment: InternPool.Alignment,
1013 is_const: bool,
1014 };
10001015
10011016 // Make sure we don't accidentally add a field to make this union
10021017 // bigger than expected. Note that in Debug builds, Zig is allowed
......@@ -1287,8 +1302,6 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index, ip: InternPool) Type {
12871302 .sub_with_overflow,
12881303 .mul_with_overflow,
12891304 .shl_with_overflow,
1290 .inferred_alloc,
1291 .inferred_alloc_comptime,
12921305 .ptr_add,
12931306 .ptr_sub,
12941307 .try_ptr,
......@@ -1424,6 +1437,9 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index, ip: InternPool) Type {
14241437 .work_group_size,
14251438 .work_group_id,
14261439 => return Type.u32,
1440
1441 .inferred_alloc => unreachable,
1442 .inferred_alloc_comptime => unreachable,
14271443 }
14281444}
14291445
src/InternPool.zig-12
......@@ -1156,8 +1156,6 @@ pub const Index = enum(u32) {
11561156 slice_const_u8_sentinel_0_type,
11571157 anyerror_void_error_union_type,
11581158 generic_poison_type,
1159 inferred_alloc_const_type,
1160 inferred_alloc_mut_type,
11611159 /// `@TypeOf(.{})`
11621160 empty_struct_type,
11631161
......@@ -1525,10 +1523,6 @@ pub const static_keys = [_]Key{
15251523
15261524 // generic_poison_type
15271525 .{ .simple_type = .generic_poison },
1528 // inferred_alloc_const_type
1529 .{ .simple_type = .inferred_alloc_const },
1530 // inferred_alloc_mut_type
1531 .{ .simple_type = .inferred_alloc_mut },
15321526
15331527 // empty_struct_type
15341528 .{ .anon_struct_type = .{
......@@ -1958,12 +1952,6 @@ pub const SimpleType = enum(u32) {
19581952 type_info,
19591953
19601954 generic_poison,
1961 /// TODO: remove this from `SimpleType`; instead make it only a special `Index` tag like
1962 /// `var_args_param_type`.
1963 inferred_alloc_const,
1964 /// TODO: remove this from `SimpleType`; instead make it only a special `Index` tag like
1965 /// `var_args_param_type`.
1966 inferred_alloc_mut,
19671955};
19681956
19691957pub const SimpleValue = enum(u32) {
src/Sema.zig+128-160
......@@ -89,7 +89,9 @@ is_generic_instantiation: bool = false,
8989/// function types will emit generic poison instead of a partial type.
9090no_partial_func_ty: bool = false,
9191
92unresolved_inferred_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, void) = .{},
92/// The temporary arena is used for the memory of the `InferredAlloc` values
93/// here so the values can be dropped without any cleanup.
94unresolved_inferred_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, InferredAlloc) = .{},
9395
9496const std = @import("std");
9597const math = std.math;
......@@ -718,7 +720,7 @@ pub const Block = struct {
718720 }
719721
720722 /// `alignment` value of 0 means to use ABI alignment.
721 pub fn finish(wad: *WipAnonDecl, ty: Type, val: Value, alignment: u32) !Decl.Index {
723 pub fn finish(wad: *WipAnonDecl, ty: Type, val: Value, alignment: u64) !Decl.Index {
722724 const sema = wad.block.sema;
723725 // Do this ahead of time because `createAnonymousDecl` depends on calling
724726 // `type.hasRuntimeBits()`.
......@@ -728,7 +730,8 @@ pub const Block = struct {
728730 .val = val,
729731 });
730732 const new_decl = sema.mod.declPtr(new_decl_index);
731 new_decl.@"align" = alignment;
733 // TODO: migrate Decl alignment to use `InternPool.Alignment`
734 new_decl.@"align" = @intCast(u32, alignment);
732735 errdefer sema.mod.abortAnonDecl(new_decl_index);
733736 try new_decl.finalizeNewArena(&wad.new_decl_arena);
734737 wad.finished = true;
......@@ -748,6 +751,23 @@ const LabeledBlock = struct {
748751 }
749752};
750753
754/// The value stored in the inferred allocation. This will go into
755/// peer type resolution. This is stored in a separate list so that
756/// the items are contiguous in memory and thus can be passed to
757/// `Module.resolvePeerTypes`.
758const InferredAlloc = struct {
759 prongs: std.MultiArrayList(struct {
760 /// The dummy instruction used as a peer to resolve the type.
761 /// Although this has a redundant type with placeholder, this is
762 /// needed in addition because it may be a constant value, which
763 /// affects peer type resolution.
764 stored_inst: Air.Inst.Ref,
765 /// The bitcast instruction used as a placeholder when the
766 /// new result pointer type is not yet known.
767 placeholder: Air.Inst.Index,
768 }) = .{},
769};
770
751771pub fn deinit(sema: *Sema) void {
752772 const gpa = sema.gpa;
753773 sema.air_instructions.deinit(gpa);
......@@ -909,10 +929,10 @@ fn analyzeBodyInner(
909929 const air_inst: Air.Inst.Ref = switch (tags[inst]) {
910930 // zig fmt: off
911931 .alloc => try sema.zirAlloc(block, inst),
912 .alloc_inferred => try sema.zirAllocInferred(block, inst, .{ .ip_index = .inferred_alloc_const_type }),
913 .alloc_inferred_mut => try sema.zirAllocInferred(block, inst, .{ .ip_index = .inferred_alloc_mut_type }),
914 .alloc_inferred_comptime => try sema.zirAllocInferredComptime(inst, .{ .ip_index = .inferred_alloc_const_type }),
915 .alloc_inferred_comptime_mut => try sema.zirAllocInferredComptime(inst, .{ .ip_index = .inferred_alloc_mut_type }),
932 .alloc_inferred => try sema.zirAllocInferred(block, inst, true),
933 .alloc_inferred_mut => try sema.zirAllocInferred(block, inst, false),
934 .alloc_inferred_comptime => try sema.zirAllocInferredComptime(inst, true),
935 .alloc_inferred_comptime_mut => try sema.zirAllocInferredComptime(inst, false),
916936 .alloc_mut => try sema.zirAllocMut(block, inst),
917937 .alloc_comptime_mut => try sema.zirAllocComptime(block, inst),
918938 .make_ptr_const => try sema.zirMakePtrConst(block, inst),
......@@ -1707,7 +1727,7 @@ fn analyzeBodyInner(
17071727 break :blk Air.Inst.Ref.void_value;
17081728 },
17091729 };
1710 if (sema.typeOf(air_inst).isNoReturn(mod))
1730 if (sema.isNoReturn(air_inst))
17111731 break always_noreturn;
17121732 map.putAssumeCapacity(inst, air_inst);
17131733 i += 1;
......@@ -1751,8 +1771,6 @@ pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
17511771 // The last section of indexes refers to the map of ZIR => AIR.
17521772 const inst = sema.inst_map.get(i - InternPool.static_len).?;
17531773 if (inst == .generic_poison) return error.GenericPoison;
1754 const ty = sema.typeOf(inst);
1755 assert(!ty.isGenericPoison());
17561774 return inst;
17571775}
17581776
......@@ -2431,20 +2449,20 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
24312449 const tracy = trace(@src());
24322450 defer tracy.end();
24332451
2452 const mod = sema.mod;
24342453 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
24352454 const src = inst_data.src();
24362455 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
24372456 const pointee_ty = try sema.resolveType(block, src, extra.lhs);
24382457 const ptr = try sema.resolveInst(extra.rhs);
2439 const target = sema.mod.getTarget();
2458 const target = mod.getTarget();
24402459 const addr_space = target_util.defaultAddressSpace(target, .local);
24412460
24422461 if (Air.refToIndex(ptr)) |ptr_inst| {
24432462 switch (sema.air_instructions.items(.tag)[ptr_inst]) {
24442463 .inferred_alloc => {
2445 const air_datas = sema.air_instructions.items(.data);
2446 const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload];
2447 const inferred_alloc = &ptr_val.castTag(.inferred_alloc).?.data;
2464 const ia1 = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc;
2465 const ia2 = sema.unresolved_inferred_allocs.getPtr(ptr_inst).?;
24482466 // Add the stored instruction to the set we will use to resolve peer types
24492467 // for the inferred allocation.
24502468 // This instruction will not make it to codegen; it is only to participate
......@@ -2453,14 +2471,14 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
24532471 defer trash_block.instructions.deinit(sema.gpa);
24542472 const operand = try trash_block.addBitCast(pointee_ty, .void_value);
24552473
2456 const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
2457 .pointee_type = pointee_ty,
2458 .@"align" = inferred_alloc.alignment,
2459 .@"addrspace" = addr_space,
2474 const ptr_ty = try mod.ptrType(.{
2475 .elem_type = pointee_ty.toIntern(),
2476 .alignment = ia1.alignment,
2477 .address_space = addr_space,
24602478 });
24612479 const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr);
24622480
2463 try inferred_alloc.prongs.append(sema.arena, .{
2481 try ia2.prongs.append(sema.arena, .{
24642482 .stored_inst = operand,
24652483 .placeholder = Air.refToIndex(bitcasted_ptr).?,
24662484 });
......@@ -2468,31 +2486,30 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
24682486 return bitcasted_ptr;
24692487 },
24702488 .inferred_alloc_comptime => {
2471 const air_datas = sema.air_instructions.items(.data);
2472 const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload];
2473 const iac = ptr_val.castTag(.inferred_alloc_comptime).?;
2489 const alignment = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime.alignment;
24742490 // There will be only one coerce_result_ptr because we are running at comptime.
24752491 // The alloc will turn into a Decl.
24762492 var anon_decl = try block.startAnonDecl();
24772493 defer anon_decl.deinit();
2478 iac.data.decl_index = try anon_decl.finish(
2494 const decl_index = try anon_decl.finish(
24792495 pointee_ty,
24802496 Value.undef,
2481 iac.data.alignment,
2497 alignment.toByteUnits(0),
24822498 );
2483 if (iac.data.alignment != 0) {
2499 sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime.decl_index = decl_index;
2500 if (alignment != .none) {
24842501 try sema.resolveTypeLayout(pointee_ty);
24852502 }
2486 const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
2487 .pointee_type = pointee_ty,
2488 .@"align" = iac.data.alignment,
2489 .@"addrspace" = addr_space,
2503 const ptr_ty = try mod.ptrType(.{
2504 .elem_type = pointee_ty.toIntern(),
2505 .alignment = alignment,
2506 .address_space = addr_space,
24902507 });
2491 try sema.maybeQueueFuncBodyAnalysis(iac.data.decl_index);
2492 return sema.addConstant(ptr_ty, (try sema.mod.intern(.{ .ptr = .{
2508 try sema.maybeQueueFuncBodyAnalysis(decl_index);
2509 return sema.addConstant(ptr_ty, (try mod.intern(.{ .ptr = .{
24932510 .ty = ptr_ty.toIntern(),
24942511 .addr = .{ .mut_decl = .{
2495 .decl = iac.data.decl_index,
2512 .decl = decl_index,
24962513 .runtime_index = block.runtime_index,
24972514 } },
24982515 } })).toValue());
......@@ -3479,25 +3496,16 @@ fn zirAllocExtended(
34793496 break :blk alignment;
34803497 } else 0;
34813498
3482 const inferred_alloc_ty = if (small.is_const)
3483 Type{ .ip_index = .inferred_alloc_const_type }
3484 else
3485 Type{ .ip_index = .inferred_alloc_mut_type };
3486
34873499 if (block.is_comptime or small.is_comptime) {
34883500 if (small.has_type) {
34893501 return sema.analyzeComptimeAlloc(block, var_ty, alignment);
34903502 } else {
3491 const ty_inst = try sema.addType(inferred_alloc_ty);
3492 try sema.air_values.append(gpa, try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{
3493 .decl_index = undefined,
3494 .alignment = alignment,
3495 }));
34963503 try sema.air_instructions.append(gpa, .{
34973504 .tag = .inferred_alloc_comptime,
3498 .data = .{ .ty_pl = .{
3499 .ty = ty_inst,
3500 .payload = @intCast(u32, sema.air_values.items.len - 1),
3505 .data = .{ .inferred_alloc_comptime = .{
3506 .decl_index = undefined,
3507 .alignment = InternPool.Alignment.fromByteUnits(alignment),
3508 .is_const = small.is_const,
35013509 } },
35023510 });
35033511 return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));
......@@ -3518,18 +3526,14 @@ fn zirAllocExtended(
35183526 return block.addTy(.alloc, ptr_type);
35193527 }
35203528
3521 const ty_inst = try sema.addType(inferred_alloc_ty);
3522 try sema.air_values.append(gpa, try Value.Tag.inferred_alloc.create(sema.arena, .{
3523 .alignment = alignment,
3524 }));
35253529 const result_index = try block.addInstAsIndex(.{
35263530 .tag = .inferred_alloc,
3527 .data = .{ .ty_pl = .{
3528 .ty = ty_inst,
3529 .payload = @intCast(u32, sema.air_values.items.len - 1),
3531 .data = .{ .inferred_alloc = .{
3532 .alignment = InternPool.Alignment.fromByteUnits(alignment),
3533 .is_const = small.is_const,
35303534 } },
35313535 });
3532 try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, {});
3536 try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, .{});
35333537 return Air.indexToRef(result_index);
35343538}
35353539
......@@ -3623,23 +3627,19 @@ fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Ai
36233627fn zirAllocInferredComptime(
36243628 sema: *Sema,
36253629 inst: Zir.Inst.Index,
3626 inferred_alloc_ty: Type,
3630 is_const: bool,
36273631) CompileError!Air.Inst.Ref {
36283632 const gpa = sema.gpa;
36293633 const src_node = sema.code.instructions.items(.data)[inst].node;
36303634 const src = LazySrcLoc.nodeOffset(src_node);
36313635 sema.src = src;
36323636
3633 const ty_inst = try sema.addType(inferred_alloc_ty);
3634 try sema.air_values.append(gpa, try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{
3635 .decl_index = undefined,
3636 .alignment = 0,
3637 }));
36383637 try sema.air_instructions.append(gpa, .{
36393638 .tag = .inferred_alloc_comptime,
3640 .data = .{ .ty_pl = .{
3641 .ty = ty_inst,
3642 .payload = @intCast(u32, sema.air_values.items.len - 1),
3639 .data = .{ .inferred_alloc_comptime = .{
3640 .decl_index = undefined,
3641 .alignment = .none,
3642 .is_const = is_const,
36433643 } },
36443644 });
36453645 return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));
......@@ -3688,7 +3688,7 @@ fn zirAllocInferred(
36883688 sema: *Sema,
36893689 block: *Block,
36903690 inst: Zir.Inst.Index,
3691 inferred_alloc_ty: Type,
3691 is_const: bool,
36923692) CompileError!Air.Inst.Ref {
36933693 const tracy = trace(@src());
36943694 defer tracy.end();
......@@ -3698,33 +3698,26 @@ fn zirAllocInferred(
36983698 const src = LazySrcLoc.nodeOffset(src_node);
36993699 sema.src = src;
37003700
3701 const ty_inst = try sema.addType(inferred_alloc_ty);
37023701 if (block.is_comptime) {
3703 try sema.air_values.append(gpa, try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{
3704 .decl_index = undefined,
3705 .alignment = 0,
3706 }));
37073702 try sema.air_instructions.append(gpa, .{
37083703 .tag = .inferred_alloc_comptime,
3709 .data = .{ .ty_pl = .{
3710 .ty = ty_inst,
3711 .payload = @intCast(u32, sema.air_values.items.len - 1),
3704 .data = .{ .inferred_alloc_comptime = .{
3705 .decl_index = undefined,
3706 .alignment = .none,
3707 .is_const = is_const,
37123708 } },
37133709 });
37143710 return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));
37153711 }
37163712
3717 try sema.air_values.append(gpa, try Value.Tag.inferred_alloc.create(sema.arena, .{
3718 .alignment = 0,
3719 }));
37203713 const result_index = try block.addInstAsIndex(.{
37213714 .tag = .inferred_alloc,
3722 .data = .{ .ty_pl = .{
3723 .ty = ty_inst,
3724 .payload = @intCast(u32, sema.air_values.items.len - 1),
3715 .data = .{ .inferred_alloc = .{
3716 .alignment = .none,
3717 .is_const = is_const,
37253718 } },
37263719 });
3727 try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, {});
3720 try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, .{});
37283721 return Air.indexToRef(result_index);
37293722}
37303723
......@@ -3732,44 +3725,36 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
37323725 const tracy = trace(@src());
37333726 defer tracy.end();
37343727
3728 const mod = sema.mod;
37353729 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
37363730 const src = inst_data.src();
37373731 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node };
37383732 const ptr = try sema.resolveInst(inst_data.operand);
37393733 const ptr_inst = Air.refToIndex(ptr).?;
3740 const value_index = sema.air_instructions.items(.data)[ptr_inst].ty_pl.payload;
3741 const ptr_val = sema.air_values.items[value_index];
3742 const var_is_mut = switch (sema.typeOf(ptr).toIntern()) {
3743 .inferred_alloc_const_type => false,
3744 .inferred_alloc_mut_type => true,
3745 else => unreachable,
3746 };
3747 const target = sema.mod.getTarget();
3734 const target = mod.getTarget();
37483735
37493736 switch (sema.air_instructions.items(.tag)[ptr_inst]) {
37503737 .inferred_alloc_comptime => {
3751 const iac = ptr_val.castTag(.inferred_alloc_comptime).?;
3752 const decl_index = iac.data.decl_index;
3753 try sema.mod.declareDeclDependency(sema.owner_decl_index, decl_index);
3738 const iac = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime;
3739 const decl_index = iac.decl_index;
3740 try mod.declareDeclDependency(sema.owner_decl_index, decl_index);
37543741
3755 const decl = sema.mod.declPtr(decl_index);
3742 const decl = mod.declPtr(decl_index);
37563743 const final_elem_ty = decl.ty;
3757 const final_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
3758 .pointee_type = final_elem_ty,
3759 .mutable = true,
3760 .@"align" = iac.data.alignment,
3761 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
3744 const final_ptr_ty = try mod.ptrType(.{
3745 .elem_type = final_elem_ty.toIntern(),
3746 .is_const = false,
3747 .alignment = iac.alignment,
3748 .address_space = target_util.defaultAddressSpace(target, .local),
37623749 });
3763 const final_ptr_ty_inst = try sema.addType(final_ptr_ty);
3764 sema.air_instructions.items(.data)[ptr_inst].ty_pl.ty = final_ptr_ty_inst;
37653750
37663751 try sema.maybeQueueFuncBodyAnalysis(decl_index);
37673752 // Change it to an interned.
37683753 sema.air_instructions.set(ptr_inst, .{
37693754 .tag = .interned,
3770 .data = .{ .interned = try sema.mod.intern(.{ .ptr = .{
3755 .data = .{ .interned = try mod.intern(.{ .ptr = .{
37713756 .ty = final_ptr_ty.toIntern(),
3772 .addr = if (var_is_mut) .{ .mut_decl = .{
3757 .addr = if (!iac.is_const) .{ .mut_decl = .{
37733758 .decl = decl_index,
37743759 .runtime_index = block.runtime_index,
37753760 } } else .{ .decl = decl_index },
......@@ -3777,19 +3762,18 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
37773762 });
37783763 },
37793764 .inferred_alloc => {
3780 assert(sema.unresolved_inferred_allocs.remove(ptr_inst));
3781 const inferred_alloc = ptr_val.castTag(.inferred_alloc).?;
3782 const peer_inst_list = inferred_alloc.data.prongs.items(.stored_inst);
3765 const ia1 = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc;
3766 const ia2 = sema.unresolved_inferred_allocs.fetchRemove(ptr_inst).?.value;
3767 const peer_inst_list = ia2.prongs.items(.stored_inst);
37833768 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list, .none);
37843769
3785 const final_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
3786 .pointee_type = final_elem_ty,
3787 .mutable = true,
3788 .@"align" = inferred_alloc.data.alignment,
3789 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
3770 const final_ptr_ty = try mod.ptrType(.{
3771 .elem_type = final_elem_ty.toIntern(),
3772 .alignment = ia1.alignment,
3773 .address_space = target_util.defaultAddressSpace(target, .local),
37903774 });
37913775
3792 if (var_is_mut) {
3776 if (!ia1.is_const) {
37933777 try sema.validateVarType(block, ty_src, final_elem_ty, false);
37943778 } else ct: {
37953779 // Detect if the value is comptime-known. In such case, the
......@@ -3858,23 +3842,23 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
38583842 const new_decl_index = try anon_decl.finish(
38593843 final_elem_ty,
38603844 try store_val.copy(anon_decl.arena()),
3861 inferred_alloc.data.alignment,
3845 ia1.alignment.toByteUnits(0),
38623846 );
38633847 break :d new_decl_index;
38643848 };
3865 try sema.mod.declareDeclDependency(sema.owner_decl_index, new_decl_index);
3849 try mod.declareDeclDependency(sema.owner_decl_index, new_decl_index);
38663850
38673851 // Even though we reuse the constant instruction, we still remove it from the
38683852 // block so that codegen does not see it.
38693853 block.instructions.shrinkRetainingCapacity(search_index);
38703854 try sema.maybeQueueFuncBodyAnalysis(new_decl_index);
3871 sema.air_values.items[value_index] = (try sema.mod.intern(.{ .ptr = .{
3872 .ty = final_elem_ty.toIntern(),
3873 .addr = .{ .decl = new_decl_index },
3874 } })).toValue();
3875 // if bitcast ty ref needs to be made const, make_ptr_const
3876 // ZIR handles it later, so we can just use the ty ref here.
3877 air_datas[ptr_inst].ty_pl.ty = air_datas[bitcast_inst].ty_op.ty;
3855 sema.air_instructions.set(ptr_inst, .{
3856 .tag = .interned,
3857 .data = .{ .interned = try mod.intern(.{ .ptr = .{
3858 .ty = final_elem_ty.toIntern(),
3859 .addr = .{ .decl = new_decl_index },
3860 } }) },
3861 });
38783862
38793863 // Unless the block is comptime, `alloc_inferred` always produces
38803864 // a runtime constant. The final inferred type needs to be
......@@ -3895,18 +3879,17 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
38953879 // Now we need to go back over all the coerce_result_ptr instructions, which
38963880 // previously inserted a bitcast as a placeholder, and do the logic as if
38973881 // the new result ptr type was available.
3898 const placeholders = inferred_alloc.data.prongs.items(.placeholder);
3882 const placeholders = ia2.prongs.items(.placeholder);
38993883 const gpa = sema.gpa;
39003884
39013885 var trash_block = block.makeSubBlock();
39023886 trash_block.is_comptime = false;
39033887 defer trash_block.instructions.deinit(gpa);
39043888
3905 const mut_final_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
3906 .pointee_type = final_elem_ty,
3907 .mutable = true,
3908 .@"align" = inferred_alloc.data.alignment,
3909 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
3889 const mut_final_ptr_ty = try mod.ptrType(.{
3890 .elem_type = final_elem_ty.toIntern(),
3891 .alignment = ia1.alignment,
3892 .address_space = target_util.defaultAddressSpace(target, .local),
39103893 });
39113894 const dummy_ptr = try trash_block.addTy(.alloc, mut_final_ptr_ty);
39123895 const empty_trash_count = trash_block.instructions.items.len;
......@@ -3914,7 +3897,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
39143897 for (peer_inst_list, placeholders) |peer_inst, placeholder_inst| {
39153898 const sub_ptr_ty = sema.typeOf(Air.indexToRef(placeholder_inst));
39163899
3917 if (mut_final_ptr_ty.eql(sub_ptr_ty, sema.mod)) {
3900 if (mut_final_ptr_ty.eql(sub_ptr_ty, mod)) {
39183901 // New result location type is the same as the old one; nothing
39193902 // to do here.
39203903 continue;
......@@ -5009,17 +4992,14 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
50094992 const src: LazySrcLoc = sema.src;
50104993 blk: {
50114994 const ptr_inst = Air.refToIndex(ptr) orelse break :blk;
5012 const air_data = sema.air_instructions.items(.data)[ptr_inst];
50134995 switch (sema.air_instructions.items(.tag)[ptr_inst]) {
50144996 .inferred_alloc_comptime => {
5015 const ptr_val = sema.air_values.items[air_data.ty_pl.payload];
5016 const iac = ptr_val.castTag(.inferred_alloc_comptime).?;
4997 const iac = &sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime;
50174998 return sema.storeToInferredAllocComptime(block, src, operand, iac);
50184999 },
50195000 .inferred_alloc => {
5020 const ptr_val = sema.air_values.items[air_data.ty_pl.payload];
5021 const inferred_alloc = ptr_val.castTag(.inferred_alloc).?;
5022 return sema.storeToInferredAlloc(block, ptr, operand, inferred_alloc);
5001 const ia = sema.unresolved_inferred_allocs.getPtr(ptr_inst).?;
5002 return sema.storeToInferredAlloc(block, ptr, operand, ia);
50235003 },
50245004 else => break :blk,
50255005 }
......@@ -5038,16 +5018,15 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi
50385018 const operand = try sema.resolveInst(bin_inst.rhs);
50395019 const ptr_inst = Air.refToIndex(ptr).?;
50405020 const air_datas = sema.air_instructions.items(.data);
5041 const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload];
50425021
50435022 switch (sema.air_instructions.items(.tag)[ptr_inst]) {
50445023 .inferred_alloc_comptime => {
5045 const iac = ptr_val.castTag(.inferred_alloc_comptime).?;
5024 const iac = &air_datas[ptr_inst].inferred_alloc_comptime;
50465025 return sema.storeToInferredAllocComptime(block, src, operand, iac);
50475026 },
50485027 .inferred_alloc => {
5049 const inferred_alloc = ptr_val.castTag(.inferred_alloc).?;
5050 return sema.storeToInferredAlloc(block, ptr, operand, inferred_alloc);
5028 const ia = sema.unresolved_inferred_allocs.getPtr(ptr_inst).?;
5029 return sema.storeToInferredAlloc(block, ptr, operand, ia);
50515030 },
50525031 else => unreachable,
50535032 }
......@@ -5058,14 +5037,14 @@ fn storeToInferredAlloc(
50585037 block: *Block,
50595038 ptr: Air.Inst.Ref,
50605039 operand: Air.Inst.Ref,
5061 inferred_alloc: *Value.Payload.InferredAlloc,
5040 inferred_alloc: *InferredAlloc,
50625041) CompileError!void {
50635042 // Create a store instruction as a placeholder. This will be replaced by a
50645043 // proper store sequence once we know the stored type.
50655044 const dummy_store = try block.addBinOp(.store, ptr, operand);
50665045 // Add the stored instruction to the set we will use to resolve peer types
50675046 // for the inferred allocation.
5068 try inferred_alloc.data.prongs.append(sema.arena, .{
5047 try inferred_alloc.prongs.append(sema.arena, .{
50695048 .stored_inst = operand,
50705049 .placeholder = Air.refToIndex(dummy_store).?,
50715050 });
......@@ -5076,7 +5055,7 @@ fn storeToInferredAllocComptime(
50765055 block: *Block,
50775056 src: LazySrcLoc,
50785057 operand: Air.Inst.Ref,
5079 iac: *Value.Payload.InferredAllocComptime,
5058 iac: *Air.Inst.Data.InferredAllocComptime,
50805059) CompileError!void {
50815060 const operand_ty = sema.typeOf(operand);
50825061 // There will be only one store_to_inferred_ptr because we are running at comptime.
......@@ -5085,10 +5064,10 @@ fn storeToInferredAllocComptime(
50855064 if (operand_val.getVariable(sema.mod) != null) break :store;
50865065 var anon_decl = try block.startAnonDecl();
50875066 defer anon_decl.deinit();
5088 iac.data.decl_index = try anon_decl.finish(
5067 iac.decl_index = try anon_decl.finish(
50895068 operand_ty,
50905069 try operand_val.copy(anon_decl.arena()),
5091 iac.data.alignment,
5070 iac.alignment.toByteUnits(0),
50925071 );
50935072 return;
50945073 }
......@@ -27643,17 +27622,6 @@ fn obtainBitCastedVectorPtr(sema: *Sema, ptr: Air.Inst.Ref) ?Air.Inst.Ref {
2764327622 const prev_ptr = air_datas[ptr_inst].ty_op.operand;
2764427623 const prev_ptr_ty = sema.typeOf(prev_ptr);
2764527624 if (prev_ptr_ty.zigTypeTag(mod) != .Pointer) return null;
27646
27647 // TODO: I noticed that the behavior tests do not pass if these two
27648 // checks are missing. I don't understand why the presence of inferred
27649 // allocations is relevant to this function, or why it would have
27650 // different behavior depending on whether the types were inferred.
27651 // Something seems wrong here.
27652 switch (prev_ptr_ty.toIntern()) {
27653 .inferred_alloc_mut_type, .inferred_alloc_const_type => return null,
27654 else => {},
27655 }
27656
2765727625 const prev_ptr_child_ty = prev_ptr_ty.childType(mod);
2765827626 if (prev_ptr_child_ty.zigTypeTag(mod) == .Vector) break prev_ptr;
2765927627 ptr_inst = Air.refToIndex(prev_ptr) orelse return null;
......@@ -31749,9 +31717,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3174931717 .enum_literal,
3175031718 .type_info,
3175131719 => true,
31752
31753 .inferred_alloc_const => unreachable,
31754 .inferred_alloc_mut => unreachable,
3175531720 },
3175631721 .struct_type => |struct_type| {
3175731722 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
......@@ -32009,8 +31974,6 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
3200931974 .bool_false => unreachable,
3201031975 .empty_struct => unreachable,
3201131976 .generic_poison => unreachable,
32012 .inferred_alloc_const_type => unreachable,
32013 .inferred_alloc_mut_type => unreachable,
3201431977
3201531978 .type_info_type => return sema.getBuiltinType("Type"),
3201631979 .extern_options_type => return sema.getBuiltinType("ExternOptions"),
......@@ -33201,8 +33164,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3320133164 .undefined => Value.undef,
3320233165
3320333166 .generic_poison => return error.GenericPoison,
33204 .inferred_alloc_const => unreachable,
33205 .inferred_alloc_mut => unreachable,
3320633167 },
3320733168 .struct_type => |struct_type| {
3320833169 const resolved_ty = try sema.resolveTypeFields(ty);
......@@ -33737,9 +33698,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3373733698 .enum_literal,
3373833699 .type_info,
3373933700 => true,
33740
33741 .inferred_alloc_const => unreachable,
33742 .inferred_alloc_mut => unreachable,
3374333701 },
3374433702 .struct_type => |struct_type| {
3374533703 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
......@@ -34501,3 +34459,13 @@ fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type {
3450134459
3450234460 return mod.errorSetFromUnsortedNames(names.keys());
3450334461}
34462
34463/// Avoids crashing the compiler when asking if inferred allocations are noreturn.
34464fn isNoReturn(sema: *Sema, ref: Air.Inst.Ref) bool {
34465 if (ref == .noreturn_type) return true;
34466 if (Air.refToIndex(ref)) |inst| switch (sema.air_instructions.items(.tag)[inst]) {
34467 .inferred_alloc, .inferred_alloc_comptime => return false,
34468 else => {},
34469 };
34470 return sema.typeOf(ref).isNoReturn(sema.mod);
34471}
src/TypedValue.zig-3
......@@ -178,9 +178,6 @@ pub fn print(
178178 ty = ty.optionalChild(mod);
179179 return print(.{ .ty = ty, .val = val }, writer, level, mod);
180180 },
181 // TODO these should not appear in this function
182 .inferred_alloc => return writer.writeAll("(inferred allocation value)"),
183 .inferred_alloc_comptime => return writer.writeAll("(inferred comptime allocation value)"),
184181 },
185182 else => {
186183 const key = mod.intern_pool.indexToKey(val.ip_index);
src/Zir.zig-2
......@@ -2112,8 +2112,6 @@ pub const Inst = struct {
21122112 slice_const_u8_sentinel_0_type = @enumToInt(InternPool.Index.slice_const_u8_sentinel_0_type),
21132113 anyerror_void_error_union_type = @enumToInt(InternPool.Index.anyerror_void_error_union_type),
21142114 generic_poison_type = @enumToInt(InternPool.Index.generic_poison_type),
2115 inferred_alloc_const_type = @enumToInt(InternPool.Index.inferred_alloc_const_type),
2116 inferred_alloc_mut_type = @enumToInt(InternPool.Index.inferred_alloc_mut_type),
21172115 empty_struct_type = @enumToInt(InternPool.Index.empty_struct_type),
21182116 undef = @enumToInt(InternPool.Index.undef),
21192117 zero = @enumToInt(InternPool.Index.zero),
src/type.zig+6-30
......@@ -88,8 +88,6 @@ pub const Type = struct {
8888 .type_info => .Union,
8989
9090 .generic_poison => return error.GenericPoison,
91
92 .inferred_alloc_const, .inferred_alloc_mut => return .Pointer,
9391 },
9492
9593 // values, not types
......@@ -620,8 +618,6 @@ pub const Type = struct {
620618 => false,
621619
622620 .generic_poison => unreachable,
623 .inferred_alloc_const => unreachable,
624 .inferred_alloc_mut => unreachable,
625621 },
626622 .struct_type => |struct_type| {
627623 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse {
......@@ -777,9 +773,6 @@ pub const Type = struct {
777773 .type_info,
778774 .generic_poison,
779775 => false,
780
781 .inferred_alloc_const => unreachable,
782 .inferred_alloc_mut => unreachable,
783776 },
784777 .struct_type => |struct_type| {
785778 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse {
......@@ -1028,8 +1021,6 @@ pub const Type = struct {
10281021
10291022 .noreturn => unreachable,
10301023 .generic_poison => unreachable,
1031 .inferred_alloc_const => unreachable,
1032 .inferred_alloc_mut => unreachable,
10331024 },
10341025 .struct_type => |struct_type| {
10351026 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse
......@@ -1488,8 +1479,6 @@ pub const Type = struct {
14881479 .type_info => unreachable,
14891480 .noreturn => unreachable,
14901481 .generic_poison => unreachable,
1491 .inferred_alloc_const => unreachable,
1492 .inferred_alloc_mut => unreachable,
14931482 },
14941483 .struct_type => |struct_type| switch (ty.containerLayout(mod)) {
14951484 .Packed => {
......@@ -1732,8 +1721,6 @@ pub const Type = struct {
17321721 .undefined => unreachable,
17331722 .enum_literal => unreachable,
17341723 .generic_poison => unreachable,
1735 .inferred_alloc_const => unreachable,
1736 .inferred_alloc_mut => unreachable,
17371724
17381725 .atomic_order => unreachable, // missing call to resolveTypeFields
17391726 .atomic_rmw_op => unreachable, // missing call to resolveTypeFields
......@@ -1833,12 +1820,9 @@ pub const Type = struct {
18331820 }
18341821
18351822 pub fn isSinglePointer(ty: Type, mod: *const Module) bool {
1836 return switch (ty.ip_index) {
1837 .inferred_alloc_const_type, .inferred_alloc_mut_type => true,
1838 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1839 .ptr_type => |ptr_info| ptr_info.size == .One,
1840 else => false,
1841 },
1823 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1824 .ptr_type => |ptr_info| ptr_info.size == .One,
1825 else => false,
18421826 };
18431827 }
18441828
......@@ -1849,12 +1833,9 @@ pub const Type = struct {
18491833
18501834 /// Returns `null` if `ty` is not a pointer.
18511835 pub fn ptrSizeOrNull(ty: Type, mod: *const Module) ?std.builtin.Type.Pointer.Size {
1852 return switch (ty.ip_index) {
1853 .inferred_alloc_const_type, .inferred_alloc_mut_type => .One,
1854 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1855 .ptr_type => |ptr_info| ptr_info.size,
1856 else => null,
1857 },
1836 return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1837 .ptr_type => |ptr_info| ptr_info.size,
1838 else => null,
18581839 };
18591840 }
18601841
......@@ -2612,8 +2593,6 @@ pub const Type = struct {
26122593 .undefined => return Value.undef,
26132594
26142595 .generic_poison => unreachable,
2615 .inferred_alloc_const => unreachable,
2616 .inferred_alloc_mut => unreachable,
26172596 },
26182597 .struct_type => |struct_type| {
26192598 if (mod.structPtrUnwrap(struct_type.index)) |s| {
......@@ -2799,9 +2778,6 @@ pub const Type = struct {
27992778 .enum_literal,
28002779 .type_info,
28012780 => true,
2802
2803 .inferred_alloc_const => unreachable,
2804 .inferred_alloc_mut => unreachable,
28052781 },
28062782 .struct_type => |struct_type| {
28072783 // A struct with no fields is not comptime-only.
src/value.zig-47
......@@ -63,12 +63,6 @@ pub const Value = struct {
6363 aggregate,
6464 /// An instance of a union.
6565 @"union",
66 /// This is a special value that tracks a set of types that have been stored
67 /// to an inferred allocation. It does not support any of the normal value queries.
68 inferred_alloc,
69 /// Used to coordinate alloc_inferred, store_to_inferred_ptr, and resolve_inferred_alloc
70 /// instructions for comptime code.
71 inferred_alloc_comptime,
7266
7367 pub const no_payload_count = 0;
7468
......@@ -82,8 +76,6 @@ pub const Value = struct {
8276 .bytes => Payload.Bytes,
8377 .aggregate => Payload.Aggregate,
8478 .@"union" => Payload.Union,
85 .inferred_alloc => Payload.InferredAlloc,
86 .inferred_alloc_comptime => Payload.InferredAllocComptime,
8779 };
8880 }
8981
......@@ -250,8 +242,6 @@ pub const Value = struct {
250242 .legacy = .{ .ptr_otherwise = &new_payload.base },
251243 };
252244 },
253 .inferred_alloc => unreachable,
254 .inferred_alloc_comptime => unreachable,
255245 }
256246 }
257247
......@@ -308,8 +298,6 @@ pub const Value = struct {
308298 val = val.castTag(.repeated).?.data;
309299 },
310300 .slice => return out_stream.writeAll("(slice)"),
311 .inferred_alloc => return out_stream.writeAll("(inferred allocation value)"),
312 .inferred_alloc_comptime => return out_stream.writeAll("(inferred comptime allocation value)"),
313301 };
314302 }
315303
......@@ -4147,41 +4135,6 @@ pub const Value = struct {
41474135 val: Value,
41484136 };
41494137 };
4150
4151 pub const InferredAlloc = struct {
4152 pub const base_tag = Tag.inferred_alloc;
4153
4154 base: Payload = .{ .tag = base_tag },
4155 data: struct {
4156 /// The value stored in the inferred allocation. This will go into
4157 /// peer type resolution. This is stored in a separate list so that
4158 /// the items are contiguous in memory and thus can be passed to
4159 /// `Module.resolvePeerTypes`.
4160 prongs: std.MultiArrayList(struct {
4161 /// The dummy instruction used as a peer to resolve the type.
4162 /// Although this has a redundant type with placeholder, this is
4163 /// needed in addition because it may be a constant value, which
4164 /// affects peer type resolution.
4165 stored_inst: Air.Inst.Ref,
4166 /// The bitcast instruction used as a placeholder when the
4167 /// new result pointer type is not yet known.
4168 placeholder: Air.Inst.Index,
4169 }) = .{},
4170 /// 0 means ABI-aligned.
4171 alignment: u32,
4172 },
4173 };
4174
4175 pub const InferredAllocComptime = struct {
4176 pub const base_tag = Tag.inferred_alloc_comptime;
4177
4178 base: Payload = .{ .tag = base_tag },
4179 data: struct {
4180 decl_index: Module.Decl.Index,
4181 /// 0 means ABI-aligned.
4182 alignment: u32,
4183 },
4184 };
41854138 };
41864139
41874140 pub const BigIntSpace = InternPool.Key.Int.Storage.BigIntSpace;