aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-05-25 22:28:02 -0700
committerAndrew Kelley <andrew@ziglang.org>2023-06-10 20:47:55 -0700
commitf37c0a459382fa033cefc9bb139277436a78b25e (patch)
tree6860bcc6f0d95190cb68fb43fc7da6d593322b1c /src/Sema.zig
parent5d0d5893fd39047e4fdbb6623e4d69babf0b2ed4 (diff)
downloadzig-f37c0a459382fa033cefc9bb139277436a78b25e.tar.gz
zig-f37c0a459382fa033cefc9bb139277436a78b25e.zip
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.
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig288
1 files changed, 128 insertions, 160 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 6927a4bde9..5395bb63d1 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -89,7 +89,9 @@ is_generic_instantiation: bool = false,
/// function types will emit generic poison instead of a partial type.
no_partial_func_ty: bool = false,
-unresolved_inferred_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, void) = .{},
+/// The temporary arena is used for the memory of the `InferredAlloc` values
+/// here so the values can be dropped without any cleanup.
+unresolved_inferred_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, InferredAlloc) = .{},
const std = @import("std");
const math = std.math;
@@ -718,7 +720,7 @@ pub const Block = struct {
}
/// `alignment` value of 0 means to use ABI alignment.
- pub fn finish(wad: *WipAnonDecl, ty: Type, val: Value, alignment: u32) !Decl.Index {
+ pub fn finish(wad: *WipAnonDecl, ty: Type, val: Value, alignment: u64) !Decl.Index {
const sema = wad.block.sema;
// Do this ahead of time because `createAnonymousDecl` depends on calling
// `type.hasRuntimeBits()`.
@@ -728,7 +730,8 @@ pub const Block = struct {
.val = val,
});
const new_decl = sema.mod.declPtr(new_decl_index);
- new_decl.@"align" = alignment;
+ // TODO: migrate Decl alignment to use `InternPool.Alignment`
+ new_decl.@"align" = @intCast(u32, alignment);
errdefer sema.mod.abortAnonDecl(new_decl_index);
try new_decl.finalizeNewArena(&wad.new_decl_arena);
wad.finished = true;
@@ -748,6 +751,23 @@ const LabeledBlock = struct {
}
};
+/// The value stored in the inferred allocation. This will go into
+/// peer type resolution. This is stored in a separate list so that
+/// the items are contiguous in memory and thus can be passed to
+/// `Module.resolvePeerTypes`.
+const InferredAlloc = struct {
+ prongs: std.MultiArrayList(struct {
+ /// The dummy instruction used as a peer to resolve the type.
+ /// Although this has a redundant type with placeholder, this is
+ /// needed in addition because it may be a constant value, which
+ /// affects peer type resolution.
+ stored_inst: Air.Inst.Ref,
+ /// The bitcast instruction used as a placeholder when the
+ /// new result pointer type is not yet known.
+ placeholder: Air.Inst.Index,
+ }) = .{},
+};
+
pub fn deinit(sema: *Sema) void {
const gpa = sema.gpa;
sema.air_instructions.deinit(gpa);
@@ -909,10 +929,10 @@ fn analyzeBodyInner(
const air_inst: Air.Inst.Ref = switch (tags[inst]) {
// zig fmt: off
.alloc => try sema.zirAlloc(block, inst),
- .alloc_inferred => try sema.zirAllocInferred(block, inst, .{ .ip_index = .inferred_alloc_const_type }),
- .alloc_inferred_mut => try sema.zirAllocInferred(block, inst, .{ .ip_index = .inferred_alloc_mut_type }),
- .alloc_inferred_comptime => try sema.zirAllocInferredComptime(inst, .{ .ip_index = .inferred_alloc_const_type }),
- .alloc_inferred_comptime_mut => try sema.zirAllocInferredComptime(inst, .{ .ip_index = .inferred_alloc_mut_type }),
+ .alloc_inferred => try sema.zirAllocInferred(block, inst, true),
+ .alloc_inferred_mut => try sema.zirAllocInferred(block, inst, false),
+ .alloc_inferred_comptime => try sema.zirAllocInferredComptime(inst, true),
+ .alloc_inferred_comptime_mut => try sema.zirAllocInferredComptime(inst, false),
.alloc_mut => try sema.zirAllocMut(block, inst),
.alloc_comptime_mut => try sema.zirAllocComptime(block, inst),
.make_ptr_const => try sema.zirMakePtrConst(block, inst),
@@ -1707,7 +1727,7 @@ fn analyzeBodyInner(
break :blk Air.Inst.Ref.void_value;
},
};
- if (sema.typeOf(air_inst).isNoReturn(mod))
+ if (sema.isNoReturn(air_inst))
break always_noreturn;
map.putAssumeCapacity(inst, air_inst);
i += 1;
@@ -1751,8 +1771,6 @@ pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
// The last section of indexes refers to the map of ZIR => AIR.
const inst = sema.inst_map.get(i - InternPool.static_len).?;
if (inst == .generic_poison) return error.GenericPoison;
- const ty = sema.typeOf(inst);
- assert(!ty.isGenericPoison());
return inst;
}
@@ -2431,20 +2449,20 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
const tracy = trace(@src());
defer tracy.end();
+ const mod = sema.mod;
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
const pointee_ty = try sema.resolveType(block, src, extra.lhs);
const ptr = try sema.resolveInst(extra.rhs);
- const target = sema.mod.getTarget();
+ const target = mod.getTarget();
const addr_space = target_util.defaultAddressSpace(target, .local);
if (Air.refToIndex(ptr)) |ptr_inst| {
switch (sema.air_instructions.items(.tag)[ptr_inst]) {
.inferred_alloc => {
- const air_datas = sema.air_instructions.items(.data);
- const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload];
- const inferred_alloc = &ptr_val.castTag(.inferred_alloc).?.data;
+ const ia1 = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc;
+ const ia2 = sema.unresolved_inferred_allocs.getPtr(ptr_inst).?;
// Add the stored instruction to the set we will use to resolve peer types
// for the inferred allocation.
// 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
defer trash_block.instructions.deinit(sema.gpa);
const operand = try trash_block.addBitCast(pointee_ty, .void_value);
- const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
- .pointee_type = pointee_ty,
- .@"align" = inferred_alloc.alignment,
- .@"addrspace" = addr_space,
+ const ptr_ty = try mod.ptrType(.{
+ .elem_type = pointee_ty.toIntern(),
+ .alignment = ia1.alignment,
+ .address_space = addr_space,
});
const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr);
- try inferred_alloc.prongs.append(sema.arena, .{
+ try ia2.prongs.append(sema.arena, .{
.stored_inst = operand,
.placeholder = Air.refToIndex(bitcasted_ptr).?,
});
@@ -2468,31 +2486,30 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
return bitcasted_ptr;
},
.inferred_alloc_comptime => {
- const air_datas = sema.air_instructions.items(.data);
- const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload];
- const iac = ptr_val.castTag(.inferred_alloc_comptime).?;
+ const alignment = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime.alignment;
// There will be only one coerce_result_ptr because we are running at comptime.
// The alloc will turn into a Decl.
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
- iac.data.decl_index = try anon_decl.finish(
+ const decl_index = try anon_decl.finish(
pointee_ty,
Value.undef,
- iac.data.alignment,
+ alignment.toByteUnits(0),
);
- if (iac.data.alignment != 0) {
+ sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime.decl_index = decl_index;
+ if (alignment != .none) {
try sema.resolveTypeLayout(pointee_ty);
}
- const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
- .pointee_type = pointee_ty,
- .@"align" = iac.data.alignment,
- .@"addrspace" = addr_space,
+ const ptr_ty = try mod.ptrType(.{
+ .elem_type = pointee_ty.toIntern(),
+ .alignment = alignment,
+ .address_space = addr_space,
});
- try sema.maybeQueueFuncBodyAnalysis(iac.data.decl_index);
- return sema.addConstant(ptr_ty, (try sema.mod.intern(.{ .ptr = .{
+ try sema.maybeQueueFuncBodyAnalysis(decl_index);
+ return sema.addConstant(ptr_ty, (try mod.intern(.{ .ptr = .{
.ty = ptr_ty.toIntern(),
.addr = .{ .mut_decl = .{
- .decl = iac.data.decl_index,
+ .decl = decl_index,
.runtime_index = block.runtime_index,
} },
} })).toValue());
@@ -3479,25 +3496,16 @@ fn zirAllocExtended(
break :blk alignment;
} else 0;
- const inferred_alloc_ty = if (small.is_const)
- Type{ .ip_index = .inferred_alloc_const_type }
- else
- Type{ .ip_index = .inferred_alloc_mut_type };
-
if (block.is_comptime or small.is_comptime) {
if (small.has_type) {
return sema.analyzeComptimeAlloc(block, var_ty, alignment);
} else {
- const ty_inst = try sema.addType(inferred_alloc_ty);
- try sema.air_values.append(gpa, try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{
- .decl_index = undefined,
- .alignment = alignment,
- }));
try sema.air_instructions.append(gpa, .{
.tag = .inferred_alloc_comptime,
- .data = .{ .ty_pl = .{
- .ty = ty_inst,
- .payload = @intCast(u32, sema.air_values.items.len - 1),
+ .data = .{ .inferred_alloc_comptime = .{
+ .decl_index = undefined,
+ .alignment = InternPool.Alignment.fromByteUnits(alignment),
+ .is_const = small.is_const,
} },
});
return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));
@@ -3518,18 +3526,14 @@ fn zirAllocExtended(
return block.addTy(.alloc, ptr_type);
}
- const ty_inst = try sema.addType(inferred_alloc_ty);
- try sema.air_values.append(gpa, try Value.Tag.inferred_alloc.create(sema.arena, .{
- .alignment = alignment,
- }));
const result_index = try block.addInstAsIndex(.{
.tag = .inferred_alloc,
- .data = .{ .ty_pl = .{
- .ty = ty_inst,
- .payload = @intCast(u32, sema.air_values.items.len - 1),
+ .data = .{ .inferred_alloc = .{
+ .alignment = InternPool.Alignment.fromByteUnits(alignment),
+ .is_const = small.is_const,
} },
});
- try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, {});
+ try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, .{});
return Air.indexToRef(result_index);
}
@@ -3623,23 +3627,19 @@ fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Ai
fn zirAllocInferredComptime(
sema: *Sema,
inst: Zir.Inst.Index,
- inferred_alloc_ty: Type,
+ is_const: bool,
) CompileError!Air.Inst.Ref {
const gpa = sema.gpa;
const src_node = sema.code.instructions.items(.data)[inst].node;
const src = LazySrcLoc.nodeOffset(src_node);
sema.src = src;
- const ty_inst = try sema.addType(inferred_alloc_ty);
- try sema.air_values.append(gpa, try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{
- .decl_index = undefined,
- .alignment = 0,
- }));
try sema.air_instructions.append(gpa, .{
.tag = .inferred_alloc_comptime,
- .data = .{ .ty_pl = .{
- .ty = ty_inst,
- .payload = @intCast(u32, sema.air_values.items.len - 1),
+ .data = .{ .inferred_alloc_comptime = .{
+ .decl_index = undefined,
+ .alignment = .none,
+ .is_const = is_const,
} },
});
return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));
@@ -3688,7 +3688,7 @@ fn zirAllocInferred(
sema: *Sema,
block: *Block,
inst: Zir.Inst.Index,
- inferred_alloc_ty: Type,
+ is_const: bool,
) CompileError!Air.Inst.Ref {
const tracy = trace(@src());
defer tracy.end();
@@ -3698,33 +3698,26 @@ fn zirAllocInferred(
const src = LazySrcLoc.nodeOffset(src_node);
sema.src = src;
- const ty_inst = try sema.addType(inferred_alloc_ty);
if (block.is_comptime) {
- try sema.air_values.append(gpa, try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{
- .decl_index = undefined,
- .alignment = 0,
- }));
try sema.air_instructions.append(gpa, .{
.tag = .inferred_alloc_comptime,
- .data = .{ .ty_pl = .{
- .ty = ty_inst,
- .payload = @intCast(u32, sema.air_values.items.len - 1),
+ .data = .{ .inferred_alloc_comptime = .{
+ .decl_index = undefined,
+ .alignment = .none,
+ .is_const = is_const,
} },
});
return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));
}
- try sema.air_values.append(gpa, try Value.Tag.inferred_alloc.create(sema.arena, .{
- .alignment = 0,
- }));
const result_index = try block.addInstAsIndex(.{
.tag = .inferred_alloc,
- .data = .{ .ty_pl = .{
- .ty = ty_inst,
- .payload = @intCast(u32, sema.air_values.items.len - 1),
+ .data = .{ .inferred_alloc = .{
+ .alignment = .none,
+ .is_const = is_const,
} },
});
- try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, {});
+ try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, .{});
return Air.indexToRef(result_index);
}
@@ -3732,44 +3725,36 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
const tracy = trace(@src());
defer tracy.end();
+ const mod = sema.mod;
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node };
const ptr = try sema.resolveInst(inst_data.operand);
const ptr_inst = Air.refToIndex(ptr).?;
- const value_index = sema.air_instructions.items(.data)[ptr_inst].ty_pl.payload;
- const ptr_val = sema.air_values.items[value_index];
- const var_is_mut = switch (sema.typeOf(ptr).toIntern()) {
- .inferred_alloc_const_type => false,
- .inferred_alloc_mut_type => true,
- else => unreachable,
- };
- const target = sema.mod.getTarget();
+ const target = mod.getTarget();
switch (sema.air_instructions.items(.tag)[ptr_inst]) {
.inferred_alloc_comptime => {
- const iac = ptr_val.castTag(.inferred_alloc_comptime).?;
- const decl_index = iac.data.decl_index;
- try sema.mod.declareDeclDependency(sema.owner_decl_index, decl_index);
+ const iac = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime;
+ const decl_index = iac.decl_index;
+ try mod.declareDeclDependency(sema.owner_decl_index, decl_index);
- const decl = sema.mod.declPtr(decl_index);
+ const decl = mod.declPtr(decl_index);
const final_elem_ty = decl.ty;
- const final_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
- .pointee_type = final_elem_ty,
- .mutable = true,
- .@"align" = iac.data.alignment,
- .@"addrspace" = target_util.defaultAddressSpace(target, .local),
+ const final_ptr_ty = try mod.ptrType(.{
+ .elem_type = final_elem_ty.toIntern(),
+ .is_const = false,
+ .alignment = iac.alignment,
+ .address_space = target_util.defaultAddressSpace(target, .local),
});
- const final_ptr_ty_inst = try sema.addType(final_ptr_ty);
- sema.air_instructions.items(.data)[ptr_inst].ty_pl.ty = final_ptr_ty_inst;
try sema.maybeQueueFuncBodyAnalysis(decl_index);
// Change it to an interned.
sema.air_instructions.set(ptr_inst, .{
.tag = .interned,
- .data = .{ .interned = try sema.mod.intern(.{ .ptr = .{
+ .data = .{ .interned = try mod.intern(.{ .ptr = .{
.ty = final_ptr_ty.toIntern(),
- .addr = if (var_is_mut) .{ .mut_decl = .{
+ .addr = if (!iac.is_const) .{ .mut_decl = .{
.decl = decl_index,
.runtime_index = block.runtime_index,
} } else .{ .decl = decl_index },
@@ -3777,19 +3762,18 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
});
},
.inferred_alloc => {
- assert(sema.unresolved_inferred_allocs.remove(ptr_inst));
- const inferred_alloc = ptr_val.castTag(.inferred_alloc).?;
- const peer_inst_list = inferred_alloc.data.prongs.items(.stored_inst);
+ const ia1 = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc;
+ const ia2 = sema.unresolved_inferred_allocs.fetchRemove(ptr_inst).?.value;
+ const peer_inst_list = ia2.prongs.items(.stored_inst);
const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list, .none);
- const final_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
- .pointee_type = final_elem_ty,
- .mutable = true,
- .@"align" = inferred_alloc.data.alignment,
- .@"addrspace" = target_util.defaultAddressSpace(target, .local),
+ const final_ptr_ty = try mod.ptrType(.{
+ .elem_type = final_elem_ty.toIntern(),
+ .alignment = ia1.alignment,
+ .address_space = target_util.defaultAddressSpace(target, .local),
});
- if (var_is_mut) {
+ if (!ia1.is_const) {
try sema.validateVarType(block, ty_src, final_elem_ty, false);
} else ct: {
// 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
const new_decl_index = try anon_decl.finish(
final_elem_ty,
try store_val.copy(anon_decl.arena()),
- inferred_alloc.data.alignment,
+ ia1.alignment.toByteUnits(0),
);
break :d new_decl_index;
};
- try sema.mod.declareDeclDependency(sema.owner_decl_index, new_decl_index);
+ try mod.declareDeclDependency(sema.owner_decl_index, new_decl_index);
// Even though we reuse the constant instruction, we still remove it from the
// block so that codegen does not see it.
block.instructions.shrinkRetainingCapacity(search_index);
try sema.maybeQueueFuncBodyAnalysis(new_decl_index);
- sema.air_values.items[value_index] = (try sema.mod.intern(.{ .ptr = .{
- .ty = final_elem_ty.toIntern(),
- .addr = .{ .decl = new_decl_index },
- } })).toValue();
- // if bitcast ty ref needs to be made const, make_ptr_const
- // ZIR handles it later, so we can just use the ty ref here.
- air_datas[ptr_inst].ty_pl.ty = air_datas[bitcast_inst].ty_op.ty;
+ sema.air_instructions.set(ptr_inst, .{
+ .tag = .interned,
+ .data = .{ .interned = try mod.intern(.{ .ptr = .{
+ .ty = final_elem_ty.toIntern(),
+ .addr = .{ .decl = new_decl_index },
+ } }) },
+ });
// Unless the block is comptime, `alloc_inferred` always produces
// 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
// Now we need to go back over all the coerce_result_ptr instructions, which
// previously inserted a bitcast as a placeholder, and do the logic as if
// the new result ptr type was available.
- const placeholders = inferred_alloc.data.prongs.items(.placeholder);
+ const placeholders = ia2.prongs.items(.placeholder);
const gpa = sema.gpa;
var trash_block = block.makeSubBlock();
trash_block.is_comptime = false;
defer trash_block.instructions.deinit(gpa);
- const mut_final_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
- .pointee_type = final_elem_ty,
- .mutable = true,
- .@"align" = inferred_alloc.data.alignment,
- .@"addrspace" = target_util.defaultAddressSpace(target, .local),
+ const mut_final_ptr_ty = try mod.ptrType(.{
+ .elem_type = final_elem_ty.toIntern(),
+ .alignment = ia1.alignment,
+ .address_space = target_util.defaultAddressSpace(target, .local),
});
const dummy_ptr = try trash_block.addTy(.alloc, mut_final_ptr_ty);
const empty_trash_count = trash_block.instructions.items.len;
@@ -3914,7 +3897,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
for (peer_inst_list, placeholders) |peer_inst, placeholder_inst| {
const sub_ptr_ty = sema.typeOf(Air.indexToRef(placeholder_inst));
- if (mut_final_ptr_ty.eql(sub_ptr_ty, sema.mod)) {
+ if (mut_final_ptr_ty.eql(sub_ptr_ty, mod)) {
// New result location type is the same as the old one; nothing
// to do here.
continue;
@@ -5009,17 +4992,14 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
const src: LazySrcLoc = sema.src;
blk: {
const ptr_inst = Air.refToIndex(ptr) orelse break :blk;
- const air_data = sema.air_instructions.items(.data)[ptr_inst];
switch (sema.air_instructions.items(.tag)[ptr_inst]) {
.inferred_alloc_comptime => {
- const ptr_val = sema.air_values.items[air_data.ty_pl.payload];
- const iac = ptr_val.castTag(.inferred_alloc_comptime).?;
+ const iac = &sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime;
return sema.storeToInferredAllocComptime(block, src, operand, iac);
},
.inferred_alloc => {
- const ptr_val = sema.air_values.items[air_data.ty_pl.payload];
- const inferred_alloc = ptr_val.castTag(.inferred_alloc).?;
- return sema.storeToInferredAlloc(block, ptr, operand, inferred_alloc);
+ const ia = sema.unresolved_inferred_allocs.getPtr(ptr_inst).?;
+ return sema.storeToInferredAlloc(block, ptr, operand, ia);
},
else => break :blk,
}
@@ -5038,16 +5018,15 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi
const operand = try sema.resolveInst(bin_inst.rhs);
const ptr_inst = Air.refToIndex(ptr).?;
const air_datas = sema.air_instructions.items(.data);
- const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload];
switch (sema.air_instructions.items(.tag)[ptr_inst]) {
.inferred_alloc_comptime => {
- const iac = ptr_val.castTag(.inferred_alloc_comptime).?;
+ const iac = &air_datas[ptr_inst].inferred_alloc_comptime;
return sema.storeToInferredAllocComptime(block, src, operand, iac);
},
.inferred_alloc => {
- const inferred_alloc = ptr_val.castTag(.inferred_alloc).?;
- return sema.storeToInferredAlloc(block, ptr, operand, inferred_alloc);
+ const ia = sema.unresolved_inferred_allocs.getPtr(ptr_inst).?;
+ return sema.storeToInferredAlloc(block, ptr, operand, ia);
},
else => unreachable,
}
@@ -5058,14 +5037,14 @@ fn storeToInferredAlloc(
block: *Block,
ptr: Air.Inst.Ref,
operand: Air.Inst.Ref,
- inferred_alloc: *Value.Payload.InferredAlloc,
+ inferred_alloc: *InferredAlloc,
) CompileError!void {
// Create a store instruction as a placeholder. This will be replaced by a
// proper store sequence once we know the stored type.
const dummy_store = try block.addBinOp(.store, ptr, operand);
// Add the stored instruction to the set we will use to resolve peer types
// for the inferred allocation.
- try inferred_alloc.data.prongs.append(sema.arena, .{
+ try inferred_alloc.prongs.append(sema.arena, .{
.stored_inst = operand,
.placeholder = Air.refToIndex(dummy_store).?,
});
@@ -5076,7 +5055,7 @@ fn storeToInferredAllocComptime(
block: *Block,
src: LazySrcLoc,
operand: Air.Inst.Ref,
- iac: *Value.Payload.InferredAllocComptime,
+ iac: *Air.Inst.Data.InferredAllocComptime,
) CompileError!void {
const operand_ty = sema.typeOf(operand);
// There will be only one store_to_inferred_ptr because we are running at comptime.
@@ -5085,10 +5064,10 @@ fn storeToInferredAllocComptime(
if (operand_val.getVariable(sema.mod) != null) break :store;
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
- iac.data.decl_index = try anon_decl.finish(
+ iac.decl_index = try anon_decl.finish(
operand_ty,
try operand_val.copy(anon_decl.arena()),
- iac.data.alignment,
+ iac.alignment.toByteUnits(0),
);
return;
}
@@ -27643,17 +27622,6 @@ fn obtainBitCastedVectorPtr(sema: *Sema, ptr: Air.Inst.Ref) ?Air.Inst.Ref {
const prev_ptr = air_datas[ptr_inst].ty_op.operand;
const prev_ptr_ty = sema.typeOf(prev_ptr);
if (prev_ptr_ty.zigTypeTag(mod) != .Pointer) return null;
-
- // TODO: I noticed that the behavior tests do not pass if these two
- // checks are missing. I don't understand why the presence of inferred
- // allocations is relevant to this function, or why it would have
- // different behavior depending on whether the types were inferred.
- // Something seems wrong here.
- switch (prev_ptr_ty.toIntern()) {
- .inferred_alloc_mut_type, .inferred_alloc_const_type => return null,
- else => {},
- }
-
const prev_ptr_child_ty = prev_ptr_ty.childType(mod);
if (prev_ptr_child_ty.zigTypeTag(mod) == .Vector) break prev_ptr;
ptr_inst = Air.refToIndex(prev_ptr) orelse return null;
@@ -31749,9 +31717,6 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
.enum_literal,
.type_info,
=> true,
-
- .inferred_alloc_const => unreachable,
- .inferred_alloc_mut => unreachable,
},
.struct_type => |struct_type| {
const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
@@ -32009,8 +31974,6 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
.bool_false => unreachable,
.empty_struct => unreachable,
.generic_poison => unreachable,
- .inferred_alloc_const_type => unreachable,
- .inferred_alloc_mut_type => unreachable,
.type_info_type => return sema.getBuiltinType("Type"),
.extern_options_type => return sema.getBuiltinType("ExternOptions"),
@@ -33201,8 +33164,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
.undefined => Value.undef,
.generic_poison => return error.GenericPoison,
- .inferred_alloc_const => unreachable,
- .inferred_alloc_mut => unreachable,
},
.struct_type => |struct_type| {
const resolved_ty = try sema.resolveTypeFields(ty);
@@ -33737,9 +33698,6 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
.enum_literal,
.type_info,
=> true,
-
- .inferred_alloc_const => unreachable,
- .inferred_alloc_mut => unreachable,
},
.struct_type => |struct_type| {
const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
@@ -34501,3 +34459,13 @@ fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type {
return mod.errorSetFromUnsortedNames(names.keys());
}
+
+/// Avoids crashing the compiler when asking if inferred allocations are noreturn.
+fn isNoReturn(sema: *Sema, ref: Air.Inst.Ref) bool {
+ if (ref == .noreturn_type) return true;
+ if (Air.refToIndex(ref)) |inst| switch (sema.air_instructions.items(.tag)[inst]) {
+ .inferred_alloc, .inferred_alloc_comptime => return false,
+ else => {},
+ };
+ return sema.typeOf(ref).isNoReturn(sema.mod);
+}