authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-23 18:45:51-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-23 18:45:51-07:00
log7378ce67dabf996f2d0927138f826dfb3d6fa05f
tree8db3025dfa20a9120c62b7c56796e75cbcecec3d
parent57539a26b4b1a118c9947116f2873ea3c0ced3da

Sema: introduce a type resolution queue

That happens after a function body is analyzed. This prevents circular dependency compile errors and yet a way to mark types that need to be fully resolved before a given function is sent to the codegen backend.

5 files changed, 82 insertions(+), 44 deletions(-)

src/Air.zig+1-1
......@@ -1072,7 +1072,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
10721072 .sub_with_overflow,
10731073 .mul_with_overflow,
10741074 .shl_with_overflow,
1075 => return Type.initTag(.bool),
1075 => return Type.bool,
10761076 }
10771077}
10781078
src/Module.zig+17
......@@ -4837,6 +4837,9 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn, arena: Allocator) Sem
48374837
48384838 // Finally we must resolve the return type and parameter types so that backends
48394839 // have full access to type information.
4840 // Crucially, this happens *after* we set the function state to success above,
4841 // so that dependencies on the function body will now be satisfied rather than
4842 // result in circular dependency errors.
48404843 const src: LazySrcLoc = .{ .node_offset = 0 };
48414844 sema.resolveFnTypes(&inner_block, src, fn_ty_info) catch |err| switch (err) {
48424845 error.NeededSourceLocation => unreachable,
......@@ -4847,6 +4850,20 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn, arena: Allocator) Sem
48474850 else => |e| return e,
48484851 };
48494852
4853 // Similarly, resolve any queued up types that were requested to be resolved for
4854 // the backends.
4855 for (sema.types_to_resolve.items) |inst_ref| {
4856 const ty = sema.getTmpAir().getRefType(inst_ref);
4857 sema.resolveTypeFully(&inner_block, src, ty) catch |err| switch (err) {
4858 error.NeededSourceLocation => unreachable,
4859 error.GenericPoison => unreachable,
4860 error.ComptimeReturn => unreachable,
4861 error.ComptimeBreak => unreachable,
4862 error.AnalysisFail => {},
4863 else => |e| return e,
4864 };
4865 }
4866
48504867 return Air{
48514868 .instructions = sema.air_instructions.toOwnedSlice(),
48524869 .extra = sema.air_extra.toOwnedSlice(gpa),
src/Sema.zig+25-10
......@@ -63,6 +63,11 @@ comptime_args_fn_inst: Zir.Inst.Index = 0,
6363/// extra hash table lookup in the `monomorphed_funcs` set.
6464/// Sema will set this to null when it takes ownership.
6565preallocated_new_func: ?*Module.Fn = null,
66/// The key is `constant` AIR instructions to types that must be fully resolved
67/// after the current function body analysis is done.
68/// TODO: after upgrading to use InternPool change the key here to be an
69/// InternPool value index.
70types_to_resolve: std.ArrayListUnmanaged(Air.Inst.Ref) = .{},
6671
6772const std = @import("std");
6873const mem = std.mem;
......@@ -527,6 +532,7 @@ pub fn deinit(sema: *Sema) void {
527532 sema.air_values.deinit(gpa);
528533 sema.inst_map.deinit(gpa);
529534 sema.decl_val_table.deinit(gpa);
535 sema.types_to_resolve.deinit(gpa);
530536 sema.* = undefined;
531537}
532538
......@@ -1747,7 +1753,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
17471753 return sema.bitCast(block, ptr_ty, new_ptr, src);
17481754 }
17491755 const ty_op = air_datas[trash_inst].ty_op;
1750 const operand_ty = sema.getTmpAir().typeOf(ty_op.operand);
1756 const operand_ty = sema.typeOf(ty_op.operand);
17511757 const ptr_operand_ty = try Type.ptr(sema.arena, target, .{
17521758 .pointee_type = operand_ty,
17531759 .@"addrspace" = addr_space,
......@@ -2592,7 +2598,7 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
25922598 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
25932599 });
25942600 try sema.requireRuntimeBlock(block, var_decl_src);
2595 try sema.resolveTypeFully(block, ty_src, var_ty);
2601 try sema.queueFullTypeResolution(var_ty);
25962602 return block.addTy(.alloc, ptr_type);
25972603}
25982604
......@@ -2614,7 +2620,7 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
26142620 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
26152621 });
26162622 try sema.requireRuntimeBlock(block, var_decl_src);
2617 try sema.resolveTypeFully(block, ty_src, var_ty);
2623 try sema.queueFullTypeResolution(var_ty);
26182624 return block.addTy(.alloc, ptr_type);
26192625}
26202626
......@@ -2770,7 +2776,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
27702776 }
27712777
27722778 try sema.requireRuntimeBlock(block, src);
2773 try sema.resolveTypeFully(block, ty_src, final_elem_ty);
2779 try sema.queueFullTypeResolution(final_elem_ty);
27742780
27752781 // Change it to a normal alloc.
27762782 sema.air_instructions.set(ptr_inst, .{
......@@ -4363,6 +4369,8 @@ fn addDbgVar(
43634369 else => unreachable,
43644370 }
43654371
4372 try sema.queueFullTypeResolution(operand_ty);
4373
43664374 // Add the name to the AIR.
43674375 const name_extra_index = @intCast(u32, sema.air_extra.items.len);
43684376 const elements_used = name.len / 4 + 1;
......@@ -5004,7 +5012,7 @@ fn analyzeCall(
50045012 }
50055013 }
50065014
5007 try sema.resolveTypeFully(block, call_src, func_ty_info.return_type);
5015 try sema.queueFullTypeResolution(func_ty_info.return_type);
50085016
50095017 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len +
50105018 args.len);
......@@ -5344,7 +5352,7 @@ fn instantiateGenericCall(
53445352 total_i += 1;
53455353 }
53465354
5347 try sema.resolveTypeFully(block, call_src, new_fn_info.return_type);
5355 try sema.queueFullTypeResolution(new_fn_info.return_type);
53485356 }
53495357 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len +
53505358 runtime_args_len);
......@@ -12030,7 +12038,8 @@ fn unionInit(
1203012038 }
1203112039
1203212040 try sema.requireRuntimeBlock(block, init_src);
12033 try sema.resolveTypeLayout(block, union_ty_src, union_ty);
12041 _ = union_ty_src;
12042 try sema.queueFullTypeResolution(union_ty);
1203412043 return block.addUnionInit(union_ty, field_index, init);
1203512044}
1203612045
......@@ -12205,6 +12214,7 @@ fn finishStructInit(
1220512214 }
1220612215
1220712216 try sema.requireRuntimeBlock(block, src);
12217 try sema.queueFullTypeResolution(struct_ty);
1220812218 return block.addAggregateInit(struct_ty, field_inits);
1220912219}
1221012220
......@@ -12351,7 +12361,7 @@ fn zirArrayInit(
1235112361 };
1235212362
1235312363 try sema.requireRuntimeBlock(block, runtime_src);
12354 try sema.resolveTypeLayout(block, src, elem_ty);
12364 try sema.queueFullTypeResolution(elem_ty);
1235512365
1235612366 if (is_ref) {
1235712367 const target = sema.mod.getTarget();
......@@ -18339,7 +18349,7 @@ fn storePtr2(
1833918349 // TODO handle if the element type requires comptime
1834018350
1834118351 try sema.requireRuntimeBlock(block, runtime_src);
18342 try sema.resolveTypeLayout(block, src, elem_ty);
18352 try sema.queueFullTypeResolution(elem_ty);
1834318353 _ = try block.addBinOp(air_tag, ptr, operand);
1834418354}
1834518355
......@@ -21907,7 +21917,7 @@ fn typeOf(sema: *Sema, inst: Air.Inst.Ref) Type {
2190721917 return sema.getTmpAir().typeOf(inst);
2190821918}
2190921919
21910fn getTmpAir(sema: Sema) Air {
21920pub fn getTmpAir(sema: Sema) Air {
2191121921 return .{
2191221922 .instructions = sema.air_instructions.slice(),
2191321923 .extra = sema.air_extra.items,
......@@ -22572,3 +22582,8 @@ fn anonStructFieldIndex(
2257222582fn kit(sema: *Sema, block: *Block, src: LazySrcLoc) Module.WipAnalysis {
2257322583 return .{ .sema = sema, .block = block, .src = src };
2257422584}
22585
22586fn queueFullTypeResolution(sema: *Sema, ty: Type) !void {
22587 const inst_ref = try sema.addType(ty);
22588 try sema.types_to_resolve.append(sema.gpa, inst_ref);
22589}
src/arch/wasm/CodeGen.zig+33-33
......@@ -632,7 +632,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!WValue {
632632 // means we must generate it from a constant.
633633 const val = self.air.value(ref).?;
634634 const ty = self.air.typeOf(ref);
635 if (!ty.hasRuntimeBits() and !ty.isInt()) {
635 if (!ty.hasRuntimeBitsIgnoreComptime() and !ty.isInt()) {
636636 gop.value_ptr.* = WValue{ .none = {} };
637637 return gop.value_ptr.*;
638638 }
......@@ -805,13 +805,13 @@ fn genFunctype(gpa: Allocator, fn_ty: Type, target: std.Target) !wasm.Type {
805805 defer gpa.free(fn_params);
806806 fn_ty.fnParamTypes(fn_params);
807807 for (fn_params) |param_type| {
808 if (!param_type.hasRuntimeBits()) continue;
808 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;
809809 try params.append(typeToValtype(param_type, target));
810810 }
811811 }
812812
813813 // return type
814 if (!want_sret and return_type.hasRuntimeBits()) {
814 if (!want_sret and return_type.hasRuntimeBitsIgnoreComptime()) {
815815 try returns.append(typeToValtype(return_type, target));
816816 }
817817
......@@ -970,7 +970,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) InnerError!CallWValu
970970 .Naked => return result,
971971 .Unspecified, .C => {
972972 for (param_types) |ty| {
973 if (!ty.hasRuntimeBits()) {
973 if (!ty.hasRuntimeBitsIgnoreComptime()) {
974974 continue;
975975 }
976976
......@@ -1015,7 +1015,7 @@ fn restoreStackPointer(self: *Self) !void {
10151015///
10161016/// Asserts Type has codegenbits
10171017fn allocStack(self: *Self, ty: Type) !WValue {
1018 assert(ty.hasRuntimeBits());
1018 assert(ty.hasRuntimeBitsIgnoreComptime());
10191019 if (self.initial_stack_value == .none) {
10201020 try self.initializeStack();
10211021 }
......@@ -1049,7 +1049,7 @@ fn allocStackPtr(self: *Self, inst: Air.Inst.Index) !WValue {
10491049 try self.initializeStack();
10501050 }
10511051
1052 if (!pointee_ty.hasRuntimeBits()) {
1052 if (!pointee_ty.hasRuntimeBitsIgnoreComptime()) {
10531053 return self.allocStack(Type.usize); // create a value containing just the stack pointer.
10541054 }
10551055
......@@ -1235,18 +1235,18 @@ fn isByRef(ty: Type, target: std.Target) bool {
12351235 .Struct,
12361236 .Frame,
12371237 .Union,
1238 => return ty.hasRuntimeBits(),
1238 => return ty.hasRuntimeBitsIgnoreComptime(),
12391239 .Int => return if (ty.intInfo(target).bits > 64) true else false,
12401240 .ErrorUnion => {
1241 const has_tag = ty.errorUnionSet().hasRuntimeBits();
1242 const has_pl = ty.errorUnionPayload().hasRuntimeBits();
1241 const has_tag = ty.errorUnionSet().hasRuntimeBitsIgnoreComptime();
1242 const has_pl = ty.errorUnionPayload().hasRuntimeBitsIgnoreComptime();
12431243 if (!has_tag or !has_pl) return false;
1244 return ty.hasRuntimeBits();
1244 return ty.hasRuntimeBitsIgnoreComptime();
12451245 },
12461246 .Optional => {
12471247 if (ty.isPtrLikeOptional()) return false;
12481248 var buf: Type.Payload.ElemType = undefined;
1249 return ty.optionalChild(&buf).hasRuntimeBits();
1249 return ty.optionalChild(&buf).hasRuntimeBitsIgnoreComptime();
12501250 },
12511251 .Pointer => {
12521252 // Slices act like struct and will be passed by reference
......@@ -1511,7 +1511,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
15111511 const un_op = self.air.instructions.items(.data)[inst].un_op;
15121512 const operand = try self.resolveInst(un_op);
15131513 const ret_ty = self.air.typeOf(un_op).childType();
1514 if (!ret_ty.hasRuntimeBits()) return WValue.none;
1514 if (!ret_ty.hasRuntimeBitsIgnoreComptime()) return WValue.none;
15151515
15161516 if (!isByRef(ret_ty, self.target)) {
15171517 const result = try self.load(operand, ret_ty, 0);
......@@ -1567,7 +1567,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
15671567 const arg_val = try self.resolveInst(arg_ref);
15681568
15691569 const arg_ty = self.air.typeOf(arg_ref);
1570 if (!arg_ty.hasRuntimeBits()) continue;
1570 if (!arg_ty.hasRuntimeBitsIgnoreComptime()) continue;
15711571
15721572 switch (arg_val) {
15731573 .stack_offset => try self.emitWValue(try self.buildPointerOffset(arg_val, 0, .new)),
......@@ -1591,7 +1591,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
15911591 try self.addLabel(.call_indirect, fn_type_index);
15921592 }
15931593
1594 if (self.liveness.isUnused(inst) or !ret_ty.hasRuntimeBits()) {
1594 if (self.liveness.isUnused(inst) or !ret_ty.hasRuntimeBitsIgnoreComptime()) {
15951595 return WValue.none;
15961596 } else if (ret_ty.isNoReturn()) {
15971597 try self.addTag(.@"unreachable");
......@@ -1625,7 +1625,7 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro
16251625 .ErrorUnion => {
16261626 const err_ty = ty.errorUnionSet();
16271627 const pl_ty = ty.errorUnionPayload();
1628 if (!pl_ty.hasRuntimeBits()) {
1628 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {
16291629 return self.store(lhs, rhs, err_ty, 0);
16301630 }
16311631
......@@ -1638,7 +1638,7 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro
16381638 }
16391639 var buf: Type.Payload.ElemType = undefined;
16401640 const pl_ty = ty.optionalChild(&buf);
1641 if (!pl_ty.hasRuntimeBits()) {
1641 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {
16421642 return self.store(lhs, rhs, Type.u8, 0);
16431643 }
16441644
......@@ -1696,7 +1696,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
16961696 const operand = try self.resolveInst(ty_op.operand);
16971697 const ty = self.air.getRefType(ty_op.ty);
16981698
1699 if (!ty.hasRuntimeBits()) return WValue{ .none = {} };
1699 if (!ty.hasRuntimeBitsIgnoreComptime()) return WValue{ .none = {} };
17001700
17011701 if (isByRef(ty, self.target)) {
17021702 const new_local = try self.allocStack(ty);
......@@ -2200,7 +2200,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: std.math.CompareOperator) Inner
22002200 if (operand_ty.zigTypeTag() == .Optional and !operand_ty.isPtrLikeOptional()) {
22012201 var buf: Type.Payload.ElemType = undefined;
22022202 const payload_ty = operand_ty.optionalChild(&buf);
2203 if (payload_ty.hasRuntimeBits()) {
2203 if (payload_ty.hasRuntimeBitsIgnoreComptime()) {
22042204 // When we hit this case, we must check the value of optionals
22052205 // that are not pointers. This means first checking against non-null for
22062206 // both lhs and rhs, as well as checking the payload are matching of lhs and rhs
......@@ -2257,7 +2257,7 @@ fn airBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
22572257 const block = self.blocks.get(br.block_inst).?;
22582258
22592259 // if operand has codegen bits we should break with a value
2260 if (self.air.typeOf(br.operand).hasRuntimeBits()) {
2260 if (self.air.typeOf(br.operand).hasRuntimeBitsIgnoreComptime()) {
22612261 const operand = try self.resolveInst(br.operand);
22622262 const op = switch (operand) {
22632263 .stack_offset => try self.buildPointerOffset(operand, 0, .new),
......@@ -2357,7 +2357,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
23572357 const operand = try self.resolveInst(struct_field.struct_operand);
23582358 const field_index = struct_field.field_index;
23592359 const field_ty = struct_ty.structFieldType(field_index);
2360 if (!field_ty.hasRuntimeBits()) return WValue{ .none = {} };
2360 if (!field_ty.hasRuntimeBitsIgnoreComptime()) return WValue{ .none = {} };
23612361 const offset = std.math.cast(u32, struct_ty.structFieldOffset(field_index, self.target)) catch {
23622362 return self.fail("Field type '{}' too big to fit into stack frame", .{field_ty.fmt(self.target)});
23632363 };
......@@ -2544,7 +2544,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!W
25442544
25452545 // load the error tag value
25462546 try self.emitWValue(operand);
2547 if (pl_ty.hasRuntimeBits()) {
2547 if (pl_ty.hasRuntimeBitsIgnoreComptime()) {
25482548 try self.addMemArg(.i32_load16_u, .{
25492549 .offset = operand.offset(),
25502550 .alignment = err_ty.errorUnionSet().abiAlignment(self.target),
......@@ -2567,7 +2567,7 @@ fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index, op_is_ptr: bool)
25672567 const op_ty = self.air.typeOf(ty_op.operand);
25682568 const err_ty = if (op_is_ptr) op_ty.childType() else op_ty;
25692569 const payload_ty = err_ty.errorUnionPayload();
2570 if (!payload_ty.hasRuntimeBits()) return WValue{ .none = {} };
2570 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return WValue{ .none = {} };
25712571 const err_align = err_ty.abiAlignment(self.target);
25722572 const set_size = err_ty.errorUnionSet().abiSize(self.target);
25732573 const offset = mem.alignForwardGeneric(u64, set_size, err_align);
......@@ -2585,7 +2585,7 @@ fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index, op_is_ptr: bool) In
25852585 const op_ty = self.air.typeOf(ty_op.operand);
25862586 const err_ty = if (op_is_ptr) op_ty.childType() else op_ty;
25872587 const payload_ty = err_ty.errorUnionPayload();
2588 if (op_is_ptr or !payload_ty.hasRuntimeBits()) {
2588 if (op_is_ptr or !payload_ty.hasRuntimeBitsIgnoreComptime()) {
25892589 return operand;
25902590 }
25912591
......@@ -2599,7 +2599,7 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
25992599 const operand = try self.resolveInst(ty_op.operand);
26002600
26012601 const op_ty = self.air.typeOf(ty_op.operand);
2602 if (!op_ty.hasRuntimeBits()) return operand;
2602 if (!op_ty.hasRuntimeBitsIgnoreComptime()) return operand;
26032603 const err_ty = self.air.getRefType(ty_op.ty);
26042604 const err_align = err_ty.abiAlignment(self.target);
26052605 const set_size = err_ty.errorUnionSet().abiSize(self.target);
......@@ -2624,7 +2624,7 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
26242624 const operand = try self.resolveInst(ty_op.operand);
26252625 const err_ty = self.air.getRefType(ty_op.ty);
26262626
2627 if (!err_ty.errorUnionPayload().hasRuntimeBits()) return operand;
2627 if (!err_ty.errorUnionPayload().hasRuntimeBitsIgnoreComptime()) return operand;
26282628
26292629 const err_union = try self.allocStack(err_ty);
26302630 try self.store(err_union, operand, err_ty.errorUnionSet(), 0);
......@@ -2690,7 +2690,7 @@ fn isNull(self: *Self, operand: WValue, optional_ty: Type, opcode: wasm.Opcode)
26902690 const payload_ty = optional_ty.optionalChild(&buf);
26912691 // When payload is zero-bits, we can treat operand as a value, rather than
26922692 // a pointer to the stack value
2693 if (payload_ty.hasRuntimeBits()) {
2693 if (payload_ty.hasRuntimeBitsIgnoreComptime()) {
26942694 try self.addMemArg(.i32_load8_u, .{ .offset = operand.offset(), .alignment = 1 });
26952695 }
26962696 }
......@@ -2710,7 +2710,7 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
27102710 const operand = try self.resolveInst(ty_op.operand);
27112711 const opt_ty = self.air.typeOf(ty_op.operand);
27122712 const payload_ty = self.air.typeOfIndex(inst);
2713 if (!payload_ty.hasRuntimeBits()) return WValue{ .none = {} };
2713 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return WValue{ .none = {} };
27142714 if (opt_ty.isPtrLikeOptional()) return operand;
27152715
27162716 const offset = opt_ty.abiSize(self.target) - payload_ty.abiSize(self.target);
......@@ -2731,7 +2731,7 @@ fn airOptionalPayloadPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
27312731
27322732 var buf: Type.Payload.ElemType = undefined;
27332733 const payload_ty = opt_ty.optionalChild(&buf);
2734 if (!payload_ty.hasRuntimeBits() or opt_ty.isPtrLikeOptional()) {
2734 if (!payload_ty.hasRuntimeBitsIgnoreComptime() or opt_ty.isPtrLikeOptional()) {
27352735 return operand;
27362736 }
27372737
......@@ -2745,7 +2745,7 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) InnerError!WValue
27452745 const opt_ty = self.air.typeOf(ty_op.operand).childType();
27462746 var buf: Type.Payload.ElemType = undefined;
27472747 const payload_ty = opt_ty.optionalChild(&buf);
2748 if (!payload_ty.hasRuntimeBits()) {
2748 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
27492749 return self.fail("TODO: Implement OptionalPayloadPtrSet for optional with zero-sized type {}", .{payload_ty.fmtDebug()});
27502750 }
27512751
......@@ -2769,7 +2769,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
27692769
27702770 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
27712771 const payload_ty = self.air.typeOf(ty_op.operand);
2772 if (!payload_ty.hasRuntimeBits()) {
2772 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
27732773 const non_null_bit = try self.allocStack(Type.initTag(.u1));
27742774 try self.emitWValue(non_null_bit);
27752775 try self.addImm32(1);
......@@ -2958,7 +2958,7 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
29582958 const slice_local = try self.allocStack(slice_ty);
29592959
29602960 // store the array ptr in the slice
2961 if (array_ty.hasRuntimeBits()) {
2961 if (array_ty.hasRuntimeBitsIgnoreComptime()) {
29622962 try self.store(slice_local, operand, Type.usize, 0);
29632963 }
29642964
......@@ -3408,7 +3408,7 @@ fn airWasmMemoryGrow(self: *Self, inst: Air.Inst.Index) !WValue {
34083408}
34093409
34103410fn cmpOptionals(self: *Self, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue {
3411 assert(operand_ty.hasRuntimeBits());
3411 assert(operand_ty.hasRuntimeBitsIgnoreComptime());
34123412 assert(op == .eq or op == .neq);
34133413 var buf: Type.Payload.ElemType = undefined;
34143414 const payload_ty = operand_ty.optionalChild(&buf);
......@@ -3575,7 +3575,7 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) InnerError!WValue
35753575
35763576 if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
35773577
3578 if (!payload_ty.hasRuntimeBits()) {
3578 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
35793579 return operand;
35803580 }
35813581
test/behavior/eval.zig+6
......@@ -853,3 +853,9 @@ test "comptime pointer load through elem_ptr" {
853853 assert(ptr[1].x == 2);
854854 }
855855}
856
857test "debug variable type resolved through indirect zero-bit types" {
858 const T = struct { key: []void };
859 const slice: []const T = &[_]T{};
860 _ = slice;
861}