authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-03-01 07:32:09+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-03-10 10:26:14+00:00
log4eb8360911d80d4891be6ed47792121a2ccde353
treeebb5a857cb872564a36e390372e142ec5eedbc8a
parentc64755fb2f3178b4f593ef9f2cb54beef03af36f
signaturelock-open Commit is signed but in an unrecognized format.

compiler: various lil' fixes


16 files changed, 312 insertions(+), 203 deletions(-)

lib/compiler/objcopy.zig+2-2
...@@ -388,8 +388,8 @@ const BinaryElfOutput = struct {...@@ -388,8 +388,8 @@ const BinaryElfOutput = struct {
388388
389 pub fn parse(allocator: Allocator, in: *File.Reader, elf_hdr: elf.Header) !Self {389 pub fn parse(allocator: Allocator, in: *File.Reader, elf_hdr: elf.Header) !Self {
390 var self: Self = .{390 var self: Self = .{
391 .segments = .{},391 .segments = .empty,
392 .sections = .{},392 .sections = .empty,
393 .allocator = allocator,393 .allocator = allocator,
394 .shstrtab = null,394 .shstrtab = null,
395 };395 };
lib/std/pdb.zig+2-2
...@@ -332,7 +332,7 @@ pub const ProcSym = extern struct {...@@ -332,7 +332,7 @@ pub const ProcSym = extern struct {
332 name: [1]u8, // null-terminated332 name: [1]u8, // null-terminated
333};333};
334334
335pub const ProcSymFlags = packed struct {335pub const ProcSymFlags = packed struct(u8) {
336 has_fp: bool,336 has_fp: bool,
337 has_iret: bool,337 has_iret: bool,
338 has_fret: bool,338 has_fret: bool,
...@@ -373,7 +373,7 @@ pub const LineFragmentHeader = extern struct {...@@ -373,7 +373,7 @@ pub const LineFragmentHeader = extern struct {
373 code_size: u32,373 code_size: u32,
374};374};
375375
376pub const LineFlags = packed struct {376pub const LineFlags = packed struct(u16) {
377 /// CV_LINES_HAVE_COLUMNS377 /// CV_LINES_HAVE_COLUMNS
378 have_columns: bool,378 have_columns: bool,
379 unused: u15,379 unused: u15,
lib/std/zig/AstGen.zig+5
...@@ -5513,6 +5513,11 @@ fn containerDecl(...@@ -5513,6 +5513,11 @@ fn containerDecl(
5513 if (next_field_idx != fields_len) {5513 if (next_field_idx != fields_len) {
5514 return astgen.failNode(member_node, "'_' field of non-exhaustive enum must be last", .{});5514 return astgen.failNode(member_node, "'_' field of non-exhaustive enum must be last", .{});
5515 }5515 }
5516 if (tag_type_body_len == null) {
5517 return astgen.failNodeNotes(node, "non-exhaustive enum missing integer tag type", .{}, &.{
5518 try astgen.errNoteNode(member_node, "marked non-exhaustive here", .{}),
5519 });
5520 }
5516 opt_nonexhaustive_node = member_node.toOptional();5521 opt_nonexhaustive_node = member_node.toOptional();
5517 continue;5522 continue;
5518 }5523 }
src/Compilation.zig+2-1
...@@ -4180,7 +4180,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {...@@ -4180,7 +4180,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {
4180 if (!refs.contains(logging_unit)) continue;4180 if (!refs.contains(logging_unit)) continue;
4181 try messages.append(gpa, .{4181 try messages.append(gpa, .{
4182 .src_loc = compile_log.src(),4182 .src_loc = compile_log.src(),
4183 .msg = undefined, // populated later4183 .msg = "", // populated later, but must be valid for `sort` call below
4184 .notes = &.{},4184 .notes = &.{},
4185 // We actually clear this later for most of these, but we populate4185 // We actually clear this later for most of these, but we populate
4186 // this field for now to avoid having to allocate more data to track4186 // this field for now to avoid having to allocate more data to track
...@@ -4221,6 +4221,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {...@@ -4221,6 +4221,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle {
42214221
4222 break :compile_log_text try log_text.toOwnedSlice(gpa);4222 break :compile_log_text try log_text.toOwnedSlice(gpa);
4223 };4223 };
4224 defer gpa.free(compile_log_text);
42244225
4225 // TODO: eventually, this should be behind `std.debug.runtime_safety`. But right now, this is a4226 // TODO: eventually, this should be behind `std.debug.runtime_safety`. But right now, this is a
4226 // very common way for incremental compilation bugs to manifest, so let's always check it.4227 // very common way for incremental compilation bugs to manifest, so let's always check it.
src/Sema.zig+90-101
...@@ -416,7 +416,7 @@ pub const Block = struct {...@@ -416,7 +416,7 @@ pub const Block = struct {
416 return block.comptime_reason != null;416 return block.comptime_reason != null;
417 }417 }
418418
419 fn builtinCallArgSrc(block: *Block, builtin_call_node: std.zig.Ast.Node.Offset, arg_index: u32) LazySrcLoc {419 pub fn builtinCallArgSrc(block: *Block, builtin_call_node: std.zig.Ast.Node.Offset, arg_index: u32) LazySrcLoc {
420 return block.src(.{ .node_offset_builtin_call_arg = .{420 return block.src(.{ .node_offset_builtin_call_arg = .{
421 .builtin_call_node = builtin_call_node,421 .builtin_call_node = builtin_call_node,
422 .arg_index = arg_index,422 .arg_index = arg_index,
...@@ -4654,47 +4654,14 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -4654,47 +4654,14 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
4654 .slice => return sema.fail(block, src, "index syntax required for slice type '{f}'", .{operand_ty.fmt(pt)}),4654 .slice => return sema.fail(block, src, "index syntax required for slice type '{f}'", .{operand_ty.fmt(pt)}),
4655 }4655 }
46564656
4657 const elem_ty = operand_ty.childType(zcu);
4658 try sema.ensureLayoutResolved(elem_ty, src, .ptr_access);
4659
4660 const need_comptime = switch (elem_ty.classify(zcu)) {
4661 .no_possible_value => return sema.fail(block, src, "cannot load {s} type '{f}'", .{
4662 if (elem_ty.zigTypeTag(zcu) == .@"opaque") "opaque" else "uninstantiable",
4663 elem_ty.fmt(pt),
4664 }),
4665 .one_possible_value => return, // no need to validate the actual pointer value!
4666 .runtime => false,
4667 .partially_comptime, .fully_comptime => true,
4668 };
4669
4670 if (sema.resolveValue(operand)) |val| {4657 if (sema.resolveValue(operand)) |val| {
4671 if (val.isUndef(zcu)) {4658 // Error for deref of undef pointer, unless the pointee is OPV in which case it's legal.
4659 if (val.isUndef(zcu) and operand_ty.childType(zcu).classify(zcu) != .one_possible_value) {
4672 return sema.fail(block, src, "cannot dereference undefined value", .{});4660 return sema.fail(block, src, "cannot dereference undefined value", .{});
4673 }4661 }
4674 } else if (need_comptime) {
4675 const msg = msg: {
4676 const msg = try sema.errMsg(
4677 src,
4678 "values of type '{f}' must be comptime-known, but operand value is runtime-known",
4679 .{elem_ty.fmt(pt)},
4680 );
4681 errdefer msg.destroy(sema.gpa);
4682
4683 try sema.explainWhyTypeIsComptime(msg, src, elem_ty);
4684 break :msg msg;
4685 };
4686 return sema.failWithOwnedErrorMsg(block, msg);
4687 }4662 }
4688}4663}
46894664
4690fn typeIsDestructurable(ty: Type, zcu: *const Zcu) bool {
4691 return switch (ty.zigTypeTag(zcu)) {
4692 .array, .vector => true,
4693 .@"struct" => ty.isTuple(zcu),
4694 else => false,
4695 };
4696}
4697
4698fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {4665fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
4699 const pt = sema.pt;4666 const pt = sema.pt;
4700 const zcu = pt.zcu;4667 const zcu = pt.zcu;
...@@ -4705,14 +4672,14 @@ fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp...@@ -4705,14 +4672,14 @@ fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
4705 const operand = sema.resolveInst(extra.operand);4672 const operand = sema.resolveInst(extra.operand);
4706 const operand_ty = sema.typeOf(operand);4673 const operand_ty = sema.typeOf(operand);
47074674
4708 if (!typeIsDestructurable(operand_ty, zcu)) {4675 if (!operand_ty.destructurable(zcu)) {
4709 return sema.failWithOwnedErrorMsg(block, msg: {4676 return sema.failWithOwnedErrorMsg(block, msg: {
4710 const msg = try sema.errMsg(src, "type '{f}' cannot be destructured", .{operand_ty.fmt(pt)});4677 const msg = try sema.errMsg(src, "type '{f}' cannot be destructured", .{operand_ty.fmt(pt)});
4711 errdefer msg.destroy(sema.gpa);4678 errdefer msg.destroy(sema.gpa);
4712 try sema.errNote(destructure_src, msg, "result destructured here", .{});4679 try sema.errNote(destructure_src, msg, "result destructured here", .{});
4713 if (operand_ty.zigTypeTag(pt.zcu) == .error_union) {4680 if (operand_ty.zigTypeTag(pt.zcu) == .error_union) {
4714 const base_op_ty = operand_ty.errorUnionPayload(zcu);4681 const base_op_ty = operand_ty.errorUnionPayload(zcu);
4715 if (typeIsDestructurable(base_op_ty, zcu))4682 if (base_op_ty.destructurable(zcu))
4716 try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{});4683 try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{});
4717 }4684 }
4718 break :msg msg;4685 break :msg msg;
...@@ -8247,8 +8214,15 @@ fn zirOptionalPayload(...@@ -8247,8 +8214,15 @@ fn zirOptionalPayload(
8247 else => return sema.failWithExpectedOptionalType(block, src, operand_ty),8214 else => return sema.failWithExpectedOptionalType(block, src, operand_ty),
8248 };8215 };
82498216
8250 if (try sema.resolveDefinedValue(block, src, operand)) |val| {8217 ct: {
8251 if (val.optionalValue(zcu)) |payload| return Air.internedToRef(payload.toIntern());8218 if (try sema.resolveDefinedValue(block, src, operand)) |val| {
8219 if (val.optionalValue(zcu)) |payload| return .fromValue(payload); // comptime-known payload
8220 } else if (try sema.resolveIsNullFromType(block, src, operand_ty)) |is_null| {
8221 if (!is_null) break :ct; // fully runtime-known
8222 } else {
8223 break :ct; // fully runtime-known
8224 }
8225 // Comptime-known to be `null`.
8252 if (block.isComptime()) return sema.fail(block, src, "unable to unwrap null", .{});8226 if (block.isComptime()) return sema.fail(block, src, "unable to unwrap null", .{});
8253 if (safety_check and block.wantSafety()) {8227 if (safety_check and block.wantSafety()) {
8254 try sema.safetyPanic(block, src, .unwrap_null);8228 try sema.safetyPanic(block, src, .unwrap_null);
...@@ -21085,7 +21059,8 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData...@@ -21085,7 +21059,8 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
21085 continue :check ip.funcIesResolvedUnordered(func_index);21059 continue :check ip.funcIesResolvedUnordered(func_index);
21086 },21060 },
21087 .error_set_type => |dest| {21061 .error_set_type => |dest| {
21088 if (operand_err_ty.isAnyError(zcu)) break :check .superset;21062 if (dest.names.len == 0) break :check .disjoint; // dest is 'error{}'
21063 if (operand_err_ty.isAnyError(zcu)) break :check .overlap; // anyerror -> error{...} (non-empty)
21089 var dest_has_all = true;21064 var dest_has_all = true;
21090 var dest_has_any = false;21065 var dest_has_any = false;
21091 for (operand_err_ty.errorSetNames(zcu).get(ip)) |operand_err_name| {21066 for (operand_err_ty.errorSetNames(zcu).get(ip)) |operand_err_name| {
...@@ -24741,15 +24716,30 @@ fn zirBuiltinExtern(...@@ -24741,15 +24716,30 @@ fn zirBuiltinExtern(
24741 const ty_src = block.builtinCallArgSrc(extra.node, 0);24716 const ty_src = block.builtinCallArgSrc(extra.node, 0);
24742 const options_src = block.builtinCallArgSrc(extra.node, 1);24717 const options_src = block.builtinCallArgSrc(extra.node, 1);
2474324718
24744 var ty = try sema.resolveType(block, ty_src, extra.lhs);24719 const ptr_ty = try sema.resolveType(block, ty_src, extra.lhs);
24745 if (!ty.isPtrAtRuntime(zcu)) {24720 if (!ptr_ty.isPtrAtRuntime(zcu)) {
24746 return sema.fail(block, ty_src, "expected (optional) pointer", .{});24721 return sema.fail(block, ty_src, "expected (optional) pointer", .{});
24747 }24722 }
24748 if (!ty.validateExtern(.other, zcu)) {24723
24724 const ptr_info = ptr_ty.ptrInfo(zcu);
24725
24726 const elem_ty: Type = .fromInterned(ptr_info.child);
24727 try sema.ensureLayoutResolved(elem_ty, src, .@"extern");
24728
24729 if (!elem_ty.validateExtern(.other, zcu)) {
24749 return sema.failWithOwnedErrorMsg(block, msg: {24730 return sema.failWithOwnedErrorMsg(block, msg: {
24750 const msg = try sema.errMsg(ty_src, "extern symbol cannot have type '{f}'", .{ty.fmt(pt)});24731 const msg = try sema.errMsg(ty_src, "extern symbol cannot have type '{f}'", .{ptr_ty.fmt(pt)});
24751 errdefer msg.destroy(sema.gpa);24732 errdefer msg.destroy(sema.gpa);
24752 try sema.explainWhyTypeIsNotExtern(msg, ty_src, ty, .other);24733 try sema.errNote(ty_src, msg, "pointer element type '{f}' is not extern compatible", .{elem_ty.fmt(pt)});
24734 try sema.explainWhyTypeIsNotExtern(msg, ty_src, elem_ty, .other);
24735 break :msg msg;
24736 });
24737 }
24738 if (elem_ty.zigTypeTag(zcu) == .@"fn" and !ptr_info.flags.is_const) {
24739 return sema.failWithOwnedErrorMsg(block, msg: {
24740 const msg = try sema.errMsg(ty_src, "extern symbol cannot have type '{f}'", .{ptr_ty.fmt(pt)});
24741 errdefer msg.destroy(sema.gpa);
24742 try sema.errNote(ty_src, msg, "pointer to extern function must be 'const'", .{});
24753 break :msg msg;24743 break :msg msg;
24754 });24744 });
24755 }24745 }
...@@ -24769,14 +24759,9 @@ fn zirBuiltinExtern(...@@ -24769,14 +24759,9 @@ fn zirBuiltinExtern(
2476924759
24770 // TODO: error for threadlocal functions, non-const functions, etc24760 // TODO: error for threadlocal functions, non-const functions, etc
2477124761
24772 if (options.linkage == .weak and !ty.ptrAllowsZero(zcu)) {
24773 ty = try pt.optionalType(ty.toIntern());
24774 }
24775 const ptr_info = ty.ptrInfo(zcu);
24776
24777 const extern_val = try pt.getExtern(.{24762 const extern_val = try pt.getExtern(.{
24778 .name = options.name,24763 .name = options.name,
24779 .ty = ptr_info.child,24764 .ty = elem_ty.toIntern(),
24780 .lib_name = options.library_name,24765 .lib_name = options.library_name,
24781 .linkage = options.linkage,24766 .linkage = options.linkage,
24782 .visibility = options.visibility,24767 .visibility = options.visibility,
...@@ -24807,13 +24792,17 @@ fn zirBuiltinExtern(...@@ -24807,13 +24792,17 @@ fn zirBuiltinExtern(
24807 .source = .builtin,24792 .source = .builtin,
24808 });24793 });
2480924794
24795 // For a weak symbol where the given type is not nullable, make the pointer optional.
24796 const result_ptr_ty: Type = if (options.linkage == .weak and !ptr_ty.ptrAllowsZero(zcu)) ty: {
24797 break :ty try pt.optionalType(ptr_ty.toIntern());
24798 } else ptr_ty;
24799
24810 const uncasted_ptr = try sema.analyzeNavRef(block, src, ip.indexToKey(extern_val).@"extern".owner_nav);24800 const uncasted_ptr = try sema.analyzeNavRef(block, src, ip.indexToKey(extern_val).@"extern".owner_nav);
24811 // We want to cast to `ty`, but that isn't necessarily an allowed coercion.
24812 if (sema.resolveValue(uncasted_ptr)) |uncasted_ptr_val| {24801 if (sema.resolveValue(uncasted_ptr)) |uncasted_ptr_val| {
24813 const casted_ptr_val = try pt.getCoerced(uncasted_ptr_val, ty);24802 const casted_ptr_val = try pt.getCoerced(uncasted_ptr_val, result_ptr_ty);
24814 return Air.internedToRef(casted_ptr_val.toIntern());24803 return Air.internedToRef(casted_ptr_val.toIntern());
24815 } else {24804 } else {
24816 return block.addBitCast(ty, uncasted_ptr);24805 return block.addBitCast(result_ptr_ty, uncasted_ptr);
24817 }24806 }
24818}24807}
2481924808
...@@ -25258,6 +25247,7 @@ pub fn explainWhyTypeIsUnpackable(...@@ -25258,6 +25247,7 @@ pub fn explainWhyTypeIsUnpackable(
25258 try sema.errNote(src, msg, "non-packed unions do not have a bit-packed representation", .{});25247 try sema.errNote(src, msg, "non-packed unions do not have a bit-packed representation", .{});
25259 try sema.addDeclaredHereNote(msg, union_ty);25248 try sema.addDeclaredHereNote(msg, union_ty);
25260 },25249 },
25250 .slice => try sema.errNote(src, msg, "slices do not have a bit-packed representation", .{}),
25261 .other => try sema.errNote(src, msg, "type does not have a bit-packed representation", .{}),25251 .other => try sema.errNote(src, msg, "type does not have a bit-packed representation", .{}),
25262 }25252 }
25263}25253}
...@@ -25501,7 +25491,10 @@ fn addSafetyCheckSentinelMismatch(...@@ -25501,7 +25491,10 @@ fn addSafetyCheckSentinelMismatch(
25501 };25491 };
25502 assert(sema.typeOf(actual_sentinel).toIntern() == sentinel_ty.toIntern());25492 assert(sema.typeOf(actual_sentinel).toIntern() == sentinel_ty.toIntern());
25503 assert(sentinel_ty.isSelfComparable(zcu, true));25493 assert(sentinel_ty.isSelfComparable(zcu, true));
25504 const ok = try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel);25494 const ok: Air.Inst.Ref = if (sentinel_ty.zigTypeTag(zcu) == .vector) ok: {
25495 const elementwise = try parent_block.addCmpVector(expected_sentinel, actual_sentinel, .eq);
25496 break :ok try parent_block.addReduce(elementwise, .And);
25497 } else try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel);
2550525498
25506 return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.sentinelMismatch", &.{25499 return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.sentinelMismatch", &.{
25507 expected_sentinel, actual_sentinel,25500 expected_sentinel, actual_sentinel,
...@@ -26574,8 +26567,13 @@ fn unionFieldVal(...@@ -26574,8 +26567,13 @@ fn unionFieldVal(
26574 const active_tag_val = union_val.unionTag(zcu).?;26567 const active_tag_val = union_val.unionTag(zcu).?;
26575 const active_index = enum_tag_ty.enumTagFieldIndex(active_tag_val, zcu).?;26568 const active_index = enum_tag_ty.enumTagFieldIndex(active_tag_val, zcu).?;
26576 if (active_index == field_index) return .fromValue(union_val.unionPayload(zcu));26569 if (active_index == field_index) return .fromValue(union_val.unionPayload(zcu));
26577 return sema.fail(block, src, "access of union field '{f}' while field '{f}' is active", .{26570 return sema.failWithOwnedErrorMsg(block, msg: {
26578 field_name.fmt(ip), enum_tag_ty.enumFieldName(active_index, zcu).fmt(ip),26571 const msg = try sema.errMsg(src, "access of union field '{f}' while field '{f}' is active", .{
26572 field_name.fmt(ip), enum_tag_ty.enumFieldName(active_index, zcu).fmt(ip),
26573 });
26574 errdefer msg.destroy(zcu.comp.gpa);
26575 try sema.addDeclaredHereNote(msg, union_ty);
26576 break :msg msg;
26579 });26577 });
26580 },26578 },
26581 .@"extern" => if (try sema.bitCastVal(union_val, field_ty, 0, 0, 0)) |field_val| {26579 .@"extern" => if (try sema.bitCastVal(union_val, field_ty, 0, 0, 0)) |field_val| {
...@@ -26745,9 +26743,17 @@ fn elemVal(...@@ -26745,9 +26743,17 @@ fn elemVal(
26745 return sema.analyzeLoad(block, src, .fromValue(elem_ptr_val), indexable_src);26743 return sema.analyzeLoad(block, src, .fromValue(elem_ptr_val), indexable_src);
26746 }26744 }
2674726745
26748 if (try child_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);26746 try sema.validateRuntimeElemAccess(block, elem_index_src, child_ty, indexable_ty, src);
26747 switch (child_ty.classify(zcu)) {
26748 .runtime => {},
26749 .one_possible_value => return .fromValue((try child_ty.onePossibleValue(pt)).?),
26750 .no_possible_value => switch (child_ty.zigTypeTag(zcu)) {
26751 .@"opaque" => return sema.fail(block, src, "cannot load opaque type '{f}'", .{child_ty.fmt(pt)}),
26752 else => return sema.fail(block, src, "cannot load uninstantiable type '{f}'", .{child_ty.fmt(pt)}),
26753 },
26754 .partially_comptime, .fully_comptime => unreachable, // caught by `validateRuntimeElemAccess`
26755 }
2674926756
26750 try sema.checkLogicalPtrOperation(block, src, indexable_ty);
26751 return block.addBinOp(.ptr_elem_val, indexable, elem_index);26757 return block.addBinOp(.ptr_elem_val, indexable, elem_index);
26752 },26758 },
26753 .one => {26759 .one => {
...@@ -29082,31 +29088,6 @@ fn storePtr2(...@@ -29082,31 +29088,6 @@ fn storePtr2(
2908229088
29083 const elem_ty = ptr_ty.childType(zcu);29089 const elem_ty = ptr_ty.childType(zcu);
2908429090
29085 // To generate better code for tuples, we detect a tuple operand here, and
29086 // analyze field loads and stores directly. This avoids an extra allocation + memcpy
29087 // which would occur if we used `coerce`.
29088 // However, we avoid this mechanism if the destination element type is a tuple,
29089 // because the regular store will be better for this case.
29090 // If the destination type is a struct we don't want this mechanism to trigger, because
29091 // this code does not handle tuple-to-struct coercion which requires dealing with missing
29092 // fields.
29093 const operand_ty = sema.typeOf(uncasted_operand);
29094 if (operand_ty.isTuple(zcu) and elem_ty.zigTypeTag(zcu) == .array) {
29095 const field_count = operand_ty.structFieldCount(zcu);
29096 var i: u32 = 0;
29097 while (i < field_count) : (i += 1) {
29098 const elem_src = operand_src; // TODO better source location
29099 const elem = try sema.tupleField(block, operand_src, uncasted_operand, elem_src, i);
29100 const elem_index = try pt.intRef(.usize, i);
29101 const elem_ptr = try sema.elemPtr(block, ptr_src, ptr, elem_index, elem_src, false, true);
29102 try sema.storePtr2(block, src, elem_ptr, elem_src, elem, elem_src, .store);
29103 }
29104 return;
29105 }
29106
29107 // TODO do the same thing for anon structs as for tuples above.
29108 // However, beware of the need to handle missing/extra fields.
29109
29110 const is_ret = air_tag == .ret_ptr;29091 const is_ret = air_tag == .ret_ptr;
2911129092
29112 const operand = sema.coerceExtra(block, elem_ty, uncasted_operand, operand_src, .{ .is_ret = is_ret }) catch |err| switch (err) {29093 const operand = sema.coerceExtra(block, elem_ty, uncasted_operand, operand_src, .{ .is_ret = is_ret }) catch |err| switch (err) {
...@@ -29129,16 +29110,13 @@ fn storePtr2(...@@ -29129,16 +29110,13 @@ fn storePtr2(
29129 return sema.storePtrVal(block, src, ptr_val, operand_val, elem_ty);29110 return sema.storePtrVal(block, src, ptr_val, operand_val, elem_ty);
29130 };29111 };
2913129112
29132 // We're performing the store at runtime; as such, we need to make sure the pointee type29113 // We're performing the store at runtime, so the pointee type must not be comptime-only.
29133 // is not comptime-only. We can hit this case with a `@ptrFromInt` pointer.29114 if (comptime_only) return sema.failWithOwnedErrorMsg(block, msg: {
29134 if (comptime_only) {29115 const msg = try sema.errMsg(src, "cannot store comptime-only type '{f}' at runtime", .{elem_ty.fmt(pt)});
29135 return sema.failWithOwnedErrorMsg(block, msg: {29116 errdefer msg.destroy(sema.gpa);
29136 const msg = try sema.errMsg(src, "cannot store comptime-only type '{f}' at runtime", .{elem_ty.fmt(pt)});29117 try sema.errNote(ptr_src, msg, "operation is runtime due to this pointer", .{});
29137 errdefer msg.destroy(sema.gpa);29118 break :msg msg;
29138 try sema.errNote(ptr_src, msg, "operation is runtime due to this pointer", .{});29119 });
29139 break :msg msg;
29140 });
29141 }
2914229120
29143 try sema.requireRuntimeBlock(block, src, runtime_src);29121 try sema.requireRuntimeBlock(block, src, runtime_src);
2914429122
...@@ -29556,7 +29534,10 @@ fn coerceEnumToUnion(...@@ -29556,7 +29534,10 @@ fn coerceEnumToUnion(
29556 return sema.failWithOwnedErrorMsg(block, msg);29534 return sema.failWithOwnedErrorMsg(block, msg);
29557 }29535 }
2955829536
29559 if (union_ty.unionHasAllZeroBitFieldTypes(zcu)) {29537 for (union_obj.field_types.get(ip)) |field_ty_ip| {
29538 if (Type.fromInterned(field_ty_ip).classify(zcu) != .one_possible_value) break;
29539 } else {
29540 // All fields are OPV, so the coercion is okay.
29560 if (try union_ty.onePossibleValue(pt)) |opv| {29541 if (try union_ty.onePossibleValue(pt)) |opv| {
29561 // The tag had redundant bits, but we've omitted the tag from the union's runtime layout, so the union is OPV and hence runtime-known.29542 // The tag had redundant bits, but we've omitted the tag from the union's runtime layout, so the union is OPV and hence runtime-known.
29562 return .fromValue(opv);29543 return .fromValue(opv);
...@@ -29566,6 +29547,8 @@ fn coerceEnumToUnion(...@@ -29566,6 +29547,8 @@ fn coerceEnumToUnion(
29566 }29547 }
29567 }29548 }
2956829549
29550 // The coercion is invalid because one or more fields is not OPV.
29551
29569 const msg = msg: {29552 const msg = msg: {
29570 const msg = try sema.errMsg(29553 const msg = try sema.errMsg(
29571 inst_src,29554 inst_src,
...@@ -30186,12 +30169,18 @@ fn analyzeLoad(...@@ -30186,12 +30169,18 @@ fn analyzeLoad(
30186 .pointer => ptr_ty.childType(zcu),30169 .pointer => ptr_ty.childType(zcu),
30187 else => return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{ptr_ty.fmt(pt)}),30170 else => return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{ptr_ty.fmt(pt)}),
30188 };30171 };
30189 if (elem_ty.zigTypeTag(zcu) == .@"opaque") {
30190 return sema.fail(block, ptr_src, "cannot load opaque type '{f}'", .{elem_ty.fmt(pt)});
30191 }
3019230172
30193 try sema.ensureLayoutResolved(elem_ty, src, .ptr_access);30173 try sema.ensureLayoutResolved(elem_ty, src, .ptr_access);
30194 if (try elem_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);30174
30175 const comptime_only = switch (elem_ty.classify(zcu)) {
30176 .no_possible_value => switch (elem_ty.zigTypeTag(zcu)) {
30177 .@"opaque" => return sema.fail(block, src, "cannot load opaque type '{f}'", .{elem_ty.fmt(pt)}),
30178 else => return sema.fail(block, src, "cannot load uninstantiable type '{f}'", .{elem_ty.fmt(pt)}),
30179 },
30180 .one_possible_value => return .fromValue((try elem_ty.onePossibleValue(pt)).?),
30181 .runtime => false,
30182 .partially_comptime, .fully_comptime => true,
30183 };
3019530184
30196 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {30185 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {
30197 if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| {30186 if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| {
...@@ -30199,7 +30188,7 @@ fn analyzeLoad(...@@ -30199,7 +30188,7 @@ fn analyzeLoad(
30199 }30188 }
30200 }30189 }
3020130190
30202 if (elem_ty.comptimeOnly(zcu)) return sema.failWithOwnedErrorMsg(block, msg: {30191 if (comptime_only) return sema.failWithOwnedErrorMsg(block, msg: {
30203 const msg = try sema.errMsg(src, "cannot load comptime-only type '{f}'", .{elem_ty.fmt(pt)});30192 const msg = try sema.errMsg(src, "cannot load comptime-only type '{f}'", .{elem_ty.fmt(pt)});
30204 errdefer msg.destroy(zcu.gpa);30193 errdefer msg.destroy(zcu.gpa);
30205 try sema.errNote(ptr_src, msg, "pointer of type '{f}' is runtime-known", .{ptr_ty.fmt(pt)});30194 try sema.errNote(ptr_src, msg, "pointer of type '{f}' is runtime-known", .{ptr_ty.fmt(pt)});
src/Sema/arith.zig+3
...@@ -20,6 +20,9 @@ pub fn incrementDefinedInt(...@@ -20,6 +20,9 @@ pub fn incrementDefinedInt(
20 const zcu = pt.zcu;20 const zcu = pt.zcu;
21 assert(prev_val.typeOf(zcu).toIntern() == ty.toIntern());21 assert(prev_val.typeOf(zcu).toIntern() == ty.toIntern());
22 assert(!prev_val.isUndef(zcu));22 assert(!prev_val.isUndef(zcu));
23 if (ty.intInfo(zcu).bits == 0) {
24 return .{ .overflow = true, .val = try comptimeIntAdd(sema, prev_val, .one_comptime_int) };
25 }
23 const res = try intAdd(sema, prev_val, try pt.intValue(ty, 1), ty);26 const res = try intAdd(sema, prev_val, try pt.intValue(ty, 1), ty);
24 return .{ .overflow = res.overflow, .val = res.val };27 return .{ .overflow = res.overflow, .val = res.val };
25}28}
src/Sema/type_resolution.zig+30-16
...@@ -33,6 +33,7 @@ pub const LayoutResolveReason = enum {...@@ -33,6 +33,7 @@ pub const LayoutResolveReason = enum {
33 align_check,33 align_check,
34 bit_ptr_child,34 bit_ptr_child,
35 @"export",35 @"export",
36 @"extern",
36 builtin_type,37 builtin_type,
3738
38 /// Written after string: "while resolving type 'T' "39 /// Written after string: "while resolving type 'T' "
...@@ -58,6 +59,7 @@ pub const LayoutResolveReason = enum {...@@ -58,6 +59,7 @@ pub const LayoutResolveReason = enum {
58 .align_check => "for alignment check here",59 .align_check => "for alignment check here",
59 .bit_ptr_child => "for bit size check here",60 .bit_ptr_child => "for bit size check here",
60 .@"export" => "for export here",61 .@"export" => "for export here",
62 .@"extern" => "for extern declaration here",
61 .builtin_type => "from 'std.builtin'",63 .builtin_type => "from 'std.builtin'",
62 // zig fmt: on64 // zig fmt: on
63 };65 };
...@@ -198,7 +200,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {...@@ -198,7 +200,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
198 const name = struct_obj.field_names.get(ip)[field_index];200 const name = struct_obj.field_names.get(ip)[field_index];
199 if (ip.addFieldName(struct_obj.field_names, struct_obj.field_name_map, name)) |prev_field_index| {201 if (ip.addFieldName(struct_obj.field_names, struct_obj.field_name_map, name)) |prev_field_index| {
200 return sema.failWithOwnedErrorMsg(&block, msg: {202 return sema.failWithOwnedErrorMsg(&block, msg: {
201 const src = block.nodeOffset(.zero);203 const src = block.builtinCallArgSrc(.zero, 2);
202 const msg = try sema.errMsg(src, "duplicate struct field '{f}' at index '{d}", .{ name.fmt(ip), field_index });204 const msg = try sema.errMsg(src, "duplicate struct field '{f}' at index '{d}", .{ name.fmt(ip), field_index });
203 errdefer msg.destroy(gpa);205 errdefer msg.destroy(gpa);
204 try sema.errNote(src, msg, "previous field at index '{d}'", .{prev_field_index});206 try sema.errNote(src, msg, "previous field at index '{d}'", .{prev_field_index});
...@@ -494,20 +496,22 @@ fn resolvePackedStructLayout(...@@ -494,20 +496,22 @@ fn resolvePackedStructLayout(
494496
495 // Finally, either validate or infer the backing int type.497 // Finally, either validate or infer the backing int type.
496 const backing_int_ty: Type = if (explicit_backing_int_ty) |backing_ty| ty: {498 const backing_int_ty: Type = if (explicit_backing_int_ty) |backing_ty| ty: {
497 // We only need to validate the type.499 if (backing_ty.zigTypeTag(zcu) != .int) return sema.fail(
498 if (backing_ty.zigTypeTag(zcu) != .int) return sema.failWithOwnedErrorMsg(block, msg: {500 block,
499 const src = struct_ty.srcLoc(zcu);501 block.src(.container_arg),
500 const msg = try sema.errMsg(src, "expected backing integer type, found '{f}'", .{backing_ty.fmt(pt)});502 "expected backing integer type, found '{f}'",
501 errdefer msg.destroy(gpa);503 .{backing_ty.fmt(pt)},
502 try sema.errNote(src, msg, "backing integer '{f}' has bit width '{d}'", .{ backing_ty.fmt(pt), backing_ty.bitSize(zcu) });504 );
503 try sema.errNote(src, msg, "struct fields have total bit width '{d}'", .{field_bits});
504 break :msg msg;
505 });
506 if (field_bits != backing_ty.intInfo(zcu).bits) return sema.failWithOwnedErrorMsg(block, msg: {505 if (field_bits != backing_ty.intInfo(zcu).bits) return sema.failWithOwnedErrorMsg(block, msg: {
507 const src = struct_ty.srcLoc(zcu);506 const src = struct_ty.srcLoc(zcu);
508 const msg = try sema.errMsg(src, "backing integer bit width does not match total bit width of fields", .{});507 const msg = try sema.errMsg(src, "backing integer bit width does not match total bit width of fields", .{});
509 errdefer msg.destroy(gpa);508 errdefer msg.destroy(gpa);
510 try sema.errNote(src, msg, "backing integer '{f}' has bit width '{d}'", .{ backing_ty.fmt(pt), backing_ty.bitSize(zcu) });509 try sema.errNote(
510 block.src(.container_arg),
511 msg,
512 "backing integer '{f}' has bit width '{d}'",
513 .{ backing_ty.fmt(pt), backing_ty.bitSize(zcu) },
514 );
511 try sema.errNote(src, msg, "struct fields have total bit width '{d}'", .{field_bits});515 try sema.errNote(src, msg, "struct fields have total bit width '{d}'", .{field_bits});
512 break :msg msg;516 break :msg msg;
513 });517 });
...@@ -1033,7 +1037,6 @@ fn resolvePackedUnionLayout(...@@ -1033,7 +1037,6 @@ fn resolvePackedUnionLayout(
1033 const msg = try sema.errMsg(field_ty_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});1037 const msg = try sema.errMsg(field_ty_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
1034 errdefer msg.destroy(gpa);1038 errdefer msg.destroy(gpa);
1035 try sema.explainWhyTypeIsUnpackable(msg, field_ty_src, reason);1039 try sema.explainWhyTypeIsUnpackable(msg, field_ty_src, reason);
1036 try sema.addDeclaredHereNote(msg, field_ty);
1037 break :msg msg;1040 break :msg msg;
1038 });1041 });
1039 assert(!field_ty.comptimeOnly(zcu)); // packable types are not comptime-only1042 assert(!field_ty.comptimeOnly(zcu)); // packable types are not comptime-only
...@@ -1062,6 +1065,12 @@ fn resolvePackedUnionLayout(...@@ -1062,6 +1065,12 @@ fn resolvePackedUnionLayout(
10621065
1063 // Finally, either validate or infer the backing int type.1066 // Finally, either validate or infer the backing int type.
1064 const backing_int_ty: Type = if (explicit_backing_int_ty) |backing_ty| ty: {1067 const backing_int_ty: Type = if (explicit_backing_int_ty) |backing_ty| ty: {
1068 if (backing_ty.zigTypeTag(zcu) != .int) return sema.fail(
1069 block,
1070 block.src(.container_arg),
1071 "expected backing integer type, found '{f}'",
1072 .{backing_ty.fmt(pt)},
1073 );
1065 const backing_int_bits = backing_ty.intInfo(zcu).bits;1074 const backing_int_bits = backing_ty.intInfo(zcu).bits;
1066 for (union_obj.field_types.get(ip), 0..) |field_type_ip, field_idx| {1075 for (union_obj.field_types.get(ip), 0..) |field_type_ip, field_idx| {
1067 const field_type: Type = .fromInterned(field_type_ip);1076 const field_type: Type = .fromInterned(field_type_ip);
...@@ -1071,7 +1080,12 @@ fn resolvePackedUnionLayout(...@@ -1071,7 +1080,12 @@ fn resolvePackedUnionLayout(
1071 const msg = try sema.errMsg(field_ty_src, "field bit width does not match backing integer", .{});1080 const msg = try sema.errMsg(field_ty_src, "field bit width does not match backing integer", .{});
1072 errdefer msg.destroy(gpa);1081 errdefer msg.destroy(gpa);
1073 try sema.errNote(field_ty_src, msg, "field type '{f}' has bit width '{d}'", .{ field_type.fmt(pt), field_bits });1082 try sema.errNote(field_ty_src, msg, "field type '{f}' has bit width '{d}'", .{ field_type.fmt(pt), field_bits });
1074 try sema.errNote(field_ty_src, msg, "backing integer '{f}' has bit width '{d}'", .{ backing_ty.fmt(pt), backing_int_bits });1083 try sema.errNote(
1084 block.src(.container_arg),
1085 msg,
1086 "backing integer '{f}' has bit width '{d}'",
1087 .{ backing_ty.fmt(pt), backing_int_bits },
1088 );
1075 try sema.errNote(field_ty_src, msg, "all fields in a packed union must have the same bit width", .{});1089 try sema.errNote(field_ty_src, msg, "all fields in a packed union must have the same bit width", .{});
1076 break :msg msg;1090 break :msg msg;
1077 });1091 });
...@@ -1157,7 +1171,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void {...@@ -1157,7 +1171,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void {
1157 const name = enum_obj.field_names.get(ip)[field_index];1171 const name = enum_obj.field_names.get(ip)[field_index];
1158 if (ip.addFieldName(enum_obj.field_names, enum_obj.field_name_map, name)) |prev_field_index| {1172 if (ip.addFieldName(enum_obj.field_names, enum_obj.field_name_map, name)) |prev_field_index| {
1159 return sema.failWithOwnedErrorMsg(&block, msg: {1173 return sema.failWithOwnedErrorMsg(&block, msg: {
1160 const src = block.nodeOffset(.zero);1174 const src = block.builtinCallArgSrc(.zero, 2);
1161 const msg = try sema.errMsg(src, "duplicate union field '{f}' at index '{d}", .{ name.fmt(ip), field_index });1175 const msg = try sema.errMsg(src, "duplicate union field '{f}' at index '{d}", .{ name.fmt(ip), field_index });
1162 errdefer msg.destroy(gpa);1176 errdefer msg.destroy(gpa);
1163 try sema.errNote(src, msg, "previous field at index '{d}'", .{prev_field_index});1177 try sema.errNote(src, msg, "previous field at index '{d}'", .{prev_field_index});
...@@ -1183,8 +1197,8 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void {...@@ -1183,8 +1197,8 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void {
1183 const name = enum_obj.field_names.get(ip)[field_index];1197 const name = enum_obj.field_names.get(ip)[field_index];
1184 if (ip.addFieldName(enum_obj.field_names, enum_obj.field_name_map, name)) |prev_field_index| {1198 if (ip.addFieldName(enum_obj.field_names, enum_obj.field_name_map, name)) |prev_field_index| {
1185 return sema.failWithOwnedErrorMsg(&block, msg: {1199 return sema.failWithOwnedErrorMsg(&block, msg: {
1186 const src = block.nodeOffset(.zero);1200 const src = block.builtinCallArgSrc(.zero, 2);
1187 const msg = try sema.errMsg(src, "duplicate enum field '{f}' at index '{d}", .{ name.fmt(ip), field_index });1201 const msg = try sema.errMsg(src, "duplicate enum field '{f}' at index '{d}'", .{ name.fmt(ip), field_index });
1188 errdefer msg.destroy(gpa);1202 errdefer msg.destroy(gpa);
1189 try sema.errNote(src, msg, "previous field at index '{d}'", .{prev_field_index});1203 try sema.errNote(src, msg, "previous field at index '{d}'", .{prev_field_index});
1190 break :msg msg;1204 break :msg msg;
src/Type.zig+13-1
...@@ -2985,12 +2985,21 @@ pub fn containerTypeName(ty: Type, ip: *const InternPool) InternPool.NullTermina...@@ -2985,12 +2985,21 @@ pub fn containerTypeName(ty: Type, ip: *const InternPool) InternPool.NullTermina
2985 };2985 };
2986}2986}
29872987
2988pub fn destructurable(ty: Type, zcu: *const Zcu) bool {
2989 return switch (ty.zigTypeTag(zcu)) {
2990 .array, .vector => true,
2991 .@"struct" => ty.isTuple(zcu),
2992 else => false,
2993 };
2994}
2995
2988pub const UnpackableReason = union(enum) {2996pub const UnpackableReason = union(enum) {
2989 comptime_only,2997 comptime_only,
2990 pointer,2998 pointer,
2991 enum_inferred_int_tag: Type,2999 enum_inferred_int_tag: Type,
2992 non_packed_struct: Type,3000 non_packed_struct: Type,
2993 non_packed_union: Type,3001 non_packed_union: Type,
3002 slice,
2994 other,3003 other,
2995};3004};
29963005
...@@ -3027,7 +3036,10 @@ pub fn unpackable(ty: Type, zcu: *const Zcu) ?UnpackableReason {...@@ -3027,7 +3036,10 @@ pub fn unpackable(ty: Type, zcu: *const Zcu) ?UnpackableReason {
3027 else3036 else
3028 .other,3037 .other,
30293038
3030 .pointer => .pointer,3039 .pointer => switch (ty.ptrSize(zcu)) {
3040 .slice => .slice,
3041 .one, .many, .c => .pointer,
3042 },
30313043
3032 .@"enum" => switch (zcu.intern_pool.loadEnumType(ty.toIntern()).int_tag_mode) {3044 .@"enum" => switch (zcu.intern_pool.loadEnumType(ty.toIntern()).int_tag_mode) {
3033 .explicit => null,3045 .explicit => null,
src/Value.zig+11-3
...@@ -2014,7 +2014,11 @@ pub fn pointerDerivation(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread, op...@@ -2014,7 +2014,11 @@ pub fn pointerDerivation(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread, op
2014 },2014 },
2015 .field => |field| base: {2015 .field => |field| base: {
2016 const base_ptr = Value.fromInterned(field.base);2016 const base_ptr = Value.fromInterned(field.base);
2017 const base_ptr_ty = base_ptr.typeOf(zcu);2017 const base_ptr_ty = try pt.ptrType(info: {
2018 var info = base_ptr.typeOf(zcu).ptrInfo(zcu);
2019 info.flags.size = .one;
2020 break :info info;
2021 });
2018 const parent_step = try arena.create(PointerDeriveStep);2022 const parent_step = try arena.create(PointerDeriveStep);
2019 parent_step.* = try pointerDerivation(base_ptr, arena, pt, opt_sema);2023 parent_step.* = try pointerDerivation(base_ptr, arena, pt, opt_sema);
2020 break :base .{ .field_ptr = .{2024 break :base .{ .field_ptr = .{
...@@ -2155,13 +2159,17 @@ pub fn pointerDerivation(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread, op...@@ -2155,13 +2159,17 @@ pub fn pointerDerivation(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread, op
2155 const start_off = cur_ty.structFieldOffset(field_idx, zcu);2159 const start_off = cur_ty.structFieldOffset(field_idx, zcu);
2156 const end_off = start_off + field_ty.abiSize(zcu);2160 const end_off = start_off + field_ty.abiSize(zcu);
2157 if (cur_offset >= start_off and cur_offset + need_bytes <= end_off) {2161 if (cur_offset >= start_off and cur_offset + need_bytes <= end_off) {
2158 const old_ptr_ty = try cur_derive.ptrType(pt);2162 const base_ptr_ty = try pt.ptrType(info: {
2163 var info = (try cur_derive.ptrType(pt)).ptrInfo(zcu);
2164 info.flags.size = .one;
2165 break :info info;
2166 });
2159 const parent = try arena.create(PointerDeriveStep);2167 const parent = try arena.create(PointerDeriveStep);
2160 parent.* = cur_derive;2168 parent.* = cur_derive;
2161 cur_derive = .{ .field_ptr = .{2169 cur_derive = .{ .field_ptr = .{
2162 .parent = parent,2170 .parent = parent,
2163 .field_idx = @intCast(field_idx),2171 .field_idx = @intCast(field_idx),
2164 .result_ptr_ty = try old_ptr_ty.fieldPtrType(@intCast(field_idx), pt),2172 .result_ptr_ty = try base_ptr_ty.fieldPtrType(@intCast(field_idx), pt),
2165 } };2173 } };
2166 cur_offset -= start_off;2174 cur_offset -= start_off;
2167 break;2175 break;
src/Zcu.zig+40-4
...@@ -2028,9 +2028,15 @@ pub const SrcLoc = struct {...@@ -2028,9 +2028,15 @@ pub const SrcLoc = struct {
2028 const tree = try src_loc.file_scope.getTree(zcu);2028 const tree = try src_loc.file_scope.getTree(zcu);
2029 const node = src_loc.base_node;2029 const node = src_loc.base_node;
2030 var buf: [2]Ast.Node.Index = undefined;2030 var buf: [2]Ast.Node.Index = undefined;
2031 const container_decl = tree.fullContainerDecl(&buf, node) orelse return tree.nodeToSpan(node);2031 if (tree.fullContainerDecl(&buf, node)) |container_decl| {
2032 const arg_node = container_decl.ast.arg.unwrap() orelse return tree.nodeToSpan(node);2032 const arg_node = container_decl.ast.arg.unwrap() orelse return tree.nodeToSpan(node);
2033 return tree.nodeToSpan(arg_node);2033 return tree.nodeToSpan(arg_node);
2034 } else if (tree.builtinCallParams(&buf, node)) |args| {
2035 // Builtin calls (`@Enum` etc) should use the first argument.
2036 return tree.nodeToSpan(if (args.len > 0) args[0] else node);
2037 } else {
2038 return tree.nodeToSpan(node);
2039 }
2034 },2040 },
2035 .container_field_name,2041 .container_field_name,
2036 .container_field_value,2042 .container_field_value,
...@@ -2040,8 +2046,38 @@ pub const SrcLoc = struct {...@@ -2040,8 +2046,38 @@ pub const SrcLoc = struct {
2040 const tree = try src_loc.file_scope.getTree(zcu);2046 const tree = try src_loc.file_scope.getTree(zcu);
2041 const node = src_loc.base_node;2047 const node = src_loc.base_node;
2042 var buf: [2]Ast.Node.Index = undefined;2048 var buf: [2]Ast.Node.Index = undefined;
2043 const container_decl = tree.fullContainerDecl(&buf, node) orelse2049 const container_decl = tree.fullContainerDecl(&buf, node) orelse {
2050 // This could be a reification builtin. These are the args we care about:
2051 // * `@Enum(_, _, names, values)`
2052 // * `@Struct(_, _, names, types, values_and_aligns)`
2053 // * `@Union(_, _, names, types, aligns)`
2054 if (tree.builtinCallParams(&buf, node)) |args| {
2055 const builtin_name = tree.tokenSlice(tree.firstToken(node));
2056 const arg_index: ?u3 = if (std.mem.eql(u8, builtin_name, "@Enum")) switch (src_loc.lazy) {
2057 .container_field_name => 2,
2058 .container_field_value => 3,
2059 .container_field_type => null,
2060 .container_field_align => null,
2061 else => unreachable,
2062 } else if (std.mem.eql(u8, builtin_name, "@Struct")) switch (src_loc.lazy) {
2063 .container_field_name => 2,
2064 .container_field_value => 4,
2065 .container_field_type => 3,
2066 .container_field_align => 4,
2067 else => unreachable,
2068 } else if (std.mem.eql(u8, builtin_name, "@Union")) switch (src_loc.lazy) {
2069 .container_field_name => 2,
2070 .container_field_value => 4,
2071 .container_field_type => 3,
2072 .container_field_align => null,
2073 else => unreachable,
2074 } else null;
2075 if (arg_index) |i| {
2076 if (args.len >= i) return tree.nodeToSpan(args[i]);
2077 }
2078 }
2044 return tree.nodeToSpan(node);2079 return tree.nodeToSpan(node);
2080 };
20452081
2046 var cur_field_idx: usize = 0;2082 var cur_field_idx: usize = 0;
2047 for (container_decl.ast.members) |member_node| {2083 for (container_decl.ast.members) |member_node| {
src/Zcu/PerThread.zig+59-38
...@@ -2176,6 +2176,9 @@ fn analyzeNavType(...@@ -2176,6 +2176,9 @@ fn analyzeNavType(
2176 return .{ .type_changed = true };2176 return .{ .type_changed = true };
2177}2177}
21782178
2179/// If `func_index` is not a runtime function (e.g. it has a comptime-only parameter type) then it
2180/// is still valid to call this function and use its `func_body` unit in general---analysis of the
2181/// runtime function body will simply fail.
2179pub fn ensureFuncBodyUpToDate(2182pub fn ensureFuncBodyUpToDate(
2180 pt: Zcu.PerThread,2183 pt: Zcu.PerThread,
2181 func_index: InternPool.Index,2184 func_index: InternPool.Index,
...@@ -2278,29 +2281,6 @@ fn analyzeFuncBody(...@@ -2278,29 +2281,6 @@ fn analyzeFuncBody(
2278 const func = zcu.funcInfo(func_index);2281 const func = zcu.funcInfo(func_index);
2279 const anal_unit = AnalUnit.wrap(.{ .func = func_index });2282 const anal_unit = AnalUnit.wrap(.{ .func = func_index });
22802283
2281 // Make sure that this function is still owned by the same `Nav`. Otherwise, analyzing
2282 // it would be a waste of time in the best case, and could cause codegen to give bogus
2283 // results in the worst case.
2284
2285 if (func.generic_owner == .none) {
2286 // Among another things, this ensures that the function's `zir_body_inst` is correct.
2287 try pt.ensureNavValUpToDate(func.owner_nav, reason);
2288 if (ip.getNav(func.owner_nav).status.fully_resolved.val != func_index) {
2289 // This function is no longer referenced! There's no point in re-analyzing it.
2290 // Just mark a transitive failure and move on.
2291 return error.AnalysisFail;
2292 }
2293 } else {
2294 const go_nav = zcu.funcInfo(func.generic_owner).owner_nav;
2295 // Among another things, this ensures that the function's `zir_body_inst` is correct.
2296 try pt.ensureNavValUpToDate(go_nav, reason);
2297 if (ip.getNav(go_nav).status.fully_resolved.val != func.generic_owner) {
2298 // The generic owner is no longer referenced, so this function is also unreferenced.
2299 // There's no point in re-analyzing it. Just mark a transitive failure and move on.
2300 return error.AnalysisFail;
2301 }
2302 }
2303
2304 // We'll want to remember what the IES used to be before the update for2284 // We'll want to remember what the IES used to be before the update for
2305 // dependency invalidation purposes.2285 // dependency invalidation purposes.
2306 const old_resolved_ies = if (func.analysisUnordered(ip).inferred_error_set)2286 const old_resolved_ies = if (func.analysisUnordered(ip).inferred_error_set)
...@@ -3263,29 +3243,25 @@ fn analyzeFuncBodyInner(...@@ -3263,29 +3243,25 @@ fn analyzeFuncBodyInner(
32633243
3264 const anal_unit = AnalUnit.wrap(.{ .func = func_index });3244 const anal_unit = AnalUnit.wrap(.{ .func = func_index });
3265 const func = zcu.funcInfo(func_index);3245 const func = zcu.funcInfo(func_index);
3266 const inst_info = func.zir_body_inst.resolveFull(ip) orelse return error.AnalysisFail;3246
3267 const file = zcu.fileByIndex(inst_info.file);3247 // This is the `Nav` corresponding to the `declaration` instruction which the function or its generic owner originates from.
3248 const decl_analysis = if (func.generic_owner == .none)
3249 ip.getNav(func.owner_nav).analysis.?
3250 else
3251 ip.getNav(zcu.funcInfo(func.generic_owner).owner_nav).analysis.?;
3252
3253 const file = zcu.fileByIndex(decl_analysis.zir_index.resolveFile(ip));
3268 const zir = file.zir.?;3254 const zir = file.zir.?;
32693255
3270 try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, reason);3256 try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, reason);
3271 defer assert(zcu.analysis_in_progress.swapRemove(anal_unit));3257 defer assert(zcu.analysis_in_progress.swapRemove(anal_unit));
32723258
3273 if (func.analysisUnordered(ip).inferred_error_set) {
3274 func.setResolvedErrorSet(ip, io, .none);
3275 }
3276
3277 if (zcu.comp.time_report) |*tr| {3259 if (zcu.comp.time_report) |*tr| {
3278 if (func.generic_owner != .none) {3260 if (func.generic_owner != .none) {
3279 tr.stats.n_generic_instances += 1;3261 tr.stats.n_generic_instances += 1;
3280 }3262 }
3281 }3263 }
32823264
3283 // This is the `Nau` corresponding to the `declaration` instruction which the function or its generic owner originates from.
3284 const decl_nav = ip.getNav(if (func.generic_owner == .none)
3285 func.owner_nav
3286 else
3287 zcu.funcInfo(func.generic_owner).owner_nav);
3288
3289 const func_nav = ip.getNav(func.owner_nav);3265 const func_nav = ip.getNav(func.owner_nav);
32903266
3291 var analysis_arena = std.heap.ArenaAllocator.init(gpa);3267 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
...@@ -3319,9 +3295,30 @@ fn analyzeFuncBodyInner(...@@ -3319,9 +3295,30 @@ fn analyzeFuncBodyInner(
33193295
3320 // Every runtime function has a dependency on the source of the Decl it originates from.3296 // Every runtime function has a dependency on the source of the Decl it originates from.
3321 // It also depends on the value of its owner Decl.3297 // It also depends on the value of its owner Decl.
3322 try sema.declareDependency(.{ .src_hash = decl_nav.analysis.?.zir_index });3298 try sema.declareDependency(.{ .src_hash = decl_analysis.zir_index });
3323 try sema.declareDependency(.{ .nav_val = func.owner_nav });3299 try sema.declareDependency(.{ .nav_val = func.owner_nav });
33243300
3301 // Make sure that the declaration `Nav` still refers to this function (or its generic owner).
3302 // This will not be the case if the incremental update has changed a function type or turned a
3303 // `fn` decl into some other declaration. In that case, we must not run analysis: this function
3304 // will not be referenced this update, and trying to generate it could be problematic since we
3305 // assume the owner NAV actually, um, owns us.
3306 //
3307 // If we *are* still owned by the right NAV, this analysis updates `zir_body_inst` if necessary.
3308
3309 if (func.generic_owner == .none) {
3310 try pt.ensureNavValUpToDate(func.owner_nav, reason);
3311 if (ip.getNav(func.owner_nav).status.fully_resolved.val != func_index) {
3312 return error.AnalysisFail;
3313 }
3314 } else {
3315 const go_nav = zcu.funcInfo(func.generic_owner).owner_nav;
3316 try pt.ensureNavValUpToDate(go_nav, reason);
3317 if (ip.getNav(go_nav).status.fully_resolved.val != func.generic_owner) {
3318 return error.AnalysisFail;
3319 }
3320 }
3321
3325 if (func.analysisUnordered(ip).inferred_error_set) {3322 if (func.analysisUnordered(ip).inferred_error_set) {
3326 const ies = try analysis_arena.allocator().create(Sema.InferredErrorSet);3323 const ies = try analysis_arena.allocator().create(Sema.InferredErrorSet);
3327 ies.* = .{ .func = func_index };3324 ies.* = .{ .func = func_index };
...@@ -3339,11 +3336,11 @@ fn analyzeFuncBodyInner(...@@ -3339,11 +3336,11 @@ fn analyzeFuncBodyInner(
3339 var inner_block: Sema.Block = .{3336 var inner_block: Sema.Block = .{
3340 .parent = null,3337 .parent = null,
3341 .sema = &sema,3338 .sema = &sema,
3342 .namespace = decl_nav.analysis.?.namespace,3339 .namespace = decl_analysis.namespace,
3343 .instructions = .empty,3340 .instructions = .empty,
3344 .inlining = null,3341 .inlining = null,
3345 .comptime_reason = null,3342 .comptime_reason = null,
3346 .src_base_inst = decl_nav.analysis.?.zir_index,3343 .src_base_inst = decl_analysis.zir_index,
3347 .type_name_ctx = func_nav.fqn,3344 .type_name_ctx = func_nav.fqn,
3348 };3345 };
3349 defer inner_block.instructions.deinit(gpa);3346 defer inner_block.instructions.deinit(gpa);
...@@ -3385,6 +3382,13 @@ fn analyzeFuncBodyInner(...@@ -3385,6 +3382,13 @@ fn analyzeFuncBodyInner(
3385 const param_ty: Type = .fromInterned(fn_ty_info.param_types.get(ip)[runtime_param_index]);3382 const param_ty: Type = .fromInterned(fn_ty_info.param_types.get(ip)[runtime_param_index]);
3386 runtime_param_index += 1;3383 runtime_param_index += 1;
33873384
3385 if (param_ty.isGenericPoison()) {
3386 // We're guaranteed to get a compile error on the `fnHasRuntimeBits` check after this
3387 // loop (the generic poison means this is a generic function). But `continue` here to
3388 // avoid an illegal call to `onePossibleValue` below.
3389 continue;
3390 }
3391
3388 const param_ty_src = inner_block.src(.{ .func_decl_param_ty = @intCast(zir_param_index) });3392 const param_ty_src = inner_block.src(.{ .func_decl_param_ty = @intCast(zir_param_index) });
33893393
3390 try sema.ensureLayoutResolved(param_ty, param_ty_src, .parameter);3394 try sema.ensureLayoutResolved(param_ty, param_ty_src, .parameter);
...@@ -3406,6 +3410,23 @@ fn analyzeFuncBodyInner(...@@ -3406,6 +3410,23 @@ fn analyzeFuncBodyInner(
34063410
3407 try sema.ensureLayoutResolved(sema.fn_ret_ty, inner_block.src(.{ .node_offset_fn_type_ret_ty = .zero }), .return_type);3411 try sema.ensureLayoutResolved(sema.fn_ret_ty, inner_block.src(.{ .node_offset_fn_type_ret_ty = .zero }), .return_type);
34083412
3413 // The function type is now resolved, so we're ready to check whether it even makes sense to ask
3414 // for it to be analyzed at runtime.
3415 if (!fn_ty.fnHasRuntimeBits(zcu)) {
3416 const description: []const u8 = switch (fn_ty_info.cc) {
3417 .@"inline" => "inline",
3418 else => "generic",
3419 };
3420 // This error makes sense because the only reason this analysis would ever be requested is
3421 // for IES resolution.
3422 return sema.fail(
3423 &inner_block,
3424 inner_block.nodeOffset(.zero),
3425 "cannot resolve inferred error set of {s} function type '{f}'",
3426 .{ description, fn_ty.fmt(pt) },
3427 );
3428 }
3429
3409 const last_arg_index = inner_block.instructions.items.len;3430 const last_arg_index = inner_block.instructions.items.len;
34103431
3411 // Save the error trace as our first action in the function.3432 // Save the error trace as our first action in the function.
src/codegen/c.zig+11-4
...@@ -2112,7 +2112,7 @@ pub fn genTagNameFn(...@@ -2112,7 +2112,7 @@ pub fn genTagNameFn(
2112 const loaded_enum = ip.loadEnumType(enum_ty.toIntern());2112 const loaded_enum = ip.loadEnumType(enum_ty.toIntern());
2113 assert(loaded_enum.field_names.len > 0);2113 assert(loaded_enum.field_names.len > 0);
2114 if (Type.fromInterned(loaded_enum.int_tag_type).bitSize(zcu) > 64) {2114 if (Type.fromInterned(loaded_enum.int_tag_type).bitSize(zcu) > 64) {
2115 @panic("TODO CBE: tagName for enum over 128 bits");2115 @panic("TODO CBE: tagName for enum over 64 bits");
2116 }2116 }
21172117
2118 try w.print("static {s} zig_tagName_{f}__{d}({s} tag) {{\n", .{2118 try w.print("static {s} zig_tagName_{f}__{d}({s} tag) {{\n", .{
...@@ -2130,10 +2130,10 @@ pub fn genTagNameFn(...@@ -2130,10 +2130,10 @@ pub fn genTagNameFn(
2130 try w.writeAll(" switch (tag) {\n");2130 try w.writeAll(" switch (tag) {\n");
2131 const field_values = loaded_enum.field_values.get(ip);2131 const field_values = loaded_enum.field_values.get(ip);
2132 for (loaded_enum.field_names.get(ip), 0..) |field_name, field_index| {2132 for (loaded_enum.field_names.get(ip), 0..) |field_name, field_index| {
2133 const field_int: u64 = int: {2133 const field_int: i65 = int: {
2134 if (field_values.len == 0) break :int field_index;2134 if (field_values.len == 0) break :int field_index;
2135 const field_val: Value = .fromInterned(field_values[field_index]);2135 const field_val: Value = .fromInterned(field_values[field_index]);
2136 break :int field_val.toUnsignedInt(zcu);2136 break :int field_val.getUnsignedInt(zcu) orelse field_val.toSignedInt(zcu);
2137 };2137 };
2138 try w.print(" case {d}: return ({s}){{name{d},{d}}};\n", .{2138 try w.print(" case {d}: return ({s}){{name{d},{d}}};\n", .{
2139 field_int,2139 field_int,
...@@ -3278,7 +3278,10 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3278,7 +3278,10 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
3278 const operand_ty = f.typeOf(ty_op.operand);3278 const operand_ty = f.typeOf(ty_op.operand);
3279 const scalar_ty = operand_ty.scalarType(zcu);3279 const scalar_ty = operand_ty.scalarType(zcu);
32803280
3281 if (f.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) return f.moveCValue(inst, inst_ty, operand);3281 // `intCastIsNoop` doesn't apply to vectors because every vector lowers to a different C struct.
3282 if (inst_ty.zigTypeTag(zcu) != .vector and f.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) {
3283 return f.moveCValue(inst, inst_ty, operand);
3284 }
32823285
3283 const w = &f.code.writer;3286 const w = &f.code.writer;
3284 const local = try f.allocLocal(inst, inst_ty);3287 const local = try f.allocLocal(inst, inst_ty);
...@@ -3491,6 +3494,8 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:...@@ -3491,6 +3494,8 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
3491 const operand_ty = f.typeOf(bin_op.lhs);3494 const operand_ty = f.typeOf(bin_op.lhs);
3492 const scalar_ty = operand_ty.scalarType(zcu);3495 const scalar_ty = operand_ty.scalarType(zcu);
34933496
3497 const ref_arg = lowersToBigInt(scalar_ty, zcu);
3498
3494 const w = &f.code.writer;3499 const w = &f.code.writer;
3495 const local = try f.allocLocal(inst, inst_ty);3500 const local = try f.allocLocal(inst, inst_ty);
3496 const v = try Vectorize.start(f, inst, w, operand_ty);3501 const v = try Vectorize.start(f, inst, w, operand_ty);
...@@ -3504,9 +3509,11 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:...@@ -3504,9 +3509,11 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
3504 try f.writeCValueMember(w, local, .{ .field = 0 });3509 try f.writeCValueMember(w, local, .{ .field = 0 });
3505 try v.elem(f, w);3510 try v.elem(f, w);
3506 try w.writeAll(", ");3511 try w.writeAll(", ");
3512 if (ref_arg) try w.writeByte('&');
3507 try f.writeCValue(w, lhs, .other);3513 try f.writeCValue(w, lhs, .other);
3508 try v.elem(f, w);3514 try v.elem(f, w);
3509 try w.writeAll(", ");3515 try w.writeAll(", ");
3516 if (ref_arg) try w.writeByte('&');
3510 try f.writeCValue(w, rhs, .other);3517 try f.writeCValue(w, rhs, .other);
3511 if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);3518 if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w);
3512 try f.dg.renderBuiltinInfo(w, scalar_ty, info);3519 try f.dg.renderBuiltinInfo(w, scalar_ty, info);
src/codegen/c/type.zig+12-2
...@@ -898,13 +898,23 @@ pub const CType = union(enum) {...@@ -898,13 +898,23 @@ pub const CType = union(enum) {
898 try w.writeAll("fn_"); // intentional double underscore to start898 try w.writeAll("fn_"); // intentional double underscore to start
899 for (func_type.param_types.get(ip)) |param_ty_ip| {899 for (func_type.param_types.get(ip)) |param_ty_ip| {
900 const param_ty: Type = .fromInterned(param_ty_ip);900 const param_ty: Type = .fromInterned(param_ty_ip);
901 try w.print("_P{f}", .{fmtZigType(param_ty, zcu)});901 if (param_ty.isGenericPoison()) {
902 try w.writeAll("_Pgeneric");
903 } else {
904 try w.print("_P{f}", .{fmtZigType(param_ty, zcu)});
905 }
902 }906 }
903 if (func_type.is_var_args) {907 if (func_type.is_var_args) {
904 try w.writeAll("_VA");908 try w.writeAll("_VA");
905 }909 }
906 const ret_ty: Type = .fromInterned(func_type.return_type);910 const ret_ty: Type = .fromInterned(func_type.return_type);
907 try w.print("_R{f}", .{fmtZigType(ret_ty, zcu)});911 if (ret_ty.isGenericPoison()) {
912 try w.writeAll("_Rgeneric");
913 } else if (ret_ty.zigTypeTag(zcu) == .error_union and ret_ty.errorUnionPayload(zcu).isGenericPoison()) {
914 try w.writeAll("_Rgeneric_ies");
915 } else {
916 try w.print("_R{f}", .{fmtZigType(ret_ty, zcu)});
917 }
908 },918 },
909919
910 .vector => try w.print("vec_{d}_{f}", .{920 .vector => try w.print("vec_{d}_{f}", .{
src/codegen/llvm.zig+7-25
...@@ -3436,9 +3436,9 @@ pub const Object = struct {...@@ -3436,9 +3436,9 @@ pub const Object = struct {
3436 }3436 }
34373437
3438 if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) {3438 if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) {
3439 const stack_trace_ty = zcu.builtin_decl_values.get(.StackTrace);3439 // First parameter is a pointer to `std.builtin.StackTrace`.
3440 const ptr_ty = try pt.ptrType(.{ .child = stack_trace_ty });3440 const llvm_ptr_ty = try o.builder.ptrType(toLlvmAddressSpace(.generic, target));
3441 try llvm_params.append(o.gpa, try o.lowerType(pt, ptr_ty));3441 try llvm_params.append(o.gpa, llvm_ptr_ty);
3442 }3442 }
34433443
3444 var it = iterateParamTypes(o, pt, fn_info);3444 var it = iterateParamTypes(o, pt, fn_info);
...@@ -6719,16 +6719,11 @@ pub const FuncGen = struct {...@@ -6719,16 +6719,11 @@ pub const FuncGen = struct {
6719 const zcu = pt.zcu;6719 const zcu = pt.zcu;
6720 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;6720 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
6721 const ptr_ty = self.typeOf(bin_op.lhs);6721 const ptr_ty = self.typeOf(bin_op.lhs);
6722 const elem_ty = ptr_ty.childType(zcu);6722 const elem_ty = ptr_ty.indexableElem(zcu);
6723 const llvm_elem_ty = try o.lowerType(pt, elem_ty);6723 const llvm_elem_ty = try o.lowerType(pt, elem_ty);
6724 const base_ptr = try self.resolveInst(bin_op.lhs);6724 const base_ptr = try self.resolveInst(bin_op.lhs);
6725 const rhs = try self.resolveInst(bin_op.rhs);6725 const rhs = try self.resolveInst(bin_op.rhs);
6726 // TODO: when we go fully opaque pointers in LLVM 16 we can remove this branch6726 const ptr = try self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{rhs}, "");
6727 const ptr = try self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, if (ptr_ty.isSinglePointer(zcu))
6728 // If this is a single-item pointer to an array, we need another index in the GEP.
6729 &.{ try o.builder.intValue(try o.lowerType(pt, Type.usize), 0), rhs }
6730 else
6731 &.{rhs}, "");
6732 if (isByRef(elem_ty, zcu)) {6727 if (isByRef(elem_ty, zcu)) {
6733 self.maybeMarkAllowZeroAccess(ptr_ty.ptrInfo(zcu));6728 self.maybeMarkAllowZeroAccess(ptr_ty.ptrInfo(zcu));
6734 const ptr_align = (ptr_ty.ptrAlignment(zcu).min(elem_ty.abiAlignment(zcu))).toLlvm();6729 const ptr_align = (ptr_ty.ptrAlignment(zcu).min(elem_ty.abiAlignment(zcu))).toLlvm();
...@@ -6808,11 +6803,6 @@ pub const FuncGen = struct {...@@ -6808,11 +6803,6 @@ pub const FuncGen = struct {
6808 const truncated_int =6803 const truncated_int =
6809 try self.wip.cast(.trunc, shifted_value, same_size_int, "");6804 try self.wip.cast(.trunc, shifted_value, same_size_int, "");
6810 return self.wip.cast(.bitcast, truncated_int, elem_llvm_ty, "");6805 return self.wip.cast(.bitcast, truncated_int, elem_llvm_ty, "");
6811 } else if (field_ty.isPtrAtRuntime(zcu)) {
6812 const same_size_int = try o.builder.intType(@intCast(field_ty.bitSize(zcu)));
6813 const truncated_int =
6814 try self.wip.cast(.trunc, shifted_value, same_size_int, "");
6815 return self.wip.cast(.inttoptr, truncated_int, elem_llvm_ty, "");
6816 }6806 }
6817 return self.wip.cast(.trunc, shifted_value, elem_llvm_ty, "");6807 return self.wip.cast(.trunc, shifted_value, elem_llvm_ty, "");
6818 },6808 },
...@@ -6830,11 +6820,6 @@ pub const FuncGen = struct {...@@ -6830,11 +6820,6 @@ pub const FuncGen = struct {
6830 const truncated_int =6820 const truncated_int =
6831 try self.wip.cast(.trunc, containing_int, same_size_int, "");6821 try self.wip.cast(.trunc, containing_int, same_size_int, "");
6832 return self.wip.cast(.bitcast, truncated_int, elem_llvm_ty, "");6822 return self.wip.cast(.bitcast, truncated_int, elem_llvm_ty, "");
6833 } else if (field_ty.isPtrAtRuntime(zcu)) {
6834 const same_size_int = try o.builder.intType(@intCast(field_ty.bitSize(zcu)));
6835 const truncated_int =
6836 try self.wip.cast(.trunc, containing_int, same_size_int, "");
6837 return self.wip.cast(.inttoptr, truncated_int, elem_llvm_ty, "");
6838 }6823 }
6839 return self.wip.cast(.trunc, containing_int, elem_llvm_ty, "");6824 return self.wip.cast(.trunc, containing_int, elem_llvm_ty, "");
6840 },6825 },
...@@ -10110,7 +10095,7 @@ pub const FuncGen = struct {...@@ -10110,7 +10095,7 @@ pub const FuncGen = struct {
10110 const ip = &zcu.intern_pool;10095 const ip = &zcu.intern_pool;
10111 const enum_type = ip.loadEnumType(enum_ty.toIntern());10096 const enum_type = ip.loadEnumType(enum_ty.toIntern());
1011210097
10113 // TODO: detect when the type changes and re-emit this function.10098 // TODO: detect when the type changes (`updateContainerType` will be called) and re-emit this function
10114 const gop = try o.named_enum_map.getOrPut(o.gpa, enum_ty.toIntern());10099 const gop = try o.named_enum_map.getOrPut(o.gpa, enum_ty.toIntern());
10115 if (gop.found_existing) return gop.value_ptr.*;10100 if (gop.found_existing) return gop.value_ptr.*;
10116 errdefer assert(o.named_enum_map.remove(enum_ty.toIntern()));10101 errdefer assert(o.named_enum_map.remove(enum_ty.toIntern()));
...@@ -10728,10 +10713,7 @@ pub const FuncGen = struct {...@@ -10728,10 +10713,7 @@ pub const FuncGen = struct {
10728 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]);10713 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]);
10729 const non_int_val = try self.resolveInst(extra.init);10714 const non_int_val = try self.resolveInst(extra.init);
10730 const small_int_ty = try o.builder.intType(@intCast(field_ty.bitSize(zcu)));10715 const small_int_ty = try o.builder.intType(@intCast(field_ty.bitSize(zcu)));
10731 const small_int_val = if (field_ty.isPtrAtRuntime(zcu))10716 const small_int_val = try self.wip.cast(.bitcast, non_int_val, small_int_ty, "");
10732 try self.wip.cast(.ptrtoint, non_int_val, small_int_ty, "")
10733 else
10734 try self.wip.cast(.bitcast, non_int_val, small_int_ty, "");
10735 return self.wip.conv(.unsigned, small_int_val, int_llvm_ty, "");10717 return self.wip.conv(.unsigned, small_int_val, int_llvm_ty, "");
10736 }10718 }
1073710719
src/link/Dwarf.zig+6
...@@ -2252,6 +2252,12 @@ pub const WipNav = struct {...@@ -2252,6 +2252,12 @@ pub const WipNav = struct {
2252 .generic_decl_const,2252 .generic_decl_const,
2253 .generic_decl_func,2253 .generic_decl_func,
2254 => true,2254 => true,
2255
2256 // This comes from a decl which was previously generated as an incomplete value
2257 // (I think that must mean either a function or an extern which previously had
2258 // incomplete types).
2259 .undefined_comptime_value => false,
2260
2255 else => |t| std.debug.panic("bad decl abbrev code: {t}", .{t}),2261 else => |t| std.debug.panic("bad decl abbrev code: {t}", .{t}),
2256 };2262 };
2257 if (parent_type.getCaptures(zcu).len == 0) {2263 if (parent_type.getCaptures(zcu).len == 0) {
src/print_value.zig+19-4
...@@ -113,7 +113,7 @@ pub fn print(...@@ -113,7 +113,7 @@ pub fn print(
113 if (slice.len == .zero_usize) {113 if (slice.len == .zero_usize) {
114 return writer.writeAll("&.{}");114 return writer.writeAll("&.{}");
115 }115 }
116 try print(.fromInterned(slice.ptr), writer, level - 1, pt, opt_sema);116 try print(.fromInterned(slice.ptr), writer, level, pt, opt_sema);
117 } else {117 } else {
118 const print_contents = switch (ip.getBackingAddrTag(slice.ptr).?) {118 const print_contents = switch (ip.getBackingAddrTag(slice.ptr).?) {
119 .field, .arr_elem, .eu_payload, .opt_payload => unreachable,119 .field, .arr_elem, .eu_payload, .opt_payload => unreachable,
...@@ -170,6 +170,9 @@ pub fn print(...@@ -170,6 +170,9 @@ pub fn print(
170 }170 }
171 },171 },
172 .bitpack => |bitpack| {172 .bitpack => |bitpack| {
173 if (level == 0) {
174 return writer.writeAll(".{ ... }");
175 }
173 const ty: Type = .fromInterned(bitpack.ty);176 const ty: Type = .fromInterned(bitpack.ty);
174 switch (ty.zigTypeTag(zcu)) {177 switch (ty.zigTypeTag(zcu)) {
175 .@"struct" => {178 .@"struct" => {
...@@ -464,18 +467,30 @@ pub fn printPtrDerivation(...@@ -464,18 +467,30 @@ pub fn printPtrDerivation(
464 .uav_ptr => |uav| {467 .uav_ptr => |uav| {
465 const ty = Value.fromInterned(uav.val).typeOf(zcu);468 const ty = Value.fromInterned(uav.val).typeOf(zcu);
466 try writer.print("@as({f}, ", .{ty.fmt(pt)});469 try writer.print("@as({f}, ", .{ty.fmt(pt)});
467 try print(Value.fromInterned(uav.val), writer, x.level - 1, pt, x.opt_sema);470 if (x.level == 0) {
471 try writer.writeAll("...");
472 } else {
473 try print(Value.fromInterned(uav.val), writer, x.level - 1, pt, x.opt_sema);
474 }
468 try writer.writeByte(')');475 try writer.writeByte(')');
469 },476 },
470 .comptime_alloc_ptr => |info| {477 .comptime_alloc_ptr => |info| {
471 try writer.print("@as({f}, ", .{info.val.typeOf(zcu).fmt(pt)});478 try writer.print("@as({f}, ", .{info.val.typeOf(zcu).fmt(pt)});
472 try print(info.val, writer, x.level - 1, pt, x.opt_sema);479 if (x.level == 0) {
480 try writer.writeAll("...");
481 } else {
482 try print(info.val, writer, x.level - 1, pt, x.opt_sema);
483 }
473 try writer.writeByte(')');484 try writer.writeByte(')');
474 },485 },
475 .comptime_field_ptr => |val| {486 .comptime_field_ptr => |val| {
476 const ty = val.typeOf(zcu);487 const ty = val.typeOf(zcu);
477 try writer.print("@as({f}, ", .{ty.fmt(pt)});488 try writer.print("@as({f}, ", .{ty.fmt(pt)});
478 try print(val, writer, x.level - 1, pt, x.opt_sema);489 if (x.level == 0) {
490 try writer.writeAll("...");
491 } else {
492 try print(val, writer, x.level - 1, pt, x.opt_sema);
493 }
479 try writer.writeByte(')');494 try writer.writeByte(')');
480 },495 },
481 else => unreachable,496 else => unreachable,