From 5e8397d5e03269d8a39efb22605ea20102848084 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Mon, 12 Jan 2026 14:47:14 +0000 Subject: [PATCH 01/79] Zir: rework container type declarations Only AstGen and print_zir currently support the new representation, so attempting to build the compiler will emit (many) compile errors. --- lib/std/zig/AstGen.zig | 1652 +++++++++++++--------------------------- lib/std/zig/Zir.zig | 942 ++++++++++++++--------- src/print_zir.zig | 537 +++---------- 3 files changed, 1205 insertions(+), 1926 deletions(-) diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index 667f5ef045bd431512b3aed957be43e125ddb0ad..6a6585192ddb7efd7dc1b6455ce28cdf27425530 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -3975,81 +3975,67 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node. return rvalue(gz, ri, result, node); } -const WipMembers = struct { - payload: *ArrayList(u32), - payload_top: usize, - field_bits_start: u32, - fields_start: u32, - fields_end: u32, - decl_index: u32 = 0, - field_index: u32 = 0, - - const Self = @This(); - - fn init(gpa: Allocator, payload: *ArrayList(u32), decl_count: u32, field_count: u32, comptime bits_per_field: u32, comptime max_field_size: u32) Allocator.Error!Self { - const payload_top: u32 = @intCast(payload.items.len); - const field_bits_start = payload_top + decl_count; - const fields_start = field_bits_start + if (bits_per_field > 0) blk: { - const fields_per_u32 = 32 / bits_per_field; - break :blk (field_count + fields_per_u32 - 1) / fields_per_u32; - } else 0; - const payload_end = fields_start + field_count * max_field_size; - try payload.resize(gpa, payload_end); +const Scratch = struct { + astgen: *AstGen, + scratch_top: u32, + fn init(astgen: *AstGen) Scratch { return .{ - .payload = payload, - .payload_top = payload_top, - .field_bits_start = field_bits_start, - .fields_start = fields_start, - .fields_end = fields_start, + .astgen = astgen, + .scratch_top = @intCast(astgen.scratch.items.len), }; } - - fn nextDecl(self: *Self, decl_inst: Zir.Inst.Index) void { - self.payload.items[self.payload_top + self.decl_index] = @intFromEnum(decl_inst); - self.decl_index += 1; + fn reset(s: *Scratch) void { + s.astgen.scratch.shrinkRetainingCapacity(s.scratch_top); + s.* = undefined; } - - fn nextField(self: *Self, comptime bits_per_field: u32, bits: [bits_per_field]bool) void { - const fields_per_u32 = 32 / bits_per_field; - const index = self.field_bits_start + self.field_index / fields_per_u32; - assert(index < self.fields_start); - var bit_bag: u32 = if (self.field_index % fields_per_u32 == 0) 0 else self.payload.items[index]; - bit_bag >>= bits_per_field; - comptime var i = 0; - inline while (i < bits_per_field) : (i += 1) { - bit_bag |= @as(u32, @intFromBool(bits[i])) << (32 - bits_per_field + i); - } - self.payload.items[index] = bit_bag; - self.field_index += 1; + fn addSlice(s: *Scratch, len: u32) Allocator.Error!Slice { + const start: u32 = @intCast(s.astgen.scratch.items.len); + try s.astgen.scratch.resize(s.astgen.gpa, start + len); + return .{ .start = start, .len = len }; } - - fn appendToField(self: *Self, data: u32) void { - assert(self.fields_end < self.payload.items.len); - self.payload.items[self.fields_end] = data; - self.fields_end += 1; + fn addOptionalSlice(s: *Scratch, present: bool, len: u32) Allocator.Error!?Slice { + if (!present) return null; + return try addSlice(s, len); } - - fn finishBits(self: *Self, comptime bits_per_field: u32) void { - if (bits_per_field > 0) { - const fields_per_u32 = 32 / bits_per_field; - const empty_field_slots = fields_per_u32 - (self.field_index % fields_per_u32); - if (self.field_index > 0 and empty_field_slots < fields_per_u32) { - const index = self.field_bits_start + self.field_index / fields_per_u32; - self.payload.items[index] >>= @intCast(empty_field_slots * bits_per_field); - } - } + fn appendBodyWithFixups(s: *Scratch, body: []const Zir.Inst.Index) Allocator.Error!u32 { + const len = countBodyLenAfterFixups(s.astgen, body); + try s.astgen.scratch.ensureUnusedCapacity(s.astgen.gpa, len); + appendBodyWithFixupsArrayList(s.astgen, &s.astgen.scratch, body); + return len; } - - fn declsSlice(self: *Self) []u32 { - return self.payload.items[self.payload_top..][0..self.decl_index]; + /// Returns the slice containing all data added to this `Scratch`. + fn all(s: *Scratch) Slice { + const len = s.astgen.scratch.items.len - s.scratch_top; + return .{ .start = s.scratch_top, .len = @intCast(len) }; } + const Slice = struct { + start: u32, + len: u32, + fn get(s: Slice, astgen: *AstGen) []u32 { + return astgen.scratch.items[s.start..][0..s.len]; + } + }; +}; - fn fieldsSlice(self: *Self) []u32 { - return self.payload.items[self.field_bits_start..self.fields_end]; - } +const WipDecls = struct { + astgen: *AstGen, + slice: Scratch.Slice, + index: u32, - fn deinit(self: *Self) void { - self.payload.items.len = self.payload_top; + fn init(scratch: *Scratch, decls_len: u32) Allocator.Error!WipDecls { + return .{ + .astgen = scratch.astgen, + .slice = try scratch.addSlice(decls_len), + .index = 0, + }; + } + fn finish(wip: *WipDecls) void { + assert(wip.index == wip.slice.len); + wip.* = undefined; + } + fn nextDecl(wip: *WipDecls, decl_inst: Zir.Inst.Index) void { + wip.slice.get(wip.astgen)[wip.index] = @intFromEnum(decl_inst); + wip.index += 1; } }; @@ -4057,7 +4043,7 @@ fn fnDecl( astgen: *AstGen, gz: *GenZir, scope: *Scope, - wip_members: *WipMembers, + wip_decls: *WipDecls, decl_node: Ast.Node.Index, body_node: Ast.Node.OptionalIndex, fn_proto: Ast.full.FnProto, @@ -4133,7 +4119,7 @@ fn fnDecl( assert(!is_extern); // validated by parser (TODO why???) } - wip_members.nextDecl(decl_inst); + wip_decls.nextDecl(decl_inst); var type_gz: GenZir = .{ .is_comptime = true, @@ -4488,7 +4474,7 @@ fn globalVarDecl( astgen: *AstGen, gz: *GenZir, scope: *Scope, - wip_members: *WipMembers, + wip_decls: *WipDecls, node: Ast.Node.Index, var_decl: Ast.full.VarDecl, ) InnerError!void { @@ -4533,7 +4519,7 @@ fn globalVarDecl( const decl_column = astgen.source_column; const decl_inst = try gz.makeDeclaration(node); - wip_members.nextDecl(decl_inst); + wip_decls.nextDecl(decl_inst); if (var_decl.ast.init_node.unwrap()) |init_node| { if (is_extern) { @@ -4635,7 +4621,7 @@ fn comptimeDecl( astgen: *AstGen, gz: *GenZir, scope: *Scope, - wip_members: *WipMembers, + wip_decls: *WipDecls, node: Ast.Node.Index, ) InnerError!void { const tree = astgen.tree; @@ -4650,7 +4636,7 @@ fn comptimeDecl( // Up top so the ZIR instruction index marks the start range of this // top-level declaration. const decl_inst = try gz.makeDeclaration(node); - wip_members.nextDecl(decl_inst); + wip_decls.nextDecl(decl_inst); astgen.advanceSourceCursorToNode(node); // This is just needed for the `setDeclaration` call. @@ -4698,7 +4684,7 @@ fn testDecl( astgen: *AstGen, gz: *GenZir, scope: *Scope, - wip_members: *WipMembers, + wip_decls: *WipDecls, node: Ast.Node.Index, ) InnerError!void { const tree = astgen.tree; @@ -4714,7 +4700,7 @@ fn testDecl( // top-level declaration. const decl_inst = try gz.makeDeclaration(node); - wip_members.nextDecl(decl_inst); + wip_decls.nextDecl(decl_inst); astgen.advanceSourceCursorToNode(node); // This is just needed for the `setDeclaration` call. @@ -4914,7 +4900,7 @@ fn structDeclInner( node: Ast.Node.Index, container_decl: Ast.full.ContainerDecl, layout: std.builtin.Type.ContainerLayout, - backing_int_node: Ast.Node.OptionalIndex, + maybe_backing_int_node: Ast.Node.OptionalIndex, name_strat: Zir.Inst.NameStrategy, ) InnerError!Zir.Inst.Ref { const astgen = gz.astgen; @@ -4930,27 +4916,39 @@ fn structDeclInner( if (node == .root) { return astgen.failNode(tuple_field_node, "file cannot be a tuple", .{}); } else { - return tupleDecl(gz, scope, node, container_decl, layout, backing_int_node); + return tupleDecl(gz, scope, node, container_decl, layout, maybe_backing_int_node); } } + astgen.advanceSourceCursorToNode(node); + + const backing_int_type_ref: Zir.Inst.Ref = ty: { + const backing_int_node = maybe_backing_int_node.unwrap() orelse break :ty .none; + if (layout != .@"packed") return astgen.failNode( + backing_int_node, + "non-packed struct does not support backing integer type", + .{}, + ); + break :ty try typeExpr(gz, scope, backing_int_node); + }; + const decl_inst = try gz.reserveInstructionIndex(); - if (container_decl.ast.members.len == 0 and backing_int_node == .none) { + if (container_decl.ast.members.len == 0 and backing_int_type_ref == .none) { try gz.setStruct(decl_inst, .{ .src_node = node, + .name_strat = name_strat, .layout = layout, - .captures_len = 0, - .fields_len = 0, + .backing_int_type = .none, .decls_len = 0, - .has_backing_int = false, - .known_non_opv = false, - .known_comptime_only = false, + .fields_len = 0, + .any_field_aligns = false, + .any_field_defaults = false, .any_comptime_fields = false, - .any_default_inits = false, - .any_aligned_fields = false, - .fields_hash = std.zig.hashSrc(@tagName(layout)), - .name_strat = name_strat, + .fields_hash = @splat(0), + .captures = &.{}, + .capture_names = &.{}, + .remaining = &.{}, }); return decl_inst.toRef(); } @@ -4967,7 +4965,6 @@ fn structDeclInner( // The struct_decl instruction introduces a scope in which the decls of the struct // are in scope, so that field types, alignments, and default value expressions // can refer to decls within the struct itself. - astgen.advanceSourceCursorToNode(node); var block_scope: GenZir = .{ .parent = &namespace.base, .decl_node_index = node, @@ -4979,197 +4976,118 @@ fn structDeclInner( }; defer block_scope.unstack(); - const scratch_top = astgen.scratch.items.len; - defer astgen.scratch.items.len = scratch_top; + const scan_result = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"struct"); - var backing_int_body_len: usize = 0; - const backing_int_ref: Zir.Inst.Ref = blk: { - if (backing_int_node.unwrap()) |arg| { - if (layout != .@"packed") { - return astgen.failNode(arg, "non-packed struct does not support backing integer type", .{}); - } else { - const backing_int_ref = try typeExpr(&block_scope, &namespace.base, arg); - if (!block_scope.isEmpty()) { - if (!block_scope.endsWithNoReturn()) { - _ = try block_scope.addBreak(.break_inline, decl_inst, backing_int_ref); - } + var scratch: Scratch = .init(astgen); + defer scratch.reset(); - const body = block_scope.instructionsSlice(); - const old_scratch_len = astgen.scratch.items.len; - try astgen.scratch.ensureUnusedCapacity(gpa, countBodyLenAfterFixups(astgen, body)); - appendBodyWithFixupsArrayList(astgen, &astgen.scratch, body); - backing_int_body_len = astgen.scratch.items.len - old_scratch_len; - block_scope.instructions.items.len = block_scope.instructions_top; - } - break :blk backing_int_ref; - } - } else { - break :blk .none; - } - }; - - const decl_count = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"struct"); - const field_count: u32 = @intCast(container_decl.ast.members.len - decl_count); - - const bits_per_field = 4; - const max_field_size = 5; - var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size); - defer wip_members.deinit(); - - // We will use the scratch buffer, starting here, for the bodies: - // bodies: { // for every fields_len - // field_type_body_inst: Inst, // for each field_type_body_len - // align_body_inst: Inst, // for each align_body_len - // init_body_inst: Inst, // for each init_body_len - // } - // Note that the scratch buffer is simultaneously being used by WipMembers, however - // it will not access any elements beyond this point in the ArrayList. It also - // accesses via the ArrayList items field so it can handle the scratch buffer being - // reallocated. - // No defer needed here because it is handled by `wip_members.deinit()` above. - const bodies_start = astgen.scratch.items.len; + // Replicate the structure of the ZIR trailing data in `scratch` + var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len); + const field_names = try scratch.addSlice(scan_result.fields_len); + const field_type_body_lens = try scratch.addSlice(scan_result.fields_len); + const field_align_body_lens = try scratch.addOptionalSlice(scan_result.any_field_aligns, scan_result.fields_len); + const field_default_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, scan_result.fields_len); + const field_comptime_bits = try scratch.addOptionalSlice( + scan_result.any_comptime_fields, + std.math.divCeil(u32, scan_result.fields_len, 32) catch unreachable, + ); + if (field_comptime_bits) |bits| @memset(bits.get(astgen), 0); const old_hasher = astgen.src_hasher; defer astgen.src_hasher = old_hasher; - astgen.src_hasher = std.zig.SrcHasher.init(.{}); - astgen.src_hasher.update(@tagName(layout)); - if (backing_int_node.unwrap()) |arg| { - astgen.src_hasher.update(tree.getNodeSource(arg)); - } + astgen.src_hasher = .init(.{}); - var known_non_opv = false; - var known_comptime_only = false; - var any_comptime_fields = false; - var any_aligned_fields = false; - var any_default_inits = false; + var next_field_idx: u32 = 0; for (container_decl.ast.members) |member_node| { - var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { + var member = switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) { .decl => continue, .field => |field| field, }; + const field_idx = next_field_idx; + next_field_idx += 1; astgen.src_hasher.update(tree.getNodeSource(member_node)); - const field_name = try astgen.identAsString(member.ast.main_token); member.convertToNonTupleLike(astgen.tree); assert(!member.ast.tuple_like); - wip_members.appendToField(@intFromEnum(field_name)); - const type_expr = member.ast.type_expr.unwrap() orelse { - return astgen.failTok(member.ast.main_token, "struct field missing type", .{}); - }; + field_names.get(astgen)[field_idx] = @intFromEnum(try astgen.identAsString(member.ast.main_token)); - const field_type = try typeExpr(&block_scope, &namespace.base, type_expr); - const have_type_body = !block_scope.isEmpty(); - const have_align = member.ast.align_expr != .none; - const have_value = member.ast.value_expr != .none; - const is_comptime = member.comptime_token != null; + { + const type_node = member.ast.type_expr.unwrap() orelse { + return astgen.failTok(member.ast.main_token, "struct field missing type", .{}); + }; + const type_ref = try typeExpr(&block_scope, &namespace.base, type_node); + if (!block_scope.endsWithNoReturn()) { + _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref); + } + const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); + field_type_body_lens.get(astgen)[field_idx] = body_len; + block_scope.instructions.items.len = block_scope.instructions_top; + } - if (is_comptime) { + if (member.ast.align_expr.unwrap()) |align_node| { + if (layout == .@"packed") { + return astgen.failNode(align_node, "unable to override alignment of packed struct fields", .{}); + } + const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_node); + if (!block_scope.endsWithNoReturn()) { + _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref); + } + const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); + field_align_body_lens.?.get(astgen)[field_idx] = body_len; + block_scope.instructions.items.len = block_scope.instructions_top; + } else if (field_align_body_lens) |lens| { + lens.get(astgen)[field_idx] = 0; + } + + if (member.ast.value_expr.unwrap()) |default_node| { + const ri: ResultInfo = .{ .rl = .{ .coerced_ty = decl_inst.toRef() } }; + const default_ref = try expr(&block_scope, &namespace.base, ri, default_node); + if (!block_scope.endsWithNoReturn()) { + _ = try block_scope.addBreak(.break_inline, decl_inst, default_ref); + } + const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); + field_default_body_lens.?.get(astgen)[field_idx] = body_len; + block_scope.instructions.items.len = block_scope.instructions_top; + } else if (field_default_body_lens) |lens| { + lens.get(astgen)[field_idx] = 0; + } + + if (member.comptime_token) |comptime_token| { switch (layout) { - .@"packed", .@"extern" => return astgen.failTok(member.comptime_token.?, "{s} struct fields cannot be marked comptime", .{@tagName(layout)}), - .auto => any_comptime_fields = true, + .@"packed", .@"extern" => return astgen.failTok(comptime_token, "{s} struct fields cannot be marked comptime", .{@tagName(layout)}), + .auto => {}, } - } else { - known_non_opv = known_non_opv or - nodeImpliesMoreThanOnePossibleValue(tree, type_expr); - known_comptime_only = known_comptime_only or - nodeImpliesComptimeOnly(tree, type_expr); - } - wip_members.nextField(bits_per_field, .{ have_align, have_value, is_comptime, have_type_body }); - - if (have_type_body) { - if (!block_scope.endsWithNoReturn()) { - _ = try block_scope.addBreak(.break_inline, decl_inst, field_type); + if (member.ast.value_expr == .none) { + return astgen.failTok(comptime_token, "comptime field without default initialization value", .{}); } - const body = block_scope.instructionsSlice(); - const old_scratch_len = astgen.scratch.items.len; - try astgen.scratch.ensureUnusedCapacity(gpa, countBodyLenAfterFixups(astgen, body)); - appendBodyWithFixupsArrayList(astgen, &astgen.scratch, body); - wip_members.appendToField(@intCast(astgen.scratch.items.len - old_scratch_len)); - block_scope.instructions.items.len = block_scope.instructions_top; - } else { - wip_members.appendToField(@intFromEnum(field_type)); - } - - if (member.ast.align_expr.unwrap()) |align_expr| { - if (layout == .@"packed") { - return astgen.failNode(align_expr, "unable to override alignment of packed struct fields", .{}); - } - any_aligned_fields = true; - const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_expr); - if (!block_scope.endsWithNoReturn()) { - _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref); - } - const body = block_scope.instructionsSlice(); - const old_scratch_len = astgen.scratch.items.len; - try astgen.scratch.ensureUnusedCapacity(gpa, countBodyLenAfterFixups(astgen, body)); - appendBodyWithFixupsArrayList(astgen, &astgen.scratch, body); - wip_members.appendToField(@intCast(astgen.scratch.items.len - old_scratch_len)); - block_scope.instructions.items.len = block_scope.instructions_top; - } - - if (member.ast.value_expr.unwrap()) |value_expr| { - any_default_inits = true; - - // The decl_inst is used as here so that we can easily reconstruct a mapping - // between it and the field type when the fields inits are analyzed. - const ri: ResultInfo = .{ .rl = if (field_type == .none) .none else .{ .coerced_ty = decl_inst.toRef() } }; - - const default_inst = try expr(&block_scope, &namespace.base, ri, value_expr); - if (!block_scope.endsWithNoReturn()) { - _ = try block_scope.addBreak(.break_inline, decl_inst, default_inst); - } - const body = block_scope.instructionsSlice(); - const old_scratch_len = astgen.scratch.items.len; - try astgen.scratch.ensureUnusedCapacity(gpa, countBodyLenAfterFixups(astgen, body)); - appendBodyWithFixupsArrayList(astgen, &astgen.scratch, body); - wip_members.appendToField(@intCast(astgen.scratch.items.len - old_scratch_len)); - block_scope.instructions.items.len = block_scope.instructions_top; - } else if (member.comptime_token) |comptime_token| { - return astgen.failTok(comptime_token, "comptime field without default initialization value", .{}); + const mask = @as(u32, 1) << @intCast(field_idx % 32); + field_comptime_bits.?.get(astgen)[field_idx / 32] |= mask; } } + assert(next_field_idx == scan_result.fields_len); + wip_decls.finish(); var fields_hash: std.zig.SrcHash = undefined; astgen.src_hasher.final(&fields_hash); try gz.setStruct(decl_inst, .{ .src_node = node, + .name_strat = name_strat, .layout = layout, - .captures_len = @intCast(namespace.captures.count()), - .fields_len = field_count, - .decls_len = decl_count, - .has_backing_int = backing_int_ref != .none, - .known_non_opv = known_non_opv, - .known_comptime_only = known_comptime_only, - .any_comptime_fields = any_comptime_fields, - .any_default_inits = any_default_inits, - .any_aligned_fields = any_aligned_fields, + .backing_int_type = backing_int_type_ref, + .decls_len = scan_result.decls_len, + .fields_len = scan_result.fields_len, + .any_field_aligns = scan_result.any_field_aligns, + .any_field_defaults = scan_result.any_field_values, + .any_comptime_fields = scan_result.any_comptime_fields, .fields_hash = fields_hash, - .name_strat = name_strat, + .captures = namespace.captures.keys(), + .capture_names = namespace.captures.values(), + .remaining = scratch.all().get(astgen), }); - wip_members.finishBits(bits_per_field); - const decls_slice = wip_members.declsSlice(); - const fields_slice = wip_members.fieldsSlice(); - const bodies_slice = astgen.scratch.items[bodies_start..]; - try astgen.extra.ensureUnusedCapacity(gpa, backing_int_body_len + 2 + - decls_slice.len + namespace.captures.count() * 2 + fields_slice.len + bodies_slice.len); - astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); - astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.values())); - if (backing_int_ref != .none) { - astgen.extra.appendAssumeCapacity(@intCast(backing_int_body_len)); - if (backing_int_body_len == 0) { - astgen.extra.appendAssumeCapacity(@intFromEnum(backing_int_ref)); - } else { - astgen.extra.appendSliceAssumeCapacity(astgen.scratch.items[scratch_top..][0..backing_int_body_len]); - } - } - astgen.extra.appendSliceAssumeCapacity(decls_slice); - astgen.extra.appendSliceAssumeCapacity(fields_slice); - astgen.extra.appendSliceAssumeCapacity(bodies_slice); - block_scope.unstack(); return decl_inst.toRef(); } @@ -5281,11 +5199,34 @@ fn unionDeclInner( auto_enum_tok: ?Ast.TokenIndex, name_strat: Zir.Inst.NameStrategy, ) InnerError!Zir.Inst.Ref { - const decl_inst = try gz.reserveInstructionIndex(); - const astgen = gz.astgen; const gpa = astgen.gpa; + const explicit_int_or_enum_tag = switch (layout) { + .auto => opt_arg_node != .none, + .@"extern" => if (opt_arg_node.unwrap()) |arg_node| { + return astgen.failNode(arg_node, "{s} union does not support enum tag type", .{@tagName(layout)}); + } else false, + .@"packed" => false, + }; + + if (auto_enum_tok) |t| { + if (layout != .auto) { + return astgen.failTok(t, "{s} union does not support enum tag type", .{@tagName(layout)}); + } + } + + const is_tagged = explicit_int_or_enum_tag or auto_enum_tok != null; + + astgen.advanceSourceCursorToNode(node); + + const arg_type_ref: Zir.Inst.Ref = ref: { + const arg_node = opt_arg_node.unwrap() orelse break :ref .none; + break :ref try typeExpr(gz, scope, arg_node); + }; + + const decl_inst = try gz.reserveInstructionIndex(); + var namespace: Scope.Namespace = .{ .parent = scope, .node = node, @@ -5298,7 +5239,6 @@ fn unionDeclInner( // The union_decl instruction introduces a scope in which the decls of the union // are in scope, so that field types, alignments, and default value expressions // can refer to decls within the union itself. - astgen.advanceSourceCursorToNode(node); var block_scope: GenZir = .{ .parent = &namespace.base, .decl_node_index = node, @@ -5310,42 +5250,31 @@ fn unionDeclInner( }; defer block_scope.unstack(); - const decl_count = try astgen.scanContainer(&namespace, members, .@"union"); - const field_count: u32 = @intCast(members.len - decl_count); + const scan_result = try astgen.scanContainer(&namespace, members, .@"union"); - if (layout != .auto and (auto_enum_tok != null or opt_arg_node != .none)) { - if (opt_arg_node.unwrap()) |arg_node| { - return astgen.failNode(arg_node, "{s} union does not support enum tag type", .{@tagName(layout)}); - } else { - return astgen.failTok(auto_enum_tok.?, "{s} union does not support enum tag type", .{@tagName(layout)}); - } - } + var scratch: Scratch = .init(astgen); + defer scratch.reset(); - const arg_inst: Zir.Inst.Ref = if (opt_arg_node.unwrap()) |arg_node| - try typeExpr(&block_scope, &namespace.base, arg_node) - else - .none; - - const bits_per_field = 4; - const max_field_size = 4; - var any_aligned_fields = false; - var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size); - defer wip_members.deinit(); + // Replicate the structure of the ZIR trailing data in `scratch` + var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len); + const field_names = try scratch.addSlice(scan_result.fields_len); + const field_type_body_lens = try scratch.addSlice(scan_result.fields_len); + const field_align_body_lens = try scratch.addOptionalSlice(scan_result.any_field_aligns, scan_result.fields_len); + const field_value_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, scan_result.fields_len); const old_hasher = astgen.src_hasher; defer astgen.src_hasher = old_hasher; - astgen.src_hasher = std.zig.SrcHasher.init(.{}); - astgen.src_hasher.update(@tagName(layout)); - astgen.src_hasher.update(&.{@intFromBool(auto_enum_tok != null)}); - if (opt_arg_node.unwrap()) |arg_node| { - astgen.src_hasher.update(astgen.tree.getNodeSource(arg_node)); - } + astgen.src_hasher = .init(.{}); + var next_field_idx: u32 = 0; for (members) |member_node| { - var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { + var member = switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) { .decl => continue, .field => |field| field, }; + const field_idx = next_field_idx; + next_field_idx += 1; + astgen.src_hasher.update(astgen.tree.getNodeSource(member_node)); member.convertToNonTupleLike(astgen.tree); if (member.ast.tuple_like) { @@ -5355,97 +5284,91 @@ fn unionDeclInner( return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{}); } - const field_name = try astgen.identAsString(member.ast.main_token); - wip_members.appendToField(@intFromEnum(field_name)); + field_names.get(astgen)[field_idx] = @intFromEnum(try astgen.identAsString(member.ast.main_token)); - const have_type = member.ast.type_expr != .none; - const have_align = member.ast.align_expr != .none; - const have_value = member.ast.value_expr != .none; - const unused = false; - wip_members.nextField(bits_per_field, .{ have_type, have_align, have_value, unused }); - - if (member.ast.type_expr.unwrap()) |type_expr| { - const field_type = try typeExpr(&block_scope, &namespace.base, type_expr); - wip_members.appendToField(@intFromEnum(field_type)); - } else if (arg_inst == .none and auto_enum_tok == null) { + if (member.ast.type_expr.unwrap()) |type_node| { + const type_ref = try typeExpr(&block_scope, &namespace.base, type_node); + if (!block_scope.endsWithNoReturn()) { + _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref); + } + const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); + field_type_body_lens.get(astgen)[field_idx] = body_len; + block_scope.instructions.items.len = block_scope.instructions_top; + } else if (!is_tagged) { return astgen.failNode(member_node, "union field missing type", .{}); + } else { + field_type_body_lens.get(astgen)[field_idx] = 0; } - if (member.ast.align_expr.unwrap()) |align_expr| { + + if (member.ast.align_expr.unwrap()) |align_node| { if (layout == .@"packed") { - return astgen.failNode(align_expr, "unable to override alignment of packed union fields", .{}); + return astgen.failNode(align_node, "unable to override alignment of packed union fields", .{}); } - const align_inst = try expr(&block_scope, &block_scope.base, coerced_align_ri, align_expr); - wip_members.appendToField(@intFromEnum(align_inst)); - any_aligned_fields = true; + const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_node); + if (!block_scope.endsWithNoReturn()) { + _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref); + } + const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); + field_align_body_lens.?.get(astgen)[field_idx] = body_len; + block_scope.instructions.items.len = block_scope.instructions_top; + } else if (field_align_body_lens) |lens| { + lens.get(astgen)[field_idx] = 0; } - if (member.ast.value_expr.unwrap()) |value_expr| { - if (arg_inst == .none) { - return astgen.failNodeNotes( - node, - "explicitly valued tagged union missing integer tag type", - .{}, - &[_]u32{ - try astgen.errNoteNode( - value_expr, - "tag value specified here", - .{}, - ), - }, - ); + + if (member.ast.value_expr.unwrap()) |value_node| { + if (!explicit_int_or_enum_tag) return astgen.failNodeNotes( + node, + "explicitly valued tagged union missing integer tag type", + .{}, + &.{try astgen.errNoteNode(value_node, "tag value specified here", .{})}, + ); + if (auto_enum_tok == null) return astgen.failNodeNotes( + node, + "explicitly valued tagged union requires inferred enum tag type", + .{}, + &.{try astgen.errNoteNode(value_node, "tag value specified here", .{})}, + ); + const ri: ResultInfo = .{ .rl = .{ .coerced_ty = decl_inst.toRef() } }; + const value_ref = try expr(&block_scope, &namespace.base, ri, value_node); + if (!block_scope.endsWithNoReturn()) { + _ = try block_scope.addBreak(.break_inline, decl_inst, value_ref); } - if (auto_enum_tok == null) { - return astgen.failNodeNotes( - node, - "explicitly valued tagged union requires inferred enum tag type", - .{}, - &[_]u32{ - try astgen.errNoteNode( - value_expr, - "tag value specified here", - .{}, - ), - }, - ); - } - const tag_value = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = arg_inst } }, value_expr); - wip_members.appendToField(@intFromEnum(tag_value)); + const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); + field_value_body_lens.?.get(astgen)[field_idx] = body_len; + block_scope.instructions.items.len = block_scope.instructions_top; + } else if (field_value_body_lens) |lens| { + lens.get(astgen)[field_idx] = 0; } } + assert(next_field_idx == scan_result.fields_len); + wip_decls.finish(); var fields_hash: std.zig.SrcHash = undefined; astgen.src_hasher.final(&fields_hash); - if (!block_scope.isEmpty()) { - _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); - } - - const body = block_scope.instructionsSlice(); - const body_len = astgen.countBodyLenAfterFixups(body); - try gz.setUnion(decl_inst, .{ .src_node = node, - .layout = layout, - .tag_type = arg_inst, - .captures_len = @intCast(namespace.captures.count()), - .body_len = body_len, - .fields_len = field_count, - .decls_len = decl_count, - .auto_enum_tag = auto_enum_tok != null, - .any_aligned_fields = any_aligned_fields, - .fields_hash = fields_hash, .name_strat = name_strat, + .kind = switch (layout) { + .auto => if (auto_enum_tok == null) l: { + break :l if (opt_arg_node == .none) .auto else .tagged_explicit; + } else l: { + break :l if (opt_arg_node == .none) .tagged_enum else .tagged_enum_explicit; + }, + .@"extern" => .@"extern", + .@"packed" => if (opt_arg_node != .none) .packed_explicit else .@"packed", + }, + .arg_type = arg_type_ref, + .decls_len = scan_result.decls_len, + .fields_len = scan_result.fields_len, + .any_field_aligns = scan_result.any_field_aligns, + .any_field_values = scan_result.any_field_values, + .fields_hash = fields_hash, + .captures = namespace.captures.keys(), + .capture_names = namespace.captures.values(), + .remaining = scratch.all().get(astgen), }); - wip_members.finishBits(bits_per_field); - const decls_slice = wip_members.declsSlice(); - const fields_slice = wip_members.fieldsSlice(); - try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() * 2 + decls_slice.len + body_len + fields_slice.len); - astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); - astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.values())); - astgen.extra.appendSliceAssumeCapacity(decls_slice); - astgen.appendBodyWithFixups(body); - astgen.extra.appendSliceAssumeCapacity(fields_slice); - block_scope.unstack(); return decl_inst.toRef(); } @@ -5494,103 +5417,13 @@ fn containerDecl( if (container_decl.layout_token) |t| { return astgen.failTok(t, "enums do not support 'packed' or 'extern'; instead provide an explicit integer tag type", .{}); } - // Count total fields as well as how many have explicitly provided tag values. - const counts = blk: { - var values: usize = 0; - var total_fields: usize = 0; - var decls: usize = 0; - var opt_nonexhaustive_node: Ast.Node.OptionalIndex = .none; - var nonfinal_nonexhaustive = false; - for (container_decl.ast.members) |member_node| { - var member = tree.fullContainerField(member_node) orelse { - decls += 1; - continue; - }; - member.convertToNonTupleLike(astgen.tree); - if (member.ast.tuple_like) { - return astgen.failTok(member.ast.main_token, "enum field missing name", .{}); - } - if (member.comptime_token) |comptime_token| { - return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{}); - } - if (member.ast.type_expr.unwrap()) |type_expr| { - return astgen.failNodeNotes( - type_expr, - "enum fields do not have types", - .{}, - &[_]u32{ - try astgen.errNoteNode( - node, - "consider 'union(enum)' here to make it a tagged union", - .{}, - ), - }, - ); - } - if (member.ast.align_expr.unwrap()) |align_expr| { - return astgen.failNode(align_expr, "enum fields cannot be aligned", .{}); - } - const name_token = member.ast.main_token; - if (mem.eql(u8, tree.tokenSlice(name_token), "_")) { - if (opt_nonexhaustive_node.unwrap()) |nonexhaustive_node| { - return astgen.failNodeNotes( - member_node, - "redundant non-exhaustive enum mark", - .{}, - &[_]u32{ - try astgen.errNoteNode( - nonexhaustive_node, - "other mark here", - .{}, - ), - }, - ); - } - opt_nonexhaustive_node = member_node.toOptional(); - if (member.ast.value_expr.unwrap()) |value_expr| { - return astgen.failNode(value_expr, "'_' is used to mark an enum as non-exhaustive and cannot be assigned a value", .{}); - } - continue; - } else if (opt_nonexhaustive_node != .none) { - nonfinal_nonexhaustive = true; - } - total_fields += 1; - if (member.ast.value_expr.unwrap()) |value_expr| { - if (container_decl.ast.arg == .none) { - return astgen.failNode(value_expr, "value assigned to enum tag with inferred tag type", .{}); - } - values += 1; - } - } - if (nonfinal_nonexhaustive) { - return astgen.failNode(opt_nonexhaustive_node.unwrap().?, "'_' field of non-exhaustive enum must be last", .{}); - } - break :blk .{ - .total_fields = total_fields, - .values = values, - .decls = decls, - .nonexhaustive_node = opt_nonexhaustive_node, - }; + astgen.advanceSourceCursorToNode(node); + + const tag_type_ref: Zir.Inst.Ref = ref: { + const arg_node = container_decl.ast.arg.unwrap() orelse break :ref .none; + break :ref try typeExpr(gz, scope, arg_node); }; - if (counts.nonexhaustive_node != .none and container_decl.ast.arg == .none) { - const nonexhaustive_node = counts.nonexhaustive_node.unwrap().?; - return astgen.failNodeNotes( - node, - "non-exhaustive enum missing integer tag type", - .{}, - &[_]u32{ - try astgen.errNoteNode( - nonexhaustive_node, - "marked non-exhaustive here", - .{}, - ), - }, - ); - } - // In this case we must generate ZIR code for the tag values, similar to - // how structs are handled above. - const nonexhaustive = counts.nonexhaustive_node != .none; const decl_inst = try gz.reserveInstructionIndex(); @@ -5605,7 +5438,6 @@ fn containerDecl( // The enum_decl instruction introduces a scope in which the decls of the enum // are in scope, so that tag values can refer to decls within the enum itself. - astgen.advanceSourceCursorToNode(node); var block_scope: GenZir = .{ .parent = &namespace.base, .decl_node_index = node, @@ -5617,104 +5449,111 @@ fn containerDecl( }; defer block_scope.unstack(); - _ = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"enum"); - namespace.base.tag = .namespace; + const scan_result = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"enum"); + // The name `_` is not actually a field; it marks a non-exhaustive enum. + const fields_len: u32 = scan_result.fields_len - @intFromBool(scan_result.has_underscore_field); - const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg.unwrap()) |arg| - try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, arg, .type) - else - .none; + var scratch: Scratch = .init(astgen); + defer scratch.reset(); - const bits_per_field = 1; - const max_field_size = 2; - var wip_members = try WipMembers.init(gpa, &astgen.scratch, @intCast(counts.decls), @intCast(counts.total_fields), bits_per_field, max_field_size); - defer wip_members.deinit(); + // Replicate the structure of the ZIR trailing data in `scratch` + var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len); + const field_names = try scratch.addSlice(fields_len); + const field_value_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, fields_len); const old_hasher = astgen.src_hasher; defer astgen.src_hasher = old_hasher; - astgen.src_hasher = std.zig.SrcHasher.init(.{}); - if (container_decl.ast.arg.unwrap()) |arg| { - astgen.src_hasher.update(tree.getNodeSource(arg)); - } - astgen.src_hasher.update(&.{@intFromBool(nonexhaustive)}); + astgen.src_hasher = .init(.{}); + var next_field_idx: u32 = 0; + var opt_nonexhaustive_node: Ast.Node.OptionalIndex = .none; for (container_decl.ast.members) |member_node| { - if (member_node.toOptional() == counts.nonexhaustive_node) - continue; - astgen.src_hasher.update(tree.getNodeSource(member_node)); - var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { + var member = switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) { .decl => continue, .field => |field| field, }; member.convertToNonTupleLike(astgen.tree); - assert(member.comptime_token == null); - assert(member.ast.type_expr == .none); - assert(member.ast.align_expr == .none); + if (member.ast.tuple_like) return astgen.failTok(member.ast.main_token, "enum field missing name", .{}); + if (member.comptime_token) |t| return astgen.failTok(t, "enum fields cannot be marked comptime", .{}); + if (member.ast.type_expr.unwrap()) |type_node| { + return astgen.failNodeNotes(type_node, "enum fields do not have types", .{}, &.{ + try astgen.errNoteNode(node, "consider 'union(enum)' here to make it a tagged union", .{}), + }); + } + if (member.ast.align_expr.unwrap()) |n| return astgen.failNode(n, "enum fields cannot be aligned", .{}); + if (mem.eql(u8, tree.tokenSlice(member.ast.main_token), "_")) { + // non-exhaustive mark + assert(scan_result.has_underscore_field); + if (opt_nonexhaustive_node.unwrap()) |prev_node| { + return astgen.failNodeNotes(member_node, "redundant non-exhaustive enum mark", .{}, &.{ + try astgen.errNoteNode(prev_node, "other mark here", .{}), + }); + } + if (member.ast.value_expr.unwrap()) |value_node| { + return astgen.failNode(value_node, "'_' is used to mark an enum as non-exhaustive and cannot be assigned a value", .{}); + } + if (next_field_idx != fields_len) { + return astgen.failNode(member_node, "'_' field of non-exhaustive enum must be last", .{}); + } + opt_nonexhaustive_node = member_node.toOptional(); + continue; + } - const field_name = try astgen.identAsString(member.ast.main_token); - wip_members.appendToField(@intFromEnum(field_name)); + // This is a real field rather than a non-exhaustive mark. + const field_idx = next_field_idx; + next_field_idx += 1; - const have_value = member.ast.value_expr != .none; - wip_members.nextField(bits_per_field, .{have_value}); + astgen.src_hasher.update(tree.getNodeSource(member_node)); - if (member.ast.value_expr.unwrap()) |value_expr| { - if (arg_inst == .none) { - return astgen.failNodeNotes( - node, - "explicitly valued enum missing integer tag type", - .{}, - &[_]u32{ - try astgen.errNoteNode( - value_expr, - "tag value specified here", - .{}, - ), - }, - ); + field_names.get(astgen)[field_idx] = @intFromEnum(try astgen.identAsString(member.ast.main_token)); + + if (member.ast.value_expr.unwrap()) |value_node| { + if (tag_type_ref == .none) { + return astgen.failNodeNotes(node, "explicitly valued enum missing integer tag type", .{}, &.{ + try astgen.errNoteNode(value_node, "tag value specified here", .{}), + }); + } + const val_ri: ResultInfo = .{ .rl = .{ .coerced_ty = decl_inst.toRef() } }; + const value_ref = try expr(&block_scope, &namespace.base, val_ri, value_node); + if (!block_scope.endsWithNoReturn()) { + _ = try block_scope.addBreak(.break_inline, decl_inst, value_ref); } - const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, value_expr); - wip_members.appendToField(@intFromEnum(tag_value_inst)); + const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); + field_value_body_lens.?.get(astgen)[field_idx] = body_len; + block_scope.instructions.items.len = block_scope.instructions_top; + } else if (field_value_body_lens) |lens| { + lens.get(astgen)[field_idx] = 0; } } - - if (!block_scope.isEmpty()) { - _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); - } + assert(scan_result.has_underscore_field == (opt_nonexhaustive_node != .none)); + assert(next_field_idx == fields_len); + wip_decls.finish(); var fields_hash: std.zig.SrcHash = undefined; astgen.src_hasher.final(&fields_hash); - const body = block_scope.instructionsSlice(); - const body_len = astgen.countBodyLenAfterFixups(body); - try gz.setEnum(decl_inst, .{ .src_node = node, - .nonexhaustive = nonexhaustive, - .tag_type = arg_inst, - .captures_len = @intCast(namespace.captures.count()), - .body_len = body_len, - .fields_len = @intCast(counts.total_fields), - .decls_len = @intCast(counts.decls), + .name_strat = name_strat, + .tag_type = tag_type_ref, + .nonexhaustive = scan_result.has_underscore_field, + .decls_len = scan_result.decls_len, + .fields_len = fields_len, + .any_field_values = scan_result.any_field_values, .fields_hash = fields_hash, - .name_strat = name_strat, + .captures = namespace.captures.keys(), + .capture_names = namespace.captures.values(), + .remaining = scratch.all().get(astgen), }); - wip_members.finishBits(bits_per_field); - const decls_slice = wip_members.declsSlice(); - const fields_slice = wip_members.fieldsSlice(); - try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() * 2 + decls_slice.len + body_len + fields_slice.len); - astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); - astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.values())); - astgen.extra.appendSliceAssumeCapacity(decls_slice); - astgen.appendBodyWithFixups(body); - astgen.extra.appendSliceAssumeCapacity(fields_slice); - block_scope.unstack(); return rvalue(gz, ri, decl_inst.toRef(), node); }, .keyword_opaque => { assert(container_decl.ast.arg == .none); + astgen.advanceSourceCursorToNode(node); + const decl_inst = try gz.reserveInstructionIndex(); var namespace: Scope.Namespace = .{ @@ -5726,7 +5565,6 @@ fn containerDecl( }; defer namespace.deinit(gpa); - astgen.advanceSourceCursorToNode(node); var block_scope: GenZir = .{ .parent = &namespace.base, .decl_node_index = node, @@ -5738,36 +5576,34 @@ fn containerDecl( }; defer block_scope.unstack(); - const decl_count = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"opaque"); + const scan_result = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"opaque"); - var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, 0, 0, 0); - defer wip_members.deinit(); + var scratch: Scratch = .init(astgen); + defer scratch.reset(); + var wip_decls: WipDecls = try .init(&scratch, scan_result.decls_len); if (container_decl.layout_token) |layout_token| { return astgen.failTok(layout_token, "opaque types do not support 'packed' or 'extern'", .{}); } for (container_decl.ast.members) |member_node| { - const res = try containerMember(&block_scope, &namespace.base, &wip_members, member_node); - if (res == .field) { - return astgen.failNode(member_node, "opaque types cannot have fields", .{}); + switch (try containerMember(&block_scope, &namespace.base, &wip_decls, member_node)) { + .decl => {}, + .field => return astgen.failNode(member_node, "opaque types cannot have fields", .{}), } } + wip_decls.finish(); + try gz.setOpaque(decl_inst, .{ .src_node = node, - .captures_len = @intCast(namespace.captures.count()), - .decls_len = decl_count, .name_strat = name_strat, + .decls_len = scan_result.decls_len, + .captures = namespace.captures.keys(), + .capture_names = namespace.captures.values(), + .decls = @ptrCast(scratch.all().get(astgen)), }); - wip_members.finishBits(0); - const decls_slice = wip_members.declsSlice(); - try astgen.extra.ensureUnusedCapacity(gpa, namespace.captures.count() * 2 + decls_slice.len); - astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.keys())); - astgen.extra.appendSliceAssumeCapacity(@ptrCast(namespace.captures.values())); - astgen.extra.appendSliceAssumeCapacity(decls_slice); - block_scope.unstack(); return rvalue(gz, ri, decl_inst.toRef(), node); }, @@ -5780,7 +5616,7 @@ const ContainerMemberResult = union(enum) { decl, field: Ast.full.ContainerField fn containerMember( gz: *GenZir, scope: *Scope, - wip_members: *WipMembers, + wip_decls: *WipDecls, member_node: Ast.Node.Index, ) InnerError!ContainerMemberResult { const astgen = gz.astgen; @@ -5805,13 +5641,13 @@ fn containerMember( else .none; - const prev_decl_index = wip_members.decl_index; - astgen.fnDecl(gz, scope, wip_members, member_node, body, full) catch |err| switch (err) { + const prev_decl_index = wip_decls.index; + astgen.fnDecl(gz, scope, wip_decls, member_node, body, full) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.AnalysisFail => { - wip_members.decl_index = prev_decl_index; + wip_decls.index = prev_decl_index; try addFailedDeclaration( - wip_members, + wip_decls, gz, .@"const", try astgen.identAsString(full.name_token.?), @@ -5828,13 +5664,13 @@ fn containerMember( .aligned_var_decl, => { const full = tree.fullVarDecl(member_node).?; - const prev_decl_index = wip_members.decl_index; - astgen.globalVarDecl(gz, scope, wip_members, member_node, full) catch |err| switch (err) { + const prev_decl_index = wip_decls.index; + astgen.globalVarDecl(gz, scope, wip_decls, member_node, full) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.AnalysisFail => { - wip_members.decl_index = prev_decl_index; + wip_decls.index = prev_decl_index; try addFailedDeclaration( - wip_members, + wip_decls, gz, .@"const", // doesn't really matter try astgen.identAsString(full.ast.mut_token + 1), @@ -5846,13 +5682,13 @@ fn containerMember( }, .@"comptime" => { - const prev_decl_index = wip_members.decl_index; - astgen.comptimeDecl(gz, scope, wip_members, member_node) catch |err| switch (err) { + const prev_decl_index = wip_decls.index; + astgen.comptimeDecl(gz, scope, wip_decls, member_node) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.AnalysisFail => { - wip_members.decl_index = prev_decl_index; + wip_decls.index = prev_decl_index; try addFailedDeclaration( - wip_members, + wip_decls, gz, .@"comptime", .empty, @@ -5863,16 +5699,16 @@ fn containerMember( }; }, .test_decl => { - const prev_decl_index = wip_members.decl_index; + const prev_decl_index = wip_decls.index; // We need to have *some* decl here so that the decl count matches what's expected. // Since it doesn't strictly matter *what* this is, let's save ourselves the trouble // of duplicating the test name logic, and just assume this is an unnamed test. - astgen.testDecl(gz, scope, wip_members, member_node) catch |err| switch (err) { + astgen.testDecl(gz, scope, wip_decls, member_node) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.AnalysisFail => { - wip_members.decl_index = prev_decl_index; + wip_decls.index = prev_decl_index; try addFailedDeclaration( - wip_members, + wip_decls, gz, .unnamed_test, .empty, @@ -10619,482 +10455,6 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev } } -/// Returns `true` if it is known the type expression has more than one possible value; -/// `false` otherwise. -fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.Index) bool { - var node = start_node; - while (true) { - switch (tree.nodeTag(node)) { - .root, - .test_decl, - .switch_case, - .switch_case_inline, - .switch_case_one, - .switch_case_inline_one, - .container_field_init, - .container_field_align, - .container_field, - .asm_output, - .asm_input, - .global_var_decl, - .local_var_decl, - .simple_var_decl, - .aligned_var_decl, - => unreachable, - - .@"return", - .@"break", - .@"continue", - .bit_not, - .bool_not, - .@"defer", - .@"errdefer", - .address_of, - .negation, - .negation_wrap, - .@"resume", - .array_type, - .@"suspend", - .fn_decl, - .anyframe_literal, - .number_literal, - .enum_literal, - .string_literal, - .multiline_string_literal, - .char_literal, - .unreachable_literal, - .error_set_decl, - .container_decl, - .container_decl_trailing, - .container_decl_two, - .container_decl_two_trailing, - .container_decl_arg, - .container_decl_arg_trailing, - .tagged_union, - .tagged_union_trailing, - .tagged_union_two, - .tagged_union_two_trailing, - .tagged_union_enum_tag, - .tagged_union_enum_tag_trailing, - .@"asm", - .asm_simple, - .add, - .add_wrap, - .add_sat, - .array_cat, - .array_mult, - .assign, - .assign_destructure, - .assign_bit_and, - .assign_bit_or, - .assign_shl, - .assign_shl_sat, - .assign_shr, - .assign_bit_xor, - .assign_div, - .assign_sub, - .assign_sub_wrap, - .assign_sub_sat, - .assign_mod, - .assign_add, - .assign_add_wrap, - .assign_add_sat, - .assign_mul, - .assign_mul_wrap, - .assign_mul_sat, - .bang_equal, - .bit_and, - .bit_or, - .shl, - .shl_sat, - .shr, - .bit_xor, - .bool_and, - .bool_or, - .div, - .equal_equal, - .error_union, - .greater_or_equal, - .greater_than, - .less_or_equal, - .less_than, - .merge_error_sets, - .mod, - .mul, - .mul_wrap, - .mul_sat, - .switch_range, - .for_range, - .field_access, - .sub, - .sub_wrap, - .sub_sat, - .slice, - .slice_open, - .slice_sentinel, - .deref, - .array_access, - .error_value, - .while_simple, - .while_cont, - .for_simple, - .if_simple, - .@"catch", - .@"orelse", - .array_init_one, - .array_init_one_comma, - .array_init_dot_two, - .array_init_dot_two_comma, - .array_init_dot, - .array_init_dot_comma, - .array_init, - .array_init_comma, - .struct_init_one, - .struct_init_one_comma, - .struct_init_dot_two, - .struct_init_dot_two_comma, - .struct_init_dot, - .struct_init_dot_comma, - .struct_init, - .struct_init_comma, - .@"while", - .@"if", - .@"for", - .@"switch", - .switch_comma, - .call_one, - .call_one_comma, - .call, - .call_comma, - .block_two, - .block_two_semicolon, - .block, - .block_semicolon, - .builtin_call, - .builtin_call_comma, - .builtin_call_two, - .builtin_call_two_comma, - // these are function bodies, not pointers - .fn_proto_simple, - .fn_proto_multi, - .fn_proto_one, - .fn_proto, - => return false, - - // Forward the question to the LHS sub-expression. - .@"try", - .@"comptime", - .@"nosuspend", - => node = tree.nodeData(node).node, - .grouped_expression, - .unwrap_optional, - => node = tree.nodeData(node).node_and_token[0], - - .ptr_type_aligned, - .ptr_type_sentinel, - .ptr_type, - .ptr_type_bit_range, - .optional_type, - .anyframe_type, - .array_type_sentinel, - => return true, - - .identifier => { - const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node)); - if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) { - .anyerror_type, - .anyframe_type, - .anyopaque_type, - .bool_type, - .c_int_type, - .c_long_type, - .c_longdouble_type, - .c_longlong_type, - .c_char_type, - .c_short_type, - .c_uint_type, - .c_ulong_type, - .c_ulonglong_type, - .c_ushort_type, - .comptime_float_type, - .comptime_int_type, - .f16_type, - .f32_type, - .f64_type, - .f80_type, - .f128_type, - .i16_type, - .i32_type, - .i64_type, - .i128_type, - .i8_type, - .isize_type, - .type_type, - .u16_type, - .u29_type, - .u32_type, - .u64_type, - .u128_type, - .u1_type, - .u8_type, - .usize_type, - => return true, - - .void_type, - .bool_false, - .bool_true, - .null_value, - .undef, - .noreturn_type, - => return false, - - else => unreachable, // that's all the values from `primitives`. - } else { - return false; - } - }, - } - } -} - -/// Returns `true` if it is known the expression is a type that cannot be used at runtime; -/// `false` otherwise. -fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool { - var node = start_node; - while (true) { - switch (tree.nodeTag(node)) { - .root, - .test_decl, - .switch_case, - .switch_case_inline, - .switch_case_one, - .switch_case_inline_one, - .container_field_init, - .container_field_align, - .container_field, - .asm_output, - .asm_input, - .global_var_decl, - .local_var_decl, - .simple_var_decl, - .aligned_var_decl, - => unreachable, - - .@"return", - .@"break", - .@"continue", - .bit_not, - .bool_not, - .@"defer", - .@"errdefer", - .address_of, - .negation, - .negation_wrap, - .@"resume", - .array_type, - .@"suspend", - .fn_decl, - .anyframe_literal, - .number_literal, - .enum_literal, - .string_literal, - .multiline_string_literal, - .char_literal, - .unreachable_literal, - .error_set_decl, - .container_decl, - .container_decl_trailing, - .container_decl_two, - .container_decl_two_trailing, - .container_decl_arg, - .container_decl_arg_trailing, - .tagged_union, - .tagged_union_trailing, - .tagged_union_two, - .tagged_union_two_trailing, - .tagged_union_enum_tag, - .tagged_union_enum_tag_trailing, - .@"asm", - .asm_simple, - .add, - .add_wrap, - .add_sat, - .array_cat, - .array_mult, - .assign, - .assign_destructure, - .assign_bit_and, - .assign_bit_or, - .assign_shl, - .assign_shl_sat, - .assign_shr, - .assign_bit_xor, - .assign_div, - .assign_sub, - .assign_sub_wrap, - .assign_sub_sat, - .assign_mod, - .assign_add, - .assign_add_wrap, - .assign_add_sat, - .assign_mul, - .assign_mul_wrap, - .assign_mul_sat, - .bang_equal, - .bit_and, - .bit_or, - .shl, - .shl_sat, - .shr, - .bit_xor, - .bool_and, - .bool_or, - .div, - .equal_equal, - .error_union, - .greater_or_equal, - .greater_than, - .less_or_equal, - .less_than, - .merge_error_sets, - .mod, - .mul, - .mul_wrap, - .mul_sat, - .switch_range, - .for_range, - .field_access, - .sub, - .sub_wrap, - .sub_sat, - .slice, - .slice_open, - .slice_sentinel, - .deref, - .array_access, - .error_value, - .while_simple, - .while_cont, - .for_simple, - .if_simple, - .@"catch", - .@"orelse", - .array_init_one, - .array_init_one_comma, - .array_init_dot_two, - .array_init_dot_two_comma, - .array_init_dot, - .array_init_dot_comma, - .array_init, - .array_init_comma, - .struct_init_one, - .struct_init_one_comma, - .struct_init_dot_two, - .struct_init_dot_two_comma, - .struct_init_dot, - .struct_init_dot_comma, - .struct_init, - .struct_init_comma, - .@"while", - .@"if", - .@"for", - .@"switch", - .switch_comma, - .call_one, - .call_one_comma, - .call, - .call_comma, - .block_two, - .block_two_semicolon, - .block, - .block_semicolon, - .builtin_call, - .builtin_call_comma, - .builtin_call_two, - .builtin_call_two_comma, - .ptr_type_aligned, - .ptr_type_sentinel, - .ptr_type, - .ptr_type_bit_range, - .optional_type, - .anyframe_type, - .array_type_sentinel, - => return false, - - // these are function bodies, not pointers - .fn_proto_simple, - .fn_proto_multi, - .fn_proto_one, - .fn_proto, - => return true, - - // Forward the question to the LHS sub-expression. - .@"try", - .@"comptime", - .@"nosuspend", - => node = tree.nodeData(node).node, - .grouped_expression, - .unwrap_optional, - => node = tree.nodeData(node).node_and_token[0], - - .identifier => { - const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node)); - if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) { - .anyerror_type, - .anyframe_type, - .anyopaque_type, - .bool_type, - .c_int_type, - .c_long_type, - .c_longdouble_type, - .c_longlong_type, - .c_char_type, - .c_short_type, - .c_uint_type, - .c_ulong_type, - .c_ulonglong_type, - .c_ushort_type, - .f16_type, - .f32_type, - .f64_type, - .f80_type, - .f128_type, - .i16_type, - .i32_type, - .i64_type, - .i128_type, - .i8_type, - .isize_type, - .u16_type, - .u29_type, - .u32_type, - .u64_type, - .u128_type, - .u1_type, - .u8_type, - .usize_type, - .void_type, - .bool_false, - .bool_true, - .null_value, - .undef, - .noreturn_type, - => return false, - - .comptime_float_type, - .comptime_int_type, - .type_type, - => return true, - - else => unreachable, // that's all the values from `primitives`. - } else { - return false; - } - }, - } - } -} - /// Applies `rl` semantics to `result`. Expressions which do not do their own handling of /// result locations must call this function on their result. /// As an example, if `ri.rl` is `.ptr`, it will write the result to the pointer. @@ -13044,18 +12404,19 @@ const GenZir = struct { fn setStruct(gz: *GenZir, inst: Zir.Inst.Index, args: struct { src_node: Ast.Node.Index, - captures_len: u32, - fields_len: u32, - decls_len: u32, - has_backing_int: bool, + name_strat: Zir.Inst.NameStrategy, layout: std.builtin.Type.ContainerLayout, - known_non_opv: bool, - known_comptime_only: bool, + backing_int_type: Zir.Inst.Ref, + decls_len: u32, + fields_len: u32, + any_field_aligns: bool, + any_field_defaults: bool, any_comptime_fields: bool, - any_default_inits: bool, - any_aligned_fields: bool, fields_hash: std.zig.SrcHash, - name_strat: Zir.Inst.NameStrategy, + captures: []const Zir.Inst.Capture, + capture_names: []const Zir.NullTerminatedString, + /// The trailing declaration list, field information, and body instructions. + remaining: []const u32, }) !void { const astgen = gz.astgen; const gpa = astgen.gpa; @@ -13063,9 +12424,16 @@ const GenZir = struct { // Node .root is valid for the root `struct_decl` of a file! assert(args.src_node != .root or gz.parent.tag == .top); + const captures_len: u32 = @intCast(args.captures.len); + assert(args.capture_names.len == captures_len); + const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); - try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len + 3); + try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len + + 4 + // `captures_len`, `decls_len`, `fields_len`, `backing_int_type` + captures_len * 2 + // `capture`, `capture_name` + args.remaining.len); + const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.StructDecl{ .fields_hash_0 = fields_hash_arr[0], .fields_hash_1 = fields_hash_arr[1], @@ -13075,31 +12443,28 @@ const GenZir = struct { .src_node = args.src_node, }); - if (args.captures_len != 0) { - astgen.extra.appendAssumeCapacity(args.captures_len); - } - if (args.fields_len != 0) { - astgen.extra.appendAssumeCapacity(args.fields_len); - } - if (args.decls_len != 0) { - astgen.extra.appendAssumeCapacity(args.decls_len); - } + if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len); + if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len); + if (args.fields_len != 0) astgen.extra.appendAssumeCapacity(args.fields_len); + if (args.backing_int_type != .none) astgen.extra.appendAssumeCapacity(@intFromEnum(args.backing_int_type)); + astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures)); + astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names)); + astgen.extra.appendSliceAssumeCapacity(args.remaining); + astgen.instructions.set(@intFromEnum(inst), .{ .tag = .extended, .data = .{ .extended = .{ .opcode = .struct_decl, .small = @bitCast(Zir.Inst.StructDecl.Small{ - .has_captures_len = args.captures_len != 0, - .has_fields_len = args.fields_len != 0, + .has_captures_len = captures_len != 0, .has_decls_len = args.decls_len != 0, - .has_backing_int = args.has_backing_int, - .known_non_opv = args.known_non_opv, - .known_comptime_only = args.known_comptime_only, + .has_fields_len = args.fields_len != 0, .name_strategy = args.name_strat, .layout = args.layout, + .has_backing_int_type = args.backing_int_type != .none, + .any_field_aligns = args.any_field_aligns, + .any_field_defaults = args.any_field_defaults, .any_comptime_fields = args.any_comptime_fields, - .any_default_inits = args.any_default_inits, - .any_aligned_fields = args.any_aligned_fields, }), .operand = payload_index, } }, @@ -13108,25 +12473,34 @@ const GenZir = struct { fn setUnion(gz: *GenZir, inst: Zir.Inst.Index, args: struct { src_node: Ast.Node.Index, - tag_type: Zir.Inst.Ref, - captures_len: u32, - body_len: u32, - fields_len: u32, + name_strat: Zir.Inst.NameStrategy, + kind: Zir.Inst.UnionDecl.Kind, + arg_type: Zir.Inst.Ref, decls_len: u32, - layout: std.builtin.Type.ContainerLayout, - auto_enum_tag: bool, - any_aligned_fields: bool, + fields_len: u32, + any_field_aligns: bool, + any_field_values: bool, fields_hash: std.zig.SrcHash, - name_strat: Zir.Inst.NameStrategy, + captures: []const Zir.Inst.Capture, + capture_names: []const Zir.NullTerminatedString, + /// The trailing declaration list, field information, and body instructions. + remaining: []const u32, }) !void { const astgen = gz.astgen; const gpa = astgen.gpa; assert(args.src_node != .root); + const captures_len: u32 = @intCast(args.captures.len); + assert(args.capture_names.len == captures_len); + const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); - try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.UnionDecl).@"struct".fields.len + 5); + try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.UnionDecl).@"struct".fields.len + + 4 + // `captures_len`, `decls_len`, `fields_len`, `backing_int_type` + captures_len * 2 + // `capture`, `capture_name` + args.remaining.len); + const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.UnionDecl{ .fields_hash_0 = fields_hash_arr[0], .fields_hash_1 = fields_hash_arr[1], @@ -13136,60 +12510,68 @@ const GenZir = struct { .src_node = args.src_node, }); - if (args.tag_type != .none) { - astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); - } - if (args.captures_len != 0) { - astgen.extra.appendAssumeCapacity(args.captures_len); - } - if (args.body_len != 0) { - astgen.extra.appendAssumeCapacity(args.body_len); - } - if (args.fields_len != 0) { - astgen.extra.appendAssumeCapacity(args.fields_len); - } - if (args.decls_len != 0) { - astgen.extra.appendAssumeCapacity(args.decls_len); - } + if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len); + if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len); + if (args.fields_len != 0) astgen.extra.appendAssumeCapacity(args.fields_len); + if (args.kind.hasArgType()) { + assert(args.arg_type != .none); + astgen.extra.appendAssumeCapacity(@intFromEnum(args.arg_type)); + } else { + assert(args.arg_type == .none); + } + astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures)); + astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names)); + astgen.extra.appendSliceAssumeCapacity(args.remaining); + astgen.instructions.set(@intFromEnum(inst), .{ .tag = .extended, - .data = .{ .extended = .{ - .opcode = .union_decl, - .small = @bitCast(Zir.Inst.UnionDecl.Small{ - .has_tag_type = args.tag_type != .none, - .has_captures_len = args.captures_len != 0, - .has_body_len = args.body_len != 0, - .has_fields_len = args.fields_len != 0, - .has_decls_len = args.decls_len != 0, - .name_strategy = args.name_strat, - .layout = args.layout, - .auto_enum_tag = args.auto_enum_tag, - .any_aligned_fields = args.any_aligned_fields, - }), - .operand = payload_index, - } }, + .data = .{ + .extended = .{ + .opcode = .union_decl, + .small = @bitCast(Zir.Inst.UnionDecl.Small{ + .has_captures_len = captures_len != 0, + .has_decls_len = args.decls_len != 0, + .has_fields_len = args.fields_len != 0, + .name_strategy = args.name_strat, + .kind = args.kind, + .any_field_aligns = args.any_field_aligns, + .any_field_values = args.any_field_values, + }), + .operand = payload_index, + }, + }, }); } fn setEnum(gz: *GenZir, inst: Zir.Inst.Index, args: struct { src_node: Ast.Node.Index, + name_strat: Zir.Inst.NameStrategy, tag_type: Zir.Inst.Ref, - captures_len: u32, - body_len: u32, - fields_len: u32, - decls_len: u32, nonexhaustive: bool, + decls_len: u32, + fields_len: u32, + any_field_values: bool, fields_hash: std.zig.SrcHash, - name_strat: Zir.Inst.NameStrategy, + captures: []const Zir.Inst.Capture, + capture_names: []const Zir.NullTerminatedString, + /// The trailing declaration list, field information, and body instructions. + remaining: []const u32, }) !void { const astgen = gz.astgen; const gpa = astgen.gpa; assert(args.src_node != .root); + const captures_len: u32 = @intCast(args.captures.len); + assert(args.capture_names.len == captures_len); + const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); - try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).@"struct".fields.len + 5); + try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).@"struct".fields.len + + 4 + // `captures_len`, `decls_len`, `fields_len`, `tag_type` + captures_len * 2 + // `capture`, `capture_name` + args.remaining.len); + const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{ .fields_hash_0 = fields_hash_arr[0], .fields_hash_1 = fields_hash_arr[1], @@ -13199,33 +12581,26 @@ const GenZir = struct { .src_node = args.src_node, }); - if (args.tag_type != .none) { - astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); - } - if (args.captures_len != 0) { - astgen.extra.appendAssumeCapacity(args.captures_len); - } - if (args.body_len != 0) { - astgen.extra.appendAssumeCapacity(args.body_len); - } - if (args.fields_len != 0) { - astgen.extra.appendAssumeCapacity(args.fields_len); - } - if (args.decls_len != 0) { - astgen.extra.appendAssumeCapacity(args.decls_len); - } + if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len); + if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len); + if (args.fields_len != 0) astgen.extra.appendAssumeCapacity(args.fields_len); + if (args.tag_type != .none) astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); + astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures)); + astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names)); + astgen.extra.appendSliceAssumeCapacity(args.remaining); + astgen.instructions.set(@intFromEnum(inst), .{ .tag = .extended, .data = .{ .extended = .{ .opcode = .enum_decl, .small = @bitCast(Zir.Inst.EnumDecl.Small{ - .has_tag_type = args.tag_type != .none, - .has_captures_len = args.captures_len != 0, - .has_body_len = args.body_len != 0, - .has_fields_len = args.fields_len != 0, + .has_captures_len = captures_len != 0, .has_decls_len = args.decls_len != 0, + .has_fields_len = args.fields_len != 0, .name_strategy = args.name_strat, + .has_tag_type = args.tag_type != .none, .nonexhaustive = args.nonexhaustive, + .any_field_values = args.any_field_values, }), .operand = payload_index, } }, @@ -13234,33 +12609,41 @@ const GenZir = struct { fn setOpaque(gz: *GenZir, inst: Zir.Inst.Index, args: struct { src_node: Ast.Node.Index, - captures_len: u32, - decls_len: u32, name_strat: Zir.Inst.NameStrategy, + decls_len: u32, + captures: []const Zir.Inst.Capture, + capture_names: []const Zir.NullTerminatedString, + decls: []const Zir.Inst.Index, }) !void { const astgen = gz.astgen; const gpa = astgen.gpa; assert(args.src_node != .root); - try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).@"struct".fields.len + 2); + const captures_len: u32 = @intCast(args.captures.len); + assert(args.capture_names.len == captures_len); + + try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).@"struct".fields.len + + 2 + // `captures_len`, `decls_len` + captures_len * 2 + // `capture`, `capture_name` + args.decls.len); + const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{ .src_line = astgen.source_line, .src_node = args.src_node, }); + if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len); + if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len); + astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures)); + astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names)); + astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.decls)); - if (args.captures_len != 0) { - astgen.extra.appendAssumeCapacity(args.captures_len); - } - if (args.decls_len != 0) { - astgen.extra.appendAssumeCapacity(args.decls_len); - } astgen.instructions.set(@intFromEnum(inst), .{ .tag = .extended, .data = .{ .extended = .{ .opcode = .opaque_decl, .small = @bitCast(Zir.Inst.OpaqueDecl.Small{ - .has_captures_len = args.captures_len != 0, + .has_captures_len = captures_len != 0, .has_decls_len = args.decls_len != 0, .name_strategy = args.name_strat, }), @@ -13484,14 +12867,24 @@ fn restoreSourceCursor(astgen: *AstGen, cursor: SourceCursor) void { astgen.source_column = cursor.column; } +const ScanContainerResult = struct { + /// Includes unnamed declarations (e.g. `comptime` decls) + decls_len: u32, + fields_len: u32, + any_field_aligns: bool, + any_field_values: bool, + any_comptime_fields: bool, + /// Whether there is a field named `_` (indicating a non-exhaustive enum) + has_underscore_field: bool, +}; + /// Detects name conflicts for decls and fields, and populates `namespace.decls` with all named declarations. -/// Returns the number of declarations in the namespace, including unnamed declarations (e.g. `comptime` decls). fn scanContainer( astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.Node.Index, container_kind: enum { @"struct", @"union", @"enum", @"opaque" }, -) !u32 { +) !ScanContainerResult { const gpa = astgen.gpa; const tree = astgen.tree; @@ -13521,6 +12914,10 @@ fn scanContainer( var any_duplicates = false; var decl_count: u32 = 0; + var any_field_aligns = false; + var any_field_values = false; + var any_comptime_fields = false; + var has_underscore_field = false; for (members) |member_node| { const Kind = enum { decl, field }; const kind: Kind, const name_token = switch (tree.nodeTag(member_node)) { @@ -13533,6 +12930,10 @@ fn scanContainer( .@"struct", .@"opaque" => {}, .@"union", .@"enum" => full.convertToNonTupleLike(astgen.tree), } + if (full.ast.align_expr != .none) any_field_aligns = true; + if (full.ast.value_expr != .none) any_field_values = true; + if (full.comptime_token != null) any_comptime_fields = true; + if (mem.eql(u8, tree.tokenSlice(full.ast.main_token), "_")) has_underscore_field = true; if (full.ast.tuple_like) continue; break :blk .{ .field, full.ast.main_token }; }, @@ -13698,7 +13099,14 @@ fn scanContainer( if (!any_duplicates) { if (any_invalid_declarations) return error.AnalysisFail; - return decl_count; + return .{ + .decls_len = decl_count, + .fields_len = @intCast(members.len - decl_count), + .any_field_aligns = any_field_aligns, + .any_field_values = any_field_values, + .any_comptime_fields = any_comptime_fields, + .has_underscore_field = has_underscore_field, + }; } for (names.keys(), names.values()) |name, first| { @@ -13954,7 +13362,7 @@ const DeclarationName = union(enum) { }; fn addFailedDeclaration( - wip_members: *WipMembers, + wip_decls: *WipDecls, gz: *GenZir, kind: Zir.Inst.Declaration.Unwrapped.Kind, name: Zir.NullTerminatedString, @@ -13962,7 +13370,7 @@ fn addFailedDeclaration( is_pub: bool, ) !void { const decl_inst = try gz.makeDeclaration(src_node); - wip_members.nextDecl(decl_inst); + wip_decls.nextDecl(decl_inst); var dummy_gz = gz.makeSubBlock(&gz.base); diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index 0e76f4ff5bf792d033ee6af276b90663742f06bf..165f37edfad0452651ffc51565e1383b67c41a63 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -2443,7 +2443,7 @@ pub const Inst = struct { has_align: bool, has_addrspace: bool, has_bit_range: bool, - _: u1 = undefined, + _: u1 = 0, }, size: std.builtin.Type.Pointer.Size, /// Index into extra. See `PtrType`. @@ -2668,7 +2668,7 @@ pub const Inst = struct { has_ret_ty_body: bool, has_any_noalias: bool, ret_ty_is_generic: bool, - _: u23 = undefined, + _: u23 = 0, }; }; @@ -3134,7 +3134,7 @@ pub const Inst = struct { pub const Flags = packed struct { is_nosuspend: bool, ensure_result_used: bool, - _: u30 = undefined, + _: u30 = 0, comptime { if (@sizeOf(Flags) != 4 or @bitSizeOf(Flags) != 32) @@ -3462,33 +3462,20 @@ pub const Inst = struct { }; /// Trailing: - /// 0. captures_len: u32 // if has_captures_len - /// 1. fields_len: u32, // if has_fields_len - /// 2. decls_len: u32, // if has_decls_len - /// 3. capture: Capture // for every captures_len - /// 4. capture_name: NullTerminatedString // for every captures_len - /// 5. backing_int_body_len: u32, // if has_backing_int - /// 6. backing_int_ref: Ref, // if has_backing_int and backing_int_body_len is 0 - /// 7. backing_int_body_inst: Inst, // if has_backing_int and backing_int_body_len is > 0 - /// 8. decl: Index, // for every decls_len; points to a `declaration` instruction - /// 9. flags: u32 // for every 8 fields - /// - sets of 4 bits: - /// 0b000X: whether corresponding field has an align expression - /// 0b00X0: whether corresponding field has a default expression - /// 0b0X00: whether corresponding field is comptime - /// 0bX000: whether corresponding field has a type expression - /// 10. fields: { // for every fields_len - /// field_name: u32, - /// field_type: Ref, // if corresponding bit is not set. none means anytype. - /// field_type_body_len: u32, // if corresponding bit is set - /// align_body_len: u32, // if corresponding bit is set - /// init_body_len: u32, // if corresponding bit is set - /// } - /// 11. bodies: { // for every fields_len - /// field_type_body_inst: Inst, // for each field_type_body_len - /// align_body_inst: Inst, // for each align_body_len - /// init_body_inst: Inst, // for each init_body_len - /// } + /// 0. captures_len: u32 // if `has_captures_len` + /// 1. decls_len: u32, // if `has_decls_len` + /// 2. fields_len: u32, // if `has_fields_len` + /// 3. backing_int_type: Ref // if `has_backing_int` + /// 4. capture: Capture // for every `captures_len` + /// 5. capture_name: NullTerminatedString // for every `captures_len` + /// 6. decl: Index, // for every `decls_len`; points to a `declaration` instruction + /// 7. field_name: NullTerminatedString // for every `fields_len` + /// 8. field_type_body_len: u32 // for every `fields_len` + /// 9. field_align_body_len: u32 // for every `fields_len` if `any_field_aligns` + /// 10. field_default_body_len: u32 // for every `fields_len` if `any_field_defaults` + /// 11. field_comptime_bits: u32 // one bit per `fields_len` if `any_comptime_fields` + /// // LSB is first field, minimum number of `u32` needed + /// 12. body_inst: Inst.Index // type body, then align body, then default body, for each field pub const StructDecl = struct { // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`. // This hash contains the source of all fields, and any specified attributes (`extern`, backing type, etc). @@ -3500,19 +3487,18 @@ pub const Inst = struct { /// This node provides a new absolute baseline node for all instructions within this struct. src_node: Ast.Node.Index, - pub const Small = packed struct { + pub const Small = packed struct(u16) { has_captures_len: bool, - has_fields_len: bool, has_decls_len: bool, - has_backing_int: bool, - known_non_opv: bool, - known_comptime_only: bool, + has_fields_len: bool, name_strategy: NameStrategy, layout: std.builtin.Type.ContainerLayout, - any_default_inits: bool, + /// Always `false` if `layout != .@"packed"`. + has_backing_int_type: bool, + any_field_aligns: bool, + any_field_defaults: bool, any_comptime_fields: bool, - any_aligned_fields: bool, - _: u3 = undefined, + _: u5 = 0, }; }; @@ -3633,21 +3619,16 @@ pub const Inst = struct { }; /// Trailing: - /// 0. tag_type: Ref, // if has_tag_type - /// 1. captures_len: u32, // if has_captures_len - /// 2. body_len: u32, // if has_body_len - /// 3. fields_len: u32, // if has_fields_len - /// 4. decls_len: u32, // if has_decls_len - /// 5. capture: Capture // for every captures_len - /// 6. capture_name: NullTerminatedString // for every captures_len - /// 7. decl: Index, // for every decls_len; points to a `declaration` instruction - /// 8. inst: Index // for every body_len - /// 9. has_bits: u32 // for every 32 fields - /// - the bit is whether corresponding field has an value expression - /// 10. fields: { // for every fields_len - /// field_name: u32, - /// value: Ref, // if corresponding bit is set - /// } + /// 0. captures_len: u32, // if has_captures_len + /// 1. decls_len: u32, // if has_decls_len + /// 2. fields_len: u32, // if has_fields_len + /// 3. tag_type: Ref, // if has_tag_type + /// 4. capture: Capture // for every `captures_len` + /// 5. capture_name: NullTerminatedString // for every `captures_len` + /// 6. decl: Index, // for every `decls_len`; points to a `declaration` instruction + /// 7. field_name: NullTerminatedString // for every `fields_len` + /// 8. field_value_body_len: u32 // for every `fields_len` if `any_field_values` + /// 9. body_inst: Inst.Index // value body for each field pub const EnumDecl = struct { // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`. // This hash contains the source of all fields, and the backing type if specified. @@ -3659,40 +3640,31 @@ pub const Inst = struct { /// This node provides a new absolute baseline node for all instructions within this struct. src_node: Ast.Node.Index, - pub const Small = packed struct { - has_tag_type: bool, + pub const Small = packed struct(u16) { has_captures_len: bool, - has_body_len: bool, - has_fields_len: bool, has_decls_len: bool, + has_fields_len: bool, name_strategy: NameStrategy, + has_tag_type: bool, nonexhaustive: bool, - _: u8 = undefined, + any_field_values: bool, + _: u8 = 0, }; }; /// Trailing: - /// 0. tag_type: Ref, // if has_tag_type - /// 1. captures_len: u32 // if has_captures_len - /// 2. body_len: u32, // if has_body_len - /// 3. fields_len: u32, // if has_fields_len - /// 4. decls_len: u32, // if has_decls_len - /// 5. capture: Capture // for every captures_len - /// 6. capture_name: NullTerminatedString // for every captures_len - /// 7. decl: Index, // for every decls_len; points to a `declaration` instruction - /// 8. inst: Index // for every body_len - /// 9. has_bits: u32 // for every 8 fields - /// - sets of 4 bits: - /// 0b000X: whether corresponding field has a type expression - /// 0b00X0: whether corresponding field has a align expression - /// 0b0X00: whether corresponding field has a tag value expression - /// 0bX000: unused - /// 10. fields: { // for every fields_len - /// field_name: NullTerminatedString, // null terminated string index - /// field_type: Ref, // if corresponding bit is set - /// align: Ref, // if corresponding bit is set - /// tag_value: Ref, // if corresponding bit is set - /// } + /// 0. captures_len: u32 // if `has_captures_len` + /// 1. decls_len: u32, // if `has_decls_len` + /// 2. fields_len: u32, // if `has_fields_len` + /// 3. arg_type: Ref, // if `kind.hasArgType()` + /// 4. capture: Capture // for every `captures_len` + /// 5. capture_name: NullTerminatedString // for every `captures_len` + /// 6. decl: Index, // for every `decls_len`; points to a `declaration` instruction + /// 7. field_name: NullTerminatedString // for every `fields_len` + /// 8. field_type_body_len: u32 // for every `fields_len` + /// 9 . field_align_body_len: u32 // for every `fields_len` if `any_field_aligns` + /// 10. field_value_body_len: u32 // for every `fields_len` if `any_field_values` + /// 11. body_inst: Inst.Index // type body, then align body, then value body, for each field pub const UnionDecl = struct { // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`. // This hash contains the source of all fields, and any specified attributes (`extern` etc). @@ -3704,23 +3676,47 @@ pub const Inst = struct { /// This node provides a new absolute baseline node for all instructions within this struct. src_node: Ast.Node.Index, - pub const Small = packed struct { - has_tag_type: bool, + pub const Small = packed struct(u16) { has_captures_len: bool, - has_body_len: bool, - has_fields_len: bool, has_decls_len: bool, + has_fields_len: bool, name_strategy: NameStrategy, - layout: std.builtin.Type.ContainerLayout, - /// has_tag_type | auto_enum_tag | result - /// ------------------------------------- - /// false | false | union { } - /// false | true | union(enum) { } - /// true | true | union(enum(T)) { } - /// true | false | union(T) { } - auto_enum_tag: bool, - any_aligned_fields: bool, - _: u5 = undefined, + kind: Kind, + any_field_aligns: bool, + any_field_values: bool, + _: u6 = 0, + }; + + pub const Kind = enum(u3) { + /// `union` + auto, + /// `union(T)` + tagged_explicit, + /// `union(enum)` + tagged_enum, + /// `union(enum(T))` + tagged_enum_explicit, + /// `extern union` + @"extern", + /// `packed union` + @"packed", + /// `packed union(T)` + packed_explicit, + + pub fn hasArgType(k: Kind) bool { + return switch (k) { + .auto, .tagged_enum, .@"extern", .@"packed" => false, + .tagged_explicit, .tagged_enum_explicit, .packed_explicit => true, + }; + } + + pub fn layout(k: Kind) std.builtin.ContainerLayout { + return switch (k) { + .auto, .tagged_explicit, .tagged_enum, .tagged_enum_explicit => .auto, + .@"extern" => .@"extern", + .@"packed", .packed_explicit => .@"packed", + }; + } }; }; @@ -3735,11 +3731,11 @@ pub const Inst = struct { /// This node provides a new absolute baseline node for all instructions within this struct. src_node: Ast.Node.Index, - pub const Small = packed struct { + pub const Small = packed struct(u16) { has_captures_len: bool, has_decls_len: bool, name_strategy: NameStrategy, - _: u12 = undefined, + _: u12 = 0, }; }; @@ -3904,12 +3900,12 @@ pub const Inst = struct { pub const AllocExtended = struct { src_node: Ast.Node.Offset, - pub const Small = packed struct { + pub const Small = packed struct(u16) { has_type: bool, has_align: bool, is_const: bool, is_comptime: bool, - _: u12 = undefined, + _: u12 = 0, }; }; @@ -4012,133 +4008,18 @@ pub const Inst = struct { }; }; +/// MLUGG TODO: delete this! pub const DeclIterator = struct { - extra_index: u32, - decls_remaining: u32, - zir: Zir, - + decls: []const Inst.Index, + index: usize, pub fn next(it: *DeclIterator) ?Inst.Index { - if (it.decls_remaining == 0) return null; - const decl_inst: Zir.Inst.Index = @enumFromInt(it.zir.extra[it.extra_index]); - it.extra_index += 1; - it.decls_remaining -= 1; - assert(it.zir.instructions.items(.tag)[@intFromEnum(decl_inst)] == .declaration); - return decl_inst; + if (it.index == it.decls.len) return null; + defer it.index += 1; + return it.decls[it.index]; } }; - pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { - const inst = zir.instructions.get(@intFromEnum(decl_inst)); - assert(inst.tag == .extended); - const extended = inst.data.extended; - switch (extended.opcode) { - .struct_decl => { - const small: Inst.StructDecl.Small = @bitCast(extended.small); - var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.StructDecl).@"struct".fields.len); - const captures_len = if (small.has_captures_len) captures_len: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :captures_len captures_len; - } else 0; - extra_index += @intFromBool(small.has_fields_len); - const decls_len = if (small.has_decls_len) decls_len: { - const decls_len = zir.extra[extra_index]; - extra_index += 1; - break :decls_len decls_len; - } else 0; - - extra_index += captures_len * 2; - - if (small.has_backing_int) { - const backing_int_body_len = zir.extra[extra_index]; - extra_index += 1; // backing_int_body_len - if (backing_int_body_len == 0) { - extra_index += 1; // backing_int_ref - } else { - extra_index += backing_int_body_len; // backing_int_body_inst - } - } - - return .{ - .extra_index = extra_index, - .decls_remaining = decls_len, - .zir = zir, - }; - }, - .enum_decl => { - const small: Inst.EnumDecl.Small = @bitCast(extended.small); - var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.EnumDecl).@"struct".fields.len); - extra_index += @intFromBool(small.has_tag_type); - const captures_len = if (small.has_captures_len) captures_len: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :captures_len captures_len; - } else 0; - extra_index += @intFromBool(small.has_body_len); - extra_index += @intFromBool(small.has_fields_len); - const decls_len = if (small.has_decls_len) decls_len: { - const decls_len = zir.extra[extra_index]; - extra_index += 1; - break :decls_len decls_len; - } else 0; - - extra_index += captures_len * 2; - - return .{ - .extra_index = extra_index, - .decls_remaining = decls_len, - .zir = zir, - }; - }, - .union_decl => { - const small: Inst.UnionDecl.Small = @bitCast(extended.small); - var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.UnionDecl).@"struct".fields.len); - extra_index += @intFromBool(small.has_tag_type); - const captures_len = if (small.has_captures_len) captures_len: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :captures_len captures_len; - } else 0; - extra_index += @intFromBool(small.has_body_len); - extra_index += @intFromBool(small.has_fields_len); - const decls_len = if (small.has_decls_len) decls_len: { - const decls_len = zir.extra[extra_index]; - extra_index += 1; - break :decls_len decls_len; - } else 0; - - extra_index += captures_len * 2; - - return .{ - .extra_index = extra_index, - .decls_remaining = decls_len, - .zir = zir, - }; - }, - .opaque_decl => { - const small: Inst.OpaqueDecl.Small = @bitCast(extended.small); - var extra_index: u32 = @intCast(extended.operand + @typeInfo(Inst.OpaqueDecl).@"struct".fields.len); - const decls_len = if (small.has_decls_len) decls_len: { - const decls_len = zir.extra[extra_index]; - extra_index += 1; - break :decls_len decls_len; - } else 0; - const captures_len = if (small.has_captures_len) captures_len: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :captures_len captures_len; - } else 0; - - extra_index += captures_len * 2; - - return .{ - .extra_index = extra_index, - .decls_remaining = decls_len, - .zir = zir, - }; - }, - else => unreachable, - } + return .{ .decls = zir.typeDecls(decl_inst), .index = 0 }; } /// `DeclContents` contains all "interesting" instructions found within a declaration by `findTrackable`. @@ -4524,7 +4405,7 @@ fn findTrackableInner( try zir.findTrackableBody(gpa, contents, defers, body); }, - // Reifications and opaque declarations need tracking, but have no body. + // Reifications and opaque declarations need tracking, but have no bodies. .reify_enum, .reify_struct, .reify_union, @@ -4535,150 +4416,37 @@ fn findTrackableInner( .struct_decl => { try contents.explicit_types.append(gpa, inst); - const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); - const extra = zir.extraData(Zir.Inst.StructDecl, extended.operand); - var extra_index = extra.end; - const captures_len = if (small.has_captures_len) blk: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - const fields_len = if (small.has_fields_len) blk: { - const fields_len = zir.extra[extra_index]; - extra_index += 1; - break :blk fields_len; - } else 0; - const decls_len = if (small.has_decls_len) blk: { - const decls_len = zir.extra[extra_index]; - extra_index += 1; - break :blk decls_len; - } else 0; - extra_index += captures_len * 2; - if (small.has_backing_int) { - const backing_int_body_len = zir.extra[extra_index]; - extra_index += 1; - if (backing_int_body_len == 0) { - extra_index += 1; // backing_int_ref - } else { - const body = zir.bodySlice(extra_index, backing_int_body_len); - extra_index += backing_int_body_len; - try zir.findTrackableBody(gpa, contents, defers, body); - } + const struct_decl = zir.getStructDecl(inst); + var it = struct_decl.iterateFields(); + while (it.next()) |field| { + try zir.findTrackableBody(gpa, contents, defers, field.type_body); + if (field.align_body) |b| try zir.findTrackableBody(gpa, contents, defers, b); + if (field.default_body) |b| try zir.findTrackableBody(gpa, contents, defers, b); } - extra_index += decls_len; - - // This ZIR is structured in a slightly awkward way, so we have to split up the iteration. - // `extra_index` iterates `flags` (bags of bits). - // `fields_extra_index` iterates `fields`. - // We accumulate the total length of bodies into `total_bodies_len`. This is sufficient because - // the bodies are packed together in `extra` and we only need to traverse their instructions (we - // don't really care about the structure). - - const bits_per_field = 4; - const fields_per_u32 = 32 / bits_per_field; - const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; - var cur_bit_bag: u32 = undefined; - - var fields_extra_index = extra_index + bit_bags_count; - var total_bodies_len: u32 = 0; - - for (0..fields_len) |field_i| { - if (field_i % fields_per_u32 == 0) { - cur_bit_bag = zir.extra[extra_index]; - extra_index += 1; - } - - const has_align = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - const has_init = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 2; // also skip `is_comptime`; we don't care - const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - - fields_extra_index += 1; // field_name - - if (has_type_body) { - const field_type_body_len = zir.extra[fields_extra_index]; - total_bodies_len += field_type_body_len; - } - fields_extra_index += 1; // field_type or field_type_body_len - - if (has_align) { - const align_body_len = zir.extra[fields_extra_index]; - fields_extra_index += 1; - total_bodies_len += align_body_len; - } - - if (has_init) { - const init_body_len = zir.extra[fields_extra_index]; - fields_extra_index += 1; - total_bodies_len += init_body_len; - } - } - - // Now, `fields_extra_index` points to `bodies`. Let's treat this as one big body. - const merged_bodies = zir.bodySlice(fields_extra_index, total_bodies_len); - try zir.findTrackableBody(gpa, contents, defers, merged_bodies); }, - // Union declarations need tracking and have a body. + // Union declarations need tracking and have bodies. .union_decl => { try contents.explicit_types.append(gpa, inst); - const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); - const extra = zir.extraData(Zir.Inst.UnionDecl, extended.operand); - var extra_index = extra.end; - extra_index += @intFromBool(small.has_tag_type); - const captures_len = if (small.has_captures_len) blk: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - const body_len = if (small.has_body_len) blk: { - const body_len = zir.extra[extra_index]; - extra_index += 1; - break :blk body_len; - } else 0; - extra_index += @intFromBool(small.has_fields_len); - const decls_len = if (small.has_decls_len) blk: { - const decls_len = zir.extra[extra_index]; - extra_index += 1; - break :blk decls_len; - } else 0; - extra_index += captures_len * 2; - extra_index += decls_len; - const body = zir.bodySlice(extra_index, body_len); - try zir.findTrackableBody(gpa, contents, defers, body); + const union_decl = zir.getUnionDecl(inst); + var it = union_decl.iterateFields(); + while (it.next()) |field| { + if (field.type_body) |b| try zir.findTrackableBody(gpa, contents, defers, b); + if (field.align_body) |b| try zir.findTrackableBody(gpa, contents, defers, b); + if (field.value_body) |b| try zir.findTrackableBody(gpa, contents, defers, b); + } }, - // Enum declarations need tracking and have a body. + // Enum declarations need tracking and have bodies. .enum_decl => { try contents.explicit_types.append(gpa, inst); - const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small); - const extra = zir.extraData(Zir.Inst.EnumDecl, extended.operand); - var extra_index = extra.end; - extra_index += @intFromBool(small.has_tag_type); - const captures_len = if (small.has_captures_len) blk: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - const body_len = if (small.has_body_len) blk: { - const body_len = zir.extra[extra_index]; - extra_index += 1; - break :blk body_len; - } else 0; - extra_index += @intFromBool(small.has_fields_len); - const decls_len = if (small.has_decls_len) blk: { - const decls_len = zir.extra[extra_index]; - extra_index += 1; - break :blk decls_len; - } else 0; - extra_index += captures_len * 2; - extra_index += decls_len; - const body = zir.bodySlice(extra_index, body_len); - try zir.findTrackableBody(gpa, contents, defers, body); + const enum_decl = zir.getEnumDecl(inst); + var it = enum_decl.iterateFields(); + while (it.next()) |field| { + if (field.value_body) |b| try zir.findTrackableBody(gpa, contents, defers, b); + } }, } }, @@ -5481,34 +5249,452 @@ pub fn assertTrackable(zir: Zir, inst_idx: Zir.Inst.Index) void { } } +/// MLUGG TODO: maybe delete these two? pub fn typeCapturesLen(zir: Zir, type_decl: Inst.Index) u32 { const inst = zir.instructions.get(@intFromEnum(type_decl)); assert(inst.tag == .extended); - switch (inst.data.extended.opcode) { - .struct_decl => { - const small: Inst.StructDecl.Small = @bitCast(inst.data.extended.small); - if (!small.has_captures_len) return 0; - const extra = zir.extraData(Inst.StructDecl, inst.data.extended.operand); - return zir.extra[extra.end]; - }, - .union_decl => { - const small: Inst.UnionDecl.Small = @bitCast(inst.data.extended.small); - if (!small.has_captures_len) return 0; - const extra = zir.extraData(Inst.UnionDecl, inst.data.extended.operand); - return zir.extra[extra.end + @intFromBool(small.has_tag_type)]; - }, - .enum_decl => { - const small: Inst.EnumDecl.Small = @bitCast(inst.data.extended.small); - if (!small.has_captures_len) return 0; - const extra = zir.extraData(Inst.EnumDecl, inst.data.extended.operand); - return zir.extra[extra.end + @intFromBool(small.has_tag_type)]; - }, - .opaque_decl => { - const small: Inst.OpaqueDecl.Small = @bitCast(inst.data.extended.small); - if (!small.has_captures_len) return 0; - const extra = zir.extraData(Inst.OpaqueDecl, inst.data.extended.operand); - return zir.extra[extra.end]; - }, + return switch (inst.data.extended.opcode) { + .struct_decl => @intCast(zir.getStructDecl(type_decl).captures.len), + .union_decl => @intCast(zir.getUnionDecl(type_decl).captures.len), + .enum_decl => @intCast(zir.getEnumDecl(type_decl).captures.len), + .opaque_decl => @intCast(zir.getOpaqueDecl(type_decl).captures.len), else => unreachable, + }; +} +pub fn typeDecls(zir: Zir, type_decl: Inst.Index) []const Zir.Inst.Index { + const inst = zir.instructions.get(@intFromEnum(type_decl)); + assert(inst.tag == .extended); + return switch (inst.data.extended.opcode) { + .struct_decl => zir.getStructDecl(type_decl).decls, + .union_decl => zir.getUnionDecl(type_decl).decls, + .enum_decl => zir.getEnumDecl(type_decl).decls, + .opaque_decl => zir.getOpaqueDecl(type_decl).decls, + else => unreachable, + }; +} + +pub fn getStructDecl(zir: *const Zir, struct_decl: Inst.Index) UnwrappedStructDecl { + const inst_data = zir.instructions.get(@intFromEnum(struct_decl)); + assert(inst_data.tag == .extended); + assert(inst_data.data.extended.opcode == .struct_decl); + const small: Inst.StructDecl.Small = @bitCast(inst_data.data.extended.small); + const extra = zir.extraData(Inst.StructDecl, inst_data.data.extended.operand); + var extra_index = extra.end; + const captures_len: u32 = if (small.has_captures_len) blk: { + const captures_len = zir.extra[extra_index]; + extra_index += 1; + break :blk captures_len; + } else 0; + const decls_len: u32 = if (small.has_decls_len) blk: { + const decls_len = zir.extra[extra_index]; + extra_index += 1; + break :blk decls_len; + } else 0; + const fields_len: u32 = if (small.has_fields_len) blk: { + const fields_len = zir.extra[extra_index]; + extra_index += 1; + break :blk fields_len; + } else 0; + const backing_int_type: Inst.Ref = if (small.has_backing_int_type) ty: { + const ty = zir.extra[extra_index]; + extra_index += 1; + break :ty @enumFromInt(ty); + } else .none; + const captures: []const Inst.Capture = @ptrCast(zir.extra[extra_index..][0..captures_len]); + extra_index += captures_len; + const capture_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..captures_len]); + extra_index += captures_len; + const decls: []const Inst.Index = @ptrCast(zir.extra[extra_index..][0..decls_len]); + extra_index += decls_len; + const field_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..fields_len]); + extra_index += fields_len; + const field_type_body_lens: []const u32 = @ptrCast(zir.extra[extra_index..][0..fields_len]); + extra_index += fields_len; + const field_align_body_lens: ?[]const u32 = if (small.any_field_aligns) lens: { + const lens = zir.extra[extra_index..][0..fields_len]; + extra_index += fields_len; + break :lens @ptrCast(lens); + } else null; + const field_default_body_lens: ?[]const u32 = if (small.any_field_defaults) lens: { + const lens = zir.extra[extra_index..][0..fields_len]; + extra_index += fields_len; + break :lens @ptrCast(lens); + } else null; + const field_comptime_bits: ?[]const u32 = if (small.any_comptime_fields) bits: { + const bits_len = std.math.divCeil(u32, fields_len, 32) catch unreachable; + const bits = zir.extra[extra_index..][0..bits_len]; + extra_index += bits_len; + break :bits bits; + } else null; + const field_bodies_overlong: []const Inst.Index = @ptrCast(zir.extra[extra_index..]); + return .{ + .src_line = extra.data.src_line, + .src_node = extra.data.src_node, + .name_strategy = small.name_strategy, + .captures = captures, + .capture_names = capture_names, + .decls = decls, + .layout = small.layout, + .backing_int_type = backing_int_type, + .field_names = field_names, + .field_type_body_lens = field_type_body_lens, + .field_align_body_lens = field_align_body_lens, + .field_default_body_lens = field_default_body_lens, + .field_comptime_bits = field_comptime_bits, + .field_bodies_overlong = field_bodies_overlong, + }; +} +pub const UnwrappedStructDecl = struct { + src_line: u32, + src_node: Ast.Node.Index, + name_strategy: Inst.NameStrategy, + + captures: []const Inst.Capture, + capture_names: []const NullTerminatedString, + + decls: []const Inst.Index, + + layout: std.builtin.Type.ContainerLayout, + backing_int_type: Inst.Ref, + + field_names: []const NullTerminatedString, + field_type_body_lens: []const u32, + field_align_body_lens: ?[]const u32, + field_default_body_lens: ?[]const u32, + field_comptime_bits: ?[]const u32, + field_bodies_overlong: []const Inst.Index, + + pub fn iterateFields(struct_decl: UnwrappedStructDecl) FieldIterator { + return .{ + .next_idx = 0, + .names = struct_decl.field_names, + .type_body_lens = struct_decl.field_type_body_lens, + .align_body_lens = struct_decl.field_align_body_lens, + .default_body_lens = struct_decl.field_default_body_lens, + .comptime_bits = struct_decl.field_comptime_bits, + .bodies_overlong = struct_decl.field_bodies_overlong, + }; + } + + pub const FieldIterator = struct { + next_idx: u32, + names: []const NullTerminatedString, + type_body_lens: []const u32, + align_body_lens: ?[]const u32, + default_body_lens: ?[]const u32, + comptime_bits: ?[]const u32, + bodies_overlong: []const Inst.Index, + pub const Field = struct { + idx: u32, + name: NullTerminatedString, + type_body: []const Inst.Index, + align_body: ?[]const Inst.Index, + default_body: ?[]const Inst.Index, + is_comptime: bool, + }; + pub fn next(it: *FieldIterator) ?Field { + const idx = it.next_idx; + if (idx == it.names.len) return null; + it.next_idx += 1; + return .{ + .idx = idx, + .name = it.names[idx], + .type_body = it.body(it.type_body_lens[idx]).?, + .align_body = it.body(if (it.align_body_lens) |l| l[idx] else 0), + .default_body = it.body(if (it.default_body_lens) |l| l[idx] else 0), + .is_comptime = ct: { + const bits = it.comptime_bits orelse break :ct false; + const big = bits[idx / 32]; + const shifted = big >> @intCast(idx % 32); + break :ct @as(u1, @truncate(shifted)) == 1; + }, + }; + } + fn body(it: *FieldIterator, len: u32) ?[]const Inst.Index { + if (len == 0) return null; + const b = it.bodies_overlong[0..len]; + it.bodies_overlong = it.bodies_overlong[len..]; + return b; + } + }; +}; + +pub fn getUnionDecl(zir: *const Zir, union_decl: Inst.Index) UnwrappedUnionDecl { + const inst_data = zir.instructions.get(@intFromEnum(union_decl)); + assert(inst_data.tag == .extended); + assert(inst_data.data.extended.opcode == .union_decl); + const small: Inst.UnionDecl.Small = @bitCast(inst_data.data.extended.small); + const extra = zir.extraData(Inst.UnionDecl, inst_data.data.extended.operand); + var extra_index = extra.end; + const captures_len: u32 = if (small.has_captures_len) blk: { + const captures_len = zir.extra[extra_index]; + extra_index += 1; + break :blk captures_len; + } else 0; + const decls_len: u32 = if (small.has_decls_len) blk: { + const decls_len = zir.extra[extra_index]; + extra_index += 1; + break :blk decls_len; + } else 0; + const fields_len: u32 = if (small.has_fields_len) blk: { + const fields_len = zir.extra[extra_index]; + extra_index += 1; + break :blk fields_len; + } else 0; + const arg_type: Inst.Ref = if (small.kind.hasArgType()) ty: { + const ty = zir.extra[extra_index]; + extra_index += 1; + break :ty @enumFromInt(ty); + } else .none; + const captures: []const Inst.Capture = @ptrCast(zir.extra[extra_index..][0..captures_len]); + extra_index += captures_len; + const capture_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..captures_len]); + extra_index += captures_len; + const decls: []const Inst.Index = @ptrCast(zir.extra[extra_index..][0..decls_len]); + extra_index += decls_len; + const field_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..fields_len]); + extra_index += fields_len; + const field_type_body_lens: []const u32 = @ptrCast(zir.extra[extra_index..][0..fields_len]); + extra_index += fields_len; + const field_align_body_lens: ?[]const u32 = if (small.any_field_aligns) lens: { + const lens = zir.extra[extra_index..][0..fields_len]; + extra_index += fields_len; + break :lens @ptrCast(lens); + } else null; + const field_value_body_lens: ?[]const u32 = if (small.any_field_values) lens: { + const lens = zir.extra[extra_index..][0..fields_len]; + extra_index += fields_len; + break :lens @ptrCast(lens); + } else null; + const field_bodies_overlong: []const Inst.Index = @ptrCast(zir.extra[extra_index..]); + return .{ + .src_line = extra.data.src_line, + .src_node = extra.data.src_node, + .name_strategy = small.name_strategy, + .captures = captures, + .capture_names = capture_names, + .decls = decls, + .kind = small.kind, + .arg_type = arg_type, + .field_names = field_names, + .field_type_body_lens = field_type_body_lens, + .field_align_body_lens = field_align_body_lens, + .field_value_body_lens = field_value_body_lens, + .field_bodies_overlong = field_bodies_overlong, + }; +} +pub const UnwrappedUnionDecl = struct { + src_line: u32, + src_node: Ast.Node.Index, + name_strategy: Inst.NameStrategy, + + captures: []const Inst.Capture, + capture_names: []const NullTerminatedString, + + decls: []const Inst.Index, + + kind: Inst.UnionDecl.Kind, + arg_type: Inst.Ref, + + field_names: []const NullTerminatedString, + field_type_body_lens: []const u32, + field_align_body_lens: ?[]const u32, + field_value_body_lens: ?[]const u32, + field_bodies_overlong: []const Inst.Index, + + pub fn iterateFields(union_decl: UnwrappedUnionDecl) FieldIterator { + return .{ + .next_idx = 0, + .names = union_decl.field_names, + .type_body_lens = union_decl.field_type_body_lens, + .align_body_lens = union_decl.field_align_body_lens, + .value_body_lens = union_decl.field_value_body_lens, + .bodies_overlong = union_decl.field_bodies_overlong, + }; + } + + pub const FieldIterator = struct { + next_idx: u32, + names: []const NullTerminatedString, + type_body_lens: []const u32, + align_body_lens: ?[]const u32, + value_body_lens: ?[]const u32, + bodies_overlong: []const Inst.Index, + pub const Field = struct { + idx: u32, + name: NullTerminatedString, + type_body: ?[]const Inst.Index, + align_body: ?[]const Inst.Index, + value_body: ?[]const Inst.Index, + }; + pub fn next(it: *FieldIterator) ?Field { + const idx = it.next_idx; + if (idx == it.names.len) return null; + it.next_idx += 1; + return .{ + .idx = idx, + .name = it.names[idx], + .type_body = it.body(it.type_body_lens[idx]), + .align_body = it.body(if (it.align_body_lens) |l| l[idx] else 0), + .value_body = it.body(if (it.value_body_lens) |l| l[idx] else 0), + }; + } + fn body(it: *FieldIterator, len: u32) ?[]const Inst.Index { + if (len == 0) return null; + const b = it.bodies_overlong[0..len]; + it.bodies_overlong = it.bodies_overlong[len..]; + return b; + } + }; +}; + +pub fn getEnumDecl(zir: *const Zir, enum_decl: Inst.Index) UnwrappedEnumDecl { + const inst_data = zir.instructions.get(@intFromEnum(enum_decl)); + assert(inst_data.tag == .extended); + assert(inst_data.data.extended.opcode == .enum_decl); + const small: Inst.EnumDecl.Small = @bitCast(inst_data.data.extended.small); + const extra = zir.extraData(Inst.EnumDecl, inst_data.data.extended.operand); + var extra_index = extra.end; + const captures_len: u32 = if (small.has_captures_len) blk: { + const captures_len = zir.extra[extra_index]; + extra_index += 1; + break :blk captures_len; + } else 0; + const decls_len: u32 = if (small.has_decls_len) blk: { + const decls_len = zir.extra[extra_index]; + extra_index += 1; + break :blk decls_len; + } else 0; + const fields_len: u32 = if (small.has_fields_len) blk: { + const fields_len = zir.extra[extra_index]; + extra_index += 1; + break :blk fields_len; + } else 0; + const tag_type: Inst.Ref = if (small.has_tag_type) ty: { + const ty = zir.extra[extra_index]; + extra_index += 1; + break :ty @enumFromInt(ty); + } else .none; + const captures: []const Inst.Capture = @ptrCast(zir.extra[extra_index..][0..captures_len]); + extra_index += captures_len; + const capture_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..captures_len]); + extra_index += captures_len; + const decls: []const Inst.Index = @ptrCast(zir.extra[extra_index..][0..decls_len]); + extra_index += decls_len; + const field_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..fields_len]); + extra_index += fields_len; + const field_value_body_lens: ?[]const u32 = if (small.any_field_values) lens: { + const lens = zir.extra[extra_index..][0..fields_len]; + extra_index += fields_len; + break :lens @ptrCast(lens); + } else null; + const field_bodies_overlong: []const Inst.Index = @ptrCast(zir.extra[extra_index..]); + return .{ + .src_line = extra.data.src_line, + .src_node = extra.data.src_node, + .name_strategy = small.name_strategy, + .captures = captures, + .capture_names = capture_names, + .decls = decls, + .tag_type = tag_type, + .nonexhaustive = small.nonexhaustive, + .field_names = field_names, + .field_value_body_lens = field_value_body_lens, + .field_bodies_overlong = field_bodies_overlong, + }; +} +pub const UnwrappedEnumDecl = struct { + src_line: u32, + src_node: Ast.Node.Index, + name_strategy: Inst.NameStrategy, + + captures: []const Inst.Capture, + capture_names: []const NullTerminatedString, + + decls: []const Inst.Index, + + tag_type: Inst.Ref, + nonexhaustive: bool, + + field_names: []const NullTerminatedString, + field_value_body_lens: ?[]const u32, + field_bodies_overlong: []const Inst.Index, + + pub fn iterateFields(enum_decl: UnwrappedEnumDecl) FieldIterator { + return .{ + .next_idx = 0, + .names = enum_decl.field_names, + .value_body_lens = enum_decl.field_value_body_lens, + .bodies_overlong = enum_decl.field_bodies_overlong, + }; } + + pub const FieldIterator = struct { + next_idx: u32, + names: []const NullTerminatedString, + value_body_lens: ?[]const u32, + bodies_overlong: []const Inst.Index, + pub const Field = struct { + idx: u32, + name: NullTerminatedString, + value_body: ?[]const Inst.Index, + }; + pub fn next(it: *FieldIterator) ?Field { + const idx = it.next_idx; + if (idx == it.names.len) return null; + it.next_idx += 1; + return .{ + .idx = idx, + .name = it.names[idx], + .value_body = it.body(if (it.value_body_lens) |l| l[idx] else 0), + }; + } + fn body(it: *FieldIterator, len: u32) ?[]const Inst.Index { + if (len == 0) return null; + const b = it.bodies_overlong[0..len]; + it.bodies_overlong = it.bodies_overlong[len..]; + return b; + } + }; +}; + +pub fn getOpaqueDecl(zir: *const Zir, opaque_decl: Inst.Index) UnwrappedOpaqueDecl { + const inst_data = zir.instructions.get(@intFromEnum(opaque_decl)); + assert(inst_data.tag == .extended); + assert(inst_data.data.extended.opcode == .opaque_decl); + const small: Inst.OpaqueDecl.Small = @bitCast(inst_data.data.extended.small); + const extra = zir.extraData(Inst.OpaqueDecl, inst_data.data.extended.operand); + var extra_index = extra.end; + const captures_len: u32 = if (small.has_captures_len) blk: { + const captures_len = zir.extra[extra_index]; + extra_index += 1; + break :blk captures_len; + } else 0; + const decls_len: u32 = if (small.has_decls_len) blk: { + const decls_len = zir.extra[extra_index]; + extra_index += 1; + break :blk decls_len; + } else 0; + const captures: []const Inst.Capture = @ptrCast(zir.extra[extra_index..][0..captures_len]); + extra_index += captures_len; + const capture_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..captures_len]); + extra_index += captures_len; + const decls: []const Inst.Index = @ptrCast(zir.extra[extra_index..][0..decls_len]); + extra_index += decls_len; + return .{ + .src_line = extra.data.src_line, + .src_node = extra.data.src_node, + .name_strategy = small.name_strategy, + .captures = captures, + .capture_names = capture_names, + .decls = decls, + }; } +pub const UnwrappedOpaqueDecl = struct { + src_line: u32, + src_node: Ast.Node.Index, + name_strategy: Inst.NameStrategy, + captures: []const Inst.Capture, + capture_names: []const NullTerminatedString, + decls: []const Inst.Index, +}; diff --git a/src/print_zir.zig b/src/print_zir.zig index c3a494de8466600670dff6d74b567cd80ee04a71..cd7d18351ca48c7c767c1347f52e53589a921404 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -548,10 +548,10 @@ const Writer = struct { .shl_with_overflow, => try self.writeOverflowArithmetic(stream, extended), - .struct_decl => try self.writeStructDecl(stream, extended), - .union_decl => try self.writeUnionDecl(stream, extended), - .enum_decl => try self.writeEnumDecl(stream, extended), - .opaque_decl => try self.writeOpaqueDecl(stream, extended), + .struct_decl => try self.writeStructDecl(stream, inst), + .union_decl => try self.writeUnionDecl(stream, inst), + .enum_decl => try self.writeEnumDecl(stream, inst), + .opaque_decl => try self.writeOpaqueDecl(stream, inst), .tuple_decl => try self.writeTupleDecl(stream, extended), @@ -1427,187 +1427,57 @@ const Writer = struct { try self.writeSrcNode(stream, inst_data.src_node); } - fn writeStructDecl(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { - const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); - - const extra = self.code.extraData(Zir.Inst.StructDecl, extended.operand); + fn writeStructDecl(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { + const struct_decl = self.code.getStructDecl(inst); const prev_parent_decl_node = self.parent_decl_node; - self.parent_decl_node = extra.data.src_node; + self.parent_decl_node = struct_decl.src_node; defer self.parent_decl_node = prev_parent_decl_node; - const fields_hash: std.zig.SrcHash = @bitCast([4]u32{ - extra.data.fields_hash_0, - extra.data.fields_hash_1, - extra.data.fields_hash_2, - extra.data.fields_hash_3, - }); - + const fields_hash = self.code.getAssociatedSrcHash(inst).?; try stream.print("hash({x}) ", .{&fields_hash}); - var extra_index: usize = extra.end; + try stream.print("{s}, ", .{@tagName(struct_decl.name_strategy)}); - const captures_len = if (small.has_captures_len) blk: { - const captures_len = self.code.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - - const fields_len = if (small.has_fields_len) blk: { - const fields_len = self.code.extra[extra_index]; - extra_index += 1; - break :blk fields_len; - } else 0; - - const decls_len = if (small.has_decls_len) blk: { - const decls_len = self.code.extra[extra_index]; - extra_index += 1; - break :blk decls_len; - } else 0; - - try self.writeFlag(stream, "known_non_opv, ", small.known_non_opv); - try self.writeFlag(stream, "known_comptime_only, ", small.known_comptime_only); - - try stream.print("{s}, ", .{@tagName(small.name_strategy)}); - - extra_index = try self.writeCaptures(stream, extra_index, captures_len); - try stream.writeAll(", "); - - if (small.has_backing_int) { - const backing_int_body_len = self.code.extra[extra_index]; - extra_index += 1; + if (struct_decl.backing_int_type != .none) { + assert(struct_decl.layout == .@"packed"); try stream.writeAll("packed("); - if (backing_int_body_len == 0) { - const backing_int_ref: Zir.Inst.Ref = @enumFromInt(self.code.extra[extra_index]); - extra_index += 1; - try self.writeInstRef(stream, backing_int_ref); - } else { - const body = self.code.bodySlice(extra_index, backing_int_body_len); - extra_index += backing_int_body_len; - self.indent += 2; - try self.writeBracedDecl(stream, body); - self.indent -= 2; - } + try self.writeInstRef(stream, struct_decl.backing_int_type); try stream.writeAll("), "); } else { - try stream.print("{s}, ", .{@tagName(small.layout)}); + try stream.print("{s}, ", .{@tagName(struct_decl.layout)}); } - if (decls_len == 0) { - try stream.writeAll("{}, "); - } else { - try stream.writeAll("{\n"); - self.indent += 2; - try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); - self.indent -= 2; - extra_index += decls_len; - try stream.splatByteAll(' ', self.indent); - try stream.writeAll("}, "); - } + try self.writeCaptures(stream, struct_decl.captures, struct_decl.capture_names); + try stream.writeAll(", "); + try self.writeBracedDecl(stream, struct_decl.decls); + try stream.writeAll(", "); - if (fields_len == 0) { - try stream.writeAll("{}, {}) "); + if (struct_decl.field_names.len == 0) { + try stream.writeAll("{}) "); } else { - const bits_per_field = 4; - const fields_per_u32 = 32 / bits_per_field; - const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; - const Field = struct { - type_len: u32 = 0, - align_len: u32 = 0, - init_len: u32 = 0, - type: Zir.Inst.Ref = .none, - name: Zir.NullTerminatedString, - is_comptime: bool, - }; - const fields = try self.arena.alloc(Field, fields_len); - { - var bit_bag_index: usize = extra_index; - extra_index += bit_bags_count; - var cur_bit_bag: u32 = undefined; - var field_i: u32 = 0; - while (field_i < fields_len) : (field_i += 1) { - if (field_i % fields_per_u32 == 0) { - cur_bit_bag = self.code.extra[bit_bag_index]; - bit_bag_index += 1; - } - const has_align = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - const has_default = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - const is_comptime = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - - const field_name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]); - extra_index += 1; - - fields[field_i] = .{ - .is_comptime = is_comptime, - .name = field_name_index, - }; - - if (has_type_body) { - fields[field_i].type_len = self.code.extra[extra_index]; - } else { - fields[field_i].type = @enumFromInt(self.code.extra[extra_index]); - } - extra_index += 1; - - if (has_align) { - fields[field_i].align_len = self.code.extra[extra_index]; - extra_index += 1; - } - - if (has_default) { - fields[field_i].init_len = self.code.extra[extra_index]; - extra_index += 1; - } - } - } - try stream.writeAll("{\n"); self.indent += 2; - for (fields, 0..) |field, i| { + var it = struct_decl.iterateFields(); + while (it.next()) |field| { try stream.splatByteAll(' ', self.indent); try self.writeFlag(stream, "comptime ", field.is_comptime); - if (field.name != .empty) { - const field_name = self.code.nullTerminatedString(field.name); - try stream.print("{f}: ", .{std.zig.fmtIdP(field_name)}); - } else { - try stream.print("@\"{d}\": ", .{i}); - } - if (field.type != .none) { - try self.writeInstRef(stream, field.type); - } - - if (field.type_len > 0) { - const body = self.code.bodySlice(extra_index, field.type_len); - extra_index += body.len; - self.indent += 2; - try self.writeBracedDecl(stream, body); - self.indent -= 2; - } + const field_name = self.code.nullTerminatedString(field.name); + try stream.print("{f}: ", .{std.zig.fmtIdP(field_name)}); - if (field.align_len > 0) { - const body = self.code.bodySlice(extra_index, field.align_len); - extra_index += body.len; - self.indent += 2; + self.indent += 2; + try self.writeBracedDecl(stream, field.type_body); + if (field.align_body) |body| { try stream.writeAll(" align("); try self.writeBracedDecl(stream, body); - try stream.writeAll(")"); - self.indent -= 2; + try stream.writeByte(')'); } - - if (field.init_len > 0) { - const body = self.code.bodySlice(extra_index, field.init_len); - extra_index += body.len; - self.indent += 2; + if (field.default_body) |body| { try stream.writeAll(" = "); try self.writeBracedDecl(stream, body); - self.indent -= 2; } + self.indent -= 2; try stream.writeAll(",\n"); } @@ -1619,266 +1489,115 @@ const Writer = struct { try self.writeSrcNode(stream, .zero); } - fn writeUnionDecl(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { - const small = @as(Zir.Inst.UnionDecl.Small, @bitCast(extended.small)); - - const extra = self.code.extraData(Zir.Inst.UnionDecl, extended.operand); + fn writeUnionDecl(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { + const union_decl = self.code.getUnionDecl(inst); const prev_parent_decl_node = self.parent_decl_node; - self.parent_decl_node = extra.data.src_node; + self.parent_decl_node = union_decl.src_node; defer self.parent_decl_node = prev_parent_decl_node; - const fields_hash: std.zig.SrcHash = @bitCast([4]u32{ - extra.data.fields_hash_0, - extra.data.fields_hash_1, - extra.data.fields_hash_2, - extra.data.fields_hash_3, - }); - + const fields_hash = self.code.getAssociatedSrcHash(inst).?; try stream.print("hash({x}) ", .{&fields_hash}); - var extra_index: usize = extra.end; - - const tag_type_ref = if (small.has_tag_type) blk: { - const tag_type_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); - extra_index += 1; - break :blk tag_type_ref; - } else .none; - - const captures_len = if (small.has_captures_len) blk: { - const captures_len = self.code.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - - const body_len = if (small.has_body_len) blk: { - const body_len = self.code.extra[extra_index]; - extra_index += 1; - break :blk body_len; - } else 0; - - const fields_len = if (small.has_fields_len) blk: { - const fields_len = self.code.extra[extra_index]; - extra_index += 1; - break :blk fields_len; - } else 0; - - const decls_len = if (small.has_decls_len) blk: { - const decls_len = self.code.extra[extra_index]; - extra_index += 1; - break :blk decls_len; - } else 0; - - try stream.print("{s}, {s}, ", .{ - @tagName(small.name_strategy), @tagName(small.layout), - }); - try self.writeFlag(stream, "autoenum, ", small.auto_enum_tag); + try stream.print("{s}, ", .{@tagName(union_decl.name_strategy)}); + + switch (union_decl.kind) { + .auto => try stream.writeAll("auto, "), + .@"extern" => try stream.writeAll("extern, "), + .@"packed" => try stream.writeAll("packed, "), + .packed_explicit => { + try stream.writeAll("packed("); + try self.writeInstRef(stream, union_decl.arg_type); + try stream.writeAll("), "); + }, + .tagged_explicit => { + try stream.writeAll("auto("); + try self.writeInstRef(stream, union_decl.arg_type); + try stream.writeAll("), "); + }, + .tagged_enum => try stream.writeAll("auto(enum)"), + .tagged_enum_explicit => { + try stream.writeAll("auto(enum("); + try self.writeInstRef(stream, union_decl.arg_type); + try stream.writeAll(")), "); + }, + } - extra_index = try self.writeCaptures(stream, extra_index, captures_len); + try self.writeCaptures(stream, union_decl.captures, union_decl.capture_names); + try stream.writeAll(", "); + try self.writeBracedDecl(stream, union_decl.decls); try stream.writeAll(", "); - if (decls_len == 0) { - try stream.writeAll("{}"); + if (union_decl.field_names.len == 0) { + try stream.writeAll("}) "); } else { try stream.writeAll("{\n"); self.indent += 2; - try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); - self.indent -= 2; - extra_index += decls_len; - try stream.splatByteAll(' ', self.indent); - try stream.writeAll("}"); - } - - if (tag_type_ref != .none) { - try stream.writeAll(", "); - try self.writeInstRef(stream, tag_type_ref); - } - - if (fields_len == 0) { - try stream.writeAll("}) "); - try self.writeSrcNode(stream, .zero); - return; - } - try stream.writeAll(", "); - const body = self.code.bodySlice(extra_index, body_len); - extra_index += body.len; + var it = union_decl.iterateFields(); + while (it.next()) |field| { + try stream.splatByteAll(' ', self.indent); + const field_name = self.code.nullTerminatedString(field.name); + try stream.print("{f}", .{std.zig.fmtIdP(field_name)}); - try self.writeBracedDecl(stream, body); - try stream.writeAll(", {\n"); + self.indent += 2; + if (field.type_body) |body| { + try stream.writeAll(": "); + try self.writeBracedDecl(stream, body); + } + if (field.align_body) |body| { + try stream.writeAll(" align("); + try self.writeBracedDecl(stream, body); + try stream.writeByte(')'); + } + if (field.value_body) |body| { + try stream.writeAll(" = "); + try self.writeBracedDecl(stream, body); + } + self.indent -= 2; - self.indent += 2; - const bits_per_field = 4; - const fields_per_u32 = 32 / bits_per_field; - const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; - const body_end = extra_index; - extra_index += bit_bags_count; - var bit_bag_index: usize = body_end; - var cur_bit_bag: u32 = undefined; - var field_i: u32 = 0; - while (field_i < fields_len) : (field_i += 1) { - if (field_i % fields_per_u32 == 0) { - cur_bit_bag = self.code.extra[bit_bag_index]; - bit_bag_index += 1; + try stream.writeAll(",\n"); } - const has_type = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - const has_align = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - const has_value = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - const unused = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - - _ = unused; - - const field_name_index: Zir.NullTerminatedString = @enumFromInt(self.code.extra[extra_index]); - const field_name = self.code.nullTerminatedString(field_name_index); - extra_index += 1; - + self.indent -= 2; try stream.splatByteAll(' ', self.indent); - try stream.print("{f}", .{std.zig.fmtIdP(field_name)}); - - if (has_type) { - const field_type = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); - extra_index += 1; - - try stream.writeAll(": "); - try self.writeInstRef(stream, field_type); - } - if (has_align) { - const align_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); - extra_index += 1; - - try stream.writeAll(" align("); - try self.writeInstRef(stream, align_ref); - try stream.writeAll(")"); - } - if (has_value) { - const default_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); - extra_index += 1; - - try stream.writeAll(" = "); - try self.writeInstRef(stream, default_ref); - } - try stream.writeAll(",\n"); + try stream.writeAll("}) "); } - - self.indent -= 2; - try stream.splatByteAll(' ', self.indent); - try stream.writeAll("}) "); try self.writeSrcNode(stream, .zero); } - fn writeEnumDecl(self: *Writer, stream: *std.Io.Writer, extended: Zir.Inst.Extended.InstData) !void { - const small = @as(Zir.Inst.EnumDecl.Small, @bitCast(extended.small)); - - const extra = self.code.extraData(Zir.Inst.EnumDecl, extended.operand); + fn writeEnumDecl(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { + const enum_decl = self.code.getEnumDecl(inst); const prev_parent_decl_node = self.parent_decl_node; - self.parent_decl_node = extra.data.src_node; + self.parent_decl_node = enum_decl.src_node; defer self.parent_decl_node = prev_parent_decl_node; - const fields_hash: std.zig.SrcHash = @bitCast([4]u32{ - extra.data.fields_hash_0, - extra.data.fields_hash_1, - extra.data.fields_hash_2, - extra.data.fields_hash_3, - }); - + const fields_hash = self.code.getAssociatedSrcHash(inst).?; try stream.print("hash({x}) ", .{&fields_hash}); - var extra_index: usize = extra.end; - - const tag_type_ref = if (small.has_tag_type) blk: { - const tag_type_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); - extra_index += 1; - break :blk tag_type_ref; - } else .none; + try stream.print("{s}, ", .{@tagName(enum_decl.name_strategy)}); + try self.writeFlag(stream, "nonexhaustive, ", enum_decl.nonexhaustive); + try self.writeInstRef(stream, enum_decl.tag_type); - const captures_len = if (small.has_captures_len) blk: { - const captures_len = self.code.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - - const body_len = if (small.has_body_len) blk: { - const body_len = self.code.extra[extra_index]; - extra_index += 1; - break :blk body_len; - } else 0; - - const fields_len = if (small.has_fields_len) blk: { - const fields_len = self.code.extra[extra_index]; - extra_index += 1; - break :blk fields_len; - } else 0; - - const decls_len = if (small.has_decls_len) blk: { - const decls_len = self.code.extra[extra_index]; - extra_index += 1; - break :blk decls_len; - } else 0; - - try stream.print("{s}, ", .{@tagName(small.name_strategy)}); - try self.writeFlag(stream, "nonexhaustive, ", small.nonexhaustive); - - extra_index = try self.writeCaptures(stream, extra_index, captures_len); + try self.writeCaptures(stream, enum_decl.captures, enum_decl.capture_names); + try stream.writeAll(", "); + try self.writeBracedDecl(stream, enum_decl.decls); try stream.writeAll(", "); - if (decls_len == 0) { - try stream.writeAll("{}, "); - } else { - try stream.writeAll("{\n"); - self.indent += 2; - try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); - self.indent -= 2; - extra_index += decls_len; - try stream.splatByteAll(' ', self.indent); - try stream.writeAll("}, "); - } - - if (tag_type_ref != .none) { - try self.writeInstRef(stream, tag_type_ref); - try stream.writeAll(", "); - } - - const body = self.code.bodySlice(extra_index, body_len); - extra_index += body.len; - - try self.writeBracedDecl(stream, body); - if (fields_len == 0) { + if (enum_decl.field_names.len == 0) { try stream.writeAll(", {}) "); } else { try stream.writeAll(", {\n"); - self.indent += 2; - const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable; - const body_end = extra_index; - extra_index += bit_bags_count; - var bit_bag_index: usize = body_end; - var cur_bit_bag: u32 = undefined; - var field_i: u32 = 0; - while (field_i < fields_len) : (field_i += 1) { - if (field_i % 32 == 0) { - cur_bit_bag = self.code.extra[bit_bag_index]; - bit_bag_index += 1; - } - const has_tag_value = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - - const field_name = self.code.nullTerminatedString(@enumFromInt(self.code.extra[extra_index])); - extra_index += 1; + var it = enum_decl.iterateFields(); + while (it.next()) |field| { try stream.splatByteAll(' ', self.indent); + const field_name = self.code.nullTerminatedString(field.name); try stream.print("{f}", .{std.zig.fmtIdP(field_name)}); - - if (has_tag_value) { - const tag_value_ref = @as(Zir.Inst.Ref, @enumFromInt(self.code.extra[extra_index])); - extra_index += 1; - + if (field.value_body) |body| { try stream.writeAll(" = "); - try self.writeInstRef(stream, tag_value_ref); + try self.writeBracedDecl(stream, body); } try stream.writeAll(",\n"); } @@ -1889,47 +1608,18 @@ const Writer = struct { try self.writeSrcNode(stream, .zero); } - fn writeOpaqueDecl( - self: *Writer, - stream: *std.Io.Writer, - extended: Zir.Inst.Extended.InstData, - ) !void { - const small = @as(Zir.Inst.OpaqueDecl.Small, @bitCast(extended.small)); - const extra = self.code.extraData(Zir.Inst.OpaqueDecl, extended.operand); + fn writeOpaqueDecl(self: *Writer, stream: *std.Io.Writer, inst: Zir.Inst.Index) !void { + const opaque_decl = self.code.getOpaqueDecl(inst); const prev_parent_decl_node = self.parent_decl_node; - self.parent_decl_node = extra.data.src_node; + self.parent_decl_node = opaque_decl.src_node; defer self.parent_decl_node = prev_parent_decl_node; - var extra_index: usize = extra.end; - - const captures_len = if (small.has_captures_len) blk: { - const captures_len = self.code.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - - const decls_len = if (small.has_decls_len) blk: { - const decls_len = self.code.extra[extra_index]; - extra_index += 1; - break :blk decls_len; - } else 0; - - try stream.print("{s}, ", .{@tagName(small.name_strategy)}); - - extra_index = try self.writeCaptures(stream, extra_index, captures_len); + try stream.print("{s}, ", .{@tagName(opaque_decl.name_strategy)}); + try self.writeCaptures(stream, opaque_decl.captures, opaque_decl.capture_names); try stream.writeAll(", "); - - if (decls_len == 0) { - try stream.writeAll("{}) "); - } else { - try stream.writeAll("{\n"); - self.indent += 2; - try self.writeBody(stream, self.code.bodySlice(extra_index, decls_len)); - self.indent -= 2; - try stream.splatByteAll(' ', self.indent); - try stream.writeAll("}) "); - } + try self.writeBracedDecl(stream, opaque_decl.decls); + try stream.writeAll(") "); try self.writeSrcNode(stream, .zero); } @@ -2588,14 +2278,11 @@ const Writer = struct { return stream.print("%{d}", .{@intFromEnum(inst)}); } - fn writeCaptures(self: *Writer, stream: *std.Io.Writer, extra_index: usize, captures_len: u32) !usize { - if (captures_len == 0) { - try stream.writeAll("{}"); - return extra_index; + fn writeCaptures(self: *Writer, stream: *std.Io.Writer, captures: []const Zir.Inst.Capture, capture_names: []const Zir.NullTerminatedString) !void { + if (captures.len == 0) { + assert(capture_names.len == 0); + return stream.writeAll("{}"); } - - const captures: []const Zir.Inst.Capture = @ptrCast(self.code.extra[extra_index..][0..captures_len]); - const capture_names: []const Zir.NullTerminatedString = @ptrCast(self.code.extra[extra_index + captures_len ..][0..captures_len]); for (captures, capture_names) |capture, name| { try stream.writeAll("{ "); if (name != .empty) { @@ -2604,8 +2291,6 @@ const Writer = struct { } try self.writeCapture(stream, capture); } - - return extra_index + 2 * captures_len; } fn writeCapture(self: *Writer, stream: *std.Io.Writer, capture: Zir.Inst.Capture) !void { -- 2.54.0 From 510ea6f61f93c722c4cb2c2b39605201cc2f9c32 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Thu, 15 Jan 2026 14:01:15 +0000 Subject: [PATCH 02/79] type resolution progress --- lib/std/math/big/int.zig | 14 +- lib/std/zig/Zir.zig | 16 +- lib/std/zig/target.zig | 6 +- src/Air.zig | 13 +- src/Air/types_resolved.zig | 536 --- src/Compilation.zig | 185 +- src/IncrementalDebugServer.zig | 14 +- src/InternPool.zig | 4702 +++++++++------------ src/Sema.zig | 6549 ++++++++++-------------------- src/Sema/LowerZon.zig | 21 +- src/Sema/arith.zig | 39 +- src/Sema/bitcast.zig | 11 +- src/Sema/comptime_ptr_access.zig | 38 +- src/Sema/type_resolution.zig | 993 +++++ src/Type.zig | 2927 ++++--------- src/Value.zig | 787 +--- src/Zcu.zig | 163 +- src/Zcu/PerThread.zig | 1504 +++---- src/codegen.zig | 2 +- src/codegen/aarch64/Select.zig | 8 +- src/codegen/c.zig | 8 +- src/codegen/llvm.zig | 2 +- src/codegen/mips/abi.zig | 2 +- src/codegen/riscv64/CodeGen.zig | 5 +- src/codegen/spirv/CodeGen.zig | 2 +- src/codegen/x86_64/CodeGen.zig | 37 +- src/link/Dwarf.zig | 8 +- src/mutable_value.zig | 18 +- src/print_value.zig | 12 +- 29 files changed, 7305 insertions(+), 11317 deletions(-) delete mode 100644 src/Air/types_resolved.zig create mode 100644 src/Sema/type_resolution.zig diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index 96fee84ddf2c6459a72b6823d4a0ea513a113270..9fc50c9e5b1ce4be1f0013af0f906cdd8d0920e2 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -924,7 +924,12 @@ pub const Mutable = struct { /// Asserts the result fits in `r`. Upper bound on the number of limbs needed by /// r is `calcTwosCompLimbCount(bit_count)`. pub fn bitReverse(r: *Mutable, a: Const, signedness: Signedness, bit_count: usize) void { - if (bit_count == 0) return; + if (bit_count == 0) { + r.limbs[0] = 0; + r.len = 1; + r.positive = true; + return; + } r.copy(a); @@ -986,7 +991,12 @@ pub const Mutable = struct { /// Asserts the result fits in `r`. Upper bound on the number of limbs needed by /// r is `calcTwosCompLimbCount(8*byte_count)`. pub fn byteSwap(r: *Mutable, a: Const, signedness: Signedness, byte_count: usize) void { - if (byte_count == 0) return; + if (byte_count == 0) { + r.limbs[0] = 0; + r.len = 1; + r.positive = true; + return; + } r.copy(a); const limbs_required = calcTwosCompLimbCount(8 * byte_count); diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index 165f37edfad0452651ffc51565e1383b67c41a63..c0270a9e03e7fe5eca1e0af9d8fdf36e64fc34e3 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -3710,7 +3710,7 @@ pub const Inst = struct { }; } - pub fn layout(k: Kind) std.builtin.ContainerLayout { + pub fn layout(k: Kind) std.builtin.Type.ContainerLayout { return switch (k) { .auto, .tagged_explicit, .tagged_enum, .tagged_enum_explicit => .auto, .@"extern" => .@"extern", @@ -4008,20 +4008,6 @@ pub const Inst = struct { }; }; -/// MLUGG TODO: delete this! -pub const DeclIterator = struct { - decls: []const Inst.Index, - index: usize, - pub fn next(it: *DeclIterator) ?Inst.Index { - if (it.index == it.decls.len) return null; - defer it.index += 1; - return it.decls[it.index]; - } -}; -pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator { - return .{ .decls = zir.typeDecls(decl_inst), .index = 0 }; -} - /// `DeclContents` contains all "interesting" instructions found within a declaration by `findTrackable`. /// These instructions are partitioned into a few different sets, since this makes ZIR instruction mapping /// more effective. diff --git a/lib/std/zig/target.zig b/lib/std/zig/target.zig index 34709e17ac9f0e9da4ff212c541e144f09d71da0..f87b93608650fe1e99955695853b2b7aa02acaf9 100644 --- a/lib/std/zig/target.zig +++ b/lib/std/zig/target.zig @@ -503,8 +503,7 @@ pub fn intByteSize(target: *const std.Target, bits: u16) u16 { pub fn intAlignment(target: *const std.Target, bits: u16) u16 { return switch (target.cpu.arch) { .x86 => switch (bits) { - 0 => 0, - 1...8 => 1, + 0...8 => 1, 9...16 => 2, 17...32 => 4, 33...64 => switch (target.os.tag) { @@ -514,8 +513,7 @@ pub fn intAlignment(target: *const std.Target, bits: u16) u16 { else => 16, }, .x86_64 => switch (bits) { - 0 => 0, - 1...8 => 1, + 0...8 => 1, 9...16 => 2, 17...32 => 4, 33...64 => 8, diff --git a/src/Air.zig b/src/Air.zig index 28b7a27ba992f375fffa3a96e7045f5de5952d1e..3f7314e11674a00620f6cf9e0da5d6fbb8671d28 100644 --- a/src/Air.zig +++ b/src/Air.zig @@ -14,7 +14,6 @@ const Type = @import("Type.zig"); const Value = @import("Value.zig"); const Zcu = @import("Zcu.zig"); const print = @import("Air/print.zig"); -const types_resolved = @import("Air/types_resolved.zig"); pub const Legalize = @import("Air/Legalize.zig"); pub const Liveness = @import("Air/Liveness.zig"); @@ -173,8 +172,8 @@ pub const Inst = struct { /// outside the provenance of the operand, the result is undefined. /// /// Uses the `ty_pl` field. Payload is `Bin`. The lhs is the pointer, - /// rhs is the offset. Result type is the same as lhs. The operand may - /// be a slice. + /// rhs is the offset. Result type is the same as lhs. The operand type's + /// pointer size may be `.slice`, `.many`, or `.c`. ptr_add, /// Subtract an offset, in element type units, from a pointer, /// returning a new pointer. Element type may not be zero bits. @@ -183,8 +182,8 @@ pub const Inst = struct { /// outside the provenance of the operand, the result is undefined. /// /// Uses the `ty_pl` field. Payload is `Bin`. The lhs is the pointer, - /// rhs is the offset. Result type is the same as lhs. The operand may - /// be a slice. + /// rhs is the offset. Result type is the same as lhs. The operand type's + /// pointer size may be `.slice`, `.many`, or `.c`. ptr_sub, /// Given two operands which can be floats, integers, or vectors, returns the /// greater of the operands. For vectors it operates element-wise. @@ -693,6 +692,7 @@ pub const Inst = struct { /// Uses the `ty_pl` field with payload `Bin`. slice_elem_ptr, /// Given a pointer value, and element index, return the element value at that index. + /// The pointer size is either `.c` or `.many`. /// Result type is the element type of the pointer operand. /// Uses the `bin_op` field. ptr_elem_val, @@ -2440,9 +2440,6 @@ pub fn unwrapShuffleTwo(air: *const Air, zcu: *const Zcu, inst_index: Inst.Index }; } -pub const typesFullyResolved = types_resolved.typesFullyResolved; -pub const typeFullyResolved = types_resolved.checkType; -pub const valFullyResolved = types_resolved.checkVal; pub const legalize = Legalize.legalize; pub const write = print.write; pub const writeInst = print.writeInst; diff --git a/src/Air/types_resolved.zig b/src/Air/types_resolved.zig deleted file mode 100644 index 216f690414abdf2daea6993536b303812a05866e..0000000000000000000000000000000000000000 --- a/src/Air/types_resolved.zig +++ /dev/null @@ -1,536 +0,0 @@ -const Air = @import("../Air.zig"); -const Zcu = @import("../Zcu.zig"); -const Type = @import("../Type.zig"); -const Value = @import("../Value.zig"); -const InternPool = @import("../InternPool.zig"); - -/// Given a body of AIR instructions, returns whether all type resolution necessary for codegen is complete. -/// If `false`, then type resolution must have failed, so codegen cannot proceed. -pub fn typesFullyResolved(air: Air, zcu: *Zcu) bool { - return checkBody(air, air.getMainBody(), zcu); -} - -fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool { - const tags = air.instructions.items(.tag); - const datas = air.instructions.items(.data); - - for (body) |inst| { - const data = datas[@intFromEnum(inst)]; - switch (tags[@intFromEnum(inst)]) { - .inferred_alloc, .inferred_alloc_comptime => unreachable, - - .arg => { - if (!checkType(data.arg.ty.toType(), zcu)) return false; - }, - - .add, - .add_safe, - .add_optimized, - .add_wrap, - .add_sat, - .sub, - .sub_safe, - .sub_optimized, - .sub_wrap, - .sub_sat, - .mul, - .mul_safe, - .mul_optimized, - .mul_wrap, - .mul_sat, - .div_float, - .div_float_optimized, - .div_trunc, - .div_trunc_optimized, - .div_floor, - .div_floor_optimized, - .div_exact, - .div_exact_optimized, - .rem, - .rem_optimized, - .mod, - .mod_optimized, - .max, - .min, - .bit_and, - .bit_or, - .shr, - .shr_exact, - .shl, - .shl_exact, - .shl_sat, - .xor, - .cmp_lt, - .cmp_lt_optimized, - .cmp_lte, - .cmp_lte_optimized, - .cmp_eq, - .cmp_eq_optimized, - .cmp_gte, - .cmp_gte_optimized, - .cmp_gt, - .cmp_gt_optimized, - .cmp_neq, - .cmp_neq_optimized, - .bool_and, - .bool_or, - .store, - .store_safe, - .set_union_tag, - .array_elem_val, - .slice_elem_val, - .ptr_elem_val, - .memset, - .memset_safe, - .memcpy, - .memmove, - .atomic_store_unordered, - .atomic_store_monotonic, - .atomic_store_release, - .atomic_store_seq_cst, - .legalize_vec_elem_val, - => { - if (!checkRef(data.bin_op.lhs, zcu)) return false; - if (!checkRef(data.bin_op.rhs, zcu)) return false; - }, - - .not, - .bitcast, - .clz, - .ctz, - .popcount, - .byte_swap, - .bit_reverse, - .abs, - .load, - .fptrunc, - .fpext, - .intcast, - .intcast_safe, - .trunc, - .optional_payload, - .optional_payload_ptr, - .optional_payload_ptr_set, - .wrap_optional, - .unwrap_errunion_payload, - .unwrap_errunion_err, - .unwrap_errunion_payload_ptr, - .unwrap_errunion_err_ptr, - .errunion_payload_ptr_set, - .wrap_errunion_payload, - .wrap_errunion_err, - .struct_field_ptr_index_0, - .struct_field_ptr_index_1, - .struct_field_ptr_index_2, - .struct_field_ptr_index_3, - .get_union_tag, - .slice_len, - .slice_ptr, - .ptr_slice_len_ptr, - .ptr_slice_ptr_ptr, - .array_to_slice, - .int_from_float, - .int_from_float_optimized, - .int_from_float_safe, - .int_from_float_optimized_safe, - .float_from_int, - .splat, - .error_set_has_value, - .addrspace_cast, - .c_va_arg, - .c_va_copy, - => { - if (!checkType(data.ty_op.ty.toType(), zcu)) return false; - if (!checkRef(data.ty_op.operand, zcu)) return false; - }, - - .alloc, - .ret_ptr, - .c_va_start, - => { - if (!checkType(data.ty, zcu)) return false; - }, - - .ptr_add, - .ptr_sub, - .add_with_overflow, - .sub_with_overflow, - .mul_with_overflow, - .shl_with_overflow, - .slice, - .slice_elem_ptr, - .ptr_elem_ptr, - => { - const bin = air.extraData(Air.Bin, data.ty_pl.payload).data; - if (!checkType(data.ty_pl.ty.toType(), zcu)) return false; - if (!checkRef(bin.lhs, zcu)) return false; - if (!checkRef(bin.rhs, zcu)) return false; - }, - - .block, - .loop, - => { - const block = air.unwrapBlock(inst); - if (!checkType(block.ty, zcu)) return false; - if (!checkBody( - air, - block.body, - zcu, - )) return false; - }, - - .dbg_inline_block => { - const block = air.unwrapDbgBlock(inst); - if (!checkType(block.ty, zcu)) return false; - if (!checkBody( - air, - block.body, - zcu, - )) return false; - }, - - .sqrt, - .sin, - .cos, - .tan, - .exp, - .exp2, - .log, - .log2, - .log10, - .floor, - .ceil, - .round, - .trunc_float, - .neg, - .neg_optimized, - .is_null, - .is_non_null, - .is_null_ptr, - .is_non_null_ptr, - .is_err, - .is_non_err, - .is_err_ptr, - .is_non_err_ptr, - .ret, - .ret_safe, - .ret_load, - .is_named_enum_value, - .tag_name, - .error_name, - .cmp_lt_errors_len, - .c_va_end, - .set_err_return_trace, - => { - if (!checkRef(data.un_op, zcu)) return false; - }, - - .br, .switch_dispatch => { - if (!checkRef(data.br.operand, zcu)) return false; - }, - - .cmp_vector, - .cmp_vector_optimized, - => { - const extra = air.extraData(Air.VectorCmp, data.ty_pl.payload).data; - if (!checkType(data.ty_pl.ty.toType(), zcu)) return false; - if (!checkRef(extra.lhs, zcu)) return false; - if (!checkRef(extra.rhs, zcu)) return false; - }, - - .reduce, - .reduce_optimized, - => { - if (!checkRef(data.reduce.operand, zcu)) return false; - }, - - .struct_field_ptr, - .struct_field_val, - => { - const extra = air.extraData(Air.StructField, data.ty_pl.payload).data; - if (!checkType(data.ty_pl.ty.toType(), zcu)) return false; - if (!checkRef(extra.struct_operand, zcu)) return false; - }, - - .shuffle_one => { - const unwrapped = air.unwrapShuffleOne(zcu, inst); - if (!checkType(unwrapped.result_ty, zcu)) return false; - if (!checkRef(unwrapped.operand, zcu)) return false; - for (unwrapped.mask) |m| switch (m.unwrap()) { - .elem => {}, - .value => |val| if (!checkVal(.fromInterned(val), zcu)) return false, - }; - }, - - .shuffle_two => { - const unwrapped = air.unwrapShuffleTwo(zcu, inst); - if (!checkType(unwrapped.result_ty, zcu)) return false; - if (!checkRef(unwrapped.operand_a, zcu)) return false; - if (!checkRef(unwrapped.operand_b, zcu)) return false; - // No values to check because there are no comptime-known values other than undef - }, - - .cmpxchg_weak, - .cmpxchg_strong, - => { - const extra = air.extraData(Air.Cmpxchg, data.ty_pl.payload).data; - if (!checkType(data.ty_pl.ty.toType(), zcu)) return false; - if (!checkRef(extra.ptr, zcu)) return false; - if (!checkRef(extra.expected_value, zcu)) return false; - if (!checkRef(extra.new_value, zcu)) return false; - }, - - .aggregate_init => { - const ty = data.ty_pl.ty.toType(); - const elems_len: usize = @intCast(ty.arrayLen(zcu)); - const elems: []const Air.Inst.Ref = @ptrCast(air.extra.items[data.ty_pl.payload..][0..elems_len]); - if (!checkType(ty, zcu)) return false; - if (ty.zigTypeTag(zcu) == .@"struct") { - for (elems, 0..) |elem, elem_idx| { - if (ty.structFieldIsComptime(elem_idx, zcu)) continue; - if (!checkRef(elem, zcu)) return false; - } - } else { - for (elems) |elem| { - if (!checkRef(elem, zcu)) return false; - } - } - }, - - .union_init => { - const extra = air.extraData(Air.UnionInit, data.ty_pl.payload).data; - if (!checkType(data.ty_pl.ty.toType(), zcu)) return false; - if (!checkRef(extra.init, zcu)) return false; - }, - - .field_parent_ptr => { - const extra = air.extraData(Air.FieldParentPtr, data.ty_pl.payload).data; - if (!checkType(data.ty_pl.ty.toType(), zcu)) return false; - if (!checkRef(extra.field_ptr, zcu)) return false; - }, - - .atomic_load => { - if (!checkRef(data.atomic_load.ptr, zcu)) return false; - }, - - .prefetch => { - if (!checkRef(data.prefetch.ptr, zcu)) return false; - }, - - .runtime_nav_ptr => { - if (!checkType(.fromInterned(data.ty_nav.ty), zcu)) return false; - }, - - .select, - .mul_add, - .legalize_vec_store_elem, - => { - const bin = air.extraData(Air.Bin, data.pl_op.payload).data; - if (!checkRef(data.pl_op.operand, zcu)) return false; - if (!checkRef(bin.lhs, zcu)) return false; - if (!checkRef(bin.rhs, zcu)) return false; - }, - - .atomic_rmw => { - const extra = air.extraData(Air.AtomicRmw, data.pl_op.payload).data; - if (!checkRef(data.pl_op.operand, zcu)) return false; - if (!checkRef(extra.operand, zcu)) return false; - }, - - .call, - .call_always_tail, - .call_never_tail, - .call_never_inline, - => { - const call = air.unwrapCall(inst); - const args = call.args; - if (!checkRef(call.callee, zcu)) return false; - for (args) |arg| if (!checkRef(arg, zcu)) return false; - }, - - .dbg_var_ptr, - .dbg_var_val, - .dbg_arg_inline, - => { - if (!checkRef(data.pl_op.operand, zcu)) return false; - }, - - .@"try", .try_cold => { - const unwrapped_try = air.unwrapTry(inst); - if (!checkRef(unwrapped_try.error_union, zcu)) return false; - if (!checkBody( - air, - unwrapped_try.else_body, - zcu, - )) return false; - }, - - .try_ptr, .try_ptr_cold => { - const unwrapped_try = air.unwrapTryPtr(inst); - if (!checkType(unwrapped_try.error_union_payload_ptr_ty.toType(), zcu)) return false; - if (!checkRef(unwrapped_try.error_union_ptr, zcu)) return false; - if (!checkBody( - air, - unwrapped_try.else_body, - zcu, - )) return false; - }, - - .cond_br => { - const cond_br = air.unwrapCondBr(inst); - if (!checkRef(cond_br.condition, zcu)) return false; - if (!checkBody( - air, - cond_br.then_body, - zcu, - )) return false; - if (!checkBody( - air, - cond_br.else_body, - zcu, - )) return false; - }, - - .switch_br, .loop_switch_br => { - const switch_br = air.unwrapSwitch(inst); - if (!checkRef(switch_br.operand, zcu)) return false; - var it = switch_br.iterateCases(); - while (it.next()) |case| { - for (case.items) |item| if (!checkRef(item, zcu)) return false; - for (case.ranges) |range| { - if (!checkRef(range[0], zcu)) return false; - if (!checkRef(range[1], zcu)) return false; - } - if (!checkBody(air, case.body, zcu)) return false; - } - if (!checkBody(air, it.elseBody(), zcu)) return false; - }, - - .assembly => { - const unwrapped_asm = air.unwrapAsm(inst); - if (!checkType(data.ty_pl.ty.toType(), zcu)) return false; - // Luckily, we only care about the inputs and outputs, so we don't have to do - // the whole null-terminated string dance. - const outputs = unwrapped_asm.outputs; - const inputs = unwrapped_asm.inputs; - - for (outputs) |output| if (output != .none and !checkRef(output, zcu)) return false; - for (inputs) |input| if (input != .none and !checkRef(input, zcu)) return false; - }, - - .legalize_compiler_rt_call => { - const rt_call = air.unwrapCompilerRtCall(inst); - const args = rt_call.args; - for (args) |arg| if (!checkRef(arg, zcu)) return false; - }, - - .trap, - .breakpoint, - .ret_addr, - .frame_addr, - .unreach, - .wasm_memory_size, - .wasm_memory_grow, - .work_item_id, - .work_group_size, - .work_group_id, - .dbg_stmt, - .dbg_empty_stmt, - .err_return_trace, - .save_err_return_trace_index, - .repeat, - => {}, - } - } - return true; -} - -fn checkRef(ref: Air.Inst.Ref, zcu: *Zcu) bool { - const ip_index = ref.toInterned() orelse { - // This operand refers back to a previous instruction. - // We have already checked that instruction's type. - // So, there's no need to check this operand's type. - return true; - }; - return checkVal(Value.fromInterned(ip_index), zcu); -} - -pub fn checkVal(val: Value, zcu: *Zcu) bool { - const ty = val.typeOf(zcu); - if (!checkType(ty, zcu)) return false; - if (val.isUndef(zcu)) return true; - if (ty.toIntern() == .type_type and !checkType(val.toType(), zcu)) return false; - // Check for lazy values - switch (zcu.intern_pool.indexToKey(val.toIntern())) { - .int => |int| switch (int.storage) { - .u64, .i64, .big_int => return true, - .lazy_align, .lazy_size => |ty_index| { - return checkType(Type.fromInterned(ty_index), zcu); - }, - }, - else => return true, - } -} - -pub fn checkType(ty: Type, zcu: *Zcu) bool { - const ip = &zcu.intern_pool; - if (ty.isGenericPoison()) return true; - return switch (ty.zigTypeTag(zcu)) { - .type, - .void, - .bool, - .noreturn, - .int, - .float, - .error_set, - .@"enum", - .@"opaque", - .vector, - // These types can appear due to some dummy instructions Sema introduces and expects to be omitted by Liveness. - // It's a little silly -- but fine, we'll return `true`. - .comptime_float, - .comptime_int, - .undefined, - .null, - .enum_literal, - => true, - - .frame, - .@"anyframe", - => @panic("TODO Air.types_resolved.checkType async frames"), - - .optional => checkType(ty.childType(zcu), zcu), - .error_union => checkType(ty.errorUnionPayload(zcu), zcu), - .pointer => checkType(ty.childType(zcu), zcu), - .array => checkType(ty.childType(zcu), zcu), - - .@"fn" => { - const info = zcu.typeToFunc(ty).?; - for (0..info.param_types.len) |i| { - const param_ty = info.param_types.get(ip)[i]; - if (!checkType(Type.fromInterned(param_ty), zcu)) return false; - } - return checkType(Type.fromInterned(info.return_type), zcu); - }, - .@"struct" => switch (ip.indexToKey(ty.toIntern())) { - .struct_type => { - const struct_obj = zcu.typeToStruct(ty).?; - return switch (struct_obj.layout) { - .@"packed" => struct_obj.backingIntTypeUnordered(ip) != .none, - .auto, .@"extern" => struct_obj.flagsUnordered(ip).fully_resolved, - }; - }, - .tuple_type => |tuple| { - for (0..tuple.types.len) |i| { - const field_is_comptime = tuple.values.get(ip)[i] != .none; - if (field_is_comptime) continue; - const field_ty = tuple.types.get(ip)[i]; - if (!checkType(Type.fromInterned(field_ty), zcu)) return false; - } - return true; - }, - else => unreachable, - }, - .@"union" => return zcu.typeToUnion(ty).?.flagsUnordered(ip).status == .fully_resolved, - }; -} diff --git a/src/Compilation.zig b/src/Compilation.zig index 521de0b427c4a9cba23daab8e46521bc1ec6ef59..14046f38fc2e41c9aa50efa7586f6815ba67aeb6 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -126,15 +126,7 @@ oneshot_prelink_tasks: std.ArrayList(link.PrelinkTask), /// work is queued or not. queued_jobs: QueuedJobs, -work_queues: [ - len: { - var len: usize = 0; - for (std.enums.values(Job.Tag)) |tag| { - len = @max(Job.stage(tag) + 1, len); - } - break :len len; - } -]std.Deque(Job), +work_queues: [2]std.Deque(Job), /// These jobs are to invoke the Clang compiler to create an object file, which /// gets linked with the Compilation. @@ -990,35 +982,27 @@ const Job = union(enum) { update_line_number: InternPool.TrackedInst.Index, /// The `AnalUnit`, which is *not* a `func`, must be semantically analyzed. /// This may be its first time being analyzed, or it may be outdated. - /// If the unit is a test function, an `analyze_func` job will then be queued. - analyze_comptime_unit: InternPool.AnalUnit, - /// This function must be semantically analyzed. - /// This may be its first time being analyzed, or it may be outdated. - /// After analysis, a `codegen_func` job will be queued. - /// These must be separate jobs to ensure any needed type resolution occurs *before* codegen. - /// This job is separate from `analyze_comptime_unit` because it has a different priority. - analyze_func: InternPool.Index, + /// If the unit is a function, a `codegen_func` job will be queued after analysis completes. + /// If the unit is a *test* function, an `analyze_func` job will also be queued. + analyze_unit: InternPool.AnalUnit, /// The main source file for the module needs to be analyzed. analyze_mod: *Package.Module, - /// Fully resolve the given `struct` or `union` type. - resolve_type_fully: InternPool.Index, /// The value is the index into `windows_libs`. windows_import_lib: usize, - const Tag = @typeInfo(Job).@"union".tag_type.?; - fn stage(tag: Tag) usize { - return switch (tag) { - // Prioritize functions so that codegen can get to work on them on a - // separate thread, while Sema goes back to its own work. - .resolve_type_fully, .analyze_func, .codegen_func => 0, + fn stage(job: *const Job) usize { + // Prioritize functions so that codegen can get to work on them on a + // separate thread, while Sema goes back to its own work. + return switch (job.*) { + .codegen_func => 0, + .analyze_unit => |unit| switch (unit.unwrap()) { + .func => 0, + else => 1, + }, else => 1, }; } - comptime { - // Job dependencies - assert(stage(.resolve_type_fully) <= stage(.codegen_func)); - } }; pub const CObject = struct { @@ -3728,7 +3712,9 @@ const Header = extern struct { src_hash_deps_len: u32, nav_val_deps_len: u32, nav_ty_deps_len: u32, - interned_deps_len: u32, + type_layout_deps_len: u32, + type_inits_deps_len: u32, + func_ies_deps_len: u32, zon_file_deps_len: u32, embed_file_deps_len: u32, namespace_deps_len: u32, @@ -3776,7 +3762,9 @@ pub fn saveState(comp: *Compilation) !void { .src_hash_deps_len = @intCast(ip.src_hash_deps.count()), .nav_val_deps_len = @intCast(ip.nav_val_deps.count()), .nav_ty_deps_len = @intCast(ip.nav_ty_deps.count()), - .interned_deps_len = @intCast(ip.interned_deps.count()), + .type_layout_deps_len = @intCast(ip.type_layout_deps.count()), + .type_inits_deps_len = @intCast(ip.type_inits_deps.count()), + .func_ies_deps_len = @intCast(ip.func_ies_deps.count()), .zon_file_deps_len = @intCast(ip.zon_file_deps.count()), .embed_file_deps_len = @intCast(ip.embed_file_deps.count()), .namespace_deps_len = @intCast(ip.namespace_deps.count()), @@ -3800,7 +3788,7 @@ pub fn saveState(comp: *Compilation) !void { }, }); - try bufs.ensureTotalCapacityPrecise(22 + 9 * pt_headers.items.len); + try bufs.ensureTotalCapacityPrecise(26 + 9 * pt_headers.items.len); addBuf(&bufs, mem.asBytes(&header)); addBuf(&bufs, @ptrCast(pt_headers.items)); @@ -3810,8 +3798,12 @@ pub fn saveState(comp: *Compilation) !void { addBuf(&bufs, @ptrCast(ip.nav_val_deps.values())); addBuf(&bufs, @ptrCast(ip.nav_ty_deps.keys())); addBuf(&bufs, @ptrCast(ip.nav_ty_deps.values())); - addBuf(&bufs, @ptrCast(ip.interned_deps.keys())); - addBuf(&bufs, @ptrCast(ip.interned_deps.values())); + addBuf(&bufs, @ptrCast(ip.type_layout_deps.keys())); + addBuf(&bufs, @ptrCast(ip.type_layout_deps.values())); + addBuf(&bufs, @ptrCast(ip.type_inits_deps.keys())); + addBuf(&bufs, @ptrCast(ip.type_inits_deps.values())); + addBuf(&bufs, @ptrCast(ip.func_ies_deps.keys())); + addBuf(&bufs, @ptrCast(ip.func_ies_deps.values())); addBuf(&bufs, @ptrCast(ip.zon_file_deps.keys())); addBuf(&bufs, @ptrCast(ip.zon_file_deps.values())); addBuf(&bufs, @ptrCast(ip.embed_file_deps.keys())); @@ -4489,7 +4481,7 @@ pub fn addModuleErrorMsg( const root_name: ?[]const u8 = switch (ref.referencer.unwrap()) { .@"comptime" => "comptime", .nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip), - .type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), + .type_layout, .type_inits => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip), .memoized_state => null, }; @@ -4900,15 +4892,7 @@ fn performAllTheWork( // If there's no work queued, check if there's anything outdated // which we need to work on, and queue it if so. if (try zcu.findOutdatedToAnalyze()) |outdated| { - try comp.queueJob(switch (outdated.unwrap()) { - .func => |f| .{ .analyze_func = f }, - .memoized_state, - .@"comptime", - .nav_ty, - .nav_val, - .type, - => .{ .analyze_comptime_unit = outdated }, - }); + try comp.queueJob(.{ .analyze_unit = outdated }); continue; } zcu.sema_prog_node.end(); @@ -5151,7 +5135,7 @@ fn dispatchPrelinkWork(comp: *Compilation, main_progress_node: std.Progress.Node const JobError = Allocator.Error || Io.Cancelable; pub fn queueJob(comp: *Compilation, job: Job) !void { - try comp.work_queues[Job.stage(job)].pushBack(comp.gpa, job); + try comp.work_queues[job.stage()].pushBack(comp.gpa, job); } pub fn queueJobs(comp: *Compilation, jobs: []const Job) !void { @@ -5166,13 +5150,24 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v var owned_air: ?Air = func.air; defer if (owned_air) |*air| air.deinit(gpa); - if (!owned_air.?.typesFullyResolved(zcu)) { - // Type resolution failed in a way which affects this function. This is a transitive - // failure, but it doesn't need recording, because this function semantically depends - // on the failed type, so when it is changed the function is updated. - zcu.codegen_prog_node.completeOne(); - comp.link_prog_node.completeOne(); - return; + { + const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid)); + defer pt.deactivate(); + pt.resolveAirTypesForCodegen(&owned_air.?) catch |err| switch (err) { + error.OutOfMemory, + error.Canceled, + => |e| return e, + + error.AnalysisFail => { + // Type resolution failed, making codegen of this function impossible. This + // is a transitive failure, but it doesn't need recording, because this + // function semantically depends on the failed type, so when it is changed + // the function will be updated. + zcu.codegen_prog_node.completeOne(); + comp.link_prog_node.completeOne(); + return; + }, + }; } // Some linkers need to refer to the AIR. In that case, the linker is not running @@ -5198,45 +5193,54 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v } } assert(nav.status == .fully_resolved); - if (!Air.valFullyResolved(zcu.navValue(nav_index), zcu)) { - // Type resolution failed in a way which affects this `Nav`. This is a transitive - // failure, but it doesn't need recording, because this `Nav` semantically depends - // on the failed type, so when it is changed the `Nav` will be updated. - comp.link_prog_node.completeOne(); - return; + { + const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid)); + defer pt.deactivate(); + pt.resolveValueTypesForCodegen(zcu.navValue(nav_index)) catch |err| switch (err) { + error.OutOfMemory, + error.Canceled, + => |e| return e, + + error.AnalysisFail => { + // Type resolution failed, making codegen of this `Nav` impossible. This is + // a transitive failure, but it doesn't need recording, because this `Nav` + // semantically depends on the failed type, so when it is changed the value + // of the `Nav` will be updated. + comp.link_prog_node.completeOne(); + return; + }, + }; } try comp.link_queue.enqueueZcu(comp, tid, .{ .link_nav = nav_index }); }, .link_type => |ty| { const zcu = comp.zcu.?; if (zcu.failed_types.fetchSwapRemove(ty)) |*entry| entry.value.deinit(zcu.gpa); - if (!Air.typeFullyResolved(.fromInterned(ty), zcu)) { - // Type resolution failed in a way which affects this type. This is a transitive - // failure, but it doesn't need recording, because this type semantically depends - // on the failed type, so when that is changed, this type will be updated. - comp.link_prog_node.completeOne(); - return; + { + const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid)); + defer pt.deactivate(); + pt.resolveTypeForCodegen(.fromInterned(ty)) catch |err| switch (err) { + error.OutOfMemory, + error.Canceled, + => |e| return e, + + error.AnalysisFail => { + // Type resolution failed, making codegen of this type impossible. This is + // a transitive failure, but it doesn't need recording, because this type + // semantically depends on the failed type, so when it is changed the type + // will be updated appropriately. + comp.link_prog_node.completeOne(); + return; + }, + }; } try comp.link_queue.enqueueZcu(comp, tid, .{ .link_type = ty }); }, .update_line_number => |tracked_inst| { try comp.link_queue.enqueueZcu(comp, tid, .{ .update_line_number = tracked_inst }); }, - .analyze_func => |func| { - const tracy_trace = traceNamed(@src(), "analyze_func"); - defer tracy_trace.end(); - - const pt: Zcu.PerThread = .activate(comp.zcu.?, tid); - defer pt.deactivate(); - - pt.ensureFuncBodyUpToDate(func) catch |err| switch (err) { - error.OutOfMemory => |e| return e, - error.Canceled => |e| return e, - error.AnalysisFail => return, - }; - }, - .analyze_comptime_unit => |unit| { - const tracy_trace = traceNamed(@src(), "analyze_comptime_unit"); + .analyze_unit => |unit| { + const tracy_trace = traceNamed(@src(), "analyze_unit"); defer tracy_trace.end(); const pt: Zcu.PerThread = .activate(comp.zcu.?, tid); @@ -5246,9 +5250,10 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v .@"comptime" => |cu| pt.ensureComptimeUnitUpToDate(cu), .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav), .nav_val => |nav| pt.ensureNavValUpToDate(nav), - .type => |ty| if (pt.ensureTypeUpToDate(ty)) |_| {} else |err| err, + .type_layout => |ty| pt.ensureTypeLayoutUpToDate(.fromInterned(ty)), + .type_inits => |ty| pt.ensureTypeInitsUpToDate(.fromInterned(ty)), .memoized_state => |stage| pt.ensureMemoizedStateUpToDate(stage), - .func => unreachable, + .func => |func| pt.ensureFuncBodyUpToDate(func), }; maybe_err catch |err| switch (err) { error.OutOfMemory => |e| return e, @@ -5275,27 +5280,15 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v try pt.zcu.ensureFuncBodyAnalysisQueued(ip.getNav(nav).status.fully_resolved.val); } }, - .resolve_type_fully => |ty| { - const tracy_trace = traceNamed(@src(), "resolve_type_fully"); - defer tracy_trace.end(); - - const pt: Zcu.PerThread = .activate(comp.zcu.?, tid); - defer pt.deactivate(); - Type.fromInterned(ty).resolveFully(pt) catch |err| switch (err) { - error.OutOfMemory, error.Canceled => |e| return e, - error.AnalysisFail => return, - }; - }, .analyze_mod => |mod| { const tracy_trace = traceNamed(@src(), "analyze_mod"); defer tracy_trace.end(); const pt: Zcu.PerThread = .activate(comp.zcu.?, tid); defer pt.deactivate(); - pt.semaMod(mod) catch |err| switch (err) { - error.OutOfMemory, error.Canceled => |e| return e, - error.AnalysisFail => return, - }; + + const mod_root_file = pt.zcu.module_roots.get(mod).?.unwrap().?; + try pt.ensureFileAnalyzed(mod_root_file); }, .windows_import_lib => |index| { const tracy_trace = traceNamed(@src(), "windows_import_lib"); diff --git a/src/IncrementalDebugServer.zig b/src/IncrementalDebugServer.zig index b4bc2c812ebd8ad67dce61738989efca3f388058..ce40844057d8e34d409f6ba78eb1b6b59f9085dc 100644 --- a/src/IncrementalDebugServer.zig +++ b/src/IncrementalDebugServer.zig @@ -306,12 +306,8 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const try w.print("[{d}] ", .{i}); switch (dependee) { .src_hash, .namespace, .namespace_name, .zon_file, .embed_file => try w.print("{f}", .{zcu.fmtDependee(dependee)}), - .nav_val, .nav_ty => |nav| try w.print("{s} {d}", .{ @tagName(dependee), @intFromEnum(nav) }), - .interned => |ip_index| switch (ip.indexToKey(ip_index)) { - .struct_type, .union_type, .enum_type => try w.print("type {d}", .{@intFromEnum(ip_index)}), - .func => try w.print("func {d}", .{@intFromEnum(ip_index)}), - else => unreachable, - }, + .nav_val, .nav_ty => |nav| try w.print("{t} {d}", .{ dependee, @intFromEnum(nav) }), + .type_layout, .type_inits, .func_ies => |ip_index| try w.print("{t} {d}", .{ dependee, @intFromEnum(ip_index) }), .memoized_state => |stage| try w.print("memoized_state {s}", .{@tagName(stage)}), } try w.writeByte('\n'); @@ -376,8 +372,10 @@ fn parseAnalUnit(str: []const u8) ?AnalUnit { return .wrap(.{ .nav_val = @enumFromInt(parseIndex(idx_str) orelse return null) }); } else if (std.mem.eql(u8, kind, "nav_ty")) { return .wrap(.{ .nav_ty = @enumFromInt(parseIndex(idx_str) orelse return null) }); - } else if (std.mem.eql(u8, kind, "type")) { - return .wrap(.{ .type = @enumFromInt(parseIndex(idx_str) orelse return null) }); + } else if (std.mem.eql(u8, kind, "type_layout")) { + return .wrap(.{ .type_layout = @enumFromInt(parseIndex(idx_str) orelse return null) }); + } else if (std.mem.eql(u8, kind, "type_inits")) { + return .wrap(.{ .type_inits = @enumFromInt(parseIndex(idx_str) orelse return null) }); } else if (std.mem.eql(u8, kind, "func")) { return .wrap(.{ .func = @enumFromInt(parseIndex(idx_str) orelse return null) }); } else if (std.mem.eql(u8, kind, "memoized_state")) { diff --git a/src/InternPool.zig b/src/InternPool.zig index 595bedd5473653ccc2885b3181d5007dfe0b926e..ed4666a5b91a940bab9f91146c2095911c0909ef 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -47,11 +47,15 @@ nav_val_deps: std.AutoArrayHashMapUnmanaged(Nav.Index, DepEntry.Index), /// Dependencies on the type of a Nav. /// Value is index into `dep_entries` of the first dependency on this Nav value. nav_ty_deps: std.AutoArrayHashMapUnmanaged(Nav.Index, DepEntry.Index), -/// Dependencies on an interned value, either: -/// * a runtime function (invalidated when its IES changes) -/// * a container type requiring resolution (invalidated when the type must be recreated at a new index) -/// Value is index into `dep_entries` of the first dependency on this interned value. -interned_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), +/// Dependencies on a function's inferred error set. Key is the function body, not the IES. +/// Value is index into `dep_entries` of the first dependency on this function's IES. +func_ies_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), +/// Dependencies on the resolved layout of a `struct` or `union` type. +/// Value is index into `dep_entries` of the first dependency on this type's layout. +type_layout_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), +/// Dependencies on the resolved initializers of a `struct` or `enum` type. +/// Value is index into `dep_entries` of the first dependency on this type's inits. +type_inits_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), /// Dependencies on a ZON file. Triggered by `@import` of ZON. /// Value is index into `dep_entries` of the first dependency on this ZON file. zon_file_deps: std.AutoArrayHashMapUnmanaged(FileIndex, DepEntry.Index), @@ -104,7 +108,9 @@ pub const empty: InternPool = .{ .src_hash_deps = .empty, .nav_val_deps = .empty, .nav_ty_deps = .empty, - .interned_deps = .empty, + .func_ies_deps = .empty, + .type_layout_deps = .empty, + .type_inits_deps = .empty, .zon_file_deps = .empty, .embed_file_deps = .empty, .namespace_deps = .empty, @@ -415,7 +421,8 @@ pub const AnalUnit = packed struct(u64) { @"comptime", nav_val, nav_ty, - type, + type_layout, + type_inits, func, memoized_state, }; @@ -427,9 +434,11 @@ pub const AnalUnit = packed struct(u64) { nav_val: Nav.Index, /// This `AnalUnit` resolves the type of the given `Nav`. nav_ty: Nav.Index, - /// This `AnalUnit` resolves the given `struct`/`union`/`enum` type. - /// Generated tag enums are never used here (they do not undergo type resolution). - type: InternPool.Index, + /// This `AnalUnit` resolves the layout of the given `struct` or `union` type. + type_layout: InternPool.Index, + /// This `AnalUnit` resolves the field inits of the given `struct` or `enum` type. + /// The type may be a union's auto-generated tag enum, if the union has explicit field values. + type_inits: InternPool.Index, /// This `AnalUnit` analyzes the body of the given runtime function. func: InternPool.Index, /// This `AnalUnit` resolves all state which is memoized in fields on `Zcu`. @@ -840,7 +849,10 @@ pub const Dependee = union(enum) { src_hash: TrackedInst.Index, nav_val: Nav.Index, nav_ty: Nav.Index, - interned: Index, + /// Index is the function, not its IES. + func_ies: Index, + type_layout: Index, + type_inits: Index, zon_file: FileIndex, embed_file: Zcu.EmbedFile.Index, namespace: TrackedInst.Index, @@ -892,7 +904,9 @@ pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyI .src_hash => |x| ip.src_hash_deps.get(x), .nav_val => |x| ip.nav_val_deps.get(x), .nav_ty => |x| ip.nav_ty_deps.get(x), - .interned => |x| ip.interned_deps.get(x), + .func_ies => |x| ip.func_ies_deps.get(x), + .type_layout => |x| ip.type_layout_deps.get(x), + .type_inits => |x| ip.type_inits_deps.get(x), .zon_file => |x| ip.zon_file_deps.get(x), .embed_file => |x| ip.embed_file_deps.get(x), .namespace => |x| ip.namespace_deps.get(x), @@ -965,7 +979,9 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend .src_hash => ip.src_hash_deps, .nav_val => ip.nav_val_deps, .nav_ty => ip.nav_ty_deps, - .interned => ip.interned_deps, + .func_ies => ip.func_ies_deps, + .type_layout => ip.type_layout_deps, + .type_inits => ip.type_inits_deps, .zon_file => ip.zon_file_deps, .embed_file => ip.embed_file_deps, .namespace => ip.namespace_deps, @@ -2065,15 +2081,15 @@ pub const Key = union(enum) { simple_type: SimpleType, /// This represents a struct that has been explicitly declared in source code, /// or was created with `@Struct`. It is unique and based on a declaration. - struct_type: NamespaceType, + struct_type: ContainerType, /// This is a tuple type. Tuples are logically similar to structs, but have some /// important differences in semantics; they do not undergo staged type resolution, /// so cannot be self-referential, and they are not considered container/namespace /// types, so cannot have declarations and have structural equality properties. tuple_type: TupleType, - union_type: NamespaceType, - opaque_type: NamespaceType, - enum_type: NamespaceType, + union_type: ContainerType, + opaque_type: ContainerType, + enum_type: ContainerType, func_type: FuncType, error_set_type: ErrorSetType, /// The payload is the function body, either a `func_decl` or `func_instance`. @@ -2211,16 +2227,10 @@ pub const Key = union(enum) { /// * `loadUnionType` /// * `loadEnumType` /// * `loadOpaqueType` - pub const NamespaceType = union(enum) { + pub const ContainerType = union(enum) { /// This type corresponds to an actual source declaration, e.g. `struct { ... }`. /// It is hashed based on its ZIR instruction index and set of captures. declared: Declared, - /// This type is an automatically-generated enum tag type for a union. - /// It is hashed based on the index of the union type it corresponds to. - generated_tag: struct { - /// The union for which this is a tag type. - union_type: Index, - }, /// This type originates from a reification via `@Enum`, `@Struct`, `@Union` or from an anonymous initialization. /// It is hashed based on its ZIR instruction index and fields, attributes, etc. /// To avoid making this key overly complex, the type-specific data is hashed by Sema. @@ -2231,10 +2241,17 @@ pub const Key = union(enum) { /// A hash of this type's attributes, fields, etc, generated by Sema. type_hash: u64, }, + /// This type is an automatically-generated enum tag type for this union type. + /// It is hashed based on the index of the union type it corresponds to. + generated_union_tag: Index, pub const Declared = struct { /// A `struct_decl`, `union_decl`, `enum_decl`, or `opaque_decl` instruction. zir_index: TrackedInst.Index, + /// If the type declaration had an argument type (tag type or packed backing type), this + /// is that type. Otherwise, this is `.none`. It is always `.none` for `opaque` types as + /// `opaque(T)` does not exist. + arg_ty: Index, /// The captured values of this type. These values must be fully resolved per the language spec. captures: union(enum) { owned: CaptureValue.Slice, @@ -2254,7 +2271,6 @@ pub const Key = union(enum) { noalias_bits: u32, cc: std.builtin.CallingConvention, is_var_args: bool, - is_generic: bool, is_noinline: bool, pub fn paramIsComptime(self: @This(), i: u5) bool { @@ -2273,7 +2289,6 @@ pub const Key = union(enum) { a.comptime_bits == b.comptime_bits and a.noalias_bits == b.noalias_bits and a.is_var_args == b.is_var_args and - a.is_generic == b.is_generic and a.is_noinline == b.is_noinline and std.meta.eql(a.cc, b.cc); } @@ -2287,7 +2302,6 @@ pub const Key = union(enum) { std.hash.autoHash(hasher, self.noalias_bits); std.hash.autoHash(hasher, self.cc); std.hash.autoHash(hasher, self.is_var_args); - std.hash.autoHash(hasher, self.is_generic); std.hash.autoHash(hasher, self.is_noinline); } }; @@ -2471,8 +2485,6 @@ pub const Key = union(enum) { u64: u64, i64: i64, big_int: BigIntConst, - lazy_align: Index, - lazy_size: Index, /// Big enough to fit any non-BigInt value pub const BigIntSpace = struct { @@ -2485,7 +2497,6 @@ pub const Key = union(enum) { return switch (storage) { .big_int => |x| x, inline .u64, .i64 => |x| BigIntMutable.init(&space.limbs, x).toConst(), - .lazy_align, .lazy_size => unreachable, }; } }; @@ -2734,6 +2745,7 @@ pub const Key = union(enum) { switch (namespace_type) { .declared => |declared| { std.hash.autoHash(&hasher, declared.zir_index); + std.hash.autoHash(&hasher, declared.arg_ty); const captures = switch (declared.captures) { .owned => |cvs| cvs.get(ip), .external => |cvs| cvs, @@ -2742,13 +2754,13 @@ pub const Key = union(enum) { std.hash.autoHash(&hasher, cv); } }, - .generated_tag => |generated_tag| { - std.hash.autoHash(&hasher, generated_tag.union_type); - }, .reified => |reified| { std.hash.autoHash(&hasher, reified.zir_index); std.hash.autoHash(&hasher, reified.type_hash); }, + .generated_union_tag => |union_type| { + std.hash.autoHash(&hasher, union_type); + }, } return hasher.final(); }, @@ -2756,23 +2768,12 @@ pub const Key = union(enum) { .int => |int| { var hasher = Hash.init(seed); // Canonicalize all integers by converting them to BigIntConst. - switch (int.storage) { - .u64, .i64, .big_int => { - var buffer: Key.Int.Storage.BigIntSpace = undefined; - const big_int = int.storage.toBigInt(&buffer); + var buffer: Key.Int.Storage.BigIntSpace = undefined; + const big_int = int.storage.toBigInt(&buffer); - std.hash.autoHash(&hasher, int.ty); - std.hash.autoHash(&hasher, big_int.positive); - for (big_int.limbs) |limb| std.hash.autoHash(&hasher, limb); - }, - .lazy_align, .lazy_size => |lazy_ty| { - std.hash.autoHash( - &hasher, - @as(@typeInfo(Key.Int.Storage).@"union".tag_type.?, int.storage), - ); - std.hash.autoHash(&hasher, lazy_ty); - }, - } + std.hash.autoHash(&hasher, int.ty); + std.hash.autoHash(&hasher, big_int.positive); + for (big_int.limbs) |limb| std.hash.autoHash(&hasher, limb); return hasher.final(); }, @@ -3102,27 +3103,16 @@ pub const Key = union(enum) { .u64 => |bb| aa == bb, .i64 => |bb| aa == bb, .big_int => |bb| bb.orderAgainstScalar(aa) == .eq, - .lazy_align, .lazy_size => false, }, .i64 => |aa| switch (b_info.storage) { .u64 => |bb| aa == bb, .i64 => |bb| aa == bb, .big_int => |bb| bb.orderAgainstScalar(aa) == .eq, - .lazy_align, .lazy_size => false, }, .big_int => |aa| switch (b_info.storage) { .u64 => |bb| aa.orderAgainstScalar(bb) == .eq, .i64 => |bb| aa.orderAgainstScalar(bb) == .eq, .big_int => |bb| aa.eql(bb), - .lazy_align, .lazy_size => false, - }, - .lazy_align => |aa| switch (b_info.storage) { - .u64, .i64, .big_int, .lazy_size => false, - .lazy_align => |bb| aa == bb, - }, - .lazy_size => |aa| switch (b_info.storage) { - .u64, .i64, .big_int, .lazy_align => false, - .lazy_size => |bb| aa == bb, }, }; }, @@ -3165,6 +3155,7 @@ pub const Key = union(enum) { .declared => |a_d| { const b_d = b_info.declared; if (a_d.zir_index != b_d.zir_index) return false; + if (a_d.arg_ty != b_d.arg_ty) return false; const a_captures = switch (a_d.captures) { .owned => |s| s.get(ip), .external => |cvs| cvs, @@ -3175,12 +3166,12 @@ pub const Key = union(enum) { }; return std.mem.eql(u32, @ptrCast(a_captures), @ptrCast(b_captures)); }, - .generated_tag => |a_gt| return a_gt.union_type == b_info.generated_tag.union_type, .reified => |a_r| { const b_r = b_info.reified; return a_r.zir_index == b_r.zir_index and a_r.type_hash == b_r.type_hash; }, + .generated_union_tag => |a_union_ty| return a_union_ty == b_info.generated_union_tag, } }, .aggregate => |a_info| { @@ -3313,374 +3304,40 @@ pub const Key = union(enum) { } }; -pub const RequiresComptime = enum(u2) { no, yes, unknown, wip }; - -// Unlike `Tag.TypeUnion` which is an encoding, and `Key.UnionType` which is a -// minimal hashmap key, this type is a convenience type that contains info -// needed by semantic analysis. -pub const LoadedUnionType = struct { - tid: Zcu.PerThread.Id, - /// The index of the `Tag.TypeUnion` payload. - extra_index: u32, - // TODO: the non-fqn will be needed by the new dwarf structure - /// The name of this union type. - name: NullTerminatedString, - /// Represents the declarations inside this union. - namespace: NamespaceIndex, - /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. - /// Otherwise, this is `.none`. - name_nav: Nav.Index.Optional, - /// The enum tag type. - enum_tag_ty: Index, - /// List of field types in declaration order. - /// These are `none` until `status` is `have_field_types` or `have_layout`. - field_types: Index.Slice, - /// List of field alignments in declaration order. - /// `none` means the ABI alignment of the type. - /// If this slice has length 0 it means all elements are `none`. - field_aligns: Alignment.Slice, - /// Index of the union_decl or reify ZIR instruction. - zir_index: TrackedInst.Index, - captures: CaptureValue.Slice, - - pub const RuntimeTag = enum(u2) { - none, - safety, - tagged, - - pub fn hasTag(self: RuntimeTag) bool { - return switch (self) { - .none => false, - .tagged, .safety => true, - }; - } - }; - - pub const Status = enum(u3) { - none, - field_types_wip, - have_field_types, - layout_wip, - have_layout, - fully_resolved_wip, - /// The types and all its fields have had their layout resolved. - /// Even through pointer, which `have_layout` does not ensure. - fully_resolved, - - pub fn haveFieldTypes(status: Status) bool { - return switch (status) { - .none, - .field_types_wip, - => false, - .have_field_types, - .layout_wip, - .have_layout, - .fully_resolved_wip, - .fully_resolved, - => true, - }; - } - - pub fn haveLayout(status: Status) bool { - return switch (status) { - .none, - .field_types_wip, - .have_field_types, - .layout_wip, - => false, - .have_layout, - .fully_resolved_wip, - .fully_resolved, - => true, - }; - } - }; - - pub fn loadTagType(self: LoadedUnionType, ip: *const InternPool) LoadedEnumType { - return ip.loadEnumType(self.enum_tag_ty); - } - - /// Pointer to an enum type which is used for the tag of the union. - /// This type is created even for untagged unions, even when the memory - /// layout does not store the tag. - /// Whether zig chooses this type or the user specifies it, it is stored here. - /// This will be set to the null type until status is `have_field_types`. - /// This accessor is provided so that the tag type can be mutated, and so that - /// when it is mutated, the mutations are observed. - /// The returned pointer expires with any addition to the `InternPool`. - fn tagTypePtr(self: LoadedUnionType, ip: *const InternPool) *Index { - const extra = ip.getLocalShared(self.tid).extra.acquire(); - const field_index = std.meta.fieldIndex(Tag.TypeUnion, "tag_ty").?; - return @ptrCast(&extra.view().items(.@"0")[self.extra_index + field_index]); - } - - pub fn tagTypeUnordered(u: LoadedUnionType, ip: *const InternPool) Index { - return @atomicLoad(Index, u.tagTypePtr(ip), .unordered); - } - - pub fn setTagType(u: LoadedUnionType, ip: *InternPool, io: Io, tag_type: Index) void { - const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - @atomicStore(Index, u.tagTypePtr(ip), tag_type, .release); - } - - /// The returned pointer expires with any addition to the `InternPool`. - fn flagsPtr(self: LoadedUnionType, ip: *const InternPool) *Tag.TypeUnion.Flags { - const extra = ip.getLocalShared(self.tid).extra.acquire(); - const field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?; - return @ptrCast(&extra.view().items(.@"0")[self.extra_index + field_index]); - } - - pub fn flagsUnordered(u: LoadedUnionType, ip: *const InternPool) Tag.TypeUnion.Flags { - return @atomicLoad(Tag.TypeUnion.Flags, u.flagsPtr(ip), .unordered); - } - - pub fn setStatus(u: LoadedUnionType, ip: *InternPool, io: Io, status: Status) void { - const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = u.flagsPtr(ip); - var flags = flags_ptr.*; - flags.status = status; - @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); - } - - pub fn setStatusIfLayoutWip(u: LoadedUnionType, ip: *InternPool, io: Io, status: Status) void { - const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = u.flagsPtr(ip); - var flags = flags_ptr.*; - if (flags.status == .layout_wip) flags.status = status; - @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); - } - - pub fn setAlignment(u: LoadedUnionType, ip: *InternPool, io: Io, alignment: Alignment) void { - const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = u.flagsPtr(ip); - var flags = flags_ptr.*; - flags.alignment = alignment; - @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); - } - - pub fn assumeRuntimeBitsIfFieldTypesWip(u: LoadedUnionType, ip: *InternPool, io: Io) bool { - const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = u.flagsPtr(ip); - var flags = flags_ptr.*; - defer if (flags.status == .field_types_wip) { - flags.assumed_runtime_bits = true; - @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); - }; - return flags.status == .field_types_wip; - } - - pub fn requiresComptime(u: LoadedUnionType, ip: *const InternPool) RequiresComptime { - return u.flagsUnordered(ip).requires_comptime; - } - - pub fn setRequiresComptimeWip(u: LoadedUnionType, ip: *InternPool, io: Io) RequiresComptime { - const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = u.flagsPtr(ip); - var flags = flags_ptr.*; - defer if (flags.requires_comptime == .unknown) { - flags.requires_comptime = .wip; - @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); - }; - return flags.requires_comptime; - } - - pub fn setRequiresComptime(u: LoadedUnionType, ip: *InternPool, io: Io, requires_comptime: RequiresComptime) void { - assert(requires_comptime != .wip); // see setRequiresComptimeWip - - const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = u.flagsPtr(ip); - var flags = flags_ptr.*; - flags.requires_comptime = requires_comptime; - @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); - } - - pub fn assumePointerAlignedIfFieldTypesWip(u: LoadedUnionType, ip: *InternPool, io: Io, ptr_align: Alignment) bool { - const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = u.flagsPtr(ip); - var flags = flags_ptr.*; - defer if (flags.status == .field_types_wip) { - flags.alignment = ptr_align; - flags.assumed_pointer_aligned = true; - @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); - }; - return flags.status == .field_types_wip; - } - - /// The returned pointer expires with any addition to the `InternPool`. - fn sizePtr(self: LoadedUnionType, ip: *const InternPool) *u32 { - const extra = ip.getLocalShared(self.tid).extra.acquire(); - const field_index = std.meta.fieldIndex(Tag.TypeUnion, "size").?; - return &extra.view().items(.@"0")[self.extra_index + field_index]; - } - - pub fn sizeUnordered(u: LoadedUnionType, ip: *const InternPool) u32 { - return @atomicLoad(u32, u.sizePtr(ip), .unordered); - } - - /// The returned pointer expires with any addition to the `InternPool`. - fn paddingPtr(self: LoadedUnionType, ip: *const InternPool) *u32 { - const extra = ip.getLocalShared(self.tid).extra.acquire(); - const field_index = std.meta.fieldIndex(Tag.TypeUnion, "padding").?; - return &extra.view().items(.@"0")[self.extra_index + field_index]; - } - - pub fn paddingUnordered(u: LoadedUnionType, ip: *const InternPool) u32 { - return @atomicLoad(u32, u.paddingPtr(ip), .unordered); - } - - pub fn hasTag(self: LoadedUnionType, ip: *const InternPool) bool { - return self.flagsUnordered(ip).runtime_tag.hasTag(); - } - - pub fn haveFieldTypes(self: LoadedUnionType, ip: *const InternPool) bool { - return self.flagsUnordered(ip).status.haveFieldTypes(); - } - - pub fn haveLayout(self: LoadedUnionType, ip: *const InternPool) bool { - return self.flagsUnordered(ip).status.haveLayout(); - } - - pub fn setHaveLayout(u: LoadedUnionType, ip: *InternPool, io: Io, size: u32, padding: u32, alignment: Alignment) void { - const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - @atomicStore(u32, u.sizePtr(ip), size, .unordered); - @atomicStore(u32, u.paddingPtr(ip), padding, .unordered); - const flags_ptr = u.flagsPtr(ip); - var flags = flags_ptr.*; - flags.alignment = alignment; - flags.status = .have_layout; - @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release); - } - - pub fn fieldAlign(self: LoadedUnionType, ip: *const InternPool, field_index: usize) Alignment { - if (self.field_aligns.len == 0) return .none; - return self.field_aligns.get(ip)[field_index]; - } - - /// This does not mutate the field of LoadedUnionType. - pub fn setZirIndex(self: LoadedUnionType, ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void { - const flags_field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?; - const zir_index_field_index = std.meta.fieldIndex(Tag.TypeUnion, "zir_index").?; - const ptr: *TrackedInst.Index.Optional = - @ptrCast(&ip.extra_.items[self.flags_index - flags_field_index + zir_index_field_index]); - ptr.* = new_zir_index; - } - - pub fn setFieldTypes(self: LoadedUnionType, ip: *const InternPool, types: []const Index) void { - @memcpy(self.field_types.get(ip), types); - } - - pub fn setFieldAligns(self: LoadedUnionType, ip: *const InternPool, aligns: []const Alignment) void { - if (aligns.len == 0) return; - assert(self.flagsUnordered(ip).any_aligned_fields); - @memcpy(self.field_aligns.get(ip), aligns); - } -}; - -pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { - const unwrapped_index = index.unwrap(ip); - const extra_list = unwrapped_index.getExtra(ip); - const data = unwrapped_index.getData(ip); - const type_union = extraDataTrail(extra_list, Tag.TypeUnion, data); - const fields_len = type_union.data.fields_len; - - var extra_index = type_union.end; - const captures_len = if (type_union.data.flags.any_captures) c: { - const len = extra_list.view().items(.@"0")[extra_index]; - extra_index += 1; - break :c len; - } else 0; - - const captures: CaptureValue.Slice = .{ - .tid = unwrapped_index.tid, - .start = extra_index, - .len = captures_len, - }; - extra_index += captures_len; - if (type_union.data.flags.is_reified) { - extra_index += 2; // PackedU64 - } - - const field_types: Index.Slice = .{ - .tid = unwrapped_index.tid, - .start = extra_index, - .len = fields_len, - }; - extra_index += fields_len; - - const field_aligns = if (type_union.data.flags.any_aligned_fields) a: { - const a: Alignment.Slice = .{ - .tid = unwrapped_index.tid, - .start = extra_index, - .len = fields_len, - }; - extra_index += std.math.divCeil(u32, fields_len, 4) catch unreachable; - break :a a; - } else Alignment.Slice.empty; - - return .{ - .tid = unwrapped_index.tid, - .extra_index = data, - .name = type_union.data.name, - .name_nav = type_union.data.name_nav, - .namespace = type_union.data.namespace, - .enum_tag_ty = type_union.data.tag_ty, - .field_types = field_types, - .field_aligns = field_aligns, - .zir_index = type_union.data.zir_index, - .captures = captures, - }; -} - pub const LoadedStructType = struct { - tid: Zcu.PerThread.Id, - /// The index of the `Tag.TypeStruct` or `Tag.TypeStructPacked` payload. - extra_index: u32, + /// Index of the `struct_decl` or `reify` ZIR instruction. + zir_index: TrackedInst.Index, + captures: CaptureValue.Slice, + // TODO: the non-fqn will be needed by the new dwarf structure /// The name of this struct type. name: NullTerminatedString, - namespace: NamespaceIndex, /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. /// Otherwise, or if this is a file's root struct type, this is `.none`. name_nav: Nav.Index.Optional, - /// Index of the `struct_decl` or `reify` ZIR instruction. - zir_index: TrackedInst.Index, + namespace: NamespaceIndex, + layout: std.builtin.Type.ContainerLayout, + /// May be `undefined` if `layout != .@"packed"`. + packed_backing_mode: PackedBackingMode, + /// May be `undefined` if `layout != .@"packed", + packed_backing_int_type: Index, + + field_name_map: MapIndex, field_names: NullTerminatedString.Slice, field_types: Index.Slice, - field_inits: Index.Slice, + field_defaults: Index.Slice, field_aligns: Alignment.Slice, - runtime_order: RuntimeOrder.Slice, - comptime_bits: ComptimeBits, - offsets: Offsets, - names_map: OptionalMapIndex, - captures: CaptureValue.Slice, + field_is_comptime_bits: ComptimeBits, + field_runtime_order: RuntimeOrder.Slice, + field_offsets: Offsets, + + // These fields are only valid once the layout is resolved, and are never valid for `layout == .@"packed"`. + has_no_possible_value: bool, + has_one_possible_value: bool, + comptime_only: bool, + size: u32, + alignment: Alignment, pub const ComptimeBits = struct { tid: Zcu.PerThread.Id, @@ -3690,22 +3347,14 @@ pub const LoadedStructType = struct { pub const empty: ComptimeBits = .{ .tid = .main, .start = 0, .len = 0 }; - pub fn get(this: ComptimeBits, ip: *const InternPool) []u32 { + pub fn getAll(this: ComptimeBits, ip: *const InternPool) []u32 { const extra = ip.getLocalShared(this.tid).extra.acquire(); return extra.view().items(.@"0")[this.start..][0..this.len]; } - pub fn getBit(this: ComptimeBits, ip: *const InternPool, i: usize) bool { + pub fn get(this: ComptimeBits, ip: *const InternPool, i: usize) bool { if (this.len == 0) return false; - return @as(u1, @truncate(this.get(ip)[i / 32] >> @intCast(i % 32))) != 0; - } - - pub fn setBit(this: ComptimeBits, ip: *const InternPool, i: usize) void { - this.get(ip)[i / 32] |= @as(u32, 1) << @intCast(i % 32); - } - - pub fn clearBit(this: ComptimeBits, ip: *const InternPool, i: usize) void { - this.get(ip)[i / 32] &= ~(@as(u32, 1) << @intCast(i % 32)); + return @as(u1, @truncate(this.getAll(ip)[i / 32] >> @intCast(i % 32))) != 0; } }; @@ -3753,865 +3402,550 @@ pub const LoadedStructType = struct { /// Look up field index based on field name. pub fn nameIndex(s: LoadedStructType, ip: *const InternPool, name: NullTerminatedString) ?u32 { - const names_map = s.names_map.unwrap() orelse { - const i = name.toUnsigned(ip) orelse return null; - if (i >= s.field_types.len) return null; - return i; - }; - const map = names_map.get(ip); + const map = s.field_name_map.get(ip); const adapter: NullTerminatedString.Adapter = .{ .strings = s.field_names.get(ip) }; const field_index = map.getIndexAdapted(name, adapter) orelse return null; return @intCast(field_index); } - /// Returns the already-existing field with the same name, if any. - pub fn addFieldName( - s: LoadedStructType, - ip: *InternPool, - name: NullTerminatedString, - ) ?u32 { - const extra = ip.getLocalShared(s.tid).extra.acquire(); - return ip.addFieldName(extra, s.names_map.unwrap().?, s.field_names.start, name); - } - - pub fn fieldAlign(s: LoadedStructType, ip: *const InternPool, i: usize) Alignment { - if (s.field_aligns.len == 0) return .none; - return s.field_aligns.get(ip)[i]; - } - - pub fn fieldInit(s: LoadedStructType, ip: *const InternPool, i: usize) Index { - if (s.field_inits.len == 0) return .none; - assert(s.haveFieldInits(ip)); - return s.field_inits.get(ip)[i]; - } - - pub fn fieldName(s: LoadedStructType, ip: *const InternPool, i: usize) NullTerminatedString { - return s.field_names.get(ip)[i]; - } - - pub fn fieldIsComptime(s: LoadedStructType, ip: *const InternPool, i: usize) bool { - return s.comptime_bits.getBit(ip, i); - } - - pub fn setFieldComptime(s: LoadedStructType, ip: *InternPool, i: usize) void { - s.comptime_bits.setBit(ip, i); - } - - /// The returned pointer expires with any addition to the `InternPool`. - /// Asserts the struct is not packed. - fn flagsPtr(s: LoadedStructType, ip: *const InternPool) *Tag.TypeStruct.Flags { - assert(s.layout != .@"packed"); - const extra = ip.getLocalShared(s.tid).extra.acquire(); - const flags_field_index = std.meta.fieldIndex(Tag.TypeStruct, "flags").?; - return @ptrCast(&extra.view().items(.@"0")[s.extra_index + flags_field_index]); - } - - pub fn flagsUnordered(s: LoadedStructType, ip: *const InternPool) Tag.TypeStruct.Flags { - return @atomicLoad(Tag.TypeStruct.Flags, s.flagsPtr(ip), .unordered); - } - - /// The returned pointer expires with any addition to the `InternPool`. - /// Asserts that the struct is packed. - fn packedFlagsPtr(s: LoadedStructType, ip: *const InternPool) *Tag.TypeStructPacked.Flags { - assert(s.layout == .@"packed"); - const extra = ip.getLocalShared(s.tid).extra.acquire(); - const flags_field_index = std.meta.fieldIndex(Tag.TypeStructPacked, "flags").?; - return @ptrCast(&extra.view().items(.@"0")[s.extra_index + flags_field_index]); - } - - pub fn packedFlagsUnordered(s: LoadedStructType, ip: *const InternPool) Tag.TypeStructPacked.Flags { - return @atomicLoad(Tag.TypeStructPacked.Flags, s.packedFlagsPtr(ip), .unordered); - } - - /// Reads the non-opv flag calculated during AstGen. Used to short-circuit more - /// complicated logic. - pub fn knownNonOpv(s: LoadedStructType, ip: *const InternPool) bool { - return switch (s.layout) { - .@"packed" => false, - .auto, .@"extern" => s.flagsUnordered(ip).known_non_opv, - }; - } - - pub fn requiresComptime(s: LoadedStructType, ip: *const InternPool) RequiresComptime { - return s.flagsUnordered(ip).requires_comptime; - } - - pub fn setRequiresComptimeWip(s: LoadedStructType, ip: *InternPool, io: Io) RequiresComptime { - const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = s.flagsPtr(ip); - var flags = flags_ptr.*; - defer if (flags.requires_comptime == .unknown) { - flags.requires_comptime = .wip; - @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); - }; - return flags.requires_comptime; - } - - pub fn setRequiresComptime(s: LoadedStructType, ip: *InternPool, io: Io, requires_comptime: RequiresComptime) void { - assert(requires_comptime != .wip); // see setRequiresComptimeWip - - const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = s.flagsPtr(ip); - var flags = flags_ptr.*; - flags.requires_comptime = requires_comptime; - @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); - } - - pub fn assumeRuntimeBitsIfFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io) bool { - if (s.layout == .@"packed") return false; - - const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = s.flagsPtr(ip); - var flags = flags_ptr.*; - defer if (flags.field_types_wip) { - flags.assumed_runtime_bits = true; - @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); - }; - return flags.field_types_wip; - } - - pub fn setFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io) bool { - if (s.layout == .@"packed") return false; - - const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = s.flagsPtr(ip); - var flags = flags_ptr.*; - defer { - flags.field_types_wip = true; - @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); - } - return flags.field_types_wip; - } - - pub fn clearFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io) void { - if (s.layout == .@"packed") return; - - const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = s.flagsPtr(ip); - var flags = flags_ptr.*; - flags.field_types_wip = false; - @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); - } - - pub fn setLayoutWip(s: LoadedStructType, ip: *InternPool, io: Io) bool { - if (s.layout == .@"packed") return false; - - const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = s.flagsPtr(ip); - var flags = flags_ptr.*; - defer { - flags.layout_wip = true; - @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); - } - return flags.layout_wip; - } - - pub fn clearLayoutWip(s: LoadedStructType, ip: *InternPool, io: Io) void { - if (s.layout == .@"packed") return; - - const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = s.flagsPtr(ip); - var flags = flags_ptr.*; - flags.layout_wip = false; - @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); - } - - pub fn setAlignment(s: LoadedStructType, ip: *InternPool, io: Io, alignment: Alignment) void { - const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = s.flagsPtr(ip); - var flags = flags_ptr.*; - flags.alignment = alignment; - @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); - } - - pub fn assumePointerAlignedIfFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io, ptr_align: Alignment) bool { - const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = s.flagsPtr(ip); - var flags = flags_ptr.*; - defer if (flags.field_types_wip) { - flags.alignment = ptr_align; - flags.assumed_pointer_aligned = true; - @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); - }; - return flags.field_types_wip; - } - - pub fn assumePointerAlignedIfWip(s: LoadedStructType, ip: *InternPool, io: Io, ptr_align: Alignment) bool { - const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = s.flagsPtr(ip); - var flags = flags_ptr.*; - defer { - if (flags.alignment_wip) { - flags.alignment = ptr_align; - flags.assumed_pointer_aligned = true; - } else flags.alignment_wip = true; - @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); - } - return flags.alignment_wip; - } - - pub fn clearAlignmentWip(s: LoadedStructType, ip: *InternPool, io: Io) void { - if (s.layout == .@"packed") return; - - const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = s.flagsPtr(ip); - var flags = flags_ptr.*; - flags.alignment_wip = false; - @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); - } - - pub fn setInitsWip(s: LoadedStructType, ip: *InternPool, io: Io) bool { - const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - switch (s.layout) { - .@"packed" => { - const flags_ptr = s.packedFlagsPtr(ip); - var flags = flags_ptr.*; - defer { - flags.field_inits_wip = true; - @atomicStore(Tag.TypeStructPacked.Flags, flags_ptr, flags, .release); - } - return flags.field_inits_wip; - }, - .auto, .@"extern" => { - const flags_ptr = s.flagsPtr(ip); - var flags = flags_ptr.*; - defer { - flags.field_inits_wip = true; - @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); - } - return flags.field_inits_wip; - }, - } - } - - pub fn clearInitsWip(s: LoadedStructType, ip: *InternPool, io: Io) void { - const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - switch (s.layout) { - .@"packed" => { - const flags_ptr = s.packedFlagsPtr(ip); - var flags = flags_ptr.*; - flags.field_inits_wip = false; - @atomicStore(Tag.TypeStructPacked.Flags, flags_ptr, flags, .release); - }, - .auto, .@"extern" => { - const flags_ptr = s.flagsPtr(ip); - var flags = flags_ptr.*; - flags.field_inits_wip = false; - @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); - }, - } - } - - pub fn setFullyResolved(s: LoadedStructType, ip: *InternPool, io: Io) bool { - if (s.layout == .@"packed") return true; - - const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = s.flagsPtr(ip); - var flags = flags_ptr.*; - defer { - flags.fully_resolved = true; - @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); - } - return flags.fully_resolved; - } - - pub fn clearFullyResolved(s: LoadedStructType, ip: *InternPool, io: Io) void { - const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const flags_ptr = s.flagsPtr(ip); - var flags = flags_ptr.*; - flags.fully_resolved = false; - @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); - } - - /// The returned pointer expires with any addition to the `InternPool`. - /// Asserts the struct is not packed. - fn sizePtr(s: LoadedStructType, ip: *const InternPool) *u32 { - assert(s.layout != .@"packed"); - const extra = ip.getLocalShared(s.tid).extra.acquire(); - const size_field_index = std.meta.fieldIndex(Tag.TypeStruct, "size").?; - return @ptrCast(&extra.view().items(.@"0")[s.extra_index + size_field_index]); - } - - pub fn sizeUnordered(s: LoadedStructType, ip: *const InternPool) u32 { - return @atomicLoad(u32, s.sizePtr(ip), .unordered); - } - - /// The backing integer type of the packed struct. Whether zig chooses - /// this type or the user specifies it, it is stored here. This will be - /// set to `none` until the layout is resolved. - /// Asserts the struct is packed. - fn backingIntTypePtr(s: LoadedStructType, ip: *const InternPool) *Index { - assert(s.layout == .@"packed"); - const extra = ip.getLocalShared(s.tid).extra.acquire(); - const field_index = std.meta.fieldIndex(Tag.TypeStructPacked, "backing_int_ty").?; - return @ptrCast(&extra.view().items(.@"0")[s.extra_index + field_index]); - } - - pub fn backingIntTypeUnordered(s: LoadedStructType, ip: *const InternPool) Index { - return @atomicLoad(Index, s.backingIntTypePtr(ip), .unordered); - } - - pub fn setBackingIntType(s: LoadedStructType, ip: *InternPool, io: Io, backing_int_ty: Index) void { - const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - @atomicStore(Index, s.backingIntTypePtr(ip), backing_int_ty, .release); - } - - /// Asserts the struct is not packed. - pub fn setZirIndex(s: LoadedStructType, ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void { - assert(s.layout != .@"packed"); - const field_index = std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?; - ip.extra_.items[s.extra_index + field_index] = @intFromEnum(new_zir_index); - } - - pub fn haveFieldTypes(s: LoadedStructType, ip: *const InternPool) bool { - const types = s.field_types.get(ip); - return types.len == 0 or types[types.len - 1] != .none; - } - - pub fn haveFieldInits(s: LoadedStructType, ip: *const InternPool) bool { - return switch (s.layout) { - .@"packed" => s.packedFlagsUnordered(ip).inits_resolved, - .auto, .@"extern" => s.flagsUnordered(ip).inits_resolved, - }; - } - - pub fn setHaveFieldInits(s: LoadedStructType, ip: *InternPool, io: Io) void { - const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - switch (s.layout) { - .@"packed" => { - const flags_ptr = s.packedFlagsPtr(ip); - var flags = flags_ptr.*; - flags.inits_resolved = true; - @atomicStore(Tag.TypeStructPacked.Flags, flags_ptr, flags, .release); - }, - .auto, .@"extern" => { - const flags_ptr = s.flagsPtr(ip); - var flags = flags_ptr.*; - flags.inits_resolved = true; - @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); - }, - } - } - - pub fn haveLayout(s: LoadedStructType, ip: *const InternPool) bool { - return switch (s.layout) { - .@"packed" => s.backingIntTypeUnordered(ip) != .none, - .auto, .@"extern" => s.flagsUnordered(ip).layout_resolved, - }; - } - - pub fn setLayoutResolved(s: LoadedStructType, ip: *InternPool, io: Io, size: u32, alignment: Alignment) void { - const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - @atomicStore(u32, s.sizePtr(ip), size, .unordered); - const flags_ptr = s.flagsPtr(ip); - var flags = flags_ptr.*; - flags.alignment = alignment; - flags.layout_resolved = true; - @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release); - } - - pub fn hasReorderedFields(s: LoadedStructType) bool { - return s.layout == .auto; - } - - pub const RuntimeOrderIterator = struct { - ip: *InternPool, - field_index: u32, - struct_type: InternPool.LoadedStructType, - - pub fn next(it: *@This()) ?u32 { - var i = it.field_index; - - if (i >= it.struct_type.field_types.len) - return null; - - if (it.struct_type.hasReorderedFields()) { - it.field_index += 1; - return it.struct_type.runtime_order.get(it.ip)[i].toInt(); - } - - while (it.struct_type.fieldIsComptime(it.ip, i)) { - i += 1; - if (i >= it.struct_type.field_types.len) - return null; - } - - it.field_index = i + 1; - return i; - } - }; - /// Iterates over non-comptime fields in the order they are laid out in memory at runtime. /// May or may not include zero-bit fields. /// Asserts the struct is not packed. - pub fn iterateRuntimeOrder(s: LoadedStructType, ip: *InternPool) RuntimeOrderIterator { - assert(s.layout != .@"packed"); - return .{ - .ip = ip, - .field_index = 0, - .struct_type = s, - }; + pub fn iterateRuntimeOrder(s: *const LoadedStructType, ip: *InternPool) RuntimeOrderIterator { + switch (s.layout) { + .auto => { + const ro = std.mem.sliceTo(s.field_runtime_order.get(ip), .omitted); + return .{ + .runtime_order = ro, + .fields_len = @intCast(ro.len), + .next_index = 0, + }; + }, + .@"extern" => return .{ + .runtime_order = null, + .fields_len = s.field_names.len, + .next_index = 0, + }, + .@"packed" => unreachable, + } } + pub const RuntimeOrderIterator = struct { + runtime_order: ?[]const RuntimeOrder, + fields_len: u32, + next_index: u32, + pub fn next(it: *RuntimeOrderIterator) ?u32 { + const i = it.next_index; + if (i == it.fields_len) return null; + it.next_index = i + 1; + const ro = it.runtime_order orelse return i; + return ro[i].toInt().?; + } + }; + pub fn iterateRuntimeOrderReverse(s: *const LoadedStructType, ip: *InternPool) ReverseRuntimeOrderIterator { + switch (s.layout) { + .auto => { + const ro = std.mem.sliceTo(s.field_runtime_order.get(ip), .omitted); + return .{ + .runtime_order = ro, + .last_index = @intCast(ro.len), + }; + }, + .@"extern" => return .{ + .runtime_order = null, + .last_index = s.field_names.len, + }, + .@"packed" => unreachable, + } + } pub const ReverseRuntimeOrderIterator = struct { - ip: *InternPool, + runtime_order: ?[]const RuntimeOrder, last_index: u32, - struct_type: InternPool.LoadedStructType, - - pub fn next(it: *@This()) ?u32 { - if (it.last_index == 0) - return null; - - if (it.struct_type.hasReorderedFields()) { - it.last_index -= 1; - const order = it.struct_type.runtime_order.get(it.ip); - while (order[it.last_index] == .omitted) { - it.last_index -= 1; - if (it.last_index == 0) - return null; - } - return order[it.last_index].toInt(); - } - - it.last_index -= 1; - while (it.struct_type.fieldIsComptime(it.ip, it.last_index)) { - it.last_index -= 1; - if (it.last_index == 0) - return null; - } - - return it.last_index; + pub fn next(it: *ReverseRuntimeOrderIterator) ?u32 { + if (it.last_index == 0) return null; + const i = it.last_index - 1; + it.last_index = i; + const ro = it.runtime_order orelse return i; + return ro[i].toInt().?; } }; - - pub fn iterateRuntimeOrderReverse(s: LoadedStructType, ip: *InternPool) ReverseRuntimeOrderIterator { - assert(s.layout != .@"packed"); - return .{ - .ip = ip, - .last_index = s.field_types.len, - .struct_type = s, - }; - } }; -pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { - const unwrapped_index = index.unwrap(ip); - const extra_list = unwrapped_index.getExtra(ip); - const extra_items = extra_list.view().items(.@"0"); - const item = unwrapped_index.getItem(ip); - switch (item.tag) { - .type_struct => { - const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "name").?]); - const name_nav: Nav.Index.Optional = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?]); - const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?]); - const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?]); - const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "fields_len").?]; - const flags: Tag.TypeStruct.Flags = @bitCast(@atomicLoad(u32, &extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "flags").?], .unordered)); - var extra_index = item.data + @as(u32, @typeInfo(Tag.TypeStruct).@"struct".fields.len); - const captures_len = if (flags.any_captures) c: { - const len = extra_list.view().items(.@"0")[extra_index]; - extra_index += 1; - break :c len; - } else 0; - const captures: CaptureValue.Slice = .{ - .tid = unwrapped_index.tid, - .start = extra_index, - .len = captures_len, - }; - extra_index += captures_len; - if (flags.is_reified) { - extra_index += 2; // type_hash: PackedU64 - } - const field_types: Index.Slice = .{ - .tid = unwrapped_index.tid, - .start = extra_index, - .len = fields_len, - }; - extra_index += fields_len; - const names_map: OptionalMapIndex, const names = n: { - const names_map: OptionalMapIndex = @enumFromInt(extra_list.view().items(.@"0")[extra_index]); - extra_index += 1; - const names: NullTerminatedString.Slice = .{ - .tid = unwrapped_index.tid, - .start = extra_index, - .len = fields_len, - }; - extra_index += fields_len; - break :n .{ names_map, names }; - }; - const inits: Index.Slice = if (flags.any_default_inits) i: { - const inits: Index.Slice = .{ - .tid = unwrapped_index.tid, - .start = extra_index, - .len = fields_len, - }; - extra_index += fields_len; - break :i inits; - } else Index.Slice.empty; - const aligns: Alignment.Slice = if (flags.any_aligned_fields) a: { - const a: Alignment.Slice = .{ - .tid = unwrapped_index.tid, - .start = extra_index, - .len = fields_len, - }; - extra_index += std.math.divCeil(u32, fields_len, 4) catch unreachable; - break :a a; - } else Alignment.Slice.empty; - const comptime_bits: LoadedStructType.ComptimeBits = if (flags.any_comptime_fields) c: { - const len = std.math.divCeil(u32, fields_len, 32) catch unreachable; - const c: LoadedStructType.ComptimeBits = .{ - .tid = unwrapped_index.tid, - .start = extra_index, - .len = len, - }; - extra_index += len; - break :c c; - } else LoadedStructType.ComptimeBits.empty; - const runtime_order: LoadedStructType.RuntimeOrder.Slice = if (!flags.is_extern) ro: { - const ro: LoadedStructType.RuntimeOrder.Slice = .{ - .tid = unwrapped_index.tid, - .start = extra_index, - .len = fields_len, - }; - extra_index += fields_len; - break :ro ro; - } else LoadedStructType.RuntimeOrder.Slice.empty; - const offsets: LoadedStructType.Offsets = o: { - const o: LoadedStructType.Offsets = .{ - .tid = unwrapped_index.tid, - .start = extra_index, - .len = fields_len, - }; - extra_index += fields_len; - break :o o; - }; - return .{ - .tid = unwrapped_index.tid, - .extra_index = item.data, - .name = name, - .name_nav = name_nav, - .namespace = namespace, - .zir_index = zir_index, - .layout = if (flags.is_extern) .@"extern" else .auto, - .field_names = names, - .field_types = field_types, - .field_inits = inits, - .field_aligns = aligns, - .runtime_order = runtime_order, - .comptime_bits = comptime_bits, - .offsets = offsets, - .names_map = names_map, - .captures = captures, - }; - }, - .type_struct_packed, .type_struct_packed_inits => { - const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?]); - const name_nav: Nav.Index.Optional = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?]); - const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "zir_index").?]); - const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "fields_len").?]; - const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?]); - const names_map: MapIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "names_map").?]); - const flags: Tag.TypeStructPacked.Flags = @bitCast(@atomicLoad(u32, &extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "flags").?], .unordered)); - var extra_index = item.data + @as(u32, @typeInfo(Tag.TypeStructPacked).@"struct".fields.len); - const has_inits = item.tag == .type_struct_packed_inits; - const captures_len = if (flags.any_captures) c: { - const len = extra_list.view().items(.@"0")[extra_index]; - extra_index += 1; - break :c len; - } else 0; - const captures: CaptureValue.Slice = .{ - .tid = unwrapped_index.tid, - .start = extra_index, - .len = captures_len, - }; - extra_index += captures_len; - if (flags.is_reified) { - extra_index += 2; // PackedU64 - } - const field_types: Index.Slice = .{ - .tid = unwrapped_index.tid, - .start = extra_index, - .len = fields_len, - }; - extra_index += fields_len; - const field_names: NullTerminatedString.Slice = .{ - .tid = unwrapped_index.tid, - .start = extra_index, - .len = fields_len, - }; - extra_index += fields_len; - const field_inits: Index.Slice = if (has_inits) inits: { - const i: Index.Slice = .{ - .tid = unwrapped_index.tid, - .start = extra_index, - .len = fields_len, - }; - extra_index += fields_len; - break :inits i; - } else Index.Slice.empty; - return .{ - .tid = unwrapped_index.tid, - .extra_index = item.data, - .name = name, - .name_nav = name_nav, - .namespace = namespace, - .zir_index = zir_index, - .layout = .@"packed", - .field_names = field_names, - .field_types = field_types, - .field_inits = field_inits, - .field_aligns = Alignment.Slice.empty, - .runtime_order = LoadedStructType.RuntimeOrder.Slice.empty, - .comptime_bits = LoadedStructType.ComptimeBits.empty, - .offsets = LoadedStructType.Offsets.empty, - .names_map = names_map.toOptional(), - .captures = captures, - }; - }, - else => unreachable, - } -} +/// Unlike `Tag.TypeUnion` which is an encoding, and `Key.UnionType` which is a +/// minimal hashmap key, this type is a convenience type that contains info +/// needed by semantic analysis. +pub const LoadedUnionType = struct { + /// Index of the `union_decl` or `reify` ZIR instruction. + zir_index: TrackedInst.Index, + captures: CaptureValue.Slice, + + // TODO: the non-fqn will be needed by the new dwarf structure + /// The name of this union type. + name: NullTerminatedString, + /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. + /// Otherwise, this is `.none`. + name_nav: Nav.Index.Optional, + namespace: NamespaceIndex, + + layout: std.builtin.Type.ContainerLayout, + runtime_tag: RuntimeTag, + /// Even if `runtime_tag == .none`, this is populated with the union's "hypothetical" tag type. + enum_tag_type: Index, + /// May be `undefined` if `layout != .@"packed"`. + packed_backing_mode: PackedBackingMode, + /// May be `undefined` if `layout != .@"packed", + packed_backing_int_type: Index, + + // Field names are not stored here, because fields are guaranteed to map one-to-one to the + // fields of the enum tag type. If you need field names, load them from `enum_tag_type`. + field_types: Index.Slice, + field_aligns: Alignment.Slice, + + // These fields are only valid once the layout is resolved, and are never valid for `layout == .@"packed"`. + has_no_possible_value: bool, + has_one_possible_value: bool, + comptime_only: bool, + size: u32, + padding: u32, + alignment: Alignment, + + pub const RuntimeTag = enum(u2) { + none, + safety, + tagged, + }; +}; pub const LoadedEnumType = struct { + /// This is `none` iff this is a generated tag type. + /// Otherwise, index of the `enum_decl` or `reify` ZIR instruction. + zir_index: TrackedInst.Index.Optional, + captures: CaptureValue.Slice, + /// If `zir_index` is `.none`, this is the union type for which this enum is the tag type. + owner_union: Index, + // TODO: the non-fqn will be needed by the new dwarf structure /// The name of this enum type. name: NullTerminatedString, - /// Represents the declarations inside this enum. - namespace: NamespaceIndex, /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. /// Otherwise, this is `.none`. name_nav: Nav.Index.Optional, - /// An integer type which is used for the numerical value of the enum. - /// This field is present regardless of whether the enum has an - /// explicitly provided tag type or auto-numbered. - tag_ty: Index, - /// Set of field names in declaration order. - names: NullTerminatedString.Slice, - /// Maps integer tag value to field index. - /// Entries are in declaration order, same as `fields`. - /// If this is empty, it means the enum tags are auto-numbered. - values: Index.Slice, - tag_mode: TagMode, - names_map: MapIndex, - /// This is guaranteed to not be `.none` if explicit values are provided. - values_map: OptionalMapIndex, - /// This is `none` only if this is a generated tag type. - zir_index: TrackedInst.Index.Optional, - captures: CaptureValue.Slice, + namespace: NamespaceIndex, - pub const TagMode = enum { - /// The integer tag type was auto-numbered by zig. - auto, - /// The integer tag type was provided by the enum declaration, and the enum - /// is exhaustive. - explicit, - /// The integer tag type was provided by the enum declaration, and the enum - /// is non-exhaustive. - nonexhaustive, - }; + /// An integer type which is used for the numerical value of the enum. Populated immediately, regardless + /// of whether the integer tag type was explicitly provided or inferred by the compiler. + int_tag_type: Index, + int_tag_is_explicit: bool, + nonexhaustive: bool, + + /// Uses `NullTerminatedString.Adapter` with `field_names`. + field_name_map: MapIndex, + /// If this is `.none`, the enum tag type is auto-generated and so the fields are auto-numbered. + /// Otherwise, uses `Index.Adapter` with `field_values`. + field_value_map: OptionalMapIndex, + field_names: NullTerminatedString.Slice, + /// Empty if `field_value_map` is `.none`. + field_values: Index.Slice, /// Look up field index based on field name. - pub fn nameIndex(self: LoadedEnumType, ip: *const InternPool, name: NullTerminatedString) ?u32 { - const map = self.names_map.get(ip); - const adapter: NullTerminatedString.Adapter = .{ .strings = self.names.get(ip) }; + pub fn nameIndex(e: LoadedEnumType, ip: *const InternPool, name: NullTerminatedString) ?u32 { + const map = e.field_name_map.get(ip); + const adapter: NullTerminatedString.Adapter = .{ .strings = e.field_names.get(ip) }; const field_index = map.getIndexAdapted(name, adapter) orelse return null; return @intCast(field_index); } - /// Look up field index based on tag value. - /// Asserts that `values_map` is not `none`. - /// This function returns `null` when `tag_val` does not have the - /// integer tag type of the enum. - pub fn tagValueIndex(self: LoadedEnumType, ip: *const InternPool, tag_val: Index) ?u32 { - assert(tag_val != .none); - // TODO: we should probably decide a single interface for this function, but currently - // it's being called with both tag values and underlying ints. Fix this! - const int_tag_val = switch (ip.indexToKey(tag_val)) { - .enum_tag => |enum_tag| enum_tag.int, - .int => tag_val, - else => unreachable, - }; - if (self.values_map.unwrap()) |values_map| { - const map = values_map.get(ip); - const adapter: Index.Adapter = .{ .indexes = self.values.get(ip) }; - const field_index = map.getIndexAdapted(int_tag_val, adapter) orelse return null; + /// Look up field index based on integer tag value. + /// Asserts that the type of `tag_val` is `enum_obj.int_tag_type`. + /// Asserts that `tag_val` is not `undefined`. + pub fn tagValueIndex(e: LoadedEnumType, ip: *const InternPool, tag_val: Index) ?u32 { + assert(ip.typeOf(tag_val) == e.int_tag_type); + assert(ip.indexToKey(tag_val) == .int); + if (e.field_value_map.unwrap()) |field_value_map| { + const map = field_value_map.get(ip); + const adapter: Index.Adapter = .{ .indexes = e.field_values.get(ip) }; + const field_index = map.getIndexAdapted(tag_val, adapter) orelse return null; return @intCast(field_index); } - // Auto-numbered enum. Convert `int_tag_val` to field index. - const field_index = switch (ip.indexToKey(int_tag_val).int.storage) { + // Auto-numbered enum, so convert `tag_val` to field index + const field_index = switch (ip.indexToKey(tag_val).int.storage) { inline .u64, .i64 => |x| std.math.cast(u32, x) orelse return null, .big_int => |x| x.toInt(u32) catch return null, - .lazy_align, .lazy_size => unreachable, }; - return if (field_index < self.names.len) field_index else null; + return if (field_index < e.field_names.len) field_index else null; } }; -pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType { - const unwrapped_index = index.unwrap(ip); - const extra_list = unwrapped_index.getExtra(ip); - const item = unwrapped_index.getItem(ip); - const tag_mode: LoadedEnumType.TagMode = switch (item.tag) { - .type_enum_auto => { - const extra = extraDataTrail(extra_list, EnumAuto, item.data); - var extra_index: u32 = @intCast(extra.end); - if (extra.data.zir_index == .none) { - extra_index += 1; // owner_union - } - const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: { - extra_index += 2; // type_hash: PackedU64 - break :c 0; - } else extra.data.captures_len; - return .{ - .name = extra.data.name, - .name_nav = extra.data.name_nav, - .namespace = extra.data.namespace, - .tag_ty = extra.data.int_tag_type, - .names = .{ - .tid = unwrapped_index.tid, - .start = extra_index + captures_len, - .len = extra.data.fields_len, - }, - .values = Index.Slice.empty, - .tag_mode = .auto, - .names_map = extra.data.names_map, - .values_map = .none, - .zir_index = extra.data.zir_index, - .captures = .{ - .tid = unwrapped_index.tid, - .start = extra_index, - .len = captures_len, - }, - }; - }, - .type_enum_explicit => .explicit, - .type_enum_nonexhaustive => .nonexhaustive, - else => unreachable, - }; - const extra = extraDataTrail(extra_list, EnumExplicit, item.data); - var extra_index: u32 = @intCast(extra.end); - if (extra.data.zir_index == .none) { - extra_index += 1; // owner_union - } - const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: { - extra_index += 2; // type_hash: PackedU64 - break :c 0; - } else extra.data.captures_len; - return .{ - .name = extra.data.name, - .name_nav = extra.data.name_nav, - .namespace = extra.data.namespace, - .tag_ty = extra.data.int_tag_type, - .names = .{ - .tid = unwrapped_index.tid, - .start = extra_index + captures_len, - .len = extra.data.fields_len, - }, - .values = .{ - .tid = unwrapped_index.tid, - .start = extra_index + captures_len + extra.data.fields_len, - .len = if (extra.data.values_map != .none) extra.data.fields_len else 0, - }, - .tag_mode = tag_mode, - .names_map = extra.data.names_map, - .values_map = extra.data.values_map, - .zir_index = extra.data.zir_index, - .captures = .{ - .tid = unwrapped_index.tid, - .start = extra_index, - .len = captures_len, - }, - }; -} - -/// Note that this type doubles as the payload for `Tag.type_opaque`. pub const LoadedOpaqueType = struct { - /// Contains the declarations inside this opaque. - namespace: NamespaceIndex, + /// Index of the `opaque_decl` instruction. + zir_index: TrackedInst.Index, + captures: CaptureValue.Slice, + // TODO: the non-fqn will be needed by the new dwarf structure /// The name of this opaque type. name: NullTerminatedString, /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. /// Otherwise, this is `.none`. name_nav: Nav.Index.Optional, - /// Index of the `opaque_decl` or `reify` instruction. - zir_index: TrackedInst.Index, - captures: CaptureValue.Slice, + namespace: NamespaceIndex, }; +pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { + const unwrapped_index = index.unwrap(ip); + const extra_list = unwrapped_index.getExtra(ip); + const extra_items = extra_list.view().items(.@"0"); + const item = unwrapped_index.getItem(ip); + // Exiting this `switch` means this is a `packed struct`. + const backing_mode: PackedBackingMode, const any_defaults: bool = switch (item.tag) { + .type_struct_packed_auto => .{ .auto, false }, + .type_struct_packed_explicit => .{ .explicit, false }, + .type_struct_packed_auto_defaults => .{ .auto, true }, + .type_struct_packed_explicit_defaults => .{ .explicit, true }, + .type_struct => { + const extra = extraDataTrail(extra_list, Tag.TypeStruct, item.data); + var extra_index = extra.end; + const captures: CaptureValue.Slice = switch (extra.data.flags.any_captures) { + .reified => captures: { + extra_index += 2; // type_hash: PackedU64 + break :captures .empty; + }, + .false => .empty, + .true => captures: { + const len = extra_items[extra_index]; + extra_index += 1; + break :captures .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = len, + }; + }, + }; + extra_index += captures.len; + const field_names: NullTerminatedString.Slice = .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = extra.data.fields_len, + }; + extra_index += field_names.len; + const field_types: Index.Slice = .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = extra.data.fields_len, + }; + extra_index += field_types.len; + const field_defaults: Index.Slice = if (extra.data.flags.any_field_defaults) .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = extra.data.fields_len, + } else .empty; + extra_index += field_defaults.len; + const field_aligns: Alignment.Slice = if (extra.data.flags.any_field_aligns) .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = extra.data.fields_len, + } else .empty; + extra_index += std.math.divCeil(u32, field_aligns.len, 4) catch unreachable; + const field_is_comptime_bits: LoadedStructType.ComptimeBits = if (extra.data.flags.any_comptime_fields) .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = std.math.divCeil(u32, extra.data.fields_len, 32) catch unreachable, + } else .empty; + extra_index += field_is_comptime_bits.len; + const field_runtime_order: LoadedStructType.RuntimeOrder.Slice = if (extra.data.flags.layout == .auto) .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = extra.data.fields_len, + } else .empty; + extra_index += field_runtime_order.len; + const field_offsets: LoadedStructType.Offsets = .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = extra.data.fields_len, + }; + extra_index += field_offsets.len; + + return .{ + .zir_index = extra.data.zir_index, + .captures = captures, + .name = extra.data.name, + .name_nav = extra.data.name_nav, + .namespace = extra.data.namespace, + .layout = switch (extra.data.flags.layout) { + .auto => .auto, + .@"extern" => .@"extern", + }, + .packed_backing_mode = undefined, + .packed_backing_int_type = undefined, + .field_name_map = extra.data.field_name_map, + .field_names = field_names, + .field_types = field_types, + .field_defaults = field_defaults, + .field_aligns = field_aligns, + .field_is_comptime_bits = field_is_comptime_bits, + .field_runtime_order = field_runtime_order, + .field_offsets = field_offsets, + .has_no_possible_value = extra.data.flags.has_no_possible_value, + .has_one_possible_value = extra.data.flags.has_one_possible_value, + .comptime_only = extra.data.flags.comptime_only, + .size = extra.data.size, + .alignment = extra.data.flags.alignment, + }; + }, + else => unreachable, + }; + const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, item.data); + var extra_index = extra.end; + const captures: CaptureValue.Slice = switch (extra.data.captures_len) { + .reified => captures: { + extra_index += 2; // type_hash: PackedU64 + break :captures .empty; + }, + _ => .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = @intFromEnum(extra.data.captures_len), + }, + }; + extra_index += captures.len; + const field_names: NullTerminatedString.Slice = .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = extra.data.fields_len, + }; + extra_index += field_names.len; + const field_types: Index.Slice = .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = extra.data.fields_len, + }; + extra_index += field_types.len; + const field_defaults: Index.Slice = if (any_defaults) .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = extra.data.fields_len, + } else .empty; + extra_index += field_defaults.len; + return .{ + .zir_index = extra.data.zir_index, + .captures = captures, + .name = extra.data.name, + .name_nav = extra.data.name_nav, + .namespace = extra.data.namespace, + .layout = .@"packed", + .packed_backing_mode = backing_mode, + .packed_backing_int_type = extra.data.backing_int_type, + .field_name_map = extra.data.field_name_map, + .field_names = field_names, + .field_types = field_types, + .field_defaults = field_defaults, + .field_aligns = .empty, + .field_is_comptime_bits = .empty, + .field_runtime_order = .empty, + .field_offsets = .empty, + .has_no_possible_value = undefined, + .has_one_possible_value = undefined, + .comptime_only = undefined, + .size = undefined, + .alignment = undefined, + }; +} + +pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { + const unwrapped_index = index.unwrap(ip); + const extra_list = unwrapped_index.getExtra(ip); + const extra_items = extra_list.view().items(.@"0"); + const item = unwrapped_index.getItem(ip); + // Exiting this `switch` means this is a `packed union`. + const backing_mode: PackedBackingMode = switch (item.tag) { + .type_union_packed_auto => .auto, + .type_union_packed_explicit => .explicit, + .type_union => { + const extra = extraDataTrail(extra_list, Tag.TypeUnion, item.data); + var extra_index = extra.end; + const captures: CaptureValue.Slice = switch (extra.data.flags.any_captures) { + .reified => captures: { + extra_index += 2; // type_hash: PackedU64 + break :captures .empty; + }, + .false => .empty, + .true => captures: { + const len = extra_items[extra_index]; + extra_index += 1; + break :captures .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = len, + }; + }, + }; + extra_index += captures.len; + const field_types: Index.Slice = .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = extra.data.fields_len, + }; + extra_index += field_types.len; + const field_aligns: Alignment.Slice = if (extra.data.flags.any_field_aligns) .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = extra.data.fields_len, + } else .empty; + extra_index += std.math.divCeil(u32, field_aligns.len, 4) catch unreachable; + + return .{ + .zir_index = extra.data.zir_index, + .captures = captures, + .name = extra.data.name, + .name_nav = extra.data.name_nav, + .namespace = extra.data.namespace, + .layout = switch (extra.data.flags.layout) { + .auto => .auto, + .@"extern" => .@"extern", + }, + .runtime_tag = extra.data.flags.runtime_tag, + .enum_tag_type = extra.data.enum_tag_type, + .packed_backing_mode = undefined, + .packed_backing_int_type = undefined, + .field_types = field_types, + .field_aligns = field_aligns, + .has_no_possible_value = extra.data.flags.has_no_possible_value, + .has_one_possible_value = extra.data.flags.has_one_possible_value, + .comptime_only = extra.data.flags.comptime_only, + .size = extra.data.size, + .padding = extra.data.padding, + .alignment = extra.data.flags.alignment, + }; + }, + else => unreachable, + }; + const extra = extraDataTrail(extra_list, Tag.TypeUnionPacked, item.data); + var extra_index = extra.end; + const captures: CaptureValue.Slice = switch (extra.data.captures_len) { + .reified => captures: { + extra_index += 2; // type_hash: PackedU64 + break :captures .empty; + }, + _ => .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = @intFromEnum(extra.data.captures_len), + }, + }; + extra_index += captures.len; + const field_types: Index.Slice = .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = extra.data.fields_len, + }; + extra_index += field_types.len; + return .{ + .zir_index = extra.data.zir_index, + .captures = captures, + .name = extra.data.name, + .name_nav = extra.data.name_nav, + .namespace = extra.data.namespace, + .layout = .@"packed", + .runtime_tag = .none, + .enum_tag_type = extra.data.enum_tag_type, + .packed_backing_mode = backing_mode, + .packed_backing_int_type = extra.data.backing_int_type, + .field_types = field_types, + .field_aligns = .empty, + .has_no_possible_value = undefined, + .has_one_possible_value = undefined, + .comptime_only = undefined, + .size = undefined, + .padding = undefined, + .alignment = undefined, + }; +} + +pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType { + const unwrapped_index = index.unwrap(ip); + const extra_list = unwrapped_index.getExtra(ip); + const extra_items = extra_list.view().items(.@"0"); + const item = unwrapped_index.getItem(ip); + const explicit_int_tag: bool, const nonexhaustive: bool = switch (item.tag) { + .type_enum_auto => .{ false, false }, + .type_enum_explicit => .{ true, false }, + .type_enum_nonexhaustive => .{ true, true }, + else => unreachable, + }; + const extra = extraDataTrail(extra_list, Tag.TypeEnum, item.data); + var extra_index: u32 = @intCast(extra.end); + const zir_index: TrackedInst.Index.Optional, const captures: CaptureValue.Slice, const owner_union: Index = switch (extra.data.captures_len) { + .reified => info: { + const zir_index: TrackedInst.Index = @enumFromInt(extra_items[extra_index]); + extra_index += 1; + extra_index += 2; // type_hash: PackedU64 + break :info .{ zir_index.toOptional(), .empty, .none }; + }, + .generated_union_tag => info: { + const owner_union: Index = @enumFromInt(extra_items[extra_index]); + extra_index += 1; + break :info .{ .none, .empty, owner_union }; + }, + _ => info: { + const zir_index: TrackedInst.Index = @enumFromInt(extra_items[extra_index]); + extra_index += 1; + const captures: CaptureValue.Slice = .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = @intFromEnum(extra.data.captures_len), + }; + extra_index += captures.len; + break :info .{ zir_index.toOptional(), captures, .none }; + }, + }; + const field_value_map: OptionalMapIndex = if (explicit_int_tag) m: { + const map: MapIndex = @enumFromInt(extra_items[extra_index]); + extra_index += 1; + break :m map.toOptional(); + } else .none; + const field_names: NullTerminatedString.Slice = .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = extra.data.fields_len, + }; + extra_index += field_names.len; + const field_values: Index.Slice = if (explicit_int_tag) .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = extra.data.fields_len, + } else .empty; + extra_index += field_values.len; + return .{ + .zir_index = zir_index, + .captures = captures, + .owner_union = owner_union, + .name = extra.data.name, + .name_nav = extra.data.name_nav, + .namespace = extra.data.namespace, + .int_tag_type = extra.data.int_tag_type, + .int_tag_is_explicit = explicit_int_tag, + .nonexhaustive = nonexhaustive, + .field_name_map = extra.data.field_name_map, + .field_value_map = field_value_map, + .field_names = field_names, + .field_values = field_values, + }; +} + pub fn loadOpaqueType(ip: *const InternPool, index: Index) LoadedOpaqueType { const unwrapped_index = index.unwrap(ip); const item = unwrapped_index.getItem(ip); assert(item.tag == .type_opaque); const extra = extraDataTrail(unwrapped_index.getExtra(ip), Tag.TypeOpaque, item.data); - const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) - 0 - else - extra.data.captures_len; return .{ - .name = extra.data.name, - .name_nav = extra.data.name_nav, - .namespace = extra.data.namespace, .zir_index = extra.data.zir_index, .captures = .{ .tid = unwrapped_index.tid, .start = extra.end, - .len = captures_len, + .len = extra.data.captures_len, }, + .name = extra.data.name, + .name_nav = extra.data.name_nav, + .namespace = extra.data.namespace, }; } @@ -4819,7 +4153,7 @@ pub const Index = enum(u32) { }; /// Used for a map of `Index` values to the index within a list of `Index` values. - const Adapter = struct { + pub const Adapter = struct { indexes: []const Index, pub fn eql(ctx: @This(), a: Index, b_void: void, b_map_index: usize) bool { @@ -4891,26 +4225,6 @@ pub const Index = enum(u32) { /// Tag to encoding mapping to facilitate fancy debug printing for this type. fn dbHelper(self: *Index, tag_to_encoding_map: *struct { const DataIsIndex = struct { data: Index }; - const DataIsExtraIndexOfEnumExplicit = struct { - const @"data.fields_len" = opaque {}; - data: *EnumExplicit, - @"trailing.names.len": *@"data.fields_len", - @"trailing.values.len": *@"data.fields_len", - trailing: struct { - names: []NullTerminatedString, - values: []Index, - }, - }; - const DataIsExtraIndexOfTypeTuple = struct { - const @"data.fields_len" = opaque {}; - data: *TypeTuple, - @"trailing.types.len": *@"data.fields_len", - @"trailing.values.len": *@"data.fields_len", - trailing: struct { - types: []Index, - values: []Index, - }, - }; removed: void, type_int_signed: struct { data: u32 }, @@ -4931,21 +4245,7 @@ pub const Index = enum(u32) { trailing: struct { names: []NullTerminatedString }, }, type_inferred_error_set: DataIsIndex, - type_enum_auto: struct { - const @"data.fields_len" = opaque {}; - data: *EnumAuto, - @"trailing.names.len": *@"data.fields_len", - trailing: struct { names: []NullTerminatedString }, - }, - type_enum_explicit: DataIsExtraIndexOfEnumExplicit, - type_enum_nonexhaustive: DataIsExtraIndexOfEnumExplicit, simple_type: void, - type_opaque: struct { data: *Tag.TypeOpaque }, - type_struct: struct { data: *Tag.TypeStruct }, - type_struct_packed: struct { data: *Tag.TypeStructPacked }, - type_struct_packed_inits: struct { data: *Tag.TypeStructPacked }, - type_tuple: DataIsExtraIndexOfTypeTuple, - type_union: struct { data: *Tag.TypeUnion }, type_function: struct { const @"data.flags.has_comptime_bits" = opaque {}; const @"data.flags.has_noalias_bits" = opaque {}; @@ -4956,6 +4256,29 @@ pub const Index = enum(u32) { @"trailing.param_types.len": *@"data.params_len", trailing: struct { comptime_bits: []u32, noalias_bits: []u32, param_types: []Index }, }, + type_tuple: struct { + const @"data.fields_len" = opaque {}; + data: *TypeTuple, + @"trailing.types.len": *@"data.fields_len", + @"trailing.values.len": *@"data.fields_len", + trailing: struct { + types: []Index, + values: []Index, + }, + }, + + type_struct: struct { data: *Tag.TypeStruct }, + type_struct_packed_auto: struct { data: *Tag.TypeStructPacked }, + type_struct_packed_explicit: struct { data: *Tag.TypeStructPacked }, + type_struct_packed_auto_defaults: struct { data: *Tag.TypeStructPacked }, + type_struct_packed_explicit_defaults: struct { data: *Tag.TypeStructPacked }, + type_union: struct { data: *Tag.TypeUnion }, + type_union_packed_auto: struct { data: *Tag.TypeUnionPacked }, + type_union_packed_explicit: struct { data: *Tag.TypeUnionPacked }, + type_enum_auto: struct { data: *Tag.TypeEnum }, + type_enum_explicit: struct { data: *Tag.TypeEnum }, + type_enum_nonexhaustive: struct { data: *Tag.TypeEnum }, + type_opaque: struct { data: *Tag.TypeOpaque }, undef: DataIsIndex, simple_value: void, @@ -4982,8 +4305,6 @@ pub const Index = enum(u32) { int_small: struct { data: *IntSmall }, int_positive: struct { data: u32 }, int_negative: struct { data: u32 }, - int_lazy_align: struct { data: *IntLazy }, - int_lazy_size: struct { data: *IntLazy }, error_set_error: struct { data: *Key.Error }, error_union_error: struct { data: *Key.Error }, error_union_payload: struct { data: *Tag.TypeValue }, @@ -5485,6 +4806,8 @@ pub const Tag = enum(u8) { /// assert not this tag. `data` is unused. removed, + /// A type that can be represented with only an enum tag. + simple_type, /// An integer type. /// data is number of bits type_int_signed, @@ -5524,41 +4847,68 @@ pub const Tag = enum(u8) { /// The inferred error set type of a function. /// data is `Index` of a `func_decl` or `func_instance`. type_inferred_error_set, - /// An enum type with auto-numbered tag values. - /// The enum is exhaustive. - /// data is payload index to `EnumAuto`. + /// A function body type. + /// `data` is extra index to `TypeFunction`. + type_function, + /// A `TupleType`. + /// data is extra index of `TypeTuple`. + type_tuple, + + /// A non-packed struct type. + /// data is extra index of `TypeStruct`. + type_struct, + /// `packed struct { ... }` with no default field values. + /// data is extra index of `TypeStructPacked`. + type_struct_packed_auto, + /// `packed struct(T) { ... }` with no default field values. + /// data is extra index of `TypeStructPacked`. + type_struct_packed_explicit, + /// `packed struct { ... }` with one or more default field values. + /// data is extra index of `TypeStructPacked`. + type_struct_packed_auto_defaults, + /// `packed struct(T) { ... }` with one or more default field values. + /// data is extra index of `TypeStructPacked`. + type_struct_packed_explicit_defaults, + + /// A non-packed union type. + /// data is extra index of `TypeUnion`. + type_union, + /// `packed union { ... }`. + /// data is extra index of `TypeUnionPacked`. + type_union_packed_auto, + /// `packed union(T) { ... }`. + /// data is extra index of `TypeUnionPacked`. + type_union_packed_explicit, + + /// An exhaustive enum type *without* an explicit integer tag type. The tag type is inferred. + /// + /// Because the tag type is inferred, there are no explicit field values. + /// + /// May be the generated tag type for a `union(enum)`. + /// + /// data is extra index of `TypeEnum`. type_enum_auto, - /// An enum type with an explicitly provided integer tag type. - /// The enum is exhaustive. - /// data is payload index to `EnumExplicit`. + /// An exhaustive enum type *with* an explicit integer tag type. + /// + /// May have explicit field values. + /// + /// May be the generated tag type for a `union(enum(T))`. + /// + /// data is extra index of `TypeEnum`. type_enum_explicit, - /// An enum type with an explicitly provided integer tag type. - /// The enum is non-exhaustive. - /// data is payload index to `EnumExplicit`. + /// An non-exhaustive enum type (with an explicit integer tag type, since it is required for + /// non-exhaustive enums). + /// + /// May have explicit field values. + /// + /// This is *not* a union's generated tag type, because such types are always exhaustive. + /// + /// data is extra index of `TypeEnum`. type_enum_nonexhaustive, - /// A type that can be represented with only an enum tag. - simple_type, + /// An opaque type. - /// data is index of Tag.TypeOpaque in extra. + /// data is extra index of `TypeOpaque`. type_opaque, - /// A non-packed struct type. - /// data is 0 or extra index of `TypeStruct`. - type_struct, - /// A packed struct, no fields have any init values. - /// data is extra index of `TypeStructPacked`. - type_struct_packed, - /// A packed struct, one or more fields have init values. - /// data is extra index of `TypeStructPacked`. - type_struct_packed_inits, - /// A `TupleType`. - /// data is extra index of `TypeTuple`. - type_tuple, - /// A union type. - /// `data` is extra index of `TypeUnion`. - type_union, - /// A function body type. - /// `data` is extra index to `TypeFunction`. - type_function, /// Typed `undefined`. /// `data` is `Index` of the type. @@ -5644,12 +4994,6 @@ pub const Tag = enum(u8) { /// A negative integer value. /// data is a limbs index to `Int`. int_negative, - /// The ABI alignment of a lazy type. - /// data is extra index of `IntLazy`. - int_lazy_align, - /// The ABI size of a lazy type. - /// data is extra index of `IntLazy`. - int_lazy_size, /// An error value. /// data is extra index of `Key.Error`. error_set_error, @@ -5747,24 +5091,77 @@ pub const Tag = enum(u8) { const Union = Key.Union; const TypePointer = Key.PtrType; + const struct_packed_encoding = .{ + .summary = .@"{.payload.name%summary#\"}", + .payload = TypeStructPacked, + .trailing = struct { + type_hash: ?u64, + captures: ?[]CaptureValue, + field_names: []NullTerminatedString, + field_types: []Index, + }, + .config = .{ + .@"trailing.type_hash.?" = .@"payload.captures_len == .reified", + .@"trailing.captures.?" = .@"payload.captures_len != .reified", + .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)", + .@"trailing.field_names.len" = .@"payload.fields_len", + .@"trailing.field_types.len" = .@"payload.fields_len", + }, + }; + const struct_packed_defaults_encoding = .{ + .summary = .@"{.payload.name%summary#\"}", + .payload = TypeStructPacked, + .trailing = struct { + type_hash: ?u64, + captures: ?[]CaptureValue, + field_names: []NullTerminatedString, + field_types: []Index, + field_defaults: []Index, + }, + .config = .{ + .@"trailing.type_hash.?" = .@"payload.captures_len == .reified", + .@"trailing.captures.?" = .@"payload.captures_len != .reified", + .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)", + .@"trailing.field_names.len" = .@"payload.fields_len", + .@"trailing.field_types.len" = .@"payload.fields_len", + .@"trailing.field_defaults.len" = .@"payload.fields_len", + }, + }; + const union_packed_encoding = .{ + .summary = .@"{.payload.name%summary#\"}", + .payload = TypeUnionPacked, + .trailing = struct { + type_hash: ?u64, + captures: ?[]CaptureValue, + field_types: []Index, + }, + .config = .{ + .@"trailing.type_hash.?" = .@"payload.captures_len == .reified", + .@"trailing.captures.?" = .@"payload.captures_len != .reified", + .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)", + .@"trailing.field_types.len" = .@"payload.fields_len", + }, + }; const enum_explicit_encoding = .{ .summary = .@"{.payload.name%summary#\"}", - .payload = EnumExplicit, + .payload = TypeEnum, .trailing = struct { - owner_union: Index, - captures: ?[]CaptureValue, + owner_union: ?Index, + zir_index: ?TrackedInst.Index, type_hash: ?u64, + captures: ?[]CaptureValue, + field_value_map: MapIndex, field_names: []NullTerminatedString, - tag_values: []Index, + field_values: []Index, }, .config = .{ - .@"trailing.owner_union.?" = .@"payload.zir_index == .none", - .@"trailing.cau.?" = .@"payload.zir_index != .none", - .@"trailing.captures.?" = .@"payload.captures_len < 0xffffffff", - .@"trailing.captures.?.len" = .@"payload.captures_len", - .@"trailing.type_hash.?" = .@"payload.captures_len == 0xffffffff", + .@"trailing.owner_union.?" = .@"payload.captures_len == .generated_union_tag", + .@"trailing.zir_index.?" = .@"payload.captures_len != .generated_union_tag", + .@"trailing.type_hash.?" = .@"payload.captures_len == .reified", + .@"trailing.captures.?" = .@"payload.captures_len != .reified and payload.captures_len != .generated_enum_tag", + .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)", .@"trailing.field_names.len" = .@"payload.fields_len", - .@"trailing.tag_values.len" = .@"payload.fields_len", + .@"trailing.field_values.len" = .@"payload.fields_len", }, }; const encodings = .{ @@ -5792,107 +5189,7 @@ pub const Tag = enum(u8) { .summary = .@"@typeInfo(@typeInfo(@TypeOf({.data%summary})).@\"fn\".return_type.?).error_union.error_set", .data = Index, }, - .type_enum_auto = .{ - .summary = .@"{.payload.name%summary#\"}", - .payload = EnumAuto, - .trailing = struct { - owner_union: ?Index, - captures: ?[]CaptureValue, - type_hash: ?u64, - field_names: []NullTerminatedString, - }, - .config = .{ - .@"trailing.owner_union.?" = .@"payload.zir_index == .none", - .@"trailing.cau.?" = .@"payload.zir_index != .none", - .@"trailing.captures.?" = .@"payload.captures_len < 0xffffffff", - .@"trailing.captures.?.len" = .@"payload.captures_len", - .@"trailing.type_hash.?" = .@"payload.captures_len == 0xffffffff", - .@"trailing.field_names.len" = .@"payload.fields_len", - }, - }, - .type_enum_explicit = enum_explicit_encoding, - .type_enum_nonexhaustive = enum_explicit_encoding, .simple_type = .{ .summary = .@"{.index%value#.}", .index = SimpleType }, - .type_opaque = .{ - .summary = .@"{.payload.name%summary#\"}", - .payload = TypeOpaque, - .trailing = struct { captures: []CaptureValue }, - .config = .{ .@"trailing.captures.len" = .@"payload.captures_len" }, - }, - .type_struct = .{ - .summary = .@"{.payload.name%summary#\"}", - .payload = TypeStruct, - .trailing = struct { - captures_len: ?u32, - captures: ?[]CaptureValue, - type_hash: ?u64, - field_types: []Index, - field_names_map: OptionalMapIndex, - field_names: []NullTerminatedString, - field_inits: ?[]Index, - field_aligns: ?[]Alignment, - field_is_comptime_bits: ?[]u32, - field_index: ?[]LoadedStructType.RuntimeOrder, - field_offset: []u32, - }, - .config = .{ - .@"trailing.captures_len.?" = .@"payload.flags.any_captures", - .@"trailing.captures.?" = .@"payload.flags.any_captures", - .@"trailing.captures.?.len" = .@"trailing.captures_len.?", - .@"trailing.type_hash.?" = .@"payload.flags.is_reified", - .@"trailing.field_types.len" = .@"payload.fields_len", - .@"trailing.field_names.len" = .@"payload.fields_len", - .@"trailing.field_inits.?" = .@"payload.flags.any_default_inits", - .@"trailing.field_inits.?.len" = .@"payload.fields_len", - .@"trailing.field_aligns.?" = .@"payload.flags.any_aligned_fields", - .@"trailing.field_aligns.?.len" = .@"payload.fields_len", - .@"trailing.field_is_comptime_bits.?" = .@"payload.flags.any_comptime_fields", - .@"trailing.field_is_comptime_bits.?.len" = .@"(payload.fields_len + 31) / 32", - .@"trailing.field_index.?" = .@"!payload.flags.is_extern", - .@"trailing.field_index.?.len" = .@"payload.fields_len", - .@"trailing.field_offset.len" = .@"payload.fields_len", - }, - }, - .type_struct_packed = .{ - .summary = .@"{.payload.name%summary#\"}", - .payload = TypeStructPacked, - .trailing = struct { - captures_len: ?u32, - captures: ?[]CaptureValue, - type_hash: ?u64, - field_types: []Index, - field_names: []NullTerminatedString, - }, - .config = .{ - .@"trailing.captures_len.?" = .@"payload.flags.any_captures", - .@"trailing.captures.?" = .@"payload.flags.any_captures", - .@"trailing.captures.?.len" = .@"trailing.captures_len.?", - .@"trailing.type_hash.?" = .@"payload.is_flags.is_reified", - .@"trailing.field_types.len" = .@"payload.fields_len", - .@"trailing.field_names.len" = .@"payload.fields_len", - }, - }, - .type_struct_packed_inits = .{ - .summary = .@"{.payload.name%summary#\"}", - .payload = TypeStructPacked, - .trailing = struct { - captures_len: ?u32, - captures: ?[]CaptureValue, - type_hash: ?u64, - field_types: []Index, - field_names: []NullTerminatedString, - field_inits: []Index, - }, - .config = .{ - .@"trailing.captures_len.?" = .@"payload.flags.any_captures", - .@"trailing.captures.?" = .@"payload.flags.any_captures", - .@"trailing.captures.?.len" = .@"trailing.captures_len.?", - .@"trailing.type_hash.?" = .@"payload.is_flags.is_reified", - .@"trailing.field_types.len" = .@"payload.fields_len", - .@"trailing.field_names.len" = .@"payload.fields_len", - .@"trailing.field_inits.len" = .@"payload.fields_len", - }, - }, .type_tuple = .{ .summary = .@"struct {...}", .payload = TypeTuple, @@ -5905,25 +5202,6 @@ pub const Tag = enum(u8) { .@"trailing.field_values.len" = .@"payload.fields_len", }, }, - .type_union = .{ - .summary = .@"{.payload.name%summary#\"}", - .payload = TypeUnion, - .trailing = struct { - captures_len: ?u32, - captures: ?[]CaptureValue, - type_hash: ?u64, - field_types: []Index, - field_aligns: []Alignment, - }, - .config = .{ - .@"trailing.captures_len.?" = .@"payload.flags.any_captures", - .@"trailing.captures.?" = .@"payload.flags.any_captures", - .@"trailing.captures.?.len" = .@"trailing.captures_len.?", - .@"trailing.type_hash.?" = .@"payload.is_flags.is_reified", - .@"trailing.field_types.len" = .@"payload.fields_len", - .@"trailing.field_aligns.len" = .@"payload.fields_len", - }, - }, .type_function = .{ .summary = .@"fn (...) ... {.payload.return_type%summary}", .payload = TypeFunction, @@ -5941,6 +5219,93 @@ pub const Tag = enum(u8) { }, }, + .type_struct = .{ + .summary = .@"{.payload.name%summary#\"}", + .payload = TypeStruct, + .trailing = struct { + type_hash: ?u64, + captures_len: ?u32, + captures: ?[]CaptureValue, + field_names: []NullTerminatedString, + field_types: []Index, + field_defaults: ?[]Index, + field_aligns: ?[]Alignment, + field_is_comptime_bits: ?[]u32, + field_runtime_order: ?[]u32, + field_offsets: []u32, + }, + .config = .{ + .@"trailing.type_hash.?" = .@"payload.flags.any_captures == .reified", + .@"trailing.captures_len.?" = .@"payload.flags.any_captures == .true", + .@"trailing.captures.?" = .@"payload.flags.any_captures == .true", + .@"trailing.captures.?.len" = .@"trailing.captures_len.?", + .@"trailing.field_names.len" = .@"payload.fields_len", + .@"trailing.field_types.len" = .@"payload.fields_len", + .@"trailing.field_defaults.?" = .@"payload.flags.any_field_defaults", + .@"trailing.field_defaults.?.len" = .@"payload.fields_len", + .@"trailing.field_aligns.?" = .@"payload.flags.any_field_aligns", + .@"trailing.field_aligns.?.len" = .@"payload.fields_len", + .@"trailing.field_is_comptime_bits.?" = .@"payload.flags.any_comptime_fields", + .@"trailing.field_is_comptime_bits.?.len" = .@"(payload.fields_len + 31) / 32", + .@"trailing.field_runtime_order.?" = .@"payload.flags.layout == .auto", + .@"trailing.field_runtime_order.?.len" = .@"payload.fields_len", + .@"trailing.field_offsets.len" = .@"payload.fields_len", + }, + }, + .type_struct_packed_auto = struct_packed_encoding, + .type_struct_packed_explicit = struct_packed_encoding, + .type_struct_packed_auto_defaults = struct_packed_defaults_encoding, + .type_struct_packed_explicit_defaults = struct_packed_defaults_encoding, + .type_union = .{ + .summary = .@"{.payload.name%summary#\"}", + .payload = TypeUnion, + .trailing = struct { + type_hash: ?u64, + captures_len: ?u32, + captures: ?[]CaptureValue, + field_types: []Index, + field_aligns: ?[]Alignment, + }, + .config = .{ + .@"trailing.type_hash.?" = .@"payload.flags.any_captures == .reified", + .@"trailing.captures_len.?" = .@"payload.flags.any_captures == .true", + .@"trailing.captures.?" = .@"payload.flags.any_captures == .true", + .@"trailing.captures.?.len" = .@"trailing.captures_len.?", + .@"trailing.field_types.len" = .@"payload.fields_len", + .@"trailing.field_aligns.?" = .@"payloads.flags.any_field_aligns", + .@"trailing.field_aligns.?.len" = .@"payload.fields_len", + }, + }, + .type_union_packed_auto = union_packed_encoding, + .type_union_packed_explicit = union_packed_encoding, + .type_enum_auto = .{ + .summary = .@"{.payload.name%summary#\"}", + .payload = TypeEnum, + .trailing = struct { + owner_union: ?Index, + zir_index: ?TrackedInst.Index, + type_hash: ?u64, + captures: ?[]CaptureValue, + field_names: []NullTerminatedString, + }, + .config = .{ + .@"trailing.owner_union.?" = .@"payload.captures_len == .generated_union_tag", + .@"trailing.zir_index.?" = .@"payload.captures_len != .generated_union_tag", + .@"trailing.type_hash.?" = .@"payload.captures_len == .reified", + .@"trailing.captures.?" = .@"payload.captures_len != .reified and payload.captures_len != .generated_enum_tag", + .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)", + .@"trailing.field_names.len" = .@"payload.fields_len", + }, + }, + .type_enum_explicit = enum_explicit_encoding, + .type_enum_nonexhaustive = enum_explicit_encoding, + .type_opaque = .{ + .summary = .@"{.payload.name%summary#\"}", + .payload = TypeOpaque, + .trailing = struct { captures: []CaptureValue }, + .config = .{ .@"trailing.captures.len" = .@"payload.captures_len" }, + }, + .undef = .{ .summary = .@"@as({.data%summary}, undefined)", .data = Index }, .simple_value = .{ .summary = .@"{.index%value#.}", .index = SimpleValue }, .ptr_nav = .{ @@ -5999,8 +5364,6 @@ pub const Tag = enum(u8) { .int_small = .{ .summary = .@"@as({.payload.ty%summary}, {.payload.value%value})", .payload = IntSmall }, .int_positive = .{}, .int_negative = .{}, - .int_lazy_align = .{ .summary = .@"@as({.payload.ty%summary}, @alignOf({.payload.lazy_ty%summary}))", .payload = IntLazy }, - .int_lazy_size = .{ .summary = .@"@as({.payload.ty%summary}, @sizeOf({.payload.lazy_ty%summary}))", .payload = IntLazy }, .error_set_error = .{ .summary = .@"@as({.payload.ty%summary}, error.@{.payload.name%summary})", .payload = Error }, .error_union_error = .{ .summary = .@"@as({.payload.ty%summary}, error.@{.payload.name%summary})", .payload = Error }, .error_union_payload = .{ .summary = .@"@as({.payload.ty%summary}, {.payload.val%summary})", .payload = TypeValue }, @@ -6166,77 +5529,10 @@ pub const Tag = enum(u8) { pub const Flags = packed struct(u32) { cc: PackedCallingConvention, is_var_args: bool, - is_generic: bool, has_comptime_bits: bool, has_noalias_bits: bool, is_noinline: bool, - _: u9 = 0, - }; - }; - - /// Trailing: - /// 0. captures_len: u32 // if `any_captures` - /// 1. capture: CaptureValue // for each `captures_len` - /// 2. type_hash: PackedU64 // if `is_reified` - /// 3. field type: Index for each field; declaration order - /// 4. field align: Alignment for each field; declaration order - pub const TypeUnion = struct { - name: NullTerminatedString, - name_nav: Nav.Index.Optional, - flags: Flags, - /// This could be provided through the tag type, but it is more convenient - /// to store it directly. This is also necessary for `dumpStatsFallible` to - /// work on unresolved types. - fields_len: u32, - /// Only valid after .have_layout - size: u32, - /// Only valid after .have_layout - padding: u32, - namespace: NamespaceIndex, - /// The enum that provides the list of field names and values. - tag_ty: Index, - zir_index: TrackedInst.Index, - - pub const Flags = packed struct(u32) { - any_captures: bool, - runtime_tag: LoadedUnionType.RuntimeTag, - /// If false, the field alignment trailing data is omitted. - any_aligned_fields: bool, - layout: std.builtin.Type.ContainerLayout, - status: LoadedUnionType.Status, - requires_comptime: RequiresComptime, - assumed_runtime_bits: bool, - assumed_pointer_aligned: bool, - alignment: Alignment, - is_reified: bool, - _: u12 = 0, - }; - }; - - /// Trailing: - /// 0. captures_len: u32 // if `any_captures` - /// 1. capture: CaptureValue // for each `captures_len` - /// 2. type_hash: PackedU64 // if `is_reified` - /// 3. type: Index for each fields_len - /// 4. name: NullTerminatedString for each fields_len - /// 5. init: Index for each fields_len // if tag is type_struct_packed_inits - pub const TypeStructPacked = struct { - name: NullTerminatedString, - name_nav: Nav.Index.Optional, - zir_index: TrackedInst.Index, - fields_len: u32, - namespace: NamespaceIndex, - backing_int_ty: Index, - names_map: MapIndex, - flags: Flags, - - pub const Flags = packed struct(u32) { - any_captures: bool = false, - /// Dependency loop detection when resolving field inits. - field_inits_wip: bool = false, - inits_resolved: bool = false, - is_reified: bool = false, - _: u28 = 0, + _: u10 = 0, }; }; @@ -6255,75 +5551,220 @@ pub const Tag = enum(u8) { /// than coming up with some other scheme for the data. /// /// Trailing: - /// 0. captures_len: u32 // if `any_captures` - /// 1. capture: CaptureValue // for each `captures_len` - /// 2. type_hash: PackedU64 // if `is_reified` - /// 3. type: Index for each field in declared order - /// 4. if any_default_inits: - /// init: Index // for each field in declared order - /// 5. if any_aligned_fields: - /// align: Alignment // for each field in declared order - /// 6. if any_comptime_fields: - /// field_is_comptime_bits: u32 // minimal number of u32s needed, LSB is field 0 - /// 7. if not is_extern: - /// field_index: RuntimeOrder // for each field in runtime order - /// 8. field_offset: u32 // for each field in declared order, undef until layout_resolved + /// 0. type_hash: PackedU64 // if `any_captures == .reified` + /// 1. captures_len: u32 // if `any_captures == .true` + /// 2. capture: CaptureValue // for each `captures_len` + /// 3. field_name: NullTerminatedString // for each `fields_len` + /// 4. field_type: Index // for each `fields_len` + /// 5. field_default: Index // if `any_field_defaults`; for each `fields_len` + /// 6. field_align: Alignment // if `any_field_aligns`; for each `fields_len` + /// 7. field_is_comptime_bits: u32 // if `any_comptime_fields`; minimum `u32` for `fields_len`; LSB is field 0 + /// 8. field_runtime_order: RuntimeOrder // if `layout == .auto`; for each `fields_len` + /// 9. field_offset: u32 // for each `fields_len` pub const TypeStruct = struct { + zir_index: TrackedInst.Index, + name: NullTerminatedString, name_nav: Nav.Index.Optional, - zir_index: TrackedInst.Index, namespace: NamespaceIndex, + fields_len: u32, + field_name_map: MapIndex, + + /// Size in bytes of the whole struct. Always 0 until layout resolved. + size: u32, + flags: Flags, + + pub const Flags = packed struct(u32) { + any_captures: enum(u2) { true, false, reified }, + + /// `packed` layout is represented separately by `TypeStructPacked`. + layout: enum(u1) { auto, @"extern" }, + + any_comptime_fields: bool, + any_field_defaults: bool, + any_field_aligns: bool, + + /// Whether the struct is an OPV type. Always `false` until layout resolved. + /// The actual OPV is not cached, but caching this bit of state means we avoid + /// repeatedly doing redundant checks to find that the struct is not OPV! + has_one_possible_value: bool, + /// Like `has_one_possible_value`, but for a "noreturn" union (where all fields are noreturn). + has_no_possible_value: bool, + /// Whether the struct is comptime-only. Always `false` until layout resolved. + comptime_only: bool, + /// Alignment of the whole struct. Always `.none` until layout resolved. + alignment: Alignment, + + _: u17 = 0, + }; + }; + + /// Trailing: + /// 0. type_hash: PackedU64 // if `captures_len == .reified` + /// 1. capture: CaptureValue // if `captures_len != .reified`; for each `captures_len` + /// 2. field_name: NullTerminatedString // for each `fields_len` + /// 3. field_type: Index // for each `fields_len` + /// 4. field_default: Index // if item tag implies field defaults; for each `fields_len` + pub const TypeStructPacked = struct { + zir_index: TrackedInst.Index, + captures_len: enum(u32) { + reified = std.math.maxInt(u32), + _, + }, + + name: NullTerminatedString, + name_nav: Nav.Index.Optional, + namespace: NamespaceIndex, + + /// The corresponding `PackedBackingMode` depends on the item's `Tag`. + backing_int_type: Index, + + fields_len: u32, + field_name_map: MapIndex, + }; + + /// Field names are intentionally omitted---they are available in `enum_tag_type`. + /// + /// Trailing: + /// 0. type_hash: PackedU64 // if `any_captures == .reified` + /// 1. captures_len: u32 // if `any_captures == .true` + /// 2. capture: CaptureValue // if `any_captures == .true`; for each `captures_len` + /// 3. field_type: Index // for each `fields_len` + /// 4. field_align: Alignment // for each `fields_len` if `any_field_aligns` + pub const TypeUnion = struct { + zir_index: TrackedInst.Index, + + name: NullTerminatedString, + name_nav: Nav.Index.Optional, + namespace: NamespaceIndex, + /// The enum that provides the list of field names and values. + enum_tag_type: Index, + + /// This could be provided through the tag type, but it is more convenient + /// to store it directly. This is also necessary for `dumpStatsFallible` to + /// work on unresolved types. + /// MLUGG TODO: reconsider, because we resolve the tag type eagerly now. + fields_len: u32, + + /// Always 0 until layout resolved. size: u32, + /// Always 0 until layout resolved. + padding: u32, + + flags: Flags, pub const Flags = packed struct(u32) { - any_captures: bool = false, - is_extern: bool = false, - known_non_opv: bool = false, - requires_comptime: RequiresComptime = @enumFromInt(0), - assumed_runtime_bits: bool = false, - assumed_pointer_aligned: bool = false, - any_comptime_fields: bool = false, - any_default_inits: bool = false, - any_aligned_fields: bool = false, - /// `.none` until layout_resolved - alignment: Alignment = @enumFromInt(0), - /// Dependency loop detection when resolving struct alignment. - alignment_wip: bool = false, - /// Dependency loop detection when resolving field types. - field_types_wip: bool = false, - /// Dependency loop detection when resolving struct layout. - layout_wip: bool = false, - /// Indicates whether `size`, `alignment`, runtime field order, and - /// field offets are populated. - layout_resolved: bool = false, - /// Dependency loop detection when resolving field inits. - field_inits_wip: bool = false, - /// Indicates whether `field_inits` has been resolved. - inits_resolved: bool = false, - // The types and all its fields have had their layout resolved. Even through pointer = false, - // which `layout_resolved` does not ensure. - fully_resolved: bool = false, - is_reified: bool = false, - _: u8 = 0, + any_captures: enum(u2) { true, false, reified }, + + /// Whether `enum_tag_type` was explicitly specified with `union(E)` syntax. + /// + /// For `union(enum(E))` syntax, this is `false`, but the generated enum tag type is + /// considered to have an explicitly specified integer tag type. + explicit_tag_type: bool, + + /// `packed` layout is represented separately by `TypeStructPacked`. + layout: enum(u1) { auto, @"extern" }, + + any_field_aligns: bool, + runtime_tag: LoadedUnionType.RuntimeTag, + + /// Whether the union is an OPV type. Always `false` until layout resolved. + /// The actual OPV is not cached, but caching this bit of state means we avoid + /// repeatedly doing redundant checks to find that the union is not OPV! + has_one_possible_value: bool, + /// Like `has_one_possible_value`, but for a "noreturn" union (where all fields are noreturn). + has_no_possible_value: bool, + /// Whether the union is comptime-only. Always `false` until layout resolved. + comptime_only: bool, + /// Alignment of the whole union. Always `.none` until layout resolved. + alignment: Alignment, + + _: u16 = 0, }; }; + /// Field names are intentionally omitted---they are available in `enum_tag_type`. + /// + /// Trailing: + /// 0. type_hash: PackedU64 // if `captures_len == .reified` + /// 1. capture: CaptureValue // if `captures_len != .reified`; for each `captures_len` + /// 2. field_type: Index // for each `fields_len` + pub const TypeUnionPacked = struct { + zir_index: TrackedInst.Index, + captures_len: enum(u32) { + reified = std.math.maxInt(u32), + _, + }, + + name: NullTerminatedString, + name_nav: Nav.Index.Optional, + namespace: NamespaceIndex, + + /// The corresponding `PackedBackingMode` depends on the item's `Tag`. + backing_int_type: Index, + /// Although packed unions do not semantically have a tag type, the compiler still assigns + /// them a "hypothetical" tag type. + enum_tag_type: Index, + + /// This could be provided through the tag type, but it is more convenient + /// to store it directly. This is also necessary for `dumpStatsFallible` to + /// work on unresolved types. + /// MLUGG TODO: reconsider, because we resolve the tag type eagerly now. + fields_len: u32, + }; + + /// Trailing: + /// 0. owner_union: Index // if `captures_len == .generated_union_tag` + /// 1. zir_index: TrackedInst.Index // if `captures_len != .generated_union_tag` + /// 2. type_hash: PackedU64 // if `captures_len == .reified` + /// 3. capture: CaptureValue // if `captures_len` is not a named tag; for each `captures_len` + /// 4. field_value_map: MapIndex // if tag is not `.type_enum_auto` + /// 5. field_name: NullTerminatedString // for each `fields_len` + /// 6. field_value: Index // if tag is not `.type_enum_auto`; for each `fields_len` + pub const TypeEnum = struct { + captures_len: enum(u32) { + reified = std.math.maxInt(u32), + generated_union_tag = std.math.maxInt(u32) - 1, + _, + }, + + name: NullTerminatedString, + name_nav: Nav.Index.Optional, + namespace: NamespaceIndex, + + /// An integer type which is used for the numerical value of the enum. Whether this was + /// user-provided or inferred by the compiler depends on the tag. Either way, the field + /// is populated immediately (i.e. does not require any type resolution). + int_tag_type: Index, + + fields_len: u32, + field_name_map: MapIndex, + }; + /// Trailing: /// 0. capture: CaptureValue // for each `captures_len` pub const TypeOpaque = struct { - name: NullTerminatedString, - name_nav: Nav.Index.Optional, - /// Contains the declarations inside this opaque. - namespace: NamespaceIndex, - /// The index of the `opaque_decl` instruction. zir_index: TrackedInst.Index, - /// `std.math.maxInt(u32)` indicates this type is reified. captures_len: u32, + + name: NullTerminatedString, + name_nav: Nav.Index.Optional, + namespace: NamespaceIndex, }; }; +/// Differentiates between user-provided and compiler-generated backing types for packed aggregates. +pub const PackedBackingMode = enum(u1) { + /// The backing type was explicitly provided by the user, i.e. `packed struct(T)` or `packed union(T)`. + /// Type resolution simply *validates* that type. + explicit, + /// No backing type was explicitly provided by the user. Type layout resolution will populate the + /// backing type based on the field types; before then it is invalid (probably `.none`). + auto, +}; + /// State that is mutable during semantic analysis. This data is not used for /// equality or hashing, except for `inferred_error_set` which is considered /// to be part of the type of the function. @@ -6536,10 +5977,8 @@ pub const Alignment = enum(u6) { pub const empty: Slice = .{ .tid = .main, .start = 0, .len = 0 }; pub fn get(slice: Slice, ip: *const InternPool) []Alignment { - // TODO: implement @ptrCast between slices changing the length const extra = ip.getLocalShared(slice.tid).extra.acquire(); - //const bytes: []u8 = @ptrCast(extra.view().items(.@"0")[slice.start..]); - const bytes: []u8 = std.mem.sliceAsBytes(extra.view().items(.@"0")[slice.start..]); + const bytes: []u8 = @ptrCast(extra.view().items(.@"0")[slice.start..]); return @ptrCast(bytes[0..slice.len]); } }; @@ -6596,55 +6035,6 @@ pub const Array = struct { } }; -/// Trailing: -/// 0. owner_union: Index // if `zir_index == .none` -/// 1. capture: CaptureValue // for each `captures_len` -/// 2. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`) -/// 3. field name: NullTerminatedString for each fields_len; declaration order -/// 4. tag value: Index for each fields_len; declaration order -pub const EnumExplicit = struct { - name: NullTerminatedString, - name_nav: Nav.Index.Optional, - /// `std.math.maxInt(u32)` indicates this type is reified. - captures_len: u32, - namespace: NamespaceIndex, - /// An integer type which is used for the numerical value of the enum, which - /// has been explicitly provided by the enum declaration. - int_tag_type: Index, - fields_len: u32, - /// Maps field names to declaration index. - names_map: MapIndex, - /// Maps field values to declaration index. - /// If this is `none`, it means the trailing tag values are absent because - /// they are auto-numbered. - values_map: OptionalMapIndex, - /// `none` means this is a generated tag type. - /// There will be a trailing union type for which this is a tag. - zir_index: TrackedInst.Index.Optional, -}; - -/// Trailing: -/// 0. owner_union: Index // if `zir_index == .none` -/// 1. capture: CaptureValue // for each `captures_len` -/// 2. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`) -/// 3. field name: NullTerminatedString for each fields_len; declaration order -pub const EnumAuto = struct { - name: NullTerminatedString, - name_nav: Nav.Index.Optional, - /// `std.math.maxInt(u32)` indicates this type is reified. - captures_len: u32, - namespace: NamespaceIndex, - /// An integer type which is used for the numerical value of the enum, which - /// was inferred by Zig based on the number of tags. - int_tag_type: Index, - fields_len: u32, - /// Maps field names to declaration index. - names_map: MapIndex, - /// `none` means this is a generated tag type. - /// There will be a trailing union type for which this is a tag. - zir_index: TrackedInst.Index.Optional, -}; - pub const PackedU64 = packed struct(u64) { a: u32, b: u32, @@ -6827,11 +6217,6 @@ pub const IntSmall = struct { value: u32, }; -pub const IntLazy = struct { - ty: Index, - lazy_ty: Index, -}; - /// A f64 value, broken up into 2 u32 parts. pub const Float64 = struct { piece0: u32, @@ -6994,7 +6379,9 @@ pub fn deinit(ip: *InternPool, gpa: Allocator, io: Io) void { ip.src_hash_deps.deinit(gpa); ip.nav_val_deps.deinit(gpa); ip.nav_ty_deps.deinit(gpa); - ip.interned_deps.deinit(gpa); + ip.func_ies_deps.deinit(gpa); + ip.type_layout_deps.deinit(gpa); + ip.type_inits_deps.deinit(gpa); ip.zon_file_deps.deinit(gpa); ip.embed_file_deps.deinit(gpa); ip.namespace_deps.deinit(gpa); @@ -7130,132 +6517,138 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { .type_inferred_error_set => .{ .inferred_error_set_type = @enumFromInt(data), }, - - .type_opaque => .{ .opaque_type = ns: { - const extra = extraDataTrail(unwrapped_index.getExtra(ip), Tag.TypeOpaque, data); - if (extra.data.captures_len == std.math.maxInt(u32)) { - break :ns .{ .reified = .{ - .zir_index = extra.data.zir_index, - .type_hash = 0, - } }; - } - break :ns .{ .declared = .{ - .zir_index = extra.data.zir_index, - .captures = .{ .owned = .{ - .tid = unwrapped_index.tid, - .start = extra.end, - .len = extra.data.captures_len, - } }, - } }; - } }, - - .type_struct => .{ .struct_type = ns: { - const extra_list = unwrapped_index.getExtra(ip); - const extra_items = extra_list.view().items(.@"0"); - const zir_index: TrackedInst.Index = @enumFromInt(extra_items[data + std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?]); - const flags: Tag.TypeStruct.Flags = @bitCast(@atomicLoad(u32, &extra_items[data + std.meta.fieldIndex(Tag.TypeStruct, "flags").?], .unordered)); - const end_extra_index = data + @as(u32, @typeInfo(Tag.TypeStruct).@"struct".fields.len); - if (flags.is_reified) { - assert(!flags.any_captures); - break :ns .{ .reified = .{ - .zir_index = zir_index, - .type_hash = extraData(extra_list, PackedU64, end_extra_index).get(), - } }; - } - break :ns .{ .declared = .{ - .zir_index = zir_index, - .captures = .{ .owned = if (flags.any_captures) .{ - .tid = unwrapped_index.tid, - .start = end_extra_index + 1, - .len = extra_list.view().items(.@"0")[end_extra_index], - } else CaptureValue.Slice.empty }, - } }; - } }, - - .type_struct_packed, .type_struct_packed_inits => .{ .struct_type = ns: { - const extra_list = unwrapped_index.getExtra(ip); - const extra_items = extra_list.view().items(.@"0"); - const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "zir_index").?]); - const flags: Tag.TypeStructPacked.Flags = @bitCast(@atomicLoad(u32, &extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "flags").?], .unordered)); - const end_extra_index = data + @as(u32, @typeInfo(Tag.TypeStructPacked).@"struct".fields.len); - if (flags.is_reified) { - assert(!flags.any_captures); - break :ns .{ .reified = .{ - .zir_index = zir_index, - .type_hash = extraData(extra_list, PackedU64, end_extra_index).get(), - } }; - } - break :ns .{ .declared = .{ - .zir_index = zir_index, - .captures = .{ .owned = if (flags.any_captures) .{ - .tid = unwrapped_index.tid, - .start = end_extra_index + 1, - .len = extra_items[end_extra_index], - } else CaptureValue.Slice.empty }, - } }; - } }, + .type_function => .{ .func_type = extraFuncType(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) }, .type_tuple => .{ .tuple_type = extraTypeTuple(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) }, + + .type_struct => .{ .struct_type = ns: { + const extra_list = unwrapped_index.getExtra(ip); + const extra = extraDataTrail(extra_list, Tag.TypeStruct, data); + break :ns switch (extra.data.flags.any_captures) { + .reified => .{ .reified = .{ + .zir_index = extra.data.zir_index, + .type_hash = extraData(extra_list, PackedU64, extra.end).get(), + } }, + .false => .{ .declared = .{ + .zir_index = extra.data.zir_index, + .arg_ty = .none, + .captures = .{ .owned = .empty }, + } }, + .true => .{ .declared = .{ + .zir_index = extra.data.zir_index, + .arg_ty = .none, + .captures = .{ .owned = .{ + .tid = unwrapped_index.tid, + .start = extra.end + 1, + .len = extra_list.view().items(.@"0")[extra.end], + } }, + } }, + }; + } }, + .type_struct_packed_auto, + .type_struct_packed_explicit, + .type_struct_packed_auto_defaults, + .type_struct_packed_explicit_defaults, + => .{ .struct_type = ns: { + const extra_list = unwrapped_index.getExtra(ip); + const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, data); + break :ns switch (extra.data.captures_len) { + .reified => .{ .reified = .{ + .zir_index = extra.data.zir_index, + .type_hash = extraData(extra_list, PackedU64, extra.end).get(), + } }, + _ => .{ .declared = .{ + .zir_index = extra.data.zir_index, + .arg_ty = switch (item.tag) { + .type_struct_packed_auto, .type_struct_packed_auto_defaults => .none, + .type_struct_packed_explicit, .type_struct_packed_explicit_defaults => extra.data.backing_int_type, + else => unreachable, + }, + .captures = .{ .owned = .{ + .tid = unwrapped_index.tid, + .start = extra.end, + .len = @intFromEnum(extra.data.captures_len), + } }, + } }, + }; + } }, .type_union => .{ .union_type = ns: { const extra_list = unwrapped_index.getExtra(ip); const extra = extraDataTrail(extra_list, Tag.TypeUnion, data); - if (extra.data.flags.is_reified) { - assert(!extra.data.flags.any_captures); - break :ns .{ .reified = .{ + break :ns switch (extra.data.flags.any_captures) { + .reified => .{ .reified = .{ .zir_index = extra.data.zir_index, .type_hash = extraData(extra_list, PackedU64, extra.end).get(), - } }; - } + } }, + .false => .{ .declared = .{ + .zir_index = extra.data.zir_index, + .arg_ty = if (extra.data.flags.explicit_tag_type) extra.data.enum_tag_type else .none, + .captures = .{ .owned = .empty }, + } }, + .true => .{ .declared = .{ + .zir_index = extra.data.zir_index, + .arg_ty = if (extra.data.flags.explicit_tag_type) extra.data.enum_tag_type else .none, + .captures = .{ .owned = .{ + .tid = unwrapped_index.tid, + .start = extra.end + 1, + .len = extra_list.view().items(.@"0")[extra.end], + } }, + } }, + }; + } }, + .type_union_packed_auto, .type_union_packed_explicit => .{ .union_type = ns: { + const extra_list = unwrapped_index.getExtra(ip); + const extra = extraDataTrail(extra_list, Tag.TypeUnionPacked, data); + break :ns switch (extra.data.captures_len) { + .reified => .{ .reified = .{ + .zir_index = extra.data.zir_index, + .type_hash = extraData(extra_list, PackedU64, extra.end).get(), + } }, + _ => .{ .declared = .{ + .zir_index = extra.data.zir_index, + .arg_ty = switch (item.tag) { + .type_union_packed_auto => .none, + .type_union_packed_explicit => extra.data.backing_int_type, + else => unreachable, + }, + .captures = .{ .owned = .{ + .tid = unwrapped_index.tid, + .start = extra.end, + .len = @intFromEnum(extra.data.captures_len), + } }, + } }, + }; + } }, + .type_enum_auto, .type_enum_explicit, .type_enum_nonexhaustive => .{ .enum_type = ns: { + const extra_list = unwrapped_index.getExtra(ip); + const extra = extraDataTrail(extra_list, Tag.TypeEnum, data); + break :ns switch (extra.data.captures_len) { + .reified => .{ .reified = .{ + .zir_index = @enumFromInt(extra_list.view().items(.@"0")[extra.end]), + .type_hash = extraData(extra_list, PackedU64, extra.end + 1).get(), + } }, + .generated_union_tag => .{ .generated_union_tag = owner_union: { + break :owner_union @enumFromInt(extra_list.view().items(.@"0")[extra.end]); + } }, + _ => .{ .declared = .{ + .zir_index = @enumFromInt(extra_list.view().items(.@"0")[extra.end]), + .arg_ty = switch (item.tag) { + .type_enum_auto => .none, + .type_enum_explicit, .type_enum_nonexhaustive => extra.data.int_tag_type, + else => unreachable, + }, + .captures = .{ .owned = .{ + .tid = unwrapped_index.tid, + .start = extra.end + 1, + .len = @intFromEnum(extra.data.captures_len), + } }, + } }, + }; + } }, + .type_opaque => .{ .opaque_type = ns: { + const extra = extraDataTrail(unwrapped_index.getExtra(ip), Tag.TypeOpaque, data); break :ns .{ .declared = .{ .zir_index = extra.data.zir_index, - .captures = .{ .owned = if (extra.data.flags.any_captures) .{ - .tid = unwrapped_index.tid, - .start = extra.end + 1, - .len = extra_list.view().items(.@"0")[extra.end], - } else CaptureValue.Slice.empty }, - } }; - } }, - - .type_enum_auto => .{ .enum_type = ns: { - const extra_list = unwrapped_index.getExtra(ip); - const extra = extraDataTrail(extra_list, EnumAuto, data); - const zir_index = extra.data.zir_index.unwrap() orelse { - assert(extra.data.captures_len == 0); - break :ns .{ .generated_tag = .{ - .union_type = @enumFromInt(extra_list.view().items(.@"0")[extra.end]), - } }; - }; - if (extra.data.captures_len == std.math.maxInt(u32)) { - break :ns .{ .reified = .{ - .zir_index = zir_index, - .type_hash = extraData(extra_list, PackedU64, extra.end).get(), - } }; - } - break :ns .{ .declared = .{ - .zir_index = zir_index, - .captures = .{ .owned = .{ - .tid = unwrapped_index.tid, - .start = extra.end, - .len = extra.data.captures_len, - } }, - } }; - } }, - .type_enum_explicit, .type_enum_nonexhaustive => .{ .enum_type = ns: { - const extra_list = unwrapped_index.getExtra(ip); - const extra = extraDataTrail(extra_list, EnumExplicit, data); - const zir_index = extra.data.zir_index.unwrap() orelse { - assert(extra.data.captures_len == 0); - break :ns .{ .generated_tag = .{ - .union_type = @enumFromInt(extra_list.view().items(.@"0")[extra.end]), - } }; - }; - if (extra.data.captures_len == std.math.maxInt(u32)) { - break :ns .{ .reified = .{ - .zir_index = zir_index, - .type_hash = extraData(extra_list, PackedU64, extra.end).get(), - } }; - } - break :ns .{ .declared = .{ - .zir_index = zir_index, + .arg_ty = .none, .captures = .{ .owned = .{ .tid = unwrapped_index.tid, .start = extra.end, @@ -7263,7 +6656,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { } }, } }; } }, - .type_function => .{ .func_type = extraFuncType(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) }, .undef => .{ .undef = @enumFromInt(data) }, .opt_null => .{ .opt = .{ @@ -7390,17 +6782,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { .storage = .{ .u64 = info.value }, } }; }, - .int_lazy_align, .int_lazy_size => |tag| { - const info = extraData(unwrapped_index.getExtra(ip), IntLazy, data); - return .{ .int = .{ - .ty = info.ty, - .storage = switch (tag) { - .int_lazy_align => .{ .lazy_align = info.lazy_ty }, - .int_lazy_size => .{ .lazy_size = info.lazy_ty }, - else => unreachable, - }, - } }; - }, .float_f16 => .{ .float = .{ .ty = .f16_type, .storage = .{ .f16 = @bitCast(@as(u16, @intCast(data))) }, @@ -7488,7 +6869,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { }, .type_array_small, .type_vector, - .type_struct_packed, + // MLUGG TODO: is this still possible? also, i hate .only_possible_value, it should die in a fire. + .type_struct_packed_auto, + .type_struct_packed_explicit, => .{ .aggregate = .{ .ty = ty, .storage = .{ .elems = &.{} }, @@ -7496,11 +6879,15 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { // There is only one possible value precisely due to the // fact that this values slice is fully populated! - .type_struct, .type_struct_packed_inits => { + .type_struct, + // MLUGG TODO: is this still possible? also, i hate .only_possible_value, it should die in a fire. + .type_struct_packed_auto_defaults, + .type_struct_packed_explicit_defaults, + => { const info = loadStructType(ip, ty); return .{ .aggregate = .{ .ty = ty, - .storage = .{ .elems = @ptrCast(info.field_inits.get(ip)) }, + .storage = .{ .elems = @ptrCast(info.field_defaults.get(ip)) }, } }; }, @@ -7634,7 +7021,6 @@ fn extraFuncType(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Ke .cc = type_function.data.flags.cc.unpack(), .is_var_args = type_function.data.flags.is_var_args, .is_noinline = type_function.data.flags.is_noinline, - .is_generic = type_function.data.flags.is_generic, }; } @@ -7893,45 +7279,6 @@ fn getOrPutKeyEnsuringAdditionalCapacity( .map_index = map_index, } }; } -/// Like `getOrPutKey`, but asserts that the key already exists, and prepares to replace -/// its shard entry with a new `Index` anyway. After finalizing this, the old index remains -/// valid (in that `indexToKey` and similar queries will behave as before), but it will -/// never be returned from a lookup (`getOrPutKey` etc). -/// This is used by incremental compilation when an existing container type is outdated. In -/// this case, the type must be recreated at a new `InternPool.Index`, but the old index must -/// remain valid since now-unreferenced `AnalUnit`s may retain references to it. The old index -/// will be cleaned up when the `Zcu` undergoes garbage collection. -fn putKeyReplace( - ip: *InternPool, - io: Io, - tid: Zcu.PerThread.Id, - key: Key, -) GetOrPutKey { - const full_hash = key.hash64(ip); - const hash: u32 = @truncate(full_hash >> 32); - const shard = &ip.shards[@intCast(full_hash & (ip.shards.len - 1))]; - shard.mutate.map.mutex.lock(io, tid); - errdefer shard.mutate.map.mutex.unlock(io); - const map = shard.shared.map; - const map_mask = map.header().mask(); - var map_index = hash; - while (true) : (map_index += 1) { - map_index &= map_mask; - const entry = &map.entries[map_index]; - const index = entry.value; - assert(index != .none); // key not present - if (entry.hash == hash and ip.indexToKey(index).eql(key, ip)) { - break; // we found the entry to replace - } - } - return .{ .new = .{ - .ip = ip, - .tid = tid, - .io = io, - .shard = shard, - .map_index = map_index, - } }; -} pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: Key) Allocator.Error!Index { var gop = try ip.getOrPutKey(gpa, io, tid, key); @@ -8249,23 +7596,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: .int => |int| b: { assert(ip.isIntegerType(int.ty)); - switch (int.storage) { - .u64, .i64, .big_int => {}, - .lazy_align, .lazy_size => |lazy_ty| { - items.appendAssumeCapacity(.{ - .tag = switch (int.storage) { - else => unreachable, - .lazy_align => .int_lazy_align, - .lazy_size => .int_lazy_size, - }, - .data = try addExtra(extra, IntLazy{ - .ty = int.ty, - .lazy_ty = lazy_ty, - }), - }); - return gop.put(); - }, - } switch (int.ty) { .u8_type => switch (int.storage) { .big_int => |big_int| { @@ -8282,7 +7612,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: }); break :b; }, - .lazy_align, .lazy_size => unreachable, }, .u16_type => switch (int.storage) { .big_int => |big_int| { @@ -8299,7 +7628,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: }); break :b; }, - .lazy_align, .lazy_size => unreachable, }, .u32_type => switch (int.storage) { .big_int => |big_int| { @@ -8316,7 +7644,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: }); break :b; }, - .lazy_align, .lazy_size => unreachable, }, .i32_type => switch (int.storage) { .big_int => |big_int| { @@ -8334,7 +7661,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: }); break :b; }, - .lazy_align, .lazy_size => unreachable, }, .usize_type => switch (int.storage) { .big_int => |big_int| { @@ -8355,7 +7681,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: break :b; } }, - .lazy_align, .lazy_size => unreachable, }, .comptime_int_type => switch (int.storage) { .big_int => |big_int| { @@ -8390,7 +7715,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: break :b; } }, - .lazy_align, .lazy_size => unreachable, }, else => {}, } @@ -8427,7 +7751,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: const tag: Tag = if (big_int.positive) .int_positive else .int_negative; try addInt(ip, gpa, io, tid, int.ty, tag, big_int.limbs); }, - .lazy_align, .lazy_size => unreachable, } }, @@ -8468,7 +7791,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: assert(ip.isEnumType(enum_tag.ty)); switch (ip.indexToKey(enum_tag.ty)) { .simple_type => assert(ip.isIntegerType(ip.typeOf(enum_tag.int))), - .enum_type => assert(ip.typeOf(enum_tag.int) == ip.loadEnumType(enum_tag.ty).tag_ty), + .enum_type => assert(ip.typeOf(enum_tag.int) == ip.loadEnumType(enum_tag.ty).int_tag_type), else => unreachable, } items.appendAssumeCapacity(.{ @@ -8735,304 +8058,57 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: return gop.put(); } -pub fn getUnion( - ip: *InternPool, - gpa: Allocator, - io: Io, - tid: Zcu.PerThread.Id, - un: Key.Union, -) Allocator.Error!Index { - var gop = try ip.getOrPutKey(gpa, io, tid, .{ .un = un }); - defer gop.deinit(); - if (gop == .existing) return gop.existing; - const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa, io); - const extra = local.getMutableExtra(gpa, io); - try items.ensureUnusedCapacity(1); - - assert(un.ty != .none); - assert(un.val != .none); - items.appendAssumeCapacity(.{ - .tag = .union_value, - .data = try addExtra(extra, un), - }); - - return gop.put(); -} - -pub const UnionTypeInit = struct { - flags: packed struct { - runtime_tag: LoadedUnionType.RuntimeTag, - any_aligned_fields: bool, - layout: std.builtin.Type.ContainerLayout, - status: LoadedUnionType.Status, - requires_comptime: RequiresComptime, - assumed_runtime_bits: bool, - assumed_pointer_aligned: bool, - alignment: Alignment, - }, +pub fn getStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct { fields_len: u32, - enum_tag_ty: Index, - /// May have length 0 which leaves the values unset until later. - field_types: []const Index, - /// May have length 0 which leaves the values unset until later. - /// The logic for `any_aligned_fields` is asserted to have been done before - /// calling this function. - field_aligns: []const Alignment, - key: union(enum) { - declared: struct { - zir_index: TrackedInst.Index, - captures: []const CaptureValue, - }, - declared_owned_captures: struct { - zir_index: TrackedInst.Index, - captures: CaptureValue.Slice, - }, - reified: struct { - zir_index: TrackedInst.Index, - type_hash: u64, - }, - }, -}; - -pub fn getUnionType( - ip: *InternPool, - gpa: Allocator, - io: Io, - tid: Zcu.PerThread.Id, - ini: UnionTypeInit, - /// If it is known that there is an existing type with this key which is outdated, - /// this is passed as `true`, and the type is replaced with one at a fresh index. - replace_existing: bool, -) Allocator.Error!WipNamespaceType.Result { - const key: Key = .{ .union_type = switch (ini.key) { - .declared => |d| .{ .declared = .{ - .zir_index = d.zir_index, - .captures = .{ .external = d.captures }, - } }, - .declared_owned_captures => |d| .{ .declared = .{ - .zir_index = d.zir_index, - .captures = .{ .owned = d.captures }, - } }, - .reified => |r| .{ .reified = .{ - .zir_index = r.zir_index, - .type_hash = r.type_hash, - } }, - } }; - var gop = if (replace_existing) - ip.putKeyReplace(io, tid, key) - else - try ip.getOrPutKey(gpa, io, tid, key); - defer gop.deinit(); - if (gop == .existing) return .{ .existing = gop.existing }; - - const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa, io); - try items.ensureUnusedCapacity(1); - const extra = local.getMutableExtra(gpa, io); - - const align_elements_len = if (ini.flags.any_aligned_fields) (ini.fields_len + 3) / 4 else 0; - const align_element: u32 = @bitCast([1]u8{@intFromEnum(Alignment.none)} ** 4); - try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeUnion).@"struct".fields.len + - // TODO: fmt bug - // zig fmt: off - switch (ini.key) { - inline .declared, .declared_owned_captures => |d| @intFromBool(d.captures.len != 0) + d.captures.len, - .reified => 2, // type_hash: PackedU64 - } + - // zig fmt: on - ini.fields_len + // field types - align_elements_len); - - const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnion{ - .flags = .{ - .any_captures = switch (ini.key) { - inline .declared, .declared_owned_captures => |d| d.captures.len != 0, - .reified => false, - }, - .runtime_tag = ini.flags.runtime_tag, - .any_aligned_fields = ini.flags.any_aligned_fields, - .layout = ini.flags.layout, - .status = ini.flags.status, - .requires_comptime = ini.flags.requires_comptime, - .assumed_runtime_bits = ini.flags.assumed_runtime_bits, - .assumed_pointer_aligned = ini.flags.assumed_pointer_aligned, - .alignment = ini.flags.alignment, - .is_reified = switch (ini.key) { - .declared, .declared_owned_captures => false, - .reified => true, - }, - }, - .fields_len = ini.fields_len, - .size = std.math.maxInt(u32), - .padding = std.math.maxInt(u32), - .name = undefined, // set by `finish` - .name_nav = undefined, // set by `finish` - .namespace = undefined, // set by `finish` - .tag_ty = ini.enum_tag_ty, - .zir_index = switch (ini.key) { - inline else => |x| x.zir_index, - }, - }); - - items.appendAssumeCapacity(.{ - .tag = .type_union, - .data = extra_index, - }); - - switch (ini.key) { - .declared => |d| if (d.captures.len != 0) { - extra.appendAssumeCapacity(.{@intCast(d.captures.len)}); - extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}); - }, - .declared_owned_captures => |d| if (d.captures.len != 0) { - extra.appendAssumeCapacity(.{@intCast(d.captures.len)}); - extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}); - }, - .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)), - } - - // field types - if (ini.field_types.len > 0) { - assert(ini.field_types.len == ini.fields_len); - extra.appendSliceAssumeCapacity(.{@ptrCast(ini.field_types)}); - } else { - extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); - } - - // field alignments - if (ini.flags.any_aligned_fields) { - extra.appendNTimesAssumeCapacity(.{align_element}, align_elements_len); - if (ini.field_aligns.len > 0) { - assert(ini.field_aligns.len == ini.fields_len); - @memcpy((Alignment.Slice{ - .tid = tid, - .start = @intCast(extra.mutate.len - align_elements_len), - .len = @intCast(ini.field_aligns.len), - }).get(ip), ini.field_aligns); - } - } else { - assert(ini.field_aligns.len == 0); - } - - return .{ .wip = .{ - .tid = tid, - .index = gop.put(), - .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?, - .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name_nav").?, - .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?, - } }; -} - -pub const WipNamespaceType = struct { - tid: Zcu.PerThread.Id, - index: Index, - type_name_extra_index: u32, - namespace_extra_index: u32, - name_nav_extra_index: u32, - - pub fn setName( - wip: WipNamespaceType, - ip: *InternPool, - type_name: NullTerminatedString, - /// This should be the `Nav` we are named after if we use the `.parent` name strategy; `.none` otherwise. - /// This is also `.none` if we use `.parent` because we are the root struct type for a file. - name_nav: Nav.Index.Optional, - ) void { - const extra = ip.getLocalShared(wip.tid).extra.acquire(); - const extra_items = extra.view().items(.@"0"); - extra_items[wip.type_name_extra_index] = @intFromEnum(type_name); - extra_items[wip.name_nav_extra_index] = @intFromEnum(name_nav); - } - - pub fn finish( - wip: WipNamespaceType, - ip: *InternPool, - namespace: NamespaceIndex, - ) Index { - const extra = ip.getLocalShared(wip.tid).extra.acquire(); - const extra_items = extra.view().items(.@"0"); - - extra_items[wip.namespace_extra_index] = @intFromEnum(namespace); - - return wip.index; - } - - pub fn cancel(wip: WipNamespaceType, ip: *InternPool, tid: Zcu.PerThread.Id) void { - ip.remove(tid, wip.index); - } - - pub const Result = union(enum) { - wip: WipNamespaceType, - existing: Index, - }; -}; - -pub const StructTypeInit = struct { layout: std.builtin.Type.ContainerLayout, - fields_len: u32, - known_non_opv: bool, - requires_comptime: RequiresComptime, + /// The following only applies if `layout == .@"packed"`; this field is ignored otherwise. + /// + /// The explicitly specified backing integer type. `.none` means the backing integer is inferred + /// by the compiler. Asserts that this is an integer type. + explicit_packed_backing_type: Index, any_comptime_fields: bool, - any_default_inits: bool, - inits_resolved: bool, - any_aligned_fields: bool, + any_field_defaults: bool, + any_field_aligns: bool, key: union(enum) { declared: struct { zir_index: TrackedInst.Index, captures: []const CaptureValue, }, - declared_owned_captures: struct { - zir_index: TrackedInst.Index, - captures: CaptureValue.Slice, - }, reified: struct { zir_index: TrackedInst.Index, type_hash: u64, }, }, -}; - -pub fn getStructType( - ip: *InternPool, - gpa: Allocator, - io: Io, - tid: Zcu.PerThread.Id, - ini: StructTypeInit, - /// If it is known that there is an existing type with this key which is outdated, - /// this is passed as `true`, and the type is replaced with one at a fresh index. - replace_existing: bool, -) Allocator.Error!WipNamespaceType.Result { +}) Allocator.Error!WipContainerType.Result { const key: Key = .{ .struct_type = switch (ini.key) { .declared => |d| .{ .declared = .{ .zir_index = d.zir_index, + .arg_ty = switch (ini.layout) { + .auto, .@"extern" => .none, + .@"packed" => ini.explicit_packed_backing_type, + }, .captures = .{ .external = d.captures }, } }, - .declared_owned_captures => |d| .{ .declared = .{ - .zir_index = d.zir_index, - .captures = .{ .owned = d.captures }, - } }, .reified => |r| .{ .reified = .{ .zir_index = r.zir_index, .type_hash = r.type_hash, } }, } }; - var gop = if (replace_existing) - ip.putKeyReplace(io, tid, key) - else - try ip.getOrPutKey(gpa, io, tid, key); + var gop = try ip.getOrPutKey(gpa, io, tid, key); defer gop.deinit(); if (gop == .existing) return .{ .existing = gop.existing }; const local = ip.getLocal(tid); const items = local.getMutableItems(gpa, io); const extra = local.getMutableExtra(gpa, io); + try items.ensureUnusedCapacity(1); - const names_map = try ip.addMap(gpa, io, tid, ini.fields_len); + const field_name_map = try ip.addMap(gpa, io, tid, ini.fields_len); errdefer local.mutate.maps.len -= 1; - const zir_index = switch (ini.key) { - inline else => |x| x.zir_index, + const zir_index, const type_hash_captures_extra_len = switch (ini.key) { + .declared => |d| .{ d.zir_index, d.captures.len + @intFromBool(ini.layout != .@"packed") }, + .reified => |r| .{ r.zir_index, 2 }, }; const is_extern = switch (ini.layout) { @@ -9040,160 +8116,579 @@ pub fn getStructType( .@"extern" => true, .@"packed" => { try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeStructPacked).@"struct".fields.len + - // TODO: fmt bug - // zig fmt: off - switch (ini.key) { - inline .declared, .declared_owned_captures => |d| @intFromBool(d.captures.len != 0) + d.captures.len, - .reified => 2, // type_hash: PackedU64 - } + - // zig fmt: on - ini.fields_len + // types - ini.fields_len + // names - ini.fields_len); // inits + type_hash_captures_extra_len + + ini.fields_len + // field_name + ini.fields_len + // field_type + (if (ini.any_field_defaults) ini.fields_len else 0)); // field_default + const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStructPacked{ + .zir_index = zir_index, + .captures_len = switch (ini.key) { + .declared => |d| @enumFromInt(d.captures.len), + .reified => .reified, + }, .name = undefined, // set by `finish` .name_nav = undefined, // set by `finish` - .zir_index = zir_index, - .fields_len = ini.fields_len, .namespace = undefined, // set by `finish` - .backing_int_ty = .none, - .names_map = names_map, - .flags = .{ - .any_captures = switch (ini.key) { - inline .declared, .declared_owned_captures => |d| d.captures.len != 0, - .reified => false, - }, - .field_inits_wip = false, - .inits_resolved = ini.inits_resolved, - .is_reified = switch (ini.key) { - .declared, .declared_owned_captures => false, - .reified => true, - }, - }, - }); - try items.append(.{ - .tag = if (ini.any_default_inits) .type_struct_packed_inits else .type_struct_packed, - .data = extra_index, + .backing_int_type = ini.explicit_packed_backing_type, + .fields_len = ini.fields_len, + .field_name_map = field_name_map, }); switch (ini.key) { - .declared => |d| if (d.captures.len != 0) { - extra.appendAssumeCapacity(.{@intCast(d.captures.len)}); - extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}); - }, - .declared_owned_captures => |d| if (d.captures.len != 0) { - extra.appendAssumeCapacity(.{@intCast(d.captures.len)}); - extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}); - }, - .reified => |r| { - _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)); - }, + .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}), + .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)), } - extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); - extra.appendNTimesAssumeCapacity(.{@intFromEnum(OptionalNullTerminatedString.none)}, ini.fields_len); - if (ini.any_default_inits) { - extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); + const field_names_start = extra.mutate.len; + extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name + extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type + if (ini.any_field_defaults) { + extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_default } + items.appendAssumeCapacity(.{ + .tag = switch (ini.explicit_packed_backing_type) { + .none => if (ini.any_field_defaults) .type_struct_packed_auto_defaults else .type_struct_packed_auto, + else => if (ini.any_field_defaults) .type_struct_packed_explicit_defaults else .type_struct_packed_explicit, + }, + .data = extra_index, + }); return .{ .wip = .{ - .tid = tid, .index = gop.put(), - .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?, - .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?, - .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?, + .tid = tid, + .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?, + .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?, + .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?, + .tag_type_index = null, + .fields_len = ini.fields_len, + .field_name_map = field_name_map, + .field_names_start = field_names_start, + .field_comptime_bits_start = null, } }; }, }; - const align_elements_len = if (ini.any_aligned_fields) (ini.fields_len + 3) / 4 else 0; - const align_element: u32 = @bitCast([1]u8{@intFromEnum(Alignment.none)} ** 4); - const comptime_elements_len = if (ini.any_comptime_fields) (ini.fields_len + 31) / 32 else 0; - try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeStruct).@"struct".fields.len + - // TODO: fmt bug - // zig fmt: off - switch (ini.key) { - inline .declared, .declared_owned_captures => |d| @intFromBool(d.captures.len != 0) + d.captures.len, - .reified => 2, // type_hash: PackedU64 - } + - // zig fmt: on - (ini.fields_len * 5) + // types, names, inits, runtime order, offsets - align_elements_len + comptime_elements_len + - 1); // names_map + type_hash_captures_extra_len + + ini.fields_len + // field_name + ini.fields_len + // field_type + (if (ini.any_field_defaults) ini.fields_len else 0) + // field_default + (if (ini.any_field_aligns) (ini.fields_len + 3) / 4 else 0) + // field_align + (if (ini.any_comptime_fields) (ini.fields_len + 31) / 32 else 0) + // field_is_comptime_bits + (if (!is_extern) ini.fields_len else 0) + // field_runtime_order + ini.fields_len); // field_offset + const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{ + .zir_index = zir_index, .name = undefined, // set by `finish` .name_nav = undefined, // set by `finish` - .zir_index = zir_index, .namespace = undefined, // set by `finish` .fields_len = ini.fields_len, - .size = std.math.maxInt(u32), + .field_name_map = field_name_map, + .size = 0, .flags = .{ .any_captures = switch (ini.key) { - inline .declared, .declared_owned_captures => |d| d.captures.len != 0, - .reified => false, + .declared => |d| if (d.captures.len != 0) .true else .false, + .reified => .reified, }, - .is_extern = is_extern, - .known_non_opv = ini.known_non_opv, - .requires_comptime = ini.requires_comptime, - .assumed_runtime_bits = false, - .assumed_pointer_aligned = false, + .layout = if (is_extern) .@"extern" else .auto, .any_comptime_fields = ini.any_comptime_fields, - .any_default_inits = ini.any_default_inits, - .any_aligned_fields = ini.any_aligned_fields, + .any_field_defaults = ini.any_field_defaults, + .any_field_aligns = ini.any_field_aligns, + .has_one_possible_value = false, + .has_no_possible_value = false, + .comptime_only = false, .alignment = .none, - .alignment_wip = false, - .field_types_wip = false, - .layout_wip = false, - .layout_resolved = false, - .field_inits_wip = false, - .inits_resolved = ini.inits_resolved, - .fully_resolved = false, - .is_reified = switch (ini.key) { - .declared, .declared_owned_captures => false, - .reified => true, - }, }, }); - try items.append(.{ + switch (ini.key) { + .declared => |d| if (d.captures.len != 0) { + extra.appendAssumeCapacity(.{@intCast(d.captures.len)}); + extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}); + }, + .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)), + } + const field_names_start = extra.mutate.len; + extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name + extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type + if (ini.any_field_defaults) { + extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_default + } + if (ini.any_field_aligns) { + extra.appendNTimesAssumeCapacity(.{0}, (ini.fields_len + 3) / 4); // field_align + } + const field_comptime_bits_start: ?u32 = if (ini.any_comptime_fields) start: { + const start = extra.mutate.len; + extra.appendNTimesAssumeCapacity(.{0}, (ini.fields_len + 31) / 32); // field_is_comptime_bits + break :start start; + } else null; + if (!is_extern) { + extra.appendNTimesAssumeCapacity(.{@intFromEnum(LoadedStructType.RuntimeOrder.unresolved)}, ini.fields_len); // field_runtime_order + } + extra.appendNTimesAssumeCapacity(.{0}, ini.fields_len); // field_offset + items.appendAssumeCapacity(.{ .tag = .type_struct, .data = extra_index, }); + return .{ .wip = .{ + .index = gop.put(), + .tid = tid, + .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?, + .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?, + .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?, + .tag_type_index = null, + .fields_len = ini.fields_len, + .field_name_map = field_name_map, + .field_names_start = field_names_start, + .field_comptime_bits_start = field_comptime_bits_start, + } }; +} + +pub fn getUnionType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct { + fields_len: u32, + layout: std.builtin.Type.ContainerLayout, + /// The explicitly specified backing integer type for a `packed union`. + /// `.none` means the backing integer is inferred by the compiler. If set, + /// must be an integer type. If the union is not packed, must be `.none`. + explicit_packed_backing_type: Index, + runtime_tag: LoadedUnionType.RuntimeTag, + /// `true` for `union(T)`, but `false` for anything else, including `union(enum(T))`. + have_explicit_enum_tag: bool, + any_field_aligns: bool, + key: union(enum) { + declared: struct { + zir_index: TrackedInst.Index, + captures: []const CaptureValue, + /// This is the `T` in one of the following: + /// * `union(T)` (enum tag type) + /// * `union(enum(T))` (int tag type) + /// * `packed union(T)` (int backing type) + /// Or `.none` otherwise. + arg_ty: InternPool.Index, + }, + reified: struct { + zir_index: TrackedInst.Index, + type_hash: u64, + }, + }, +}) Allocator.Error!WipContainerType.Result { + if (ini.explicit_packed_backing_type != .none) { + assert(ip.zigTypeTag(ini.explicit_packed_backing_type) == .int); + if (ini.key == .declared) assert(ini.key.declared.arg_ty == ini.explicit_packed_backing_type); + } + const key: Key = .{ .union_type = switch (ini.key) { + .declared => |d| .{ .declared = .{ + .zir_index = d.zir_index, + .arg_ty = d.arg_ty, + .captures = .{ .external = d.captures }, + } }, + .reified => |r| .{ .reified = .{ + .zir_index = r.zir_index, + .type_hash = r.type_hash, + } }, + } }; + var gop = try ip.getOrPutKey(gpa, io, tid, key); + defer gop.deinit(); + if (gop == .existing) return .{ .existing = gop.existing }; + + const local = ip.getLocal(tid); + const items = local.getMutableItems(gpa, io); + const extra = local.getMutableExtra(gpa, io); + try items.ensureUnusedCapacity(1); + + const zir_index, const type_hash_captures_extra_len = switch (ini.key) { + .declared => |d| .{ d.zir_index, d.captures.len + @intFromBool(ini.layout != .@"packed") }, + .reified => |r| .{ r.zir_index, 2 }, + }; + + const is_extern = switch (ini.layout) { + .auto => false, + .@"extern" => true, + .@"packed" => { + try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeUnionPacked).@"struct".fields.len + + type_hash_captures_extra_len + + ini.fields_len); // field_type + + const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnionPacked{ + .zir_index = zir_index, + .captures_len = switch (ini.key) { + .declared => |d| @enumFromInt(d.captures.len), + .reified => .reified, + }, + .name = undefined, // set by `finish` + .name_nav = undefined, // set by `finish` + .namespace = undefined, // set by `finish` + .backing_int_type = ini.explicit_packed_backing_type, + .enum_tag_type = .none, // set by `setTagType` + .fields_len = ini.fields_len, + }); + switch (ini.key) { + .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}), + .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)), + } + extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type + items.appendAssumeCapacity(.{ + .tag = switch (ini.explicit_packed_backing_type) { + .none => .type_union_packed_auto, + else => .type_union_packed_explicit, + }, + .data = extra_index, + }); + return .{ + .wip = .{ + .index = gop.put(), + .tid = tid, + .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name").?, + .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name_nav").?, + .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "namespace").?, + .tag_type_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "enum_tag_type").?, + .fields_len = 0, // the fields come from the enum, so nothing to set + .field_name_map = undefined, + .field_names_start = undefined, + .field_comptime_bits_start = undefined, + }, + }; + }, + }; + + try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeUnion).@"struct".fields.len + + type_hash_captures_extra_len + + ini.fields_len + // field_type + (if (ini.any_field_aligns) (ini.fields_len + 3) / 4 else 0)); // field_align + + const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnion{ + .zir_index = zir_index, + .name = undefined, // set by `finish` + .name_nav = undefined, // set by `finish` + .namespace = undefined, // set by `finish` + .enum_tag_type = .none, // set by `setTagType` + .fields_len = ini.fields_len, + .size = 0, + .padding = 0, + .flags = .{ + .any_captures = switch (ini.key) { + .declared => |d| if (d.captures.len != 0) .true else .false, + .reified => .reified, + }, + .explicit_tag_type = ini.have_explicit_enum_tag, + .layout = if (is_extern) .@"extern" else .auto, + .any_field_aligns = ini.any_field_aligns, + .runtime_tag = ini.runtime_tag, + .has_one_possible_value = false, + .has_no_possible_value = false, + .comptime_only = false, + .alignment = .none, + }, + }); switch (ini.key) { .declared => |d| if (d.captures.len != 0) { extra.appendAssumeCapacity(.{@intCast(d.captures.len)}); extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}); }, - .declared_owned_captures => |d| if (d.captures.len != 0) { - extra.appendAssumeCapacity(.{@intCast(d.captures.len)}); - extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}); + .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)), + } + extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type + if (ini.any_field_aligns) { + extra.appendNTimesAssumeCapacity(.{0}, (ini.fields_len + 3) / 4); // field_align + } + items.appendAssumeCapacity(.{ + .tag = .type_union, + .data = extra_index, + }); + return .{ + .wip = .{ + .index = gop.put(), + .tid = tid, + .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?, + .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name_nav").?, + .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?, + .tag_type_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "enum_tag_type").?, + .fields_len = 0, // the fields come from the enum, so nothing to set + .field_name_map = undefined, + .field_names_start = undefined, + .field_comptime_bits_start = undefined, + }, + }; +} + +pub fn getEnumType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct { + fields_len: u32, + /// For `enum(T)` or `union(enum(T))`, this is `T`. Asserts `T` is an integer type. + /// Otherwise, `.none`. + explicit_int_tag_type: Index, + nonexhaustive: bool, + key: union(enum) { + declared: struct { + zir_index: TrackedInst.Index, + captures: []const CaptureValue, + }, + reified: struct { + zir_index: TrackedInst.Index, + type_hash: u64, + }, + generated_union_tag: Index, + }, +}) Allocator.Error!WipContainerType.Result { + const key: Key = .{ .enum_type = switch (ini.key) { + .declared => |d| .{ .declared = .{ + .zir_index = d.zir_index, + .arg_ty = ini.explicit_int_tag_type, + .captures = .{ .external = d.captures }, + } }, + .reified => |r| .{ .reified = .{ + .zir_index = r.zir_index, + .type_hash = r.type_hash, + } }, + .generated_union_tag => |u| .{ .generated_union_tag = u }, + } }; + var gop = try ip.getOrPutKey(gpa, io, tid, key); + defer gop.deinit(); + if (gop == .existing) return .{ .existing = gop.existing }; + + const local = ip.getLocal(tid); + const items = local.getMutableItems(gpa, io); + const extra = local.getMutableExtra(gpa, io); + try items.ensureUnusedCapacity(1); + + const tag: Tag, const have_values: bool = if (ini.nonexhaustive) + .{ .type_enum_nonexhaustive, true } + else if (ini.explicit_int_tag_type != .none) + .{ .type_enum_explicit, true } + else + .{ .type_enum_auto, false }; + + const field_name_map = try ip.addMap(gpa, io, tid, ini.fields_len); + errdefer local.mutate.maps.len -= 1; + + const field_value_map = if (have_values) try ip.addMap(gpa, io, tid, ini.fields_len) else undefined; + errdefer local.mutate.maps.len -= @intFromBool(have_values); + + try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeEnum).@"struct".fields.len + + switch (ini.key) { + .declared => |d| 1 + d.captures.len, // `zir_index` and `capture` + .reified => 3, // `zir_index` and `type_hash` + .generated_union_tag => 1, // owner_union + } + + @intFromBool(have_values) + // field_value_map + ini.fields_len + // field_name + (if (have_values) ini.fields_len else 0)); // field_value + + const extra_index = addExtraAssumeCapacity(extra, Tag.TypeEnum{ + .captures_len = switch (ini.key) { + .declared => |d| @enumFromInt(d.captures.len), + .reified => .reified, + .generated_union_tag => .generated_union_tag, + }, + .name = undefined, // set by `finish` + .name_nav = undefined, // set by `finish` + .namespace = undefined, // set by `finish` + .int_tag_type = ini.explicit_int_tag_type, + .fields_len = ini.fields_len, + .field_name_map = field_name_map, + }); + switch (ini.key) { + .declared => |d| { + extra.appendAssumeCapacity(.{@intFromEnum(d.zir_index)}); // zir_index + extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}); // capture }, .reified => |r| { - _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)); + extra.appendAssumeCapacity(.{@intFromEnum(r.zir_index)}); // zir_index + _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)); // type_hash + }, + .generated_union_tag => |owner_union| { + extra.appendAssumeCapacity(.{@intFromEnum(owner_union)}); // owner_union }, } - extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); - extra.appendAssumeCapacity(.{@intFromEnum(names_map)}); - extra.appendNTimesAssumeCapacity(.{@intFromEnum(OptionalNullTerminatedString.none)}, ini.fields_len); - if (ini.any_default_inits) { - extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); - } - if (ini.any_aligned_fields) { - extra.appendNTimesAssumeCapacity(.{align_element}, align_elements_len); - } - if (ini.any_comptime_fields) { - extra.appendNTimesAssumeCapacity(.{0}, comptime_elements_len); - } - if (ini.layout == .auto) { - extra.appendNTimesAssumeCapacity(.{@intFromEnum(LoadedStructType.RuntimeOrder.unresolved)}, ini.fields_len); - } - extra.appendNTimesAssumeCapacity(.{std.math.maxInt(u32)}, ini.fields_len); + if (have_values) extra.appendAssumeCapacity(.{@intFromEnum(field_value_map)}); + const field_names_start = extra.mutate.len; + extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name + if (have_values) extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_value + items.appendAssumeCapacity(.{ + .tag = tag, + .data = extra_index, + }); return .{ .wip = .{ + .index = gop.put(), .tid = tid, + .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name").?, + .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name_nav").?, + .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "namespace").?, + .tag_type_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "int_tag_type").?, + .fields_len = ini.fields_len, + .field_name_map = field_name_map, + .field_names_start = field_names_start, + .field_comptime_bits_start = null, + } }; +} + +pub fn getOpaqueType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct { + zir_index: TrackedInst.Index, + captures: []const CaptureValue, +}) Allocator.Error!WipContainerType.Result { + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .opaque_type = .{ .declared = .{ + .zir_index = ini.zir_index, + .captures = .{ .external = ini.captures }, + .arg_ty = .none, + } } }); + defer gop.deinit(); + if (gop == .existing) return .{ .existing = gop.existing }; + + const local = ip.getLocal(tid); + const items = local.getMutableItems(gpa, io); + const extra = local.getMutableExtra(gpa, io); + try items.ensureUnusedCapacity(1); + + try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + ini.captures.len); + const extra_index = addExtraAssumeCapacity(extra, Tag.TypeOpaque{ + .zir_index = ini.zir_index, + .captures_len = @intCast(ini.captures.len), + .name = undefined, // set by `finish` + .name_nav = undefined, // set by `finish` + .namespace = undefined, // set by `finish` + }); + extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)}); + items.appendAssumeCapacity(.{ + .tag = .type_opaque, + .data = extra_index, + }); + return .{ .wip = .{ .index = gop.put(), - .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?, - .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?, - .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?, + .tid = tid, + .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name").?, + .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name_nav").?, + .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "namespace").?, + .tag_type_index = null, + .fields_len = 0, + .field_name_map = undefined, + .field_names_start = undefined, + .field_comptime_bits_start = undefined, } }; } +pub const WipContainerType = struct { + index: Index, + tid: Zcu.PerThread.Id, + type_name_index: u32, + name_nav_index: u32, + namespace_index: u32, + + tag_type_index: ?u32, + + fields_len: u32, + field_name_map: MapIndex, + field_names_start: u32, + field_comptime_bits_start: ?u32, + + pub fn setName( + wip: WipContainerType, + ip: *InternPool, + type_name: NullTerminatedString, + /// This should be the `Nav` we are named after if we use the `.parent` name strategy; `.none` otherwise. + /// This is also `.none` if we use `.parent` because we are the root struct type for a file. + name_nav: Nav.Index.Optional, + ) void { + const extra = ip.getLocalShared(wip.tid).extra.acquire(); + const extra_items = extra.view().items(.@"0"); + extra_items[wip.type_name_index] = @intFromEnum(type_name); + extra_items[wip.name_nav_index] = @intFromEnum(name_nav); + } + + pub fn setTagType( + wip: WipContainerType, + ip: *InternPool, + tag_ty: Index, + ) void { + const extra = ip.getLocalShared(wip.tid).extra.acquire(); + const extra_items = extra.view().items(.@"0"); + const i = wip.tag_type_index.?; + const old_val: InternPool.Index = @enumFromInt(extra_items[i]); + assert(old_val == .none); + assert(tag_ty != .none); + extra_items[i] = @intFromEnum(tag_ty); + } + + /// Returns the already-existing field with the same name, if any. + pub fn nextField( + wip: WipContainerType, + ip: *InternPool, + name: NullTerminatedString, + marked_comptime: bool, + ) ?u32 { + assert(wip.fields_len > 0); + const extra = ip.getLocalShared(wip.tid).extra.acquire(); + const extra_items = extra.view().items(.@"0"); + const map = wip.field_name_map.get(ip); + const field_idx = map.count(); + assert(field_idx < wip.fields_len); + const names: []NullTerminatedString = @ptrCast(extra_items[wip.field_names_start..][0..wip.fields_len]); + const adapter: NullTerminatedString.Adapter = .{ .strings = names[0..field_idx] }; + const gop = map.getOrPutAssumeCapacityAdapted(name, adapter); + if (gop.found_existing) return @intCast(gop.index); + names[field_idx] = name; + if (wip.field_comptime_bits_start) |start_idx| { + if (marked_comptime) { + extra_items[start_idx + field_idx / 32] |= @as(u32, 1) << @intCast(field_idx % 32); + } + } else { + assert(!marked_comptime); + } + return null; + } + + pub fn finish( + wip: WipContainerType, + ip: *InternPool, + namespace: NamespaceIndex, + ) Index { + const extra = ip.getLocalShared(wip.tid).extra.acquire(); + const extra_items = extra.view().items(.@"0"); + + extra_items[wip.namespace_index] = @intFromEnum(namespace); + + if (wip.fields_len > 0) { + assert(wip.field_name_map.get(ip).count() == wip.fields_len); + } + if (wip.tag_type_index) |i| { + const tag_ty: Index = @enumFromInt(extra_items[i]); + assert(tag_ty != .none); + } + + return wip.index; + } + + pub fn cancel(wip: WipContainerType, ip: *InternPool, tid: Zcu.PerThread.Id) void { + ip.remove(tid, wip.index); + } + + pub const Result = union(enum) { + wip: WipContainerType, + existing: Index, + }; +}; + +pub fn getUnion( + ip: *InternPool, + gpa: Allocator, + io: Io, + tid: Zcu.PerThread.Id, + un: Key.Union, +) Allocator.Error!Index { + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .un = un }); + defer gop.deinit(); + if (gop == .existing) return gop.existing; + const local = ip.getLocal(tid); + const items = local.getMutableItems(gpa, io); + const extra = local.getMutableExtra(gpa, io); + try items.ensureUnusedCapacity(1); + + assert(un.ty != .none); + assert(un.val != .none); + items.appendAssumeCapacity(.{ + .tag = .union_value, + .data = try addExtra(extra, un), + }); + + return gop.put(); +} + pub const TupleTypeInit = struct { types: []const Index, /// These elements may be `none`, indicating runtime-known. @@ -9252,10 +8747,7 @@ pub const GetFuncTypeKey = struct { /// `null` means generic. cc: ?std.builtin.CallingConvention = .auto, is_var_args: bool = false, - is_generic: bool = false, is_noinline: bool = false, - section_is_generic: bool = false, - addrspace_is_generic: bool = false, }; pub fn getFuncType( @@ -9293,7 +8785,6 @@ pub fn getFuncType( .is_var_args = key.is_var_args, .has_comptime_bits = key.comptime_bits != 0, .has_noalias_bits = key.noalias_bits != 0, - .is_generic = key.is_generic, .is_noinline = key.is_noinline, }, }); @@ -9480,7 +8971,6 @@ pub const GetFuncDeclIesKey = struct { /// null means generic. cc: ?std.builtin.CallingConvention, is_var_args: bool, - is_generic: bool, is_noinline: bool, zir_body_inst: TrackedInst.Index, lbrace_line: u32, @@ -9564,7 +9054,6 @@ pub fn getFuncDeclIes( .is_var_args = key.is_var_args, .has_comptime_bits = key.comptime_bits != 0, .has_noalias_bits = key.noalias_bits != 0, - .is_generic = key.is_generic, .is_noinline = key.is_noinline, }, }); @@ -9864,7 +9353,6 @@ fn getFuncInstanceIes( .is_var_args = false, .has_comptime_bits = false, .has_noalias_bits = arg.noalias_bits != 0, - .is_generic = false, .is_noinline = arg.is_noinline, }, }); @@ -9972,444 +9460,6 @@ fn finishFuncInstance( ] = @intFromEnum(nav_index); } -pub const EnumTypeInit = struct { - has_values: bool, - tag_mode: LoadedEnumType.TagMode, - fields_len: u32, - key: union(enum) { - declared: struct { - zir_index: TrackedInst.Index, - captures: []const CaptureValue, - }, - declared_owned_captures: struct { - zir_index: TrackedInst.Index, - captures: CaptureValue.Slice, - }, - reified: struct { - zir_index: TrackedInst.Index, - type_hash: u64, - }, - }, -}; - -pub const WipEnumType = struct { - tid: Zcu.PerThread.Id, - index: Index, - tag_ty_index: u32, - type_name_extra_index: u32, - namespace_extra_index: u32, - name_nav_extra_index: u32, - names_map: MapIndex, - names_start: u32, - values_map: OptionalMapIndex, - values_start: u32, - - pub fn setName( - wip: WipEnumType, - ip: *InternPool, - type_name: NullTerminatedString, - /// This should be the `Nav` we are named after if we use the `.parent` name strategy; `.none` otherwise. - name_nav: Nav.Index.Optional, - ) void { - const extra = ip.getLocalShared(wip.tid).extra.acquire(); - const extra_items = extra.view().items(.@"0"); - extra_items[wip.type_name_extra_index] = @intFromEnum(type_name); - extra_items[wip.name_nav_extra_index] = @intFromEnum(name_nav); - } - - pub fn prepare( - wip: WipEnumType, - ip: *InternPool, - namespace: NamespaceIndex, - ) void { - const extra = ip.getLocalShared(wip.tid).extra.acquire(); - const extra_items = extra.view().items(.@"0"); - - extra_items[wip.namespace_extra_index] = @intFromEnum(namespace); - } - - pub fn setTagTy(wip: WipEnumType, ip: *InternPool, tag_ty: Index) void { - assert(ip.isIntegerType(tag_ty)); - const extra = ip.getLocalShared(wip.tid).extra.acquire(); - extra.view().items(.@"0")[wip.tag_ty_index] = @intFromEnum(tag_ty); - } - - pub const FieldConflict = struct { - kind: enum { name, value }, - prev_field_idx: u32, - }; - - /// Returns the already-existing field with the same name or value, if any. - /// If the enum is automatially numbered, `value` must be `.none`. - /// Otherwise, the type of `value` must be the integer tag type of the enum. - pub fn nextField(wip: WipEnumType, ip: *InternPool, name: NullTerminatedString, value: Index) ?FieldConflict { - const unwrapped_index = wip.index.unwrap(ip); - const extra_list = ip.getLocalShared(unwrapped_index.tid).extra.acquire(); - const extra_items = extra_list.view().items(.@"0"); - if (ip.addFieldName(extra_list, wip.names_map, wip.names_start, name)) |conflict| { - return .{ .kind = .name, .prev_field_idx = conflict }; - } - if (value == .none) { - assert(wip.values_map == .none); - return null; - } - assert(ip.typeOf(value) == @as(Index, @enumFromInt(extra_items[wip.tag_ty_index]))); - const map = wip.values_map.unwrap().?.get(ip); - const field_index = map.count(); - const indexes = extra_items[wip.values_start..][0..field_index]; - const adapter: Index.Adapter = .{ .indexes = @ptrCast(indexes) }; - const gop = map.getOrPutAssumeCapacityAdapted(value, adapter); - if (gop.found_existing) { - return .{ .kind = .value, .prev_field_idx = @intCast(gop.index) }; - } - extra_items[wip.values_start + field_index] = @intFromEnum(value); - return null; - } - - pub fn cancel(wip: WipEnumType, ip: *InternPool, tid: Zcu.PerThread.Id) void { - ip.remove(tid, wip.index); - } - - pub const Result = union(enum) { - wip: WipEnumType, - existing: Index, - }; -}; - -pub fn getEnumType( - ip: *InternPool, - gpa: Allocator, - io: Io, - tid: Zcu.PerThread.Id, - ini: EnumTypeInit, - /// If it is known that there is an existing type with this key which is outdated, - /// this is passed as `true`, and the type is replaced with one at a fresh index. - replace_existing: bool, -) Allocator.Error!WipEnumType.Result { - const key: Key = .{ .enum_type = switch (ini.key) { - .declared => |d| .{ .declared = .{ - .zir_index = d.zir_index, - .captures = .{ .external = d.captures }, - } }, - .declared_owned_captures => |d| .{ .declared = .{ - .zir_index = d.zir_index, - .captures = .{ .owned = d.captures }, - } }, - .reified => |r| .{ .reified = .{ - .zir_index = r.zir_index, - .type_hash = r.type_hash, - } }, - } }; - var gop = if (replace_existing) - ip.putKeyReplace(io, tid, key) - else - try ip.getOrPutKey(gpa, io, tid, key); - defer gop.deinit(); - if (gop == .existing) return .{ .existing = gop.existing }; - - const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa, io); - try items.ensureUnusedCapacity(1); - const extra = local.getMutableExtra(gpa, io); - - const names_map = try ip.addMap(gpa, io, tid, ini.fields_len); - errdefer local.mutate.maps.len -= 1; - - switch (ini.tag_mode) { - .auto => { - assert(!ini.has_values); - try extra.ensureUnusedCapacity(@typeInfo(EnumAuto).@"struct".fields.len + - // TODO: fmt bug - // zig fmt: off - switch (ini.key) { - inline .declared, .declared_owned_captures => |d| d.captures.len, - .reified => 2, // type_hash: PackedU64 - } + - // zig fmt: on - ini.fields_len); // field types - - const extra_index = addExtraAssumeCapacity(extra, EnumAuto{ - .name = undefined, // set by `prepare` - .name_nav = undefined, // set by `prepare` - .captures_len = switch (ini.key) { - inline .declared, .declared_owned_captures => |d| @intCast(d.captures.len), - .reified => std.math.maxInt(u32), - }, - .namespace = undefined, // set by `prepare` - .int_tag_type = .none, // set by `prepare` - .fields_len = ini.fields_len, - .names_map = names_map, - .zir_index = switch (ini.key) { - inline else => |x| x.zir_index, - }.toOptional(), - }); - items.appendAssumeCapacity(.{ - .tag = .type_enum_auto, - .data = extra_index, - }); - switch (ini.key) { - .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}), - .declared_owned_captures => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}), - .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)), - } - const names_start = extra.mutate.len; - _ = extra.addManyAsSliceAssumeCapacity(ini.fields_len); - return .{ .wip = .{ - .tid = tid, - .index = gop.put(), - .tag_ty_index = extra_index + std.meta.fieldIndex(EnumAuto, "int_tag_type").?, - .type_name_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "name").?, - .name_nav_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "name_nav").?, - .namespace_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "namespace").?, - .names_map = names_map, - .names_start = @intCast(names_start), - .values_map = .none, - .values_start = undefined, - } }; - }, - .explicit, .nonexhaustive => { - const values_map: OptionalMapIndex = if (!ini.has_values) .none else m: { - const values_map = try ip.addMap(gpa, io, tid, ini.fields_len); - break :m values_map.toOptional(); - }; - errdefer if (ini.has_values) { - local.mutate.maps.len -= 1; - }; - - try extra.ensureUnusedCapacity(@typeInfo(EnumExplicit).@"struct".fields.len + - // TODO: fmt bug - // zig fmt: off - switch (ini.key) { - inline .declared, .declared_owned_captures => |d| d.captures.len, - .reified => 2, // type_hash: PackedU64 - } + - // zig fmt: on - ini.fields_len + // field types - ini.fields_len * @intFromBool(ini.has_values)); // field values - - const extra_index = addExtraAssumeCapacity(extra, EnumExplicit{ - .name = undefined, // set by `prepare` - .name_nav = undefined, // set by `prepare` - .captures_len = switch (ini.key) { - inline .declared, .declared_owned_captures => |d| @intCast(d.captures.len), - .reified => std.math.maxInt(u32), - }, - .namespace = undefined, // set by `prepare` - .int_tag_type = .none, // set by `prepare` - .fields_len = ini.fields_len, - .names_map = names_map, - .values_map = values_map, - .zir_index = switch (ini.key) { - inline else => |x| x.zir_index, - }.toOptional(), - }); - items.appendAssumeCapacity(.{ - .tag = switch (ini.tag_mode) { - .auto => unreachable, - .explicit => .type_enum_explicit, - .nonexhaustive => .type_enum_nonexhaustive, - }, - .data = extra_index, - }); - switch (ini.key) { - .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}), - .declared_owned_captures => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}), - .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)), - } - const names_start = extra.mutate.len; - _ = extra.addManyAsSliceAssumeCapacity(ini.fields_len); - const values_start = extra.mutate.len; - if (ini.has_values) { - _ = extra.addManyAsSliceAssumeCapacity(ini.fields_len); - } - return .{ .wip = .{ - .tid = tid, - .index = gop.put(), - .tag_ty_index = extra_index + std.meta.fieldIndex(EnumExplicit, "int_tag_type").?, - .type_name_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "name").?, - .name_nav_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "name_nav").?, - .namespace_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "namespace").?, - .names_map = names_map, - .names_start = @intCast(names_start), - .values_map = values_map, - .values_start = @intCast(values_start), - } }; - }, - } -} - -const GeneratedTagEnumTypeInit = struct { - name: NullTerminatedString, - owner_union_ty: Index, - tag_ty: Index, - names: []const NullTerminatedString, - values: []const Index, - tag_mode: LoadedEnumType.TagMode, - parent_namespace: NamespaceIndex, -}; - -/// Creates an enum type which was automatically-generated as the tag type of a -/// `union` with no explicit tag type. Since this is only called once per union -/// type, it asserts that no matching type yet exists. -pub fn getGeneratedTagEnumType( - ip: *InternPool, - gpa: Allocator, - io: Io, - tid: Zcu.PerThread.Id, - ini: GeneratedTagEnumTypeInit, -) Allocator.Error!Index { - assert(ip.isUnion(ini.owner_union_ty)); - assert(ip.isIntegerType(ini.tag_ty)); - for (ini.values) |val| assert(ip.typeOf(val) == ini.tag_ty); - - const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa, io); - try items.ensureUnusedCapacity(1); - const extra = local.getMutableExtra(gpa, io); - - const names_map = try ip.addMap(gpa, io, tid, ini.names.len); - errdefer local.mutate.maps.len -= 1; - ip.addStringsToMap(names_map, ini.names); - - const fields_len: u32 = @intCast(ini.names.len); - - // Predict the index the enum will live at so we can construct the namespace before releasing the shard's mutex. - const enum_index = Index.Unwrapped.wrap(.{ - .tid = tid, - .index = items.mutate.len, - }, ip); - const parent_namespace = ip.namespacePtr(ini.parent_namespace); - const namespace = try ip.createNamespace(gpa, io, tid, .{ - .parent = ini.parent_namespace.toOptional(), - .owner_type = enum_index, - .file_scope = parent_namespace.file_scope, - .generation = parent_namespace.generation, - }); - errdefer ip.destroyNamespace(tid, namespace); - - const prev_extra_len = extra.mutate.len; - switch (ini.tag_mode) { - .auto => { - try extra.ensureUnusedCapacity(@typeInfo(EnumAuto).@"struct".fields.len + - 1 + // owner_union - fields_len); // field names - items.appendAssumeCapacity(.{ - .tag = .type_enum_auto, - .data = addExtraAssumeCapacity(extra, EnumAuto{ - .name = ini.name, - .name_nav = .none, - .captures_len = 0, - .namespace = namespace, - .int_tag_type = ini.tag_ty, - .fields_len = fields_len, - .names_map = names_map, - .zir_index = .none, - }), - }); - extra.appendAssumeCapacity(.{@intFromEnum(ini.owner_union_ty)}); - extra.appendSliceAssumeCapacity(.{@ptrCast(ini.names)}); - }, - .explicit, .nonexhaustive => { - try extra.ensureUnusedCapacity(@typeInfo(EnumExplicit).@"struct".fields.len + - 1 + // owner_union - fields_len + // field names - ini.values.len); // field values - - const values_map: OptionalMapIndex = if (ini.values.len != 0) m: { - const map = try ip.addMap(gpa, io, tid, ini.values.len); - ip.addIndexesToMap(map, ini.values); - break :m map.toOptional(); - } else .none; - // We don't clean up the values map on error! - errdefer @compileError("error path leaks values_map"); - - items.appendAssumeCapacity(.{ - .tag = switch (ini.tag_mode) { - .explicit => .type_enum_explicit, - .nonexhaustive => .type_enum_nonexhaustive, - .auto => unreachable, - }, - .data = addExtraAssumeCapacity(extra, EnumExplicit{ - .name = ini.name, - .name_nav = .none, - .captures_len = 0, - .namespace = namespace, - .int_tag_type = ini.tag_ty, - .fields_len = fields_len, - .names_map = names_map, - .values_map = values_map, - .zir_index = .none, - }), - }); - extra.appendAssumeCapacity(.{@intFromEnum(ini.owner_union_ty)}); - extra.appendSliceAssumeCapacity(.{@ptrCast(ini.names)}); - extra.appendSliceAssumeCapacity(.{@ptrCast(ini.values)}); - }, - } - errdefer extra.mutate.len = prev_extra_len; - errdefer switch (ini.tag_mode) { - .auto => {}, - .explicit, .nonexhaustive => if (ini.values.len != 0) { - local.mutate.maps.len -= 1; - }, - }; - - var gop = try ip.getOrPutKey(gpa, io, tid, .{ .enum_type = .{ - .generated_tag = .{ .union_type = ini.owner_union_ty }, - } }); - defer gop.deinit(); - assert(gop.put() == enum_index); - return enum_index; -} - -pub const OpaqueTypeInit = struct { - zir_index: TrackedInst.Index, - captures: []const CaptureValue, -}; - -pub fn getOpaqueType( - ip: *InternPool, - gpa: Allocator, - io: Io, - tid: Zcu.PerThread.Id, - ini: OpaqueTypeInit, -) Allocator.Error!WipNamespaceType.Result { - var gop = try ip.getOrPutKey(gpa, io, tid, .{ .opaque_type = .{ .declared = .{ - .zir_index = ini.zir_index, - .captures = .{ .external = ini.captures }, - } } }); - defer gop.deinit(); - if (gop == .existing) return .{ .existing = gop.existing }; - - const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa, io); - const extra = local.getMutableExtra(gpa, io); - try items.ensureUnusedCapacity(1); - - try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + ini.captures.len); - const extra_index = addExtraAssumeCapacity(extra, Tag.TypeOpaque{ - .name = undefined, // set by `finish` - .name_nav = undefined, // set by `finish` - .namespace = undefined, // set by `finish` - .zir_index = ini.zir_index, - .captures_len = @intCast(ini.captures.len), - }); - items.appendAssumeCapacity(.{ - .tag = .type_opaque, - .data = extra_index, - }); - extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)}); - return .{ - .wip = .{ - .tid = tid, - .index = gop.put(), - .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name").?, - .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name_nav").?, - .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "namespace").?, - }, - }; -} - pub fn getIfExists(ip: *const InternPool, key: Key) ?Index { const full_hash = key.hash64(ip); const hash: u32 = @truncate(full_hash >> 32); @@ -10534,6 +9584,9 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 { TrackedInst.Index, TrackedInst.Index.Optional, ComptimeAllocIndex, + @FieldType(Tag.TypeStructPacked, "captures_len"), + @FieldType(Tag.TypeUnionPacked, "captures_len"), + @FieldType(Tag.TypeEnum, "captures_len"), => @intFromEnum(@field(item, field.name)), u32, @@ -10545,7 +9598,6 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 { Tag.TypePointer.PackedOffset, Tag.TypeUnion.Flags, Tag.TypeStruct.Flags, - Tag.TypeStructPacked.Flags, => @bitCast(@field(item, field.name)), else => @compileError("bad field type: " ++ @typeName(field.type)), @@ -10597,6 +9649,9 @@ fn extraDataTrail(extra: Local.Extra, comptime T: type, index: u32) struct { dat TrackedInst.Index, TrackedInst.Index.Optional, ComptimeAllocIndex, + @FieldType(Tag.TypeStructPacked, "captures_len"), + @FieldType(Tag.TypeUnionPacked, "captures_len"), + @FieldType(Tag.TypeEnum, "captures_len"), => @enumFromInt(extra_item), u32, @@ -10607,7 +9662,6 @@ fn extraDataTrail(extra: Local.Extra, comptime T: type, index: u32) struct { dat Tag.TypePointer.PackedOffset, Tag.TypeUnion.Flags, Tag.TypeStruct.Flags, - Tag.TypeStructPacked.Flags, FuncAnalysis, => @bitCast(extra_item), @@ -10786,7 +9840,7 @@ pub fn getCoerced( .int => |int| switch (ip.indexToKey(new_ty)) { .enum_type => return ip.get(gpa, io, tid, .{ .enum_tag = .{ .ty = new_ty, - .int = try ip.getCoerced(gpa, io, tid, val, ip.loadEnumType(new_ty).tag_ty), + .int = try ip.getCoerced(gpa, io, tid, val, ip.loadEnumType(new_ty).int_tag_type), } }), .ptr_type => switch (int.storage) { inline .u64, .i64 => |int_val| return ip.get(gpa, io, tid, .{ .ptr = .{ @@ -10795,7 +9849,6 @@ pub fn getCoerced( .byte_offset = @intCast(int_val), } }), .big_int => unreachable, // must be a usize - .lazy_align, .lazy_size => {}, }, else => if (ip.isIntegerType(new_ty)) return ip.getCoercedInts(gpa, io, tid, int, new_ty), @@ -10825,11 +9878,11 @@ pub fn getCoerced( const index = enum_type.nameIndex(ip, enum_literal).?; return ip.get(gpa, io, tid, .{ .enum_tag = .{ .ty = new_ty, - .int = if (enum_type.values.len != 0) - enum_type.values.get(ip)[index] + .int = if (enum_type.field_values.len != 0) + enum_type.field_values.get(ip)[index] else try ip.get(gpa, io, tid, .{ .int = .{ - .ty = enum_type.tag_ty, + .ty = enum_type.int_tag_type, .storage = .{ .u64 = index }, } }), } }); @@ -11266,92 +10319,10 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo break :b @sizeOf(Tag.ErrorSet) + (@sizeOf(u32) * info.names_len); }, .type_inferred_error_set => 0, - .type_enum_explicit, .type_enum_nonexhaustive => b: { - const info = extraData(extra_list, EnumExplicit, data); - var ints = @typeInfo(EnumExplicit).@"struct".fields.len; - if (info.zir_index == .none) ints += 1; - ints += if (info.captures_len != std.math.maxInt(u32)) - info.captures_len - else - @typeInfo(PackedU64).@"struct".fields.len; - ints += info.fields_len; - if (info.values_map != .none) ints += info.fields_len; - break :b @sizeOf(u32) * ints; - }, - .type_enum_auto => b: { - const info = extraData(extra_list, EnumAuto, data); - const ints = @typeInfo(EnumAuto).@"struct".fields.len + info.captures_len + info.fields_len; - break :b @sizeOf(u32) * ints; - }, - .type_opaque => b: { - const info = extraData(extra_list, Tag.TypeOpaque, data); - const ints = @typeInfo(Tag.TypeOpaque).@"struct".fields.len + info.captures_len; - break :b @sizeOf(u32) * ints; - }, - .type_struct => b: { - const extra = extraDataTrail(extra_list, Tag.TypeStruct, data); - const info = extra.data; - var ints: usize = @typeInfo(Tag.TypeStruct).@"struct".fields.len; - if (info.flags.any_captures) { - const captures_len = extra_items[extra.end]; - ints += 1 + captures_len; - } - ints += info.fields_len; // types - ints += 1; // names_map - ints += info.fields_len; // names - if (info.flags.any_default_inits) - ints += info.fields_len; // inits - if (info.flags.any_aligned_fields) - ints += (info.fields_len + 3) / 4; // aligns - if (info.flags.any_comptime_fields) - ints += (info.fields_len + 31) / 32; // comptime bits - if (!info.flags.is_extern) - ints += info.fields_len; // runtime order - ints += info.fields_len; // offsets - break :b @sizeOf(u32) * ints; - }, - .type_struct_packed => b: { - const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, data); - const captures_len = if (extra.data.flags.any_captures) - extra_items[extra.end] - else - 0; - break :b @sizeOf(u32) * (@typeInfo(Tag.TypeStructPacked).@"struct".fields.len + - @intFromBool(extra.data.flags.any_captures) + captures_len + - extra.data.fields_len * 2); - }, - .type_struct_packed_inits => b: { - const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, data); - const captures_len = if (extra.data.flags.any_captures) - extra_items[extra.end] - else - 0; - break :b @sizeOf(u32) * (@typeInfo(Tag.TypeStructPacked).@"struct".fields.len + - @intFromBool(extra.data.flags.any_captures) + captures_len + - extra.data.fields_len * 3); - }, .type_tuple => b: { const info = extraData(extra_list, TypeTuple, data); break :b @sizeOf(TypeTuple) + (@sizeOf(u32) * 2 * info.fields_len); }, - - .type_union => b: { - const extra = extraDataTrail(extra_list, Tag.TypeUnion, data); - const captures_len = if (extra.data.flags.any_captures) - extra_items[extra.end] - else - 0; - const per_field = @sizeOf(u32); // field type - // 1 byte per field for alignment, rounded up to the nearest 4 bytes - const alignments = if (extra.data.flags.any_aligned_fields) - ((extra.data.fields_len + 3) / 4) * 4 - else - 0; - break :b @sizeOf(Tag.TypeUnion) + - 4 * (@intFromBool(extra.data.flags.any_captures) + captures_len) + - (extra.data.fields_len * per_field) + alignments; - }, - .type_function => b: { const info = extraData(extra_list, Tag.TypeFunction, data); break :b @sizeOf(Tag.TypeFunction) + @@ -11360,6 +10331,127 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo (@as(u32, 4) * @intFromBool(info.flags.has_noalias_bits)); }, + .type_struct => b: { + var n: usize = @typeInfo(Tag.TypeStruct).@"struct".fields.len; + const extra = extraDataTrail(extra_list, Tag.TypeStruct, data); + switch (extra.data.flags.any_captures) { + .reified => n += 2, // type_hash: PackedU64 + .true => { + n += 1; // captures_len: u32 + n += extra_items[extra.end]; // capture: CaptureValue + }, + .false => {}, + } + n += extra.data.fields_len; // field_name: NullTerminatedString + n += extra.data.fields_len; // field_type: Index + if (extra.data.flags.any_field_defaults) { + n += extra.data.fields_len; // field_default: Index + } + if (extra.data.flags.any_field_aligns) { + n += (extra.data.fields_len + 3) / 4; // field_align: Alignment + } + if (extra.data.flags.any_comptime_fields) { + n += (extra.data.fields_len + 31) / 32; // field_is_comptime_bits: u32 + } + if (extra.data.flags.layout == .auto) { + n += extra.data.fields_len; // field_runtime_order: RuntimeOrder + } + n += extra.data.fields_len; // field_offset: u32 + break :b n * @sizeOf(u32); + }, + .type_struct_packed_auto, .type_struct_packed_explicit => b: { + var n: usize = @typeInfo(Tag.TypeStructPacked).@"struct".fields.len; + const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, data); + switch (extra.data.captures_len) { + .reified => n += 2, // type_hash: PackedU64 + _ => |len| n += @intFromEnum(len), // capture: CaptureValue + } + n += extra.data.fields_len; // field_name: NullTerminatedString + n += extra.data.fields_len; // field_type: Index + break :b n * @sizeOf(u32); + }, + .type_struct_packed_auto_defaults, .type_struct_packed_explicit_defaults => b: { + var n: usize = @typeInfo(Tag.TypeStructPacked).@"struct".fields.len; + const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, data); + switch (extra.data.captures_len) { + .reified => n += 2, // type_hash: PackedU64 + _ => |len| n += @intFromEnum(len), // capture: CaptureValue + } + n += extra.data.fields_len; // field_name: NullTerminatedString + n += extra.data.fields_len; // field_type: Index + n += extra.data.fields_len; // field_default: Index + break :b n * @sizeOf(u32); + }, + .type_union => b: { + var n: usize = @typeInfo(Tag.TypeUnion).@"struct".fields.len; + const extra = extraDataTrail(extra_list, Tag.TypeUnion, data); + switch (extra.data.flags.any_captures) { + .reified => n += 2, // type_hash: PackedU64 + .true => { + n += 1; // captures_len: u32 + n += extra_items[extra.end]; // capture: CaptureValue + }, + .false => {}, + } + n += extra.data.fields_len; // field_type: Index + if (extra.data.flags.any_field_aligns) { + n += (extra.data.fields_len + 3) / 4; // field_align: Alignment + } + break :b n * @sizeOf(u32); + }, + .type_union_packed_auto, .type_union_packed_explicit => b: { + var n: usize = @typeInfo(Tag.TypeUnionPacked).@"struct".fields.len; + const extra = extraDataTrail(extra_list, Tag.TypeUnionPacked, data); + switch (extra.data.captures_len) { + .reified => n += 2, // type_hash: PackedU64 + _ => |len| n += @intFromEnum(len), // capture: CaptureValue + } + n += extra.data.fields_len; // field_type: Index + break :b n * @sizeOf(u32); + }, + .type_enum_auto => b: { + var n: usize = @typeInfo(Tag.TypeEnum).@"struct".fields.len; + const extra = extraData(extra_list, Tag.TypeEnum, data); + switch (extra.captures_len) { + .generated_union_tag => n += 1, // owner_union: Index + .reified => { + n += 1; // zir_index: TrackedInst.Index, + n += 2; // type_hash: PackedU64 + }, + _ => |len| { + n += 1; // zir_index: TrackedInst.Index, + n += @intFromEnum(len); // capture: CaptureValue + }, + } + n += extra.fields_len; // field_name: NullTerminatedString + break :b n * @sizeOf(u32); + }, + .type_enum_explicit, .type_enum_nonexhaustive => b: { + var n: usize = @typeInfo(Tag.TypeEnum).@"struct".fields.len; + const extra = extraData(extra_list, Tag.TypeEnum, data); + switch (extra.captures_len) { + .generated_union_tag => n += 1, // owner_union: Index + .reified => { + n += 1; // zir_index: TrackedInst.Index, + n += 2; // type_hash: PackedU64 + }, + _ => |len| { + n += 1; // zir_index: TrackedInst.Index, + n += @intFromEnum(len); // capture: CaptureValue + }, + } + n += 1; // field_value_map: MapIndex + n += extra.fields_len; // field_name: NullTerminatedString + n += extra.fields_len; // field_value: Index + break :b n * @sizeOf(u32); + }, + .type_opaque => b: { + var n: usize = @typeInfo(Tag.TypeEnum).@"struct".fields.len; + const extra = extraData(extra_list, Tag.TypeOpaque, data); + n += extra.captures_len; // capture: CaptureValue + break :b n * @sizeOf(u32); + }, + .undef => 0, .simple_type => 0, .simple_value => 0, @@ -11393,8 +10485,6 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo break :b @sizeOf(Int) + int.limbs_len * @sizeOf(Limb); }, - .int_lazy_align, .int_lazy_size => @sizeOf(IntLazy), - .error_set_error, .error_union_error => @sizeOf(Key.Error), .error_union_payload => @sizeOf(Tag.TypeValue), .enum_literal => 0, @@ -11484,16 +10574,20 @@ fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void { .type_anyerror_union, .type_error_set, .type_inferred_error_set, + .type_tuple, + .type_function, + .type_struct, + .type_struct_packed_auto, + .type_struct_packed_explicit, + .type_struct_packed_auto_defaults, + .type_struct_packed_explicit_defaults, + .type_union, + .type_union_packed_auto, + .type_union_packed_explicit, + .type_enum_auto, .type_enum_explicit, .type_enum_nonexhaustive, - .type_enum_auto, .type_opaque, - .type_struct, - .type_struct_packed, - .type_struct_packed_inits, - .type_tuple, - .type_union, - .type_function, .undef, .ptr_nav, .ptr_comptime_alloc, @@ -11517,8 +10611,6 @@ fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void { .int_small, .int_positive, .int_negative, - .int_lazy_align, - .int_lazy_size, .error_set_error, .error_union_error, .error_union_payload, @@ -12245,16 +11337,20 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { .type_anyerror_union, .type_error_set, .type_inferred_error_set, + .type_tuple, + .type_function, + .type_struct, + .type_struct_packed_auto, + .type_struct_packed_explicit, + .type_struct_packed_auto_defaults, + .type_struct_packed_explicit_defaults, + .type_union, + .type_union_packed_auto, + .type_union_packed_explicit, .type_enum_auto, .type_enum_explicit, .type_enum_nonexhaustive, .type_opaque, - .type_struct, - .type_struct_packed, - .type_struct_packed_inits, - .type_tuple, - .type_union, - .type_function, => .type_type, .undef, @@ -12278,8 +11374,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { .opt_payload, .error_union_payload, .int_small, - .int_lazy_align, - .int_lazy_size, .error_set_error, .error_union_error, .enum_tag, @@ -12613,22 +11707,26 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId { .type_inferred_error_set, => .error_set, + .simple_type => unreachable, // handled via Index tag above + + .type_tuple => .@"struct", + + .type_struct, + .type_struct_packed_auto, + .type_struct_packed_explicit, + .type_struct_packed_auto_defaults, + .type_struct_packed_explicit_defaults, + => .@"struct", + .type_union, + .type_union_packed_auto, + .type_union_packed_explicit, + => .@"union", .type_enum_auto, .type_enum_explicit, .type_enum_nonexhaustive, => .@"enum", - - .simple_type => unreachable, // handled via Index tag above - - .type_opaque => .@"opaque", - - .type_struct, - .type_struct_packed, - .type_struct_packed_inits, - .type_tuple, - => .@"struct", - - .type_union => .@"union", + .type_opaque, + => .@"opaque", .type_function => .@"fn", @@ -12658,8 +11756,6 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId { .int_small, .int_positive, .int_negative, - .int_lazy_align, - .int_lazy_size, .error_set_error, .error_union_error, .error_union_payload, @@ -13169,3 +12265,113 @@ const PackedCallingConvention = packed struct(u18) { }; } }; + +/// Asserts that `struct_type` is a non-packed struct type. +/// As well as calling this function, the caller must also populate these arrays: +/// * `field_types` +/// * `field_aligns` +/// * `field_runtime_order` +/// * `field_offsets` +pub fn resolveStructLayout( + ip: *InternPool, + io: Io, + struct_type: Index, + size: u32, + alignment: Alignment, + has_no_possible_value: bool, + has_one_possible_value: bool, + comptime_only: bool, +) void { + const unwrapped_index = struct_type.unwrap(ip); + + const local = ip.getLocal(unwrapped_index.tid); + local.mutate.extra.mutex.lockUncancelable(io); + defer local.mutate.extra.mutex.unlock(io); + + const extra_items = local.shared.extra.view().items(.@"0"); + const item = unwrapped_index.getItem(ip); + assert(item.tag == .type_struct); + + extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "size").?] = size; + const flags: *Tag.TypeStruct.Flags = @ptrCast(&extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "flags").?]); + flags.has_no_possible_value = has_no_possible_value; + flags.has_one_possible_value = has_one_possible_value; + flags.comptime_only = comptime_only; + flags.alignment = alignment; +} + +/// Asserts that `union_type` is a non-packed union type. +/// As well as calling this function, the caller must also populate these arrays: +/// * `field_types` +/// * `field_aligns` +pub fn resolveUnionLayout( + ip: *InternPool, + io: Io, + union_type: Index, + size: u32, + padding: u32, + alignment: Alignment, + has_no_possible_value: bool, + has_one_possible_value: bool, + comptime_only: bool, +) void { + const unwrapped_index = union_type.unwrap(ip); + + const local = ip.getLocal(unwrapped_index.tid); + local.mutate.extra.mutex.lockUncancelable(io); + defer local.mutate.extra.mutex.unlock(io); + + const extra_items = local.shared.extra.view().items(.@"0"); + const item = unwrapped_index.getItem(ip); + assert(item.tag == .type_union); + + extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnion, "size").?] = size; + extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnion, "padding").?] = padding; + const flags: *Tag.TypeUnion.Flags = @ptrCast(&extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnion, "flags").?]); + flags.has_no_possible_value = has_no_possible_value; + flags.has_one_possible_value = has_one_possible_value; + flags.comptime_only = comptime_only; + flags.alignment = alignment; +} + +/// Asserts that `struct_type` is a packed struct type. +pub fn resolvePackedStructBackingInt(ip: *InternPool, io: Io, struct_type: Index, backing_int_type: Index) void { + const unwrapped_index = struct_type.unwrap(ip); + + const local = ip.getLocal(unwrapped_index.tid); + local.mutate.extra.mutex.lockUncancelable(io); + defer local.mutate.extra.mutex.unlock(io); + + const extra_items = local.shared.extra.view().items(.@"0"); + const item = unwrapped_index.getItem(ip); + switch (item.tag) { + .type_struct_packed_auto, + .type_struct_packed_explicit, + .type_struct_packed_auto_defaults, + .type_struct_packed_explicit_defaults, + => {}, + else => unreachable, + } + + extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "backing_int_type").?] = @intFromEnum(backing_int_type); +} + +/// Asserts that `union_type` is a packed union type. +pub fn resolvePackedUnionBackingInt(ip: *InternPool, io: Io, union_type: Index, backing_int_type: Index) void { + const unwrapped_index = union_type.unwrap(ip); + + const local = ip.getLocal(unwrapped_index.tid); + local.mutate.extra.mutex.lockUncancelable(io); + defer local.mutate.extra.mutex.unlock(io); + + const extra_items = local.shared.extra.view().items(.@"0"); + const item = unwrapped_index.getItem(ip); + switch (item.tag) { + .type_union_packed_auto, + .type_union_packed_explicit, + => {}, + else => unreachable, + } + + extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnionPacked, "backing_int_type").?] = @intFromEnum(backing_int_type); +} diff --git a/src/Sema.zig b/src/Sema.zig index 58fa1af124239ff05093bc9cf857a16f36de09e4..55fb718a45b989ecac821626638dde9a98ab99b5 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -173,13 +173,17 @@ const ComptimeAlloc = struct { runtime_index: RuntimeIndex, }; +/// Asserts that `ty` is not an OPV type. /// `src` may be `null` if `is_const` will be set. fn newComptimeAlloc(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type, alignment: Alignment) !ComptimeAllocIndex { const pt = sema.pt; - const init_val = try sema.typeHasOnePossibleValue(ty) orelse try pt.undefValue(ty); + + // Explicit guard because this call mutates the InternPool so cannot be optimized out. + if (std.debug.runtime_safety) assert(ty.onePossibleValue(pt) catch @panic("") == null); + const idx = sema.comptime_allocs.items.len; try sema.comptime_allocs.append(sema.gpa, .{ - .val = .{ .interned = init_val.toIntern() }, + .val = .{ .interned = (try pt.undefValue(ty)).toIntern() }, .is_const = false, .src = src, .alignment = alignment, @@ -1382,10 +1386,10 @@ fn analyzeBodyInner( const extended = datas[@intFromEnum(inst)].extended; break :ext switch (extended.opcode) { // zig fmt: off - .struct_decl => try sema.zirStructDecl( block, extended, inst), - .enum_decl => try sema.zirEnumDecl( block, extended, inst), - .union_decl => try sema.zirUnionDecl( block, extended, inst), - .opaque_decl => try sema.zirOpaqueDecl( block, extended, inst), + .struct_decl => try sema.zirStructDecl( block, inst), + .enum_decl => try sema.zirEnumDecl( block, inst), + .union_decl => try sema.zirUnionDecl( block, inst), + .opaque_decl => try sema.zirOpaqueDecl( block, inst), .tuple_decl => try sema.zirTupleDecl( block, extended), .this => try sema.zirThis( block, extended), .ret_addr => try sema.zirRetAddr( block, extended), @@ -1993,6 +1997,24 @@ fn analyzeBodyInner( assert(sema.isNoReturn(block.instructions.items[block.instructions.items.len - 1].toRef())); break; } + // + if (air_inst.toIndex()) |air_inst_index| { + switch (sema.air_instructions.items(.tag)[@intFromEnum(air_inst_index)]) { + .inferred_alloc, .inferred_alloc_comptime => {}, + else => { + assert(sema.typeOf(air_inst).onePossibleValue(pt) catch @panic("") == null); + sema.typeOf(air_inst).assertHasLayout(zcu); + }, + } + } else { + switch (tags[@intFromEnum(inst)]) { + // MLUGG TODO: do we actually *want* this exception? we could arguably simplify things without it + // e.g. analyzeNavVal could stop doing ensureLayoutResolved in most cases (`extern` is an exception) and instead do `assertHasLayout` + .func, .func_inferred, .func_fancy => {}, // exception: we're in a func decl, layout will get resolved in a bit by `analyzeNavVal` + else => sema.typeOf(air_inst).assertHasLayout(zcu), + } + } + // map.putAssumeCapacity(inst, air_inst); i += 1; } @@ -2190,7 +2212,7 @@ fn genericPoisonReason(sema: *Sema, block: *Block, ref: Zir.Inst.Ref) GenericPoi } } -fn analyzeAsType( +pub fn analyzeAsType( sema: *Sema, block: *Block, src: LazySrcLoc, @@ -2227,7 +2249,6 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) // var st: StackTrace = undefined; const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace); - try stack_trace_ty.resolveFields(pt); const st_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(stack_trace_ty)); // st.instruction_addresses = &addrs; @@ -2247,14 +2268,11 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) } /// Return the Value corresponding to a given AIR ref, or `null` if it refers to a runtime value. -fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value { +/// TODO MLUGG: remove the error union return! +fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) error{}!?Value { const zcu = sema.pt.zcu; assert(inst != .none); - if (try sema.typeHasOnePossibleValue(sema.typeOf(inst))) |opv| { - return opv; - } - if (inst.toInterned()) |ip_index| { const val: Value = .fromInterned(ip_index); assert(val.getVariable(zcu) == null); @@ -2267,12 +2285,18 @@ fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value { .inferred_alloc_comptime => unreachable, // assertion failure else => {}, } + // Assert that the type is not OPV -- if it was, the value would have been comptime-known. + // Explicit guard because this could add to the InternPool so cannot be optimized away. + if (std.debug.runtime_safety) { + const opv = sema.typeOf(inst).onePossibleValue(sema.pt) catch @panic("oom in assert"); + assert(opv == null); + } return null; } } /// Like `resolveValue`, but emits an error if the value is not comptime-known. -fn resolveConstValue( +pub fn resolveConstValue( sema: *Sema, block: *Block, src: LazySrcLoc, @@ -2301,7 +2325,7 @@ fn resolveDefinedValue( } /// Like `resolveValue`, but emits an error if the value is not comptime-known or is undefined. -fn resolveConstDefinedValue( +pub fn resolveConstDefinedValue( sema: *Sema, block: *Block, src: LazySrcLoc, @@ -2315,11 +2339,6 @@ fn resolveConstDefinedValue( return val; } -/// Like `resolveValue`, but recursively resolves lazy values before returning. -fn resolveValueResolveLazy(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value { - return try sema.resolveLazyValue((try sema.resolveValue(inst)) orelse return null); -} - /// Value Tag may be `undef` or `variable`. pub fn resolveFinalDeclValue( sema: *Sema, @@ -2439,13 +2458,14 @@ fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError { const pt = sema.pt; + const zcu = pt.zcu; const msg = msg: { const msg = try sema.errMsg(src, "type '{f}' does not support array initialization syntax", .{ ty.fmt(pt), }); errdefer msg.destroy(sema.gpa); - if (ty.isSlice(pt.zcu)) { - try sema.errNote(src, msg, "inferred array length is specified with an underscore: '[_]{f}'", .{ty.elemType2(pt.zcu).fmt(pt)}); + if (ty.isSlice(zcu)) { + try sema.errNote(src, msg, "inferred array length is specified with an underscore: '[_]{f}'", .{ty.childType(zcu).fmt(pt)}); } break :msg msg; }; @@ -2644,7 +2664,7 @@ pub fn fail( src: LazySrcLoc, comptime format: []const u8, args: anytype, -) CompileError { +) SemaError { const err_msg = try sema.errMsg(src, format, args); inline for (args) |arg| { if (@TypeOf(arg) == Type.Formatter) { @@ -2798,27 +2818,26 @@ fn analyzeAsInt( ) !u64 { const coerced = try sema.coerce(block, dest_ty, air_ref, src); const val = try sema.resolveConstDefinedValue(block, src, coerced, reason); - return try val.toUnsignedIntSema(sema.pt); + return val.toUnsignedInt(sema.pt.zcu); } fn analyzeValueAsCallconv( sema: *Sema, block: *Block, src: LazySrcLoc, - unresolved_val: Value, + val: Value, ) !std.builtin.CallingConvention { - return interpretBuiltinType(sema, block, src, unresolved_val, std.builtin.CallingConvention); + return interpretBuiltinType(sema, block, src, val, std.builtin.CallingConvention); } fn interpretBuiltinType( sema: *Sema, block: *Block, src: LazySrcLoc, - unresolved_val: Value, + val: Value, comptime T: type, ) !T { - const resolved_val = try sema.resolveLazyValue(unresolved_val); - return resolved_val.interpret(T, sema.pt) catch |err| switch (err) { + return val.interpret(T, sema.pt) catch |err| switch (err) { error.OutOfMemory => |e| return e, error.UndefinedValue => return sema.failWithUseOfUndef(block, src, null), error.TypeMismatch => @panic("std.builtin is corrupt"), @@ -2913,7 +2932,13 @@ fn validateTupleFieldType( /// Given a ZIR extra index which points to a list of `Zir.Inst.Capture`, /// resolves this into a list of `InternPool.CaptureValue` allocated by `arena`. -fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: usize, captures_len: u32) ![]InternPool.CaptureValue { +fn getCaptures( + sema: *Sema, + block: *Block, + type_src: LazySrcLoc, + zir_captures: []const Zir.Inst.Capture, + zir_capture_names: []const Zir.NullTerminatedString, +) ![]InternPool.CaptureValue { const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; @@ -2924,41 +2949,38 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us const parent_ty: Type = .fromInterned(zcu.namespacePtr(block.namespace).owner_type); const parent_captures: InternPool.CaptureValue.Slice = parent_ty.getCaptures(zcu); - const captures = try sema.arena.alloc(InternPool.CaptureValue, captures_len); + const captures = try sema.arena.alloc(InternPool.CaptureValue, zir_captures.len); - for (sema.code.extra[extra_index..][0..captures_len], sema.code.extra[extra_index + captures_len ..][0..captures_len], captures) |raw, raw_name, *capture| { - const zir_capture: Zir.Inst.Capture = @bitCast(raw); - const zir_name: Zir.NullTerminatedString = @enumFromInt(raw_name); + for (zir_captures, zir_capture_names, captures) |zir_capture, zir_name, *capture| { const zir_name_slice = sema.code.nullTerminatedString(zir_name); capture.* = switch (zir_capture.unwrap()) { .nested => |parent_idx| parent_captures.get(ip)[parent_idx], - .instruction_load => |ptr_inst| InternPool.CaptureValue.wrap(capture: { + .instruction_load => |ptr_inst| capture: { const ptr_ref = try sema.resolveInst(ptr_inst.toRef()); const ptr_val = try sema.resolveValue(ptr_ref) orelse { - break :capture .{ .runtime = sema.typeOf(ptr_ref).childType(zcu).toIntern() }; + break :capture .wrap(.{ .runtime = sema.typeOf(ptr_ref).childType(zcu).toIntern() }); }; // TODO: better source location - const unresolved_loaded_val = try sema.pointerDeref(block, type_src, ptr_val, sema.typeOf(ptr_ref)) orelse { - break :capture .{ .runtime = sema.typeOf(ptr_ref).childType(zcu).toIntern() }; + const loaded_val = try sema.pointerDeref(block, type_src, ptr_val, sema.typeOf(ptr_ref)) orelse { + break :capture .wrap(.{ .runtime = sema.typeOf(ptr_ref).childType(zcu).toIntern() }); }; - const loaded_val = try sema.resolveLazyValue(unresolved_loaded_val); if (loaded_val.canMutateComptimeVarState(zcu)) { const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_name_slice, .no_embedded_nulls); return sema.failWithContainsReferenceToComptimeVar(block, type_src, field_name, "captured value", loaded_val); } - break :capture .{ .@"comptime" = loaded_val.toIntern() }; - }), - .instruction => |inst| InternPool.CaptureValue.wrap(capture: { + break :capture .wrap(.{ .@"comptime" = loaded_val.toIntern() }); + }, + .instruction => |inst| capture: { const air_ref = try sema.resolveInst(inst.toRef()); - if (try sema.resolveValueResolveLazy(air_ref)) |val| { + if (try sema.resolveValue(air_ref)) |val| { if (val.canMutateComptimeVarState(zcu)) { const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_name_slice, .no_embedded_nulls); return sema.failWithContainsReferenceToComptimeVar(block, type_src, field_name, "captured value", val); } - break :capture .{ .@"comptime" = val.toIntern() }; + break :capture .wrap(.{ .@"comptime" = val.toIntern() }); } - break :capture .{ .runtime = sema.typeOf(air_ref).toIntern() }; - }), + break :capture .wrap(.{ .runtime = sema.typeOf(air_ref).toIntern() }); + }, .decl_val => |str| capture: { const decl_name = try ip.getOrPutString( gpa, @@ -2968,7 +2990,7 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us .no_embedded_nulls, ); const nav = try sema.lookupIdentifier(block, decl_name); - break :capture InternPool.CaptureValue.wrap(.{ .nav_val = nav }); + break :capture .wrap(.{ .nav_val = nav }); }, .decl_ref => |str| capture: { const decl_name = try ip.getOrPutString( @@ -2987,621 +3009,6 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us return captures; } -fn zirStructDecl( - sema: *Sema, - block: *Block, - extended: Zir.Inst.Extended.InstData, - inst: Zir.Inst.Index, -) CompileError!Air.Inst.Ref { - const pt = sema.pt; - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const io = comp.io; - const ip = &zcu.intern_pool; - - const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); - const extra = sema.code.extraData(Zir.Inst.StructDecl, extended.operand); - - const tracked_inst = try block.trackZir(inst); - const src: LazySrcLoc = .{ - .base_node_inst = tracked_inst, - .offset = LazySrcLoc.Offset.nodeOffset(.zero), - }; - - var extra_index = extra.end; - - const captures_len = if (small.has_captures_len) blk: { - const captures_len = sema.code.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - const fields_len = if (small.has_fields_len) blk: { - const fields_len = sema.code.extra[extra_index]; - extra_index += 1; - break :blk fields_len; - } else 0; - const decls_len = if (small.has_decls_len) blk: { - const decls_len = sema.code.extra[extra_index]; - extra_index += 1; - break :blk decls_len; - } else 0; - - const captures = try sema.getCaptures(block, src, extra_index, captures_len); - extra_index += captures_len * 2; - - if (small.has_backing_int) { - const backing_int_body_len = sema.code.extra[extra_index]; - extra_index += 1; // backing_int_body_len - if (backing_int_body_len == 0) { - extra_index += 1; // backing_int_ref - } else { - extra_index += backing_int_body_len; // backing_int_body_inst - } - } - - const struct_init: InternPool.StructTypeInit = .{ - .layout = small.layout, - .fields_len = fields_len, - .known_non_opv = small.known_non_opv, - .requires_comptime = if (small.known_comptime_only) .yes else .unknown, - .any_comptime_fields = small.any_comptime_fields, - .any_default_inits = small.any_default_inits, - .inits_resolved = false, - .any_aligned_fields = small.any_aligned_fields, - .key = .{ .declared = .{ - .zir_index = tracked_inst, - .captures = captures, - } }, - }; - const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, struct_init, false)) { - .existing => |ty| { - const new_ty = try pt.ensureTypeUpToDate(ty); - - // Make sure we update the namespace if the declaration is re-analyzed, to pick - // up on e.g. changed comptime decls. - try pt.ensureNamespaceUpToDate(Type.fromInterned(new_ty).getNamespaceIndex(zcu)); - - try sema.declareDependency(.{ .interned = new_ty }); - try sema.addTypeReferenceEntry(src, new_ty); - return Air.internedToRef(new_ty); - }, - .wip => |wip| wip, - }; - errdefer wip_ty.cancel(ip, pt.tid); - - const type_name = try sema.createTypeName( - block, - small.name_strategy, - "struct", - inst, - wip_ty.index, - ); - wip_ty.setName(ip, type_name.name, type_name.nav); - - const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ - .parent = block.namespace.toOptional(), - .owner_type = wip_ty.index, - .file_scope = block.getFileScopeIndex(zcu), - .generation = zcu.generation, - }); - errdefer pt.destroyNamespace(new_namespace_index); - - if (pt.zcu.comp.config.incremental) { - try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = tracked_inst }); - } - - const decls = sema.code.bodySlice(extra_index, decls_len); - try pt.scanNamespace(new_namespace_index, decls); - - try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); - codegen_type: { - if (zcu.comp.config.use_llvm) break :codegen_type; - if (block.ownerModule().strip) break :codegen_type; - // This job depends on any resolve_type_fully jobs queued up before it. - zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); - try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); - } - try sema.declareDependency(.{ .interned = wip_ty.index }); - try sema.addTypeReferenceEntry(src, wip_ty.index); - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); - return Air.internedToRef(wip_ty.finish(ip, new_namespace_index)); -} - -pub fn createTypeName( - sema: *Sema, - block: *Block, - name_strategy: Zir.Inst.NameStrategy, - anon_prefix: []const u8, - inst: ?Zir.Inst.Index, - /// This is used purely to give the type a unique name in the `anon` case. - type_index: InternPool.Index, -) CompileError!struct { - name: InternPool.NullTerminatedString, - nav: InternPool.Nav.Index.Optional, -} { - const pt = sema.pt; - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const io = comp.io; - const ip = &zcu.intern_pool; - - switch (name_strategy) { - .anon => {}, // handled after switch - .parent => return .{ - .name = block.type_name_ctx, - .nav = sema.owner.unwrap().nav_val.toOptional(), - }, - .func => func_strat: { - const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse return error.AnalysisFail); - const zir_tags = sema.code.instructions.items(.tag); - - var aw: std.Io.Writer.Allocating = .init(gpa); - defer aw.deinit(); - const w = &aw.writer; - w.print("{f}(", .{block.type_name_ctx.fmt(ip)}) catch return error.OutOfMemory; - - var arg_i: usize = 0; - for (fn_info.param_body) |zir_inst| switch (zir_tags[@intFromEnum(zir_inst)]) { - .param, .param_comptime, .param_anytype, .param_anytype_comptime => { - const arg = sema.inst_map.get(zir_inst).?; - // If this is being called in a generic function then analyzeCall will - // have already resolved the args and this will work. - // If not then this is a struct type being returned from a non-generic - // function and the name doesn't matter since it will later - // result in a compile error. - const arg_val = try sema.resolveValue(arg) orelse break :func_strat; // fall through to anon strat - - if (arg_i != 0) w.writeByte(',') catch return error.OutOfMemory; - - // Limiting the depth here helps avoid type names getting too long, which - // in turn helps to avoid unreasonably long symbol names for namespaced - // symbols. Such names should ideally be human-readable, and additionally, - // some tooling may not support very long symbol names. - w.print("{f}", .{Value.fmtValueSemaFull(.{ - .val = arg_val, - .pt = pt, - .opt_sema = sema, - .depth = 1, - })}) catch return error.OutOfMemory; - - arg_i += 1; - continue; - }, - else => continue, - }; - - w.writeByte(')') catch return error.OutOfMemory; - return .{ - .name = try ip.getOrPutString(gpa, io, pt.tid, aw.written(), .no_embedded_nulls), - .nav = .none, - }; - }, - .dbg_var => { - // TODO: this logic is questionable. We ideally should be traversing the `Block` rather than relying on the order of AstGen instructions. - const ref = inst.?.toRef(); - const zir_tags = sema.code.instructions.items(.tag); - const zir_data = sema.code.instructions.items(.data); - for (@intFromEnum(inst.?)..zir_tags.len) |i| switch (zir_tags[i]) { - .dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) { - return .{ - .name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}.{s}", .{ - block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code), - }, .no_embedded_nulls), - .nav = .none, - }; - }, - else => {}, - }; - // fall through to anon strat - }, - } - - // anon strat handling - - // It would be neat to have "struct:line:column" but this name has - // to survive incremental updates, where it may have been shifted down - // or up to a different line, but unchanged, and thus not unnecessarily - // semantically analyzed. - // TODO: that would be possible, by detecting line number changes and renaming - // types appropriately. However, `@typeName` becomes a problem then. If we remove - // that builtin from the language, we can consider this. - - return .{ - .name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}__{s}_{d}", .{ - block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(type_index), - }, .no_embedded_nulls), - .nav = .none, - }; -} - -fn zirEnumDecl( - sema: *Sema, - block: *Block, - extended: Zir.Inst.Extended.InstData, - inst: Zir.Inst.Index, -) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - - const pt = sema.pt; - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const io = comp.io; - const ip = &zcu.intern_pool; - - const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small); - const extra = sema.code.extraData(Zir.Inst.EnumDecl, extended.operand); - var extra_index: usize = extra.end; - - const tracked_inst = try block.trackZir(inst); - const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) }; - - const tag_type_ref = if (small.has_tag_type) blk: { - const tag_type_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); - extra_index += 1; - break :blk tag_type_ref; - } else .none; - - const captures_len = if (small.has_captures_len) blk: { - const captures_len = sema.code.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - - const body_len = if (small.has_body_len) blk: { - const body_len = sema.code.extra[extra_index]; - extra_index += 1; - break :blk body_len; - } else 0; - - const fields_len = if (small.has_fields_len) blk: { - const fields_len = sema.code.extra[extra_index]; - extra_index += 1; - break :blk fields_len; - } else 0; - - const decls_len = if (small.has_decls_len) blk: { - const decls_len = sema.code.extra[extra_index]; - extra_index += 1; - break :blk decls_len; - } else 0; - - const captures = try sema.getCaptures(block, src, extra_index, captures_len); - extra_index += captures_len * 2; - - const decls = sema.code.bodySlice(extra_index, decls_len); - extra_index += decls_len; - - const body = sema.code.bodySlice(extra_index, body_len); - extra_index += body.len; - - const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable; - const body_end = extra_index; - extra_index += bit_bags_count; - - const any_values = for (sema.code.extra[body_end..][0..bit_bags_count]) |bag| { - if (bag != 0) break true; - } else false; - - const enum_init: InternPool.EnumTypeInit = .{ - .has_values = any_values, - .tag_mode = if (small.nonexhaustive) - .nonexhaustive - else if (tag_type_ref == .none) - .auto - else - .explicit, - .fields_len = fields_len, - .key = .{ .declared = .{ - .zir_index = tracked_inst, - .captures = captures, - } }, - }; - const wip_ty = switch (try ip.getEnumType(gpa, io, pt.tid, enum_init, false)) { - .existing => |ty| { - const new_ty = try pt.ensureTypeUpToDate(ty); - - // Make sure we update the namespace if the declaration is re-analyzed, to pick - // up on e.g. changed comptime decls. - try pt.ensureNamespaceUpToDate(Type.fromInterned(new_ty).getNamespaceIndex(zcu)); - - try sema.declareDependency(.{ .interned = new_ty }); - try sema.addTypeReferenceEntry(src, new_ty); - - // Since this is an enum, it has to be resolved immediately. - // `ensureTypeUpToDate` has resolved the new type if necessary. - // We just need to check for resolution failures. - const ty_unit: AnalUnit = .wrap(.{ .type = new_ty }); - if (zcu.failed_analysis.contains(ty_unit) or zcu.transitive_failed_analysis.contains(ty_unit)) { - return error.AnalysisFail; - } - - return Air.internedToRef(new_ty); - }, - .wip => |wip| wip, - }; - - // Once this is `true`, we will not delete the decl or type even upon failure, since we - // have finished constructing the type and are in the process of analyzing it. - var done = false; - - errdefer if (!done) wip_ty.cancel(ip, pt.tid); - - const type_name = try sema.createTypeName( - block, - small.name_strategy, - "enum", - inst, - wip_ty.index, - ); - wip_ty.setName(ip, type_name.name, type_name.nav); - - const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ - .parent = block.namespace.toOptional(), - .owner_type = wip_ty.index, - .file_scope = block.getFileScopeIndex(zcu), - .generation = zcu.generation, - }); - errdefer if (!done) pt.destroyNamespace(new_namespace_index); - - try pt.scanNamespace(new_namespace_index, decls); - - try sema.declareDependency(.{ .interned = wip_ty.index }); - try sema.addTypeReferenceEntry(src, wip_ty.index); - - // We've finished the initial construction of this type, and are about to perform analysis. - // Set the namespace appropriately, and don't destroy anything on failure. - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); - wip_ty.prepare(ip, new_namespace_index); - done = true; - - { - const tracked_unit = zcu.trackUnitSema(type_name.name.toSlice(ip), null); - defer tracked_unit.end(zcu); - try Sema.resolveDeclaredEnum( - pt, - wip_ty, - inst, - tracked_inst, - new_namespace_index, - type_name.name, - small, - body, - tag_type_ref, - any_values, - fields_len, - sema.code, - body_end, - ); - } - - codegen_type: { - if (zcu.comp.config.use_llvm) break :codegen_type; - if (block.ownerModule().strip) break :codegen_type; - // This job depends on any resolve_type_fully jobs queued up before it. - zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); - try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); - } - return Air.internedToRef(wip_ty.index); -} - -fn zirUnionDecl( - sema: *Sema, - block: *Block, - extended: Zir.Inst.Extended.InstData, - inst: Zir.Inst.Index, -) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - - const pt = sema.pt; - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const io = comp.io; - const ip = &zcu.intern_pool; - - const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); - const extra = sema.code.extraData(Zir.Inst.UnionDecl, extended.operand); - var extra_index: usize = extra.end; - - const tracked_inst = try block.trackZir(inst); - const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) }; - - extra_index += @intFromBool(small.has_tag_type); - const captures_len = if (small.has_captures_len) blk: { - const captures_len = sema.code.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - extra_index += @intFromBool(small.has_body_len); - const fields_len = if (small.has_fields_len) blk: { - const fields_len = sema.code.extra[extra_index]; - extra_index += 1; - break :blk fields_len; - } else 0; - - const decls_len = if (small.has_decls_len) blk: { - const decls_len = sema.code.extra[extra_index]; - extra_index += 1; - break :blk decls_len; - } else 0; - - const captures = try sema.getCaptures(block, src, extra_index, captures_len); - extra_index += captures_len * 2; - - const union_init: InternPool.UnionTypeInit = .{ - .flags = .{ - .layout = small.layout, - .status = .none, - .runtime_tag = if (small.has_tag_type or small.auto_enum_tag) - .tagged - else if (small.layout != .auto) - .none - else switch (block.wantSafeTypes()) { - true => .safety, - false => .none, - }, - .any_aligned_fields = small.any_aligned_fields, - .requires_comptime = .unknown, - .assumed_runtime_bits = false, - .assumed_pointer_aligned = false, - .alignment = .none, - }, - .fields_len = fields_len, - .enum_tag_ty = .none, // set later - .field_types = &.{}, // set later - .field_aligns = &.{}, // set later - .key = .{ .declared = .{ - .zir_index = tracked_inst, - .captures = captures, - } }, - }; - const wip_ty = switch (try ip.getUnionType(gpa, io, pt.tid, union_init, false)) { - .existing => |ty| { - const new_ty = try pt.ensureTypeUpToDate(ty); - - // Make sure we update the namespace if the declaration is re-analyzed, to pick - // up on e.g. changed comptime decls. - try pt.ensureNamespaceUpToDate(Type.fromInterned(new_ty).getNamespaceIndex(zcu)); - - try sema.declareDependency(.{ .interned = new_ty }); - try sema.addTypeReferenceEntry(src, new_ty); - return Air.internedToRef(new_ty); - }, - .wip => |wip| wip, - }; - errdefer wip_ty.cancel(ip, pt.tid); - - const type_name = try sema.createTypeName( - block, - small.name_strategy, - "union", - inst, - wip_ty.index, - ); - wip_ty.setName(ip, type_name.name, type_name.nav); - - const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ - .parent = block.namespace.toOptional(), - .owner_type = wip_ty.index, - .file_scope = block.getFileScopeIndex(zcu), - .generation = zcu.generation, - }); - errdefer pt.destroyNamespace(new_namespace_index); - - if (pt.zcu.comp.config.incremental) { - try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = tracked_inst }); - } - - const decls = sema.code.bodySlice(extra_index, decls_len); - try pt.scanNamespace(new_namespace_index, decls); - - try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); - codegen_type: { - if (zcu.comp.config.use_llvm) break :codegen_type; - if (block.ownerModule().strip) break :codegen_type; - // This job depends on any resolve_type_fully jobs queued up before it. - zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); - try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); - } - try sema.declareDependency(.{ .interned = wip_ty.index }); - try sema.addTypeReferenceEntry(src, wip_ty.index); - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); - return Air.internedToRef(wip_ty.finish(ip, new_namespace_index)); -} - -fn zirOpaqueDecl( - sema: *Sema, - block: *Block, - extended: Zir.Inst.Extended.InstData, - inst: Zir.Inst.Index, -) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - - const pt = sema.pt; - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const io = comp.io; - const ip = &zcu.intern_pool; - - const small: Zir.Inst.OpaqueDecl.Small = @bitCast(extended.small); - const extra = sema.code.extraData(Zir.Inst.OpaqueDecl, extended.operand); - var extra_index: usize = extra.end; - - const tracked_inst = try block.trackZir(inst); - const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) }; - - const captures_len = if (small.has_captures_len) blk: { - const captures_len = sema.code.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - - const decls_len = if (small.has_decls_len) blk: { - const decls_len = sema.code.extra[extra_index]; - extra_index += 1; - break :blk decls_len; - } else 0; - - const captures = try sema.getCaptures(block, src, extra_index, captures_len); - extra_index += captures_len * 2; - - const opaque_init: InternPool.OpaqueTypeInit = .{ - .zir_index = tracked_inst, - .captures = captures, - }; - const wip_ty = switch (try ip.getOpaqueType(gpa, io, pt.tid, opaque_init)) { - .existing => |ty| { - // Make sure we update the namespace if the declaration is re-analyzed, to pick - // up on e.g. changed comptime decls. - try pt.ensureNamespaceUpToDate(Type.fromInterned(ty).getNamespaceIndex(zcu)); - - try sema.declareDependency(.{ .interned = ty }); - try sema.addTypeReferenceEntry(src, ty); - return Air.internedToRef(ty); - }, - .wip => |wip| wip, - }; - errdefer wip_ty.cancel(ip, pt.tid); - - const type_name = try sema.createTypeName( - block, - small.name_strategy, - "opaque", - inst, - wip_ty.index, - ); - wip_ty.setName(ip, type_name.name, type_name.nav); - - const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ - .parent = block.namespace.toOptional(), - .owner_type = wip_ty.index, - .file_scope = block.getFileScopeIndex(zcu), - .generation = zcu.generation, - }); - errdefer pt.destroyNamespace(new_namespace_index); - - const decls = sema.code.bodySlice(extra_index, decls_len); - try pt.scanNamespace(new_namespace_index, decls); - - codegen_type: { - if (zcu.comp.config.use_llvm) break :codegen_type; - if (block.ownerModule().strip) break :codegen_type; - // This job depends on any resolve_type_fully jobs queued up before it. - zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); - try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); - } - try sema.addTypeReferenceEntry(src, wip_ty.index); - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); - return Air.internedToRef(wip_ty.finish(ip, new_namespace_index)); -} - fn zirErrorSetDecl( sema: *Sema, inst: Zir.Inst.Index, @@ -3640,16 +3047,16 @@ fn zirRetPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. defer tracy.end(); const pt = sema.pt; + const zcu = pt.zcu; const src = block.nodeOffset(sema.code.instructions.items(.data)[@intFromEnum(inst)].node); - if (block.isComptime() or try sema.fn_ret_ty.comptimeOnlySema(pt)) { - try sema.fn_ret_ty.resolveFields(pt); + if (block.isComptime() or sema.fn_ret_ty.comptimeOnly(zcu)) { return sema.analyzeComptimeAlloc(block, src, sema.fn_ret_ty, .none); } - const target = pt.zcu.getTarget(); - const ptr_type = try pt.ptrTypeSema(.{ + const target = zcu.getTarget(); + const ptr_type = try pt.ptrType(.{ .child = sema.fn_ret_ty.toIntern(), .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, }); @@ -3826,6 +3233,7 @@ fn zirAllocExtended( extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const pt = sema.pt; + const zcu = pt.zcu; const gpa = sema.gpa; const extra = sema.code.extraData(Zir.Inst.AllocExtended, extended.operand); const var_src = block.nodeOffset(extra.data.src_node); @@ -3847,37 +3255,20 @@ fn zirAllocExtended( break :blk try sema.resolveAlign(block, align_src, align_ref); } else .none; - if (block.isComptime() or small.is_comptime) { - if (small.has_type) { - return sema.analyzeComptimeAlloc(block, var_src, var_ty, alignment); - } else { - try sema.air_instructions.append(gpa, .{ - .tag = .inferred_alloc_comptime, - .data = .{ .inferred_alloc_comptime = .{ - .alignment = alignment, - .is_const = small.is_const, - .ptr = undefined, - } }, - }); - return @as(Air.Inst.Index, @enumFromInt(sema.air_instructions.len - 1)).toRef(); - } - } - - if (small.has_type and try var_ty.comptimeOnlySema(pt)) { - return sema.analyzeComptimeAlloc(block, var_src, var_ty, alignment); - } - if (small.has_type) { + try sema.ensureLayoutResolved(var_ty); + if (block.isComptime() or small.is_comptime or var_ty.comptimeOnly(zcu)) { + return sema.analyzeComptimeAlloc(block, var_src, var_ty, alignment); + } if (!small.is_const) { try sema.validateVarType(block, ty_src, var_ty, false); } const target = pt.zcu.getTarget(); - try var_ty.resolveLayout(pt); - if (sema.func_is_naked and try var_ty.hasRuntimeBitsSema(pt)) { + if (sema.func_is_naked and var_ty.hasRuntimeBits(zcu)) { const store_src = block.src(.{ .node_offset_store_ptr = extra.data.src_node }); return sema.fail(block, store_src, "local variable in naked function", .{}); } - const ptr_type = try sema.pt.ptrTypeSema(.{ + const ptr_type = try pt.ptrType(.{ .child = var_ty.toIntern(), .flags = .{ .alignment = alignment, @@ -3893,6 +3284,19 @@ fn zirAllocExtended( return ptr; } + if (block.isComptime() or small.is_comptime) { + const iac_index: Air.Inst.Index = @enumFromInt(sema.air_instructions.len); + try sema.air_instructions.append(gpa, .{ + .tag = .inferred_alloc_comptime, + .data = .{ .inferred_alloc_comptime = .{ + .alignment = alignment, + .is_const = small.is_const, + .ptr = undefined, + } }, + }); + return iac_index.toRef(); + } + const result_index = try block.addInstAsIndex(.{ .tag = .inferred_alloc, .data = .{ .inferred_alloc = .{ @@ -3916,6 +3320,7 @@ fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); const var_src = block.nodeOffset(inst_data.src_node); const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); + try sema.ensureLayoutResolved(var_ty); return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none); } @@ -3978,7 +3383,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro return sema.makePtrConst(block, Air.internedToRef(ptr_val)); } - if (try elem_ty.comptimeOnlySema(pt)) { + if (elem_ty.comptimeOnly(zcu)) { // The value was initialized through RLS, so we didn't detect the runtime condition earlier. // TODO: source location of runtime control flow const init_src = block.src(.{ .node_offset_var_decl_init = inst_data.src_node }); @@ -4001,20 +3406,23 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, const alloc_ty = resolved_alloc_ty orelse sema.typeOf(alloc); const ptr_info = alloc_ty.ptrInfo(zcu); const elem_ty: Type = .fromInterned(ptr_info.child); + elem_ty.assertHasLayout(zcu); const alloc_inst = alloc.toIndex() orelse return null; const comptime_info = sema.maybe_comptime_allocs.fetchRemove(alloc_inst) orelse return null; const stores = comptime_info.value.stores.items(.inst); + // If the elem type is OPV, no need to faff about with `stores`; just use the OPV. + if (try elem_ty.onePossibleValue(pt)) |opv| { + return sema.finishResolveComptimeKnownAllocPtr(block, alloc_ty, opv.toIntern(), null, alloc_inst, comptime_info.value); + } + + // Since the elem type isn't OPV, there should have been at least one store. + assert(stores.len > 0); + // Since the entry existed in `maybe_comptime_allocs`, the allocation is comptime-known. // We will resolve and return its value. - // We expect to have emitted at least one store, unless the elem type is OPV. - if (stores.len == 0) { - const val = (try sema.typeHasOnePossibleValue(elem_ty)).?.toIntern(); - return sema.finishResolveComptimeKnownAllocPtr(block, alloc_ty, val, null, alloc_inst, comptime_info.value); - } - // In general, we want to create a comptime alloc of the correct type and // apply the stores to that alloc in order. However, before going to all // that effort, let's optimize for the common case of a single store. @@ -4118,7 +3526,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, const idx_val = (try sema.resolveValue(data.rhs)).?; break :blk .{ data.lhs, - .{ .elem = try idx_val.toUnsignedIntSema(pt) }, + .{ .elem = idx_val.toUnsignedInt(zcu) }, }; }, .bitcast => .{ @@ -4150,7 +3558,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, // If the payload is OPV, we must use that value instead of undef. const opt_ty = Value.fromInterned(decl_parent_ptr).typeOf(zcu).childType(zcu); const payload_ty = opt_ty.optionalChild(zcu); - const payload_val = try sema.typeHasOnePossibleValue(payload_ty) orelse try pt.undefValue(payload_ty); + const payload_val = try payload_ty.onePossibleValue(pt) orelse try pt.undefValue(payload_ty); const opt_val = try pt.intern(.{ .opt = .{ .ty = opt_ty.toIntern(), .val = payload_val.toIntern(), @@ -4163,7 +3571,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, // If the payload is OPV, we must use that value instead of undef. const eu_ty = Value.fromInterned(decl_parent_ptr).typeOf(zcu).childType(zcu); const payload_ty = eu_ty.errorUnionPayload(zcu); - const payload_val = try sema.typeHasOnePossibleValue(payload_ty) orelse try pt.undefValue(payload_ty); + const payload_val = try payload_ty.onePossibleValue(pt) orelse try pt.undefValue(payload_ty); const eu_val = try pt.intern(.{ .error_union = .{ .ty = eu_ty.toIntern(), .val = .{ .payload = payload_val.toIntern() }, @@ -4178,7 +3586,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, // The payload value will be stored later, so undef is a sufficent payload for now. const payload_ty: Type = .fromInterned(union_obj.field_types.get(&zcu.intern_pool)[idx]); const payload_val = try pt.undefValue(payload_ty); - const tag_val = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), idx); + const tag_val = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_type), idx); const store_val = try pt.unionValue(maybe_union_ty, tag_val, payload_val); try sema.storePtrVal(block, .unneeded, .fromInterned(decl_parent_ptr), store_val, maybe_union_ty); } @@ -4207,7 +3615,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, const tag_val: Value = .fromInterned(store_inst.data.bin_op.rhs.toInterned().?); const union_ty = union_ptr_val.typeOf(zcu).childType(zcu); const field_ty = union_ty.unionFieldType(tag_val, zcu).?; - if (try sema.typeHasOnePossibleValue(field_ty)) |payload_val| { + if (try field_ty.onePossibleValue(pt)) |payload_val| { const new_union_val = try pt.unionValue(union_ty, tag_val, payload_val); try sema.storePtrVal(block, .unneeded, union_ptr_val, new_union_val, union_ty); } @@ -4289,7 +3697,7 @@ fn finishResolveComptimeKnownAllocPtr( fn makePtrTyConst(sema: *Sema, ptr_ty: Type) CompileError!Type { var ptr_info = ptr_ty.ptrInfo(sema.pt.zcu); ptr_info.flags.is_const = true; - return sema.pt.ptrTypeSema(ptr_info); + return sema.pt.ptrType(ptr_info); } fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Air.Inst.Ref { @@ -4326,21 +3734,23 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I defer tracy.end(); const pt = sema.pt; + const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); const var_src = block.nodeOffset(inst_data.src_node); const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); - if (block.isComptime() or try var_ty.comptimeOnlySema(pt)) { + try sema.ensureLayoutResolved(var_ty); + if (block.isComptime() or var_ty.comptimeOnly(zcu)) { return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none); } - if (sema.func_is_naked and try var_ty.hasRuntimeBitsSema(pt)) { + if (sema.func_is_naked and var_ty.hasRuntimeBits(zcu)) { const mut_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node }); return sema.fail(block, mut_src, "local variable in naked function", .{}); } - const target = pt.zcu.getTarget(); - const ptr_type = try pt.ptrTypeSema(.{ + const target = zcu.getTarget(); + const ptr_type = try pt.ptrType(.{ .child = var_ty.toIntern(), .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, }); @@ -4356,21 +3766,24 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai defer tracy.end(); const pt = sema.pt; + const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); const var_src = block.nodeOffset(inst_data.src_node); + const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); + try sema.ensureLayoutResolved(var_ty); if (block.isComptime()) { return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none); } - if (sema.func_is_naked and try var_ty.hasRuntimeBitsSema(pt)) { + if (sema.func_is_naked and var_ty.hasRuntimeBits(zcu)) { const store_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node }); return sema.fail(block, store_src, "local variable in naked function", .{}); } try sema.validateVarType(block, ty_src, var_ty, false); - const target = pt.zcu.getTarget(); - const ptr_type = try pt.ptrTypeSema(.{ + const target = zcu.getTarget(); + const ptr_type = try pt.ptrType(.{ .child = var_ty.toIntern(), .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, }); @@ -4430,8 +3843,9 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com switch (sema.air_instructions.items(.tag)[@intFromEnum(ptr_inst)]) { .inferred_alloc_comptime => { - // The work was already done for us by `Sema.storeToInferredAllocComptime`. - // All we need to do is return the pointer. + // The work was already done for us by `Sema.storeToInferredAllocComptime`. Also, since + // we had a value of the exact correct type to store, the result type's layout must be + // already resolved. So all we need to do here is return the pointer. const iac = sema.air_instructions.items(.data)[@intFromEnum(ptr_inst)].inferred_alloc_comptime; const resolved_ptr = iac.ptr; @@ -4450,7 +3864,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com }; if (zcu.intern_pool.isFuncBody(val)) { const ty: Type = .fromInterned(zcu.intern_pool.typeOf(val)); - if (try ty.fnHasRuntimeBitsSema(pt)) { + if (ty.fnHasRuntimeBits(zcu)) { const orig_fn_index = zcu.intern_pool.unwrapCoercedFunc(val); try sema.addReferenceEntry(block, src, .wrap(.{ .func = orig_fn_index })); try zcu.ensureFuncBodyAnalysisQueued(orig_fn_index); @@ -4469,8 +3883,10 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com peer_val.* = bin_op.rhs; } const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_vals, .none); + // The layout of the peers is already resolved, so the layout of `final_elem_ty` is too. + final_elem_ty.assertHasLayout(zcu); - const final_ptr_ty = try pt.ptrTypeSema(.{ + const final_ptr_ty = try pt.ptrType(.{ .child = final_elem_ty.toIntern(), .flags = .{ .alignment = ia1.alignment, @@ -4484,21 +3900,16 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com const const_ptr_ty = try sema.makePtrTyConst(final_ptr_ty); const new_const_ptr = try pt.getCoerced(Value.fromInterned(ptr_val), const_ptr_ty); - // Unless the block is comptime, `alloc_inferred` always produces - // a runtime constant. The final inferred type needs to be - // fully resolved so it can be lowered in codegen. - try final_elem_ty.resolveFully(pt); - return Air.internedToRef(new_const_ptr.toIntern()); } - if (try final_elem_ty.comptimeOnlySema(pt)) { + if (final_elem_ty.comptimeOnly(zcu)) { // The alloc wasn't comptime-known per the above logic, so the // type cannot be comptime-only. // TODO: source location of runtime control flow return sema.fail(block, src, "value with comptime-only type '{f}' depends on runtime control flow", .{final_elem_ty.fmt(pt)}); } - if (sema.func_is_naked and try final_elem_ty.hasRuntimeBitsSema(pt)) { + if (sema.func_is_naked and final_elem_ty.hasRuntimeBits(zcu)) { const mut_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node }); return sema.fail(block, mut_src, "local variable in naked function", .{}); } @@ -4812,7 +4223,7 @@ fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: boo if (is_ref) { var ptr_info = operand_ty.ptrInfo(zcu); ptr_info.child = eu_ty.toIntern(); - const eu_ptr_ty = try pt.ptrTypeSema(ptr_info); + const eu_ptr_ty = try pt.ptrType(ptr_info); return Air.internedToRef(eu_ptr_ty.toIntern()); } else { return Air.internedToRef(eu_ty.toIntern()); @@ -4935,7 +4346,6 @@ fn validateArrayInitTy( return; }, .@"struct" => if (ty.isTuple(zcu)) { - try ty.resolveFields(pt); const array_len = ty.arrayLen(zcu); if (init_count > array_len) { return sema.fail(block, src, "expected at most {d} tuple fields; found {d}", .{ @@ -5097,12 +4507,16 @@ fn validateStructInit( errdefer if (root_msg) |msg| msg.destroy(sema.gpa); for (found_fields, 0..) |explicit, i_usize| { + const i: u32 = @intCast(i_usize); + if (explicit) continue; - const i: u32 = @intCast(i_usize); + if (struct_ty.structFieldIsComptime(i, zcu)) continue; - try struct_ty.resolveStructFieldInits(pt); - const default_val = struct_ty.structFieldDefaultValue(i, zcu); - if (default_val.toIntern() == .unreachable_value) { + if (!struct_ty.isTuple(zcu)) { + try sema.ensureFieldInitsResolved(struct_ty); + } + + const default_val = struct_ty.structFieldDefaultValue(i, zcu) orelse { const field_name = struct_ty.structFieldName(i, zcu).unwrap() orelse { const template = "missing tuple field with index {d}"; if (root_msg) |msg| { @@ -5120,7 +4534,7 @@ fn validateStructInit( root_msg = try sema.errMsg(init_src, template, args); } continue; - } + }; const field_src = init_src; // TODO better source location const default_field_ptr = if (struct_ty.isTuple(zcu)) @@ -5166,11 +4580,9 @@ fn zirValidatePtrArrayInit( var root_msg: ?*Zcu.ErrorMsg = null; errdefer if (root_msg) |msg| msg.destroy(sema.gpa); - try array_ty.resolveStructFieldInits(pt); var i = instrs.len; while (i < array_len) : (i += 1) { - const default_val = array_ty.structFieldDefaultValue(i, zcu).toIntern(); - if (default_val == .unreachable_value) { + if (array_ty.structFieldDefaultValue(i, zcu) == null) { const template = "missing tuple field with index {d}"; if (root_msg) |msg| { try sema.errNote(init_src, msg, template, .{i}); @@ -5224,17 +4636,19 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr .slice => return sema.fail(block, src, "index syntax required for slice type '{f}'", .{operand_ty.fmt(pt)}), } - if ((try sema.typeHasOnePossibleValue(operand_ty.childType(zcu))) != null) { + const elem_ty = operand_ty.childType(zcu); + try sema.ensureLayoutResolved(elem_ty); + + if (try elem_ty.onePossibleValue(pt) != null) { // No need to validate the actual pointer value, we don't need it! return; } - const elem_ty = operand_ty.elemType2(zcu); if (try sema.resolveValue(operand)) |val| { if (val.isUndef(zcu)) { return sema.fail(block, src, "cannot dereference undefined value", .{}); } - } else if (try elem_ty.comptimeOnlySema(pt)) { + } else if (elem_ty.comptimeOnly(zcu)) { const msg = msg: { const msg = try sema.errMsg( src, @@ -5373,7 +4787,7 @@ fn failWithBadUnionFieldAccess( return sema.failWithOwnedErrorMsg(block, msg); } -fn addDeclaredHereNote(sema: *Sema, parent: *Zcu.ErrorMsg, decl_ty: Type) !void { +pub fn addDeclaredHereNote(sema: *Sema, parent: *Zcu.ErrorMsg, decl_ty: Type) !void { const zcu = sema.pt.zcu; const src_loc = decl_ty.srcLocOrNull(zcu) orelse return; const category = switch (decl_ty.zigTypeTag(zcu)) { @@ -5443,14 +4857,16 @@ fn storeToInferredAllocComptime( const operand_val = try sema.resolveValue(operand) orelse { return sema.failWithNeededComptime(block, src, .{ .simple = .stored_to_comptime_var }); }; - const alloc_ty = try pt.ptrTypeSema(.{ + const alloc_ty = try pt.ptrType(.{ .child = operand_ty.toIntern(), .flags = .{ .alignment = iac.alignment, .is_const = iac.is_const, }, }); - if (iac.is_const and !operand_val.canMutateComptimeVarState(zcu)) { + if (try operand_ty.onePossibleValue(pt) != null or + (iac.is_const and !operand_val.canMutateComptimeVarState(zcu))) + { iac.ptr = try pt.intern(.{ .ptr = .{ .ty = alloc_ty.toIntern(), .base_addr = .{ .uav = .{ @@ -5624,7 +5040,7 @@ fn zirCompileLog( const arg = try sema.resolveInst(arg_ref); const arg_ty = sema.typeOf(arg); - if (try sema.resolveValueResolveLazy(arg)) |val| { + if (try sema.resolveValue(arg)) |val| { writer.print("@as({f}, {f})", .{ arg_ty.fmt(pt), val.fmtValueSema(pt, sema), }) catch return error.OutOfMemory; @@ -5928,10 +5344,9 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); try pt.ensureFileAnalyzed(new_file_index); - const ty = zcu.fileRootType(new_file_index); - try sema.declareDependency(.{ .interned = ty }); + const ty: Type = .fromInterned(zcu.fileRootType(new_file_index)); try sema.addTypeReferenceEntry(src, ty); - return Air.internedToRef(ty); + return .fromType(ty); } fn zirSuspendBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -6177,10 +5592,11 @@ fn resolveAnalyzedBlock( // to emit a jump instruction to after the block when it encounters the break. try parent_block.instructions.append(gpa, merges.block_inst); const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items, .{ .override = merges.src_locs.items }); + resolved_ty.assertHasLayout(zcu); // TODO add note "missing else causes void value" const type_src = src; // TODO: better source location - if (try resolved_ty.comptimeOnlySema(pt)) { + if (resolved_ty.comptimeOnly(zcu)) { const msg = msg: { const msg = try sema.errMsg(type_src, "value with comptime-only type '{f}' depends on runtime control flow", .{resolved_ty.fmt(pt)}); errdefer msg.destroy(sema.gpa); @@ -6274,10 +5690,7 @@ fn resolveAnalyzedBlock( }); } - if (try sema.typeHasOnePossibleValue(resolved_ty)) |block_only_value| { - return Air.internedToRef(block_only_value.toIntern()); - } - + if (try resolved_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); return merges.block_inst.toRef(); } @@ -6413,7 +5826,8 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void { .@"comptime", .nav_val, .nav_ty, - .type, + .type_layout, + .type_inits, .memoized_state, => return, // does nothing outside a function }; @@ -6431,7 +5845,8 @@ fn zirDisableIntrinsics(sema: *Sema) CompileError!void { .@"comptime", .nav_val, .nav_ty, - .type, + .type_layout, + .type_inits, .memoized_state, => return, // does nothing outside a function }; @@ -6589,8 +6004,8 @@ fn addDbgVar( .dbg_var_val, .dbg_arg_inline => operand_ty, else => unreachable, }; - if (try val_ty.comptimeOnlySema(pt)) return; - if (!(try val_ty.hasRuntimeBitsSema(pt))) return; + if (val_ty.comptimeOnly(zcu)) return; + if (!val_ty.hasRuntimeBits(zcu)) return; if (try sema.resolveValue(operand)) |operand_val| { if (operand_val.canMutateComptimeVarState(zcu)) return; } @@ -6759,7 +6174,6 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref if (!block.ownerModule().error_tracing) return .none; const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace); - try stack_trace_ty.resolveFields(pt); const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) { error.AnalysisFail => @panic("std.builtin.StackTrace is corrupt"), @@ -6803,7 +6217,6 @@ fn popErrorReturnTrace( // the result is comptime-known to be a non-error. Either way, pop unconditionally. const stack_trace_ty = try sema.getBuiltinType(src, .StackTrace); - try stack_trace_ty.resolveFields(pt); const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty); const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); @@ -6829,7 +6242,6 @@ fn popErrorReturnTrace( // If non-error, then pop the error return trace by restoring the index. const stack_trace_ty = try sema.getBuiltinType(src, .StackTrace); - try stack_trace_ty.resolveFields(pt); const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); const err_return_trace = try then_block.addTy(.err_return_trace, ptr_stack_trace_ty); const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); @@ -6969,7 +6381,6 @@ fn zirCall( // need to clean-up our own trace if we were passed to a non-error-handling expression. if (input_is_error or (pop_error_return_trace and return_ty.isError(zcu))) { const stack_trace_ty = try sema.getBuiltinType(call_src, .StackTrace); - try stack_trace_ty.resolveFields(pt); const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); const field_index = try sema.structFieldIndex(block, stack_trace_ty, field_name, call_src); @@ -7318,6 +6729,8 @@ fn analyzeCall( } else func_src; const func_ty_info = zcu.typeToFunc(func_ty).?; + // MLUGG TODO: this isn't quite the check i want. this includes inline functions, which aren't *generic*... + const func_is_generic = !func_ty.fnHasRuntimeBits(zcu); if (!callConvIsCallable(func_ty_info.cc)) { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg( @@ -7353,7 +6766,7 @@ fn analyzeCall( else => unreachable, } else .{ null, false }; - if (func_ty_info.is_generic and func_val == null) { + if (func_is_generic and func_val == null) { return sema.failWithNeededComptime(block, func_src, .{ .simple = .generic_call_target }); } @@ -7369,19 +6782,18 @@ fn analyzeCall( .src = call_src, .r = .{ .simple = .comptime_call_modifier }, } }; - } else if (!inline_requested and try Type.fromInterned(func_ty_info.return_type).comptimeOnlySema(pt)) { - block.comptime_reason = .{ - .reason = .{ + } else if (!inline_requested) { + const ret_ty: Type = .fromInterned(func_ty_info.return_type); + if (ret_ty.comptimeOnly(zcu)) { + block.comptime_reason = .{ .reason = .{ .src = call_src, - .r = .{ - .comptime_only_ret_ty = .{ - .ty = .fromInterned(func_ty_info.return_type), - .is_generic_inst = false, - .ret_ty_src = func_ret_ty_src, - }, - }, - }, - }; + .r = .{ .comptime_only_ret_ty = .{ + .ty = .fromInterned(func_ty_info.return_type), + .is_generic_inst = false, + .ret_ty_src = func_ret_ty_src, + } }, + } }; + } } } @@ -7403,13 +6815,13 @@ fn analyzeCall( // This is the `inst_map` used when evaluating generic parameters and return types. var generic_inst_map: InstMap = .{}; defer generic_inst_map.deinit(gpa); - if (func_ty_info.is_generic) { + if (func_is_generic) { try generic_inst_map.ensureSpaceForInstructions(gpa, fn_zir_info.param_body); } // This exists so that `generic_block` below can include a "called from here" note back to this // call site when analyzing generic parameter/return types. - var generic_inlining: Block.Inlining = if (func_ty_info.is_generic) .{ + var generic_inlining: Block.Inlining = if (func_is_generic) .{ .call_block = block, .call_src = call_src, .func = func_val.?.toIntern(), @@ -7422,7 +6834,7 @@ fn analyzeCall( // This is the block in which we evaluate generic function components: that is, generic parameter // types and the generic return type. This must not be used if the function is not generic. // `comptime_reason` is set as needed. - var generic_block: Block = if (func_ty_info.is_generic) .{ + var generic_block: Block = if (func_is_generic) .{ .parent = null, .sema = sema, .namespace = fn_nav.analysis.?.namespace, @@ -7431,9 +6843,9 @@ fn analyzeCall( .src_base_inst = fn_nav.analysis.?.zir_index, .type_name_ctx = fn_nav.fqn, } else undefined; - defer if (func_ty_info.is_generic) generic_block.instructions.deinit(gpa); + defer if (func_is_generic) generic_block.instructions.deinit(gpa); - if (func_ty_info.is_generic) { + if (func_is_generic) { // We certainly depend on the generic owner's signature! try sema.declareDependency(.{ .src_hash = fn_tracked_inst }); } @@ -7445,7 +6857,7 @@ fn analyzeCall( if (raw != .generic_poison_type) break :ty .fromInterned(raw); // We must discover the generic parameter type. - assert(func_ty_info.is_generic); + assert(func_is_generic); const param_inst_idx = fn_zir_info.param_body[arg_idx]; const param_inst = fn_zir.instructions.get(@intFromEnum(param_inst_idx)); switch (param_inst.tag) { @@ -7494,11 +6906,11 @@ fn analyzeCall( return arg.*; // terminate analysis here } - if (func_ty_info.is_generic) { + if (func_is_generic) { // We need to put the argument into `generic_inst_map` so that other parameters can refer to it. const param_inst_idx = fn_zir_info.param_body[arg_idx]; const declared_comptime = if (std.math.cast(u5, arg_idx)) |i| func_ty_info.paramIsComptime(i) else false; - const param_is_comptime = declared_comptime or try arg_ty.comptimeOnlySema(pt); + const param_is_comptime = declared_comptime or arg_ty.comptimeOnly(zcu); // We allow comptime-known arguments to propagate to generic types not only for comptime // parameters, but if the call is known to be inline. if (param_is_comptime or early_known_inline) { @@ -7516,6 +6928,10 @@ fn analyzeCall( ); } generic_inst_map.putAssumeCapacityNoClobber(param_inst_idx, arg.*); + } else if (try arg_ty.onePossibleValue(pt)) |opv| { + // The argument is comptime-known, even though this is a generic instantiation (as + // opposed to an inline call), because the parameter type is OPV. + generic_inst_map.putAssumeCapacityNoClobber(param_inst_idx, .fromValue(opv)); } else { // We need a dummy instruction with this type. It doesn't actually need to be in any block, // since it will never be referenced at runtime! @@ -7532,7 +6948,7 @@ fn analyzeCall( // calls (where it should be the IES of the instantiation). However, it's how we print this // in error messages. const resolved_ret_ty: Type = ret_ty: { - if (!func_ty_info.is_generic) break :ret_ty .fromInterned(func_ty_info.return_type); + if (!func_is_generic) break :ret_ty .fromInterned(func_ty_info.return_type); const maybe_poison_bare = if (fn_zir_info.inferred_error_set) maybe_poison: { break :maybe_poison ip.errorUnionPayload(func_ty_info.return_type); @@ -7542,7 +6958,7 @@ fn analyzeCall( // Evaluate the generic return type. As with generic parameters, we switch out `sema.code` and `sema.inst_map`. - assert(func_ty_info.is_generic); + assert(func_is_generic); const old_code = sema.code; const old_inst_map = sema.inst_map; @@ -7584,10 +7000,11 @@ fn analyzeCall( break :ret_ty full_ty; }; + try sema.ensureLayoutResolved(resolved_ret_ty); // If we've discovered after evaluating arguments that a generic function instantiation is // comptime-only, then we can mark the block as comptime *now*. - if (!inline_requested and !block.isComptime() and try resolved_ret_ty.comptimeOnlySema(pt)) { + if (!inline_requested and !block.isComptime() and resolved_ret_ty.comptimeOnly(zcu)) { block.comptime_reason = .{ .reason = .{ .src = call_src, @@ -7618,7 +7035,7 @@ fn analyzeCall( }); if (func_ty_info.cc == .auto) { switch (sema.owner.unwrap()) { - .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {}, + .@"comptime", .nav_ty, .nav_val, .type_layout, .type_inits, .memoized_state => {}, .func => |owner_func| ip.funcSetHasErrorTrace(io, owner_func, true), } } @@ -7626,7 +7043,7 @@ fn analyzeCall( try sema.validateRuntimeValue(block, args_info.argSrc(block, arg_idx), arg); } const runtime_func: Air.Inst.Ref, const runtime_args: []const Air.Inst.Ref = func: { - if (!func_ty_info.is_generic) break :func .{ callee, args }; + if (!func_is_generic) break :func .{ callee, args }; // Instantiate the generic function! @@ -7648,7 +7065,7 @@ fn analyzeCall( break :c true; } } - break :c try arg_ty.comptimeOnlySema(pt); + break :c arg_ty.comptimeOnly(zcu); }; const is_noalias = if (std.math.cast(u5, arg_idx)) |i| func_ty_info.paramIsNoalias(i) else false; @@ -7680,6 +7097,7 @@ fn analyzeCall( .generic_owner = func_val.?.toIntern(), .comptime_args = comptime_args, }); + try sema.ensureLayoutResolved(.fromInterned(ip.typeOf(func_instance))); if (zcu.comp.debugIncremental()) { const nav = ip.indexToKey(func_instance).func.owner_nav; const gop = try zcu.incremental_debug_state.navs.getOrPut(gpa, nav); @@ -7753,12 +7171,12 @@ fn analyzeCall( return .unreachable_value; } - const result: Air.Inst.Ref = if (try sema.typeHasOnePossibleValue(sema.typeOf(maybe_opv))) |opv| - .fromValue(opv) - else - maybe_opv; - - return result; + try sema.ensureLayoutResolved(sema.typeOf(maybe_opv)); + if (try sema.typeOf(maybe_opv).onePossibleValue(pt)) |opv| { + return .fromValue(opv); + } else { + return maybe_opv; + } } // This is an inline call. The function must be comptime-known. We will analyze its body directly using this `Sema`. @@ -7824,6 +7242,11 @@ fn analyzeCall( } } + // We're about to do an inline call; if the return type expression was generic, the return type + // may not be resolved yet. It's correct to resolve it because the function is going to return a + // value of this type. + try sema.ensureLayoutResolved(resolved_ret_ty); + // For an inline call, we depend on the source code of the whole function definition. try sema.declareDependency(.{ .src_hash = fn_nav.analysis.?.zir_index }); @@ -8000,6 +7423,10 @@ fn analyzeCall( break :result try sema.resolveAnalyzedBlock(block, call_src, &child_block, &inlining.merges, need_debug_scope); }; + if (sema.typeOf(result_raw).isNoReturn(zcu)) { + return .unreachable_value; + } + const maybe_opv: Air.Inst.Ref = if (try sema.resolveValue(result_raw)) |result_val| r: { const val_resolved = try sema.resolveAdHocInferredErrorSet(block, call_src, result_val.toIntern()); break :r Air.internedToRef(val_resolved); @@ -8080,16 +7507,16 @@ fn zirArrayInitElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil const zcu = pt.zcu; const bin = sema.code.instructions.items(.data)[@intFromEnum(inst)].bin; const maybe_wrapped_indexable_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, bin.lhs) orelse return .generic_poison_type; + try sema.ensureLayoutResolved(maybe_wrapped_indexable_ty); const indexable_ty = maybe_wrapped_indexable_ty.optEuBaseType(zcu); - try indexable_ty.resolveFields(pt); assert(indexable_ty.isIndexable(zcu)); // validated by a previous instruction - if (indexable_ty.zigTypeTag(zcu) == .@"struct") { - const elem_type = indexable_ty.fieldType(@intFromEnum(bin.rhs), zcu); - return Air.internedToRef(elem_type.toIntern()); - } else { - const elem_type = indexable_ty.elemType2(zcu); - return Air.internedToRef(elem_type.toIntern()); - } + const elem_ty = switch (indexable_ty.zigTypeTag(zcu)) { + .@"struct" => indexable_ty.fieldType(@intFromEnum(bin.rhs), zcu), + .array, .vector => indexable_ty.childType(zcu), + .pointer => indexable_ty.indexablePtrElem(zcu), + else => unreachable, + }; + return .fromType(elem_ty); } fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -8355,7 +7782,7 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD const operand = try sema.coerce(block, err_int_ty, uncasted_operand, operand_src); if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| { - const int = try sema.usizeCast(block, operand_src, try value.toUnsignedIntSema(pt)); + const int = try sema.usizeCast(block, operand_src, value.toUnsignedInt(zcu)); if (int > len: { const mutate = &ip.global_error_set.mutate; mutate.map.mutex.lockUncancelable(io); @@ -8539,7 +7966,6 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const enum_tag: Air.Inst.Ref = switch (operand_ty.zigTypeTag(zcu)) { .@"enum" => operand, .@"union" => blk: { - try operand_ty.resolveFields(pt); const tag_ty = operand_ty.unionTagType(zcu) orelse { return sema.fail( block, @@ -8568,17 +7994,9 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError }); } - if (try sema.typeHasOnePossibleValue(enum_tag_ty)) |opv| { - return Air.internedToRef((try pt.getCoerced(opv, int_tag_ty)).toIntern()); - } - if (try sema.resolveValue(enum_tag)) |enum_tag_val| { - if (enum_tag_val.isUndef(zcu)) { - return pt.undefRef(int_tag_ty); - } - - const val = try enum_tag_val.intFromEnum(enum_tag_ty, pt); - return Air.internedToRef(val.toIntern()); + if (enum_tag_val.isUndef(zcu)) return pt.undefRef(int_tag_ty); + return .fromValue(enum_tag_val.intFromEnum(zcu)); } try sema.requireRuntimeBlock(block, src, operand_src); @@ -8626,19 +8044,15 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError return sema.failWithNeededComptime(block, operand_src, .{ .simple = .casted_to_comptime_enum }); } - if (try sema.typeHasOnePossibleValue(dest_ty)) |opv| { + if (try dest_ty.onePossibleValue(pt)) |opv| { if (block.wantSafety()) { // The operand is runtime-known but the result is comptime-known. In // this case we still need a safety check. - const expect_int_val = switch (zcu.intern_pool.indexToKey(opv.toIntern())) { - .enum_tag => |enum_tag| enum_tag.int, - else => unreachable, - }; - const expect_int_coerced = try pt.getCoerced(.fromInterned(expect_int_val), operand_ty); - const ok = try block.addBinOp(.cmp_eq, operand, Air.internedToRef(expect_int_coerced.toIntern())); + const expect_int = try pt.getCoerced(opv.intFromEnum(zcu), operand_ty); + const ok = try block.addBinOp(.cmp_eq, operand, .fromValue(expect_int)); try sema.addSafetyCheck(block, src, ok, .invalid_enum_value); } - return Air.internedToRef(opv.toIntern()); + return .fromValue(opv); } try sema.requireRuntimeBlock(block, src, operand_src); @@ -8666,6 +8080,7 @@ fn zirOptionalPayloadPtr( return sema.analyzeOptionalPayloadPtr(block, src, optional_ptr, safety_check, false); } +/// MLUGG TODO: pre-resolved child? fn analyzeOptionalPayloadPtr( sema: *Sema, block: *Block, @@ -8685,7 +8100,8 @@ fn analyzeOptionalPayloadPtr( } const child_type = opt_type.optionalChild(zcu); - const child_pointer = try pt.ptrTypeSema(.{ + try sema.ensureLayoutResolved(child_type); + const child_pointer = try pt.ptrType(.{ .child = child_type.toIntern(), .flags = .{ .is_const = optional_ptr_ty.isConstPtr(zcu), @@ -8698,7 +8114,7 @@ fn analyzeOptionalPayloadPtr( if (sema.isComptimeMutablePtr(ptr_val)) { // Set the optional to non-null at comptime. // If the payload is OPV, we must use that value instead of undef. - const payload_val = try sema.typeHasOnePossibleValue(child_type) orelse try pt.undefValue(child_type); + const payload_val = try child_type.onePossibleValue(pt) orelse try pt.undefValue(child_type); const opt_val = try pt.intern(.{ .opt = .{ .ty = opt_type.toIntern(), .val = payload_val.toIntern(), @@ -8759,7 +8175,7 @@ fn zirOptionalPayload( // TODO https://github.com/ziglang/zig/issues/6597 if (true) break :t operand_ty; const ptr_info = operand_ty.ptrInfo(zcu); - break :t try pt.ptrTypeSema(.{ + break :t try pt.ptrType(.{ .child = ptr_info.child, .flags = .{ .alignment = ptr_info.flags.alignment, @@ -8784,11 +8200,14 @@ fn zirOptionalPayload( return .unreachable_value; } - try sema.requireRuntimeBlock(block, src, null); if (safety_check and block.wantSafety()) { const is_non_null = try block.addUnOp(.is_non_null, operand); try sema.addSafetyCheck(block, src, is_non_null, .unwrap_null); } + + // If the payload is OPV, we need the safety check but have a comptime-known result. + if (try result_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); + return block.addTyOp(.optional_payload, result_ty, operand); } @@ -8844,8 +8263,8 @@ fn analyzeErrUnionPayload( try sema.addSafetyCheckUnwrapError(block, src, operand, .unwrap_errunion_err, .is_non_err); } - if (try sema.typeHasOnePossibleValue(payload_ty)) |payload_only_value| { - return Air.internedToRef(payload_only_value.toIntern()); + if (try payload_ty.onePossibleValue(pt)) |payload_opv| { + return .fromValue(payload_opv); } return block.addTyOp(.unwrap_errunion_payload, payload_ty, operand); @@ -8867,6 +8286,7 @@ fn zirErrUnionPayloadPtr( return sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false); } +/// MLUGG TODO LAYOUT: already-resolved child? fn analyzeErrUnionPayloadPtr( sema: *Sema, block: *Block, @@ -8888,7 +8308,8 @@ fn analyzeErrUnionPayloadPtr( const err_union_ty = operand_ty.childType(zcu); const payload_ty = err_union_ty.errorUnionPayload(zcu); - const operand_pointer_ty = try pt.ptrTypeSema(.{ + try sema.ensureLayoutResolved(payload_ty); + const operand_pointer_ty = try pt.ptrType(.{ .child = payload_ty.toIntern(), .flags = .{ .is_const = operand_ty.isConstPtr(zcu), @@ -8901,7 +8322,7 @@ fn analyzeErrUnionPayloadPtr( if (sema.isComptimeMutablePtr(ptr_val)) { // Set the error union to non-error at comptime. // If the payload is OPV, we must use that value instead of undef. - const payload_val = try sema.typeHasOnePossibleValue(payload_ty) orelse try pt.undefValue(payload_ty); + const payload_val = try payload_ty.onePossibleValue(pt) orelse try pt.undefValue(payload_ty); const eu_val = try pt.intern(.{ .error_union = .{ .ty = err_union_ty.toIntern(), .val = .{ .payload = payload_val.toIntern() }, @@ -9571,10 +8992,6 @@ fn funcCommon( const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = src_node_offset }); const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset }); - const func_src = block.nodeOffset(src_node_offset); - - const ret_ty_requires_comptime = try bare_return_type.comptimeOnlySema(pt); - var is_generic = bare_return_type.isGenericPoison() or ret_ty_requires_comptime; var comptime_bits: u32 = 0; for (block.params.items(.ty), block.params.items(.is_comptime), 0..) |param_ty_ip, param_is_comptime, i| { @@ -9587,11 +9004,7 @@ fn funcCommon( .fn_proto_node_offset = src_node_offset, .param_index = @intCast(i), } }); - const param_ty_comptime = try param_ty.comptimeOnlySema(pt); const param_ty_generic = param_ty.isGenericPoison(); - if (param_is_comptime or param_ty_comptime or param_ty_generic) { - is_generic = true; - } if (param_is_comptime) { comptime_bits |= @as(u32, 1) << @intCast(i); // TODO: handle cast error } @@ -9609,24 +9022,6 @@ fn funcCommon( param_src, cc, ); - if (param_ty_comptime and !param_is_comptime and has_body and !block.isComptime()) { - const msg = msg: { - const msg = try sema.errMsg(param_src, "parameter of type '{f}' must be declared comptime", .{ - param_ty.fmt(pt), - }); - errdefer msg.destroy(sema.gpa); - - try sema.explainWhyTypeIsComptime(msg, param_src, param_ty); - - try sema.addDeclaredHereNote(msg, param_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); - } - } - - if (var_args and is_generic) { - return sema.fail(block, func_src, "generic function cannot be variadic", .{}); } try sema.checkReturnTypeAndCallConvCommon( @@ -9643,46 +9038,6 @@ fn funcCommon( is_noinline, ); - // If the return type is comptime-only but not dependent on parameters then - // all parameter types also need to be comptime. - if (has_body and ret_ty_requires_comptime and !block.isComptime()) comptime_check: { - for (block.params.items(.is_comptime)) |is_comptime| { - if (!is_comptime) break; - } else break :comptime_check; - const ies_ret_ty_prefix: []const u8 = if (inferred_error_set) "!" else ""; - const msg = try sema.errMsg( - ret_ty_src, - "function with comptime-only return type '{s}{f}' requires all parameters to be comptime", - .{ ies_ret_ty_prefix, bare_return_type.fmt(pt) }, - ); - errdefer msg.destroy(sema.gpa); - try sema.explainWhyTypeIsComptime(msg, ret_ty_src, bare_return_type); - - const tags = sema.code.instructions.items(.tag); - const data = sema.code.instructions.items(.data); - const param_body = sema.code.getParamBody(func_inst); - for ( - block.params.items(.is_comptime), - block.params.items(.name), - param_body[0..block.params.len], - ) |is_comptime, name_nts, param_index| { - if (!is_comptime) { - const param_src = block.tokenOffset(switch (tags[@intFromEnum(param_index)]) { - .param => data[@intFromEnum(param_index)].pl_tok.src_tok, - .param_anytype => data[@intFromEnum(param_index)].str_tok.src_tok, - else => unreachable, - }); - const name = sema.code.nullTerminatedString(name_nts); - if (name.len != 0) { - try sema.errNote(param_src, msg, "param '{s}' is required to be comptime", .{name}); - } else { - try sema.errNote(param_src, msg, "param is required to be comptime", .{}); - } - } - } - return sema.failWithOwnedErrorMsg(block, msg); - } - const param_types = block.params.items(.ty); if (inferred_error_set) { @@ -9696,7 +9051,6 @@ fn funcCommon( .bare_return_type = bare_return_type.toIntern(), .cc = cc, .is_var_args = var_args, - .is_generic = is_generic, .is_noinline = is_noinline, .zir_body_inst = try block.trackZir(func_inst), @@ -9714,7 +9068,6 @@ fn funcCommon( .return_type = bare_return_type.toIntern(), .cc = cc, .is_var_args = var_args, - .is_generic = is_generic, .is_noinline = is_noinline, }); @@ -9845,16 +9198,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! if (!ptr_ty.isPtrAtRuntime(zcu)) { return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{ptr_ty.fmt(pt)}); } - const pointee_ty = ptr_ty.childType(zcu); - if (try ptr_ty.comptimeOnlySema(pt)) { - const msg = msg: { - const msg = try sema.errMsg(ptr_src, "comptime-only type '{f}' has no pointer address", .{pointee_ty.fmt(pt)}); - errdefer msg.destroy(sema.gpa); - try sema.explainWhyTypeIsComptime(msg, ptr_src, pointee_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); - } + const len = if (is_vector) operand_ty.vectorLen(zcu) else undefined; const dest_ty: Type = if (is_vector) try pt.vectorType(.{ .child = .usize_type, .len = len }) else .usize; @@ -9863,7 +9207,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! if (operand_val.isUndef(zcu)) { return .undef_usize; } - const addr = try operand_val.getUnsignedIntSema(pt) orelse { + const addr = operand_val.getUnsignedInt(zcu) orelse { // Wasn't an integer pointer. This is a runtime operation. break :ct; }; @@ -9879,7 +9223,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! new_elem.* = .undef_usize; continue; } - const addr = try ptr_val.getUnsignedIntSema(pt) orelse { + const addr = ptr_val.getUnsignedInt(zcu) orelse { // A vector element wasn't an integer pointer. This is a runtime operation. break :ct; }; @@ -10044,7 +9388,7 @@ fn intCast( try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, dest_ty_src, operand_src); const is_vector = dest_ty.zigTypeTag(zcu) == .vector; - if ((try sema.typeHasOnePossibleValue(dest_ty))) |opv| { + if (try dest_ty.onePossibleValue(pt)) |opv| { // requirement: intCast(u0, input) iff input == 0 if (block.wantSafety()) { try sema.requireRuntimeBlock(block, src, operand_src); @@ -10382,6 +9726,8 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air }; return sema.failWithOwnedErrorMsg(block, msg); } + try sema.checkIndexable(block, src, indexable_ty); + try sema.ensureLayoutResolved(indexable_ty.childType(zcu)); return sema.elemPtrOneLayerOnly(block, src, array_ptr, elem_index, src, false, false); } @@ -10764,7 +10110,8 @@ fn analyzeSwitchBlock( .{ raw_operand, .none }; const operand_ty = sema.typeOf(val); - const maybe_operand_opv = try sema.typeHasOnePossibleValue(operand_ty); + operand_ty.assertHasLayout(zcu); + const maybe_operand_opv = try operand_ty.onePossibleValue(pt); const init_cond: Air.Inst.Ref, const item_ty: Type = switch (operand_ty.zigTypeTag(zcu)) { .@"union" => tag: { const tag_ty = operand_ty.unionTagType(zcu).?; @@ -10776,6 +10123,7 @@ fn analyzeSwitchBlock( operand_ty, }, }; + item_ty.assertHasLayout(zcu); if (zir_switch.has_continue and !block.isComptime()) { const operand_alloc: Air.Inst.Ref = if (zir_switch.any_maybe_runtime_capture and @@ -10881,7 +10229,7 @@ fn analyzeSwitchBlock( unreachable; } - if (try sema.typeHasOnePossibleValue(item_ty)) |item_opv| { + if (try item_ty.onePossibleValue(pt)) |item_opv| { // We simplify conditions with OPV to either a `loop` or a `block` since // we cannot switch on a value which doesn't exist at runtime. assert(operand == .loop); // `simple` should have already been comptime-resolved above! @@ -11249,8 +10597,8 @@ fn finishSwitchBr( var item = sema.resolveConstDefinedValue(block, .unneeded, range_ref[0], undefined) catch unreachable; const item_last = sema.resolveConstDefinedValue(block, .unneeded, range_ref[1], undefined) catch unreachable; - if (try item.getUnsignedIntSema(pt)) |first_int| { - if (try item_last.getUnsignedIntSema(pt)) |last_int| { + if (item.getUnsignedInt(zcu)) |first_int| { + if (item_last.getUnsignedInt(zcu)) |last_int| { if (std.math.cast(u32, last_int - first_int)) |range_len| { try branch_hints.ensureUnusedCapacity(gpa, range_len); } @@ -11259,7 +10607,6 @@ fn finishSwitchBr( var prev_result_overflowed = false; while (item.compareScalar(.lte, item_last, operand_ty, zcu)) : ({ - // Previous validation has resolved any possible lazy values. const int_val: Value, const int_ty: Type = switch (operand_ty.zigTypeTag(zcu)) { .int => .{ item, operand_ty }, .@"enum" => b: { @@ -11896,72 +11243,68 @@ fn validateSwitchBlock( try sema.inst_map.ensureSpaceForInstructions(gpa, &.{tag_capture_inst}); } - const operand_ty: Type, const item_ty: Type = check_operand: { - const operand_ty = operand_ty: { - const raw_operand_ty = sema.typeOf(raw_operand); - if (operand_is_ref) { - try sema.checkPtrType(block, operand_src, raw_operand_ty, false); - break :operand_ty raw_operand_ty.childType(zcu); - } - break :operand_ty raw_operand_ty; - }; - - const item_ty: Type = item_ty: { - switch (operand_ty.zigTypeTag(zcu)) { - .@"enum", - .error_set, - .int, - .comptime_int, - .type, - .enum_literal, - .@"fn", - .bool, - .void, - => break :item_ty operand_ty, + const operand_ty = operand_ty: { + const raw_operand_ty = sema.typeOf(raw_operand); + if (operand_is_ref) { + try sema.checkPtrType(block, operand_src, raw_operand_ty, false); + break :operand_ty raw_operand_ty.childType(zcu); + } + break :operand_ty raw_operand_ty; + }; + try sema.ensureLayoutResolved(operand_ty); - .@"union" => { - try operand_ty.resolveFields(pt); - const enum_ty = operand_ty.unionTagType(zcu) orelse { - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(operand_src, "switch on union with no attached enum", .{}); - errdefer msg.destroy(sema.gpa); - if (operand_ty.srcLocOrNull(zcu)) |union_src| { - try sema.errNote(union_src, msg, "consider 'union(enum)' here", .{}); - } - break :msg msg; - }); - }; - break :item_ty enum_ty; - }, + const item_ty: Type = item_ty: { + switch (operand_ty.zigTypeTag(zcu)) { + .@"enum", + .error_set, + .int, + .comptime_int, + .type, + .enum_literal, + .@"fn", + .bool, + .void, + => break :item_ty operand_ty, - .pointer => { - if (!operand_ty.isSlice(zcu)) { - break :item_ty operand_ty; - } - }, + .@"union" => { + const enum_ty = operand_ty.unionTagType(zcu) orelse { + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(operand_src, "switch on union with no attached enum", .{}); + errdefer msg.destroy(sema.gpa); + if (operand_ty.srcLocOrNull(zcu)) |union_src| { + try sema.errNote(union_src, msg, "consider 'union(enum)' here", .{}); + } + break :msg msg; + }); + }; + break :item_ty enum_ty; + }, - else => {}, - } - return sema.fail(block, operand_src, "switch on type '{f}'", .{operand_ty.fmt(pt)}); - }; + .pointer => { + if (!operand_ty.isSlice(zcu)) { + break :item_ty operand_ty; + } + }, - if (zir_switch.has_continue and !block.isComptime()) { - if (try operand_ty.comptimeOnlySema(pt)) { - // Even if the operand is comptime-known, this `switch` is runtime. - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(operand_src, "operand of switch loop has comptime-only type '{f}'", .{operand_ty.fmt(pt)}); - errdefer msg.destroy(gpa); - try sema.errNote(operand_src, msg, "switch loops are evaluated at runtime outside of comptime scopes", .{}); - try sema.explainWhyTypeIsComptime(msg, operand_src, operand_ty); - break :msg msg; - }); - } - try sema.validateRuntimeValue(block, operand_src, raw_operand); + else => {}, } - - break :check_operand .{ operand_ty, item_ty }; + return sema.fail(block, operand_src, "switch on type '{f}'", .{operand_ty.fmt(pt)}); }; + if (zir_switch.has_continue and !block.isComptime()) { + if (operand_ty.comptimeOnly(zcu)) { + // Even if the operand is comptime-known, this `switch` is runtime. + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(operand_src, "operand of switch loop has comptime-only type '{f}'", .{operand_ty.fmt(pt)}); + errdefer msg.destroy(gpa); + try sema.errNote(operand_src, msg, "switch loops are evaluated at runtime outside of comptime scopes", .{}); + try sema.explainWhyTypeIsComptime(msg, operand_src, operand_ty); + break :msg msg; + }); + } + try sema.validateRuntimeValue(block, operand_src, raw_operand); + } + const has_else = zir_switch.else_case != null; const has_under = zir_switch.has_under; @@ -12305,7 +11648,7 @@ fn resolveSwitchBlock( child_block: *Block, operand: SwitchOperand, raw_operand_ty: Type, - maybe_lazy_cond_val: Value, + cond_val: Value, merges: *Block.Merges, switch_inst: Zir.Inst.Index, zir_switch: *const Zir.UnwrappedSwitchBlock, @@ -12325,9 +11668,6 @@ fn resolveSwitchBlock( const err_set = item_ty.zigTypeTag(zcu) == .error_set; const cond_ref = operand.simple.cond; - // We have to resolve lazy values to ensure that comparisons with switch - // prong items don't produce false negatives. - const cond_val = try sema.resolveLazyValue(maybe_lazy_cond_val); const case_vals = validated_switch.case_vals; var case_val_idx: usize = 0; @@ -12617,14 +11957,12 @@ fn wantSwitchProngBodyAnalysis( ) bool { const zcu = sema.pt.zcu; if (union_originally) { - const unresolved_item_val = sema.resolveConstDefinedValue(block, .unneeded, item_ref, undefined) catch unreachable; - const item_val = sema.resolveLazyValue(unresolved_item_val) catch unreachable; + const item_val = sema.resolveConstDefinedValue(block, .unneeded, item_ref, undefined) catch unreachable; const field_ty = operand_ty.unionFieldType(item_val, zcu).?; if (field_ty.isNoReturn(zcu)) return false; } if (err_set and prong_is_comptime_unreach) { - const unresolved_item_val = sema.resolveConstDefinedValue(block, .unneeded, item_ref, undefined) catch unreachable; - const item_val = sema.resolveLazyValue(unresolved_item_val) catch unreachable; + const item_val = sema.resolveConstDefinedValue(block, .unneeded, item_ref, undefined) catch unreachable; const err_name = item_val.getErrorName(zcu).unwrap().?; if (!Type.errorSetHasFieldIp(&zcu.intern_pool, operand_ty.toIntern(), err_name)) return false; } @@ -12807,7 +12145,7 @@ fn analyzeSwitchPayloadCapture( const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); if (capture_by_ref) { const operand_ptr_info = sema.typeOf(operand_ptr).ptrInfo(zcu); - const ptr_field_ty = try pt.ptrTypeSema(.{ + const ptr_field_ty = try pt.ptrType(.{ .child = field_ty.toIntern(), .flags = .{ .is_const = operand_ptr_info.flags.is_const, @@ -12821,6 +12159,7 @@ fn analyzeSwitchPayloadCapture( const tag_and_val = ip.indexToKey(union_val.toIntern()).un; return .fromIntern(tag_and_val.val); } + if (try field_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); return case_block.addStructFieldVal(operand_val, field_index, field_ty); } } else if (capture_by_ref) { @@ -12914,13 +12253,27 @@ fn analyzeSwitchPayloadCapture( const dummy_captures = try sema.arena.alloc(Air.Inst.Ref, case_vals.len); for (field_indices, dummy_captures) |field_idx, *dummy| { const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]); - const field_ptr_ty = try pt.ptrTypeSema(.{ + const field_ptr_ty = try pt.ptrType(.{ .child = field_ty.toIntern(), .flags = .{ .is_const = operand_ptr_info.flags.is_const, .is_volatile = operand_ptr_info.flags.is_volatile, .address_space = operand_ptr_info.flags.address_space, - .alignment = union_obj.fieldAlign(ip, field_idx), + // TODO MLUGG: double-check this. and, um, EVERYWHERE we do ptr alignment... + .alignment = a: { + if (operand_ty.explicitFieldAlignment(field_idx, zcu) == .none and + operand_ptr_info.flags.alignment == .none) + { + break :a .none; + } + + const union_align = switch (operand_ptr_info.flags.alignment) { + .none => operand_ty.abiAlignment(zcu), + else => |a| a, + }; + const field_align = operand_ty.resolvedFieldAlignment(field_idx, zcu); + break :a .minStrict(union_align, field_align); + }, }, }); dummy.* = try pt.undefRef(field_ptr_ty); @@ -12963,6 +12316,8 @@ fn analyzeSwitchPayloadCapture( return case_block.addStructFieldPtr(operand_ptr, first_field_index, capture_ptr_ty); } + if (try capture_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); + if (try sema.resolveDefinedValue(case_block, operand_src, operand_val)) |operand_val_val| { if (operand_val_val.isUndef(zcu)) return pt.undefRef(capture_ty); const union_val = ip.indexToKey(operand_val_val.toIntern()).un; @@ -13119,7 +12474,7 @@ fn analyzeSwitchPayloadCapture( try sema.air_instructions.append(sema.gpa, .{ .tag = .get_union_tag, .data = .{ .ty_op = .{ - .ty = .fromIntern(union_obj.enum_tag_ty), + .ty = .fromIntern(union_obj.enum_tag_type), .operand = operand_val, } }, }); @@ -13261,17 +12616,8 @@ fn resolveSwitchItem( } break :item_ref try sema.coerce(block, item_ty, uncoerced, item_src); }; - const maybe_lazy = try sema.resolveConstDefinedValue(block, item_src, item_ref, .{ .simple = .switch_item }); - - // We have to resolve lazy values here to avoid false negatives when detecting - // duplicate items and comparing items to a comptime-known switch operand. - - const val = try sema.resolveLazyValue(maybe_lazy); - const ref: Air.Inst.Ref = if (val.toIntern() == maybe_lazy.toIntern()) - item_ref - else - .fromValue(val); - return .{ .{ .ref = ref, .val = val }, end }; + const val = try sema.resolveConstDefinedValue(block, item_src, item_ref, .{ .simple = .switch_item }); + return .{ .{ .ref = item_ref, .val = val }, end }; } fn validateSwitchItemOrRange( @@ -13488,7 +12834,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const name_src = block.builtinCallArgSrc(inst_data.src_node, 1); const ty = try sema.resolveType(block, ty_src, extra.lhs); const field_name = try sema.resolveConstStringIntern(block, name_src, extra.rhs, .{ .simple = .field_name }); - try ty.resolveFields(pt); + try sema.ensureLayoutResolved(ty); const ip = &zcu.intern_pool; const has_field = hf: { @@ -13510,7 +12856,8 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai }, .union_type => { const union_type = ip.loadUnionType(ty.toIntern()); - break :hf union_type.loadTagType(ip).nameIndex(ip, field_name) != null; + const enum_type = ip.loadEnumType(union_type.enum_tag_type); + break :hf enum_type.nameIndex(ip, field_name) != null; }, .enum_type => { break :hf ip.loadEnumType(ty.toIntern()).nameIndex(ip, field_name) != null; @@ -13569,10 +12916,9 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. switch (file.getMode()) { .zig => { try pt.ensureFileAnalyzed(file_index); - const ty = zcu.fileRootType(file_index); - try sema.declareDependency(.{ .interned = ty }); + const ty: Type = .fromInterned(zcu.fileRootType(file_index)); try sema.addTypeReferenceEntry(operand_src, ty); - return Air.internedToRef(ty); + return .fromType(ty); }, .zon => { const res_ty: InternPool.Index = b: { @@ -13692,8 +13038,8 @@ fn zirShl( // we already know `scalar_rhs_ty` is valid for `.shl` -- we only need to validate for `.shl_sat`. if (air_tag == .shl_sat) _ = try sema.checkIntType(block, rhs_src, scalar_rhs_ty); - const maybe_lhs_val = try sema.resolveValueResolveLazy(lhs); - const maybe_rhs_val = try sema.resolveValueResolveLazy(rhs); + const maybe_lhs_val = try sema.resolveValue(lhs); + const maybe_rhs_val = try sema.resolveValue(rhs); const runtime_src = rs: { if (maybe_rhs_val) |rhs_val| { @@ -13713,11 +13059,11 @@ fn zirShl( const bits = scalar_ty.intInfo(zcu).bits; switch (rhs_ty.zigTypeTag(zcu)) { .int, .comptime_int => { - switch (try rhs_val.orderAgainstZeroSema(pt)) { + switch (Value.order(rhs_val, .zero_comptime_int, zcu)) { .gt => { if (air_tag != .shl_sat) { var rhs_space: Value.BigIntSpace = undefined; - const rhs_bigint = try rhs_val.toBigIntSema(&rhs_space, pt); + const rhs_bigint = rhs_val.toBigInt(&rhs_space, zcu); if (rhs_bigint.orderAgainstScalar(bits) != .lt) { return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_val, rhs_src, null); } @@ -13736,11 +13082,11 @@ fn zirShl( .shl, .shl_exact => return sema.failWithUseOfUndef(block, rhs_src, elem_idx), else => unreachable, }; - switch (try rhs_elem.orderAgainstZeroSema(pt)) { + switch (Value.order(rhs_elem, .zero_comptime_int, zcu)) { .gt => { if (air_tag != .shl_sat) { var rhs_elem_space: Value.BigIntSpace = undefined; - const rhs_elem_bigint = try rhs_elem.toBigIntSema(&rhs_elem_space, pt); + const rhs_elem_bigint = rhs_elem.toBigInt(&rhs_elem_space, zcu); if (rhs_elem_bigint.orderAgainstScalar(bits) != .lt) { return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_elem, rhs_src, elem_idx); } @@ -13769,7 +13115,7 @@ fn zirShl( .shl, .shl_exact => try sema.checkAllScalarsDefined(block, lhs_src, lhs_val), else => unreachable, } - if (try lhs_val.compareAllWithZeroSema(.eq, pt)) return lhs; + if (lhs_val.compareAllWithZero(.eq, zcu)) return lhs; } } break :rs rhs_src; @@ -13785,13 +13131,13 @@ fn zirShl( const rt_rhs_scalar_ty = try pt.smallestUnsignedInt(bit_count); if (!rhs_ty.isVector(zcu)) break :rt_rhs try pt.intValue( rt_rhs_scalar_ty, - @min(try rhs_val.getUnsignedIntSema(pt) orelse bit_count, bit_count), + @min(rhs_val.getUnsignedInt(zcu) orelse bit_count, bit_count), ); const rhs_len = rhs_ty.vectorLen(zcu); const rhs_elems = try sema.arena.alloc(InternPool.Index, rhs_len); for (rhs_elems, 0..) |*rhs_elem, i| rhs_elem.* = (try pt.intValue( rt_rhs_scalar_ty, - @min(try (try rhs_val.elemValue(pt, i)).getUnsignedIntSema(pt) orelse bit_count, bit_count), + @min((try rhs_val.elemValue(pt, i)).getUnsignedInt(zcu) orelse bit_count, bit_count), )).toIntern(); break :rt_rhs try pt.aggregateValue(try pt.vectorType(.{ .len = rhs_len, @@ -13875,8 +13221,8 @@ fn zirShr( try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); const scalar_ty = lhs_ty.scalarType(zcu); - const maybe_lhs_val = try sema.resolveValueResolveLazy(lhs); - const maybe_rhs_val = try sema.resolveValueResolveLazy(rhs); + const maybe_lhs_val = try sema.resolveValue(lhs); + const maybe_rhs_val = try sema.resolveValue(rhs); const runtime_src = rs: { if (maybe_rhs_val) |rhs_val| { @@ -13893,10 +13239,10 @@ fn zirShr( const bits = scalar_ty.intInfo(zcu).bits; switch (rhs_ty.zigTypeTag(zcu)) { .int, .comptime_int => { - switch (try rhs_val.orderAgainstZeroSema(pt)) { + switch (Value.order(rhs_val, .zero_comptime_int, zcu)) { .gt => { var rhs_space: Value.BigIntSpace = undefined; - const rhs_bigint = try rhs_val.toBigIntSema(&rhs_space, pt); + const rhs_bigint = rhs_val.toBigInt(&rhs_space, zcu); if (rhs_bigint.orderAgainstScalar(bits) != .lt) { return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_val, rhs_src, null); } @@ -13912,10 +13258,10 @@ fn zirShr( if (rhs_elem.isUndef(zcu)) { return sema.failWithUseOfUndef(block, rhs_src, elem_idx); } - switch (try rhs_elem.orderAgainstZeroSema(pt)) { + switch (Value.order(rhs_elem, .zero_comptime_int, zcu)) { .gt => { var rhs_elem_space: Value.BigIntSpace = undefined; - const rhs_elem_bigint = try rhs_elem.toBigIntSema(&rhs_elem_space, pt); + const rhs_elem_bigint = rhs_elem.toBigInt(&rhs_elem_space, zcu); if (rhs_elem_bigint.orderAgainstScalar(bits) != .lt) { return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_elem, rhs_src, elem_idx); } @@ -13936,7 +13282,7 @@ fn zirShr( } if (maybe_lhs_val) |lhs_val| { try sema.checkAllScalarsDefined(block, lhs_src, lhs_val); - if (try lhs_val.compareAllWithZeroSema(.eq, pt)) return lhs; + if (lhs_val.compareAllWithZero(.eq, zcu)) return lhs; } } break :rs rhs_src; @@ -14011,8 +13357,8 @@ fn zirBitwise( const runtime_src = runtime: { // TODO: ask the linker what kind of relocations are available, and // in some cases emit a Value that means "this decl's address AND'd with this operand". - if (try sema.resolveValueResolveLazy(casted_lhs)) |lhs_val| { - if (try sema.resolveValueResolveLazy(casted_rhs)) |rhs_val| { + if (try sema.resolveValue(casted_lhs)) |lhs_val| { + if (try sema.resolveValue(casted_rhs)) |rhs_val| { const result_val = switch (air_tag) { // zig fmt: off .bit_and => try arith.bitwiseBin(sema, resolved_type, lhs_val, rhs_val, .@"and"), @@ -14106,13 +13452,13 @@ fn analyzeTupleCat( var i: u32 = 0; while (i < lhs_len) : (i += 1) { types[i] = lhs_ty.fieldType(i, zcu).toIntern(); - const default_val = lhs_ty.structFieldDefaultValue(i, zcu); - values[i] = default_val.toIntern(); const operand_src = block.src(.{ .array_cat_lhs = .{ .array_cat_offset = src_node, .elem_index = i, } }); - if (default_val.toIntern() == .unreachable_value) { + if (lhs_ty.structFieldDefaultValue(i, zcu)) |default_val| { + values[i] = default_val.toIntern(); + } else { runtime_src = operand_src; values[i] = .none; } @@ -14120,13 +13466,13 @@ fn analyzeTupleCat( i = 0; while (i < rhs_len) : (i += 1) { types[i + lhs_len] = rhs_ty.fieldType(i, zcu).toIntern(); - const default_val = rhs_ty.structFieldDefaultValue(i, zcu); - values[i + lhs_len] = default_val.toIntern(); const operand_src = block.src(.{ .array_cat_rhs = .{ .array_cat_offset = src_node, .elem_index = i, } }); - if (default_val.toIntern() == .unreachable_value) { + if (rhs_ty.structFieldDefaultValue(i, zcu)) |default_val| { + values[i + lhs_len] = default_val.toIntern(); + } else { runtime_src = operand_src; values[i + lhs_len] = .none; } @@ -14290,8 +13636,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai var elem_i: u32 = 0; while (elem_i < lhs_len) : (elem_i += 1) { const lhs_elem_i = elem_i; - const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, zcu) else Value.@"unreachable"; - const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try lhs_sub_val.elemValue(pt, lhs_elem_i) else elem_default_val; + const elem_default_val: ?Value = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, zcu) else null; + const elem_val = elem_default_val orelse try lhs_sub_val.elemValue(pt, lhs_elem_i); const elem_val_inst = Air.internedToRef(elem_val.toIntern()); const operand_src = block.src(.{ .array_cat_lhs = .{ .array_cat_offset = inst_data.src_node, @@ -14303,8 +13649,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai } while (elem_i < result_len) : (elem_i += 1) { const rhs_elem_i = elem_i - lhs_len; - const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, zcu) else Value.@"unreachable"; - const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try rhs_sub_val.elemValue(pt, rhs_elem_i) else elem_default_val; + const elem_default_val: ?Value = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, zcu) else null; + const elem_val = elem_default_val orelse try rhs_sub_val.elemValue(pt, rhs_elem_i); const elem_val_inst = Air.internedToRef(elem_val.toIntern()); const operand_src = block.src(.{ .array_cat_rhs = .{ .array_cat_offset = inst_data.src_node, @@ -14324,18 +13670,18 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai try sema.requireRuntimeBlock(block, src, runtime_src); if (ptr_addrspace) |ptr_as| { - const constant_alloc_ty = try pt.ptrTypeSema(.{ + const constant_alloc_ty = try pt.ptrType(.{ .child = result_ty.toIntern(), .flags = .{ .address_space = ptr_as, .is_const = true, }, }); - const alloc_ty = try pt.ptrTypeSema(.{ + const alloc_ty = try pt.ptrType(.{ .child = result_ty.toIntern(), .flags = .{ .address_space = ptr_as }, }); - const elem_ptr_ty = try pt.ptrTypeSema(.{ + const elem_ptr_ty = try pt.ptrType(.{ .child = resolved_elem_ty.toIntern(), .flags = .{ .address_space = ptr_as }, }); @@ -14347,7 +13693,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai if (lhs_ty.zigTypeTag(zcu) == .pointer and rhs_ty.zigTypeTag(zcu) == .pointer) { - const slice_ty = try pt.ptrTypeSema(.{ + const slice_ty = try pt.ptrType(.{ .child = resolved_elem_ty.toIntern(), .flags = .{ .size = .slice, @@ -14486,7 +13832,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins .none => null, else => Value.fromInterned(ptr_info.sentinel), }, - .len = try val.sliceLen(pt), + .len = val.sliceLen(zcu), }; }, .one => { @@ -14500,8 +13846,20 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins .@"struct" => { if (operand_ty.isTuple(zcu) and peer_ty.isIndexable(zcu)) { assert(!peer_ty.isTuple(zcu)); + const peer_elem_ty = switch (peer_ty.zigTypeTag(zcu)) { + .pointer => switch (peer_ty.ptrSize(zcu)) { + .one => switch (peer_ty.childType(zcu).zigTypeTag(zcu)) { + .array, .vector => peer_ty.childType(zcu).childType(zcu), + .@"struct" => return null, + else => unreachable, + }, + .many, .c, .slice => peer_ty.childType(zcu), + }, + .vector, .array => peer_ty.childType(zcu), + else => unreachable, + }; return .{ - .elem_type = peer_ty.elemType2(zcu), + .elem_type = peer_elem_ty, .sentinel = null, .len = operand_ty.arrayLen(zcu), }; @@ -14543,12 +13901,13 @@ fn analyzeTupleMul( var runtime_src: ?LazySrcLoc = null; for (0..tuple_len) |i| { types[i] = operand_ty.fieldType(i, zcu).toIntern(); - values[i] = operand_ty.structFieldDefaultValue(i, zcu).toIntern(); const operand_src = block.src(.{ .array_cat_lhs = .{ .array_cat_offset = src_node, .elem_index = @intCast(i), } }); - if (values[i] == .unreachable_value) { + if (operand_ty.structFieldDefaultValue(i, zcu)) |default_val| { + values[i] = default_val.toIntern(); + } else { runtime_src = operand_src; values[i] = .none; // TODO don't treat unreachable_value as special } @@ -14714,7 +14073,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai } if (ptr_addrspace) |ptr_as| { - const alloc_ty = try pt.ptrTypeSema(.{ + const alloc_ty = try pt.ptrType(.{ .child = result_ty.toIntern(), .flags = .{ .address_space = ptr_as, @@ -14722,7 +14081,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai }, }); const alloc = try block.addTy(.alloc, alloc_ty); - const elem_ptr_ty = try pt.ptrTypeSema(.{ + const elem_ptr_ty = try pt.ptrType(.{ .child = lhs_info.elem_type.toIntern(), .flags = .{ .address_space = ptr_as }, }); @@ -14859,8 +14218,8 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div); - const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs); - const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs); + const maybe_lhs_val = try sema.resolveValue(casted_lhs); + const maybe_rhs_val = try sema.resolveValue(casted_rhs); if ((lhs_ty.zigTypeTag(zcu) == .comptime_float and rhs_ty.zigTypeTag(zcu) == .comptime_int) or (lhs_ty.zigTypeTag(zcu) == .comptime_int and rhs_ty.zigTypeTag(zcu) == .comptime_float)) @@ -14968,8 +14327,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_exact); - const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs); - const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs); + const maybe_lhs_val = try sema.resolveValue(casted_lhs); + const maybe_rhs_val = try sema.resolveValue(casted_rhs); // Because `@divExact` can trigger Illegal Behavior, undefined operands trigger Illegal Behavior. @@ -15064,8 +14423,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_floor); - const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs); - const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs); + const maybe_lhs_val = try sema.resolveValue(casted_lhs); + const maybe_rhs_val = try sema.resolveValue(casted_rhs); const allow_div_zero = !is_int and resolved_type.toIntern() != .comptime_float_type and @@ -15129,8 +14488,8 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_trunc); - const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs); - const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs); + const maybe_lhs_val = try sema.resolveValue(casted_lhs); + const maybe_rhs_val = try sema.resolveValue(casted_rhs); const allow_div_zero = !is_int and resolved_type.toIntern() != .comptime_float_type and @@ -15341,8 +14700,8 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .mod_rem); - const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs); - const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs); + const maybe_lhs_val = try sema.resolveValue(casted_lhs); + const maybe_rhs_val = try sema.resolveValue(casted_rhs); const lhs_maybe_negative = a: { if (lhs_scalar_ty.isUnsignedInt(zcu)) break :a false; @@ -15440,8 +14799,8 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .mod); - const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs); - const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs); + const maybe_lhs_val = try sema.resolveValue(casted_lhs); + const maybe_rhs_val = try sema.resolveValue(casted_rhs); const allow_div_zero = !is_int and resolved_type.toIntern() != .comptime_float_type and @@ -15504,8 +14863,8 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .rem); - const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs); - const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs); + const maybe_lhs_val = try sema.resolveValue(casted_lhs); + const maybe_rhs_val = try sema.resolveValue(casted_rhs); const allow_div_zero = !is_int and resolved_type.toIntern() != .comptime_float_type and @@ -15601,12 +14960,12 @@ fn zirOverflowArithmetic( // to the result, even if it is undefined.. // Otherwise, if either of the argument is undefined, undefined is returned. if (maybe_lhs_val) |lhs_val| { - if (!lhs_val.isUndef(zcu) and (try lhs_val.compareAllWithZeroSema(.eq, pt))) { + if (!lhs_val.isUndef(zcu) and lhs_val.compareAllWithZero(.eq, zcu)) { break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = rhs }; } } if (maybe_rhs_val) |rhs_val| { - if (!rhs_val.isUndef(zcu) and (try rhs_val.compareAllWithZeroSema(.eq, pt))) { + if (!rhs_val.isUndef(zcu) and rhs_val.compareAllWithZero(.eq, zcu)) { break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs }; } } @@ -15627,7 +14986,7 @@ fn zirOverflowArithmetic( if (maybe_rhs_val) |rhs_val| { if (rhs_val.isUndef(zcu)) { break :result .{ .overflow_bit = .undef, .wrapped = .undef }; - } else if (try rhs_val.compareAllWithZeroSema(.eq, pt)) { + } else if (rhs_val.compareAllWithZero(.eq, zcu)) { break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs }; } else if (maybe_lhs_val) |lhs_val| { if (lhs_val.isUndef(zcu)) { @@ -15642,12 +15001,12 @@ fn zirOverflowArithmetic( .mul_with_overflow => { // If either of the arguments is zero, the result is zero and no overflow occured. if (maybe_lhs_val) |lhs_val| { - if (!lhs_val.isUndef(zcu) and try lhs_val.compareAllWithZeroSema(.eq, pt)) { + if (!lhs_val.isUndef(zcu) and lhs_val.compareAllWithZero(.eq, zcu)) { break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs }; } } if (maybe_rhs_val) |rhs_val| { - if (!rhs_val.isUndef(zcu) and try rhs_val.compareAllWithZeroSema(.eq, pt)) { + if (!rhs_val.isUndef(zcu) and rhs_val.compareAllWithZero(.eq, zcu)) { break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = rhs }; } } @@ -15694,10 +15053,10 @@ fn zirOverflowArithmetic( const bits = scalar_ty.intInfo(zcu).bits; switch (rhs_ty.zigTypeTag(zcu)) { .int, .comptime_int => { - switch (try rhs_val.orderAgainstZeroSema(pt)) { + switch (Value.order(rhs_val, .zero_comptime_int, zcu)) { .gt => { var rhs_space: Value.BigIntSpace = undefined; - const rhs_bigint = try rhs_val.toBigIntSema(&rhs_space, pt); + const rhs_bigint = rhs_val.toBigInt(&rhs_space, zcu); if (rhs_bigint.orderAgainstScalar(bits) != .lt) { return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_val, rhs_src, null); } @@ -15711,10 +15070,10 @@ fn zirOverflowArithmetic( for (0..rhs_ty.vectorLen(zcu)) |elem_idx| { const rhs_elem = try rhs_val.elemValue(pt, elem_idx); if (rhs_elem.isUndef(zcu)) return sema.failWithUseOfUndef(block, rhs_src, elem_idx); - switch (try rhs_elem.orderAgainstZeroSema(pt)) { + switch (Value.order(rhs_elem, .zero_comptime_int, zcu)) { .gt => { var rhs_elem_space: Value.BigIntSpace = undefined; - const rhs_elem_bigint = try rhs_elem.toBigIntSema(&rhs_elem_space, pt); + const rhs_elem_bigint = rhs_elem.toBigInt(&rhs_elem_space, zcu); if (rhs_elem_bigint.orderAgainstScalar(bits) != .lt) { return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_elem, rhs_src, elem_idx); } @@ -15728,7 +15087,7 @@ fn zirOverflowArithmetic( }, else => unreachable, } - if (try rhs_val.compareAllWithZeroSema(.eq, pt)) { + if (rhs_val.compareAllWithZero(.eq, zcu)) { break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs }; } } else { @@ -15737,7 +15096,7 @@ fn zirOverflowArithmetic( } if (maybe_lhs_val) |lhs_val| { try sema.checkAllScalarsDefined(block, lhs_src, lhs_val); - if (try lhs_val.compareAllWithZeroSema(.eq, pt)) { + if (lhs_val.compareAllWithZero(.eq, zcu)) { break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs }; } } @@ -15817,16 +15176,16 @@ fn analyzeArithmetic( if (zir_tag != .sub) { return sema.failWithInvalidPtrArithmetic(block, src, "pointer-pointer", "subtraction"); } - if (!lhs_ty.elemType2(zcu).eql(rhs_ty.elemType2(zcu), zcu)) { + if (!lhs_ty.childType(zcu).eql(rhs_ty.childType(zcu), zcu)) { return sema.fail(block, src, "incompatible pointer arithmetic operands '{f}' and '{f}'", .{ lhs_ty.fmt(pt), rhs_ty.fmt(pt), }); } - const elem_size = lhs_ty.elemType2(zcu).abiSize(zcu); + const elem_size = lhs_ty.childType(zcu).abiSize(zcu); if (elem_size == 0) { - return sema.fail(block, src, "pointer arithmetic requires element type '{f}' to have runtime bits", .{ - lhs_ty.elemType2(zcu).fmt(pt), + return sema.fail(block, src, "pointer subtraction requires element type '{f}' to have runtime bits", .{ + lhs_ty.childType(zcu).fmt(pt), }); } @@ -15875,11 +15234,7 @@ fn analyzeArithmetic( else => return sema.failWithInvalidPtrArithmetic(block, src, "pointer-integer", "addition and subtraction"), }; - if (!try lhs_ty.elemType2(zcu).hasRuntimeBitsSema(pt)) { - return sema.fail(block, src, "pointer arithmetic requires element type '{f}' to have runtime bits", .{ - lhs_ty.elemType2(zcu).fmt(pt), - }); - } + try sema.ensureLayoutResolved(lhs_ty.childType(zcu)); return sema.analyzePtrArithmetic(block, src, lhs, rhs, air_tag, lhs_src, rhs_src); }, } @@ -15915,8 +15270,8 @@ fn analyzeArithmetic( else => unreachable, }; - const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs); - const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs); + const maybe_lhs_val = try sema.resolveValue(casted_lhs); + const maybe_rhs_val = try sema.resolveValue(casted_rhs); if (maybe_lhs_val) |lhs_val| { if (maybe_rhs_val) |rhs_val| { @@ -15972,6 +15327,7 @@ fn analyzeArithmetic( return block.addBinOp(air_tag, casted_lhs, casted_rhs); } +/// Asserts that the layout of the pointer child type is already resolved. fn analyzePtrArithmetic( sema: *Sema, block: *Block, @@ -15993,7 +15349,10 @@ fn analyzePtrArithmetic( const ptr_info = ptr_ty.ptrInfo(zcu); assert(ptr_info.flags.size == .many or ptr_info.flags.size == .c); - if ((try sema.typeHasOnePossibleValue(.fromInterned(ptr_info.child))) != null) { + const elem_ty: Type = .fromInterned(ptr_info.child); + elem_ty.assertHasLayout(zcu); + + if (elem_ty.abiSize(zcu) == 0) { // Offset will be multiplied by zero, so result is the same as the base pointer. return ptr; } @@ -16007,9 +15366,9 @@ fn analyzePtrArithmetic( } // If the addend is not a comptime-known value we can still count on // it being a multiple of the type size. - const elem_size = try Type.fromInterned(ptr_info.child).abiSizeSema(pt); + const elem_size = elem_ty.abiSize(zcu); const addend = if (opt_off_val) |off_val| a: { - const off_int = try sema.usizeCast(block, offset_src, try off_val.toUnsignedIntSema(pt)); + const off_int = try sema.usizeCast(block, offset_src, off_val.toUnsignedInt(zcu)); break :a elem_size * off_int; } else elem_size; @@ -16022,7 +15381,7 @@ fn analyzePtrArithmetic( )); assert(new_align != .none); - break :t try pt.ptrTypeSema(.{ + break :t try pt.ptrType(.{ .child = ptr_info.child, .sentinel = ptr_info.sentinel, .flags = .{ @@ -16041,10 +15400,10 @@ fn analyzePtrArithmetic( if (opt_off_val) |offset_val| { if (ptr_val.isUndef(zcu)) return pt.undefRef(new_ptr_ty); - const offset_int = try sema.usizeCast(block, offset_src, try offset_val.toUnsignedIntSema(pt)); + const offset_int = try sema.usizeCast(block, offset_src, offset_val.toUnsignedInt(zcu)); if (offset_int == 0) return ptr; if (air_tag == .ptr_sub) { - const elem_size = try Type.fromInterned(ptr_info.child).abiSizeSema(pt); + const elem_size = elem_ty.abiSize(zcu); const new_ptr_val = try sema.ptrSubtract(block, op_src, ptr_val, offset_int * elem_size, new_ptr_ty); return Air.internedToRef(new_ptr_val.toIntern()); } else { @@ -16248,6 +15607,7 @@ fn zirAsm( buffer[input.c.len + 1 + input.n.len] = 0; sema.air_extra.items.len += (input.c.len + input.n.len + (2 + 3)) / 4; } + if (try expr_ty.toType().onePossibleValue(pt)) |opv| return .fromValue(opv); return asm_air; } @@ -16343,7 +15703,6 @@ fn analyzeCmpUnionTag( const pt = sema.pt; const zcu = pt.zcu; const union_ty = sema.typeOf(un); - try union_ty.resolveFields(pt); const union_tag_ty = union_ty.unionTagType(zcu) orelse { const msg = msg: { const msg = try sema.errMsg(un_src, "comparison of union and enum literal is only valid for tagged union types", .{}); @@ -16534,10 +15893,11 @@ fn runtimeBoolCmp( fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const pt = sema.pt; + const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const ty = try sema.resolveType(block, operand_src, inst_data.operand); - switch (ty.zigTypeTag(pt.zcu)) { + switch (ty.zigTypeTag(zcu)) { .@"fn", .noreturn, .undefined, @@ -16568,8 +15928,8 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. .@"anyframe", => {}, } - const val = try ty.abiSizeLazy(pt); - return Air.internedToRef(val.toIntern()); + try sema.ensureLayoutResolved(ty); + return .fromValue(try pt.intValue(.comptime_int, ty.abiSize(zcu))); } fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -16609,8 +15969,8 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A .@"anyframe", => {}, } - const bit_size = try operand_ty.bitSizeSema(pt); - return pt.intRef(.comptime_int, bit_size); + try sema.ensureLayoutResolved(operand_ty); + return .fromValue(try pt.intValue(.comptime_int, operand_ty.bitSize(zcu))); } fn zirThis( @@ -16619,34 +15979,16 @@ fn zirThis( extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { _ = extended; - const pt = sema.pt; - const zcu = pt.zcu; - const namespace = pt.zcu.namespacePtr(block.namespace); + const zcu = sema.pt.zcu; + const namespace = zcu.namespacePtr(block.namespace); - switch (pt.zcu.intern_pool.indexToKey(namespace.owner_type)) { - .opaque_type => { - // Opaque types are never outdated since they don't undergo type resolution, so nothing to do! - return Air.internedToRef(namespace.owner_type); - }, - .struct_type, .union_type => { - const new_ty = try pt.ensureTypeUpToDate(namespace.owner_type); - try sema.declareDependency(.{ .interned = new_ty }); - return Air.internedToRef(new_ty); - }, - .enum_type => { - const new_ty = try pt.ensureTypeUpToDate(namespace.owner_type); - try sema.declareDependency(.{ .interned = new_ty }); - // Since this is an enum, it has to be resolved immediately. - // `ensureTypeUpToDate` has resolved the new type if necessary. - // We just need to check for resolution failures. - const ty_unit: AnalUnit = .wrap(.{ .type = new_ty }); - if (zcu.failed_analysis.contains(ty_unit) or zcu.transitive_failed_analysis.contains(ty_unit)) { - return error.AnalysisFail; - } - return Air.internedToRef(new_ty); - }, + switch (zcu.intern_pool.indexToKey(namespace.owner_type)) { + .opaque_type, .struct_type, .union_type => {}, + // Enum inits are resolved eagerly. TODO MLUGG: honestly i don't think they SHOULD be lol + .enum_type => try sema.ensureFieldInitsResolved(.fromInterned(namespace.owner_type)), else => unreachable, } + return .fromIntern(namespace.owner_type); } fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { @@ -16739,7 +16081,7 @@ fn zirRetAddr( _ = sema; _ = extended; if (block.isComptime()) { - // TODO: we could give a meaningful lazy value here. #14938 + // TODO: we could give a meaningful value here. #14938 return .zero_usize; } else { return block.addNoOp(.ret_addr); @@ -16886,6 +16228,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai try sema.declareDependency(.{ .namespace = type_decl_inst }); } + try sema.ensureLayoutResolved(ty); + switch (ty.zigTypeTag(zcu)) { .type, .void, @@ -16934,7 +16278,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .child = param_info_ty.toIntern(), }); const new_decl_val = (try pt.aggregateValue(new_decl_ty, param_vals)).toIntern(); - const slice_ty = (try pt.ptrTypeSema(.{ + const slice_ty = (try pt.ptrType(.{ .child = param_info_ty.toIntern(), .flags = .{ .size = .slice, @@ -16976,11 +16320,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai error.OutOfMemory => |e| return e, }; + // MLUGG TODO + const func_is_generic = false; + const field_values: [5]InternPool.Index = .{ // calling_convention: CallingConvention, callconv_val.toIntern(), // is_generic: bool, - Value.makeBool(func_ty_info.is_generic).toIntern(), + Value.makeBool(func_is_generic).toIntern(), // is_var_args: bool, Value.makeBool(func_ty_info.is_var_args).toIntern(), // return_type: ?type, @@ -17015,7 +16362,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const field_vals = .{ // bits: u16, - (try pt.intValue(.u16, ty.bitSize(zcu))).toIntern(), + (try pt.intValue(.u16, ty.floatBits(zcu.getTarget()))).toIntern(), }; return Air.internedToRef((try pt.internUnion(.{ .ty = type_info_ty.toIntern(), @@ -17025,10 +16372,13 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai }, .pointer => { const info = ty.ptrInfo(zcu); - const alignment = if (info.flags.alignment.toByteUnits()) |alignment| - try pt.intValue(.comptime_int, alignment) - else - try Type.fromInterned(info.child).lazyAbiAlignment(pt); + const alignment_val = try pt.intValue(.comptime_int, bytes: { + if (info.flags.alignment.toByteUnits()) |b| break :bytes b; + const elem_ty: Type = .fromInterned(info.child); + // MLUGG TODO: this resolution is sus, but i doubt i'll solve it in this branch + try sema.ensureLayoutResolved(elem_ty); + break :bytes elem_ty.abiAlignment(zcu).toByteUnits().?; + }); const addrspace_ty = try sema.getBuiltinType(src, .AddressSpace); const pointer_ty = try sema.getBuiltinType(src, .@"Type.Pointer"); @@ -17042,7 +16392,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai // is_volatile: bool, Value.makeBool(info.flags.is_volatile).toIntern(), // alignment: comptime_int, - alignment.toIntern(), + alignment_val.toIntern(), // address_space: AddressSpace (try pt.enumValueFieldIndex(addrspace_ty, @intFromEnum(info.flags.address_space))).toIntern(), // child: type, @@ -17159,7 +16509,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai }; // Build our ?[]const Error value - const slice_errors_ty = try pt.ptrTypeSema(.{ + const slice_errors_ty = try pt.ptrType(.{ .child = error_field_ty.toIntern(), .flags = .{ .size = .slice, @@ -17215,19 +16565,19 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai }))); }, .@"enum" => { - const is_exhaustive = Value.makeBool(ip.loadEnumType(ty.toIntern()).tag_mode != .nonexhaustive); + const enum_obj = ip.loadEnumType(ty.toIntern()); + const is_exhaustive: Value = .makeBool(!enum_obj.nonexhaustive); const enum_field_ty = try sema.getBuiltinType(src, .@"Type.EnumField"); - const enum_field_vals = try sema.arena.alloc(InternPool.Index, ip.loadEnumType(ty.toIntern()).names.len); + const enum_field_vals = try sema.arena.alloc(InternPool.Index, enum_obj.field_names.len); for (enum_field_vals, 0..) |*field_val, tag_index| { - const enum_type = ip.loadEnumType(ty.toIntern()); - const value_val = if (enum_type.values.len > 0) + const value_val = if (enum_obj.field_values.len > 0) try ip.getCoercedInts( gpa, io, pt.tid, - ip.indexToKey(enum_type.values.get(ip)[tag_index]).int, + ip.indexToKey(enum_obj.field_values.get(ip)[tag_index]).int, .comptime_int_type, ) else @@ -17235,7 +16585,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai // TODO: write something like getCoercedInts to avoid needing to dupe const name_val = v: { - const tag_name = enum_type.names.get(ip)[tag_index]; + const tag_name = enum_obj.field_names.get(ip)[tag_index]; const tag_name_len = tag_name.length(ip); const new_decl_ty = try pt.arrayType(.{ .len = tag_name_len, @@ -17275,7 +16625,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .child = enum_field_ty.toIntern(), }); const new_decl_val = (try pt.aggregateValue(fields_array_ty, enum_field_vals)).toIntern(); - const slice_ty = (try pt.ptrTypeSema(.{ + const slice_ty = (try pt.ptrType(.{ .child = enum_field_ty.toIntern(), .flags = .{ .size = .slice, @@ -17303,7 +16653,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const field_values = .{ // tag_type: type, - ip.loadEnumType(ty.toIntern()).tag_ty, + ip.loadEnumType(ty.toIntern()).int_tag_type, // fields: []const EnumField, fields_val, // decls: []const Declaration, @@ -17321,17 +16671,16 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const type_union_ty = try sema.getBuiltinType(src, .@"Type.Union"); const union_field_ty = try sema.getBuiltinType(src, .@"Type.UnionField"); - try ty.resolveLayout(pt); // Getting alignment requires type layout - const union_obj = zcu.typeToUnion(ty).?; - const tag_type = union_obj.loadTagType(ip); - const layout = union_obj.flagsUnordered(ip).layout; + const union_obj = ip.loadUnionType(ty.toIntern()); + const enum_obj = ip.loadEnumType(union_obj.enum_tag_type); + const layout = union_obj.layout; - const union_field_vals = try gpa.alloc(InternPool.Index, tag_type.names.len); + const union_field_vals = try gpa.alloc(InternPool.Index, enum_obj.field_names.len); defer gpa.free(union_field_vals); for (union_field_vals, 0..) |*field_val, field_index| { const name_val = v: { - const field_name = tag_type.names.get(ip)[field_index]; + const field_name = enum_obj.field_names.get(ip)[field_index]; const field_name_len = field_name.length(ip); const new_decl_ty = try pt.arrayType(.{ .len = field_name_len, @@ -17357,7 +16706,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai }; const alignment = switch (layout) { - .auto, .@"extern" => try ty.fieldAlignmentSema(field_index, pt), + .auto, .@"extern" => ty.resolvedFieldAlignment(field_index, zcu), .@"packed" => .none, }; @@ -17379,7 +16728,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .child = union_field_ty.toIntern(), }); const new_decl_val = (try pt.aggregateValue(array_fields_ty, union_field_vals)).toIntern(); - const slice_ty = (try pt.ptrTypeSema(.{ + const slice_ty = (try pt.ptrType(.{ .child = union_field_ty.toIntern(), .flags = .{ .size = .slice, @@ -17431,8 +16780,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const type_struct_ty = try sema.getBuiltinType(src, .@"Type.Struct"); const struct_field_ty = try sema.getBuiltinType(src, .@"Type.StructField"); - try ty.resolveLayout(pt); // Getting alignment requires type layout - var struct_field_vals: []InternPool.Index = &.{}; defer gpa.free(struct_field_vals); fv: { @@ -17468,8 +16815,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai } }); }; - try Type.fromInterned(field_ty).resolveLayout(pt); - const is_comptime = field_val != .none; const opt_default_val = if (is_comptime) Value.fromInterned(field_val) else null; const default_val_ptr = try sema.optRefValue(opt_default_val); @@ -17492,16 +16837,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .struct_type => ip.loadStructType(ty.toIntern()), else => unreachable, }; + try sema.ensureFieldInitsResolved(ty); // can't do this sooner, since it's not allowed on tuples struct_field_vals = try gpa.alloc(InternPool.Index, struct_type.field_types.len); - try ty.resolveStructFieldInits(pt); - for (struct_field_vals, 0..) |*field_val, field_index| { - const field_name = struct_type.fieldName(ip, field_index); + const field_name = struct_type.field_names.get(ip)[field_index]; const field_name_len = field_name.length(ip); const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); - const field_init = struct_type.fieldInit(ip, field_index); - const field_is_comptime = struct_type.fieldIsComptime(ip, field_index); + const field_default: InternPool.Index = if (struct_type.field_defaults.len > 0) d: { + break :d struct_type.field_defaults.get(ip)[field_index]; + } else .none; + const field_is_comptime = struct_type.field_is_comptime_bits.get(ip, field_index); const name_val = v: { const new_decl_ty = try pt.arrayType(.{ .len = field_name_len, @@ -17526,15 +16872,11 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai } }); }; - const opt_default_val = if (field_init == .none) null else Value.fromInterned(field_init); + const opt_default_val: ?Value = if (field_default == .none) null else .fromInterned(field_default); const default_val_ptr = try sema.optRefValue(opt_default_val); const alignment = switch (struct_type.layout) { + .auto, .@"extern" => ty.resolvedFieldAlignment(field_index, zcu), .@"packed" => .none, - else => try field_ty.structFieldAlignmentSema( - struct_type.fieldAlign(ip, field_index), - struct_type.layout, - pt, - ), }; const struct_field_fields = .{ @@ -17559,7 +16901,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .child = struct_field_ty.toIntern(), }); const new_decl_val = (try pt.aggregateValue(array_fields_ty, struct_field_vals)).toIntern(); - const slice_ty = (try pt.ptrTypeSema(.{ + const slice_ty = (try pt.ptrType(.{ .child = struct_field_ty.toIntern(), .flags = .{ .size = .slice, @@ -17585,9 +16927,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const backing_integer_val = try pt.intern(.{ .opt = .{ .ty = (try pt.optionalType(.type_type)).toIntern(), - .val = if (zcu.typeToPackedStruct(ty)) |packed_struct| val: { - assert(Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)).isInt(zcu)); - break :val packed_struct.backingIntTypeUnordered(ip); + .val = if (zcu.typeToPackedStruct(ty)) |struct_obj| val: { + assert(Type.fromInterned(struct_obj.packed_backing_int_type).isInt(zcu)); + break :val struct_obj.packed_backing_int_type; } else .none, } }); @@ -17616,7 +16958,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .@"opaque" => { const type_opaque_ty = try sema.getBuiltinType(src, .@"Type.Opaque"); - try ty.resolveFields(pt); const decls_val = try sema.typeInfoDecls(src, ty.getNamespace(zcu)); const field_values = .{ @@ -17658,7 +16999,7 @@ fn typeInfoDecls( .child = declaration_ty.toIntern(), }); const new_decl_val = (try pt.aggregateValue(array_decl_ty, decl_vals.items)).toIntern(); - const slice_ty = (try pt.ptrTypeSema(.{ + const slice_ty = (try pt.ptrType(.{ .child = declaration_ty.toIntern(), .flags = .{ .size = .slice, @@ -17783,22 +17124,12 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi const zcu = pt.zcu; switch (operand.zigTypeTag(zcu)) { .comptime_int => return .comptime_int, - .int => { - const bits = operand.bitSize(zcu); - const count = if (bits == 0) - 0 - else blk: { - var count: u16 = 0; - var s = bits - 1; - while (s != 0) : (s >>= 1) { - count += 1; - } - break :blk count; - }; - return pt.intType(.unsigned, count); - }, + .int => return pt.intType(.unsigned, switch (operand.intInfo(zcu).bits) { + 0 => 0, + else => |b| std.math.log2_int_ceil(u16, b), + }), .vector => { - const elem_ty = operand.elemType2(zcu); + const elem_ty = operand.childType(zcu); const log2_elem_ty = try sema.log2IntType(block, elem_ty, src); return pt.vectorType(.{ .len = operand.vectorLen(zcu), @@ -18082,13 +17413,15 @@ fn zirIsNonNullPtr( const src = block.nodeOffset(inst_data.src_node); const ptr = try sema.resolveInst(inst_data.operand); const ptr_ty = sema.typeOf(ptr); - try sema.checkNullableType(block, src, sema.typeOf(ptr).elemType2(zcu)); + assert(ptr_ty.zigTypeTag(zcu) == .pointer); + const nullable_ty = ptr_ty.childType(zcu); + try sema.checkNullableType(block, src, nullable_ty); if (try sema.resolveValue(ptr)) |ptr_val| { - if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |loaded_val| { - return sema.analyzeIsNull(block, Air.internedToRef(loaded_val.toIntern()), true); + if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |nullable_val| { + return sema.analyzeIsNull(block, .fromValue(nullable_val), true); } } - if (ptr_ty.childType(zcu).isNullFromType(zcu)) |is_null| { + if (nullable_ty.isNullFromType(zcu)) |is_null| { return if (is_null) .bool_false else .bool_true; } return block.addUnOp(.is_non_null_ptr, ptr); @@ -18125,7 +17458,10 @@ fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const ptr = try sema.resolveInst(inst_data.operand); - try sema.checkErrorType(block, src, sema.typeOf(ptr).elemType2(zcu)); + const ptr_ty = sema.typeOf(ptr); + assert(ptr_ty.zigTypeTag(zcu) == .pointer); + const error_ty = ptr_ty.childType(zcu); + try sema.checkErrorType(block, src, error_ty); const loaded = try sema.analyzeLoad(block, src, ptr, src); return sema.analyzeIsNonErr(block, src, loaded); } @@ -18294,6 +17630,11 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError! } }, }); sema.air_extra.appendSliceAssumeCapacity(@ptrCast(sub_block.instructions.items)); + + // The payload type might still be OPV, in which case `try_inst` is just there for the runtime + // control flow and we should return a comptime-known result. + if (try err_union_ty.errorUnionPayload(zcu).onePossibleValue(pt)) |opv| return .fromValue(opv); + return try_inst; } @@ -18347,7 +17688,7 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr const operand_ty = sema.typeOf(operand); const ptr_info = operand_ty.ptrInfo(zcu); - const res_ty = try pt.ptrTypeSema(.{ + const res_ty = try pt.ptrType(.{ .child = err_union_ty.errorUnionPayload(zcu).toIntern(), .flags = .{ .is_const = ptr_info.flags.is_const, @@ -18512,7 +17853,7 @@ fn zirRetImplicit( const operand = try sema.resolveInst(inst_data.operand); const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = .zero }); - const base_tag = sema.fn_ret_ty.baseZigTypeTag(zcu); + const base_tag = sema.fn_ret_ty.optEuBaseType(zcu).zigTypeTag(zcu); if (base_tag == .noreturn) { const msg = msg: { const msg = try sema.errMsg(ret_ty_src, "function declared '{f}' implicitly returns", .{ @@ -18809,8 +18150,6 @@ fn analyzeRet( return sema.failWithOwnedErrorMsg(block, msg); } - try sema.fn_ret_ty.resolveLayout(pt); - try sema.validateRuntimeValue(block, operand_src, operand); const air_tag: Air.Inst.Tag = if (block.wantSafety()) .ret_safe else .ret; @@ -18889,16 +18228,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air extra_i += 1; const coerced = try sema.coerce(block, align_ty, try sema.resolveInst(ref), align_src); const val = try sema.resolveConstDefinedValue(block, align_src, coerced, .{ .simple = .@"align" }); - // Check if this happens to be the lazy alignment of our element type, in - // which case we can make this 0 without resolving it. - switch (zcu.intern_pool.indexToKey(val.toIntern())) { - .int => |int| switch (int.storage) { - .lazy_align => |lazy_ty| if (lazy_ty == elem_ty.toIntern()) break :blk .none, - else => {}, - }, - else => {}, - } - const align_bytes = (try val.getUnsignedIntSema(pt)).?; + const align_bytes = val.toUnsignedInt(zcu); break :blk try sema.validateAlign(block, align_src, align_bytes); } else .none; @@ -18928,7 +18258,8 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air elem_ty.fmt(pt), bit_offset, bit_offset - host_size * 8, host_size, }); } - const elem_bit_size = try elem_ty.bitSizeSema(pt); + try sema.ensureLayoutResolved(elem_ty); + const elem_bit_size = elem_ty.bitSize(zcu); if (elem_bit_size > host_size * 8 - bit_offset) { return sema.fail(block, bitoffset_src, "packed type '{f}' at bit offset {d} ends {d} bits after the end of a {d} byte host integer", .{ elem_ty.fmt(pt), bit_offset, elem_bit_size - (host_size * 8 - bit_offset), host_size, @@ -18957,16 +18288,16 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air } } - if (host_size != 0 and !try sema.validatePackedType(elem_ty)) { + if (host_size != 0 and !elem_ty.packable(zcu)) { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(elem_ty_src, "bit-pointer cannot refer to value of type '{f}'", .{elem_ty.fmt(pt)}); errdefer msg.destroy(sema.gpa); - try sema.explainWhyTypeIsNotPacked(msg, elem_ty_src, elem_ty); + try sema.explainWhyTypeIsNotPackable(msg, elem_ty_src, elem_ty); break :msg msg; }); } - const ty = try pt.ptrTypeSema(.{ + const ty = try pt.ptrType(.{ .child = elem_ty.toIntern(), .sentinel = sentinel, .flags = .{ @@ -18996,6 +18327,8 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE const pt = sema.pt; const zcu = pt.zcu; + try sema.ensureLayoutResolved(obj_ty); + switch (obj_ty.zigTypeTag(zcu)) { .@"struct" => return sema.structInitEmpty(block, obj_ty, src, src), .array, .vector => return sema.arrayInitEmpty(block, src, obj_ty), @@ -19058,6 +18391,9 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is .child = ptr_ty.childType(zcu).toIntern(), }); } else ty_operand; + + try sema.ensureLayoutResolved(init_ty); + const obj_ty = init_ty.optEuBaseType(zcu); const empty_ref = switch (obj_ty.zigTypeTag(zcu)) { @@ -19076,6 +18412,7 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is } } +/// Asserts that the layout of `struct_ty` is already resolved. fn structInitEmpty( sema: *Sema, block: *Block, @@ -19087,7 +18424,7 @@ fn structInitEmpty( const zcu = pt.zcu; const gpa = sema.gpa; // This logic must be synchronized with that in `zirStructInit`. - try struct_ty.resolveFields(pt); + struct_ty.assertHasLayout(zcu); // The init values to use for the struct instance. const field_inits = try gpa.alloc(Air.Inst.Ref, struct_ty.structFieldCount(zcu)); @@ -19202,8 +18539,8 @@ fn zirStructInit( // The type wasn't actually known, so treat this as an anon struct init. return sema.structInitAnon(block, src, inst, .typed_init, extra.data, extra.end, is_ref); }; + try sema.ensureLayoutResolved(result_ty); const resolved_ty = result_ty.optEuBaseType(zcu); - try resolved_ty.resolveLayout(pt); if (resolved_ty.zigTypeTag(zcu) == .@"struct") { // This logic must be synchronized with that in `zirStructInitEmpty`. @@ -19226,7 +18563,6 @@ fn zirStructInit( var field_i: u32 = 0; var extra_index = extra.end; - const is_packed = resolved_ty.containerLayout(zcu) == .@"packed"; while (field_i < extra.data.fields_len) : (field_i += 1) { const item = sema.code.extraData(Zir.Inst.StructInit.Item, extra_index); extra_index = item.end; @@ -19251,16 +18587,16 @@ fn zirStructInit( const uncoerced_init = try sema.resolveInst(item.data.init); const field_ty = resolved_ty.fieldType(field_index, zcu); field_inits[field_index] = try sema.coerce(block, field_ty, uncoerced_init, field_src); - if (!is_packed) { - try resolved_ty.resolveStructFieldInits(pt); - if (try resolved_ty.structFieldValueComptime(pt, field_index)) |default_value| { - const init_val = (try sema.resolveValue(field_inits[field_index])) orelse { - return sema.failWithNeededComptime(block, field_src, .{ .simple = .stored_to_comptime_field }); - }; - - if (!init_val.eql(default_value, resolved_ty.fieldType(field_index, zcu), zcu)) { - return sema.failWithInvalidComptimeFieldStore(block, field_src, resolved_ty, field_index); - } + if (resolved_ty.structFieldIsComptime(field_index, zcu)) { + if (!resolved_ty.isTuple(zcu)) { + try sema.ensureFieldInitsResolved(resolved_ty); + } + const default_value = (try resolved_ty.structFieldValueComptime(pt, field_index)).?; + const init_val = (try sema.resolveValue(field_inits[field_index])) orelse { + return sema.failWithNeededComptime(block, field_src, .{ .simple = .stored_to_comptime_field }); + }; + if (!init_val.eql(default_value, resolved_ty.fieldType(field_index, zcu), zcu)) { + return sema.failWithInvalidComptimeFieldStore(block, field_src, resolved_ty, field_index); } } } @@ -19315,7 +18651,7 @@ fn zirStructInit( return sema.addConstantMaybeRef(final_val.toIntern(), is_ref); } - if (try resolved_ty.comptimeOnlySema(pt)) { + if (resolved_ty.comptimeOnly(zcu)) { return sema.failWithNeededComptime(block, field_src, .{ .comptime_only = .{ .ty = resolved_ty, .msg = .union_init, @@ -19326,7 +18662,7 @@ fn zirStructInit( if (is_ref) { const target = zcu.getTarget(); - const alloc_ty = try pt.ptrTypeSema(.{ + const alloc_ty = try pt.ptrType(.{ .child = result_ty.toIntern(), .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, }); @@ -19334,9 +18670,8 @@ fn zirStructInit( const base_ptr = try sema.optEuBasePtrInit(block, alloc, src); const field_ptr = try sema.unionFieldPtr(block, field_src, base_ptr, field_name, field_src, resolved_ty, true); try sema.storePtr(block, src, field_ptr, init_inst); - if ((try sema.typeHasOnePossibleValue(tag_ty)) == null) { - const new_tag = Air.internedToRef(tag_val.toIntern()); - _ = try block.addBinOp(.set_union_tag, base_ptr, new_tag); + if (try tag_ty.onePossibleValue(pt) == null) { + _ = try block.addBinOp(.set_union_tag, base_ptr, .fromValue(tag_val)); } return sema.makePtrConst(block, alloc); } @@ -19409,20 +18744,24 @@ fn finishStructInit( continue; } - try struct_ty.resolveStructFieldInits(pt); + try sema.ensureFieldInitsResolved(struct_ty); - const field_init = struct_type.fieldInit(ip, i); - if (field_init == .none) { - const field_name = struct_type.field_names.get(ip)[i]; - const template = "missing struct field: {f}"; - const args = .{field_name.fmt(ip)}; - if (root_msg) |msg| { - try sema.errNote(init_src, msg, template, args); - } else { - root_msg = try sema.errMsg(init_src, template, args); - } + const field_default: InternPool.Index = d: { + if (struct_type.field_defaults.len == 0) break :d .none; + break :d struct_type.field_defaults.get(ip)[i]; + }; + if (field_default != .none) { + field_inits[i] = .fromIntern(field_default); + continue; + } + + const field_name = struct_type.field_names.get(ip)[i]; + const template = "missing struct field: {f}"; + const args = .{field_name.fmt(ip)}; + if (root_msg) |msg| { + try sema.errNote(init_src, msg, template, args); } else { - field_inits[i] = Air.internedToRef(field_init); + root_msg = try sema.errMsg(init_src, template, args); } } }, @@ -19453,7 +18792,7 @@ fn finishStructInit( return sema.addConstantMaybeRef(final_val.toIntern(), is_ref); }; - if (try struct_ty.comptimeOnlySema(pt)) { + if (struct_ty.comptimeOnly(zcu)) { return sema.failWithNeededComptime(block, block.src(.{ .init_elem = .{ .init_node_offset = init_src.offset.node_offset.x, .elem_index = @intCast(runtime_index), @@ -19468,9 +18807,8 @@ fn finishStructInit( } if (is_ref) { - try struct_ty.resolveLayout(pt); const target = zcu.getTarget(); - const alloc_ty = try pt.ptrTypeSema(.{ + const alloc_ty = try pt.ptrType(.{ .child = result_ty.toIntern(), .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, }); @@ -19489,7 +18827,6 @@ fn finishStructInit( .init_node_offset = init_src.offset.node_offset.x, .elem_index = @intCast(runtime_index), } })); - try struct_ty.resolveStructFieldInits(pt); const struct_val = try block.addAggregateInit(struct_ty, field_inits); return sema.coerce(block, result_ty, struct_val, init_src); } @@ -19585,12 +18922,11 @@ fn structInitAnon( break :rs runtime_index; }; - // We treat anonymous struct types as reified types, because there are similarities: - // * They use a form of structural equivalence, which we can easily model using a custom hash - // * They do not have captures - // * They immediately have their fields resolved - // In general, other code should treat anon struct types and reified struct types identically, - // so there's no point having a separate `InternPool.NamespaceType` field for them. + // We treat anonymous struct types as reified types, because there are similarities: they have + // no captures, and instead use a form of structural equivalence which we can easy represent by + // hashing the field names/types/values. They also perform layout resolution immediately. These + // similarities mean that other code should actually treat anon struct types and reified struct + // types identically anyway, so sharing the representation makes everything simpler. const type_hash: u64 = hash: { var hasher = std.hash.Wyhash.init(0); hasher.update(std.mem.sliceAsBytes(types)); @@ -19599,36 +18935,36 @@ fn structInitAnon( break :hash hasher.final(); }; const tracked_inst = try block.trackZir(inst); - const struct_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{ - .layout = .auto, + const struct_ty: Type = switch (try ip.getStructType(gpa, io, pt.tid, .{ .fields_len = extra_data.fields_len, - .known_non_opv = false, - .requires_comptime = .unknown, + .layout = .auto, + .explicit_packed_backing_type = .none, .any_comptime_fields = any_values, - .any_default_inits = any_values, - .inits_resolved = true, - .any_aligned_fields = false, + .any_field_defaults = any_values, + .any_field_aligns = false, .key = .{ .reified = .{ .zir_index = tracked_inst, .type_hash = type_hash, } }, - }, false)) { + })) { .wip => |wip| ty: { errdefer wip.cancel(ip, pt.tid); - const type_name = try sema.createTypeName(block, .anon, "struct", inst, wip.index); - wip.setName(ip, type_name.name, type_name.nav); + // MLUGG TODO obvs this sux + const anon_prefix = (try sema.createTypeName(block, .anon, "struct", inst)).anon_prefix; + wip.setName(ip, try ip.getOrPutStringFmt(gpa, io, pt.tid, "{s}_{d}", .{ anon_prefix, @intFromEnum(wip.index) }, .no_embedded_nulls), .none); const struct_type = ip.loadStructType(wip.index); - for (names, values, 0..) |name, init_val, field_idx| { - assert(struct_type.addFieldName(ip, name) == null); - if (init_val != .none) struct_type.setFieldComptime(ip, field_idx); + for (names, values) |name, init_val| { + assert(wip.nextField(ip, name, init_val != .none) == null); // AstGen validated no duplicates for us } + // Populating these means the type is already resolved; we don't need to add it to `zcu.outdated` or anything. + // That's important because type resolution relies on types being declared. @memcpy(struct_type.field_types.get(ip), types); - if (any_values) { - @memcpy(struct_type.field_inits.get(ip), values); - } + @memcpy(struct_type.field_defaults.get(ip), if (any_values) values else @as([]const InternPool.Index, &.{})); + + try type_resolution.finishStructLayout(sema, block, src, wip.index, &struct_type); const new_namespace_index = try pt.createNamespace(.{ .parent = block.namespace.toOptional(), @@ -19636,7 +18972,6 @@ fn structInitAnon( .file_scope = block.getFileScopeIndex(zcu), .generation = zcu.generation, }); - try zcu.comp.queueJob(.{ .resolve_type_fully = wip.index }); codegen_type: { if (zcu.comp.config.use_llvm) break :codegen_type; if (block.ownerModule().strip) break :codegen_type; @@ -19644,22 +18979,21 @@ fn structInitAnon( try zcu.comp.queueJob(.{ .link_type = wip.index }); } if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - break :ty wip.finish(ip, new_namespace_index); + break :ty .fromInterned(wip.finish(ip, new_namespace_index)); }, - .existing => |ty| ty, + .existing => |ty| .fromInterned(ty), }; - try sema.declareDependency(.{ .interned = struct_ty }); try sema.addTypeReferenceEntry(src, struct_ty); _ = opt_runtime_index orelse { - const struct_val = try pt.aggregateValue(.fromInterned(struct_ty), values); + const struct_val = try pt.aggregateValue(struct_ty, values); return sema.addConstantMaybeRef(struct_val.toIntern(), is_ref); }; if (is_ref) { const target = zcu.getTarget(); - const alloc_ty = try pt.ptrTypeSema(.{ - .child = struct_ty, + const alloc_ty = try pt.ptrType(.{ + .child = struct_ty.toIntern(), .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, }); const alloc = try block.addTy(.alloc, alloc_ty); @@ -19672,7 +19006,7 @@ fn structInitAnon( }; extra_index = item.end; - const field_ptr_ty = try pt.ptrTypeSema(.{ + const field_ptr_ty = try pt.ptrType(.{ .child = field_ty, .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, }); @@ -19697,7 +19031,7 @@ fn structInitAnon( element_refs[i] = try sema.resolveInst(item.data.init); } - return block.addAggregateInit(.fromInterned(struct_ty), element_refs); + return block.addAggregateInit(struct_ty, element_refs); } fn zirArrayInit( @@ -19737,17 +19071,16 @@ fn zirArrayInit( } }); // Less inits than needed. if (i + 2 > args.len) if (is_tuple) { - const default_val = array_ty.structFieldDefaultValue(i, zcu).toIntern(); - if (default_val == .unreachable_value) { + const default_val = array_ty.structFieldDefaultValue(i, zcu) orelse { const template = "missing tuple field with index {d}"; if (root_msg) |msg| { try sema.errNote(src, msg, template, .{i}); } else { root_msg = try sema.errMsg(src, template, .{i}); } - } else { - dest.* = Air.internedToRef(default_val); - } + continue; + }; + dest.* = .fromValue(default_val); continue; } else { dest.* = Air.internedToRef(sentinel_val.?.toIntern()); @@ -19759,11 +19092,9 @@ fn zirArrayInit( const elem_ty = if (is_tuple) array_ty.fieldType(i, zcu) else - array_ty.elemType2(zcu); + array_ty.childType(zcu); dest.* = try sema.coerce(block, elem_ty, resolved_arg, elem_src); if (is_tuple) { - if (array_ty.structFieldIsComptime(i, zcu)) - try array_ty.resolveStructFieldInits(pt); if (try array_ty.structFieldValueComptime(pt, i)) |field_val| { const init_val = try sema.resolveConstValue(block, elem_src, dest.*, .{ .simple = .stored_to_comptime_field }); if (!field_val.eql(init_val, elem_ty, zcu)) { @@ -19798,7 +19129,7 @@ fn zirArrayInit( if (is_ref) { const target = zcu.getTarget(); - const alloc_ty = try pt.ptrTypeSema(.{ + const alloc_ty = try pt.ptrType(.{ .child = result_ty.toIntern(), .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, }); @@ -19807,7 +19138,7 @@ fn zirArrayInit( if (is_tuple) { for (resolved_args, 0..) |arg, i| { - const elem_ptr_ty = try pt.ptrTypeSema(.{ + const elem_ptr_ty = try pt.ptrType(.{ .child = array_ty.fieldType(i, zcu).toIntern(), .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, }); @@ -19820,8 +19151,8 @@ fn zirArrayInit( return sema.makePtrConst(block, alloc); } - const elem_ptr_ty = try pt.ptrTypeSema(.{ - .child = array_ty.elemType2(zcu).toIntern(), + const elem_ptr_ty = try pt.ptrType(.{ + .child = array_ty.childType(zcu).toIntern(), .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, }); const elem_ptr_ty_ref = Air.internedToRef(elem_ptr_ty.toIntern()); @@ -19932,14 +19263,14 @@ fn arrayInitAnon( if (is_ref) { const target = sema.pt.zcu.getTarget(); - const alloc_ty = try pt.ptrTypeSema(.{ + const alloc_ty = try pt.ptrType(.{ .child = tuple_ty.toIntern(), .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, }); const alloc = try block.addTy(.alloc, alloc_ty); for (operands, 0..) |operand, i_usize| { const i: u32 = @intCast(i_usize); - const field_ptr_ty = try pt.ptrTypeSema(.{ + const field_ptr_ty = try pt.ptrType(.{ .child = types[i], .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, }); @@ -19971,6 +19302,7 @@ fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro const field_src = block.builtinCallArgSrc(inst_data.src_node, 1); const aggregate_ty = try sema.resolveType(block, ty_src, extra.container_type); const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .simple = .field_name }); + try sema.ensureLayoutResolved(aggregate_ty); return sema.fieldType(block, aggregate_ty, field_name, field_src, ty_src); } @@ -19990,9 +19322,11 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp const aggregate_ty = wrapped_aggregate_ty.optEuBaseType(zcu); const zir_field_name = sema.code.nullTerminatedString(extra.name_start); const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_field_name, .no_embedded_nulls); + try sema.ensureLayoutResolved(aggregate_ty); return sema.fieldType(block, aggregate_ty, field_name, field_name_src, ty_src); } +/// Asserts that the layout of `aggregate_ty` is resolved. fn fieldType( sema: *Sema, block: *Block, @@ -20006,7 +19340,6 @@ fn fieldType( const ip = &zcu.intern_pool; var cur_ty = aggregate_ty; while (true) { - try cur_ty.resolveFields(pt); switch (cur_ty.zigTypeTag(zcu)) { .@"struct" => switch (ip.indexToKey(cur_ty.toIntern())) { .tuple_type => |tuple| { @@ -20024,10 +19357,11 @@ fn fieldType( }, .@"union" => { const union_obj = zcu.typeToUnion(cur_ty).?; - const field_index = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse + const enum_obj = ip.loadEnumType(union_obj.enum_tag_type); + const field_index = enum_obj.nameIndex(ip, field_name) orelse return sema.failWithBadUnionFieldAccess(block, cur_ty, union_obj, field_src, field_name); const field_ty = union_obj.field_types.get(ip)[field_index]; - return Air.internedToRef(field_ty); + return .fromIntern(field_ty); }, .optional => { // Struct/array init through optional requires the child type to not be a pointer. @@ -20056,7 +19390,6 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { const zcu = pt.zcu; const ip = &zcu.intern_pool; const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace); - try stack_trace_ty.resolveFields(pt); const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern()); @@ -20064,7 +19397,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { .func => |func| if (ip.funcAnalysisUnordered(func).has_error_trace and block.ownerModule().error_tracing) { return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty); }, - .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {}, + .@"comptime", .nav_ty, .nav_val, .type_layout, .type_inits, .memoized_state => {}, } return Air.internedToRef(try pt.intern(.{ .opt = .{ .ty = opt_ptr_stack_trace_ty.toIntern(), @@ -20083,15 +19416,16 @@ fn zirFrame( } fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const zcu = sema.pt.zcu; + const pt = sema.pt; + const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const ty = try sema.resolveType(block, operand_src, inst_data.operand); if (ty.isNoReturn(zcu)) { return sema.fail(block, operand_src, "no align available for type '{f}'", .{ty.fmt(sema.pt)}); } - const val = try ty.lazyAbiAlignment(sema.pt); - return Air.internedToRef(val.toIntern()); + try sema.ensureLayoutResolved(ty); + return .fromValue(try pt.intValue(.comptime_int, ty.abiAlignment(zcu).toByteUnits().?)); } fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -20249,7 +19583,6 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; - try operand_ty.resolveLayout(pt); const enum_ty = switch (operand_ty.zigTypeTag(zcu)) { .enum_literal => { const val = (try sema.resolveDefinedValue(block, operand_src, operand)).?; @@ -20332,7 +19665,7 @@ fn zirReifySliceArgTy( // zig fmt: on }; - const operand_ty = try pt.ptrTypeSema(.{ + const operand_ty = try pt.ptrType(.{ .child = in_scalar_ty.toIntern(), .flags = .{ .size = .slice, .is_const = true }, }); @@ -20342,7 +19675,7 @@ fn zirReifySliceArgTy( const operand_val = try sema.resolveConstDefinedValue(block, src, operand_coerced, .{ .simple = comptime_reason }); const len_val: Value = .fromInterned(zcu.intern_pool.indexToKey(operand_val.toIntern()).slice.len); if (len_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, src, null); - const len = try len_val.toUnsignedIntSema(pt); + const len = len_val.toUnsignedInt(zcu); return .fromType(try pt.singleConstPtrType(try pt.arrayType(.{ .len = len, @@ -20370,7 +19703,7 @@ fn zirReifyEnumValueSliceTy( const operand_val = try sema.resolveConstDefinedValue(block, field_names_src, operand_coerced, .{ .simple = .enum_field_names }); const len_val: Value = .fromInterned(zcu.intern_pool.indexToKey(operand_val.toIntern()).slice.len); if (len_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, field_names_src, null); - const len = try len_val.toUnsignedIntSema(pt); + const len = len_val.toUnsignedInt(zcu); return .fromType(try pt.singleConstPtrType(try pt.arrayType(.{ .len = len, @@ -20422,6 +19755,7 @@ fn zirReifyTuple( if (field_ty_val.isUndef(zcu)) { return sema.failWithUseOfUndef(block, operand_src, null); } + try sema.validateTupleFieldType(block, field_ty_val.toType(), operand_src); field_ty.* = field_ty_val.toIntern(); } @@ -20516,7 +19850,7 @@ fn zirReifyPointer( } } - return .fromType(try pt.ptrTypeSema(.{ + return .fromType(try pt.ptrType(.{ .child = elem_ty.toIntern(), .sentinel = if (opt_sentinel) |s| s.toIntern() else .none, .flags = .{ @@ -20571,6 +19905,7 @@ fn zirReifyFn( const param_attrs_arr = try sema.derefSliceAsArray(block, param_attrs_src, param_attrs_slice, .{ .simple = .fn_param_attrs }); const ret_ty = try sema.resolveType(block, ret_ty_src, extra.ret_ty); + try sema.ensureLayoutResolved(ret_ty); const fn_attrs_uncoerced = try sema.resolveInst(extra.fn_attrs); const fn_attrs_coerced = try sema.coerce(block, fn_attrs_ty, fn_attrs_uncoerced, fn_attrs_src); @@ -20595,7 +19930,8 @@ fn zirReifyFn( param_types_src, fn_attrs.@"callconv", ); - if (try param_ty.comptimeOnlySema(pt)) { + try sema.ensureLayoutResolved(param_ty); + if (param_ty.comptimeOnly(zcu)) { return sema.fail(block, param_attrs_src, "cannot reify function type with comptime-only parameter type '{f}'", .{param_ty.fmt(pt)}); } if (param_attrs.@"noalias") { @@ -20621,7 +19957,7 @@ fn zirReifyFn( false, false, ); - if (try ret_ty.comptimeOnlySema(pt)) { + if (ret_ty.comptimeOnly(zcu)) { return sema.fail(block, param_attrs_src, "cannot reify function type with comptime-only return type '{f}'", .{ret_ty.fmt(pt)}); } @@ -20632,7 +19968,6 @@ fn zirReifyFn( .return_type = ret_ty.toIntern(), .cc = fn_attrs.@"callconv", .is_var_args = fn_attrs.varargs, - .is_generic = false, .is_noinline = false, })); } @@ -20791,8 +20126,7 @@ fn zirReifyStruct( field_attrs_src, .{ .simple = .struct_field_default_value }, ); - // Resolve the value so that lazy values do not create distinct types. - break :d (try sema.resolveLazyValue(deref_val)).toIntern(); + break :d deref_val.toIntern(); }; std.hash.autoHash(&hasher, .{ @@ -20823,36 +20157,31 @@ fn zirReifyStruct( } const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{ - .layout = layout, .fields_len = @intCast(fields_len), - .known_non_opv = false, - .requires_comptime = .unknown, + .layout = layout, + .explicit_packed_backing_type = if (backing_int_ty) |t| t.toIntern() else .none, .any_comptime_fields = any_comptime_fields, - .any_default_inits = any_default_inits, - .any_aligned_fields = any_aligned_fields, - .inits_resolved = true, + .any_field_defaults = any_default_inits, + .any_field_aligns = any_aligned_fields, .key = .{ .reified = .{ .zir_index = tracked_inst, .type_hash = hasher.final(), } }, - }, false)) { + })) { .wip => |wip| wip, .existing => |ty| { - try sema.declareDependency(.{ .interned = ty }); - try sema.addTypeReferenceEntry(src, ty); - return Air.internedToRef(ty); + try sema.addTypeReferenceEntry(src, .fromInterned(ty)); + return .fromIntern(ty); }, }; errdefer wip_ty.cancel(ip, pt.tid); - const type_name = try sema.createTypeName( + _ = try (try sema.createTypeName( block, name_strategy, "struct", inst, - wip_ty.index, - ); - wip_ty.setName(ip, type_name.name, type_name.nav); + )).apply(&wip_ty, pt); const wip_struct_type = ip.loadStructType(wip_ty.index); @@ -20860,38 +20189,27 @@ fn zirReifyStruct( const field_name_val = try field_names_arr.elemValue(pt, field_idx); const field_attrs_val = try field_attrs_arr.elemValue(pt, field_idx); - const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType(); - // Don't pass a reason; first loop acts as a check that this is valid. const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined); - if (wip_struct_type.addFieldName(ip, field_name)) |prev_index| { + const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType(); + const field_attr_comptime = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex( + std.builtin.Type.StructField.Attributes, + "comptime", + ).?); + const field_attr_align = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex( + std.builtin.Type.StructField.Attributes, + "align", + ).?); + const field_attr_default_value_ptr = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex( + std.builtin.Type.StructField.Attributes, + "default_value_ptr", + ).?); + + if (wip_ty.nextField(ip, field_name, field_attr_comptime.toBool())) |prev_index| { _ = prev_index; // TODO: better source location return sema.fail(block, field_names_src, "duplicate struct field name {f}", .{field_name.fmt(ip)}); } - const field_attr_comptime = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex( - std.builtin.Type.StructField.Attributes, - "comptime", - ).?); - const field_attr_align = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex( - std.builtin.Type.StructField.Attributes, - "align", - ).?); - const field_attr_default_value_ptr = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex( - std.builtin.Type.StructField.Attributes, - "default_value_ptr", - ).?); - - if (field_attr_align.optionalValue(zcu)) |field_align_val| { - assert(layout != .@"packed"); - const bytes = try field_align_val.toUnsignedIntSema(pt); - const a = try sema.validateAlign(block, field_attrs_src, bytes); - wip_struct_type.field_aligns.get(ip)[field_idx] = a; - } else if (any_aligned_fields) { - assert(layout != .@"packed"); - wip_struct_type.field_aligns.get(ip)[field_idx] = .none; - } - const field_default: InternPool.Index = d: { const ptr_val = field_attr_default_value_ptr.optionalValue(zcu) orelse break :d .none; assert(any_default_inits); @@ -20902,20 +20220,11 @@ fn zirReifyStruct( if (deref_val.canMutateComptimeVarState(zcu)) { return sema.failWithContainsReferenceToComptimeVar(block, field_attrs_src, field_name, "field default value", deref_val); } - break :d (try sema.resolveLazyValue(deref_val)).toIntern(); + break :d deref_val.toIntern(); }; - if (field_attr_comptime.toBool()) { - assert(layout == .auto); - if (field_default == .none) { - return sema.fail(block, field_attrs_src, "comptime field without default initialization value", .{}); - } - wip_struct_type.setFieldComptime(ip, field_idx); - } - - wip_struct_type.field_types.get(ip)[field_idx] = field_ty.toIntern(); - if (field_default != .none) { - wip_struct_type.field_inits.get(ip)[field_idx] = field_default; + if (field_attr_comptime.toBool() and field_default == .none) { + return sema.fail(block, field_attrs_src, "comptime field without default initialization value", .{}); } switch (field_ty.zigTypeTag(zcu)) { @@ -20945,32 +20254,55 @@ fn zirReifyStruct( break :msg msg; }); }, - .@"packed" => if (!try sema.validatePackedType(field_ty)) { + .@"packed" => if (!field_ty.packable(zcu)) { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(field_types_src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); errdefer msg.destroy(gpa); - try sema.explainWhyTypeIsNotPacked(msg, field_types_src, field_ty); + try sema.explainWhyTypeIsNotPackable(msg, field_types_src, field_ty); try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; }); }, } + + wip_struct_type.field_types.get(ip)[field_idx] = field_ty.toIntern(); + if (field_default != .none) { + wip_struct_type.field_defaults.get(ip)[field_idx] = field_default; + } + + if (field_attr_align.optionalValue(zcu)) |field_align_val| { + assert(layout != .@"packed"); + const bytes = field_align_val.toUnsignedInt(zcu); + const a = try sema.validateAlign(block, field_attrs_src, bytes); + wip_struct_type.field_aligns.get(ip)[field_idx] = a; + } else if (any_aligned_fields) { + assert(layout != .@"packed"); + wip_struct_type.field_aligns.get(ip)[field_idx] = .none; + } } if (layout == .@"packed") { - var fields_bit_sum: u64 = 0; - for (0..wip_struct_type.field_types.len) |field_idx| { + var field_bits: u64 = 0; + for (0..fields_len) |field_idx| { const field_ty: Type = .fromInterned(wip_struct_type.field_types.get(ip)[field_idx]); - try field_ty.resolveLayout(pt); - fields_bit_sum += field_ty.bitSize(zcu); - } - if (backing_int_ty) |ty| { - try sema.checkBackingIntType(block, src, ty, fields_bit_sum); - wip_struct_type.setBackingIntType(ip, io, ty.toIntern()); - } else { - const ty = try pt.intType(.unsigned, @intCast(fields_bit_sum)); - wip_struct_type.setBackingIntType(ip, io, ty.toIntern()); + try sema.ensureLayoutResolved(field_ty); + field_bits += field_ty.bitSize(zcu); } + try type_resolution.resolvePackedStructBackingInt( + sema, + block, + field_bits, + .fromInterned(wip_ty.index), + &wip_struct_type, + ); + } else { + try type_resolution.finishStructLayout( + sema, + block, + src, + wip_ty.index, + &wip_struct_type, + ); } const new_namespace_index = try pt.createNamespace(.{ @@ -20980,16 +20312,13 @@ fn zirReifyStruct( .generation = zcu.generation, }); - try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); codegen_type: { if (zcu.comp.config.use_llvm) break :codegen_type; if (block.ownerModule().strip) break :codegen_type; - // This job depends on any resolve_type_fully jobs queued up before it. zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); } - try sema.declareDependency(.{ .interned = wip_ty.index }); - try sema.addTypeReferenceEntry(src, wip_ty.index); + try sema.addTypeReferenceEntry(src, .fromInterned(wip_ty.index)); if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); return .fromIntern(wip_ty.finish(ip, new_namespace_index)); } @@ -21134,62 +20463,52 @@ fn zirReifyUnion( } // Some basic validation to avoid a bogus `getUnionType` call... - const explicit_tag_ty: ?Type = if (arg_ty_val.optionalValue(zcu)) |arg_ty| ty: { + const explicit_tag_ty: ?Type, const explicit_packed_backing_type: ?Type = ty: { + const arg_ty = arg_ty_val.optionalValue(zcu) orelse break :ty .{ null, null }; switch (layout) { - .@"extern", .@"packed" => return sema.fail(block, arg_ty_src, "{t} union does not support enum tag type", .{layout}), - .auto => {}, + .@"extern" => return sema.fail(block, arg_ty_src, "extern union does not support enum tag type", .{}), + .@"packed" => break :ty .{ null, arg_ty.toType() }, + .auto => break :ty .{ arg_ty.toType(), null }, } - break :ty arg_ty.toType(); - } else null; + }; if (any_aligned_fields and layout == .@"packed") { return sema.fail(block, field_attrs_src, "packed union fields cannot be aligned", .{}); } const wip_ty = switch (try ip.getUnionType(gpa, io, pt.tid, .{ - .flags = .{ - .layout = layout, - .status = .none, - .runtime_tag = rt: { - if (explicit_tag_ty != null) break :rt .tagged; - if (layout == .auto and block.wantSafeTypes()) break :rt .safety; - break :rt .none; - }, - .any_aligned_fields = any_aligned_fields, - .requires_comptime = .unknown, - .assumed_runtime_bits = false, - .assumed_pointer_aligned = false, - .alignment = .none, - }, .fields_len = @intCast(fields_len), - .enum_tag_ty = .none, // set later because not yet validated - .field_types = &.{}, // set later - .field_aligns = &.{}, // set later + .layout = layout, + .explicit_packed_backing_type = if (explicit_packed_backing_type) |t| t.toIntern() else .none, + .runtime_tag = rt: { + if (explicit_tag_ty != null) break :rt .tagged; + if (layout == .auto and block.wantSafeTypes()) break :rt .safety; + break :rt .none; + }, + .have_explicit_enum_tag = explicit_tag_ty != null, + .any_field_aligns = any_aligned_fields, .key = .{ .reified = .{ .zir_index = tracked_inst, .type_hash = hasher.final(), } }, - }, false)) { + })) { .wip => |wip| wip, .existing => |ty| { - try sema.declareDependency(.{ .interned = ty }); - try sema.addTypeReferenceEntry(src, ty); - return Air.internedToRef(ty); + try sema.addTypeReferenceEntry(src, .fromInterned(ty)); + return .fromIntern(ty); }, }; errdefer wip_ty.cancel(ip, pt.tid); - const type_name = try sema.createTypeName( + const type_name = try (try sema.createTypeName( block, name_strategy, "union", inst, - wip_ty.index, - ); - wip_ty.setName(ip, type_name.name, type_name.nav); + )).apply(&wip_ty, pt); const loaded_union = ip.loadUnionType(wip_ty.index); - const enum_tag_ty, const has_explicit_tag = if (explicit_tag_ty) |enum_tag_ty| tag: { + const generated_tag_ty: InternPool.Index = if (explicit_tag_ty) |enum_tag_ty| generated_tag: { if (enum_tag_ty.zigTypeTag(zcu) != .@"enum") { return sema.fail(block, arg_ty_src, "tag type must be an enum type", .{}); } @@ -21227,26 +20546,67 @@ fn zirReifyUnion( try sema.addDeclaredHereNote(msg, enum_tag_ty); break :msg msg; }); - break :tag .{ enum_tag_ty.toIntern(), true }; - } else tag: { - // We must track field names and set up the tag type ourselves. - var field_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty; - try field_names.ensureTotalCapacity(sema.arena, fields_len); + wip_ty.setTagType(ip, enum_tag_ty.toIntern()); + break :generated_tag .none; + } else generated_tag: { + // Generate the union's hypothetical tag type. + const wip_tag_ty = switch (try ip.getEnumType(gpa, io, pt.tid, .{ + .fields_len = @intCast(fields_len), + .explicit_int_tag_type = .none, + .nonexhaustive = false, + .key = .{ .generated_union_tag = wip_ty.index }, + })) { + .existing => unreachable, // enum type is keyed on this union type which we're only just creating + .wip => |wip_tag_ty| wip_tag_ty, + }; + errdefer wip_tag_ty.cancel(ip, pt.tid); + // Set its name based on the union's name + _ = wip_tag_ty.setName(ip, try ip.getOrPutStringFmt( + gpa, + io, + pt.tid, + "@typeInfo({f}).@\"union\".tag_type.?", + .{type_name.fmt(ip)}, + .no_embedded_nulls, + ), .none); + + // Populate its fields (and report any duplicates) for (0..fields_len) |field_idx| { const field_name_val = try field_names_arr.elemValue(pt, field_idx); // Don't pass a reason; first loop acts as a check that this is valid. const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined); - const gop = field_names.getOrPutAssumeCapacity(field_name); - if (gop.found_existing) { - // TODO: better source location - return sema.fail(block, field_names_src, "duplicate union field {f}", .{field_name.fmt(ip)}); - } + if (wip_tag_ty.nextField(ip, field_name, false)) |prev_field_idx| return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(src, "duplicate union field '{f}' at index '{d}", .{ field_name.fmt(ip), field_idx }); + errdefer msg.destroy(gpa); + try sema.errNote(src, msg, "previous field at index '{d}'", .{prev_field_idx}); + break :msg msg; + }); } - const enum_tag_ty = try sema.generateUnionTagTypeSimple(block, field_names.keys(), wip_ty.index, type_name.name); - break :tag .{ enum_tag_ty, false }; + + // Populate the enum tag type's *integer* tag type + wip_tag_ty.setTagType(ip, int_tag_ty: { + // Infer the int tag type from the field count + const bits = Type.smallestUnsignedBits(fields_len -| 1); + break :int_tag_ty (try pt.intType(.unsigned, bits)).toIntern(); + }); + + // Lastly, it needs a dummy namespace + const enum_tag_type_namespace = try pt.createNamespace(.{ + .parent = block.namespace.toOptional(), + .owner_type = wip_tag_ty.index, + .file_scope = block.getFileScopeIndex(zcu), + .generation = zcu.generation, + }); + errdefer pt.destroyNamespace(enum_tag_type_namespace); + + wip_ty.setTagType(ip, wip_tag_ty.index); + + break :generated_tag wip_tag_ty.finish(ip, enum_tag_type_namespace); }; - errdefer if (!has_explicit_tag) ip.remove(pt.tid, enum_tag_ty); // remove generated tag type on error + // If we fail to create the union type, we must delete the generated enum tag type, since it + // would hold a reference to the deleted union. + errdefer if (generated_tag_ty != .none) ip.remove(pt.tid, generated_tag_ty); for (0..fields_len) |field_idx| { const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType(); @@ -21279,12 +20639,12 @@ fn zirReifyUnion( break :msg msg; }); }, - .@"packed" => if (!try sema.validatePackedType(field_ty)) { + .@"packed" => if (!field_ty.packable(zcu)) { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(field_types_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); errdefer msg.destroy(gpa); - try sema.explainWhyTypeIsNotPacked(msg, field_types_src, field_ty); + try sema.explainWhyTypeIsNotPackable(msg, field_types_src, field_ty); try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; @@ -21303,8 +20663,24 @@ fn zirReifyUnion( } } - loaded_union.setTagType(ip, io, enum_tag_ty); - loaded_union.setStatus(ip, io, .have_field_types); + if (layout == .@"packed") { + try type_resolution.resolvePackedUnionBackingInt( + sema, + block, + .fromInterned(wip_ty.index), + &loaded_union, + true, + ); + } else { + try type_resolution.finishUnionLayout( + sema, + block, + src, + wip_ty.index, + &loaded_union, + explicit_tag_ty orelse .fromInterned(generated_tag_ty), + ); + } const new_namespace_index = try pt.createNamespace(.{ .parent = block.namespace.toOptional(), @@ -21313,17 +20689,16 @@ fn zirReifyUnion( .generation = zcu.generation, }); - try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); codegen_type: { if (zcu.comp.config.use_llvm) break :codegen_type; if (block.ownerModule().strip) break :codegen_type; - // This job depends on any resolve_type_fully jobs queued up before it. zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); } - try sema.declareDependency(.{ .interned = wip_ty.index }); - try sema.addTypeReferenceEntry(src, wip_ty.index); - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); + try sema.addTypeReferenceEntry(src, .fromInterned(wip_ty.index)); + if (zcu.comp.debugIncremental()) { + try zcu.incremental_debug_state.newType(zcu, wip_ty.index); + } return .fromIntern(wip_ty.finish(ip, new_namespace_index)); } @@ -21436,86 +20811,84 @@ fn zirReifyEnum( } const wip_ty = switch (try ip.getEnumType(gpa, io, pt.tid, .{ - .has_values = true, - .tag_mode = if (nonexhaustive) .nonexhaustive else .explicit, .fields_len = @intCast(fields_len), + .explicit_int_tag_type = tag_ty.toIntern(), + .nonexhaustive = nonexhaustive, .key = .{ .reified = .{ .zir_index = tracked_inst, .type_hash = hasher.final(), } }, - }, false)) { + })) { .wip => |wip| wip, .existing => |ty| { - try sema.declareDependency(.{ .interned = ty }); - try sema.addTypeReferenceEntry(src, ty); + try sema.addTypeReferenceEntry(src, .fromInterned(ty)); return .fromIntern(ty); }, }; - var done = false; - errdefer if (!done) wip_ty.cancel(ip, pt.tid); + errdefer wip_ty.cancel(ip, pt.tid); - const type_name = try sema.createTypeName( + _ = try (try sema.createTypeName( block, name_strategy, "enum", inst, - wip_ty.index, - ); - wip_ty.setName(ip, type_name.name, type_name.nav); - - const new_namespace_index = try pt.createNamespace(.{ - .parent = block.namespace.toOptional(), - .owner_type = wip_ty.index, - .file_scope = block.getFileScopeIndex(zcu), - .generation = zcu.generation, - }); - - try sema.declareDependency(.{ .interned = wip_ty.index }); - try sema.addTypeReferenceEntry(src, wip_ty.index); - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); - wip_ty.prepare(ip, new_namespace_index); - wip_ty.setTagTy(ip, tag_ty.toIntern()); - done = true; + )).apply(&wip_ty, pt); for (0..fields_len) |field_idx| { const field_name_val = try field_names_arr.elemValue(pt, field_idx); // Don't pass a reason; first loop acts as a check that this is valid. const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined); + if (wip_ty.nextField(ip, field_name, false)) |prev_field_idx| return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(field_names_src, "duplicate enum field '{f}' at index '{d}'", .{ field_name.fmt(ip), field_idx }); + errdefer msg.destroy(gpa); + try sema.errNote(field_names_src, msg, "previous field at index '{d}'", .{prev_field_idx}); + break :msg msg; + }); + } + const enum_obj = ip.loadEnumType(wip_ty.index); + const field_value_map = enum_obj.field_value_map.unwrap().?; + for (0..fields_len) |field_idx| { const field_val = try field_values_arr.elemValue(pt, field_idx); - - if (wip_ty.nextField(ip, field_name, field_val.toIntern())) |conflict| { - return sema.failWithOwnedErrorMsg(block, switch (conflict.kind) { - .name => msg: { - const msg = try sema.errMsg(field_names_src, "duplicate enum field '{f}'", .{field_name.fmt(ip)}); - errdefer msg.destroy(gpa); - _ = conflict.prev_field_idx; // TODO: this note is incorrect - try sema.errNote(field_names_src, msg, "other field here", .{}); - break :msg msg; - }, - .value => msg: { - const msg = try sema.errMsg(field_values_src, "enum tag value {f} already taken", .{field_val.fmtValueSema(pt, sema)}); - errdefer msg.destroy(gpa); - _ = conflict.prev_field_idx; // TODO: this note is incorrect - try sema.errNote(field_values_src, msg, "other enum tag value here", .{}); - break :msg msg; - }, + const field_values = enum_obj.field_values.get(ip); + field_values[field_idx] = field_val.toIntern(); + const adapter: InternPool.Index.Adapter = .{ .indexes = field_values[0..field_idx] }; + const gop = field_value_map.get(ip).getOrPutAssumeCapacityAdapted(field_val.toIntern(), adapter); + if (gop.found_existing) return sema.failWithOwnedErrorMsg(block, msg: { + const field_names = enum_obj.field_names.get(ip); + const this_field_name = field_names[field_idx]; + const prev_field_name = field_names[gop.index]; + const msg = try sema.errMsg(field_names_src, "duplicate enum tag value '{f}' in field '{f}'", .{ + field_val.fmtValueSema(pt, sema), + this_field_name.fmt(ip), }); - } + errdefer msg.destroy(gpa); + try sema.errNote(field_names_src, msg, "previous usage in field '{f}'", .{prev_field_name.fmt(ip)}); + break :msg msg; + }); } if (nonexhaustive and fields_len > 1 and std.math.log2_int(u64, fields_len) == tag_ty.bitSize(zcu)) { return sema.fail(block, src, "non-exhaustive enum specified every value", .{}); } + const new_namespace_index = try pt.createNamespace(.{ + .parent = block.namespace.toOptional(), + .owner_type = wip_ty.index, + .file_scope = block.getFileScopeIndex(zcu), + .generation = zcu.generation, + }); + codegen_type: { if (zcu.comp.config.use_llvm) break :codegen_type; if (block.ownerModule().strip) break :codegen_type; - // This job depends on any resolve_type_fully jobs queued up before it. zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); } - return Air.internedToRef(wip_ty.index); + + try sema.addTypeReferenceEntry(src, .fromInterned(wip_ty.index)); + if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); + return .fromIntern(wip_ty.finish(ip, new_namespace_index)); } fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref { @@ -21573,7 +20946,8 @@ fn zirCVaEnd(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C const va_list_ref = try sema.resolveVaListRef(block, va_list_src, extra.operand); try sema.requireRuntimeBlock(block, src, null); - return block.addUnOp(.c_va_end, va_list_ref); + _ = try block.addUnOp(.c_va_end, va_list_ref); + return .void_value; } fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { @@ -21683,8 +21057,20 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro _ = try sema.checkIntType(block, operand_src, operand_scalar_ty); if (try sema.resolveValue(operand)) |operand_val| { - const result_val = try operand_val.floatFromIntAdvanced(sema.arena, operand_ty, dest_ty, pt, .sema); - return Air.internedToRef(result_val.toIntern()); + if (operand_val.isUndef(zcu)) return .fromValue(try pt.undefValue(dest_ty)); + if (dest_ty.zigTypeTag(zcu) != .vector) { + return .fromValue(try pt.floatValue(dest_ty, operand_val.toFloat(f128, zcu))); + } + const dest_elems = try sema.arena.alloc(InternPool.Index, dest_ty.vectorLen(zcu)); + for (dest_elems, 0..) |*out_elem, elem_idx| { + const orig_elem = try operand_val.elemValue(pt, elem_idx); + const casted_elem = if (orig_elem.isUndef(zcu)) + try pt.undefValue(dest_scalar_ty) + else + try pt.floatValue(dest_scalar_ty, orig_elem.toFloat(f128, zcu)); + out_elem.* = casted_elem.toIntern(); + } + return .fromValue(try pt.aggregateValue(dest_ty, dest_elems)); } else if (dest_scalar_ty.zigTypeTag(zcu) == .comptime_float) { return sema.failWithNeededComptime(block, operand_src, .{ .simple = .casted_to_comptime_float }); } @@ -21719,8 +21105,11 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const ptr_ty = dest_ty.scalarType(zcu); try sema.checkPtrType(block, src, ptr_ty, true); - const elem_ty = ptr_ty.elemType2(zcu); - const ptr_align = try ptr_ty.ptrAlignmentSema(pt); + const elem_ty = ptr_ty.nullablePtrElem(zcu); + + // We'll need to validate the pointer alignment. + try sema.ensureLayoutResolved(elem_ty); + const ptr_align = ptr_ty.ptrAlignment(zcu); if (ptr_ty.isSlice(zcu)) { const msg = msg: { @@ -21746,18 +21135,9 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! } return Air.internedToRef((try pt.aggregateValue(dest_ty, new_elems)).toIntern()); } - if (try ptr_ty.comptimeOnlySema(pt)) { - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(src, "pointer to comptime-only type '{f}' must be comptime-known, but operand is runtime-known", .{ptr_ty.fmt(pt)}); - errdefer msg.destroy(sema.gpa); - - try sema.explainWhyTypeIsComptime(msg, src, ptr_ty); - break :msg msg; - }); - } try sema.requireRuntimeBlock(block, src, operand_src); try sema.checkLogicalPtrOperation(block, src, ptr_ty); - if (block.wantSafety() and (try elem_ty.hasRuntimeBitsSema(pt) or elem_ty.zigTypeTag(zcu) == .@"fn")) { + if (block.wantSafety()) { if (!ptr_ty.isAllowzeroPtr(zcu)) { const is_non_zero = if (is_vector) all_non_zero: { const zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern()); @@ -21804,7 +21184,7 @@ fn ptrFromIntVal( } return sema.failWithUseOfUndef(block, operand_src, vec_idx); } - const addr = try operand_val.toUnsignedIntSema(pt); + const addr = operand_val.toUnsignedInt(zcu); if (!ptr_ty.isAllowzeroPtr(zcu) and addr == 0) return sema.fail(block, operand_src, "pointer type '{f}' does not allow address zero", .{ptr_ty.fmt(pt)}); if (addr != 0 and ptr_align != .none) { @@ -22043,8 +21423,8 @@ fn ptrCastFull( const src_info = operand_ty.ptrInfo(zcu); const dest_info = dest_ty.ptrInfo(zcu); - try Type.fromInterned(src_info.child).resolveLayout(pt); - try Type.fromInterned(dest_info.child).resolveLayout(pt); + try sema.ensureLayoutResolved(.fromInterned(src_info.child)); + try sema.ensureLayoutResolved(.fromInterned(dest_info.child)); const DestSliceLen = union(enum) { undef, @@ -22079,9 +21459,9 @@ fn ptrCastFull( .pointer => operand_val, else => unreachable, }; - const slice_len_resolved = try sema.resolveLazyValue(.fromInterned(zcu.intern_pool.sliceLen(slice_val.toIntern()))); - if (slice_len_resolved.isUndef(zcu)) break :len .undef; - break :src .{ .fromInterned(src_info.child), slice_len_resolved.toUnsignedInt(zcu) }; + const slice_len: Value = .fromInterned(zcu.intern_pool.sliceLen(slice_val.toIntern())); + if (slice_len.isUndef(zcu)) break :len .undef; + break :src .{ .fromInterned(src_info.child), slice_len.toUnsignedInt(zcu) }; }, .many, .c => { return sema.fail(block, src, "cannot infer length of slice from {s}", .{pointerSizeString(src_info.flags.size)}); @@ -22395,7 +21775,7 @@ fn ptrCastFull( }; if (dest_align.compare(.gt, src_align)) { - if (try ptr_val.getUnsignedIntSema(pt)) |addr| { + if (ptr_val.getUnsignedInt(zcu)) |addr| { const masked_addr = if (Type.fromInterned(dest_info.child).fnPtrMaskOrNull(zcu)) |mask| addr & mask else @@ -22464,7 +21844,7 @@ fn ptrCastFull( // Now, do an addrspace cast if necessary! if (!flags.addrspace_cast) break :ptr pre_addrspace_cast; - const intermediate_ptr_ty = try pt.ptrTypeSema(info: { + const intermediate_ptr_ty = try pt.ptrType(info: { var info = src_info; info.flags.address_space = dest_info.flags.address_space; break :info info; @@ -22638,7 +22018,7 @@ fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst if (flags.volatile_cast) ptr_info.flags.is_volatile = false; const dest_ty = blk: { - const dest_ty = try pt.ptrTypeSema(ptr_info); + const dest_ty = try pt.ptrType(ptr_info); if (operand_ty.zigTypeTag(zcu) == .optional) { break :blk try pt.optionalType(dest_ty.toIntern()); } @@ -22678,48 +22058,24 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai return sema.coerce(block, dest_ty, operand, operand_src); } + if (try dest_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); + const dest_info = dest_scalar_ty.intInfo(zcu); - if (try sema.typeHasOnePossibleValue(dest_ty)) |val| { - return Air.internedToRef(val.toIntern()); - } - if (operand_scalar_ty.zigTypeTag(zcu) != .comptime_int) { const operand_info = operand_ty.intInfo(zcu); - if (try sema.typeHasOnePossibleValue(operand_ty)) |val| { - return Air.internedToRef(val.toIntern()); - } if (operand_info.signedness != dest_info.signedness) { return sema.fail(block, operand_src, "expected {s} integer type, found '{f}'", .{ @tagName(dest_info.signedness), operand_ty.fmt(pt), }); } - switch (std.math.order(dest_info.bits, operand_info.bits)) { - .gt => { - const msg = msg: { - const msg = try sema.errMsg( - src, - "destination type '{f}' has more bits than source type '{f}'", - .{ dest_ty.fmt(pt), operand_ty.fmt(pt) }, - ); - errdefer msg.destroy(sema.gpa); - try sema.errNote(src, msg, "destination type has {d} bits", .{ - dest_info.bits, - }); - try sema.errNote(operand_src, msg, "operand type has {d} bits", .{ - operand_info.bits, - }); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); - }, - .eq => return operand, - .lt => {}, + if (dest_info.bits >= operand_info.bits) { + return sema.coerce(block, dest_ty, operand, operand_src); } } - if (try sema.resolveValueResolveLazy(operand)) |val| { + if (try sema.resolveValue(operand)) |val| { const result_val = try arith.truncate(sema, val, operand_ty, dest_ty, dest_info.signedness, dest_info.bits); return Air.internedToRef(result_val.toIntern()); } @@ -22745,10 +22101,6 @@ fn zirBitCount( _ = try sema.checkIntOrVector(block, operand, operand_src); const bits = operand_ty.intInfo(zcu).bits; - if (try sema.typeHasOnePossibleValue(operand_ty)) |val| { - return Air.internedToRef(val.toIntern()); - } - const result_scalar_ty = try pt.smallestUnsignedInt(bits); switch (operand_ty.zigTypeTag(zcu)) { .vector => { @@ -22774,7 +22126,7 @@ fn zirBitCount( } }, .int => { - if (try sema.resolveValueResolveLazy(operand)) |val| { + if (try sema.resolveValue(operand)) |val| { if (val.isUndef(zcu)) return pt.undefRef(result_scalar_ty); return pt.intRef(result_scalar_ty, comptimeOp(val, operand_ty, zcu)); } else { @@ -22803,9 +22155,6 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .{ scalar_ty.fmt(pt), bits }, ); } - if (try sema.typeHasOnePossibleValue(operand_ty)) |val| { - return .fromValue(val); - } if (try sema.resolveValue(operand)) |operand_val| { return .fromValue(try arith.byteSwap(sema, operand_val, operand_ty)); } @@ -22819,9 +22168,6 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const operand_ty = sema.typeOf(operand); _ = try sema.checkIntOrVector(block, operand, operand_src); - if (try sema.typeHasOnePossibleValue(operand_ty)) |val| { - return .fromValue(val); - } if (try sema.resolveValue(operand)) |operand_val| { return .fromValue(try arith.bitReverse(sema, operand_val, operand_ty)); } @@ -22849,10 +22195,11 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 const ty = try sema.resolveType(block, ty_src, extra.lhs); const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.rhs, .{ .simple = .field_name }); + try sema.ensureLayoutResolved(ty); + const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; - try ty.resolveLayout(pt); switch (ty.zigTypeTag(zcu)) { .@"struct" => {}, else => return sema.fail(block, ty_src, "expected struct type, found '{f}'", .{ty.fmt(pt)}), @@ -23126,7 +22473,7 @@ fn checkAtomicPtrOperand( const ptr_data = switch (ptr_ty.zigTypeTag(zcu)) { .pointer => ptr_ty.ptrInfo(zcu), else => { - const wanted_ptr_ty = try pt.ptrTypeSema(wanted_ptr_data); + const wanted_ptr_ty = try pt.ptrType(wanted_ptr_data); _ = try sema.coerce(block, wanted_ptr_ty, ptr, ptr_src); unreachable; }, @@ -23136,7 +22483,7 @@ fn checkAtomicPtrOperand( wanted_ptr_data.flags.is_allowzero = ptr_data.flags.is_allowzero; wanted_ptr_data.flags.is_volatile = ptr_data.flags.is_volatile; - const wanted_ptr_ty = try pt.ptrTypeSema(wanted_ptr_data); + const wanted_ptr_ty = try pt.ptrType(wanted_ptr_data); const casted_ptr = try sema.coerce(block, wanted_ptr_ty, ptr, ptr_src); return casted_ptr; @@ -23470,11 +22817,8 @@ fn zirCmpxchg( const result_ty = try pt.optionalType(elem_ty.toIntern()); // special case zero bit types - if ((try sema.typeHasOnePossibleValue(elem_ty)) != null) { - return Air.internedToRef((try pt.intern(.{ .opt = .{ - .ty = result_ty.toIntern(), - .val = .none, - } }))); + if (try elem_ty.onePossibleValue(pt) != null) { + return .fromValue(try pt.nullValue(result_ty)); } const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: { @@ -23537,11 +22881,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I const len = try sema.usizeCast(block, src, dest_ty.arrayLen(zcu)); - if (try sema.typeHasOnePossibleValue(dest_ty)) |val| { - return Air.internedToRef(val.toIntern()); - } - - // We also need this case because `[0:s]T` is not OPV. + // If the length is 0, the result is comptime-known even if the operand isn't. if (len == 0) return .fromValue(try pt.aggregateValue(dest_ty, &.{})); const maybe_sentinel = dest_ty.sentinel(zcu); @@ -23733,7 +23073,7 @@ fn analyzeShuffle( continue; } // Safe because mask elements are `i32` and we already checked for undef: - const raw = (try sema.resolveLazyValue(mask_val)).toSignedInt(zcu); + const raw = mask_val.toSignedInt(zcu); if (raw >= 0) { const idx: u32 = @intCast(raw); a_used = true; @@ -23938,6 +23278,8 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const ptr = try sema.checkAtomicPtrOperand(block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, true); const order = try sema.resolveAtomicOrder(block, order_src, extra.ordering, .{ .simple = .atomic_order }); + try sema.ensureLayoutResolved(elem_ty); + switch (order) { .release, .acq_rel => { return sema.fail( @@ -23950,9 +23292,7 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! else => {}, } - if (try sema.typeHasOnePossibleValue(elem_ty)) |val| { - return Air.internedToRef(val.toIntern()); - } + if (try elem_ty.onePossibleValue(sema.pt)) |opv| return .fromValue(opv); if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { if (try sema.pointerDeref(block, ptr_src, ptr_val, sema.typeOf(ptr))) |elem_val| { @@ -24009,9 +23349,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A } // special case zero bit types - if (try sema.typeHasOnePossibleValue(elem_ty)) |val| { - return Air.internedToRef(val.toIntern()); - } + if (try elem_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: { const maybe_operand_val = try sema.resolveValue(operand); @@ -24260,11 +23598,11 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins return sema.fail(block, inst_src, "expected single pointer type, found '{f}'", .{parent_ptr_ty.fmt(pt)}); } const parent_ty: Type = .fromInterned(parent_ptr_info.child); + try sema.ensureLayoutResolved(parent_ty); switch (parent_ty.zigTypeTag(zcu)) { .@"struct", .@"union" => {}, else => return sema.fail(block, inst_src, "expected pointer to struct or union type, found '{f}'", .{parent_ptr_ty.fmt(pt)}), } - try parent_ty.resolveLayout(pt); const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.field_name, .{ .simple = .field_name }); const field_index = switch (parent_ty.zigTypeTag(zcu)) { @@ -24293,7 +23631,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins var actual_parent_ptr_info: InternPool.Key.PtrType = .{ .child = parent_ty.toIntern(), .flags = .{ - .alignment = try parent_ptr_ty.ptrAlignmentSema(pt), + .alignment = parent_ptr_ty.ptrAlignment(zcu), .is_const = field_ptr_info.flags.is_const, .is_volatile = field_ptr_info.flags.is_volatile, .is_allowzero = field_ptr_info.flags.is_allowzero, @@ -24305,7 +23643,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins var actual_field_ptr_info: InternPool.Key.PtrType = .{ .child = field_ty.toIntern(), .flags = .{ - .alignment = try field_ptr_ty.ptrAlignmentSema(pt), + .alignment = field_ptr_ty.ptrAlignment(zcu), .is_const = field_ptr_info.flags.is_const, .is_volatile = field_ptr_info.flags.is_volatile, .is_allowzero = field_ptr_info.flags.is_allowzero, @@ -24315,23 +23653,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins }; switch (parent_ty.containerLayout(zcu)) { .auto => { - actual_parent_ptr_info.flags.alignment = actual_field_ptr_info.flags.alignment.minStrict( - if (zcu.typeToStruct(parent_ty)) |struct_obj| - try field_ty.structFieldAlignmentSema( - struct_obj.fieldAlign(ip, field_index), - struct_obj.layout, - pt, - ) - else if (zcu.typeToUnion(parent_ty)) |union_obj| - try field_ty.unionFieldAlignmentSema( - union_obj.fieldAlign(ip, field_index), - union_obj.flagsUnordered(ip).layout, - pt, - ) - else - actual_field_ptr_info.flags.alignment, - ); - + actual_parent_ptr_info.flags.alignment = parent_ty.resolvedFieldAlignment(field_index, zcu); actual_parent_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 }; actual_field_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 }; }, @@ -24357,9 +23679,9 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins }, } - const actual_field_ptr_ty = try pt.ptrTypeSema(actual_field_ptr_info); + const actual_field_ptr_ty = try pt.ptrType(actual_field_ptr_info); const casted_field_ptr = try sema.coerce(block, actual_field_ptr_ty, field_ptr, field_ptr_src); - const actual_parent_ptr_ty = try pt.ptrTypeSema(actual_parent_ptr_info); + const actual_parent_ptr_ty = try pt.ptrType(actual_parent_ptr_info); const result = if (try sema.resolveDefinedValue(block, field_ptr_src, casted_field_ptr)) |field_ptr_val| result: { switch (parent_ty.zigTypeTag(zcu)) { @@ -24590,7 +23912,7 @@ fn analyzeMinMax( const operand_scalar_ty = sema.typeOf(operand).scalarType(zcu); const want_strat: TypeStrat = switch (operand_scalar_ty.zigTypeTag(zcu)) { .comptime_int => s: { - const val = (try sema.resolveValueResolveLazy(operand)).?; + const val = (try sema.resolveValue(operand)).?; if (val.isUndef(zcu)) break :s .none; break :s .{ .int = .{ .all_comptime_int = true, @@ -24609,7 +23931,7 @@ fn analyzeMinMax( // (replaced with just the simple calls to `Type.minInt`/`Type.maxInt`) so that we only // use the input *types* to determine the result type. const min: Value, const max: Value = bounds: { - if (try sema.resolveValueResolveLazy(operand)) |operand_val| { + if (try sema.resolveValue(operand)) |operand_val| { if (vector_len) |len| { var min = try operand_val.elemValue(pt, 0); var max = min; @@ -24696,6 +24018,9 @@ fn analyzeMinMax( .child = intermediate_scalar_ty.toIntern(), }) else intermediate_scalar_ty; + // We might have refined all the way down to an OPV type---check now. + if (try result_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); + // This value, if not `null`, will have type `intermediate_ty`. const comptime_part: ?Value = ct: { // Contains the comptime-known scalar result values. @@ -24712,7 +24037,7 @@ fn analyzeMinMax( var opt_runtime_src: ?LazySrcLoc = null; for (operands, operand_srcs) |operand, operand_src| { - const operand_val = try sema.resolveValueResolveLazy(operand) orelse { + const operand_val = try sema.resolveValue(operand) orelse { if (opt_runtime_src == null) opt_runtime_src = operand_src; continue; }; @@ -24819,7 +24144,7 @@ fn upgradeToArrayPtr(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, len: u64) !A // Already an array pointer. return ptr; } - const new_ty = try pt.ptrTypeSema(.{ + const new_ty = try pt.ptrType(.{ .child = (try pt.arrayType(.{ .len = len, .sentinel = info.sentinel, @@ -24883,6 +24208,9 @@ fn zirMemcpy( const dest_elem_ty = dest_ty.indexablePtrElem(zcu); const src_elem_ty = src_ty.indexablePtrElem(zcu); + try sema.ensureLayoutResolved(dest_elem_ty); + try sema.ensureLayoutResolved(src_elem_ty); + const imc = try sema.coerceInMemoryAllowed( block, dest_elem_ty, @@ -24946,13 +24274,13 @@ fn zirMemcpy( } zero_bit: { - const src_comptime = try src_elem_ty.comptimeOnlySema(pt); - const dest_comptime = try dest_elem_ty.comptimeOnlySema(pt); + const src_comptime = src_elem_ty.comptimeOnly(zcu); + const dest_comptime = dest_elem_ty.comptimeOnly(zcu); assert(src_comptime == dest_comptime); // IMC if (src_comptime) break :zero_bit; - const src_has_bits = try src_elem_ty.hasRuntimeBitsIgnoreComptimeSema(pt); - const dest_has_bits = try dest_elem_ty.hasRuntimeBitsIgnoreComptimeSema(pt); + const src_has_bits = src_elem_ty.hasRuntimeBits(zcu); + const dest_has_bits = dest_elem_ty.hasRuntimeBits(zcu); assert(src_has_bits == dest_has_bits); // IMC if (src_has_bits) break :zero_bit; @@ -24968,7 +24296,7 @@ fn zirMemcpy( const raw_dest_ptr = if (dest_ty.isSlice(zcu)) dest_ptr_val.slicePtr(zcu) else dest_ptr_val; const raw_src_ptr = if (src_ty.isSlice(zcu)) src_ptr_val.slicePtr(zcu) else src_ptr_val; - const len_u64 = try len_val.?.toUnsignedIntSema(pt); + const len_u64 = len_val.?.toUnsignedInt(zcu); if (check_aliasing) { if (Value.doPointersOverlap( @@ -25018,7 +24346,7 @@ fn zirMemcpy( var new_dest_ptr = dest_ptr; var new_src_ptr = src_ptr; if (len_val) |val| { - const len = try val.toUnsignedIntSema(pt); + const len = val.toUnsignedInt(zcu); if (len == 0) { // This AIR instruction guarantees length > 0 if it is comptime-known. return; @@ -25067,7 +24395,7 @@ fn zirMemcpy( assert(dest_manyptr_ty_key.flags.size == .one); dest_manyptr_ty_key.child = dest_elem_ty.toIntern(); dest_manyptr_ty_key.flags.size = .many; - break :ptr try sema.coerceCompatiblePtrs(block, try pt.ptrTypeSema(dest_manyptr_ty_key), new_dest_ptr, dest_src); + break :ptr try sema.coerceCompatiblePtrs(block, try pt.ptrType(dest_manyptr_ty_key), new_dest_ptr, dest_src); } else new_dest_ptr; const new_src_ptr_ty = sema.typeOf(new_src_ptr); @@ -25078,7 +24406,7 @@ fn zirMemcpy( assert(src_manyptr_ty_key.flags.size == .one); src_manyptr_ty_key.child = src_elem_ty.toIntern(); src_manyptr_ty_key.flags.size = .many; - break :ptr try sema.coerceCompatiblePtrs(block, try pt.ptrTypeSema(src_manyptr_ty_key), new_src_ptr, src_src); + break :ptr try sema.coerceCompatiblePtrs(block, try pt.ptrType(src_manyptr_ty_key), new_src_ptr, src_src); } else new_src_ptr; // ok1: dest >= src + len @@ -25148,7 +24476,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void const runtime_src = rs: { const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls), dest_src); const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse break :rs dest_src; - const len_u64 = try len_val.toUnsignedIntSema(pt); + const len_u64 = len_val.toUnsignedInt(zcu); const len = try sema.usizeCast(block, dest_src, len_u64); if (len == 0) { // This AIR instruction guarantees length > 0 if it is comptime-known. @@ -25436,7 +24764,7 @@ fn resolvePrefetchOptions( return std.builtin.PrefetchOptions{ .rw = try sema.interpretBuiltinType(block, rw_src, rw_val, std.builtin.PrefetchOptions.Rw), - .locality = @intCast(try locality_val.toUnsignedIntSema(pt)), + .locality = @intCast(locality_val.toUnsignedInt(zcu)), .cache = try sema.interpretBuiltinType(block, cache_src, cache_val, std.builtin.PrefetchOptions.Cache), }; } @@ -25626,7 +24954,7 @@ fn zirBuiltinExtern( // So, for now, just use our containing `declaration`. .zir_index = switch (sema.owner.unwrap()) { .@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index, - .type => |owner_ty| Type.fromInterned(owner_ty).typeDeclInst(zcu).?, + .type_layout, .type_inits => |owner_ty| Type.fromInterned(owner_ty).typeDeclInstAllowGeneratedTag(zcu).?, .memoized_state => unreachable, .nav_ty, .nav_val => |nav| ip.getNav(nav).analysis.?.zir_index, .func => |func| zir_index: { @@ -25839,7 +25167,8 @@ fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src: } } -/// Emit a compile error if type cannot be used for a runtime variable. +/// Emit a compile error if `var_ty` cannot be used for a runtime variable. +/// Asserts that the layout of `var_ty` is already resolved. pub fn validateVarType( sema: *Sema, block: *Block, @@ -25849,6 +25178,7 @@ pub fn validateVarType( ) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; + var_ty.assertHasLayout(zcu); if (is_extern) { if (!try sema.validateExternType(var_ty, .other)) { const msg = msg: { @@ -25870,7 +25200,7 @@ pub fn validateVarType( } } - if (!try var_ty.comptimeOnlySema(pt)) return; + if (!var_ty.comptimeOnly(zcu)) return; const msg = msg: { const msg = try sema.errMsg(src, "variable of type '{f}' must be const or comptime", .{var_ty.fmt(pt)}); @@ -25886,49 +25216,28 @@ pub fn validateVarType( return sema.failWithOwnedErrorMsg(block, msg); } -const TypeSet = std.AutoHashMapUnmanaged(InternPool.Index, void); - fn explainWhyTypeIsComptime( sema: *Sema, msg: *Zcu.ErrorMsg, - src_loc: LazySrcLoc, + src: LazySrcLoc, ty: Type, -) CompileError!void { - var type_set = TypeSet{}; - defer type_set.deinit(sema.gpa); - - try ty.resolveFully(sema.pt); - return sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty, &type_set); -} - -fn explainWhyTypeIsComptimeInner( - sema: *Sema, - msg: *Zcu.ErrorMsg, - src_loc: LazySrcLoc, - ty: Type, - type_set: *TypeSet, ) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; + assert(ty.comptimeOnly(zcu)); switch (ty.zigTypeTag(zcu)) { .bool, .int, .float, .error_set, - .@"enum", .frame, .@"anyframe", .void, - => return, - - .@"fn" => { - try sema.errNote(src_loc, msg, "use '*const {f}' for a function pointer type", .{ty.fmt(pt)}); - }, - - .type => { - try sema.errNote(src_loc, msg, "types are not available at runtime", .{}); - }, + .@"enum", + .@"opaque", + .pointer, + => unreachable, // not comptime-only .comptime_float, .comptime_int, @@ -25936,78 +25245,53 @@ fn explainWhyTypeIsComptimeInner( .noreturn, .undefined, .null, - => return, + => return, // no explanation needed - .@"opaque" => { - try sema.errNote(src_loc, msg, "opaque type '{f}' has undefined size", .{ty.fmt(pt)}); - }, + .array, .vector => try sema.explainWhyTypeIsComptime(msg, src, ty.childType(zcu)), + .optional => try sema.explainWhyTypeIsComptime(msg, src, ty.optionalChild(zcu)), + .error_union => try sema.explainWhyTypeIsComptime(msg, src, ty.errorUnionPayload(zcu)), - .array, .vector => { - try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.childType(zcu), type_set); - }, - .pointer => { - const elem_ty = ty.elemType2(zcu); - if (elem_ty.zigTypeTag(zcu) == .@"fn") { - const fn_info = zcu.typeToFunc(elem_ty).?; - if (fn_info.is_generic) { - try sema.errNote(src_loc, msg, "function is generic", .{}); - } - switch (fn_info.cc) { - .@"inline" => try sema.errNote(src_loc, msg, "function has inline calling convention", .{}), - else => {}, - } - if (Type.fromInterned(fn_info.return_type).comptimeOnly(zcu)) { - try sema.errNote(src_loc, msg, "function has a comptime-only return type", .{}); - } - return; - } - try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.childType(zcu), type_set); - }, - - .optional => { - try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.optionalChild(zcu), type_set); - }, - .error_union => { - try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.errorUnionPayload(zcu), type_set); - }, - - .@"struct" => { - if ((try type_set.getOrPut(sema.gpa, ty.toIntern())).found_existing) return; + .@"fn" => try sema.errNote(src, msg, "use '*const {f}' for a function pointer type", .{ty.fmt(pt)}), + .type => try sema.errNote(src, msg, "types are not available at runtime", .{}), - if (zcu.typeToStruct(ty)) |struct_type| { - for (0..struct_type.field_types.len) |i| { - const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); - const field_src: LazySrcLoc = .{ - .base_node_inst = struct_type.zir_index, - .offset = .{ .container_field_type = @intCast(i) }, - }; - - if (try field_ty.comptimeOnlySema(pt)) { - try sema.errNote(field_src, msg, "struct requires comptime because of this field", .{}); - try sema.explainWhyTypeIsComptimeInner(msg, field_src, field_ty, type_set); - } - } + .@"struct" => if (zcu.typeToStruct(ty)) |struct_type| { + ty.assertHasLayout(zcu); + for (0..struct_type.field_types.len) |i| { + const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); + if (!field_ty.comptimeOnly(zcu)) continue; + const field_src: LazySrcLoc = .{ + .base_node_inst = struct_type.zir_index, + .offset = .{ .container_field_type = @intCast(i) }, + }; + try sema.errNote(field_src, msg, "struct requires comptime because of this field", .{}); + return sema.explainWhyTypeIsComptime(msg, field_src, field_ty); + } + unreachable; + } else { + const tuple = ip.indexToKey(ty.toIntern()).tuple_type; + for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty_ip, field_val_ip| { + if (field_val_ip != .none) continue; + const field_ty: Type = .fromInterned(field_ty_ip); + if (!field_ty.comptimeOnly(zcu)) continue; + try sema.errNote(src, msg, "tuple requires comptime because of field of type '{f}'", .{field_ty.fmt(pt)}); + return sema.explainWhyTypeIsComptime(msg, src, field_ty); } - // TODO tuples + unreachable; }, .@"union" => { - if ((try type_set.getOrPut(sema.gpa, ty.toIntern())).found_existing) return; - - if (zcu.typeToUnion(ty)) |union_obj| { - for (0..union_obj.field_types.len) |i| { - const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[i]); - const field_src: LazySrcLoc = .{ - .base_node_inst = union_obj.zir_index, - .offset = .{ .container_field_type = @intCast(i) }, - }; - - if (try field_ty.comptimeOnlySema(pt)) { - try sema.errNote(field_src, msg, "union requires comptime because of this field", .{}); - try sema.explainWhyTypeIsComptimeInner(msg, field_src, field_ty, type_set); - } - } + const union_obj = zcu.typeToUnion(ty).?; + for (0..union_obj.field_types.len) |i| { + const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[i]); + if (!field_ty.comptimeOnly(zcu)) continue; + const field_src: LazySrcLoc = .{ + .base_node_inst = union_obj.zir_index, + .offset = .{ .container_field_type = @intCast(i) }, + }; + try sema.errNote(field_src, msg, "union requires comptime because of this field", .{}); + return sema.explainWhyTypeIsComptime(msg, field_src, field_ty); } + unreachable; }, } } @@ -26022,9 +25306,8 @@ const ExternPosition = enum { }; /// Returns true if `ty` is allowed in extern types. -/// Does *NOT* require `ty` to be resolved in any way. -/// Calls `resolveLayout` for packed containers. -fn validateExternType( +/// Does not require `ty` to be resolved in any way. +pub fn validateExternType( sema: *Sema, ty: Type, position: ExternPosition, @@ -26042,7 +25325,16 @@ fn validateExternType( .error_set, .frame, => return false, - .void => return position == .union_field or position == .ret_ty or position == .struct_field or position == .element, + .void => return switch (position) { + .ret_ty, + .union_field, + .struct_field, + .element, + => true, + .param_ty, + .other, + => false, + }, .noreturn => return position == .ret_ty, .@"opaque", .bool, @@ -26050,10 +25342,12 @@ fn validateExternType( .@"anyframe", => return true, .pointer => { - if (ty.childType(zcu).zigTypeTag(zcu) == .@"fn") { - return ty.isConstPtr(zcu) and try sema.validateExternType(ty.childType(zcu), .other); + if (ty.isSlice(zcu)) return false; + const child_ty = ty.childType(zcu); + if (child_ty.zigTypeTag(zcu) == .@"fn") { + return ty.isConstPtr(zcu) and try sema.validateExternType(child_ty, .other); } - return !(ty.isSlice(zcu) or try ty.comptimeOnlySema(pt)); + return true; }, .int => switch (ty.intInfo(zcu).bits) { 0, 8, 16, 32, 64, 128 => return true, @@ -26069,29 +25363,42 @@ fn validateExternType( return !target_util.fnCallConvAllowsZigTypes(ty.fnCallingConvention(zcu)); }, .@"enum" => { - return sema.validateExternType(ty.intTagType(zcu), position); + const enum_obj = zcu.intern_pool.loadEnumType(ty.toIntern()); + if (!enum_obj.int_tag_is_explicit) return false; + return sema.validateExternType(.fromInterned(enum_obj.int_tag_type), position); }, - .@"struct", .@"union" => switch (ty.containerLayout(zcu)) { - .@"extern" => return true, - .@"packed" => { - const bit_size = try ty.bitSizeSema(pt); - switch (bit_size) { - 0, 8, 16, 32, 64, 128 => return true, - else => return false, - } - }, - .auto => return !(try ty.hasRuntimeBitsSema(pt)), + .@"struct" => { + const struct_obj = zcu.intern_pool.loadStructType(ty.toIntern()); + return switch (struct_obj.layout) { + .auto => false, + .@"extern" => true, + .@"packed" => switch (struct_obj.packed_backing_mode) { + .auto => false, + .explicit => try sema.validateExternType(.fromInterned(struct_obj.packed_backing_int_type), position), + }, + }; + }, + .@"union" => { + const union_obj = zcu.intern_pool.loadUnionType(ty.toIntern()); + return switch (union_obj.layout) { + .auto => false, + .@"extern" => true, + .@"packed" => switch (union_obj.packed_backing_mode) { + .auto => false, + .explicit => try sema.validateExternType(.fromInterned(union_obj.packed_backing_int_type), position), + }, + }; }, .array => { if (position == .ret_ty or position == .param_ty) return false; - return sema.validateExternType(ty.elemType2(zcu), .element); + return sema.validateExternType(ty.childType(zcu), .element); }, - .vector => return sema.validateExternType(ty.elemType2(zcu), .element), + .vector => return sema.validateExternType(ty.childType(zcu), .element), .optional => return ty.isPtrLikeOptional(zcu), } } -fn explainWhyTypeIsNotExtern( +pub fn explainWhyTypeIsNotExtern( sema: *Sema, msg: *Zcu.ErrorMsg, src_loc: LazySrcLoc, @@ -26125,9 +25432,6 @@ fn explainWhyTypeIsNotExtern( const pointee_ty = ty.childType(zcu); if (!ty.isConstPtr(zcu) and pointee_ty.zigTypeTag(zcu) == .@"fn") { try sema.errNote(src_loc, msg, "pointer to extern function must be 'const'", .{}); - } else if (try ty.comptimeOnlySema(pt)) { - try sema.errNote(src_loc, msg, "pointer to comptime-only type '{f}'", .{pointee_ty.fmt(pt)}); - try sema.explainWhyTypeIsComptime(msg, src_loc, ty); } try sema.explainWhyTypeIsNotExtern(msg, src_loc, pointee_ty, .other); } @@ -26157,6 +25461,7 @@ fn explainWhyTypeIsNotExtern( try sema.errNote(src_loc, msg, "enum tag type '{f}' is not extern compatible", .{tag_ty.fmt(pt)}); try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position); }, + // MLUGG TODO: these notes are bad now (because ABI sized packed type also needs explicit backing type) .@"struct" => try sema.errNote(src_loc, msg, "only extern structs and ABI sized packed structs are extern compatible", .{}), .@"union" => try sema.errNote(src_loc, msg, "only extern unions and ABI sized packed unions are extern compatible", .{}), .array => { @@ -26165,51 +25470,14 @@ fn explainWhyTypeIsNotExtern( } else if (position == .param_ty) { return sema.errNote(src_loc, msg, "arrays are not allowed as a parameter type", .{}); } - try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(zcu), .element); + try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.childType(zcu), .element); }, - .vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(zcu), .element), + .vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.childType(zcu), .element), .optional => try sema.errNote(src_loc, msg, "only pointer like optionals are extern compatible", .{}), } } -/// Returns true if `ty` is allowed in packed types. -/// Does not require `ty` to be resolved in any way, but may resolve whether it is comptime-only. -fn validatePackedType(sema: *Sema, ty: Type) !bool { - const pt = sema.pt; - const zcu = pt.zcu; - return switch (ty.zigTypeTag(zcu)) { - .type, - .comptime_float, - .comptime_int, - .enum_literal, - .undefined, - .null, - .error_union, - .error_set, - .frame, - .noreturn, - .@"opaque", - .@"anyframe", - .@"fn", - .array, - => false, - .optional => return ty.isPtrLikeOptional(zcu), - .void, - .bool, - .float, - .int, - .vector, - => true, - .@"enum" => switch (zcu.intern_pool.loadEnumType(ty.toIntern()).tag_mode) { - .auto => false, - .explicit, .nonexhaustive => true, - }, - .pointer => !ty.isSlice(zcu) and !try ty.comptimeOnlySema(pt), - .@"struct", .@"union" => ty.containerLayout(zcu) == .@"packed", - }; -} - -fn explainWhyTypeIsNotPacked( +pub fn explainWhyTypeIsNotPackable( sema: *Sema, msg: *Zcu.ErrorMsg, src_loc: LazySrcLoc, @@ -26250,8 +25518,8 @@ fn explainWhyTypeIsNotPacked( try sema.errNote(src_loc, msg, "type has no guaranteed in-memory representation", .{}); try sema.errNote(src_loc, msg, "use '*const ' to make a function pointer type", .{}); }, - .@"struct" => try sema.errNote(src_loc, msg, "only packed structs layout are allowed in packed types", .{}), - .@"union" => try sema.errNote(src_loc, msg, "only packed unions layout are allowed in packed types", .{}), + .@"struct" => try sema.errNote(src_loc, msg, "struct in packed type must have packed layout", .{}), + .@"union" => try sema.errNote(src_loc, msg, "union in packed type must have packed layout", .{}), } } @@ -26277,7 +25545,7 @@ fn getPanicIdFunc(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !In try sema.ensureMemoizedStateResolved(src, .panic); const panic_fn_index = zcu.builtin_decl_values.get(panic_id.toBuiltin()); switch (sema.owner.unwrap()) { - .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {}, + .@"comptime", .nav_ty, .nav_val, .type_layout, .type_inits, .memoized_state => {}, .func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(io, owner_func, true), } return panic_fn_index; @@ -26555,7 +25823,8 @@ fn fieldPtrLoad( const zcu = pt.zcu; const object_ptr_ty = sema.typeOf(object_ptr); const pointee_ty = object_ptr_ty.childType(zcu); - if (try typeHasOnePossibleValue(sema, pointee_ty)) |opv| { + try sema.ensureLayoutResolved(pointee_ty); // MLUGG TODO + if (try pointee_ty.onePossibleValue(pt)) |opv| { const object: Air.Inst.Ref = .fromValue(opv); return fieldVal(sema, block, src, object, field_name, field_name_src); } @@ -26603,7 +25872,7 @@ fn fieldVal( return Air.internedToRef((try pt.intValue(.usize, inner_ty.arrayLen(zcu))).toIntern()); } else if (field_name.eqlSlice("ptr", ip) and is_pointer_to) { const ptr_info = object_ty.ptrInfo(zcu); - const result_ty = try pt.ptrTypeSema(.{ + const result_ty = try pt.ptrType(.{ .child = Type.fromInterned(ptr_info.child).childType(zcu).toIntern(), .sentinel = if (inner_ty.sentinel(zcu)) |s| s.toIntern() else .none, .flags = .{ @@ -26693,7 +25962,6 @@ fn fieldVal( if (try sema.namespaceLookupVal(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { return inst; } - try child_type.resolveFields(pt); if (child_type.unionTagType(zcu)) |enum_ty| { if (enum_ty.enumFieldIndex(field_name, zcu)) |field_index_usize| { const field_index: u32 = @intCast(field_index_usize); @@ -26731,6 +25999,7 @@ fn fieldVal( }, .@"struct" => if (is_pointer_to) { // Avoid loading the entire struct by fetching a pointer and loading that + try sema.ensureLayoutResolved(inner_ty); const field_ptr = try sema.structFieldPtr(block, src, object, field_name, field_name_src, inner_ty, false); return sema.analyzeLoad(block, src, field_ptr, object_src); } else { @@ -26738,6 +26007,7 @@ fn fieldVal( }, .@"union" => if (is_pointer_to) { // Avoid loading the entire union by fetching a pointer and loading that + try sema.ensureLayoutResolved(inner_ty); const field_ptr = try sema.unionFieldPtr(block, src, object, field_name, field_name_src, inner_ty, false); return sema.analyzeLoad(block, src, field_ptr, object_src); } else { @@ -26787,7 +26057,7 @@ fn fieldPtr( return uavRef(sema, int_val.toIntern()); } else if (field_name.eqlSlice("ptr", ip) and is_pointer_to) { const ptr_info = object_ty.ptrInfo(zcu); - const new_ptr_ty = try pt.ptrTypeSema(.{ + const new_ptr_ty = try pt.ptrType(.{ .child = Type.fromInterned(ptr_info.child).childType(zcu).toIntern(), .sentinel = if (inner_ty.sentinel(zcu)) |s| s.toIntern() else .none, .flags = .{ @@ -26802,7 +26072,7 @@ fn fieldPtr( .packed_offset = ptr_info.packed_offset, }); const ptr_ptr_info = object_ptr_ty.ptrInfo(zcu); - const result_ty = try pt.ptrTypeSema(.{ + const result_ty = try pt.ptrType(.{ .child = new_ptr_ty.toIntern(), .sentinel = if (object_ptr_ty.sentinel(zcu)) |s| s.toIntern() else .none, .flags = .{ @@ -26836,7 +26106,7 @@ fn fieldPtr( if (field_name.eqlSlice("ptr", ip)) { const slice_ptr_ty = inner_ty.slicePtrFieldType(zcu); - const result_ty = try pt.ptrTypeSema(.{ + const result_ty = try pt.ptrType(.{ .child = slice_ptr_ty.toIntern(), .flags = .{ .is_const = !attr_ptr_ty.ptrIsMutable(zcu), @@ -26854,7 +26124,7 @@ fn fieldPtr( try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr); return field_ptr; } else if (field_name.eqlSlice("len", ip)) { - const result_ty = try pt.ptrTypeSema(.{ + const result_ty = try pt.ptrType(.{ .child = .usize_type, .flags = .{ .is_const = !attr_ptr_ty.ptrIsMutable(zcu), @@ -26925,7 +26195,6 @@ fn fieldPtr( if (try sema.namespaceLookupRef(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { return inst; } - try child_type.resolveFields(pt); if (child_type.unionTagType(zcu)) |enum_ty| { if (enum_ty.enumFieldIndex(field_name, zcu)) |field_index| { const field_index_u32: u32 = @intCast(field_index); @@ -26960,6 +26229,7 @@ fn fieldPtr( try sema.analyzeLoad(block, src, object_ptr, object_ptr_src) else object_ptr; + try sema.ensureLayoutResolved(inner_ty); const field_ptr = try sema.structFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty, initializing); try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr); return field_ptr; @@ -26969,6 +26239,7 @@ fn fieldPtr( try sema.analyzeLoad(block, src, object_ptr, object_ptr_src) else object_ptr; + try sema.ensureLayoutResolved(inner_ty); const field_ptr = try sema.unionFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty, initializing); try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr); return field_ptr; @@ -27012,6 +26283,7 @@ fn fieldCallBind( // Optionally dereference a second pointer to get the concrete type. const is_double_ptr = inner_ty.zigTypeTag(zcu) == .pointer and inner_ty.ptrSize(zcu) == .one; const concrete_ty = if (is_double_ptr) inner_ty.childType(zcu) else inner_ty; + try sema.ensureLayoutResolved(concrete_ty); const ptr_ty = if (is_double_ptr) inner_ty else raw_ptr_ty; const object_ptr = if (is_double_ptr) try sema.analyzeLoad(block, src, raw_ptr, src) @@ -27021,10 +26293,8 @@ fn fieldCallBind( find_field: { switch (concrete_ty.zigTypeTag(zcu)) { .@"struct" => { - try concrete_ty.resolveFields(pt); if (zcu.typeToStruct(concrete_ty)) |struct_type| { - const field_index = struct_type.nameIndex(ip, field_name) orelse - break :find_field; + const field_index = struct_type.nameIndex(ip, field_name) orelse break :find_field; const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); return sema.finishFieldCallBind(block, src, ptr_ty, field_ty, field_index, object_ptr); @@ -27047,9 +26317,9 @@ fn fieldCallBind( } }, .@"union" => { - try concrete_ty.resolveFields(pt); const union_obj = zcu.typeToUnion(concrete_ty).?; - _ = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse break :find_field; + const enum_obj = ip.loadEnumType(union_obj.enum_tag_type); + if (enum_obj.nameIndex(ip, field_name) == null) break :find_field; const field_ptr = try unionFieldPtr(sema, block, src, object_ptr, field_name, field_name_src, concrete_ty, false); return .{ .direct = try sema.analyzeLoad(block, src, field_ptr, src) }; }, @@ -27163,7 +26433,7 @@ fn finishFieldCallBind( ) CompileError!ResolvedFieldCallee { const pt = sema.pt; const zcu = pt.zcu; - const ptr_field_ty = try pt.ptrTypeSema(.{ + const ptr_field_ty = try pt.ptrType(.{ .child = field_ty.toIntern(), .flags = .{ .is_const = !ptr_ty.ptrIsMutable(zcu), @@ -27174,7 +26444,9 @@ fn finishFieldCallBind( const container_ty = ptr_ty.childType(zcu); if (container_ty.zigTypeTag(zcu) == .@"struct") { if (container_ty.structFieldIsComptime(field_index, zcu)) { - try container_ty.resolveStructFieldInits(pt); + if (!container_ty.isTuple(zcu)) { + try sema.ensureFieldInitsResolved(container_ty); + } const default_val = (try container_ty.structFieldValueComptime(pt, field_index)).?; return .{ .direct = Air.internedToRef(default_val.toIntern()) }; } @@ -27239,6 +26511,7 @@ fn namespaceLookupVal( return try sema.analyzeNavVal(block, src, nav); } +/// Asserts that the layout of `struct_ty` is already resolved. fn structFieldPtr( sema: *Sema, block: *Block, @@ -27252,10 +26525,9 @@ fn structFieldPtr( const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; - assert(struct_ty.zigTypeTag(zcu) == .@"struct"); - try struct_ty.resolveFields(pt); - try struct_ty.resolveLayout(pt); + assert(struct_ty.zigTypeTag(zcu) == .@"struct"); + struct_ty.assertHasLayout(zcu); if (struct_ty.isTuple(zcu)) { if (field_name.eqlSlice("len", ip)) { @@ -27274,6 +26546,7 @@ fn structFieldPtr( return sema.structFieldPtrByIndex(block, src, struct_ptr, field_index, struct_ty); } +/// Asserts that the layout of `struct_ty` is already resolved. fn structFieldPtrByIndex( sema: *Sema, block: *Block, @@ -27286,8 +26559,10 @@ fn structFieldPtrByIndex( const zcu = pt.zcu; const ip = &zcu.intern_pool; + struct_ty.assertHasLayout(zcu); + const struct_type = zcu.typeToStruct(struct_ty).?; - const field_is_comptime = struct_type.fieldIsComptime(ip, field_index); + const field_is_comptime = struct_type.field_is_comptime_bits.get(ip, field_index); // Comptime fields are handled later if (!field_is_comptime) { @@ -27300,6 +26575,7 @@ fn structFieldPtrByIndex( const field_ty = struct_type.field_types.get(ip)[field_index]; const struct_ptr_ty = sema.typeOf(struct_ptr); const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(zcu); + assert(struct_ptr_ty_info.child == struct_ty.toIntern()); var ptr_ty_data: InternPool.Key.PtrType = .{ .child = field_ty, @@ -27313,7 +26589,7 @@ fn structFieldPtrByIndex( const parent_align = if (struct_ptr_ty_info.flags.alignment != .none) struct_ptr_ty_info.flags.alignment else - try Type.fromInterned(struct_ptr_ty_info.child).abiAlignmentSema(pt); + struct_ty.abiAlignment(zcu); if (struct_type.layout == .@"packed") { assert(!field_is_comptime); @@ -27325,31 +26601,32 @@ fn structFieldPtrByIndex( // For extern structs, field alignment might be bigger than type's // natural alignment. Eg, in `extern struct { x: u32, y: u16 }` the // second field is aligned as u32. - const field_offset = struct_ty.structFieldOffset(field_index, zcu); - ptr_ty_data.flags.alignment = if (parent_align == .none) - .none - else - @enumFromInt(@min(@intFromEnum(parent_align), @ctz(field_offset))); + ptr_ty_data.flags.alignment = a: { + const field_off = struct_ty.structFieldOffset(field_index, zcu); + if (field_off == 0) break :a struct_ptr_ty_info.flags.alignment; + const true_field_align: Alignment = .fromLog2Units(@ctz(field_off)); + if (struct_ptr_ty_info.flags.alignment == .none and + true_field_align == Type.fromInterned(field_ty).abiAlignment(zcu)) + { + break :a .none; + } + break :a .minStrict(true_field_align, parent_align); + }; } else { // Our alignment is capped at the field alignment. - const field_align = try Type.fromInterned(field_ty).structFieldAlignmentSema( - struct_type.fieldAlign(ip, field_index), - struct_type.layout, - pt, - ); ptr_ty_data.flags.alignment = if (struct_ptr_ty_info.flags.alignment == .none) - field_align + struct_ty.explicitFieldAlignment(field_index, zcu) else - field_align.min(parent_align); + struct_ty.resolvedFieldAlignment(field_index, zcu).min(parent_align); } - const ptr_field_ty = try pt.ptrTypeSema(ptr_ty_data); + const ptr_field_ty = try pt.ptrType(ptr_ty_data); if (field_is_comptime) { - try struct_ty.resolveStructFieldInits(pt); + try sema.ensureFieldInitsResolved(struct_ty); const val = try pt.intern(.{ .ptr = .{ .ty = ptr_field_ty.toIntern(), - .base_addr = .{ .comptime_field = struct_type.field_inits.get(ip)[field_index] }, + .base_addr = .{ .comptime_field = struct_type.field_defaults.get(ip)[field_index] }, .byte_offset = 0, } }); return Air.internedToRef(val); @@ -27371,32 +26648,26 @@ fn structFieldVal( const ip = &zcu.intern_pool; assert(struct_ty.zigTypeTag(zcu) == .@"struct"); - try struct_ty.resolveFields(pt); - switch (ip.indexToKey(struct_ty.toIntern())) { .struct_type => { const struct_type = ip.loadStructType(struct_ty.toIntern()); const field_index = struct_type.nameIndex(ip, field_name) orelse return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_name_src, field_name); - if (struct_type.fieldIsComptime(ip, field_index)) { - try struct_ty.resolveStructFieldInits(pt); - return Air.internedToRef(struct_type.field_inits.get(ip)[field_index]); + if (struct_type.field_is_comptime_bits.get(ip, field_index)) { + try sema.ensureFieldInitsResolved(struct_ty); + return .fromIntern(struct_type.field_defaults.get(ip)[field_index]); } const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); - if (try sema.typeHasOnePossibleValue(field_ty)) |field_val| - return Air.internedToRef(field_val.toIntern()); + if (try field_ty.onePossibleValue(pt)) |field_val| + return .fromValue(field_val); if (try sema.resolveValue(struct_byval)) |struct_val| { if (struct_val.isUndef(zcu)) return pt.undefRef(field_ty); - if ((try sema.typeHasOnePossibleValue(field_ty))) |opv| { - return Air.internedToRef(opv.toIntern()); - } - return Air.internedToRef((try struct_val.fieldValue(pt, field_index)).toIntern()); + return .fromValue(try struct_val.fieldValue(pt, field_index)); } - try field_ty.resolveLayout(pt); return block.addStructFieldVal(struct_byval, field_index, field_ty); }, .tuple_type => { @@ -27457,16 +26728,13 @@ fn tupleFieldValByIndex( const zcu = pt.zcu; const field_ty = tuple_ty.fieldType(field_index, zcu); - if (tuple_ty.structFieldIsComptime(field_index, zcu)) - try tuple_ty.resolveStructFieldInits(pt); if (try tuple_ty.structFieldValueComptime(pt, field_index)) |default_value| { return Air.internedToRef(default_value.toIntern()); } + if (try field_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); + if (try sema.resolveValue(tuple_byval)) |tuple_val| { - if ((try sema.typeHasOnePossibleValue(field_ty))) |opv| { - return Air.internedToRef(opv.toIntern()); - } return switch (zcu.intern_pool.indexToKey(tuple_val.toIntern())) { .undef => pt.undefRef(field_ty), .aggregate => |aggregate| Air.internedToRef(switch (aggregate.storage) { @@ -27478,10 +26746,10 @@ fn tupleFieldValByIndex( }; } - try field_ty.resolveLayout(pt); return block.addStructFieldVal(tuple_byval, field_index, field_ty); } +/// Asserts that the layout of `union_ty` is already resolved. fn unionFieldPtr( sema: *Sema, block: *Block, @@ -27497,31 +26765,31 @@ fn unionFieldPtr( const ip = &zcu.intern_pool; assert(union_ty.zigTypeTag(zcu) == .@"union"); + union_ty.assertHasLayout(zcu); const union_ptr_ty = sema.typeOf(union_ptr); const union_ptr_info = union_ptr_ty.ptrInfo(zcu); - try union_ty.resolveFields(pt); const union_obj = zcu.typeToUnion(union_ty).?; const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src); const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); - const ptr_field_ty = try pt.ptrTypeSema(.{ + const ptr_field_ty = try pt.ptrType(.{ .child = field_ty.toIntern(), .flags = .{ .is_const = union_ptr_info.flags.is_const, .is_volatile = union_ptr_info.flags.is_volatile, .address_space = union_ptr_info.flags.address_space, - .alignment = if (union_obj.flagsUnordered(ip).layout == .auto) blk: { - const union_align = if (union_ptr_info.flags.alignment != .none) - union_ptr_info.flags.alignment - else - try union_ty.abiAlignmentSema(pt); - const field_align = try union_ty.fieldAlignmentSema(field_index, pt); - break :blk union_align.min(field_align); - } else union_ptr_info.flags.alignment, + .alignment = a: { + if (union_obj.layout != .auto) break :a union_ptr_info.flags.alignment; + if (union_ptr_info.flags.alignment == .none) { + break :a union_ty.explicitFieldAlignment(field_index, zcu); + } + const field_align = union_ty.resolvedFieldAlignment(field_index, zcu); + break :a union_ptr_info.flags.alignment.min(field_align); + }, }, .packed_offset = union_ptr_info.packed_offset, }); - const enum_field_index: u32 = @intCast(Type.fromInterned(union_obj.enum_tag_ty).enumFieldIndex(field_name, zcu).?); + const enum_field_index: u32 = @intCast(Type.fromInterned(union_obj.enum_tag_type).enumFieldIndex(field_name, zcu).?); if (initializing and field_ty.zigTypeTag(zcu) == .noreturn) { const msg = msg: { @@ -27538,16 +26806,16 @@ fn unionFieldPtr( } if (try sema.resolveDefinedValue(block, src, union_ptr)) |union_ptr_val| ct: { - switch (union_obj.flagsUnordered(ip).layout) { + switch (union_obj.layout) { .auto => if (initializing) { if (!sema.isComptimeMutablePtr(union_ptr_val)) { // The initialization is a runtime operation. break :ct; } // Store to the union to initialize the tag. - const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), enum_field_index); + const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_type), enum_field_index); const payload_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); - const new_union_val = try pt.unionValue(union_ty, field_tag, try pt.undefValue(payload_ty)); + const new_union_val = try pt.unionValue(union_ty, field_tag, try payload_ty.onePossibleValue(pt) orelse try pt.undefValue(payload_ty)); try sema.storePtrVal(block, src, union_ptr_val, new_union_val, union_ty); } else { const union_val = (try sema.pointerDeref(block, src, union_ptr_val, union_ptr_ty)) orelse @@ -27556,12 +26824,12 @@ fn unionFieldPtr( return sema.failWithUseOfUndef(block, src, null); } const un = ip.indexToKey(union_val.toIntern()).un; - const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), enum_field_index); + const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_type), enum_field_index); const tag_matches = un.tag == field_tag.toIntern(); if (!tag_matches) { const msg = msg: { - const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?; - const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, zcu); + const active_index = Type.fromInterned(union_obj.enum_tag_type).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?; + const active_field_name = Type.fromInterned(union_obj.enum_tag_type).enumFieldName(active_index, zcu); const msg = try sema.errMsg(src, "access of union field '{f}' while field '{f}' is active", .{ field_name.fmt(ip), active_field_name.fmt(ip), @@ -27582,15 +26850,15 @@ fn unionFieldPtr( // If the union has a tag, we must either set or or safety check it depending on `initializing`. tag: { if (union_ty.containerLayout(zcu) != .auto) break :tag; - const tag_ty: Type = .fromInterned(union_obj.enum_tag_ty); - if (try sema.typeHasOnePossibleValue(tag_ty) != null) break :tag; + const tag_ty: Type = .fromInterned(union_obj.enum_tag_type); + if (try tag_ty.onePossibleValue(pt) != null) break :tag; // There is a hypothetical non-trivial tag. We must set it even if not there at runtime, but // only emit a safety check if it's available at runtime (i.e. it's safety-tagged). const want_tag = try pt.enumValueFieldIndex(tag_ty, enum_field_index); if (initializing) { const set_tag_inst = try block.addBinOp(.set_union_tag, union_ptr, .fromValue(want_tag)); try sema.checkComptimeKnownStore(block, set_tag_inst, .unneeded); // `unneeded` since this isn't a "proper" store - } else if (block.wantSafety() and union_obj.hasTag(ip)) { + } else if (block.wantSafety() and union_obj.runtime_tag != .none) { // The tag exists at runtime (safety tag), so emit a safety check. // TODO would it be better if get_union_tag supported pointers to unions? const union_val = try block.addTyOp(.load, union_ty, union_ptr); @@ -27619,26 +26887,25 @@ fn unionFieldVal( const ip = &zcu.intern_pool; assert(union_ty.zigTypeTag(zcu) == .@"union"); - try union_ty.resolveFields(pt); const union_obj = zcu.typeToUnion(union_ty).?; const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src); const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); - const enum_field_index: u32 = @intCast(Type.fromInterned(union_obj.enum_tag_ty).enumFieldIndex(field_name, zcu).?); + const enum_field_index: u32 = @intCast(Type.fromInterned(union_obj.enum_tag_type).enumFieldIndex(field_name, zcu).?); if (try sema.resolveValue(union_byval)) |union_val| { if (union_val.isUndef(zcu)) return pt.undefRef(field_ty); const un = ip.indexToKey(union_val.toIntern()).un; - const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), enum_field_index); + const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_type), enum_field_index); const tag_matches = un.tag == field_tag.toIntern(); - switch (union_obj.flagsUnordered(ip).layout) { + switch (union_obj.layout) { .auto => { if (tag_matches) { return Air.internedToRef(un.val); } else { const msg = msg: { - const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?; - const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, zcu); + const active_index = Type.fromInterned(union_obj.enum_tag_type).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?; + const active_field_name = Type.fromInterned(union_obj.enum_tag_type).enumFieldName(active_index, zcu); const msg = try sema.errMsg(src, "access of union field '{f}' while field '{f}' is active", .{ field_name.fmt(ip), active_field_name.fmt(ip), }); @@ -27658,18 +26925,18 @@ fn unionFieldVal( .@"packed" => if (tag_matches) { // Fast path - no need to use bitcast logic. return Air.internedToRef(un.val); - } else if (try sema.bitCastVal(union_val, field_ty, 0, try union_ty.bitSizeSema(pt), 0)) |field_val| { + } else if (try sema.bitCastVal(union_val, field_ty, 0, union_ty.bitSize(zcu), 0)) |field_val| { return Air.internedToRef(field_val.toIntern()); }, } } - if (union_obj.flagsUnordered(ip).layout == .auto and block.wantSafety() and + if (union_obj.layout == .auto and block.wantSafety() and union_ty.unionTagTypeSafety(zcu) != null and union_obj.field_types.len > 1) { - const wanted_tag_val = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), enum_field_index); + const wanted_tag_val = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_type), enum_field_index); const wanted_tag = Air.internedToRef(wanted_tag_val.toIntern()); - const active_tag = try block.addTyOp(.get_union_tag, .fromInterned(union_obj.enum_tag_ty), union_byval); + const active_tag = try block.addTyOp(.get_union_tag, .fromInterned(union_obj.enum_tag_type), union_byval); try sema.addSafetyCheckInactiveUnionField(block, src, active_tag, wanted_tag); } @@ -27678,11 +26945,8 @@ fn unionFieldVal( return .unreachable_value; } - if (try sema.typeHasOnePossibleValue(field_ty)) |field_only_value| { - return Air.internedToRef(field_only_value.toIntern()); - } + if (try field_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); - try field_ty.resolveLayout(pt); return block.addStructFieldVal(union_byval, field_index, field_ty); } @@ -27706,17 +26970,19 @@ fn elemPtr( else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{f}'", .{indexable_ptr_ty.fmt(pt)}), }; try sema.checkIndexable(block, src, indexable_ty); + try sema.ensureLayoutResolved(indexable_ty); const elem_ptr = switch (indexable_ty.zigTypeTag(zcu)) { .array, .vector => try sema.elemPtrArray(block, src, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init, oob_safety), .@"struct" => blk: { // Tuple field access. const index_val = try sema.resolveConstDefinedValue(block, elem_index_src, elem_index, .{ .simple = .tuple_field_index }); - const index: u32 = @intCast(try index_val.toUnsignedIntSema(pt)); + const index: u32 = @intCast(index_val.toUnsignedInt(zcu)); break :blk try sema.tupleFieldPtr(block, src, indexable_ptr, elem_index_src, index, init); }, else => { const indexable = try sema.analyzeLoad(block, indexable_ptr_src, indexable_ptr, indexable_ptr_src); + try sema.ensureLayoutResolved(sema.typeOf(indexable).childType(zcu)); return elemPtrOneLayerOnly(sema, block, src, indexable, elem_index, elem_index_src, init, oob_safety); }, }; @@ -27725,7 +26991,7 @@ fn elemPtr( return elem_ptr; } -/// Asserts that the type of indexable is pointer. +/// Asserts that `indexable` is an indexable pointer whose child type has its layout already resolved. fn elemPtrOneLayerOnly( sema: *Sema, block: *Block, @@ -27741,7 +27007,10 @@ fn elemPtrOneLayerOnly( const pt = sema.pt; const zcu = pt.zcu; - try sema.checkIndexable(block, src, indexable_ty); + assert(indexable_ty.isIndexable(zcu)); + assert(indexable_ty.zigTypeTag(zcu) == .pointer); + const child_ty = indexable_ty.childType(zcu); + child_ty.assertHasLayout(zcu); switch (indexable_ty.ptrSize(zcu)) { .slice => return sema.elemPtrSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety), @@ -27751,7 +27020,7 @@ fn elemPtrOneLayerOnly( ct: { const ptr_val = maybe_ptr_val orelse break :ct; const index_val = maybe_index_val orelse break :ct; - const index: usize = @intCast(try index_val.toUnsignedIntSema(pt)); + const index: usize = @intCast(index_val.toUnsignedInt(zcu)); const elem_ptr = try ptr_val.ptrElem(index, pt); return Air.internedToRef(elem_ptr.toIntern()); } @@ -27762,7 +27031,7 @@ fn elemPtrOneLayerOnly( try sema.validateRuntimeElemAccess(block, elem_index_src, result_ty, indexable_ty, indexable_src); try sema.validateRuntimeValue(block, indexable_src, indexable); - if (!try result_ty.childType(zcu).hasRuntimeBitsIgnoreComptimeSema(pt)) { + if (result_ty.childType(zcu).abiSize(zcu) == 0) { // zero-bit child type; just bitcast the pointer return block.addBitCast(result_ty, indexable); } @@ -27770,13 +27039,12 @@ fn elemPtrOneLayerOnly( return block.addPtrElemPtr(indexable, elem_index, result_ty); }, .one => { - const child_ty = indexable_ty.childType(zcu); const elem_ptr = switch (child_ty.zigTypeTag(zcu)) { .array, .vector => try sema.elemPtrArray(block, src, indexable_src, indexable, elem_index_src, elem_index, init, oob_safety), .@"struct" => blk: { assert(child_ty.isTuple(zcu)); const index_val = try sema.resolveConstDefinedValue(block, elem_index_src, elem_index, .{ .simple = .tuple_field_index }); - const index: u32 = @intCast(try index_val.toUnsignedIntSema(pt)); + const index: u32 = @intCast(index_val.toUnsignedInt(zcu)); break :blk try sema.tupleFieldPtr(block, indexable_src, indexable, elem_index_src, index, false); }, else => unreachable, // Guaranteed by checkIndexable @@ -27808,45 +27076,45 @@ fn elemVal( const elem_index = try sema.coerce(block, .usize, elem_index_uncasted, elem_index_src); switch (indexable_ty.zigTypeTag(zcu)) { - .pointer => switch (indexable_ty.ptrSize(zcu)) { - .slice => return sema.elemValSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety), - .many, .c => { - const maybe_indexable_val = try sema.resolveDefinedValue(block, indexable_src, indexable); - const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); - const elem_ty = indexable_ty.elemType2(zcu); + .pointer => { + const child_ty = indexable_ty.childType(zcu); + try sema.ensureLayoutResolved(child_ty); + switch (indexable_ty.ptrSize(zcu)) { + .slice => return sema.elemValSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety), + .many, .c => { + const maybe_indexable_val = try sema.resolveDefinedValue(block, indexable_src, indexable); + const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); - ct: { - const indexable_val = maybe_indexable_val orelse break :ct; - const index_val = maybe_index_val orelse break :ct; - const index: usize = @intCast(try index_val.toUnsignedIntSema(pt)); - const many_ptr_ty = try pt.manyConstPtrType(elem_ty); - const many_ptr_val = try pt.getCoerced(indexable_val, many_ptr_ty); - const elem_ptr_ty = try pt.singleConstPtrType(elem_ty); - const elem_ptr_val = try many_ptr_val.ptrElem(index, pt); - const elem_val = try sema.pointerDeref(block, indexable_src, elem_ptr_val, elem_ptr_ty) orelse break :ct; - return Air.internedToRef((try pt.getCoerced(elem_val, elem_ty)).toIntern()); - } + ct: { + const indexable_val = maybe_indexable_val orelse break :ct; + const index_val = maybe_index_val orelse break :ct; + const index: usize = @intCast(index_val.toUnsignedInt(zcu)); + const many_ptr_ty = try pt.manyConstPtrType(child_ty); + const many_ptr_val = try pt.getCoerced(indexable_val, many_ptr_ty); + const elem_ptr_ty = try pt.singleConstPtrType(child_ty); + const elem_ptr_val = try many_ptr_val.ptrElem(index, pt); + const elem_val = try sema.pointerDeref(block, indexable_src, elem_ptr_val, elem_ptr_ty) orelse break :ct; + return Air.internedToRef((try pt.getCoerced(elem_val, child_ty)).toIntern()); + } - if (try sema.typeHasOnePossibleValue(elem_ty)) |elem_only_value| { - return Air.internedToRef(elem_only_value.toIntern()); - } + if (try child_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); - try sema.checkLogicalPtrOperation(block, src, indexable_ty); - return block.addBinOp(.ptr_elem_val, indexable, elem_index); - }, - .one => { - arr_sent: { - const inner_ty = indexable_ty.childType(zcu); - if (inner_ty.zigTypeTag(zcu) != .array) break :arr_sent; - const sentinel = inner_ty.sentinel(zcu) orelse break :arr_sent; - const index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index) orelse break :arr_sent; - const index = try sema.usizeCast(block, src, try index_val.toUnsignedIntSema(pt)); - if (index != inner_ty.arrayLen(zcu)) break :arr_sent; - return Air.internedToRef(sentinel.toIntern()); - } - const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src, false, oob_safety); - return sema.analyzeLoad(block, indexable_src, elem_ptr, elem_index_src); - }, + try sema.checkLogicalPtrOperation(block, src, indexable_ty); + return block.addBinOp(.ptr_elem_val, indexable, elem_index); + }, + .one => { + arr_sent: { + if (child_ty.zigTypeTag(zcu) != .array) break :arr_sent; + const sentinel = child_ty.sentinel(zcu) orelse break :arr_sent; + const index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index) orelse break :arr_sent; + const index = try sema.usizeCast(block, src, index_val.toUnsignedInt(zcu)); + if (index != child_ty.arrayLen(zcu)) break :arr_sent; + return .fromValue(sentinel); + } + const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src, false, oob_safety); + return sema.analyzeLoad(block, indexable_src, elem_ptr, elem_index_src); + }, + } }, .array => return sema.elemValArray(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety), .vector => { @@ -27856,7 +27124,7 @@ fn elemVal( .@"struct" => { // Tuple field access. const index_val = try sema.resolveConstDefinedValue(block, elem_index_src, elem_index, .{ .simple = .tuple_field_index }); - const index: u32 = @intCast(try index_val.toUnsignedIntSema(pt)); + const index: u32 = @intCast(index_val.toUnsignedInt(zcu)); return sema.tupleField(block, indexable_src, indexable, elem_index_src, index); }, else => unreachable, @@ -27864,6 +27132,7 @@ fn elemVal( } /// Called when the index or indexable is runtime known. +/// Asserts that the layout of `elem_ty` is already resolved. fn validateRuntimeElemAccess( sema: *Sema, block: *Block, @@ -27875,7 +27144,7 @@ fn validateRuntimeElemAccess( const pt = sema.pt; const zcu = pt.zcu; - if (try elem_ty.comptimeOnlySema(sema.pt)) { + if (elem_ty.comptimeOnly(zcu)) { const msg = msg: { const msg = try sema.errMsg( elem_index_src, @@ -27900,6 +27169,7 @@ fn validateRuntimeElemAccess( } } +/// Asserts that the layout of the tuple type is already resolved. fn tupleFieldPtr( sema: *Sema, block: *Block, @@ -27914,9 +27184,10 @@ fn tupleFieldPtr( const tuple_ptr_ty = sema.typeOf(tuple_ptr); const tuple_ptr_info = tuple_ptr_ty.ptrInfo(zcu); const tuple_ty: Type = .fromInterned(tuple_ptr_info.child); - try tuple_ty.resolveFields(pt); const field_count = tuple_ty.structFieldCount(zcu); + tuple_ty.assertHasLayout(zcu); + if (field_count == 0) { return sema.fail(block, tuple_ptr_src, "indexing into empty tuple is not allowed", .{}); } @@ -27928,7 +27199,7 @@ fn tupleFieldPtr( } const field_ty = tuple_ty.fieldType(field_index, zcu); - const ptr_field_ty = try pt.ptrTypeSema(.{ + const ptr_field_ty = try pt.ptrType(.{ .child = field_ty.toIntern(), .flags = .{ .is_const = tuple_ptr_info.flags.is_const, @@ -27938,15 +27209,12 @@ fn tupleFieldPtr( if (tuple_ptr_info.flags.alignment == .none) break :a .none; // The tuple pointer isn't naturally aligned, so the field pointer might be underaligned. const tuple_align = tuple_ptr_info.flags.alignment; - const field_align = try field_ty.abiAlignmentSema(pt); + const field_align = field_ty.abiAlignment(zcu); break :a tuple_align.min(field_align); }, }, }); - if (tuple_ty.structFieldIsComptime(field_index, zcu)) - try tuple_ty.resolveStructFieldInits(pt); - if (try tuple_ty.structFieldValueComptime(pt, field_index)) |default_val| { return Air.internedToRef((try pt.intern(.{ .ptr = .{ .ty = ptr_field_ty.toIntern(), @@ -27978,7 +27246,6 @@ fn tupleField( const pt = sema.pt; const zcu = pt.zcu; const tuple_ty = sema.typeOf(tuple); - try tuple_ty.resolveFields(pt); const field_count = tuple_ty.structFieldCount(zcu); if (field_count == 0) { @@ -27993,8 +27260,6 @@ fn tupleField( const field_ty = tuple_ty.fieldType(field_index, zcu); - if (tuple_ty.structFieldIsComptime(field_index, zcu)) - try tuple_ty.resolveStructFieldInits(pt); if (try tuple_ty.structFieldValueComptime(pt, field_index)) |default_value| { return Air.internedToRef(default_value.toIntern()); // comptime field } @@ -28006,7 +27271,6 @@ fn tupleField( try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src); - try field_ty.resolveLayout(pt); return block.addStructFieldVal(tuple, field_index, field_ty); } @@ -28037,7 +27301,7 @@ fn elemValArray( const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); if (maybe_index_val) |index_val| { - const index: usize = @intCast(try index_val.toUnsignedIntSema(pt)); + const index: usize = @intCast(index_val.toUnsignedInt(zcu)); if (array_sent) |s| { if (index == array_len) { return Air.internedToRef(s.toIntern()); @@ -28053,10 +27317,11 @@ fn elemValArray( return pt.undefRef(elem_ty); } if (maybe_index_val) |index_val| { - const index: usize = @intCast(try index_val.toUnsignedIntSema(pt)); - const elem_val = try array_val.elemValue(pt, index); - return Air.internedToRef(elem_val.toIntern()); + const index: usize = @intCast(index_val.toUnsignedInt(zcu)); + return .fromValue(try array_val.elemValue(pt, index)); } + // Since the array is comptime-known, it might be OPV, in which case the index is irrelevant. + if (try elem_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); } try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, array_ty, array_src); @@ -28071,12 +27336,10 @@ fn elemValArray( } } - if (try sema.typeHasOnePossibleValue(elem_ty)) |elem_val| - return Air.internedToRef(elem_val.toIntern()); - return block.addBinOp(.array_elem_val, array, elem_index); } +/// Asserts that the layout of the array or vector is already resolved. fn elemPtrArray( sema: *Sema, block: *Block, @@ -28103,7 +27366,7 @@ fn elemPtrArray( const maybe_undef_array_ptr_val = try sema.resolveValue(array_ptr); // The index must not be undefined since it can be out of bounds. const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: { - const index = try sema.usizeCast(block, elem_index_src, try index_val.toUnsignedIntSema(pt)); + const index = try sema.usizeCast(block, elem_index_src, index_val.toUnsignedInt(zcu)); if (index >= array_len_s) { const sentinel_label: []const u8 = if (array_sent) " +1 (sentinel)" else ""; return sema.fail(block, elem_index_src, "index {d} outside array of length {d}{s}", .{ index, array_len, sentinel_label }); @@ -28115,6 +27378,7 @@ fn elemPtrArray( return sema.fail(block, elem_index_src, "vector index not comptime known", .{}); } + array_ty.assertHasLayout(zcu); const elem_ptr_ty = try array_ptr_ty.elemPtrType(offset, pt); if (maybe_undef_array_ptr_val) |array_ptr_val| { @@ -28128,7 +27392,7 @@ fn elemPtrArray( } if (!init) { - try sema.validateRuntimeElemAccess(block, elem_index_src, array_ty.elemType2(zcu), array_ty, array_ptr_src); + try sema.validateRuntimeElemAccess(block, elem_index_src, array_ty.childType(zcu), array_ty, array_ptr_src); try sema.validateRuntimeValue(block, array_ptr_src, array_ptr); } @@ -28142,6 +27406,7 @@ fn elemPtrArray( return block.addPtrElemPtr(array_ptr, elem_index, elem_ptr_ty); } +/// Asserts that the layout of the slice element type is already resolved. fn elemValSlice( sema: *Sema, block: *Block, @@ -28156,9 +27421,11 @@ fn elemValSlice( const zcu = pt.zcu; const slice_ty = sema.typeOf(slice); const slice_sent = slice_ty.sentinel(zcu) != null; - const elem_ty = slice_ty.elemType2(zcu); + const elem_ty = slice_ty.childType(zcu); var runtime_src = slice_src; + elem_ty.assertHasLayout(zcu); + // slice must be defined since it can dereferenced as null const maybe_slice_val = try sema.resolveDefinedValue(block, slice_src, slice); // index must be defined since it can index out of bounds @@ -28166,13 +27433,13 @@ fn elemValSlice( if (maybe_slice_val) |slice_val| { runtime_src = elem_index_src; - const slice_len = try slice_val.sliceLen(pt); + const slice_len = slice_val.sliceLen(zcu); const slice_len_s = slice_len + @intFromBool(slice_sent); if (slice_len_s == 0) { return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{}); } if (maybe_index_val) |index_val| { - const index: usize = @intCast(try index_val.toUnsignedIntSema(pt)); + const index: usize = @intCast(index_val.toUnsignedInt(zcu)); if (index >= slice_len_s) { const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else ""; return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label }); @@ -28186,16 +27453,14 @@ fn elemValSlice( } } - if (try sema.typeHasOnePossibleValue(elem_ty)) |elem_only_value| { - return Air.internedToRef(elem_only_value.toIntern()); - } + if (try elem_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, slice_ty, slice_src); try sema.validateRuntimeValue(block, slice_src, slice); if (oob_safety and block.wantSafety()) { const len_inst = if (maybe_slice_val) |slice_val| - try pt.intRef(.usize, try slice_val.sliceLen(pt)) + try pt.intRef(.usize, slice_val.sliceLen(zcu)) else try block.addTyOp(.slice_len, .usize, slice); const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt; @@ -28204,6 +27469,7 @@ fn elemValSlice( return block.addBinOp(.slice_elem_val, slice, elem_index); } +/// Asserts that the layout of the slice element type is already resolved. fn elemPtrSlice( sema: *Sema, block: *Block, @@ -28219,11 +27485,12 @@ fn elemPtrSlice( const slice_ty = sema.typeOf(slice); const slice_sent = slice_ty.sentinel(zcu) != null; + slice_ty.childType(zcu).assertHasLayout(zcu); + const maybe_undef_slice_val = try sema.resolveValue(slice); // The index must not be undefined since it can be out of bounds. const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: { - const index = try sema.usizeCast(block, elem_index_src, try index_val.toUnsignedIntSema(pt)); - break :o index; + break :o try sema.usizeCast(block, elem_index_src, index_val.toUnsignedInt(zcu)); } else null; const elem_ptr_ty = try slice_ty.elemPtrType(offset, pt); @@ -28232,7 +27499,7 @@ fn elemPtrSlice( if (slice_val.isUndef(zcu)) { return pt.undefRef(elem_ptr_ty); } - const slice_len = try slice_val.sliceLen(pt); + const slice_len = slice_val.sliceLen(zcu); const slice_len_s = slice_len + @intFromBool(slice_sent); if (slice_len_s == 0) { return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{}); @@ -28254,13 +27521,13 @@ fn elemPtrSlice( const len_inst = len: { if (maybe_undef_slice_val) |slice_val| if (!slice_val.isUndef(zcu)) - break :len try pt.intRef(.usize, try slice_val.sliceLen(pt)); + break :len try pt.intRef(.usize, slice_val.sliceLen(zcu)); break :len try block.addTyOp(.slice_len, .usize, slice); }; const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt; try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op); } - if (!try slice_ty.childType(zcu).hasRuntimeBitsIgnoreComptimeSema(pt)) { + if (slice_ty.childType(zcu).abiSize(zcu) == 0) { // zero-bit child type; just extract the pointer and bitcast it const slice_ptr = try block.addTyOp(.slice_ptr, slice_ty.slicePtrFieldType(zcu), slice); return block.addBitCast(elem_ptr_ty, slice_ptr); @@ -28331,10 +27598,12 @@ fn coerceExtra( if (dest_ty.isGenericPoison()) return inst; const dest_ty_src = inst_src; // TODO better source location - try dest_ty.resolveFields(pt); const inst_ty = sema.typeOf(inst); - try inst_ty.resolveFields(pt); const target = zcu.getTarget(); + + inst_ty.assertHasLayout(zcu); + try sema.ensureLayoutResolved(dest_ty); + // If the types are the same, we can return the operand. if (dest_ty.eql(inst_ty, zcu)) return inst; @@ -28357,7 +27626,7 @@ fn coerceExtra( if (maybe_inst_val) |val| { // undefined sets the optional bit also to undefined. if (val.toIntern() == .undef) { - return pt.undefRef(dest_ty); + return .fromValue(try dest_ty.onePossibleValue(pt) orelse try pt.undefValue(dest_ty)); } // null to ?T @@ -28372,11 +27641,11 @@ fn coerceExtra( // cast from ?*T and ?[*]T to ?*anyopaque // but don't do it if the source type is a double pointer if (dest_ty.isPtrLikeOptional(zcu) and - dest_ty.elemType2(zcu).toIntern() == .anyopaque_type and + dest_ty.nullablePtrElem(zcu).toIntern() == .anyopaque_type and inst_ty.isPtrAtRuntime(zcu)) anyopaque_check: { if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :optional; - const elem_ty = inst_ty.elemType2(zcu); + const elem_ty = inst_ty.nullablePtrElem(zcu); if (elem_ty.zigTypeTag(zcu) == .pointer or elem_ty.isPtrLikeOptional(zcu)) { in_memory_result = .{ .double_ptr_to_anyopaque = .{ .actual = inst_ty, @@ -28520,7 +27789,7 @@ fn coerceExtra( // but don't do it if the source type is a double pointer if (dest_info.child == .anyopaque_type and inst_ty.zigTypeTag(zcu) == .pointer) to_anyopaque: { if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer; - const elem_ty = inst_ty.elemType2(zcu); + const elem_ty = inst_ty.childType(zcu); if (elem_ty.zigTypeTag(zcu) == .pointer or elem_ty.isPtrLikeOptional(zcu)) { in_memory_result = .{ .double_ptr_to_anyopaque = .{ .actual = inst_ty, @@ -28616,7 +27885,9 @@ fn coerceExtra( // empty tuple to zero-length slice // note that this allows coercing to a mutable slice. if (inst_child_ty.structFieldCount(zcu) == 0) { - const align_val = try dest_ty.ptrAlignmentSema(pt); + // TODO MLUGG: this is *unacceptably* stupid. we're resolving the child for the alignment value + try sema.ensureLayoutResolved(dest_ty.childType(zcu)); + const align_val = dest_ty.ptrAlignment(zcu); return Air.internedToRef(try pt.intern(.{ .slice = .{ .ty = dest_ty.toIntern(), .ptr = try pt.intern(.{ .ptr = .{ @@ -28689,7 +27960,7 @@ fn coerceExtra( return sema.fail(block, inst_src, "type '{f}' cannot represent integer value '{f}'", .{ dest_ty.fmt(pt), val.fmtValueSema(pt, sema) }); } return switch (zcu.intern_pool.indexToKey(val.toIntern())) { - .undef => try pt.undefRef(dest_ty), + .undef => .fromValue(try dest_ty.onePossibleValue(pt) orelse try pt.undefValue(dest_ty)), .int => |int| Air.internedToRef( try zcu.intern_pool.getCoercedInts(gpa, io, pt.tid, int, dest_ty.toIntern()), ), @@ -28768,7 +28039,7 @@ fn coerceExtra( } break :int; }; - const result_val = try val.floatFromIntAdvanced(sema.arena, inst_ty, dest_ty, pt, .sema); + const result_val = try pt.floatValue(dest_ty, val.toFloat(f128, zcu)); const fits: bool = switch (ip.indexToKey(result_val.toIntern())) { else => unreachable, .undef => true, @@ -28905,11 +28176,11 @@ fn coerceExtra( else => true, }; - if (can_coerce_to) { + if (can_coerce_to and inst == .undef) { // undefined to anything. We do this after the big switch above so that // special logic has a chance to run first, such as `*[N]T` to `[]T` which // should initialize the length field of the slice. - if (maybe_inst_val) |val| if (val.toIntern() == .undef) return pt.undefRef(dest_ty); + return .fromValue(try dest_ty.onePossibleValue(pt) orelse try pt.undefValue(dest_ty)); } if (!opts.report_err) return error.NotCoercible; @@ -29444,17 +28715,13 @@ pub fn coerceInMemoryAllowed( } // Pointers / Pointer-like Optionals - const maybe_dest_ptr_ty = try sema.typePtrOrOptionalPtrTy(dest_ty); - const maybe_src_ptr_ty = try sema.typePtrOrOptionalPtrTy(src_ty); - if (maybe_dest_ptr_ty) |dest_ptr_ty| { - if (maybe_src_ptr_ty) |src_ptr_ty| { - return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_ptr_ty, src_ptr_ty, dest_is_mut, target, dest_src, src_src); - } + if (dest_ty.isPtrAtRuntime(zcu) and src_ty.isPtrAtRuntime(zcu)) { + return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_is_mut, target, dest_src, src_src); } // Slices if (dest_ty.isSlice(zcu) and src_ty.isSlice(zcu)) { - return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_ty, src_ty, dest_is_mut, target, dest_src, src_src); + return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_is_mut, target, dest_src, src_src); } // Functions @@ -29554,7 +28821,8 @@ pub fn coerceInMemoryAllowed( // Optionals if (dest_tag == .optional and src_tag == .optional) { - if ((maybe_dest_ptr_ty != null) != (maybe_src_ptr_ty != null)) { + if (dest_ty.isPtrAtRuntime(zcu) or src_ty.isPtrAtRuntime(zcu)) { + // Only one is, because we already handled when both are. return .{ .optional_shape = .{ .actual = src_ty, .wanted = dest_ty, @@ -29581,7 +28849,7 @@ pub fn coerceInMemoryAllowed( const field_count = dest_ty.structFieldCount(zcu); for (0..field_count) |field_idx| { if (dest_ty.structFieldIsComptime(field_idx, zcu) != src_ty.structFieldIsComptime(field_idx, zcu)) break :tuple; - if (dest_ty.fieldAlignment(field_idx, zcu) != src_ty.fieldAlignment(field_idx, zcu)) break :tuple; + if (dest_ty.resolvedFieldAlignment(field_idx, zcu) != src_ty.resolvedFieldAlignment(field_idx, zcu)) break :tuple; const dest_field_ty = dest_ty.fieldType(field_idx, zcu); const src_field_ty = src_ty.fieldType(field_idx, zcu); const field = try sema.coerceInMemoryAllowed(block, dest_field_ty, src_field_ty, dest_is_mut, target, dest_src, src_src, null); @@ -29714,11 +28982,7 @@ fn coerceInMemoryAllowedFns( { if (dest_info.is_var_args != src_info.is_var_args) { - return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args }; - } - - if (dest_info.is_generic != src_info.is_generic) { - return InMemoryCoercionResult{ .fn_generic = dest_info.is_generic }; + return .{ .fn_var_args = dest_info.is_var_args }; } const callconv_ok = callconvCoerceAllowed(target, src_info.cc, dest_info.cc) and @@ -29731,6 +28995,12 @@ fn coerceInMemoryAllowedFns( } }; } + try sema.ensureLayoutResolved(src_ty); + try sema.ensureLayoutResolved(dest_ty); + const src_is_runtime = src_ty.fnHasRuntimeBits(zcu); + const dest_is_runtime = dest_ty.fnHasRuntimeBits(zcu); + if (src_is_runtime != dest_is_runtime) return .{ .fn_generic = !dest_is_runtime }; + if (!switch (src_info.return_type) { .generic_poison_type => true, .noreturn_type => !dest_is_mut, @@ -29780,7 +29050,8 @@ fn coerceInMemoryAllowedFns( const src_is_comptime = src_info.paramIsComptime(@intCast(param_i)); const dest_is_comptime = dest_info.paramIsComptime(@intCast(param_i)); if (src_is_comptime == dest_is_comptime) break :comptime_param; - if (!dest_is_mut and src_is_comptime and !dest_is_comptime and try dest_param_ty.comptimeOnlySema(pt)) { + try sema.ensureLayoutResolved(dest_param_ty); + if (!dest_is_mut and src_is_comptime and !dest_is_comptime and dest_param_ty.comptimeOnly(zcu)) { // A parameter which is marked `comptime` can drop that annotation if the type is comptime-only. // The function remains generic, and the parameter is going to be comptime-resolved either way, // so this just affects whether or not the argument is comptime-evaluated at the call site. @@ -29861,8 +29132,6 @@ fn coerceInMemoryAllowedPtrs( block: *Block, dest_ty: Type, src_ty: Type, - dest_ptr_ty: Type, - src_ptr_ty: Type, /// If set, the coercion must be valid in both directions. dest_is_mut: bool, target: *const std.Target, @@ -29875,8 +29144,8 @@ fn coerceInMemoryAllowedPtrs( const gpa = comp.gpa; const io = comp.io; - const dest_info = dest_ptr_ty.ptrInfo(zcu); - const src_info = src_ptr_ty.ptrInfo(zcu); + const dest_info = dest_ty.ptrInfo(zcu); + const src_info = src_ty.ptrInfo(zcu); const ok_ptr_size = src_info.flags.size == dest_info.flags.size or src_info.flags.size == .c or dest_info.flags.size == .c; @@ -30008,16 +29277,14 @@ fn coerceInMemoryAllowedPtrs( if (src_info.flags.alignment != .none or dest_info.flags.alignment != .none or dest_info.child != src_info.child) { - const src_align = if (src_info.flags.alignment != .none) - src_info.flags.alignment - else - try Type.fromInterned(src_info.child).abiAlignmentSema(pt); - - const dest_align = if (dest_info.flags.alignment != .none) - dest_info.flags.alignment - else - try Type.fromInterned(dest_info.child).abiAlignmentSema(pt); - + const src_align = if (src_info.flags.alignment == .none) a: { + try sema.ensureLayoutResolved(src_child); + break :a src_child.abiAlignment(zcu); + } else src_info.flags.alignment; + const dest_align = if (dest_info.flags.alignment == .none) a: { + try sema.ensureLayoutResolved(dest_child); + break :a dest_child.abiAlignment(zcu); + } else dest_info.flags.alignment; if (dest_align.compare(if (dest_is_mut) .neq else .gt, src_align)) { return InMemoryCoercionResult{ .ptr_alignment = .{ .actual = src_align, @@ -30180,9 +29447,16 @@ fn storePtr2( return sema.storePtrVal(block, src, ptr_val, operand_val, elem_ty); }; + // We do this after the possible comptime store above, for the case of field_ptr stores + // to unions because we want the comptime tag to be set, even if the field type is void. + // MLUGG TODO: that's insane, the runtime and comptime sematics should be the same. just set the tag at the same damn time + if (try elem_ty.onePossibleValue(pt) != null) { + return; + } + // We're performing the store at runtime; as such, we need to make sure the pointee type // is not comptime-only. We can hit this case with a `@ptrFromInt` pointer. - if (try elem_ty.comptimeOnlySema(pt)) { + if (elem_ty.comptimeOnly(zcu)) { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(src, "cannot store comptime-only type '{f}' at runtime", .{elem_ty.fmt(pt)}); errdefer msg.destroy(sema.gpa); @@ -30191,12 +29465,6 @@ fn storePtr2( }); } - // We do this after the possible comptime store above, for the case of field_ptr stores - // to unions because we want the comptime tag to be set, even if the field type is void. - if ((try sema.typeHasOnePossibleValue(elem_ty)) != null) { - return; - } - try sema.requireRuntimeBlock(block, src, runtime_src); const store_inst = if (is_ret) @@ -30361,10 +29629,10 @@ fn bitCast( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - try dest_ty.resolveLayout(pt); - const old_ty = sema.typeOf(inst); - try old_ty.resolveLayout(pt); + + old_ty.assertHasLayout(zcu); + try sema.ensureLayoutResolved(dest_ty); const dest_bits = dest_ty.bitSize(zcu); const old_bits = old_ty.bitSize(zcu); @@ -30510,9 +29778,7 @@ fn coerceCompatiblePtrs( } try sema.requireRuntimeBlock(block, inst_src, null); const inst_allows_zero = inst_ty.zigTypeTag(zcu) != .pointer or inst_ty.ptrAllowsZero(zcu); - if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero(zcu) and - (try dest_ty.elemType2(zcu).hasRuntimeBitsSema(pt) or dest_ty.elemType2(zcu).zigTypeTag(zcu) == .@"fn")) - { + if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero(zcu)) { try sema.checkLogicalPtrOperation(block, inst_src, inst_ty); const actual_ptr = if (inst_ty.isSlice(zcu)) try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty) @@ -30532,6 +29798,7 @@ fn coerceCompatiblePtrs( return new_ptr; } +/// Asserts that the layout of `union_ty` is already resolved. fn coerceEnumToUnion( sema: *Sema, block: *Block, @@ -30545,18 +29812,21 @@ fn coerceEnumToUnion( const ip = &zcu.intern_pool; const inst_ty = sema.typeOf(inst); - const tag_ty = union_ty.unionTagType(zcu) orelse { - const msg = msg: { - const msg = try sema.typeMismatchErrMsg(inst_src, union_ty, inst_ty); - errdefer msg.destroy(sema.gpa); - try sema.errNote(union_ty_src, msg, "cannot coerce enum to untagged union", .{}); - try sema.addDeclaredHereNote(msg, union_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); - }; + union_ty.assertHasLayout(zcu); - const enum_tag = try sema.coerce(block, tag_ty, inst, inst_src); + const union_obj = zcu.typeToUnion(union_ty).?; + const enum_ty: Type = .fromInterned(union_obj.enum_tag_type); + const enum_obj = ip.loadEnumType(enum_ty.toIntern()); + + if (union_obj.runtime_tag != .tagged) return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.typeMismatchErrMsg(inst_src, union_ty, inst_ty); + errdefer msg.destroy(sema.gpa); + try sema.errNote(union_ty_src, msg, "cannot coerce enum to untagged union", .{}); + try sema.addDeclaredHereNote(msg, union_ty); + break :msg msg; + }); + + const enum_tag = try sema.coerce(block, enum_ty, inst, inst_src); if (try sema.resolveDefinedValue(block, inst_src, enum_tag)) |val| { const field_index = union_ty.unionTagFieldIndex(val, pt.zcu) orelse { return sema.fail(block, inst_src, "union '{f}' has no tag with value '{f}'", .{ @@ -30564,15 +29834,12 @@ fn coerceEnumToUnion( }); }; - const union_obj = zcu.typeToUnion(union_ty).?; + const field_name = enum_obj.field_names.get(ip)[field_index]; const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); - try field_ty.resolveFields(pt); if (field_ty.zigTypeTag(zcu) == .noreturn) { const msg = msg: { const msg = try sema.errMsg(inst_src, "cannot initialize 'noreturn' field of union", .{}); errdefer msg.destroy(sema.gpa); - - const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{ field_name.fmt(ip), }); @@ -30581,42 +29848,35 @@ fn coerceEnumToUnion( }; return sema.failWithOwnedErrorMsg(block, msg); } - const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse { - const msg = msg: { - const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; - const msg = try sema.errMsg(inst_src, "coercion from enum '{f}' to union '{f}' must initialize '{f}' field '{f}'", .{ - inst_ty.fmt(pt), union_ty.fmt(pt), - field_ty.fmt(pt), field_name.fmt(ip), - }); - errdefer msg.destroy(sema.gpa); + const opv = try field_ty.onePossibleValue(pt) orelse return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(inst_src, "coercion from enum '{f}' to union '{f}' must initialize '{f}' field '{f}'", .{ + inst_ty.fmt(pt), union_ty.fmt(pt), + field_ty.fmt(pt), field_name.fmt(ip), + }); + errdefer msg.destroy(sema.gpa); - try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{ - field_name.fmt(ip), - }); - try sema.addDeclaredHereNote(msg, union_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); - }; + try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{field_name.fmt(ip)}); + try sema.addDeclaredHereNote(msg, union_ty); + break :msg msg; + }); return Air.internedToRef((try pt.unionValue(union_ty, val, opv)).toIntern()); } try sema.requireRuntimeBlock(block, inst_src, null); - if (tag_ty.isNonexhaustiveEnum(zcu)) { + if (enum_ty.isNonexhaustiveEnum(zcu)) { const msg = msg: { const msg = try sema.errMsg(inst_src, "runtime coercion to union '{f}' from non-exhaustive enum", .{ union_ty.fmt(pt), }); errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, tag_ty); + try sema.addDeclaredHereNote(msg, enum_ty); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); } - const union_obj = zcu.typeToUnion(union_ty).?; { var msg: ?*Zcu.ErrorMsg = null; errdefer if (msg) |some| some.destroy(sema.gpa); @@ -30626,7 +29886,7 @@ fn coerceEnumToUnion( const err_msg = msg orelse try sema.errMsg( inst_src, "runtime coercion from enum '{f}' to union '{f}' which has a 'noreturn' field", - .{ tag_ty.fmt(pt), union_ty.fmt(pt) }, + .{ enum_ty.fmt(pt), union_ty.fmt(pt) }, ); msg = err_msg; @@ -30649,14 +29909,14 @@ fn coerceEnumToUnion( const msg = try sema.errMsg( inst_src, "runtime coercion from enum '{f}' to union '{f}' which has non-void fields", - .{ tag_ty.fmt(pt), union_ty.fmt(pt) }, + .{ enum_ty.fmt(pt), union_ty.fmt(pt) }, ); errdefer msg.destroy(sema.gpa); for (0..union_obj.field_types.len) |field_index| { - const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; + const field_name = enum_obj.field_names.get(ip)[field_index]; const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); - if (!(try field_ty.hasRuntimeBitsSema(pt))) continue; + if (try field_ty.onePossibleValue(pt) != null) continue; try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' has type '{f}'", .{ field_name.fmt(ip), field_ty.fmt(pt), @@ -30904,19 +30164,16 @@ fn coerceTupleToTuple( const field_i: u32 = @intCast(field_index_usize); const field_src = inst_src; // TODO better source location - const field_ty = switch (ip.indexToKey(tuple_ty.toIntern())) { - .tuple_type => |tuple_type| tuple_type.types.get(ip)[field_index_usize], - .struct_type => ip.loadStructType(tuple_ty.toIntern()).field_types.get(ip)[field_index_usize], - else => unreachable, - }; - const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) { - .tuple_type => |tuple_type| tuple_type.values.get(ip)[field_index_usize], - .struct_type => ip.loadStructType(tuple_ty.toIntern()).fieldInit(ip, field_index_usize), - else => unreachable, - }; - const field_index: u32 = @intCast(field_index_usize); + const field_ty, const default_val = field: { + const tuple_type = ip.indexToKey(tuple_ty.toIntern()).tuple_type; + break :field .{ + tuple_type.types.get(ip)[field_index], + tuple_type.values.get(ip)[field_index], + }; + }; + const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i); const coerced = try sema.coerce(block, .fromInterned(field_ty), elem_ref, field_src); field_refs[field_index] = coerced; @@ -30946,11 +30203,7 @@ fn coerceTupleToTuple( const i: u32 = @intCast(i_usize); if (field_ref.* != .none) continue; - const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) { - .tuple_type => |tuple_type| tuple_type.values.get(ip)[i], - .struct_type => ip.loadStructType(tuple_ty.toIntern()).fieldInit(ip, i), - else => unreachable, - }; + const default_val = ip.indexToKey(tuple_ty.toIntern()).tuple_type.values.get(ip)[i]; const field_src = inst_src; // TODO better source location if (default_val == .none) { @@ -31019,13 +30272,13 @@ fn addReferenceEntry( pub fn addTypeReferenceEntry( sema: *Sema, src: LazySrcLoc, - referenced_type: InternPool.Index, + referenced_type: Type, ) !void { const zcu = sema.pt.zcu; if (!zcu.comp.config.incremental and zcu.comp.reference_trace == 0) return; - const gop = try sema.type_references.getOrPut(sema.gpa, referenced_type); + const gop = try sema.type_references.getOrPut(sema.gpa, referenced_type.toIntern()); if (gop.found_existing) return; - try zcu.addTypeReference(sema.owner, referenced_type, src); + try zcu.addTypeReference(sema.owner, referenced_type.toIntern(), src); } fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.MemoizedStateStage) SemaError!void { @@ -31143,7 +30396,7 @@ fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_inde .type_resolved => |r| .{ r.type, r.alignment, r.@"addrspace", r.is_const }, .fully_resolved => |r| .{ ip.typeOf(r.val), r.alignment, r.@"addrspace", r.is_const }, }; - const ptr_ty = try pt.ptrTypeSema(.{ + const ptr_ty = try pt.ptrType(.{ .child = ty, .flags = .{ .alignment = alignment, @@ -31185,7 +30438,7 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, block: *Block, src: LazySrcLoc, nav_i try sema.ensureNavResolved(block, src, nav_index, .type); const nav_ty: Type = .fromInterned(ip.getNav(nav_index).typeOf(ip)); if (nav_ty.zigTypeTag(zcu) != .@"fn") return; - if (!try nav_ty.fnHasRuntimeBitsSema(pt)) return; + if (!nav_ty.fnHasRuntimeBits(zcu)) return; try sema.ensureNavResolved(block, src, nav_index, .fully); const nav_val = zcu.navValue(nav_index); @@ -31218,14 +30471,14 @@ fn analyzeRef( // it's just that we can only use the *type* of the result, since the value is runtime-known. const address_space = target_util.defaultAddressSpace(zcu.getTarget(), .local); - const ptr_type = try pt.ptrTypeSema(.{ + const ptr_type = try pt.ptrType(.{ .child = operand_ty.toIntern(), .flags = .{ .is_const = true, .address_space = address_space, }, }); - const mut_ptr_type = try pt.ptrTypeSema(.{ + const mut_ptr_type = try pt.ptrType(.{ .child = operand_ty.toIntern(), .flags = .{ .address_space = address_space }, }); @@ -31261,9 +30514,8 @@ fn analyzeLoad( return sema.fail(block, ptr_src, "cannot load opaque type '{f}'", .{elem_ty.fmt(pt)}); } - if (try sema.typeHasOnePossibleValue(elem_ty)) |opv| { - return Air.internedToRef(opv.toIntern()); - } + try sema.ensureLayoutResolved(elem_ty); + if (try elem_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| { @@ -31271,6 +30523,13 @@ fn analyzeLoad( } } + if (elem_ty.comptimeOnly(zcu)) return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(src, "cannot load comptime-only type '{f}'", .{elem_ty.fmt(pt)}); + errdefer msg.destroy(zcu.gpa); + try sema.errNote(ptr_src, msg, "pointer of type '{f}' is runtime-known", .{ptr_ty.fmt(pt)}); + break :msg msg; + }); + return block.addTyOp(.load, elem_ty, ptr); } @@ -31332,7 +30591,7 @@ fn analyzeSliceLen( if (slice_val.isUndef(zcu)) { return .undef_usize; } - return pt.intRef(.usize, try slice_val.sliceLen(pt)); + return pt.intRef(.usize, slice_val.sliceLen(zcu)); } try sema.requireRuntimeBlock(block, src, null); return block.addTyOp(.slice_len, .usize, slice_inst); @@ -31682,6 +30941,8 @@ fn analyzeSlice( else => return sema.fail(block, src, "slice of non-array type '{f}'", .{ptr_ptr_child_ty.fmt(pt)}), } + try sema.ensureLayoutResolved(elem_ty); + const ptr = if (slice_ty.isSlice(zcu)) try sema.analyzeSlicePtr(block, ptr_src, ptr_or_slice, slice_ty) else if (array_ty.zigTypeTag(zcu) == .array) ptr: { @@ -31690,7 +30951,7 @@ fn analyzeSlice( assert(manyptr_ty_key.flags.size == .one); manyptr_ty_key.child = elem_ty.toIntern(); manyptr_ty_key.flags.size = .many; - break :ptr try sema.coerceCompatiblePtrs(block, try pt.ptrTypeSema(manyptr_ty_key), ptr_or_slice, ptr_src); + break :ptr try sema.coerceCompatiblePtrs(block, try pt.ptrType(manyptr_ty_key), ptr_or_slice, ptr_src); } else ptr_or_slice; const start = try sema.coerce(block, .usize, uncasted_start, start_src); @@ -31759,7 +31020,7 @@ fn analyzeSlice( return sema.fail(block, src, "slice of undefined", .{}); } const has_sentinel = slice_ty.sentinel(zcu) != null; - const slice_len = try slice_val.sliceLen(pt); + const slice_len = slice_val.sliceLen(zcu); const len_plus_sent = slice_len + @intFromBool(has_sentinel); const slice_len_val_with_sentinel = try pt.intValue(.usize, len_plus_sent); if (!(try sema.compareAll(end_val, .lte, slice_len_val_with_sentinel, .usize))) { @@ -31774,7 +31035,7 @@ fn analyzeSlice( "end index {f} out of bounds for slice of length {d}{s}", .{ end_val.fmtValueSema(pt, sema), - try slice_val.sliceLen(pt), + slice_val.sliceLen(zcu), sentinel_label, }, ); @@ -31943,9 +31204,9 @@ fn analyzeSlice( const new_allowzero = new_ptr_ty_info.flags.is_allowzero and sema.typeOf(ptr).ptrSize(zcu) != .c; if (opt_new_len_val) |new_len_val| { - const new_len_int = try new_len_val.toUnsignedIntSema(pt); + const new_len_int = new_len_val.toUnsignedInt(zcu); - const return_ty = try pt.ptrTypeSema(.{ + const return_ty = try pt.ptrType(.{ .child = (try pt.arrayType(.{ .len = new_len_int, .sentinel = if (sentinel) |s| s.toIntern() else .none, @@ -32009,7 +31270,7 @@ fn analyzeSlice( return sema.fail(block, src, "non-zero length slice of undefined pointer", .{}); } - const return_ty = try pt.ptrTypeSema(.{ + const return_ty = try pt.ptrType(.{ .child = elem_ty.toIntern(), .sentinel = if (sentinel) |s| s.toIntern() else .none, .flags = .{ @@ -32037,7 +31298,7 @@ fn analyzeSlice( if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| { // we don't need to add one for sentinels because the // underlying value data includes the sentinel - break :blk try pt.intRef(.usize, try slice_val.sliceLen(pt)); + break :blk try pt.intRef(.usize, slice_val.sliceLen(zcu)); } const slice_len_inst = try block.addTyOp(.slice_len, .usize, ptr_or_slice); @@ -32158,16 +31419,10 @@ fn cmpNumeric( const runtime_src: LazySrcLoc = if (maybe_lhs_val) |lhs_val| rs: { if (maybe_rhs_val) |rhs_val| { - const res = try Value.compareHeteroSema(lhs_val, op, rhs_val, pt); - return if (res) .bool_true else .bool_false; + return .fromValue(.makeBool(Value.compareHetero(lhs_val, op, rhs_val, zcu))); } else break :rs rhs_src; } else lhs_src; - // TODO handle comparisons against lazy zero values - // Some values can be compared against zero without being runtime-known or without forcing - // a full resolution of their value, for example `@sizeOf(@Frame(function))` is known to - // always be nonzero, and we benefit from not forcing the full evaluation and stack frame layout - // of this function if we don't need to. try sema.requireRuntimeBlock(block, src, runtime_src); // For floats, emit a float comparison instruction. @@ -32207,11 +31462,11 @@ fn cmpNumeric( // a signed integer with mantissa bits + 1, and if there was any non-integral part of the float, // add/subtract 1. const lhs_is_signed = if (maybe_lhs_val) |lhs_val| - !(try lhs_val.compareAllWithZeroSema(.gte, pt)) + !lhs_val.compareAllWithZero(.gte, zcu) else (lhs_ty.isRuntimeFloat() or lhs_ty.isSignedInt(zcu)); const rhs_is_signed = if (maybe_rhs_val) |rhs_val| - !(try rhs_val.compareAllWithZeroSema(.gte, pt)) + !rhs_val.compareAllWithZero(.gte, zcu) else (rhs_ty.isRuntimeFloat() or rhs_ty.isSignedInt(zcu)); const dest_int_is_signed = lhs_is_signed or rhs_is_signed; @@ -32219,10 +31474,9 @@ fn cmpNumeric( var dest_float_type: ?Type = null; var lhs_bits: usize = undefined; - if (maybe_lhs_val) |unresolved_lhs_val| { - const lhs_val = try sema.resolveLazyValue(unresolved_lhs_val); + if (maybe_lhs_val) |lhs_val| { if (!rhs_is_signed) { - switch (lhs_val.orderAgainstZero(zcu)) { + switch (Value.order(lhs_val, .zero_comptime_int, zcu)) { .gt => {}, .eq => switch (op) { // LHS = 0, RHS is unsigned .lte => return .bool_true, @@ -32263,10 +31517,9 @@ fn cmpNumeric( } var rhs_bits: usize = undefined; - if (maybe_rhs_val) |unresolved_rhs_val| { - const rhs_val = try sema.resolveLazyValue(unresolved_rhs_val); + if (maybe_rhs_val) |rhs_val| { if (!lhs_is_signed) { - switch (rhs_val.orderAgainstZero(zcu)) { + switch (Value.order(rhs_val, .zero_comptime_int, zcu)) { .gt => {}, .eq => switch (op) { // RHS = 0, LHS is unsigned .gte => return .bool_true, @@ -32328,7 +31581,7 @@ fn compareIntsOnlyPossibleResult( lhs_val: Value, op: std.math.CompareOperator, rhs_ty: Type, -) SemaError!?bool { +) Allocator.Error!?bool { const pt = sema.pt; const zcu = pt.zcu; @@ -32337,11 +31590,11 @@ fn compareIntsOnlyPossibleResult( if (min_rhs.toIntern() == max_rhs.toIntern()) { // RHS is effectively comptime-known. - return try Value.compareHeteroSema(lhs_val, op, min_rhs, pt); + return Value.compareHetero(lhs_val, op, min_rhs, zcu); } - const against_min = try lhs_val.orderAdvanced(min_rhs, .sema, zcu, pt.tid); - const against_max = try lhs_val.orderAdvanced(max_rhs, .sema, zcu, pt.tid); + const against_min = lhs_val.order(min_rhs, zcu); + const against_max = lhs_val.order(max_rhs, zcu); switch (op) { .eq => { @@ -32529,9 +31782,7 @@ fn unionToTag( ) !Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - if ((try sema.typeHasOnePossibleValue(enum_ty))) |opv| { - return Air.internedToRef(opv.toIntern()); - } + if (try enum_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); if (try sema.resolveValue(un)) |un_val| { const tag_val = un_val.unionTag(zcu).?; if (tag_val.isUndef(zcu)) @@ -33240,18 +32491,24 @@ fn resolvePeerTypesInner( ptr_info.sentinel = .none; } - // Note that the align can be always non-zero; Zcu.ptrType will canonicalize it - ptr_info.flags.alignment = InternPool.Alignment.min( - if (ptr_info.flags.alignment != .none) - ptr_info.flags.alignment - else - Type.fromInterned(ptr_info.child).abiAlignment(zcu), - - if (peer_info.flags.alignment != .none) - peer_info.flags.alignment - else - Type.fromInterned(peer_info.child).abiAlignment(zcu), - ); + ptr_info.flags.alignment = a: { + // If both alignments are implicit, the result alignment is implicit. + // e.g. '[*c]u32' + '[*c]c_uint' -> '[*c]u32' + if (ptr_info.flags.alignment == .none and peer_info.flags.alignment == .none) { + break :a .none; + } + // Otherwise (if either alignment is explicit), the result alignment is explicit. + // e.g. '[*c]u32' + '[*c]align(4) c_uint' -> '[*c]align(4) u32' + const cur_align = switch (ptr_info.flags.alignment) { + .none => Type.fromInterned(ptr_info.child).abiAlignment(zcu), + else => ptr_info.flags.alignment, + }; + const new_align = switch (peer_info.flags.alignment) { + .none => Type.fromInterned(peer_info.child).abiAlignment(zcu), + else => peer_info.flags.alignment, + }; + break :a .minStrict(cur_align, new_align); + }; if (ptr_info.flags.address_space != peer_info.flags.address_space) { return .{ .conflict = .{ .peer_idx_a = first_idx, @@ -33273,7 +32530,7 @@ fn resolvePeerTypesInner( opt_ptr_info = ptr_info; } - return .{ .success = try pt.ptrTypeSema(opt_ptr_info.?) }; + return .{ .success = try pt.ptrType(opt_ptr_info.?) }; }, .ptr => { @@ -33281,7 +32538,6 @@ fn resolvePeerTypesInner( // if there were no actual slices. Else, we want the slice index to report a conflict. var opt_slice_idx: ?usize = null; - var any_abi_aligned = false; var opt_ptr_info: ?InternPool.Key.PtrType = null; var first_idx: usize = undefined; var other_idx: usize = undefined; // We sometimes need a second peer index to report a generic error @@ -33325,15 +32581,24 @@ fn resolvePeerTypesInner( .peer_idx_b = i, } }; - // Note that the align can be always non-zero; Type.ptr will canonicalize it - if (peer_info.flags.alignment == .none) { - any_abi_aligned = true; - } else if (ptr_info.flags.alignment == .none) { - any_abi_aligned = true; - ptr_info.flags.alignment = peer_info.flags.alignment; - } else { - ptr_info.flags.alignment = ptr_info.flags.alignment.minStrict(peer_info.flags.alignment); - } + ptr_info.flags.alignment = a: { + // If both alignments are implicit, the result alignment is implicit. + // e.g. '[*c]u32' + '[*c]c_uint' -> '[*c]u32' + if (ptr_info.flags.alignment == .none and peer_info.flags.alignment == .none) { + break :a .none; + } + // Otherwise (if either alignment is explicit), the result alignment is explicit. + // e.g. '[*c]u32' + '[*c]align(4) c_uint' -> '[*c]align(4) u32' + const cur_align = switch (ptr_info.flags.alignment) { + .none => Type.fromInterned(ptr_info.child).abiAlignment(zcu), + else => ptr_info.flags.alignment, + }; + const new_align = switch (peer_info.flags.alignment) { + .none => Type.fromInterned(peer_info.child).abiAlignment(zcu), + else => peer_info.flags.alignment, + }; + break :a .minStrict(cur_align, new_align); + }; if (ptr_info.flags.address_space != peer_info.flags.address_space) { return generic_err; @@ -33582,13 +32847,7 @@ fn resolvePeerTypesInner( }, } - if (any_abi_aligned and opt_ptr_info.?.flags.alignment != .none) { - opt_ptr_info.?.flags.alignment = opt_ptr_info.?.flags.alignment.minStrict( - try Type.fromInterned(pointee).abiAlignmentSema(pt), - ); - } - - return .{ .success = try pt.ptrTypeSema(opt_ptr_info.?) }; + return .{ .success = try pt.ptrType(opt_ptr_info.?) }; }, .func => { @@ -33731,7 +32990,7 @@ fn resolvePeerTypesInner( .peer_idx_b = i, } }; any_comptime_known = true; - ptr_opt_val.* = try sema.resolveLazyValue(opt_val.?); + ptr_opt_val.* = opt_val.?; continue; }, .int => {}, @@ -33924,7 +33183,6 @@ fn resolvePeerTypesInner( var comptime_val: ?Value = null; for (peer_tys) |opt_ty| { const struct_ty = opt_ty orelse continue; - try struct_ty.resolveStructFieldInits(pt); const uncoerced_field_val = try struct_ty.structFieldValueComptime(pt, field_index) orelse { comptime_val = null; @@ -34058,344 +33316,6 @@ pub fn resolveIes(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError!void } } -pub fn resolveFnTypes(sema: *Sema, fn_ty: Type, src: LazySrcLoc) CompileError!void { - const pt = sema.pt; - const zcu = pt.zcu; - const ip = &zcu.intern_pool; - const fn_ty_info = zcu.typeToFunc(fn_ty).?; - - try Type.fromInterned(fn_ty_info.return_type).resolveFully(pt); - - if (zcu.comp.config.any_error_tracing and - Type.fromInterned(fn_ty_info.return_type).isError(zcu)) - { - // Ensure the type exists so that backends can assume that. - _ = try sema.getBuiltinType(src, .StackTrace); - } - - for (0..fn_ty_info.param_types.len) |i| { - try Type.fromInterned(fn_ty_info.param_types.get(ip)[i]).resolveFully(pt); - } -} - -fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value { - return val.resolveLazy(sema.arena, sema.pt); -} - -/// Resolve a struct's alignment only without triggering resolution of its layout. -/// Asserts that the alignment is not yet resolved and the layout is non-packed. -pub fn resolveStructAlignment( - sema: *Sema, - ty: InternPool.Index, - struct_type: InternPool.LoadedStructType, -) SemaError!void { - const pt = sema.pt; - const zcu = pt.zcu; - const io = zcu.comp.io; - const ip = &zcu.intern_pool; - const target = zcu.getTarget(); - - assert(sema.owner.unwrap().type == ty); - - assert(struct_type.layout != .@"packed"); - assert(struct_type.flagsUnordered(ip).alignment == .none); - - const ptr_align = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)); - - // We'll guess "pointer-aligned", if the struct has an - // underaligned pointer field then some allocations - // might require explicit alignment. - if (struct_type.assumePointerAlignedIfFieldTypesWip(ip, io, ptr_align)) return; - - try sema.resolveStructFieldTypes(ty, struct_type); - - // We'll guess "pointer-aligned", if the struct has an - // underaligned pointer field then some allocations - // might require explicit alignment. - if (struct_type.assumePointerAlignedIfWip(ip, io, ptr_align)) return; - defer struct_type.clearAlignmentWip(ip, io); - - // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis. - // It's just triggering *other* analysis, alongside a simple loop over already-resolved info. - - var alignment: Alignment = .@"1"; - - for (0..struct_type.field_types.len) |i| { - const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); - if (struct_type.fieldIsComptime(ip, i) or try field_ty.comptimeOnlySema(pt)) - continue; - const field_align = try field_ty.structFieldAlignmentSema( - struct_type.fieldAlign(ip, i), - struct_type.layout, - pt, - ); - alignment = alignment.maxStrict(field_align); - } - - struct_type.setAlignment(ip, io, alignment); -} - -pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void { - const pt = sema.pt; - const zcu = pt.zcu; - const ip = &zcu.intern_pool; - const io = zcu.comp.io; - const struct_type = zcu.typeToStruct(ty) orelse return; - - assert(sema.owner.unwrap().type == ty.toIntern()); - - if (struct_type.haveLayout(ip)) - return; - - try sema.resolveStructFieldTypes(ty.toIntern(), struct_type); - - // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis. - // It's just triggering *other* analysis, alongside a simple loop over already-resolved info. - - if (struct_type.layout == .@"packed") { - sema.backingIntType(struct_type) catch |err| switch (err) { - error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e, - error.ComptimeBreak, error.ComptimeReturn => unreachable, - }; - return; - } - - if (struct_type.setLayoutWip(ip, io)) { - const msg = try sema.errMsg( - ty.srcLoc(zcu), - "struct '{f}' depends on itself", - .{ty.fmt(pt)}, - ); - return sema.failWithOwnedErrorMsg(null, msg); - } - defer struct_type.clearLayoutWip(ip, io); - - const aligns = try sema.arena.alloc(Alignment, struct_type.field_types.len); - const sizes = try sema.arena.alloc(u64, struct_type.field_types.len); - - var big_align: Alignment = .@"1"; - - for (aligns, sizes, 0..) |*field_align, *field_size, i| { - const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); - if (struct_type.fieldIsComptime(ip, i) or try field_ty.comptimeOnlySema(pt)) { - struct_type.offsets.get(ip)[i] = 0; - field_size.* = 0; - field_align.* = .none; - continue; - } - - field_size.* = field_ty.abiSizeSema(pt) catch |err| switch (err) { - error.AnalysisFail => { - const msg = sema.err orelse return err; - try sema.addFieldErrNote(ty, i, msg, "while checking this field", .{}); - return err; - }, - else => return err, - }; - field_align.* = try field_ty.structFieldAlignmentSema( - struct_type.fieldAlign(ip, i), - struct_type.layout, - pt, - ); - big_align = big_align.maxStrict(field_align.*); - } - - if (struct_type.flagsUnordered(ip).assumed_runtime_bits and !(try ty.hasRuntimeBitsSema(pt))) { - const msg = try sema.errMsg( - ty.srcLoc(zcu), - "struct layout depends on it having runtime bits", - .{}, - ); - return sema.failWithOwnedErrorMsg(null, msg); - } - - if (struct_type.flagsUnordered(ip).assumed_pointer_aligned and - big_align.compareStrict(.neq, Alignment.fromByteUnits(@divExact(zcu.getTarget().ptrBitWidth(), 8)))) - { - const msg = try sema.errMsg( - ty.srcLoc(zcu), - "struct layout depends on being pointer aligned", - .{}, - ); - return sema.failWithOwnedErrorMsg(null, msg); - } - - if (struct_type.hasReorderedFields()) { - const runtime_order = struct_type.runtime_order.get(ip); - - for (runtime_order, 0..) |*ro, i| { - const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); - if (struct_type.fieldIsComptime(ip, i) or try field_ty.comptimeOnlySema(pt)) { - ro.* = .omitted; - } else { - ro.* = @enumFromInt(i); - } - } - - const RuntimeOrder = InternPool.LoadedStructType.RuntimeOrder; - - const AlignSortContext = struct { - aligns: []const Alignment, - - fn lessThan(ctx: @This(), a: RuntimeOrder, b: RuntimeOrder) bool { - if (a == .omitted) return false; - if (b == .omitted) return true; - const a_align = ctx.aligns[@intFromEnum(a)]; - const b_align = ctx.aligns[@intFromEnum(b)]; - return a_align.compare(.gt, b_align); - } - }; - if (!zcu.backendSupportsFeature(.field_reordering)) { - // TODO: we should probably also reorder tuple fields? This is a bit weird because it'll involve - // mutating the `InternPool` for a non-container type. - // - // TODO: implement field reordering support in all the backends! - // - // This logic does not reorder fields; it only moves the omitted ones to the end - // so that logic elsewhere does not need to special-case here. - var i: usize = 0; - var off: usize = 0; - while (i + off < runtime_order.len) { - if (runtime_order[i + off] == .omitted) { - off += 1; - continue; - } - runtime_order[i] = runtime_order[i + off]; - i += 1; - } - @memset(runtime_order[i..], .omitted); - } else { - mem.sortUnstable(RuntimeOrder, runtime_order, AlignSortContext{ - .aligns = aligns, - }, AlignSortContext.lessThan); - } - } - - // Calculate size, alignment, and field offsets. - const offsets = struct_type.offsets.get(ip); - var it = struct_type.iterateRuntimeOrder(ip); - var offset: u64 = 0; - while (it.next()) |i| { - offsets[i] = @intCast(aligns[i].forward(offset)); - offset = offsets[i] + sizes[i]; - } - const size = std.math.cast(u32, big_align.forward(offset)) orelse { - const msg = try sema.errMsg( - ty.srcLoc(zcu), - "struct layout requires size {d}, this compiler implementation supports up to {d}", - .{ big_align.forward(offset), std.math.maxInt(u32) }, - ); - return sema.failWithOwnedErrorMsg(null, msg); - }; - struct_type.setLayoutResolved(ip, io, size, big_align); - _ = try ty.comptimeOnlySema(pt); -} - -fn backingIntType( - sema: *Sema, - struct_type: InternPool.LoadedStructType, -) CompileError!void { - const pt = sema.pt; - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const io = comp.io; - const ip = &zcu.intern_pool; - - var analysis_arena = std.heap.ArenaAllocator.init(gpa); - defer analysis_arena.deinit(); - - var block: Block = .{ - .parent = null, - .sema = sema, - .namespace = struct_type.namespace, - .instructions = .{}, - .inlining = null, - .comptime_reason = null, // set below if needed - .src_base_inst = struct_type.zir_index, - .type_name_ctx = struct_type.name, - }; - defer assert(block.instructions.items.len == 0); - - const fields_bit_sum = blk: { - var accumulator: u64 = 0; - for (0..struct_type.field_types.len) |i| { - const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); - accumulator += try field_ty.bitSizeSema(pt); - } - break :blk accumulator; - }; - - const zir = zcu.namespacePtr(struct_type.namespace).fileScope(zcu).zir.?; - const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail; - const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; - assert(extended.opcode == .struct_decl); - const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); - - if (small.has_backing_int) { - var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len; - const captures_len = if (small.has_captures_len) blk: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - extra_index += @intFromBool(small.has_fields_len); - extra_index += @intFromBool(small.has_decls_len); - - extra_index += captures_len * 2; - - const backing_int_body_len = zir.extra[extra_index]; - extra_index += 1; - - const backing_int_src: LazySrcLoc = .{ - .base_node_inst = struct_type.zir_index, - .offset = .{ .node_offset_container_tag = .zero }, - }; - block.comptime_reason = .{ .reason = .{ - .src = backing_int_src, - .r = .{ .simple = .type }, - } }; - const backing_int_ty = blk: { - if (backing_int_body_len == 0) { - const backing_int_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]); - break :blk try sema.resolveType(&block, backing_int_src, backing_int_ref); - } else { - const body = zir.bodySlice(extra_index, backing_int_body_len); - const ty_ref = try sema.resolveInlineBody(&block, body, zir_index); - break :blk try sema.analyzeAsType(&block, backing_int_src, ty_ref); - } - }; - - try sema.checkBackingIntType(&block, backing_int_src, backing_int_ty, fields_bit_sum); - struct_type.setBackingIntType(ip, io, backing_int_ty.toIntern()); - } else { - if (fields_bit_sum > std.math.maxInt(u16)) { - return sema.fail(&block, block.nodeOffset(.zero), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum}); - } - const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum)); - struct_type.setBackingIntType(ip, io, backing_int_ty.toIntern()); - } - - try sema.flushExports(); -} - -fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_ty: Type, fields_bit_sum: u64) CompileError!void { - const pt = sema.pt; - const zcu = pt.zcu; - - if (!backing_int_ty.isInt(zcu)) { - return sema.fail(block, src, "expected backing integer type, found '{f}'", .{backing_int_ty.fmt(pt)}); - } - if (backing_int_ty.bitSize(zcu) != fields_bit_sum) { - return sema.fail( - block, - src, - "backing integer type '{f}' has bit size {d} but the struct fields have a total bit size of {d}", - .{ backing_int_ty.fmt(pt), backing_int_ty.bitSize(zcu), fields_bit_sum }, - ); - } -} - fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { const pt = sema.pt; if (!ty.isIndexable(pt.zcu)) { @@ -34432,358 +33352,6 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void return sema.failWithOwnedErrorMsg(block, msg); } -/// Resolve a unions's alignment only without triggering resolution of its layout. -/// Asserts that the alignment is not yet resolved. -pub fn resolveUnionAlignment( - sema: *Sema, - ty: Type, - union_type: InternPool.LoadedUnionType, -) SemaError!void { - const pt = sema.pt; - const zcu = pt.zcu; - const io = zcu.comp.io; - const ip = &zcu.intern_pool; - const target = zcu.getTarget(); - - assert(sema.owner.unwrap().type == ty.toIntern()); - - assert(!union_type.haveLayout(ip)); - - const ptr_align = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)); - - // We'll guess "pointer-aligned", if the union has an - // underaligned pointer field then some allocations - // might require explicit alignment. - if (union_type.assumePointerAlignedIfFieldTypesWip(ip, io, ptr_align)) return; - - try sema.resolveUnionFieldTypes(ty, union_type); - - // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis. - // It's just triggering *other* analysis, alongside a simple loop over already-resolved info. - - var max_align: Alignment = .@"1"; - for (0..union_type.field_types.len) |field_index| { - const field_ty: Type = .fromInterned(union_type.field_types.get(ip)[field_index]); - if (!(try field_ty.hasRuntimeBitsSema(pt))) continue; - - const explicit_align = union_type.fieldAlign(ip, field_index); - const field_align = if (explicit_align != .none) - explicit_align - else - try field_ty.abiAlignmentSema(sema.pt); - - max_align = max_align.max(field_align); - } - - union_type.setAlignment(ip, io, max_align); -} - -/// This logic must be kept in sync with `Type.getUnionLayout`. -pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void { - const pt = sema.pt; - const io = pt.zcu.comp.io; - const ip = &pt.zcu.intern_pool; - - try sema.resolveUnionFieldTypes(ty, ip.loadUnionType(ty.ip_index)); - - // Load again, since the tag type might have changed due to resolution. - const union_type = ip.loadUnionType(ty.ip_index); - - assert(sema.owner.unwrap().type == ty.toIntern()); - - const old_flags = union_type.flagsUnordered(ip); - switch (old_flags.status) { - .none, .have_field_types => {}, - .field_types_wip, .layout_wip => { - const msg = try sema.errMsg( - ty.srcLoc(pt.zcu), - "union '{f}' depends on itself", - .{ty.fmt(pt)}, - ); - return sema.failWithOwnedErrorMsg(null, msg); - }, - .have_layout, .fully_resolved_wip, .fully_resolved => return, - } - - errdefer union_type.setStatusIfLayoutWip(ip, io, old_flags.status); - - union_type.setStatus(ip, io, .layout_wip); - - // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis. - // It's just triggering *other* analysis, alongside a simple loop over already-resolved info. - - var max_size: u64 = 0; - var max_align: Alignment = .@"1"; - for (0..union_type.field_types.len) |field_index| { - const field_ty: Type = .fromInterned(union_type.field_types.get(ip)[field_index]); - if (field_ty.isNoReturn(pt.zcu)) continue; - - // We need to call `hasRuntimeBits` before calling `abiSize` to prevent reachable `unreachable`s, - // but `hasRuntimeBits` only resolves field types and so may infinite recurse on a layout wip type, - // so we must resolve the layout manually first, instead of waiting for `abiSize` to do it for us. - // This is arguably just hacking around bugs in both `abiSize` for not allowing arbitrary types to - // be queried, enabling failures to be handled with the emission of a compile error, and also in - // `hasRuntimeBits` for ever being able to infinite recurse in the first place. - try field_ty.resolveLayout(pt); - - if (try field_ty.hasRuntimeBitsSema(pt)) { - max_size = @max(max_size, field_ty.abiSizeSema(pt) catch |err| switch (err) { - error.AnalysisFail => { - const msg = sema.err orelse return err; - try sema.addFieldErrNote(ty, field_index, msg, "while checking this field", .{}); - return err; - }, - else => return err, - }); - } - - const explicit_align = union_type.fieldAlign(ip, field_index); - const field_align = if (explicit_align != .none) - explicit_align - else - try field_ty.abiAlignmentSema(pt); - max_align = max_align.max(field_align); - } - - const has_runtime_tag = union_type.flagsUnordered(ip).runtime_tag.hasTag() and - try Type.fromInterned(union_type.enum_tag_ty).hasRuntimeBitsSema(pt); - const size, const alignment, const padding = if (has_runtime_tag) layout: { - const enum_tag_type: Type = .fromInterned(union_type.enum_tag_ty); - const tag_align = try enum_tag_type.abiAlignmentSema(pt); - const tag_size = try enum_tag_type.abiSizeSema(pt); - - // Put the tag before or after the payload depending on which one's - // alignment is greater. - var size: u64 = 0; - var padding: u32 = 0; - if (tag_align.order(max_align).compare(.gte)) { - // {Tag, Payload} - size += tag_size; - size = max_align.forward(size); - size += max_size; - const prev_size = size; - size = tag_align.forward(size); - padding = @intCast(size - prev_size); - } else { - // {Payload, Tag} - size += max_size; - size = switch (pt.zcu.getTarget().ofmt) { - .c => max_align, - else => tag_align, - }.forward(size); - size += tag_size; - const prev_size = size; - size = max_align.forward(size); - padding = @intCast(size - prev_size); - } - - break :layout .{ size, max_align.max(tag_align), padding }; - } else .{ max_align.forward(max_size), max_align, 0 }; - - const casted_size = std.math.cast(u32, size) orelse { - const msg = try sema.errMsg( - ty.srcLoc(pt.zcu), - "union layout requires size {d}, this compiler implementation supports up to {d}", - .{ size, std.math.maxInt(u32) }, - ); - return sema.failWithOwnedErrorMsg(null, msg); - }; - union_type.setHaveLayout(ip, io, casted_size, padding, alignment); - - if (union_type.flagsUnordered(ip).assumed_runtime_bits and !(try ty.hasRuntimeBitsSema(pt))) { - const msg = try sema.errMsg( - ty.srcLoc(pt.zcu), - "union layout depends on it having runtime bits", - .{}, - ); - return sema.failWithOwnedErrorMsg(null, msg); - } - - if (union_type.flagsUnordered(ip).assumed_pointer_aligned and - alignment.compareStrict(.neq, Alignment.fromByteUnits(@divExact(pt.zcu.getTarget().ptrBitWidth(), 8)))) - { - const msg = try sema.errMsg( - ty.srcLoc(pt.zcu), - "union layout depends on being pointer aligned", - .{}, - ); - return sema.failWithOwnedErrorMsg(null, msg); - } - _ = try ty.comptimeOnlySema(pt); -} - -/// Returns `error.AnalysisFail` if any of the types (recursively) failed to -/// be resolved. -pub fn resolveStructFully(sema: *Sema, ty: Type) SemaError!void { - try sema.resolveStructLayout(ty); - try sema.resolveStructFieldInits(ty); - - const pt = sema.pt; - const zcu = pt.zcu; - const io = zcu.comp.io; - const ip = &zcu.intern_pool; - const struct_type = zcu.typeToStruct(ty).?; - - assert(sema.owner.unwrap().type == ty.toIntern()); - - if (struct_type.setFullyResolved(ip, io)) return; - errdefer struct_type.clearFullyResolved(ip, io); - - // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis. - // It's just triggering *other* analysis, alongside a simple loop over already-resolved info. - - // After we have resolve struct layout we have to go over the fields again to - // make sure pointer fields get their child types resolved as well. - // See also similar code for unions. - - for (0..struct_type.field_types.len) |i| { - const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); - try field_ty.resolveFully(pt); - } -} - -pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void { - try sema.resolveUnionLayout(ty); - - const pt = sema.pt; - const zcu = pt.zcu; - const io = zcu.comp.io; - const ip = &zcu.intern_pool; - const union_obj = zcu.typeToUnion(ty).?; - - assert(sema.owner.unwrap().type == ty.toIntern()); - - switch (union_obj.flagsUnordered(ip).status) { - .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {}, - .fully_resolved_wip, .fully_resolved => return, - } - - // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis. - // It's just triggering *other* analysis, alongside a simple loop over already-resolved info. - - { - // After we have resolve union layout we have to go over the fields again to - // make sure pointer fields get their child types resolved as well. - // See also similar code for structs. - const prev_status = union_obj.flagsUnordered(ip).status; - errdefer union_obj.setStatus(ip, io, prev_status); - - union_obj.setStatus(ip, io, .fully_resolved_wip); - for (0..union_obj.field_types.len) |field_index| { - const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); - try field_ty.resolveFully(pt); - } - union_obj.setStatus(ip, io, .fully_resolved); - } - - // And let's not forget comptime-only status. - _ = try ty.comptimeOnlySema(pt); -} - -pub fn resolveStructFieldTypes( - sema: *Sema, - ty: InternPool.Index, - struct_type: InternPool.LoadedStructType, -) SemaError!void { - const pt = sema.pt; - const zcu = pt.zcu; - const io = zcu.comp.io; - const ip = &zcu.intern_pool; - - assert(sema.owner.unwrap().type == ty); - - if (struct_type.haveFieldTypes(ip)) return; - - if (struct_type.setFieldTypesWip(ip, io)) { - const msg = try sema.errMsg( - Type.fromInterned(ty).srcLoc(zcu), - "struct '{f}' depends on itself", - .{Type.fromInterned(ty).fmt(pt)}, - ); - return sema.failWithOwnedErrorMsg(null, msg); - } - defer struct_type.clearFieldTypesWip(ip, io); - - // can't happen earlier than this because we only want the progress node if not already resolved - const tracked_unit = zcu.trackUnitSema(struct_type.name.toSlice(ip), null); - defer tracked_unit.end(zcu); - - sema.structFields(struct_type) catch |err| switch (err) { - error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e, - error.ComptimeBreak, error.ComptimeReturn => unreachable, - }; -} - -pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void { - const pt = sema.pt; - const zcu = pt.zcu; - const io = zcu.comp.io; - const ip = &zcu.intern_pool; - const struct_type = zcu.typeToStruct(ty) orelse return; - - assert(sema.owner.unwrap().type == ty.toIntern()); - - // Inits can start as resolved - if (struct_type.haveFieldInits(ip)) return; - - try sema.resolveStructLayout(ty); - - if (struct_type.setInitsWip(ip, io)) { - const msg = try sema.errMsg( - ty.srcLoc(zcu), - "struct '{f}' depends on itself", - .{ty.fmt(pt)}, - ); - return sema.failWithOwnedErrorMsg(null, msg); - } - defer struct_type.clearInitsWip(ip, io); - - // can't happen earlier than this because we only want the progress node if not already resolved - const tracked_unit = zcu.trackUnitSema(struct_type.name.toSlice(ip), null); - defer tracked_unit.end(zcu); - - sema.structFieldInits(struct_type) catch |err| switch (err) { - error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e, - error.ComptimeBreak, error.ComptimeReturn => unreachable, - }; - struct_type.setHaveFieldInits(ip, io); -} - -pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.LoadedUnionType) SemaError!void { - const pt = sema.pt; - const zcu = pt.zcu; - const io = zcu.comp.io; - const ip = &zcu.intern_pool; - - assert(sema.owner.unwrap().type == ty.toIntern()); - - switch (union_type.flagsUnordered(ip).status) { - .none => {}, - .field_types_wip => { - const msg = try sema.errMsg(ty.srcLoc(zcu), "union '{f}' depends on itself", .{ty.fmt(pt)}); - return sema.failWithOwnedErrorMsg(null, msg); - }, - .have_field_types, - .have_layout, - .layout_wip, - .fully_resolved_wip, - .fully_resolved, - => return, - } - - // can't happen earlier than this because we only want the progress node if not already resolved - const tracked_unit = zcu.trackUnitSema(union_type.name.toSlice(ip), null); - defer tracked_unit.end(zcu); - - union_type.setStatus(ip, io, .field_types_wip); - errdefer union_type.setStatus(ip, io, .none); - sema.unionFields(ty.toIntern(), union_type) catch |err| switch (err) { - error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e, - error.ComptimeBreak, error.ComptimeReturn => unreachable, - }; - union_type.setStatus(ip, io, .have_field_types); -} - /// Returns a normal error set corresponding to the fully populated inferred /// error set. fn resolveInferredErrorSet( @@ -34798,8 +33366,9 @@ fn resolveInferredErrorSet( const func_index = ip.iesFuncIndex(ies_index); const func = zcu.funcInfo(func_index); - try sema.declareDependency(.{ .interned = func_index }); // resolved IES + try sema.declareDependency(.{ .func_ies = func_index }); + // MLUGG TODO: this feels kinda bad now... instead check for outdated whenver we grab this? try zcu.maybeUnresolveIes(func_index); const resolved_ty = func.resolvedErrorSetUnordered(ip); if (resolved_ty != .none) return resolved_ty; @@ -34820,7 +33389,7 @@ fn resolveInferredErrorSet( if (ies_func_info.return_type == .generic_poison_type) { assert(ies_func_info.cc == .@"inline"); } else if (ip.errorUnionSet(ies_func_info.return_type) == ies_index) { - if (ies_func_info.is_generic) { + if (!Type.fromInterned(func.ty).fnHasRuntimeBits(zcu)) { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(src, "unable to resolve inferred error set of generic function", .{}); errdefer msg.destroy(sema.gpa); @@ -34935,1248 +33504,6 @@ fn resolveInferredErrorSetTy( } } -fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct { - /// fields_len - usize, - Zir.Inst.StructDecl.Small, - /// extra_index - usize, -} { - const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; - assert(extended.opcode == .struct_decl); - const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); - var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len; - - const captures_len = if (small.has_captures_len) blk: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - - const fields_len = if (small.has_fields_len) blk: { - const fields_len = zir.extra[extra_index]; - extra_index += 1; - break :blk fields_len; - } else 0; - - const decls_len = if (small.has_decls_len) decls_len: { - const decls_len = zir.extra[extra_index]; - extra_index += 1; - break :decls_len decls_len; - } else 0; - - extra_index += captures_len * 2; - - // The backing integer cannot be handled until `resolveStructLayout()`. - if (small.has_backing_int) { - const backing_int_body_len = zir.extra[extra_index]; - extra_index += 1; // backing_int_body_len - if (backing_int_body_len == 0) { - extra_index += 1; // backing_int_ref - } else { - extra_index += backing_int_body_len; // backing_int_body_inst - } - } - - // Skip over decls. - extra_index += decls_len; - - return .{ fields_len, small, extra_index }; -} - -fn structFields( - sema: *Sema, - struct_type: InternPool.LoadedStructType, -) CompileError!void { - const pt = sema.pt; - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const io = comp.io; - const ip = &zcu.intern_pool; - - const namespace_index = struct_type.namespace; - const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir.?; - const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail; - - const fields_len, _, var extra_index = structZirInfo(zir, zir_index); - - if (fields_len == 0) switch (struct_type.layout) { - .@"packed" => { - try sema.backingIntType(struct_type); - return; - }, - .auto, .@"extern" => { - struct_type.setLayoutResolved(ip, io, 0, .none); - return; - }, - }; - - var block_scope: Block = .{ - .parent = null, - .sema = sema, - .namespace = namespace_index, - .instructions = .{}, - .inlining = null, - .comptime_reason = .{ .reason = .{ - .src = .{ - .base_node_inst = struct_type.zir_index, - .offset = .nodeOffset(.zero), - }, - .r = .{ .simple = .type }, - } }, - .src_base_inst = struct_type.zir_index, - .type_name_ctx = struct_type.name, - }; - defer assert(block_scope.instructions.items.len == 0); - - const Field = struct { - type_body_len: u32 = 0, - align_body_len: u32 = 0, - init_body_len: u32 = 0, - type_ref: Zir.Inst.Ref = .none, - }; - const fields = try sema.arena.alloc(Field, fields_len); - - var any_inits = false; - var any_aligned = false; - - { - const bits_per_field = 4; - const fields_per_u32 = 32 / bits_per_field; - const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; - const flags_index = extra_index; - var bit_bag_index: usize = flags_index; - extra_index += bit_bags_count; - var cur_bit_bag: u32 = undefined; - var field_i: u32 = 0; - while (field_i < fields_len) : (field_i += 1) { - if (field_i % fields_per_u32 == 0) { - cur_bit_bag = zir.extra[bit_bag_index]; - bit_bag_index += 1; - } - const has_align = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - const has_init = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - const is_comptime = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - - if (is_comptime) struct_type.setFieldComptime(ip, field_i); - - const field_name_zir: [:0]const u8 = zir.nullTerminatedString(@enumFromInt(zir.extra[extra_index])); - extra_index += 1; // field_name - - fields[field_i] = .{}; - - if (has_type_body) { - fields[field_i].type_body_len = zir.extra[extra_index]; - } else { - fields[field_i].type_ref = @enumFromInt(zir.extra[extra_index]); - } - extra_index += 1; - - // This string needs to outlive the ZIR code. - const field_name = try ip.getOrPutString(gpa, io, pt.tid, field_name_zir, .no_embedded_nulls); - assert(struct_type.addFieldName(ip, field_name) == null); - - if (has_align) { - fields[field_i].align_body_len = zir.extra[extra_index]; - extra_index += 1; - any_aligned = true; - } - if (has_init) { - fields[field_i].init_body_len = zir.extra[extra_index]; - extra_index += 1; - any_inits = true; - } - } - } - - // Next we do only types and alignments, saving the inits for a second pass, - // so that init values may depend on type layout. - - for (fields, 0..) |zir_field, field_i| { - const ty_src: LazySrcLoc = .{ - .base_node_inst = struct_type.zir_index, - .offset = .{ .container_field_type = @intCast(field_i) }, - }; - const field_ty: Type = ty: { - if (zir_field.type_ref != .none) { - break :ty try sema.resolveType(&block_scope, ty_src, zir_field.type_ref); - } - assert(zir_field.type_body_len != 0); - const body = zir.bodySlice(extra_index, zir_field.type_body_len); - extra_index += body.len; - const ty_ref = try sema.resolveInlineBody(&block_scope, body, zir_index); - break :ty try sema.analyzeAsType(&block_scope, ty_src, ty_ref); - }; - - struct_type.field_types.get(ip)[field_i] = field_ty.toIntern(); - - if (field_ty.zigTypeTag(zcu) == .@"opaque") { - const msg = msg: { - const msg = try sema.errMsg(ty_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); - errdefer msg.destroy(sema.gpa); - - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); - } - if (field_ty.zigTypeTag(zcu) == .noreturn) { - const msg = msg: { - const msg = try sema.errMsg(ty_src, "struct fields cannot be 'noreturn'", .{}); - errdefer msg.destroy(sema.gpa); - - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); - } - switch (struct_type.layout) { - .@"extern" => if (!try sema.validateExternType(field_ty, .struct_field)) { - const msg = msg: { - const msg = try sema.errMsg(ty_src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); - errdefer msg.destroy(sema.gpa); - - try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .struct_field); - - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); - }, - .@"packed" => if (!try sema.validatePackedType(field_ty)) { - const msg = msg: { - const msg = try sema.errMsg(ty_src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); - errdefer msg.destroy(sema.gpa); - - try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty); - - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); - }, - else => {}, - } - - if (zir_field.align_body_len > 0) { - const body = zir.bodySlice(extra_index, zir_field.align_body_len); - extra_index += body.len; - const align_ref = try sema.resolveInlineBody(&block_scope, body, zir_index); - const align_src: LazySrcLoc = .{ - .base_node_inst = struct_type.zir_index, - .offset = .{ .container_field_align = @intCast(field_i) }, - }; - const field_align = try sema.analyzeAsAlign(&block_scope, align_src, align_ref); - struct_type.field_aligns.get(ip)[field_i] = field_align; - } - - extra_index += zir_field.init_body_len; - } - - struct_type.clearFieldTypesWip(ip, io); - if (!any_inits) struct_type.setHaveFieldInits(ip, io); - - try sema.flushExports(); -} - -// This logic must be kept in sync with `structFields` -fn structFieldInits( - sema: *Sema, - struct_type: InternPool.LoadedStructType, -) CompileError!void { - const pt = sema.pt; - const zcu = pt.zcu; - const ip = &zcu.intern_pool; - - assert(!struct_type.haveFieldInits(ip)); - - const namespace_index = struct_type.namespace; - const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir.?; - const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail; - const fields_len, _, var extra_index = structZirInfo(zir, zir_index); - - var block_scope: Block = .{ - .parent = null, - .sema = sema, - .namespace = namespace_index, - .instructions = .{}, - .inlining = null, - .comptime_reason = undefined, // set when `block_scope` is used - .src_base_inst = struct_type.zir_index, - .type_name_ctx = struct_type.name, - }; - defer assert(block_scope.instructions.items.len == 0); - - const Field = struct { - type_body_len: u32 = 0, - align_body_len: u32 = 0, - init_body_len: u32 = 0, - }; - const fields = try sema.arena.alloc(Field, fields_len); - - var any_inits = false; - - { - const bits_per_field = 4; - const fields_per_u32 = 32 / bits_per_field; - const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; - const flags_index = extra_index; - var bit_bag_index: usize = flags_index; - extra_index += bit_bags_count; - var cur_bit_bag: u32 = undefined; - var field_i: u32 = 0; - while (field_i < fields_len) : (field_i += 1) { - if (field_i % fields_per_u32 == 0) { - cur_bit_bag = zir.extra[bit_bag_index]; - bit_bag_index += 1; - } - const has_align = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - const has_init = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 2; - const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - - extra_index += 1; // field_name - - fields[field_i] = .{}; - - if (has_type_body) fields[field_i].type_body_len = zir.extra[extra_index]; - extra_index += 1; - - if (has_align) { - fields[field_i].align_body_len = zir.extra[extra_index]; - extra_index += 1; - } - if (has_init) { - fields[field_i].init_body_len = zir.extra[extra_index]; - extra_index += 1; - any_inits = true; - } - } - } - - if (any_inits) { - for (fields, 0..) |zir_field, field_i| { - extra_index += zir_field.type_body_len; - extra_index += zir_field.align_body_len; - const body = zir.bodySlice(extra_index, zir_field.init_body_len); - extra_index += zir_field.init_body_len; - - if (body.len == 0) continue; - - // Pre-populate the type mapping the body expects to be there. - // In init bodies, the zir index of the struct itself is used - // to refer to the current field type. - - const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_i]); - const type_ref = Air.internedToRef(field_ty.toIntern()); - try sema.inst_map.ensureSpaceForInstructions(sema.gpa, &.{zir_index}); - sema.inst_map.putAssumeCapacity(zir_index, type_ref); - - const init_src: LazySrcLoc = .{ - .base_node_inst = struct_type.zir_index, - .offset = .{ .container_field_value = @intCast(field_i) }, - }; - - block_scope.comptime_reason = .{ .reason = .{ - .src = init_src, - .r = .{ .simple = .struct_field_default_value }, - } }; - const init = try sema.resolveInlineBody(&block_scope, body, zir_index); - const coerced = try sema.coerce(&block_scope, field_ty, init, init_src); - const default_val = try sema.resolveConstValue(&block_scope, init_src, coerced, null); - - if (default_val.canMutateComptimeVarState(zcu)) { - return sema.failWithContainsReferenceToComptimeVar( - &block_scope, - init_src, - struct_type.fieldName(ip, field_i), - "field default value", - default_val, - ); - } - struct_type.field_inits.get(ip)[field_i] = default_val.toIntern(); - } - } - - try sema.flushExports(); -} - -fn unionFields( - sema: *Sema, - union_ty: InternPool.Index, - union_type: InternPool.LoadedUnionType, -) CompileError!void { - const tracy = trace(@src()); - defer tracy.end(); - - const pt = sema.pt; - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const io = comp.io; - const ip = &zcu.intern_pool; - - const zir = zcu.namespacePtr(union_type.namespace).fileScope(zcu).zir.?; - const zir_index = union_type.zir_index.resolve(ip) orelse return error.AnalysisFail; - const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended; - assert(extended.opcode == .union_decl); - const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); - const extra = zir.extraData(Zir.Inst.UnionDecl, extended.operand); - var extra_index: usize = extra.end; - - const tag_type_ref: Zir.Inst.Ref = if (small.has_tag_type) blk: { - const ty_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]); - extra_index += 1; - break :blk ty_ref; - } else .none; - - const captures_len = if (small.has_captures_len) blk: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - - const body_len = if (small.has_body_len) blk: { - const body_len = zir.extra[extra_index]; - extra_index += 1; - break :blk body_len; - } else 0; - - const fields_len = if (small.has_fields_len) blk: { - const fields_len = zir.extra[extra_index]; - extra_index += 1; - break :blk fields_len; - } else 0; - - const decls_len = if (small.has_decls_len) decls_len: { - const decls_len = zir.extra[extra_index]; - extra_index += 1; - break :decls_len decls_len; - } else 0; - - // Skip over captures and decls. - extra_index += captures_len * 2 + decls_len; - - const body = zir.bodySlice(extra_index, body_len); - extra_index += body.len; - - const src: LazySrcLoc = .{ - .base_node_inst = union_type.zir_index, - .offset = .nodeOffset(.zero), - }; - - var block_scope: Block = .{ - .parent = null, - .sema = sema, - .namespace = union_type.namespace, - .instructions = .{}, - .inlining = null, - .comptime_reason = .{ .reason = .{ - .src = src, - .r = .{ .simple = .type }, - } }, - .src_base_inst = union_type.zir_index, - .type_name_ctx = union_type.name, - }; - defer assert(block_scope.instructions.items.len == 0); - - if (body.len != 0) { - _ = try sema.analyzeInlineBody(&block_scope, body, zir_index); - } - - var int_tag_ty: Type = undefined; - var enum_field_names: []InternPool.NullTerminatedString = &.{}; - var enum_field_vals: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .empty; - var explicit_tags_seen: []bool = &.{}; - if (tag_type_ref != .none) { - const tag_ty_src: LazySrcLoc = .{ - .base_node_inst = union_type.zir_index, - .offset = .{ .node_offset_container_tag = .zero }, - }; - const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref); - if (small.auto_enum_tag) { - // The provided type is an integer type and we must construct the enum tag type here. - int_tag_ty = provided_ty; - if (int_tag_ty.zigTypeTag(zcu) != .int and int_tag_ty.zigTypeTag(zcu) != .comptime_int) { - return sema.fail(&block_scope, tag_ty_src, "expected integer tag type, found '{f}'", .{int_tag_ty.fmt(pt)}); - } - - if (fields_len > 0) { - const field_count_val = try pt.intValue(.comptime_int, fields_len - 1); - if (!(try sema.intFitsInType(field_count_val, int_tag_ty, null))) { - const msg = msg: { - const msg = try sema.errMsg(tag_ty_src, "specified integer tag type cannot represent every field", .{}); - errdefer msg.destroy(sema.gpa); - try sema.errNote(tag_ty_src, msg, "type '{f}' cannot fit values in range 0...{d}", .{ - int_tag_ty.fmt(pt), - fields_len - 1, - }); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); - } - enum_field_names = try sema.arena.alloc(InternPool.NullTerminatedString, fields_len); - try enum_field_vals.ensureTotalCapacity(sema.arena, fields_len); - } - } else { - // The provided type is the enum tag type. - const enum_type = switch (ip.indexToKey(provided_ty.toIntern())) { - .enum_type => ip.loadEnumType(provided_ty.toIntern()), - else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{f}'", .{provided_ty.fmt(pt)}), - }; - union_type.setTagType(ip, io, provided_ty.toIntern()); - // The fields of the union must match the enum exactly. - // A flag per field is used to check for missing and extraneous fields. - explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len); - @memset(explicit_tags_seen, false); - } - } else { - // If auto_enum_tag is false, this is an untagged union. However, for semantic analysis - // purposes, we still auto-generate an enum tag type the same way. That the union is - // untagged is represented by the Type tag (union vs union_tagged). - enum_field_names = try sema.arena.alloc(InternPool.NullTerminatedString, fields_len); - } - - var field_types: std.ArrayList(InternPool.Index) = .empty; - var field_aligns: std.ArrayList(InternPool.Alignment) = .empty; - - try field_types.ensureTotalCapacityPrecise(sema.arena, fields_len); - if (small.any_aligned_fields) - try field_aligns.ensureTotalCapacityPrecise(sema.arena, fields_len); - - var max_bits: u64 = 0; - var min_bits: u64 = std.math.maxInt(u64); - var max_bits_src: LazySrcLoc = undefined; - var min_bits_src: LazySrcLoc = undefined; - var max_bits_ty: Type = undefined; - var min_bits_ty: Type = undefined; - const bits_per_field = 4; - const fields_per_u32 = 32 / bits_per_field; - const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; - var bit_bag_index: usize = extra_index; - extra_index += bit_bags_count; - var cur_bit_bag: u32 = undefined; - var field_i: u32 = 0; - var last_tag_val: ?Value = null; - const layout = union_type.flagsUnordered(ip).layout; - while (field_i < fields_len) : (field_i += 1) { - if (field_i % fields_per_u32 == 0) { - cur_bit_bag = zir.extra[bit_bag_index]; - bit_bag_index += 1; - } - const has_type = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - const has_align = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - const has_tag = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - const unused = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - _ = unused; - - const field_name_index: Zir.NullTerminatedString = @enumFromInt(zir.extra[extra_index]); - const field_name_zir = zir.nullTerminatedString(field_name_index); - extra_index += 1; - - const field_type_ref: Zir.Inst.Ref = if (has_type) blk: { - const field_type_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]); - extra_index += 1; - break :blk field_type_ref; - } else .none; - - const align_ref: Zir.Inst.Ref = if (has_align) blk: { - const align_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]); - extra_index += 1; - break :blk align_ref; - } else .none; - - const tag_ref: Air.Inst.Ref = if (has_tag) blk: { - const tag_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]); - extra_index += 1; - break :blk try sema.resolveInst(tag_ref); - } else .none; - - const name_src: LazySrcLoc = .{ - .base_node_inst = union_type.zir_index, - .offset = .{ .container_field_name = field_i }, - }; - const value_src: LazySrcLoc = .{ - .base_node_inst = union_type.zir_index, - .offset = .{ .container_field_value = field_i }, - }; - const align_src: LazySrcLoc = .{ - .base_node_inst = union_type.zir_index, - .offset = .{ .container_field_align = field_i }, - }; - const type_src: LazySrcLoc = .{ - .base_node_inst = union_type.zir_index, - .offset = .{ .container_field_type = field_i }, - }; - - if (enum_field_vals.capacity() > 0) { - const enum_tag_val = if (tag_ref != .none) blk: { - const coerced = try sema.coerce(&block_scope, int_tag_ty, tag_ref, value_src); - const val = try sema.resolveConstDefinedValue(&block_scope, value_src, coerced, .{ .simple = .enum_field_tag_value }); - last_tag_val = val; - - break :blk val; - } else blk: { - if (last_tag_val) |last_tag| { - const result = try arith.incrementDefinedInt(sema, int_tag_ty, last_tag); - if (result.overflow) return sema.fail( - &block_scope, - value_src, - "enumeration value '{f}' too large for type '{f}'", - .{ result.val.fmtValueSema(pt, sema), int_tag_ty.fmt(pt) }, - ); - last_tag_val = result.val; - } else { - last_tag_val = try pt.intValue(int_tag_ty, 0); - } - break :blk last_tag_val.?; - }; - const gop = enum_field_vals.getOrPutAssumeCapacity(enum_tag_val.toIntern()); - if (gop.found_existing) { - const other_value_src: LazySrcLoc = .{ - .base_node_inst = union_type.zir_index, - .offset = .{ .container_field_value = @intCast(gop.index) }, - }; - const msg = msg: { - const msg = try sema.errMsg( - value_src, - "enum tag value {f} already taken", - .{enum_tag_val.fmtValueSema(pt, sema)}, - ); - errdefer msg.destroy(gpa); - try sema.errNote(other_value_src, msg, "other occurrence here", .{}); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); - } - } - - // This string needs to outlive the ZIR code. - const field_name = try ip.getOrPutString(gpa, io, pt.tid, field_name_zir, .no_embedded_nulls); - if (enum_field_names.len != 0) { - enum_field_names[field_i] = field_name; - } - - const field_ty: Type = if (!has_type) - .void - else if (field_type_ref == .none) - .noreturn - else - try sema.resolveType(&block_scope, type_src, field_type_ref); - - if (explicit_tags_seen.len > 0) { - const tag_ty = union_type.tagTypeUnordered(ip); - const tag_info = ip.loadEnumType(tag_ty); - const enum_index = tag_info.nameIndex(ip, field_name) orelse { - return sema.fail(&block_scope, name_src, "no field named '{f}' in enum '{f}'", .{ - field_name.fmt(ip), Type.fromInterned(tag_ty).fmt(pt), - }); - }; - - // No check for duplicate because the check already happened in order - // to create the enum type in the first place. - assert(!explicit_tags_seen[enum_index]); - explicit_tags_seen[enum_index] = true; - - // Enforce the enum fields and the union fields being in the same order. - if (enum_index != field_i) { - const msg = msg: { - const enum_field_src: LazySrcLoc = .{ - .base_node_inst = Type.fromInterned(tag_ty).typeDeclInstAllowGeneratedTag(zcu).?, - .offset = .{ .container_field_name = enum_index }, - }; - const msg = try sema.errMsg(name_src, "union field '{f}' ordered differently than corresponding enum field", .{ - field_name.fmt(ip), - }); - errdefer msg.destroy(sema.gpa); - try sema.errNote(enum_field_src, msg, "enum field here", .{}); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); - } - } - - if (field_ty.zigTypeTag(zcu) == .@"opaque") { - const msg = msg: { - const msg = try sema.errMsg(type_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); - errdefer msg.destroy(sema.gpa); - - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); - } - switch (layout) { - .@"extern" => if (!try sema.validateExternType(field_ty, .union_field)) { - const msg = msg: { - const msg = try sema.errMsg(type_src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); - errdefer msg.destroy(sema.gpa); - - try sema.explainWhyTypeIsNotExtern(msg, type_src, field_ty, .union_field); - - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); - }, - .@"packed" => { - if (!try sema.validatePackedType(field_ty)) { - const msg = msg: { - const msg = try sema.errMsg(type_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); - errdefer msg.destroy(sema.gpa); - - try sema.explainWhyTypeIsNotPacked(msg, type_src, field_ty); - - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); - } - const field_bits = try field_ty.bitSizeSema(pt); - if (field_bits >= max_bits) { - max_bits = field_bits; - max_bits_src = type_src; - max_bits_ty = field_ty; - } - if (field_bits <= min_bits) { - min_bits = field_bits; - min_bits_src = type_src; - min_bits_ty = field_ty; - } - }, - .auto => {}, - } - - field_types.appendAssumeCapacity(field_ty.toIntern()); - - if (small.any_aligned_fields) { - field_aligns.appendAssumeCapacity(if (align_ref != .none) - try sema.resolveAlign(&block_scope, align_src, align_ref) - else - .none); - } else { - assert(align_ref == .none); - } - } - - union_type.setFieldTypes(ip, field_types.items); - union_type.setFieldAligns(ip, field_aligns.items); - - if (layout == .@"packed" and fields_len != 0 and min_bits != max_bits) { - const msg = msg: { - const msg = try sema.errMsg(src, "packed union has fields with mismatching bit sizes", .{}); - errdefer msg.destroy(sema.gpa); - try sema.errNote(min_bits_src, msg, "{d} bits here", .{min_bits}); - try sema.addDeclaredHereNote(msg, min_bits_ty); - try sema.errNote(max_bits_src, msg, "{d} bits here", .{max_bits}); - try sema.addDeclaredHereNote(msg, max_bits_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); - } - - if (explicit_tags_seen.len > 0) { - const tag_ty = union_type.tagTypeUnordered(ip); - const tag_info = ip.loadEnumType(tag_ty); - if (tag_info.names.len > fields_len) { - const msg = msg: { - const msg = try sema.errMsg(src, "enum field(s) missing in union", .{}); - errdefer msg.destroy(sema.gpa); - - for (tag_info.names.get(ip), 0..) |field_name, field_index| { - if (explicit_tags_seen[field_index]) continue; - try sema.addFieldErrNote(.fromInterned(tag_ty), field_index, msg, "field '{f}' missing, declared here", .{ - field_name.fmt(ip), - }); - } - try sema.addDeclaredHereNote(msg, .fromInterned(tag_ty)); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(&block_scope, msg); - } - } else if (enum_field_vals.count() > 0) { - const enum_ty = try sema.generateUnionTagTypeNumbered(&block_scope, enum_field_names, enum_field_vals.keys(), union_ty, union_type.name); - union_type.setTagType(ip, io, enum_ty); - } else { - const enum_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, union_ty, union_type.name); - union_type.setTagType(ip, io, enum_ty); - } - - try sema.flushExports(); -} - -fn generateUnionTagTypeNumbered( - sema: *Sema, - block: *Block, - enum_field_names: []const InternPool.NullTerminatedString, - enum_field_vals: []const InternPool.Index, - union_type: InternPool.Index, - union_name: InternPool.NullTerminatedString, -) !InternPool.Index { - const pt = sema.pt; - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const io = comp.io; - const ip = &zcu.intern_pool; - - const name = try ip.getOrPutStringFmt( - gpa, - io, - pt.tid, - "@typeInfo({f}).@\"union\".tag_type.?", - .{union_name.fmt(ip)}, - .no_embedded_nulls, - ); - - const enum_ty = try ip.getGeneratedTagEnumType(gpa, io, pt.tid, .{ - .name = name, - .owner_union_ty = union_type, - .tag_ty = if (enum_field_vals.len == 0) - (try pt.intType(.unsigned, 0)).toIntern() - else - ip.typeOf(enum_field_vals[0]), - .names = enum_field_names, - .values = enum_field_vals, - .tag_mode = .explicit, - .parent_namespace = block.namespace, - }); - - return enum_ty; -} - -fn generateUnionTagTypeSimple( - sema: *Sema, - block: *Block, - enum_field_names: []const InternPool.NullTerminatedString, - union_type: InternPool.Index, - union_name: InternPool.NullTerminatedString, -) !InternPool.Index { - const pt = sema.pt; - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const io = comp.io; - const ip = &zcu.intern_pool; - - const name = try ip.getOrPutStringFmt( - gpa, - io, - pt.tid, - "@typeInfo({f}).@\"union\".tag_type.?", - .{union_name.fmt(ip)}, - .no_embedded_nulls, - ); - - const enum_ty = try ip.getGeneratedTagEnumType(gpa, io, pt.tid, .{ - .name = name, - .owner_union_ty = union_type, - .tag_ty = (try pt.smallestUnsignedInt(enum_field_names.len -| 1)).toIntern(), - .names = enum_field_names, - .values = &.{}, - .tag_mode = .auto, - .parent_namespace = block.namespace, - }); - - return enum_ty; -} - -/// There is another implementation of this in `Type.onePossibleValue`. This one -/// in `Sema` is for calling during semantic analysis, and performs field resolution -/// to get the answer. The one in `Type` is for calling during codegen and asserts -/// that the types are already resolved. -/// TODO assert the return value matches `ty.onePossibleValue` -pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { - const pt = sema.pt; - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const io = comp.io; - const ip = &zcu.intern_pool; - - return switch (ty.toIntern()) { - .u0_type, - .i0_type, - => try pt.intValue(ty, 0), - .u1_type, - .u8_type, - .i8_type, - .u16_type, - .i16_type, - .u29_type, - .u32_type, - .i32_type, - .u64_type, - .i64_type, - .u80_type, - .u128_type, - .i128_type, - .u256_type, - .usize_type, - .isize_type, - .c_char_type, - .c_short_type, - .c_ushort_type, - .c_int_type, - .c_uint_type, - .c_long_type, - .c_ulong_type, - .c_longlong_type, - .c_ulonglong_type, - .c_longdouble_type, - .f16_type, - .f32_type, - .f64_type, - .f80_type, - .f128_type, - .anyopaque_type, - .bool_type, - .type_type, - .anyerror_type, - .adhoc_inferred_error_set_type, - .comptime_int_type, - .comptime_float_type, - .enum_literal_type, - .ptr_usize_type, - .ptr_const_comptime_int_type, - .manyptr_u8_type, - .manyptr_const_u8_type, - .manyptr_const_u8_sentinel_0_type, - .manyptr_const_slice_const_u8_type, - .slice_const_u8_type, - .slice_const_u8_sentinel_0_type, - .slice_const_slice_const_u8_type, - .optional_type_type, - .manyptr_const_type_type, - .slice_const_type_type, - .vector_8_i8_type, - .vector_16_i8_type, - .vector_32_i8_type, - .vector_64_i8_type, - .vector_1_u8_type, - .vector_2_u8_type, - .vector_4_u8_type, - .vector_8_u8_type, - .vector_16_u8_type, - .vector_32_u8_type, - .vector_64_u8_type, - .vector_2_i16_type, - .vector_4_i16_type, - .vector_8_i16_type, - .vector_16_i16_type, - .vector_32_i16_type, - .vector_4_u16_type, - .vector_8_u16_type, - .vector_16_u16_type, - .vector_32_u16_type, - .vector_2_i32_type, - .vector_4_i32_type, - .vector_8_i32_type, - .vector_16_i32_type, - .vector_4_u32_type, - .vector_8_u32_type, - .vector_16_u32_type, - .vector_2_i64_type, - .vector_4_i64_type, - .vector_8_i64_type, - .vector_2_u64_type, - .vector_4_u64_type, - .vector_8_u64_type, - .vector_1_u128_type, - .vector_2_u128_type, - .vector_1_u256_type, - .vector_4_f16_type, - .vector_8_f16_type, - .vector_16_f16_type, - .vector_32_f16_type, - .vector_2_f32_type, - .vector_4_f32_type, - .vector_8_f32_type, - .vector_16_f32_type, - .vector_2_f64_type, - .vector_4_f64_type, - .vector_8_f64_type, - .anyerror_void_error_union_type, - => null, - .void_type => Value.void, - .noreturn_type => Value.@"unreachable", - .anyframe_type => unreachable, - .null_type => Value.null, - .undefined_type => Value.undef, - .optional_noreturn_type => try pt.nullValue(ty), - .generic_poison_type => unreachable, - .empty_tuple_type => Value.empty_tuple, - // values, not types - .undef, - .undef_bool, - .undef_usize, - .undef_u1, - .zero, - .zero_usize, - .zero_u1, - .zero_u8, - .one, - .one_usize, - .one_u1, - .one_u8, - .four_u8, - .negative_one, - .void_value, - .unreachable_value, - .null_value, - .bool_true, - .bool_false, - .empty_tuple, - // invalid - .none, - => unreachable, - - _ => switch (ty.toIntern().unwrap(ip).getTag(ip)) { - .removed => unreachable, - - .type_int_signed, // i0 handled above - .type_int_unsigned, // u0 handled above - .type_pointer, - .type_slice, - .type_anyframe, - .type_error_union, - .type_anyerror_union, - .type_error_set, - .type_inferred_error_set, - .type_opaque, - .type_function, - => null, - - .simple_type, // handled above - // values, not types - .undef, - .simple_value, - .ptr_nav, - .ptr_uav, - .ptr_uav_aligned, - .ptr_comptime_alloc, - .ptr_comptime_field, - .ptr_int, - .ptr_eu_payload, - .ptr_opt_payload, - .ptr_elem, - .ptr_field, - .ptr_slice, - .opt_payload, - .opt_null, - .int_u8, - .int_u16, - .int_u32, - .int_i32, - .int_usize, - .int_comptime_int_u32, - .int_comptime_int_i32, - .int_small, - .int_positive, - .int_negative, - .int_lazy_align, - .int_lazy_size, - .error_set_error, - .error_union_error, - .error_union_payload, - .enum_literal, - .enum_tag, - .float_f16, - .float_f32, - .float_f64, - .float_f80, - .float_f128, - .float_c_longdouble_f80, - .float_c_longdouble_f128, - .float_comptime_float, - .variable, - .threadlocal_variable, - .@"extern", - .func_decl, - .func_instance, - .func_coerced, - .only_possible_value, - .union_value, - .bytes, - .aggregate, - .repeated, - // memoized value, not types - .memoized_call, - => unreachable, - - .type_array_big, - .type_array_small, - .type_vector, - .type_enum_auto, - .type_enum_explicit, - .type_enum_nonexhaustive, - .type_struct, - .type_struct_packed, - .type_struct_packed_inits, - .type_tuple, - .type_union, - => switch (ip.indexToKey(ty.toIntern())) { - inline .array_type, .vector_type => |seq_type, seq_tag| { - const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none; - if (seq_type.len + @intFromBool(has_sentinel) == 0) return try pt.aggregateValue(ty, &.{}); - if (try sema.typeHasOnePossibleValue(.fromInterned(seq_type.child))) |opv| { - return try pt.aggregateSplatValue(ty, opv); - } - return null; - }, - - .struct_type => { - // Resolving the layout first helps to avoid loops. - // If the type has a coherent layout, we can recurse through fields safely. - try ty.resolveLayout(pt); - - const struct_type = ip.loadStructType(ty.toIntern()); - - if (struct_type.field_types.len == 0) { - // In this case the struct has no fields at all and - // therefore has one possible value. - return try pt.aggregateValue(ty, &.{}); - } - - const field_vals = try sema.arena.alloc( - InternPool.Index, - struct_type.field_types.len, - ); - for (field_vals, 0..) |*field_val, i| { - if (struct_type.fieldIsComptime(ip, i)) { - try ty.resolveStructFieldInits(pt); - field_val.* = struct_type.field_inits.get(ip)[i]; - continue; - } - const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); - if (try sema.typeHasOnePossibleValue(field_ty)) |field_opv| { - field_val.* = field_opv.toIntern(); - } else return null; - } - - // In this case the struct has no runtime-known fields and - // therefore has one possible value. - return try pt.aggregateValue(ty, field_vals); - }, - - .tuple_type => |tuple| { - try ty.resolveLayout(pt); - - if (tuple.types.len == 0) { - return try pt.aggregateValue(ty, &.{}); - } - - const field_vals = try sema.arena.alloc( - InternPool.Index, - tuple.types.len, - ); - for ( - field_vals, - tuple.types.get(ip), - tuple.values.get(ip), - ) |*field_val, field_ty, field_comptime_val| { - if (field_comptime_val != .none) { - field_val.* = field_comptime_val; - continue; - } - if (try sema.typeHasOnePossibleValue(.fromInterned(field_ty))) |opv| { - field_val.* = opv.toIntern(); - } else return null; - } - - return try pt.aggregateValue(ty, field_vals); - }, - - .union_type => { - // Resolving the layout first helps to avoid loops. - // If the type has a coherent layout, we can recurse through fields safely. - try ty.resolveLayout(pt); - - const union_obj = ip.loadUnionType(ty.toIntern()); - const tag_val = (try sema.typeHasOnePossibleValue(.fromInterned(union_obj.tagTypeUnordered(ip)))) orelse - return null; - if (union_obj.field_types.len == 0) { - const only = try pt.intern(.{ .empty_enum_value = ty.toIntern() }); - return Value.fromInterned(only); - } - const only_field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[0]); - const val_val = (try sema.typeHasOnePossibleValue(only_field_ty)) orelse - return null; - const only = try pt.internUnion(.{ - .ty = ty.toIntern(), - .tag = tag_val.toIntern(), - .val = val_val.toIntern(), - }); - return Value.fromInterned(only); - }, - - .enum_type => { - const enum_type = ip.loadEnumType(ty.toIntern()); - switch (enum_type.tag_mode) { - .nonexhaustive => { - if (enum_type.tag_ty == .comptime_int_type) return null; - - if (try sema.typeHasOnePossibleValue(.fromInterned(enum_type.tag_ty))) |int_opv| { - const only = try pt.intern(.{ .enum_tag = .{ - .ty = ty.toIntern(), - .int = int_opv.toIntern(), - } }); - return Value.fromInterned(only); - } - - return null; - }, - .auto, .explicit => { - if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(zcu)) return null; - - return Value.fromInterned(switch (enum_type.names.len) { - 0 => try pt.intern(.{ .empty_enum_value = ty.toIntern() }), - 1 => try pt.intern(.{ .enum_tag = .{ - .ty = ty.toIntern(), - .int = if (enum_type.values.len == 0) - (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern() - else - try ip.getCoercedInts( - gpa, - io, - pt.tid, - ip.indexToKey(enum_type.values.get(ip)[0]).int, - enum_type.tag_ty, - ), - } }), - else => return null, - }); - }, - } - }, - - else => unreachable, - }, - - .type_optional => { - const payload_ip = ip.indexToKey(ty.toIntern()).opt_type; - // Although ?noreturn is handled above, the element type - // can be effectively noreturn for example via an empty - // enum or error set. - if (ip.isNoReturn(payload_ip)) return try pt.nullValue(ty); - return null; - }, - }, - }; -} - /// Returns the type of the AIR instruction. fn typeOf(sema: *Sema, inst: Air.Inst.Ref) Type { return sema.getTmpAir().typeOf(inst, &sema.pt.zcu.intern_pool); @@ -36235,6 +33562,7 @@ fn isComptimeKnown( return (try sema.resolveValue(inst)) != null; } +/// Asserts that the layout of `var_type` has already been resolved. fn analyzeComptimeAlloc( sema: *Sema, block: *Block, @@ -36245,10 +33573,9 @@ fn analyzeComptimeAlloc( const pt = sema.pt; const zcu = pt.zcu; - // Needed to make an anon decl with type `var_type` (the `finish()` call below). - _ = try sema.typeHasOnePossibleValue(var_type); + var_type.assertHasLayout(zcu); - const ptr_type = try pt.ptrTypeSema(.{ + const ptr_type = try pt.ptrType(.{ .child = var_type.toIntern(), .flags = .{ .alignment = alignment, @@ -36256,13 +33583,23 @@ fn analyzeComptimeAlloc( }, }); - const alloc = try sema.newComptimeAlloc(block, src, var_type, alignment); - - return Air.internedToRef((try pt.intern(.{ .ptr = .{ - .ty = ptr_type.toIntern(), - .base_addr = .{ .comptime_alloc = alloc }, - .byte_offset = 0, - } }))); + if (try var_type.onePossibleValue(pt)) |opv| { + return .fromIntern(try pt.intern(.{ .ptr = .{ + .ty = ptr_type.toIntern(), + .base_addr = .{ .uav = .{ + .val = opv.toIntern(), + .orig_ty = ptr_type.toIntern(), + } }, + .byte_offset = 0, + } })); + } else { + const alloc = try sema.newComptimeAlloc(block, src, var_type, alignment); + return .fromIntern(try pt.intern(.{ .ptr = .{ + .ty = ptr_type.toIntern(), + .base_addr = .{ .comptime_alloc = alloc }, + .byte_offset = 0, + } })); + } } fn resolveAddressSpace( @@ -36363,40 +33700,6 @@ fn usizeCast(sema: *Sema, block: *Block, src: LazySrcLoc, int: u64) CompileError return std.math.cast(usize, int) orelse return sema.fail(block, src, "expression produces integer value '{d}' which is too big for this compiler implementation to handle", .{int}); } -/// For pointer-like optionals, it returns the pointer type. For pointers, -/// the type is returned unmodified. -/// This can return `error.AnalysisFail` because it sometimes requires resolving whether -/// a type has zero bits, which can cause a "foo depends on itself" compile error. -/// This logic must be kept in sync with `Type.isPtrLikeOptional`. -fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type { - const pt = sema.pt; - const zcu = pt.zcu; - return switch (zcu.intern_pool.indexToKey(ty.toIntern())) { - .ptr_type => |ptr_type| switch (ptr_type.flags.size) { - .one, .many, .c => ty, - .slice => null, - }, - .opt_type => |opt_child| switch (zcu.intern_pool.indexToKey(opt_child)) { - .ptr_type => |ptr_type| switch (ptr_type.flags.size) { - .slice, .c => null, - .many, .one => { - if (ptr_type.flags.is_allowzero) return null; - - // optionals of zero sized types behave like bools, not pointers - const payload_ty: Type = .fromInterned(opt_child); - if ((try sema.typeHasOnePossibleValue(payload_ty)) != null) { - return null; - } - - return payload_ty; - }, - }, - else => null, - }, - else => null, - }; -} - fn unionFieldIndex( sema: *Sema, block: *Block, @@ -36407,9 +33710,9 @@ fn unionFieldIndex( const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; - try union_ty.resolveFields(pt); const union_obj = zcu.typeToUnion(union_ty).?; - const field_index = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse + const enum_obj = ip.loadEnumType(union_obj.enum_tag_type); + const field_index = enum_obj.nameIndex(ip, field_name) orelse return sema.failWithBadUnionFieldAccess(block, union_ty, union_obj, field_src, field_name); return @intCast(field_index); } @@ -36424,7 +33727,6 @@ fn structFieldIndex( const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; - try struct_ty.resolveFields(pt); const struct_type = zcu.typeToStruct(struct_ty).?; return struct_type.nameIndex(ip, field_name) orelse return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_src, field_name); @@ -36513,6 +33815,7 @@ fn intFromFloatScalar( /// Vectors are also accepted. Vector results are reduced with AND. /// /// If provided, `vector_index` reports the first element that failed the range check. +/// MLUGG TODO: move to `Value` or `Type`? fn intFitsInType( sema: *Sema, val: Value, @@ -36535,30 +33838,10 @@ fn intFitsInType( .unsigned => info.bits >= ptr_bits, }; }, - .int => |int| switch (int.storage) { - .u64, .i64, .big_int => { - var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined; - const big_int = int.storage.toBigInt(&buffer); - return big_int.fitsInTwosComp(info.signedness, info.bits); - }, - .lazy_align => |lazy_ty| { - const max_needed_bits = @as(u16, 16) + @intFromBool(info.signedness == .signed); - // If it is u16 or bigger we know the alignment fits without resolving it. - if (info.bits >= max_needed_bits) return true; - const x = try Type.fromInterned(lazy_ty).abiAlignmentSema(pt); - if (x == .none) return true; - const actual_needed_bits = @as(usize, x.toLog2Units()) + 1 + @intFromBool(info.signedness == .signed); - return info.bits >= actual_needed_bits; - }, - .lazy_size => |lazy_ty| { - const max_needed_bits = @as(u16, 64) + @intFromBool(info.signedness == .signed); - // If it is u64 or bigger we know the size fits without resolving it. - if (info.bits >= max_needed_bits) return true; - const x = try Type.fromInterned(lazy_ty).abiSizeSema(pt); - if (x == 0) return true; - const actual_needed_bits = std.math.log2(x) + 1 + @intFromBool(info.signedness == .signed); - return info.bits >= actual_needed_bits; - }, + .int => |int| { + var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined; + const big_int = int.storage.toBigInt(&buffer); + return big_int.fitsInTwosComp(info.signedness, info.bits); }, .aggregate => |aggregate| { assert(ty.zigTypeTag(zcu) == .vector); @@ -36588,23 +33871,23 @@ fn intFitsInType( fn intInRange(sema: *Sema, tag_ty: Type, int_val: Value, end: usize) !bool { const pt = sema.pt; - if (!(try int_val.compareAllWithZeroSema(.gte, pt))) return false; + if (!int_val.compareAllWithZero(.gte, pt.zcu)) return false; const end_val = try pt.intValue(tag_ty, end); if (!(try sema.compareAll(int_val, .lt, end_val, tag_ty))) return false; return true; } -/// Asserts the type is an enum. +/// Asserts the type is an exhaustive enum. fn enumHasInt(sema: *Sema, ty: Type, int: Value) CompileError!bool { const pt = sema.pt; const zcu = pt.zcu; const enum_type = zcu.intern_pool.loadEnumType(ty.toIntern()); - assert(enum_type.tag_mode != .nonexhaustive); + assert(!enum_type.nonexhaustive); // The `tagValueIndex` function call below relies on the type being the integer tag type. // `getCoerced` assumes the value will fit the new type. - if (!(try sema.intFitsInType(int, .fromInterned(enum_type.tag_ty), null))) return false; - const int_coerced = try pt.getCoerced(int, .fromInterned(enum_type.tag_ty)); - + const int_tag_ty: Type = .fromInterned(enum_type.int_tag_type); + if (!try sema.intFitsInType(int, int_tag_ty, null)) return false; + const int_coerced = try pt.getCoerced(int, int_tag_ty); return enum_type.tagValueIndex(&zcu.intern_pool, int_coerced.toIntern()) != null; } @@ -36636,6 +33919,7 @@ fn compareAll( } /// Asserts the values are comparable. Both operands have type `ty`. +/// MLUGG TODO: move to `Value`? fn compareScalar( sema: *Sema, lhs: Value, @@ -36644,17 +33928,19 @@ fn compareScalar( ty: Type, ) CompileError!bool { const pt = sema.pt; + const zcu = pt.zcu; + const coerced_lhs = try pt.getCoerced(lhs, ty); const coerced_rhs = try pt.getCoerced(rhs, ty); // Equality comparisons of signed zero and NaN need to use floating point semantics - if (coerced_lhs.isFloat(pt.zcu) or coerced_rhs.isFloat(pt.zcu)) - return Value.compareHeteroSema(coerced_lhs, op, coerced_rhs, pt); + if (coerced_lhs.isFloat(zcu) or coerced_rhs.isFloat(zcu)) + return Value.compareHetero(coerced_lhs, op, coerced_rhs, zcu); switch (op) { - .eq => return sema.valuesEqual(coerced_lhs, coerced_rhs, ty), - .neq => return !(try sema.valuesEqual(coerced_lhs, coerced_rhs, ty)), - else => return Value.compareHeteroSema(coerced_lhs, op, coerced_rhs, pt), + .eq => return Value.eql(coerced_lhs, coerced_rhs, ty, zcu), + .neq => return !Value.eql(coerced_lhs, coerced_rhs, ty, zcu), + else => return Value.compareHetero(coerced_lhs, op, coerced_rhs, zcu), } } @@ -36799,7 +34085,7 @@ fn validateRuntimeValue(sema: *Sema, block: *Block, val_src: LazySrcLoc, val: Ai }); } -fn failWithContainsReferenceToComptimeVar(sema: *Sema, block: *Block, src: LazySrcLoc, value_name: InternPool.NullTerminatedString, kind_of_value: []const u8, val: ?Value) CompileError { +pub fn failWithContainsReferenceToComptimeVar(sema: *Sema, block: *Block, src: LazySrcLoc, value_name: InternPool.NullTerminatedString, kind_of_value: []const u8, val: ?Value) CompileError { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(src, "{s} contains reference to comptime var", .{kind_of_value}); errdefer msg.destroy(sema.gpa); @@ -36867,11 +34153,7 @@ fn notePathToComptimeAllocPtr( else => {}, // there will be another stage } - const derivation = comptime_ptr.pointerDerivationAdvanced(arena, pt, false, sema) catch |err| switch (err) { - error.OutOfMemory => |e| return e, - error.Canceled => @panic("TODO"), // pls don't be cancelable mlugg - error.AnalysisFail => unreachable, - }; + const derivation = try comptime_ptr.pointerDerivationAdvanced(arena, pt, false, sema); var second_path_aw: std.Io.Writer.Allocating = .init(arena); defer second_path_aw.deinit(); @@ -37058,12 +34340,12 @@ fn maybeDerefSliceAsArray( else => unreachable, }; const elem_ty = Type.fromInterned(slice.ty).childType(zcu); - const len = try Value.fromInterned(slice.len).toUnsignedIntSema(pt); + const len = Value.fromInterned(slice.len).toUnsignedInt(zcu); const array_ty = try pt.arrayType(.{ .child = elem_ty.toIntern(), .len = len, }); - const ptr_ty = try pt.ptrTypeSema(p: { + const ptr_ty = try pt.ptrType(p: { var p = Type.fromInterned(slice.ty).ptrInfo(zcu); p.flags.size = .one; p.child = array_ty.toIntern(); @@ -37129,238 +34411,6 @@ pub fn flushExports(sema: *Sema) !void { } } -/// Called as soon as a `declared` enum type is created. -/// Resolves the tag type and field inits. -/// Marks the `src_inst` dependency on the enum's declaration, so call sites need not do this. -pub fn resolveDeclaredEnum( - pt: Zcu.PerThread, - wip_ty: InternPool.WipEnumType, - inst: Zir.Inst.Index, - tracked_inst: InternPool.TrackedInst.Index, - namespace: InternPool.NamespaceIndex, - type_name: InternPool.NullTerminatedString, - small: Zir.Inst.EnumDecl.Small, - body: []const Zir.Inst.Index, - tag_type_ref: Zir.Inst.Ref, - any_values: bool, - fields_len: u32, - zir: Zir, - body_end: usize, -) Zcu.SemaError!void { - const zcu = pt.zcu; - const gpa = zcu.gpa; - - const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) }; - - var arena: std.heap.ArenaAllocator = .init(gpa); - defer arena.deinit(); - - var comptime_err_ret_trace: std.array_list.Managed(Zcu.LazySrcLoc) = .init(gpa); - defer comptime_err_ret_trace.deinit(); - - var sema: Sema = .{ - .pt = pt, - .gpa = gpa, - .arena = arena.allocator(), - .code = zir, - .owner = .wrap(.{ .type = wip_ty.index }), - .func_index = .none, - .func_is_naked = false, - .fn_ret_ty = .void, - .fn_ret_ty_ies = null, - .comptime_err_ret_trace = &comptime_err_ret_trace, - }; - defer sema.deinit(); - - if (zcu.comp.debugIncremental()) { - const info = try zcu.incremental_debug_state.getUnitInfo(gpa, sema.owner); - info.last_update_gen = zcu.generation; - } - - try sema.declareDependency(.{ .src_hash = tracked_inst }); - - var block: Block = .{ - .parent = null, - .sema = &sema, - .namespace = namespace, - .instructions = .{}, - .inlining = null, - .comptime_reason = .{ .reason = .{ - .src = src, - .r = .{ .simple = .enum_field_values }, - } }, - .src_base_inst = tracked_inst, - .type_name_ctx = type_name, - }; - defer block.instructions.deinit(gpa); - - sema.resolveDeclaredEnumInner( - &block, - wip_ty, - inst, - tracked_inst, - src, - small, - body, - tag_type_ref, - any_values, - fields_len, - zir, - body_end, - ) catch |err| switch (err) { - error.ComptimeBreak => unreachable, - error.ComptimeReturn => unreachable, - error.OutOfMemory, error.Canceled => |e| return e, - error.AnalysisFail => { - if (!zcu.failed_analysis.contains(sema.owner)) { - try zcu.transitive_failed_analysis.put(gpa, sema.owner, {}); - } - return error.AnalysisFail; - }, - }; -} - -fn resolveDeclaredEnumInner( - sema: *Sema, - block: *Block, - wip_ty: InternPool.WipEnumType, - inst: Zir.Inst.Index, - tracked_inst: InternPool.TrackedInst.Index, - src: LazySrcLoc, - small: Zir.Inst.EnumDecl.Small, - body: []const Zir.Inst.Index, - tag_type_ref: Zir.Inst.Ref, - any_values: bool, - fields_len: u32, - zir: Zir, - body_end: usize, -) Zcu.CompileError!void { - const pt = sema.pt; - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const io = comp.io; - const ip = &zcu.intern_pool; - - const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable; - - const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = .zero } }; - - const int_tag_ty = ty: { - if (body.len != 0) { - _ = try sema.analyzeInlineBody(block, body, inst); - } - - if (tag_type_ref != .none) { - const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref); - if (ty.zigTypeTag(zcu) != .int and ty.zigTypeTag(zcu) != .comptime_int) { - return sema.fail(block, tag_ty_src, "expected integer tag type, found '{f}'", .{ty.fmt(pt)}); - } - break :ty ty; - } else if (fields_len == 0) { - break :ty try pt.intType(.unsigned, 0); - } else { - const bits = std.math.log2_int_ceil(usize, fields_len); - break :ty try pt.intType(.unsigned, bits); - } - }; - - wip_ty.setTagTy(ip, int_tag_ty.toIntern()); - - var extra_index = body_end + bit_bags_count; - var bit_bag_index: usize = body_end; - var cur_bit_bag: u32 = undefined; - var last_tag_val: ?Value = null; - for (0..fields_len) |field_i_usize| { - const field_i: u32 = @intCast(field_i_usize); - if (field_i % 32 == 0) { - cur_bit_bag = zir.extra[bit_bag_index]; - bit_bag_index += 1; - } - const has_tag_value = @as(u1, @truncate(cur_bit_bag)) != 0; - cur_bit_bag >>= 1; - - const field_name_index: Zir.NullTerminatedString = @enumFromInt(zir.extra[extra_index]); - const field_name_zir = zir.nullTerminatedString(field_name_index); - extra_index += 1; // field name - - const field_name = try ip.getOrPutString(gpa, io, pt.tid, field_name_zir, .no_embedded_nulls); - - const value_src: LazySrcLoc = .{ - .base_node_inst = tracked_inst, - .offset = .{ .container_field_value = field_i }, - }; - - const tag_overflow = if (has_tag_value) overflow: { - const tag_val_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]); - extra_index += 1; - const tag_inst = try sema.resolveInst(tag_val_ref); - last_tag_val = try sema.resolveConstDefinedValue(block, .{ - .base_node_inst = tracked_inst, - .offset = .{ .container_field_name = field_i }, - }, tag_inst, .{ .simple = .enum_field_tag_value }); - if (!(try sema.intFitsInType(last_tag_val.?, int_tag_ty, null))) break :overflow true; - last_tag_val = try pt.getCoerced(last_tag_val.?, int_tag_ty); - if (wip_ty.nextField(ip, field_name, last_tag_val.?.toIntern())) |conflict| { - assert(conflict.kind == .value); // AstGen validated names are unique - const other_field_src: LazySrcLoc = .{ - .base_node_inst = tracked_inst, - .offset = .{ .container_field_value = conflict.prev_field_idx }, - }; - const msg = msg: { - const msg = try sema.errMsg(value_src, "enum tag value {f} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)}); - errdefer msg.destroy(gpa); - try sema.errNote(other_field_src, msg, "other occurrence here", .{}); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); - } - break :overflow false; - } else if (any_values) overflow: { - if (last_tag_val) |last_tag| { - const result = try arith.incrementDefinedInt(sema, int_tag_ty, last_tag); - last_tag_val = result.val; - if (result.overflow) break :overflow true; - } else { - last_tag_val = try pt.intValue(int_tag_ty, 0); - } - if (wip_ty.nextField(ip, field_name, last_tag_val.?.toIntern())) |conflict| { - assert(conflict.kind == .value); // AstGen validated names are unique - const other_field_src: LazySrcLoc = .{ - .base_node_inst = tracked_inst, - .offset = .{ .container_field_value = conflict.prev_field_idx }, - }; - const msg = msg: { - const msg = try sema.errMsg(value_src, "enum tag value {f} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)}); - errdefer msg.destroy(gpa); - try sema.errNote(other_field_src, msg, "other occurrence here", .{}); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); - } - break :overflow false; - } else overflow: { - assert(wip_ty.nextField(ip, field_name, .none) == null); - last_tag_val = try pt.intValue(.comptime_int, field_i); - if (!try sema.intFitsInType(last_tag_val.?, int_tag_ty, null)) break :overflow true; - last_tag_val = try pt.getCoerced(last_tag_val.?, int_tag_ty); - break :overflow false; - }; - - if (tag_overflow) { - const msg = try sema.errMsg(value_src, "enumeration value '{f}' too large for type '{f}'", .{ - last_tag_val.?.fmtValueSema(pt, sema), int_tag_ty.fmt(pt), - }); - return sema.failWithOwnedErrorMsg(block, msg); - } - } - if (small.nonexhaustive and int_tag_ty.toIntern() != .comptime_int_type) { - if (fields_len >= 1 and std.math.log2_int(u64, fields_len) == int_tag_ty.bitSize(zcu)) { - return sema.fail(block, src, "non-exhaustive enum specifies every value", .{}); - } - } -} - pub const bitCastVal = @import("Sema/bitcast.zig").bitCast; pub const bitCastSpliceVal = @import("Sema/bitcast.zig").bitCastSplice; @@ -37369,6 +34419,11 @@ const ComptimeLoadResult = @import("Sema/comptime_ptr_access.zig").ComptimeLoadR const storeComptimePtr = @import("Sema/comptime_ptr_access.zig").storeComptimePtr; const ComptimeStoreResult = @import("Sema/comptime_ptr_access.zig").ComptimeStoreResult; +// MLUGG TODO: decide how to do the namespacing here +pub const type_resolution = @import("Sema/type_resolution.zig"); +pub const ensureLayoutResolved = type_resolution.ensureLayoutResolved; +pub const ensureFieldInitsResolved = type_resolution.ensureFieldInitsResolved; + pub fn getBuiltinType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) SemaError!Type { assert(decl.kind() == .type); try sema.ensureMemoizedStateResolved(src, decl.stage()); @@ -37483,11 +34538,11 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, const result = try sema.analyzeNavVal(block, src, nav); const uncoerced_val = try sema.resolveConstDefinedValue(block, src, result, null); - const maybe_lazy_val: Value = switch (builtin_decl.kind()) { + const val: Value = switch (builtin_decl.kind()) { .type => if (uncoerced_val.typeOf(zcu).zigTypeTag(zcu) != .type) { return sema.fail(block, src, "{s}.{s} is not a type", .{ parent_name, name }); } else val: { - try uncoerced_val.toType().resolveFully(pt); + try sema.ensureLayoutResolved(uncoerced_val.toType()); break :val uncoerced_val; }, .func => val: { @@ -37500,7 +34555,6 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, break :val .fromInterned(coerced.toInterned().?); }, }; - const val = try sema.resolveLazyValue(maybe_lazy_val); const prev = zcu.builtin_decl_values.get(builtin_decl); if (val.toIntern() != prev) { @@ -37539,7 +34593,6 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.BuiltinDecl) CompileError!Typ => try pt.funcType(.{ .param_types = &.{ .generic_poison_type, .generic_poison_type }, .return_type = .noreturn_type, - .is_generic = true, }), // `fn (anyerror) noreturn` @@ -37590,3 +34643,823 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.BuiltinDecl) CompileError!Typ else => unreachable, }; } + +/// TODO MLUGG: this is a gnarly hack +const PartialTypeName = union(enum) { + exact: struct { + name: InternPool.NullTerminatedString, + nav: InternPool.Nav.Index.Optional, + }, + anon_prefix: []const u8, + fn apply( + name: PartialTypeName, + wip: *const InternPool.WipContainerType, + pt: Zcu.PerThread, + ) (Allocator.Error || std.Io.Cancelable)!InternPool.NullTerminatedString { + const zcu = pt.zcu; + const comp = zcu.comp; + const ip = &zcu.intern_pool; + switch (name) { + .exact => |e| { + wip.setName(ip, e.name, e.nav); + return e.name; + }, + .anon_prefix => |prefix| { + const resolved_name = try ip.getOrPutStringFmt( + comp.gpa, + comp.io, + pt.tid, + "{s}_{d}", + .{ prefix, @intFromEnum(wip.index) }, + .no_embedded_nulls, + ); + wip.setName(ip, resolved_name, .none); + return resolved_name; + }, + } + } +}; +pub fn createTypeName( + sema: *Sema, + block: *Block, + name_strategy: Zir.Inst.NameStrategy, + anon_prefix: []const u8, + inst: Zir.Inst.Index, +) CompileError!PartialTypeName { + const pt = sema.pt; + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &zcu.intern_pool; + + switch (name_strategy) { + .anon => {}, // handled after switch + .parent => return .{ .exact = .{ + .name = block.type_name_ctx, + .nav = sema.owner.unwrap().nav_val.toOptional(), + } }, + .func => func_strat: { + const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse return error.AnalysisFail); + const zir_tags = sema.code.instructions.items(.tag); + + var aw: std.Io.Writer.Allocating = .init(gpa); + defer aw.deinit(); + const w = &aw.writer; + w.print("{f}(", .{block.type_name_ctx.fmt(ip)}) catch return error.OutOfMemory; + + var arg_i: usize = 0; + for (fn_info.param_body) |zir_inst| switch (zir_tags[@intFromEnum(zir_inst)]) { + .param, .param_comptime, .param_anytype, .param_anytype_comptime => { + const arg = sema.inst_map.get(zir_inst).?; + // If this is being called in a generic function then analyzeCall will + // have already resolved the args and this will work. + // If not then this is a struct type being returned from a non-generic + // function and the name doesn't matter since it will later + // result in a compile error. + const arg_val = try sema.resolveValue(arg) orelse break :func_strat; // fall through to anon strat + + if (arg_i != 0) w.writeByte(',') catch return error.OutOfMemory; + + // Limiting the depth here helps avoid type names getting too long, which + // in turn helps to avoid unreasonably long symbol names for namespaced + // symbols. Such names should ideally be human-readable, and additionally, + // some tooling may not support very long symbol names. + w.print("{f}", .{Value.fmtValueSemaFull(.{ + .val = arg_val, + .pt = pt, + .opt_sema = sema, + .depth = 1, + })}) catch return error.OutOfMemory; + + arg_i += 1; + continue; + }, + else => continue, + }; + + w.writeByte(')') catch return error.OutOfMemory; + return .{ .exact = .{ + .name = try ip.getOrPutString(gpa, io, pt.tid, aw.written(), .no_embedded_nulls), + .nav = .none, + } }; + }, + .dbg_var => { + // TODO: this logic is questionable. We ideally should be traversing the `Block` rather than relying on the order of AstGen instructions. + const ref = inst.toRef(); + const zir_tags = sema.code.instructions.items(.tag); + const zir_data = sema.code.instructions.items(.data); + for (@intFromEnum(inst)..zir_tags.len) |i| switch (zir_tags[i]) { + .dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) { + return .{ .exact = .{ + .name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}.{s}", .{ + block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code), + }, .no_embedded_nulls), + .nav = .none, + } }; + }, + else => {}, + }; + // fall through to anon strat + }, + } + + // anon strat handling + + // It would be neat to have "struct:line:column" but this name has + // to survive incremental updates, where it may have been shifted down + // or up to a different line, but unchanged, and thus not unnecessarily + // semantically analyzed. + // TODO: that would be possible, by detecting line number changes and renaming + // types appropriately. However, `@typeName` becomes a problem then. If we remove + // that builtin from the language, we can consider this. + + return .{ .anon_prefix = try std.fmt.allocPrint( + sema.arena, + "{f}__{s}", + .{ block.type_name_ctx.fmt(ip), anon_prefix }, + ) }; +} + +pub fn analyzeStructDecl( + pt: Zcu.PerThread, + file_index: Zcu.File.Index, + zir: *const Zir, + parent_namespace: InternPool.OptionalNamespaceIndex, + tracked_inst: InternPool.TrackedInst.Index, + struct_decl: *const Zir.UnwrappedStructDecl, + explicit_backing_type: ?Type, + captures: []const InternPool.CaptureValue, + type_name: PartialTypeName, +) (Allocator.Error || std.Io.Cancelable)!Type { + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &zcu.intern_pool; + + const wip = switch (try ip.getStructType(gpa, io, pt.tid, .{ + .fields_len = @intCast(struct_decl.field_names.len), + .layout = struct_decl.layout, + .explicit_packed_backing_type = if (explicit_backing_type) |ty| ty.toIntern() else .none, + .any_comptime_fields = struct_decl.field_comptime_bits != null, + .any_field_defaults = struct_decl.field_default_body_lens != null, + .any_field_aligns = struct_decl.field_align_body_lens != null, + .key = .{ .declared = .{ + .zir_index = tracked_inst, + .captures = captures, + } }, + })) { + .existing => |ty| return .fromInterned(ty), + .wip => |wip| wip, + }; + errdefer wip.cancel(ip, pt.tid); + + _ = try type_name.apply(&wip, pt); + + var field_it = struct_decl.iterateFields(); + while (field_it.next()) |field| { + const name_slice = zir.nullTerminatedString(field.name); + const name = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls); + assert(wip.nextField(ip, name, field.is_comptime) == null); // AstGen validated this for us + } + + const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ + .parent = parent_namespace, + .owner_type = wip.index, + .file_scope = file_index, + .generation = zcu.generation, + }); + errdefer pt.destroyNamespace(new_namespace_index); + + try pt.scanNamespace(new_namespace_index, struct_decl.decls); + + // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind + try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) }); + try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_inits = wip.index }) }); + + if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); + + try zcu.outdated.ensureUnusedCapacity(gpa, 2); + try zcu.outdated_ready.ensureUnusedCapacity(gpa, 2); + errdefer comptime unreachable; // because we don't remove the `outdated` entries + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_inits = wip.index }), 0); + zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); + zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_inits = wip.index }), {}); + + return .fromInterned(wip.finish(ip, new_namespace_index)); +} +const AnalyzeUnionDeclError = error{ + OutOfMemory, + Canceled, + /// `packed union(T)` syntax was used, but `T` was not an integer type. + ExplicitBackingNotInt, + /// `union(enum(T))` syntax was used, but `T` was not an integer type. + ExplicitTagNotInt, + /// `union(T)` syntax was used, but `T` was not an enum type. + ExplicitTagNotEnum, + /// `union(T)` syntax was used, but the fields of the union do not exactly + /// correspond to the fields of the enum `T`. + ExplicitTagFieldMismatch, +}; +fn analyzeUnionDecl( + pt: Zcu.PerThread, + file_index: Zcu.File.Index, + zir: *const Zir, + parent_namespace: InternPool.OptionalNamespaceIndex, + want_safe_types: bool, + tracked_inst: InternPool.TrackedInst.Index, + union_decl: *const Zir.UnwrappedUnionDecl, + arg_type: ?Type, + captures: []const InternPool.CaptureValue, + type_name: PartialTypeName, +) AnalyzeUnionDeclError!Type { + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &zcu.intern_pool; + + switch (union_decl.kind) { + .tagged_explicit => if (arg_type.?.zigTypeTag(zcu) != .@"enum") { + return error.ExplicitTagNotEnum; + }, + .tagged_enum_explicit => if (arg_type.?.zigTypeTag(zcu) != .int) { + return error.ExplicitTagNotInt; + }, + .packed_explicit => if (arg_type.?.zigTypeTag(zcu) != .int) { + return error.ExplicitBackingNotInt; + }, + .auto, + .tagged_enum, + .@"extern", + .@"packed", + => assert(arg_type == null), + } + + const wip = switch (try ip.getUnionType(gpa, io, pt.tid, .{ + .fields_len = @intCast(union_decl.field_names.len), + .layout = union_decl.kind.layout(), + .explicit_packed_backing_type = switch (union_decl.kind) { + .packed_explicit => arg_type.?.toIntern(), + else => .none, + }, + .runtime_tag = switch (union_decl.kind) { + .auto => if (want_safe_types) .safety else .none, + + .tagged_explicit, + .tagged_enum, + .tagged_enum_explicit, + => .tagged, + + .@"extern", + .@"packed", + .packed_explicit, + => .none, + }, + .have_explicit_enum_tag = union_decl.kind == .tagged_explicit, + .any_field_aligns = union_decl.field_align_body_lens != null, + .key = .{ .declared = .{ + .zir_index = tracked_inst, + .captures = captures, + .arg_ty = if (arg_type) |t| t.toIntern() else .none, + } }, + })) { + .existing => |ty| return .fromInterned(ty), + .wip => |wip| wip, + }; + errdefer wip.cancel(ip, pt.tid); + + const resolved_type_name = try type_name.apply(&wip, pt); + + const generated_tag_ty: InternPool.Index = if (union_decl.kind == .tagged_explicit) generated_tag_ty: { + const tag_type = arg_type.?; + const enum_field_names = ip.loadEnumType(tag_type.toIntern()).field_names; + // Check that the enum field names match the union field names + if (union_decl.field_names.len != enum_field_names.len) { + return error.ExplicitTagFieldMismatch; + } + for (union_decl.field_names, enum_field_names.get(ip)) |union_field_zir, enum_field_ip| { + const union_field_name = zir.nullTerminatedString(union_field_zir); + const enum_field_name = enum_field_ip.toSlice(ip); + if (!std.mem.eql(u8, union_field_name, enum_field_name)) { + return error.ExplicitTagFieldMismatch; + } + } + wip.setTagType(ip, tag_type.toIntern()); + break :generated_tag_ty .none; + } else generated_tag_ty: { + // Generate a tag type. Even if the union is untagged (`.none`), we still generate a + // hypothetical tag type. + const wip_tag_ty = switch (try ip.getEnumType(gpa, io, pt.tid, .{ + .fields_len = @intCast(union_decl.field_names.len), + .explicit_int_tag_type = switch (union_decl.kind) { + .tagged_enum_explicit => arg_type.?.toIntern(), + else => .none, + }, + .nonexhaustive = false, + .key = .{ .generated_union_tag = wip.index }, + })) { + .existing => unreachable, // enum type is keyed on this union type which we're only just creating + .wip => |wip_tag_ty| wip_tag_ty, + }; + errdefer wip_tag_ty.cancel(ip, pt.tid); + // Populate the generated tag type's name + const tag_type_name = try ip.getOrPutStringFmt( + gpa, + io, + pt.tid, + "@typeInfo({f}).@\"union\".tag_type.?", + .{resolved_type_name.fmt(ip)}, + .no_embedded_nulls, + ); + wip_tag_ty.setName(ip, tag_type_name, .none); + // Populate the generated tag type's field names + for (union_decl.field_names) |zir_name| { + const name_slice = zir.nullTerminatedString(zir_name); + const name = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls); + assert(wip_tag_ty.nextField(ip, name, false) == null); // AstGen validated this for us + } + // If not explicitly given, populate the generated tag type's *integer* tag type + switch (union_decl.kind) { + .tagged_enum_explicit => {}, // already set by `getEnumType` + else => { + // Infer the int tag type from the field count + const bits = Type.smallestUnsignedBits(union_decl.field_names.len -| 1); + const int_tag_type = try pt.intType(.unsigned, bits); + wip_tag_ty.setTagType(ip, int_tag_type.toIntern()); + }, + } + // Create a dummy namespace for the generated tag type + const new_namespace_index = try pt.createNamespace(.{ + .parent = parent_namespace, + .owner_type = wip_tag_ty.index, + .file_scope = file_index, + .generation = zcu.generation, + }); + errdefer pt.destroyNamespace(new_namespace_index); + wip.setTagType(ip, wip_tag_ty.index); + break :generated_tag_ty wip_tag_ty.finish(ip, new_namespace_index); + }; + // If we fail to create the union type, we must delete the generated enum tag type, since it + // would hold a reference to the deleted union. + errdefer if (generated_tag_ty != .none) ip.remove(pt.tid, generated_tag_ty); + + const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ + .parent = parent_namespace, + .owner_type = wip.index, + .file_scope = file_index, + .generation = zcu.generation, + }); + errdefer pt.destroyNamespace(new_namespace_index); + + try pt.scanNamespace(new_namespace_index, union_decl.decls); + + // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind + try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) }); + if (generated_tag_ty != .none) { + try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_inits = generated_tag_ty }) }); + } + + if (zcu.comp.debugIncremental()) { + try zcu.incremental_debug_state.newType(zcu, wip.index); + if (generated_tag_ty != .none) { + try zcu.incremental_debug_state.newType(zcu, generated_tag_ty); + } + } + + try zcu.outdated.ensureUnusedCapacity(gpa, 2); + try zcu.outdated_ready.ensureUnusedCapacity(gpa, 2); + errdefer comptime unreachable; // because we don't remove the `outdated` entry + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); + zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); + if (generated_tag_ty != .none) { + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_inits = generated_tag_ty }), 0); + zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_inits = generated_tag_ty }), {}); + } + + return .fromInterned(wip.finish(ip, new_namespace_index)); +} +const AnalyzeEnumDeclError = error{ + OutOfMemory, + Canceled, + /// `enum(T)` syntax was used, but `T` was not an integer type. + ExplicitTagNotInt, +}; +fn analyzeEnumDecl( + pt: Zcu.PerThread, + file_index: Zcu.File.Index, + zir: *const Zir, + parent_namespace: InternPool.OptionalNamespaceIndex, + tracked_inst: InternPool.TrackedInst.Index, + enum_decl: *const Zir.UnwrappedEnumDecl, + explicit_tag_type: ?Type, + captures: []const InternPool.CaptureValue, + type_name: PartialTypeName, +) AnalyzeEnumDeclError!Type { + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &zcu.intern_pool; + + if (explicit_tag_type) |ty| { + // MLUGG TODO: make a final call on whether comptime_int is a valid int tag type, and follow it everywhere. + // i think not in the name of simplicity, but my opinion might depend on whether it's broken in practice today + switch (ty.zigTypeTag(zcu)) { + .int, .comptime_int => {}, + else => return error.ExplicitTagNotInt, + } + } + + const wip = switch (try ip.getEnumType(gpa, io, pt.tid, .{ + .fields_len = @intCast(enum_decl.field_names.len), + .explicit_int_tag_type = if (explicit_tag_type) |ty| ty.toIntern() else .none, + .nonexhaustive = enum_decl.nonexhaustive, + .key = .{ .declared = .{ + .zir_index = tracked_inst, + .captures = captures, + } }, + })) { + .existing => |ty| return .fromInterned(ty), + .wip => |wip| wip, + }; + errdefer wip.cancel(ip, pt.tid); + + _ = try type_name.apply(&wip, pt); + + var field_it = enum_decl.iterateFields(); + while (field_it.next()) |field| { + const name_slice = zir.nullTerminatedString(field.name); + const name = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls); + assert(wip.nextField(ip, name, false) == null); // AstGen validated this for us + } + + if (explicit_tag_type == null) { + // Infer the int tag type from the field count + const bits = Type.smallestUnsignedBits(enum_decl.field_names.len -| 1); + const int_tag_ty = try pt.intType(.unsigned, bits); + wip.setTagType(ip, int_tag_ty.toIntern()); + } + + const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ + .parent = parent_namespace, + .owner_type = wip.index, + .file_scope = file_index, + .generation = zcu.generation, + }); + errdefer pt.destroyNamespace(new_namespace_index); + + try pt.scanNamespace(new_namespace_index, enum_decl.decls); + + // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind + try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_inits = wip.index }) }); + + if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); + + try zcu.outdated.ensureUnusedCapacity(gpa, 1); + try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); + errdefer comptime unreachable; // because we don't remove the `outdated` entry + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_inits = wip.index }), 0); + zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_inits = wip.index }), {}); + + return .fromInterned(wip.finish(ip, new_namespace_index)); +} +fn analyzeOpaqueDecl( + pt: Zcu.PerThread, + file_index: Zcu.File.Index, + parent_namespace: InternPool.OptionalNamespaceIndex, + tracked_inst: InternPool.TrackedInst.Index, + opaque_decl: *const Zir.UnwrappedOpaqueDecl, + captures: []const InternPool.CaptureValue, + type_name: PartialTypeName, +) (Allocator.Error || std.Io.Cancelable)!Type { + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &zcu.intern_pool; + + const wip = switch (try ip.getOpaqueType(gpa, io, pt.tid, .{ + .zir_index = tracked_inst, + .captures = captures, + })) { + .existing => |ty| return .fromInterned(ty), + .wip => |wip| wip, + }; + errdefer wip.cancel(ip, pt.tid); + + _ = try type_name.apply(&wip, pt); + + const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ + .parent = parent_namespace, + .owner_type = wip.index, + .file_scope = file_index, + .generation = zcu.generation, + }); + errdefer pt.destroyNamespace(new_namespace_index); + + try pt.scanNamespace(new_namespace_index, opaque_decl.decls); + + if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); + return .fromInterned(wip.finish(ip, new_namespace_index)); +} + +fn zirStructDecl( + sema: *Sema, + block: *Block, + inst: Zir.Inst.Index, +) CompileError!Air.Inst.Ref { + const pt = sema.pt; + const zcu = pt.zcu; + + const tracked_inst = try block.trackZir(inst); + + const src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .nodeOffset(.zero), + }; + const backing_ty_src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .{ .node_offset_container_tag = .zero }, + }; + + const struct_decl = sema.code.getStructDecl(inst); + + const captures = try sema.getCaptures(block, src, struct_decl.captures, struct_decl.capture_names); + + const backing_int_type: ?Type = ty: { + if (struct_decl.backing_int_type == .none) break :ty null; + break :ty try sema.resolveType(block, backing_ty_src, struct_decl.backing_int_type); + // MLUGG TODO validate it's an int! + }; + + const ty = try analyzeStructDecl( + pt, + block.getFileScopeIndex(zcu), + &sema.code, + block.namespace.toOptional(), + tracked_inst, + &struct_decl, + backing_int_type, + captures, + try sema.createTypeName(block, struct_decl.name_strategy, "struct", inst), + ); + + try sema.addTypeReferenceEntry(src, ty); + + // Make sure we update the namespace if the declaration is re-analyzed, to pick + // up on e.g. changed comptime decls. + // TODO MLUGG: me no likey, maybe model namespaces less badly idk + try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)); + + return .fromIntern(ty.toIntern()); +} +fn zirUnionDecl( + sema: *Sema, + block: *Block, + inst: Zir.Inst.Index, +) CompileError!Air.Inst.Ref { + const pt = sema.pt; + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &zcu.intern_pool; + + const tracked_inst = try block.trackZir(inst); + + const src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .nodeOffset(.zero), + }; + const arg_ty_src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .{ .node_offset_container_tag = .zero }, + }; + + const union_decl = sema.code.getUnionDecl(inst); + + const captures = try sema.getCaptures(block, src, union_decl.captures, union_decl.capture_names); + + const arg_type: ?Type = ty: { + if (union_decl.arg_type == .none) break :ty null; + break :ty try sema.resolveType(block, arg_ty_src, union_decl.arg_type); + }; + + const ty = analyzeUnionDecl( + pt, + block.getFileScopeIndex(zcu), + &sema.code, + block.namespace.toOptional(), + block.wantSafeTypes(), + tracked_inst, + &union_decl, + arg_type, + captures, + try sema.createTypeName(block, union_decl.name_strategy, "union", inst), + ) catch |err| switch (err) { + error.OutOfMemory, + error.Canceled, + => |e| return e, + + error.ExplicitBackingNotInt => return sema.fail( + block, + arg_ty_src, + "expected integer backing type, found '{f}'", + .{arg_type.?.fmt(pt)}, + ), + error.ExplicitTagNotInt => return sema.fail( + block, + arg_ty_src, + "expected integer tag type, found '{f}'", + .{arg_type.?.fmt(pt)}, + ), + error.ExplicitTagNotEnum => return sema.fail( + block, + arg_ty_src, + "expected enum tag type, found '{f}'", + .{arg_type.?.fmt(pt)}, + ), + error.ExplicitTagFieldMismatch => { + const enum_obj = ip.loadEnumType(arg_type.?.toIntern()); + const enum_to_union_map = try sema.arena.alloc(?u32, enum_obj.field_names.len); + @memset(enum_to_union_map, null); + for (union_decl.field_names, 0..) |field_name_zir, union_field_idx| { + const field_name_ip = try ip.getOrPutString(gpa, io, pt.tid, sema.code.nullTerminatedString(field_name_zir), .no_embedded_nulls); + if (enum_obj.nameIndex(ip, field_name_ip)) |enum_field_idx| { + enum_to_union_map[enum_field_idx] = @intCast(union_field_idx); + continue; + } + const union_field_src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .{ .container_field_name = @intCast(union_field_idx) }, + }; + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(union_field_src, "no field named '{f}' in enum '{f}'", .{ field_name_ip.fmt(ip), arg_type.?.fmt(pt) }); + errdefer msg.destroy(gpa); + try sema.addDeclaredHereNote(msg, arg_type.?); + break :msg msg; + }); + } + for (enum_to_union_map, 0..) |union_field_idx, enum_field_idx| { + if (union_field_idx != null) continue; + const field_name_ip = enum_obj.field_names.get(ip)[enum_field_idx]; + const enum_field_src: LazySrcLoc = .{ + .base_node_inst = arg_type.?.typeDeclInstAllowGeneratedTag(zcu).?, + .offset = .{ .container_field_name = @intCast(enum_field_idx) }, + }; + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(src, "enum field '{f}' missing from union", .{field_name_ip.fmt(ip)}); + errdefer msg.destroy(gpa); + try sema.errNote(enum_field_src, msg, "enum field here", .{}); + break :msg msg; + }); + } + for (enum_to_union_map, 0..) |union_field_idx, enum_field_idx| { + if (union_field_idx.? == enum_field_idx) continue; + const field_name = sema.code.nullTerminatedString( + union_decl.field_names[union_field_idx.?], + ); + const union_field_src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .{ .container_field_name = union_field_idx.? }, + }; + const enum_field_src: LazySrcLoc = .{ + .base_node_inst = arg_type.?.typeDeclInstAllowGeneratedTag(zcu).?, + .offset = .{ .container_field_name = @intCast(enum_field_idx) }, + }; + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(src, "union field order does not match tag enum field order", .{}); + errdefer msg.destroy(gpa); + try sema.errNote(union_field_src, msg, "union field '{s}' is index {d}", .{ field_name, union_field_idx.? }); + try sema.errNote(enum_field_src, msg, "enum field '{s}' is index {d}", .{ field_name, enum_field_idx }); + break :msg msg; + }); + } + unreachable; + }, + }; + + const enum_tag_ty = ty.unionTagTypeHypothetical(zcu); + switch (ip.indexToKey(enum_tag_ty.toIntern()).enum_type) { + .declared, .reified => {}, + .generated_union_tag => |owner_union_ty| { + assert(owner_union_ty == ty.toIntern()); + // generated tag type [MLUGG] + // Enum inits are resolved eagerly. TODO MLUGG: honestly i don't think they SHOULD be lol + try sema.ensureFieldInitsResolved(.fromInterned(ip.loadUnionType(ty.toIntern()).enum_tag_type)); + }, + } + + try sema.addTypeReferenceEntry(src, ty); + + // Make sure we update the namespace if the declaration is re-analyzed, to pick + // up on e.g. changed comptime decls. + // TODO MLUGG: me no likey, maybe model namespaces less badly idk + try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)); + + return .fromIntern(ty.toIntern()); +} +fn zirEnumDecl( + sema: *Sema, + block: *Block, + inst: Zir.Inst.Index, +) CompileError!Air.Inst.Ref { + const pt = sema.pt; + const zcu = pt.zcu; + + const tracked_inst = try block.trackZir(inst); + + const src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .nodeOffset(.zero), + }; + const tag_ty_src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .{ .node_offset_container_tag = .zero }, + }; + + const enum_decl = sema.code.getEnumDecl(inst); + + const captures = try sema.getCaptures(block, src, enum_decl.captures, enum_decl.capture_names); + + const tag_type: ?Type = ty: { + if (enum_decl.tag_type == .none) break :ty null; + break :ty try sema.resolveType(block, tag_ty_src, enum_decl.tag_type); + }; + + const ty = analyzeEnumDecl( + pt, + block.getFileScopeIndex(zcu), + &sema.code, + block.namespace.toOptional(), + tracked_inst, + &enum_decl, + tag_type, + captures, + try sema.createTypeName(block, enum_decl.name_strategy, "enum", inst), + ) catch |err| switch (err) { + error.OutOfMemory, + error.Canceled, + => |e| return e, + + error.ExplicitTagNotInt => return sema.fail( + block, + tag_ty_src, + "expected integer tag type, found '{f}'", + .{tag_type.?.fmt(pt)}, + ), + }; + + // Enum inits are resolved eagerly. TODO MLUGG: honestly i don't think they SHOULD be lol + try sema.ensureFieldInitsResolved(ty); + + try sema.addTypeReferenceEntry(src, ty); + + // Make sure we update the namespace if the declaration is re-analyzed, to pick + // up on e.g. changed comptime decls. + // TODO MLUGG: me no likey, maybe model namespaces less badly idk + try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)); + + return .fromIntern(ty.toIntern()); +} +fn zirOpaqueDecl( + sema: *Sema, + block: *Block, + inst: Zir.Inst.Index, +) CompileError!Air.Inst.Ref { + const pt = sema.pt; + const zcu = pt.zcu; + + const tracked_inst = try block.trackZir(inst); + + const src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .nodeOffset(.zero), + }; + + const opaque_decl = sema.code.getOpaqueDecl(inst); + + const captures = try sema.getCaptures(block, src, opaque_decl.captures, opaque_decl.capture_names); + + const ty = try analyzeOpaqueDecl( + pt, + block.getFileScopeIndex(zcu), + block.namespace.toOptional(), + tracked_inst, + &opaque_decl, + captures, + try sema.createTypeName(block, opaque_decl.name_strategy, "opaque", inst), + ); + + try sema.addTypeReferenceEntry(src, ty); + + // Make sure we update the namespace if the declaration is re-analyzed, to pick + // up on e.g. changed comptime decls. + // TODO MLUGG: me no likey, maybe model namespaces less badly idk + try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)); + + return .fromIntern(ty.toIntern()); +} diff --git a/src/Sema/LowerZon.zig b/src/Sema/LowerZon.zig index 76cf3d7f2cc05310e4402cc3fe43072d2a07fc59..78d1d8d1df28af4b827e6d869d0e8352acd168ee 100644 --- a/src/Sema/LowerZon.zig +++ b/src/Sema/LowerZon.zig @@ -125,6 +125,7 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter return (try pt.aggregateValue(.fromInterned(ty), values)).toIntern(); }, .struct_literal => |init| { + if (true) @panic("MLUGG TODO"); const elems = try self.sema.arena.alloc(InternPool.Index, init.names.len); for (0..init.names.len) |i| { elems[i] = try self.lowerExprAnonResTy(init.vals.at(@intCast(i))); @@ -299,7 +300,7 @@ fn checkTypeInner( } else { const gop = try visited.getOrPut(sema.arena, ty.toIntern()); if (gop.found_existing) return; - try ty.resolveFields(pt); + try sema.ensureLayoutResolved(ty); const struct_info = zcu.typeToStruct(ty).?; for (struct_info.field_types.get(ip)) |field_type| { try self.checkTypeInner(.fromInterned(field_type), null, visited); @@ -308,7 +309,7 @@ fn checkTypeInner( .@"union" => { const gop = try visited.getOrPut(sema.arena, ty.toIntern()); if (gop.found_existing) return; - try ty.resolveFields(pt); + try sema.ensureLayoutResolved(ty); const union_info = zcu.typeToUnion(ty).?; for (union_info.field_types.get(ip)) |field_type| { if (field_type != .void_type) { @@ -767,8 +768,8 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool const io = comp.io; const ip = &pt.zcu.intern_pool; - try res_ty.resolveFields(self.sema.pt); - try res_ty.resolveStructFieldInits(self.sema.pt); + try self.sema.ensureLayoutResolved(res_ty); + try self.sema.ensureFieldInitsResolved(res_ty); const struct_info = self.sema.pt.zcu.typeToStruct(res_ty).?; const fields: @FieldType(Zoir.Node, "struct_literal") = switch (node.get(self.file.zoir.?)) { @@ -779,7 +780,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool const field_values = try self.sema.arena.alloc(InternPool.Index, struct_info.field_names.len); - const field_defaults = struct_info.field_inits.get(ip); + const field_defaults = struct_info.field_defaults.get(ip); if (field_defaults.len > 0) { @memcpy(field_values, field_defaults); } else { @@ -803,7 +804,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool const field_type: Type = .fromInterned(struct_info.field_types.get(ip)[name_index]); field_values[name_index] = try self.lowerExprKnownResTy(field_node, field_type); - if (struct_info.comptime_bits.getBit(ip, name_index)) { + if (struct_info.field_is_comptime_bits.get(ip, name_index)) { const val = ip.indexToKey(field_values[name_index]); const default = ip.indexToKey(field_defaults[name_index]); if (!val.eql(default, ip)) { @@ -918,9 +919,9 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. const gpa = comp.gpa; const io = comp.io; const ip = &pt.zcu.intern_pool; - try res_ty.resolveFields(self.sema.pt); - const union_info = self.sema.pt.zcu.typeToUnion(res_ty).?; - const enum_tag_info = union_info.loadTagType(ip); + try self.sema.ensureLayoutResolved(res_ty); + const union_info = pt.zcu.typeToUnion(res_ty).?; + const enum_tag_info = ip.loadEnumType(union_info.enum_tag_type); const field_name, const maybe_field_node = switch (node.get(self.file.zoir.?)) { .enum_literal => |name| b: { @@ -956,7 +957,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. const name_index = enum_tag_info.nameIndex(ip, field_name) orelse { return error.WrongType; }; - const tag = try self.sema.pt.enumValueFieldIndex(.fromInterned(union_info.enum_tag_ty), name_index); + const tag = try self.sema.pt.enumValueFieldIndex(.fromInterned(union_info.enum_tag_type), name_index); const field_type: Type = .fromInterned(union_info.field_types.get(ip)[name_index]); const val = if (maybe_field_node) |field_node| b: { if (field_type.toIntern() == .void_type) { diff --git a/src/Sema/arith.zig b/src/Sema/arith.zig index c646dc7b2167450ba54779bf2d83af6e0de86cc1..161b6e1ce03ad4ffd9ee8372f49fb39a8a279207 100644 --- a/src/Sema/arith.zig +++ b/src/Sema/arith.zig @@ -1053,7 +1053,7 @@ fn shlScalar( if (rhs_val.isUndef(zcu)) return rhs_val; }, } - switch (try rhs_val.orderAgainstZeroSema(pt)) { + switch (Value.order(rhs_val, .zero_comptime_int, zcu)) { .gt => {}, .eq => return lhs_val, .lt => return sema.failWithNegativeShiftAmount(block, rhs_src, rhs_val, vec_idx), @@ -1090,7 +1090,7 @@ fn shlWithOverflowScalar( if (lhs_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, lhs_src, vec_idx); if (rhs_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, rhs_src, vec_idx); - switch (try rhs_val.orderAgainstZeroSema(pt)) { + switch (Value.order(rhs_val, .zero_comptime_int, zcu)) { .gt => {}, .eq => return .{ .overflow_bit = .zero_u1, .wrapped_result = lhs_val }, .lt => return sema.failWithNegativeShiftAmount(block, rhs_src, rhs_val, vec_idx), @@ -1169,7 +1169,7 @@ fn shrScalar( if (lhs_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, lhs_src, vec_idx); if (rhs_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, rhs_src, vec_idx); - switch (try rhs_val.orderAgainstZeroSema(pt)) { + switch (Value.order(rhs_val, .zero_comptime_int, zcu)) { .gt => {}, .eq => return lhs_val, .lt => return sema.failWithNegativeShiftAmount(block, rhs_src, rhs_val, vec_idx), @@ -1430,8 +1430,8 @@ fn intAddWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value const info = ty.intInfo(zcu); var lhs_space: Value.BigIntSpace = undefined; var rhs_space: Value.BigIntSpace = undefined; - const lhs_bigint = try lhs.toBigIntSema(&lhs_space, pt); - const rhs_bigint = try rhs.toBigIntSema(&rhs_space, pt); + const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); + const rhs_bigint = rhs.toBigInt(&rhs_space, zcu); const limbs = try sema.arena.alloc( std.math.big.Limb, std.math.big.int.calcTwosCompLimbCount(info.bits), @@ -1512,8 +1512,8 @@ fn intSubWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value const info = ty.intInfo(zcu); var lhs_space: Value.BigIntSpace = undefined; var rhs_space: Value.BigIntSpace = undefined; - const lhs_bigint = try lhs.toBigIntSema(&lhs_space, pt); - const rhs_bigint = try rhs.toBigIntSema(&rhs_space, pt); + const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); + const rhs_bigint = rhs.toBigInt(&rhs_space, zcu); const limbs = try sema.arena.alloc( std.math.big.Limb, std.math.big.int.calcTwosCompLimbCount(info.bits), @@ -1597,8 +1597,8 @@ fn intMulWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value const info = ty.intInfo(zcu); var lhs_space: Value.BigIntSpace = undefined; var rhs_space: Value.BigIntSpace = undefined; - const lhs_bigint = try lhs.toBigIntSema(&lhs_space, pt); - const rhs_bigint = try rhs.toBigIntSema(&rhs_space, pt); + const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); + const rhs_bigint = rhs.toBigInt(&rhs_space, zcu); const limbs = try sema.arena.alloc( std.math.big.Limb, lhs_bigint.limbs.len + rhs_bigint.limbs.len, @@ -1840,7 +1840,7 @@ fn intShl( var lhs_space: Value.BigIntSpace = undefined; const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); - const shift_amt: usize = @intCast(try rhs.toUnsignedIntSema(pt)); + const shift_amt: usize = @intCast(rhs.toUnsignedInt(zcu)); if (shift_amt >= info.bits) { return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs, rhs_src, vec_idx); } @@ -1862,7 +1862,7 @@ fn intShlSat( const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); const shift_amt: usize = amt: { - if (try rhs.getUnsignedIntSema(pt)) |shift_amt_u64| { + if (rhs.getUnsignedInt(zcu)) |shift_amt_u64| { if (std.math.cast(usize, shift_amt_u64)) |shift_amt| break :amt shift_amt; } // We only support ints with up to 2^16 - 1 bits, so this @@ -1895,9 +1895,9 @@ fn intShlWithOverflow( const info = lhs_ty.intInfo(zcu); var lhs_space: Value.BigIntSpace = undefined; - const lhs_bigint = try lhs.toBigIntSema(&lhs_space, pt); + const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); - const shift_amt: usize = @intCast(try rhs.toUnsignedIntSema(pt)); + const shift_amt: usize = @intCast(rhs.toUnsignedInt(zcu)); if (shift_amt >= info.bits) { return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs, rhs_src, vec_idx); } @@ -1924,9 +1924,10 @@ fn comptimeIntShl( vec_idx: ?usize, ) !Value { const pt = sema.pt; + const zcu = pt.zcu; var lhs_space: Value.BigIntSpace = undefined; - const lhs_bigint = try lhs.toBigIntSema(&lhs_space, pt); - if (try rhs.getUnsignedIntSema(pt)) |shift_amt_u64| { + const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); + if (rhs.getUnsignedInt(zcu)) |shift_amt_u64| { if (std.math.cast(usize, shift_amt_u64)) |shift_amt| { const result_bigint = try intShlInner(sema, lhs_bigint, shift_amt); return pt.intValue_big(.comptime_int, result_bigint.toConst()); @@ -1963,15 +1964,15 @@ fn intShr( const lhs_bigint = lhs.toBigInt(&lhs_space, zcu); const shift_amt: usize = if (rhs_ty.toIntern() == .comptime_int_type) amt: { - if (try rhs.getUnsignedIntSema(pt)) |shift_amt_u64| { + if (rhs.getUnsignedInt(zcu)) |shift_amt_u64| { if (std.math.cast(usize, shift_amt_u64)) |shift_amt| break :amt shift_amt; } - if (try rhs.compareAllWithZeroSema(.lt, pt)) { + if (rhs.compareAllWithZero(.lt, zcu)) { return sema.failWithNegativeShiftAmount(block, rhs_src, rhs, vec_idx); } else { return sema.failWithUnsupportedComptimeShiftAmount(block, rhs_src, vec_idx); } - } else @intCast(try rhs.toUnsignedIntSema(pt)); + } else @intCast(rhs.toUnsignedInt(zcu)); if (lhs_ty.toIntern() != .comptime_int_type and shift_amt >= lhs_ty.intInfo(zcu).bits) { return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs, rhs_src, vec_idx); @@ -2006,7 +2007,7 @@ fn intBitReverse(sema: *Sema, val: Value, ty: Type) !Value { const info = ty.intInfo(zcu); var val_space: Value.BigIntSpace = undefined; - const val_bigint = try val.toBigIntSema(&val_space, pt); + const val_bigint = val.toBigInt(&val_space, zcu); const limbs = try sema.arena.alloc( std.math.big.Limb, diff --git a/src/Sema/bitcast.zig b/src/Sema/bitcast.zig index bc1859e51b4a60d58d628efef3c0158fc295aa6e..ee70bd1746466aaf57c8812083f37892e69dac59 100644 --- a/src/Sema/bitcast.zig +++ b/src/Sema/bitcast.zig @@ -79,8 +79,8 @@ fn bitCastInner( const val_ty = val.typeOf(zcu); - try val_ty.resolveLayout(pt); - try dest_ty.resolveLayout(pt); + val_ty.assertHasLayout(zcu); + try sema.ensureLayoutResolved(dest_ty); assert(val_ty.hasWellDefinedLayout(zcu)); @@ -138,8 +138,8 @@ fn bitCastSpliceInner( const val_ty = val.typeOf(zcu); const splice_val_ty = splice_val.typeOf(zcu); - try val_ty.resolveLayout(pt); - try splice_val_ty.resolveLayout(pt); + try sema.ensureLayoutResolved(val_ty); + try sema.ensureLayoutResolved(splice_val_ty); const splice_bits = splice_val_ty.bitSize(zcu); @@ -673,6 +673,9 @@ const PackValueBits = struct { fn primitive(pack: *PackValueBits, want_ty: Type) BitCastError!Value { const pt = pack.pt; const zcu = pt.zcu; + + if (try want_ty.onePossibleValue(pt)) |opv| return opv; + const vals, const bit_offset = pack.prepareBits(want_ty.bitSize(zcu)); for (vals) |val| { diff --git a/src/Sema/comptime_ptr_access.zig b/src/Sema/comptime_ptr_access.zig index 4e101ecd0f962fa49a2aa73ac228ce6c6fe7e3c0..c74b5c2d75fab499c27a973584d3aa0748515a94 100644 --- a/src/Sema/comptime_ptr_access.zig +++ b/src/Sema/comptime_ptr_access.zig @@ -67,7 +67,7 @@ pub fn storeComptimePtr( { const store_ty: Type = .fromInterned(ptr_info.child); - if (!try store_ty.comptimeOnlySema(pt) and !try store_ty.hasRuntimeBitsIgnoreComptimeSema(pt)) { + if (!store_ty.comptimeOnly(zcu) and !store_ty.hasRuntimeBits(zcu)) { // zero-bit store; nothing to do return .success; } @@ -354,8 +354,8 @@ fn loadComptimePtrInner( const load_one_ty, const load_count = load_ty.arrayBase(zcu); const extra_base_index: u64 = if (ptr.byte_offset == 0) 0 else idx: { - if (try load_one_ty.comptimeOnlySema(pt)) break :restructure_array; - const elem_len = try load_one_ty.abiSizeSema(pt); + if (load_one_ty.comptimeOnly(zcu)) break :restructure_array; + const elem_len = load_one_ty.abiSize(zcu); if (ptr.byte_offset % elem_len != 0) break :restructure_array; break :idx @divExact(ptr.byte_offset, elem_len); }; @@ -401,12 +401,12 @@ fn loadComptimePtrInner( var cur_offset = ptr.byte_offset; if (load_ty.zigTypeTag(zcu) == .array and array_offset > 0) { - cur_offset += try load_ty.childType(zcu).abiSizeSema(pt) * array_offset; + cur_offset += load_ty.childType(zcu).abiSize(zcu) * array_offset; } - const need_bytes = if (host_bits > 0) (host_bits + 7) / 8 else try load_ty.abiSizeSema(pt); + const need_bytes = if (host_bits > 0) (host_bits + 7) / 8 else load_ty.abiSize(zcu); - if (cur_offset + need_bytes > try cur_val.typeOf(zcu).abiSizeSema(pt)) { + if (cur_offset + need_bytes > cur_val.typeOf(zcu).abiSize(zcu)) { return .{ .out_of_bounds = cur_val.typeOf(zcu) }; } @@ -441,7 +441,7 @@ fn loadComptimePtrInner( .optional => break, // this can only be a pointer-like optional so is terminal .array => { const elem_ty = cur_ty.childType(zcu); - const elem_size = try elem_ty.abiSizeSema(pt); + const elem_size = elem_ty.abiSize(zcu); const elem_idx = cur_offset / elem_size; const next_elem_off = elem_size * (elem_idx + 1); if (cur_offset + need_bytes <= next_elem_off) { @@ -457,7 +457,7 @@ fn loadComptimePtrInner( .@"packed" => break, // let the bitcast logic handle this .@"extern" => for (0..cur_ty.structFieldCount(zcu)) |field_idx| { const start_off = cur_ty.structFieldOffset(field_idx, zcu); - const end_off = start_off + try cur_ty.fieldType(field_idx, zcu).abiSizeSema(pt); + const end_off = start_off + cur_ty.fieldType(field_idx, zcu).abiSize(zcu); if (cur_offset >= start_off and cur_offset + need_bytes <= end_off) { cur_val = try cur_val.getElem(sema.pt, field_idx); cur_offset -= start_off; @@ -484,7 +484,7 @@ fn loadComptimePtrInner( }; // The payload always has offset 0. If it's big enough // to represent the whole load type, we can use it. - if (try payload.typeOf(zcu).abiSizeSema(pt) >= need_bytes) { + if (payload.typeOf(zcu).abiSize(zcu) >= need_bytes) { cur_val = payload; } else { break; @@ -753,8 +753,8 @@ fn prepareComptimePtrStore( const store_one_ty, const store_count = store_ty.arrayBase(zcu); const extra_base_index: u64 = if (ptr.byte_offset == 0) 0 else idx: { - if (try store_one_ty.comptimeOnlySema(pt)) break :restructure_array; - const elem_len = try store_one_ty.abiSizeSema(pt); + if (store_one_ty.comptimeOnly(zcu)) break :restructure_array; + const elem_len = store_one_ty.abiSize(zcu); if (ptr.byte_offset % elem_len != 0) break :restructure_array; break :idx @divExact(ptr.byte_offset, elem_len); }; @@ -807,11 +807,11 @@ fn prepareComptimePtrStore( var cur_val: *MutableValue, var cur_offset: u64 = switch (base_strat) { .direct => |direct| .{ direct.val, 0 }, // It's okay to do `abiSize` - the comptime-only case will be caught below. - .index => |index| .{ index.val, index.elem_index * try index.val.typeOf(zcu).childType(zcu).abiSizeSema(pt) }, + .index => |index| .{ index.val, index.elem_index * index.val.typeOf(zcu).childType(zcu).abiSize(zcu) }, .flat_index => |flat_index| .{ flat_index.val, // It's okay to do `abiSize` - the comptime-only case will be caught below. - flat_index.flat_elem_index * try flat_index.val.typeOf(zcu).arrayBase(zcu)[0].abiSizeSema(pt), + flat_index.flat_elem_index * flat_index.val.typeOf(zcu).arrayBase(zcu)[0].abiSize(zcu), }, .reinterpret => |r| .{ r.val, r.byte_offset }, else => unreachable, @@ -823,12 +823,12 @@ fn prepareComptimePtrStore( } if (store_ty.zigTypeTag(zcu) == .array and array_offset > 0) { - cur_offset += try store_ty.childType(zcu).abiSizeSema(pt) * array_offset; + cur_offset += store_ty.childType(zcu).abiSize(zcu) * array_offset; } - const need_bytes = try store_ty.abiSizeSema(pt); + const need_bytes = store_ty.abiSize(zcu); - if (cur_offset + need_bytes > try cur_val.typeOf(zcu).abiSizeSema(pt)) { + if (cur_offset + need_bytes > cur_val.typeOf(zcu).abiSize(zcu)) { return .{ .out_of_bounds = cur_val.typeOf(zcu) }; } @@ -863,7 +863,7 @@ fn prepareComptimePtrStore( .optional => break, // this can only be a pointer-like optional so is terminal .array => { const elem_ty = cur_ty.childType(zcu); - const elem_size = try elem_ty.abiSizeSema(pt); + const elem_size = elem_ty.abiSize(zcu); const elem_idx = cur_offset / elem_size; const next_elem_off = elem_size * (elem_idx + 1); if (cur_offset + need_bytes <= next_elem_off) { @@ -879,7 +879,7 @@ fn prepareComptimePtrStore( .@"packed" => break, // let the bitcast logic handle this .@"extern" => for (0..cur_ty.structFieldCount(zcu)) |field_idx| { const start_off = cur_ty.structFieldOffset(field_idx, zcu); - const end_off = start_off + try cur_ty.fieldType(field_idx, zcu).abiSizeSema(pt); + const end_off = start_off + cur_ty.fieldType(field_idx, zcu).abiSize(zcu); if (cur_offset >= start_off and cur_offset + need_bytes <= end_off) { cur_val = try cur_val.elem(pt, sema.arena, field_idx); cur_offset -= start_off; @@ -902,7 +902,7 @@ fn prepareComptimePtrStore( }; // The payload always has offset 0. If it's big enough // to represent the whole load type, we can use it. - if (try payload.typeOf(zcu).abiSizeSema(pt) >= need_bytes) { + if (payload.typeOf(zcu).abiSize(zcu) >= need_bytes) { cur_val = payload; } else { break; diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig new file mode 100644 index 0000000000000000000000000000000000000000..f54a7b944e41f3c39161836a49654b177abb7c99 --- /dev/null +++ b/src/Sema/type_resolution.zig @@ -0,0 +1,993 @@ +const std = @import("std"); +const assert = std.debug.assert; +const mem = std.mem; + +const Sema = @import("../Sema.zig"); +const Block = Sema.Block; +const Type = @import("../Type.zig"); +const Value = @import("../Value.zig"); +const Zcu = @import("../Zcu.zig"); +const CompileError = Zcu.CompileError; +const SemaError = Zcu.SemaError; +const LazySrcLoc = Zcu.LazySrcLoc; +const InternPool = @import("../InternPool.zig"); +const Alignment = InternPool.Alignment; +const arith = @import("arith.zig"); + +/// Ensures that `ty` has known layout, including alignment, size, and (where relevant) field offsets. +/// `ty` may be any type; its layout is resolved *recursively* if necessary. +/// Adds incremental dependencies tracking any required type resolution. +/// MLUGG TODO: to make the langspec non-stupid, we need to call this from WAY fewer places (the conditions need to be less specific). +/// e.g. I think creating the type `fn (A, B) C` should force layout resolution of `A`,`B`,`C`, which will simplify some `analyzeCall` logic. +/// wait i just realised that's probably a terrible idea, fns are a common cause of dep loops rn... so maybe not lol idk... +/// perhaps "layout resolution" for a function should resolve layout of ret ty and stuff, idk. justification: the "layout" of a function is whether +/// fnHasRuntimeBits, which depends whether the ret ty is comptime-only, i.e. the ret ty layout +/// MLUGG TODO: to be clear, i should audit EVERY use of this before PRing +pub fn ensureLayoutResolved(sema: *Sema, ty: Type) SemaError!void { + const pt = sema.pt; + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + switch (ip.indexToKey(ty.toIntern())) { + .int_type, + .ptr_type, + .anyframe_type, + .simple_type, + .opaque_type, + .enum_type, + .error_set_type, + .inferred_error_set_type, + => {}, + + .func_type => |func_type| { + for (func_type.param_types.get(ip)) |param_ty| { + try ensureLayoutResolved(sema, .fromInterned(param_ty)); + } + try ensureLayoutResolved(sema, .fromInterned(func_type.return_type)); + }, + + .array_type => |arr| return ensureLayoutResolved(sema, .fromInterned(arr.child)), + .vector_type => |vec| return ensureLayoutResolved(sema, .fromInterned(vec.child)), + .opt_type => |child| return ensureLayoutResolved(sema, .fromInterned(child)), + .error_union_type => |eu| return ensureLayoutResolved(sema, .fromInterned(eu.payload_type)), + .tuple_type => |tuple| for (tuple.types.get(ip)) |field_ty| { + try ensureLayoutResolved(sema, .fromInterned(field_ty)); + }, + .struct_type, .union_type => { + try sema.declareDependency(.{ .type_layout = ty.toIntern() }); + if (zcu.analysis_in_progress.contains(.wrap(.{ .type_layout = ty.toIntern() }))) { + // TODO: better error message + return sema.failWithOwnedErrorMsg(null, try sema.errMsg( + ty.srcLoc(zcu), + "{s} '{f}' depends on itself", + .{ @tagName(ty.zigTypeTag(zcu)), ty.fmt(pt) }, + )); + } + try pt.ensureTypeLayoutUpToDate(ty); + }, + + // values, not types + .undef, + .simple_value, + .variable, + .@"extern", + .func, + .int, + .err, + .error_union, + .enum_literal, + .enum_tag, + .empty_enum_value, + .float, + .ptr, + .slice, + .opt, + .aggregate, + .un, + // memoization, not types + .memoized_call, + => unreachable, + } +} + +/// Asserts that `ty` is either a `struct` type, or an `enum` type. +/// If `ty` is a struct, ensures that fields' default values are resolved. +/// If `ty` is an enum, ensures that fields' integer tag valus are resolved. +/// Adds incremental dependencies tracking the required type resolution. +pub fn ensureFieldInitsResolved(sema: *Sema, ty: Type) SemaError!void { + const pt = sema.pt; + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + switch (ip.indexToKey(ty.toIntern())) { + .struct_type, .enum_type => {}, + else => unreachable, // assertion failure + } + + try sema.declareDependency(.{ .type_inits = ty.toIntern() }); + if (zcu.analysis_in_progress.contains(.wrap(.{ .type_inits = ty.toIntern() }))) { + // TODO: better error message + return sema.failWithOwnedErrorMsg(null, try sema.errMsg( + ty.srcLoc(zcu), + "{s} '{f}' depends on itself", + .{ @tagName(ty.zigTypeTag(zcu)), ty.fmt(pt) }, + )); + } + try pt.ensureTypeInitsUpToDate(ty); +} +/// Asserts that `struct_ty` is a non-packed non-tuple struct, and that `sema.owner` is that type. +/// This function *does* register the `src_hash` dependency on the struct. +pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { + const pt = sema.pt; + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const ip = &zcu.intern_pool; + + assert(sema.owner.unwrap().type_layout == struct_ty.toIntern()); + + const struct_obj = ip.loadStructType(struct_ty.toIntern()); + const zir_index = struct_obj.zir_index.resolve(ip).?; + + assert(struct_obj.layout != .@"packed"); + + try sema.declareDependency(.{ .src_hash = struct_obj.zir_index }); + + var block: Block = .{ + .parent = null, + .sema = sema, + .namespace = struct_obj.namespace, + .instructions = .{}, + .inlining = null, + .comptime_reason = undefined, // always set before using `block` + .src_base_inst = struct_obj.zir_index, + .type_name_ctx = struct_obj.name, + }; + defer assert(block.instructions.items.len == 0); + + const zir_struct = sema.code.getStructDecl(zir_index); + var field_it = zir_struct.iterateFields(); + while (field_it.next()) |zir_field| { + const field_ty_src: LazySrcLoc = .{ + .base_node_inst = struct_obj.zir_index, + .offset = .{ .container_field_type = zir_field.idx }, + }; + const field_align_src: LazySrcLoc = .{ + .base_node_inst = struct_obj.zir_index, + .offset = .{ .container_field_align = zir_field.idx }, + }; + + const field_ty: Type = field_ty: { + block.comptime_reason = .{ .reason = .{ + .src = field_ty_src, + .r = .{ .simple = .struct_field_types }, + } }; + const type_ref = try sema.resolveInlineBody(&block, zir_field.type_body, zir_index); + break :field_ty try sema.analyzeAsType(&block, field_ty_src, type_ref); + }; + assert(!field_ty.isGenericPoison()); + + try sema.ensureLayoutResolved(field_ty); + + const explicit_field_align: Alignment = a: { + block.comptime_reason = .{ .reason = .{ + .src = field_align_src, + .r = .{ .simple = .struct_field_attrs }, + } }; + const align_body = zir_field.align_body orelse break :a .none; + const align_ref = try sema.resolveInlineBody(&block, align_body, zir_index); + break :a try sema.analyzeAsAlign(&block, field_align_src, align_ref); + }; + + if (field_ty.zigTypeTag(zcu) == .@"opaque") { + return sema.failWithOwnedErrorMsg(&block, msg: { + const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in struct", .{field_ty.fmt(pt)}); + errdefer msg.destroy(gpa); + try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{}); + try sema.addDeclaredHereNote(msg, field_ty); + break :msg msg; + }); + } + if (struct_obj.layout == .@"extern" and !try sema.validateExternType(field_ty, .struct_field)) { + return sema.failWithOwnedErrorMsg(&block, msg: { + const msg = try sema.errMsg(field_ty_src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); + errdefer msg.destroy(gpa); + try sema.explainWhyTypeIsNotExtern(msg, field_ty_src, field_ty, .struct_field); + try sema.addDeclaredHereNote(msg, field_ty); + break :msg msg; + }); + } + + struct_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern(); + if (struct_obj.field_aligns.len != 0) { + struct_obj.field_aligns.get(ip)[zir_field.idx] = explicit_field_align; + } else { + assert(explicit_field_align == .none); + } + } + + try finishStructLayout(sema, &block, struct_ty.srcLoc(zcu), struct_ty.toIntern(), &struct_obj); +} + +/// Called after populating field types and alignments; populates field offsets, runtime order, and +/// overall struct layout information (size, alignment, comptime-only state, etc). +pub fn finishStructLayout( + sema: *Sema, + /// Only used to report compile errors. + block: *Block, + struct_src: LazySrcLoc, + struct_ty: InternPool.Index, + struct_obj: *const InternPool.LoadedStructType, +) SemaError!void { + const pt = sema.pt; + const zcu = pt.zcu; + const comp = zcu.comp; + const io = comp.io; + const ip = &zcu.intern_pool; + var comptime_only = false; + var one_possible_value = true; + var struct_align: Alignment = .@"1"; + // Unlike `struct_obj.field_aligns`, these are not `.none`. + const resolved_field_aligns = try sema.arena.alloc(Alignment, struct_obj.field_names.len); + for (resolved_field_aligns, 0..) |*align_out, field_idx| { + const field_ty: Type = .fromInterned(struct_obj.field_types.get(ip)[field_idx]); + const field_align: Alignment = a: { + if (struct_obj.field_aligns.len != 0) { + const a = struct_obj.field_aligns.get(ip)[field_idx]; + if (a != .none) break :a a; + } + break :a field_ty.defaultStructFieldAlignment(struct_obj.layout, zcu); + }; + if (!struct_obj.field_is_comptime_bits.get(ip, field_idx)) { + // Non-`comptime` fields contribute to the struct's layout. + struct_align = struct_align.maxStrict(field_align); + if (field_ty.comptimeOnly(zcu)) comptime_only = true; + if (try field_ty.onePossibleValue(pt) == null) one_possible_value = false; + if (struct_obj.layout == .auto) { + struct_obj.field_runtime_order.get(ip)[field_idx] = @enumFromInt(field_idx); + } + } else if (struct_obj.layout == .auto) { + struct_obj.field_runtime_order.get(ip)[field_idx] = .omitted; // comptime fields are not in the runtime order + } + align_out.* = field_align; + } + if (struct_obj.layout == .auto) { + const runtime_order = struct_obj.field_runtime_order.get(ip); + // This logic does not reorder fields; it only moves the omitted ones to the end so that logic + // elsewhere does not need to special-case. TODO: support field reordering in all the backends! + if (!zcu.backendSupportsFeature(.field_reordering)) { + var i: usize = 0; + var off: usize = 0; + while (i + off < runtime_order.len) { + if (runtime_order[i + off] == .omitted) { + off += 1; + } else { + runtime_order[i] = runtime_order[i + off]; + i += 1; + } + } + } else { + // Sort by descending alignment to minimize padding. + const RuntimeOrder = InternPool.LoadedStructType.RuntimeOrder; + const AlignSortCtx = struct { + aligns: []const Alignment, + fn lessThan(ctx: @This(), a: RuntimeOrder, b: RuntimeOrder) bool { + assert(a != .unresolved); + assert(b != .unresolved); + if (a == .omitted) return false; + if (b == .omitted) return true; + const a_align = ctx.aligns[@intFromEnum(a)]; + const b_align = ctx.aligns[@intFromEnum(b)]; + return a_align.compare(.gt, b_align); + } + }; + mem.sortUnstable( + RuntimeOrder, + runtime_order, + @as(AlignSortCtx, .{ .aligns = resolved_field_aligns }), + AlignSortCtx.lessThan, + ); + } + } + + var runtime_order_it = struct_obj.iterateRuntimeOrder(ip); + var cur_offset: u64 = 0; + while (runtime_order_it.next()) |field_idx| { + const field_ty: Type = .fromInterned(struct_obj.field_types.get(ip)[field_idx]); + const offset = resolved_field_aligns[field_idx].forward(cur_offset); + struct_obj.field_offsets.get(ip)[field_idx] = @truncate(offset); // truncate because the overflow is handled below + cur_offset = offset + field_ty.abiSize(zcu); + } + const struct_size = std.math.cast(u32, struct_align.forward(cur_offset)) orelse return sema.fail( + block, + struct_src, + "struct layout requires size {d}, this compiler implementation supports up to {d}", + .{ struct_align.forward(cur_offset), std.math.maxInt(u32) }, + ); + ip.resolveStructLayout( + io, + struct_ty, + struct_size, + struct_align, + false, // MLUGG TODO XXX NPV + one_possible_value, + comptime_only, + ); +} + +/// Asserts that `struct_ty` is a packed struct, and that `sema.owner` is that type. +/// This function *does* register the `src_hash` dependency on the struct. +pub fn resolvePackedStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { + const pt = sema.pt; + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const ip = &zcu.intern_pool; + + assert(sema.owner.unwrap().type_layout == struct_ty.toIntern()); + + const struct_obj = ip.loadStructType(struct_ty.toIntern()); + const zir_index = struct_obj.zir_index.resolve(ip).?; + + assert(struct_obj.layout == .@"packed"); + + try sema.declareDependency(.{ .src_hash = struct_obj.zir_index }); + + var block: Block = .{ + .parent = null, + .sema = sema, + .namespace = struct_obj.namespace, + .instructions = .{}, + .inlining = null, + .comptime_reason = undefined, // always set before using `block` + .src_base_inst = struct_obj.zir_index, + .type_name_ctx = struct_obj.name, + }; + defer assert(block.instructions.items.len == 0); + + var field_bits: u64 = 0; + const zir_struct = sema.code.getStructDecl(zir_index); + var field_it = zir_struct.iterateFields(); + while (field_it.next()) |zir_field| { + const field_ty_src: LazySrcLoc = .{ + .base_node_inst = struct_obj.zir_index, + .offset = .{ .container_field_type = zir_field.idx }, + }; + const field_ty: Type = field_ty: { + block.comptime_reason = .{ .reason = .{ + .src = field_ty_src, + .r = .{ .simple = .struct_field_types }, + } }; + const type_ref = try sema.resolveInlineBody(&block, zir_field.type_body, zir_index); + break :field_ty try sema.analyzeAsType(&block, field_ty_src, type_ref); + }; + assert(!field_ty.isGenericPoison()); + struct_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern(); + + try sema.ensureLayoutResolved(field_ty); + + if (field_ty.zigTypeTag(zcu) == .@"opaque") { + return sema.failWithOwnedErrorMsg(&block, msg: { + const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in struct", .{field_ty.fmt(pt)}); + errdefer msg.destroy(gpa); + try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{}); + try sema.addDeclaredHereNote(msg, field_ty); + break :msg msg; + }); + } + if (!field_ty.packable(zcu)) { + return sema.failWithOwnedErrorMsg(&block, msg: { + const msg = try sema.errMsg(field_ty_src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); + errdefer msg.destroy(gpa); + try sema.explainWhyTypeIsNotPackable(msg, field_ty_src, field_ty); + try sema.addDeclaredHereNote(msg, field_ty); + break :msg msg; + }); + } + assert(!field_ty.comptimeOnly(zcu)); // packable types are not comptime-only + field_bits += field_ty.bitSize(zcu); + } + + try resolvePackedStructBackingInt(sema, &block, field_bits, struct_ty, &struct_obj); +} + +pub fn resolvePackedStructBackingInt( + sema: *Sema, + block: *Block, + field_bits: u64, + struct_ty: Type, + struct_obj: *const InternPool.LoadedStructType, +) SemaError!void { + const pt = sema.pt; + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &zcu.intern_pool; + + switch (struct_obj.packed_backing_mode) { + .explicit => { + // We only need to validate the type. + const backing_ty: Type = .fromInterned(struct_obj.packed_backing_int_type); + assert(backing_ty.zigTypeTag(zcu) == .int); + if (field_bits != backing_ty.intInfo(zcu).bits) return sema.failWithOwnedErrorMsg(block, msg: { + const src = struct_ty.srcLoc(zcu); + const msg = try sema.errMsg(src, "backing integer bit width does not match total bit width of fields", .{}); + errdefer msg.destroy(gpa); + try sema.errNote(src, msg, "backing integer '{f}' has bit width '{d}'", .{ backing_ty.fmt(pt), backing_ty.bitSize(zcu) }); + try sema.errNote(src, msg, "struct fields have total bit width '{d}'", .{field_bits}); + break :msg msg; + }); + }, + .auto => { + // We need to generate the inferred tag. + const want_bits = std.math.cast(u16, field_bits) orelse return sema.fail( + block, + struct_ty.srcLoc(zcu), + "packed struct bit width '{d}' exceeds maximum bit width of 65535", + .{field_bits}, + ); + const backing_int = try pt.intType(.unsigned, want_bits); + ip.resolvePackedStructBackingInt(io, struct_ty.toIntern(), backing_int.toIntern()); + }, + } +} + +/// Asserts that `struct_ty` is a non-tuple struct, and that `sema.owner` is that type. +/// This function *does* register the `src_hash` dependency on the struct. +pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void { + const pt = sema.pt; + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const ip = &zcu.intern_pool; + + assert(sema.owner.unwrap().type_inits == struct_ty.toIntern()); + + try sema.ensureLayoutResolved(struct_ty); + + const struct_obj = ip.loadStructType(struct_ty.toIntern()); + const zir_index = struct_obj.zir_index.resolve(ip).?; + + try sema.declareDependency(.{ .src_hash = struct_obj.zir_index }); + + if (struct_obj.field_defaults.len == 0) { + // The struct has no default field values, so the slice has been omitted. + return; + } + + const field_types = struct_obj.field_types.get(ip); + + var block: Block = .{ + .parent = null, + .sema = sema, + .namespace = struct_obj.namespace, + .instructions = .{}, + .inlining = null, + .comptime_reason = undefined, // always set before using `block` + .src_base_inst = struct_obj.zir_index, + .type_name_ctx = struct_obj.name, + }; + defer assert(block.instructions.items.len == 0); + + // We'll need to map the struct decl instruction to provide result types + try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index}); + + const zir_struct = sema.code.getStructDecl(zir_index); + var field_it = zir_struct.iterateFields(); + while (field_it.next()) |zir_field| { + const default_val_src: LazySrcLoc = .{ + .base_node_inst = struct_obj.zir_index, + .offset = .{ .container_field_value = zir_field.idx }, + }; + block.comptime_reason = .{ .reason = .{ + .src = default_val_src, + .r = .{ .simple = .struct_field_default_value }, + } }; + const default_body = zir_field.default_body orelse { + struct_obj.field_defaults.get(ip)[zir_field.idx] = .none; + continue; + }; + const field_ty: Type = .fromInterned(field_types[zir_field.idx]); + const uncoerced = ref: { + // Provide the result type + sema.inst_map.putAssumeCapacity(zir_index, .fromIntern(field_ty.toIntern())); + defer assert(sema.inst_map.remove(zir_index)); + break :ref try sema.resolveInlineBody(&block, default_body, zir_index); + }; + const coerced = try sema.coerce(&block, field_ty, uncoerced, default_val_src); + const default_val = try sema.resolveConstValue(&block, default_val_src, coerced, null); + if (default_val.canMutateComptimeVarState(zcu)) { + const field_name = struct_obj.field_names.get(ip)[zir_field.idx]; + return sema.failWithContainsReferenceToComptimeVar(&block, default_val_src, field_name, "field default value", default_val); + } + struct_obj.field_defaults.get(ip)[zir_field.idx] = default_val.toIntern(); + } +} + +/// This logic must be kept in sync with `Type.getUnionLayout`. +pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { + const pt = sema.pt; + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const ip = &zcu.intern_pool; + + assert(sema.owner.unwrap().type_layout == union_ty.toIntern()); + + const union_obj = ip.loadUnionType(union_ty.toIntern()); + const zir_index = union_obj.zir_index.resolve(ip).?; + + assert(union_obj.layout != .@"packed"); + + try sema.declareDependency(.{ .src_hash = union_obj.zir_index }); + + var block: Block = .{ + .parent = null, + .sema = sema, + .namespace = union_obj.namespace, + .instructions = .{}, + .inlining = null, + .comptime_reason = undefined, // always set before using `block` + .src_base_inst = union_obj.zir_index, + .type_name_ctx = union_obj.name, + }; + defer assert(block.instructions.items.len == 0); + + const zir_union = sema.code.getUnionDecl(zir_index); + var field_it = zir_union.iterateFields(); + while (field_it.next()) |zir_field| { + const field_ty_src: LazySrcLoc = .{ + .base_node_inst = union_obj.zir_index, + .offset = .{ .container_field_type = zir_field.idx }, + }; + const field_align_src: LazySrcLoc = .{ + .base_node_inst = union_obj.zir_index, + .offset = .{ .container_field_align = zir_field.idx }, + }; + + const field_ty: Type = field_ty: { + block.comptime_reason = .{ .reason = .{ + .src = field_ty_src, + .r = .{ .simple = .union_field_types }, + } }; + const type_body = zir_field.type_body orelse break :field_ty .void; + const type_ref = try sema.resolveInlineBody(&block, type_body, zir_index); + break :field_ty try sema.analyzeAsType(&block, field_ty_src, type_ref); + }; + assert(!field_ty.isGenericPoison()); + union_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern(); + + try sema.ensureLayoutResolved(field_ty); + + const explicit_field_align: Alignment = a: { + block.comptime_reason = .{ .reason = .{ + .src = field_align_src, + .r = .{ .simple = .union_field_attrs }, + } }; + const align_body = zir_field.align_body orelse break :a .none; + const align_ref = try sema.resolveInlineBody(&block, align_body, zir_index); + break :a try sema.analyzeAsAlign(&block, field_align_src, align_ref); + }; + + if (union_obj.field_aligns.len != 0) { + union_obj.field_aligns.get(ip)[zir_field.idx] = explicit_field_align; + } else { + assert(explicit_field_align == .none); + } + + if (field_ty.zigTypeTag(zcu) == .@"opaque") { + return sema.failWithOwnedErrorMsg(&block, msg: { + const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in union", .{field_ty.fmt(pt)}); + errdefer msg.destroy(gpa); + try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{}); + try sema.addDeclaredHereNote(msg, field_ty); + break :msg msg; + }); + } + if (union_obj.layout == .@"extern" and !try sema.validateExternType(field_ty, .union_field)) { + return sema.failWithOwnedErrorMsg(&block, msg: { + const msg = try sema.errMsg(field_ty_src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); + errdefer msg.destroy(gpa); + try sema.explainWhyTypeIsNotExtern(msg, field_ty_src, field_ty, .union_field); + try sema.addDeclaredHereNote(msg, field_ty); + break :msg msg; + }); + } + } + + try finishUnionLayout( + sema, + &block, + union_ty.srcLoc(zcu), + union_ty.toIntern(), + &union_obj, + .fromInterned(union_obj.enum_tag_type), + ); +} + +/// Called after populating field types and alignments; populates overall union layout +/// information (size, alignment, comptime-only state, etc). +pub fn finishUnionLayout( + sema: *Sema, + /// Only used to report compile errors. + block: *Block, + union_src: LazySrcLoc, + union_ty: InternPool.Index, + union_obj: *const InternPool.LoadedUnionType, + enum_tag_ty: Type, +) SemaError!void { + const pt = sema.pt; + const zcu = pt.zcu; + const comp = zcu.comp; + const io = comp.io; + const ip = &zcu.intern_pool; + + var payload_align: Alignment = .@"1"; + var payload_size: u64 = 0; + var comptime_only = false; + var possible_values: enum { none, one, many } = .none; + for (0..union_obj.field_types.len) |field_idx| { + const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]); + const field_align: Alignment = a: { + if (union_obj.field_aligns.len != 0) { + const a = union_obj.field_aligns.get(ip)[field_idx]; + if (a != .none) break :a a; + } + break :a field_ty.abiAlignment(zcu); + }; + payload_align = payload_align.maxStrict(field_align); + payload_size = @max(payload_size, field_ty.abiSize(zcu)); + if (field_ty.comptimeOnly(zcu)) comptime_only = true; + if (!field_ty.isNoReturn(zcu)) { + if (try field_ty.onePossibleValue(pt) != null) { + possible_values = .many; // this field alone has many possible values + } else switch (possible_values) { + .none => possible_values = .one, // there were none, now there is this field's OPV + .one => possible_values = .many, // there was one, now there are two + .many => {}, + } + } + } + + const size: u64, const padding: u64, const alignment: Alignment = layout: { + if (union_obj.runtime_tag == .none) { + break :layout .{ payload_align.forward(payload_size), 0, payload_align }; + } + const tag_align = enum_tag_ty.abiAlignment(zcu); + const tag_size = enum_tag_ty.abiSize(zcu); + // The layout will either be (tag, payload, padding) or (payload, tag, padding) depending on + // which has larger alignment. So the overall size is just the tag and payload sizes, added, + // and padded to the larger alignment. + const alignment = tag_align.maxStrict(payload_align); + const unpadded_size = tag_size + payload_size; + const size = alignment.forward(unpadded_size); + break :layout .{ size, size - unpadded_size, alignment }; + }; + + const casted_size = std.math.cast(u32, size) orelse return sema.fail( + block, + union_src, + "union layout requires size {d}, this compiler implementation supports up to {d}", + .{ size, std.math.maxInt(u32) }, + ); + ip.resolveUnionLayout( + io, + union_ty, + casted_size, + @intCast(padding), // okay because padding is no greater than size + alignment, + possible_values == .none, // MLUGG TODO: make sure queries use `LoadedUnionType.has_no_possible_value`! + possible_values == .one, + comptime_only, + ); +} + +pub fn resolvePackedUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { + const pt = sema.pt; + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const ip = &zcu.intern_pool; + + assert(sema.owner.unwrap().type_layout == union_ty.toIntern()); + + const union_obj = ip.loadUnionType(union_ty.toIntern()); + const zir_index = union_obj.zir_index.resolve(ip).?; + + assert(union_obj.layout == .@"packed"); + + try sema.declareDependency(.{ .src_hash = union_obj.zir_index }); + + var block: Block = .{ + .parent = null, + .sema = sema, + .namespace = union_obj.namespace, + .instructions = .{}, + .inlining = null, + .comptime_reason = undefined, // always set before using `block` + .src_base_inst = union_obj.zir_index, + .type_name_ctx = union_obj.name, + }; + defer assert(block.instructions.items.len == 0); + + const zir_union = sema.code.getUnionDecl(zir_index); + var field_it = zir_union.iterateFields(); + while (field_it.next()) |zir_field| { + const field_ty_src: LazySrcLoc = .{ + .base_node_inst = union_obj.zir_index, + .offset = .{ .container_field_type = zir_field.idx }, + }; + const field_ty: Type = field_ty: { + block.comptime_reason = .{ .reason = .{ + .src = field_ty_src, + .r = .{ .simple = .union_field_types }, + } }; + // MLUGG TODO: i think this should probably be a compile error? (if so, it's an astgen one, right?) + const type_body = zir_field.type_body orelse break :field_ty .void; + const type_ref = try sema.resolveInlineBody(&block, type_body, zir_index); + break :field_ty try sema.analyzeAsType(&block, field_ty_src, type_ref); + }; + assert(!field_ty.isGenericPoison()); + union_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern(); + + assert(zir_field.align_body == null); // packed union fields cannot be aligned + assert(zir_field.value_body == null); // packed union fields cannot have tag values + + try sema.ensureLayoutResolved(field_ty); + + if (field_ty.zigTypeTag(zcu) == .@"opaque") { + return sema.failWithOwnedErrorMsg(&block, msg: { + const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in union", .{field_ty.fmt(pt)}); + errdefer msg.destroy(gpa); + try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{}); + try sema.addDeclaredHereNote(msg, field_ty); + break :msg msg; + }); + } + if (!field_ty.packable(zcu)) { + return sema.failWithOwnedErrorMsg(&block, msg: { + const msg = try sema.errMsg(field_ty_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); + errdefer msg.destroy(gpa); + try sema.explainWhyTypeIsNotPackable(msg, field_ty_src, field_ty); + try sema.addDeclaredHereNote(msg, field_ty); + break :msg msg; + }); + } + assert(!field_ty.comptimeOnly(zcu)); // packable types are not comptime-only + } + + try resolvePackedUnionBackingInt(sema, &block, union_ty, &union_obj, false); +} + +/// MLUGG TODO doc comment; asserts all fields are resolved or whatever +pub fn resolvePackedUnionBackingInt( + sema: *Sema, + block: *Block, + union_ty: Type, + union_obj: *const InternPool.LoadedUnionType, + is_reified: bool, +) SemaError!void { + const pt = sema.pt; + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &zcu.intern_pool; + switch (union_obj.packed_backing_mode) { + .explicit => { + const backing_int_type: Type = .fromInterned(union_obj.packed_backing_int_type); + const backing_int_bits = backing_int_type.intInfo(zcu).bits; + for (union_obj.field_types.get(ip), 0..) |field_type_ip, field_idx| { + const field_type: Type = .fromInterned(field_type_ip); + const field_bits = field_type.bitSize(zcu); + if (field_bits != backing_int_bits) return sema.failWithOwnedErrorMsg(block, msg: { + const field_ty_src: LazySrcLoc = .{ + .base_node_inst = union_obj.zir_index, + .offset = if (is_reified) + .nodeOffset(.zero) + else + .{ .container_field_type = @intCast(field_idx) }, + }; + const msg = try sema.errMsg(field_ty_src, "field bit width does not match backing integer", .{}); + errdefer msg.destroy(gpa); + try sema.errNote(field_ty_src, msg, "field type '{f}' has bit width '{d}'", .{ field_type.fmt(pt), field_bits }); + try sema.errNote(field_ty_src, msg, "backing integer '{f}' has bit width '{d}'", .{ backing_int_type.fmt(pt), backing_int_bits }); + try sema.errNote(field_ty_src, msg, "all fields in a packed union must have the same bit width", .{}); + break :msg msg; + }); + } + }, + .auto => switch (union_obj.field_types.len) { + 0 => ip.resolvePackedUnionBackingInt(io, union_ty.toIntern(), .u0_type), + else => { + const field_types = union_obj.field_types.get(ip); + const first_field_type: Type = .fromInterned(field_types[0]); + const first_field_bits = first_field_type.bitSize(zcu); + for (field_types[1..], 1..) |field_type_ip, field_idx| { + const field_type: Type = .fromInterned(field_type_ip); + const field_bits = field_type.bitSize(zcu); + if (field_bits != first_field_bits) return sema.failWithOwnedErrorMsg(block, msg: { + const first_field_ty_src: LazySrcLoc = .{ + .base_node_inst = union_obj.zir_index, + .offset = if (is_reified) + .nodeOffset(.zero) + else + .{ .container_field_type = 0 }, + }; + const field_ty_src: LazySrcLoc = .{ + .base_node_inst = union_obj.zir_index, + .offset = if (is_reified) + .nodeOffset(.zero) + else + .{ .container_field_type = @intCast(field_idx) }, + }; + const msg = try sema.errMsg(field_ty_src, "field bit width does not match earlier field", .{}); + errdefer msg.destroy(gpa); + try sema.errNote(field_ty_src, msg, "field type '{f}' has bit width '{d}'", .{ field_type.fmt(pt), field_bits }); + try sema.errNote(first_field_ty_src, msg, "other field type '{f}' has bit width '{d}'", .{ first_field_type.fmt(pt), first_field_bits }); + try sema.errNote(field_ty_src, msg, "all fields in a packed union must have the same bit width", .{}); + break :msg msg; + }); + } + const backing_int_bits = std.math.cast(u16, first_field_bits) orelse return sema.fail( + block, + block.nodeOffset(.zero), + "packed union bit width '{d}' exceeds maximum bit width of 65535", + .{first_field_bits}, + ); + const backing_int_type = try pt.intType(.unsigned, backing_int_bits); + ip.resolvePackedUnionBackingInt(io, union_ty.toIntern(), backing_int_type.toIntern()); + }, + }, + } +} + +/// Asserts that `enum_ty` is an enum and that `sema.owner` is that type. +/// This function *does* register the `src_hash` dependency on the enum. +pub fn resolveEnumValues(sema: *Sema, enum_ty: Type) CompileError!void { + const pt = sema.pt; + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const ip = &zcu.intern_pool; + + assert(sema.owner.unwrap().type_inits == enum_ty.toIntern()); + + const enum_obj = ip.loadEnumType(enum_ty.toIntern()); + + // We'll populate this map. + const field_value_map = enum_obj.field_value_map.unwrap() orelse { + // The enum has an automatically generated tag and is auto-numbered. We know that we have + // generated a suitably large type in `analyzeEnumDecl`, so we have no work to do. + return; + }; + + const maybe_parent_union_obj: ?InternPool.LoadedUnionType = un: { + if (enum_obj.owner_union == .none) break :un null; + break :un ip.loadUnionType(enum_obj.owner_union); + }; + const tracked_inst = enum_obj.zir_index.unwrap() orelse maybe_parent_union_obj.?.zir_index; + const zir_index = tracked_inst.resolve(ip).?; + + try sema.declareDependency(.{ .src_hash = tracked_inst }); + + var block: Block = .{ + .parent = null, + .sema = sema, + .namespace = enum_obj.namespace, + .instructions = .{}, + .inlining = null, + .comptime_reason = undefined, // always set before using `block` + .src_base_inst = tracked_inst, + .type_name_ctx = enum_obj.name, + }; + defer assert(block.instructions.items.len == 0); + + const int_tag_ty: Type = .fromInterned(enum_obj.int_tag_type); + + // Map the enum (or union) decl instruction to provide the tag type as the result type + try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index}); + sema.inst_map.putAssumeCapacity(zir_index, .fromIntern(int_tag_ty.toIntern())); + defer assert(sema.inst_map.remove(zir_index)); + + // First, populate any explicitly provided values. This is the part that actually depends on + // the ZIR, and hence depends on whether this is a declared or generated enum. If any explicit + // value is invalid, we'll emit an error here. + if (maybe_parent_union_obj) |union_obj| { + const zir_union = sema.code.getUnionDecl(zir_index); + var field_it = zir_union.iterateFields(); + while (field_it.next()) |zir_field| { + const field_val_src: LazySrcLoc = .{ + .base_node_inst = union_obj.zir_index, + .offset = .{ .container_field_value = zir_field.idx }, + }; + block.comptime_reason = .{ .reason = .{ + .src = field_val_src, + .r = .{ .simple = .enum_field_values }, + } }; + const value_body = zir_field.value_body orelse { + enum_obj.field_values.get(ip)[zir_field.idx] = .none; + continue; + }; + const uncoerced = try sema.resolveInlineBody(&block, value_body, zir_index); + const coerced = try sema.coerce(&block, int_tag_ty, uncoerced, field_val_src); + const val = try sema.resolveConstValue(&block, field_val_src, coerced, null); + enum_obj.field_values.get(ip)[zir_field.idx] = val.toIntern(); + } + } else { + const zir_enum = sema.code.getEnumDecl(zir_index); + var field_it = zir_enum.iterateFields(); + while (field_it.next()) |zir_field| { + const field_val_src: LazySrcLoc = .{ + .base_node_inst = enum_obj.zir_index.unwrap().?, + .offset = .{ .container_field_value = zir_field.idx }, + }; + block.comptime_reason = .{ .reason = .{ + .src = field_val_src, + .r = .{ .simple = .enum_field_values }, + } }; + const value_body = zir_field.value_body orelse { + enum_obj.field_values.get(ip)[zir_field.idx] = .none; + continue; + }; + const uncoerced = try sema.resolveInlineBody(&block, value_body, zir_index); + const coerced = try sema.coerce(&block, int_tag_ty, uncoerced, field_val_src); + const val = try sema.resolveConstDefinedValue(&block, field_val_src, coerced, null); + enum_obj.field_values.get(ip)[zir_field.idx] = val.toIntern(); + } + } + + // Explicit values are set. Now we'll go through the whole array and figure out the final + // field values. This is also where we'll detect duplicates. + + for (0..enum_obj.field_names.len) |field_idx| { + const field_val_src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .{ .container_field_value = @intCast(field_idx) }, + }; + // If the field value was not specified, compute the implicit value. + const field_val = val: { + const explicit_val = enum_obj.field_values.get(ip)[field_idx]; + if (explicit_val != .none) break :val explicit_val; + if (field_idx == 0) { + // Implicit value is 0, which is valid for every integer type. + const val = (try pt.intValue(int_tag_ty, 0)).toIntern(); + enum_obj.field_values.get(ip)[field_idx] = val; + break :val val; + } + // Implicit non-initial value: take the previous field value and add one. + const prev_field_val: Value = .fromInterned(enum_obj.field_values.get(ip)[field_idx - 1]); + const result = try arith.incrementDefinedInt(sema, int_tag_ty, prev_field_val); + if (result.overflow) return sema.fail( + &block, + field_val_src, + "enum tag value '{f}' too large for type '{f}'", + .{ result.val.fmtValueSema(pt, sema), int_tag_ty.fmt(pt) }, + ); + const val = result.val.toIntern(); + enum_obj.field_values.get(ip)[field_idx] = val; + break :val val; + }; + const adapter: InternPool.Index.Adapter = .{ .indexes = enum_obj.field_values.get(ip)[0..field_idx] }; + const gop = field_value_map.get(ip).getOrPutAssumeCapacityAdapted(field_val, adapter); + if (!gop.found_existing) continue; + const prev_field_val_src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .{ .container_field_value = @intCast(gop.index) }, + }; + return sema.failWithOwnedErrorMsg(&block, msg: { + const msg = try sema.errMsg(field_val_src, "enum tag value '{f}' already taken", .{ + Value.fromInterned(field_val).fmtValueSema(pt, sema), + }); + errdefer msg.destroy(gpa); + try sema.errNote(prev_field_val_src, msg, "previous occurrence here", .{}); + break :msg msg; + }); + } + + if (enum_obj.nonexhaustive and int_tag_ty.toIntern() != .comptime_int_type) { + const fields_len = enum_obj.field_names.len; + if (fields_len >= 1 and std.math.log2_int(u64, fields_len) == int_tag_ty.bitSize(zcu)) { + return sema.fail(&block, block.nodeOffset(.zero), "non-exhaustive enum specifies every value", .{}); + } + } +} diff --git a/src/Type.zig b/src/Type.zig index 57d8a0a5ede75204e3382f4740f28c9b83799681..52dc5ed1ebb7918d930f51d21c65ba68a8178be5 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -12,12 +12,10 @@ const Target = std.Target; const Zcu = @import("Zcu.zig"); const log = std.log.scoped(.Type); const target_util = @import("target.zig"); -const Sema = @import("Sema.zig"); const InternPool = @import("InternPool.zig"); const Alignment = InternPool.Alignment; const Zir = std.zig.Zir; const Type = @This(); -const SemaError = Zcu.SemaError; ip_index: InternPool.Index, @@ -25,16 +23,6 @@ pub fn zigTypeTag(ty: Type, zcu: *const Zcu) std.builtin.TypeId { return zcu.intern_pool.zigTypeTag(ty.toIntern()); } -pub fn baseZigTypeTag(self: Type, mod: *Zcu) std.builtin.TypeId { - return switch (self.zigTypeTag(mod)) { - .error_union => self.errorUnionPayload(mod).baseZigTypeTag(mod), - .optional => { - return self.optionalChild(mod).baseZigTypeTag(mod); - }, - else => |t| t, - }; -} - /// Asserts the type is resolved. pub fn isSelfComparable(ty: Type, zcu: *const Zcu, is_equality_cmp: bool) bool { return switch (ty.zigTypeTag(zcu)) { @@ -44,7 +32,7 @@ pub fn isSelfComparable(ty: Type, zcu: *const Zcu, is_equality_cmp: bool) bool { .comptime_int, => true, - .vector => ty.elemType2(zcu).isSelfComparable(zcu, is_equality_cmp), + .vector => ty.childType(zcu).isSelfComparable(zcu, is_equality_cmp), .bool, .type, @@ -121,11 +109,7 @@ pub fn eql(a: Type, b: Type, zcu: *const Zcu) bool { return a.toIntern() == b.toIntern(); } -pub fn format(ty: Type, writer: *std.Io.Writer) !void { - _ = ty; - _ = writer; - @compileError("do not format types directly; use either ty.fmtDebug() or ty.fmt()"); -} +pub const format = @compileError("do not format types directly; use either ty.fmtDebug() or ty.fmt()"); pub const Formatter = std.fmt.Alt(Format, Format.default); @@ -440,31 +424,7 @@ pub fn toIntern(ty: Type) InternPool.Index { } pub fn toValue(self: Type) Value { - return Value.fromInterned(self.toIntern()); -} - -const RuntimeBitsError = SemaError || error{NeedLazy}; - -pub fn hasRuntimeBits(ty: Type, zcu: *const Zcu) bool { - return hasRuntimeBitsInner(ty, false, .eager, zcu, {}) catch unreachable; -} - -pub fn hasRuntimeBitsSema(ty: Type, pt: Zcu.PerThread) SemaError!bool { - return hasRuntimeBitsInner(ty, false, .sema, pt.zcu, pt.tid) catch |err| switch (err) { - error.NeedLazy => unreachable, // this would require a resolve strat of lazy - else => |e| return e, - }; -} - -pub fn hasRuntimeBitsIgnoreComptime(ty: Type, zcu: *const Zcu) bool { - return hasRuntimeBitsInner(ty, true, .eager, zcu, {}) catch unreachable; -} - -pub fn hasRuntimeBitsIgnoreComptimeSema(ty: Type, pt: Zcu.PerThread) SemaError!bool { - return hasRuntimeBitsInner(ty, true, .sema, pt.zcu, pt.tid) catch |err| switch (err) { - error.NeedLazy => unreachable, // this would require a resolve strat of lazy - else => |e| return e, - }; + return .fromInterned(self.toIntern()); } /// true if and only if the type takes up space in memory at runtime. @@ -476,205 +436,126 @@ pub fn hasRuntimeBitsIgnoreComptimeSema(ty: Type, pt: Zcu.PerThread) SemaError!b /// * the type has only one possible value, making its ABI size 0. /// - an enum with an explicit tag type has the ABI size of the integer tag type, /// making it one-possible-value only if the integer tag type has 0 bits. -/// When `ignore_comptime_only` is true, then types that are comptime-only -/// may return false positives. -pub fn hasRuntimeBitsInner( - ty: Type, - ignore_comptime_only: bool, - comptime strat: ResolveStratLazy, - zcu: strat.ZcuPtr(), - tid: strat.Tid(), -) RuntimeBitsError!bool { +pub fn hasRuntimeBits(ty: Type, zcu: *const Zcu) bool { const ip = &zcu.intern_pool; - const io = zcu.comp.io; - return switch (ty.toIntern()) { - .empty_tuple_type => false, - else => switch (ip.indexToKey(ty.toIntern())) { - .int_type => |int_type| int_type.bits != 0, - .ptr_type => { - // Pointers to zero-bit types still have a runtime address; however, pointers - // to comptime-only types do not, with the exception of function pointers. - if (ignore_comptime_only) return true; - return switch (strat) { - .sema => { - const pt = strat.pt(zcu, tid); - return !try ty.comptimeOnlySema(pt); - }, - .eager => !ty.comptimeOnly(zcu), - .lazy => error.NeedLazy, - }; - }, - .anyframe_type => true, - .array_type => |array_type| return array_type.lenIncludingSentinel() > 0 and - try Type.fromInterned(array_type.child).hasRuntimeBitsInner(ignore_comptime_only, strat, zcu, tid), - .vector_type => |vector_type| return vector_type.len > 0 and - try Type.fromInterned(vector_type.child).hasRuntimeBitsInner(ignore_comptime_only, strat, zcu, tid), - .opt_type => |child| { - const child_ty = Type.fromInterned(child); - if (child_ty.isNoReturn(zcu)) { - // Then the optional is comptime-known to be null. - return false; - } - if (ignore_comptime_only) return true; - return switch (strat) { - .sema => !try child_ty.comptimeOnlyInner(.sema, zcu, tid), - .eager => !child_ty.comptimeOnly(zcu), - .lazy => error.NeedLazy, - }; - }, - .error_union_type, - .error_set_type, - .inferred_error_set_type, + return switch (ip.indexToKey(ty.toIntern())) { + .int_type => |int_type| int_type.bits != 0, + .ptr_type => true, + .anyframe_type => true, + .array_type => |array_type| array_type.lenIncludingSentinel() > 0 and + Type.fromInterned(array_type.child).hasRuntimeBits(zcu), + .vector_type => |vector_type| vector_type.len > 0 and + Type.fromInterned(vector_type.child).hasRuntimeBits(zcu), + .opt_type => |child| !Type.fromInterned(child).isNoReturn(zcu), + + .error_union_type, + .error_set_type, + .inferred_error_set_type, + => true, + + // These are function *bodies*, not pointers. + // They return false here because they are comptime-only types. + // Special exceptions have to be made when emitting functions due to + // this returning false. + .func_type => false, + + .simple_type => |t| switch (t) { + .f16, + .f32, + .f64, + .f80, + .f128, + .usize, + .isize, + .c_char, + .c_short, + .c_ushort, + .c_int, + .c_uint, + .c_long, + .c_ulong, + .c_longlong, + .c_ulonglong, + .c_longdouble, + .bool, + .anyerror, + .adhoc_inferred_error_set, + .anyopaque, => true, - // These are function *bodies*, not pointers. - // They return false here because they are comptime-only types. - // Special exceptions have to be made when emitting functions due to - // this returning false. - .func_type => false, - - .simple_type => |t| switch (t) { - .f16, - .f32, - .f64, - .f80, - .f128, - .usize, - .isize, - .c_char, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .c_longdouble, - .bool, - .anyerror, - .adhoc_inferred_error_set, - .anyopaque, - => true, - - // These are false because they are comptime-only types. - .void, - .type, - .comptime_int, - .comptime_float, - .noreturn, - .null, - .undefined, - .enum_literal, - => false, - - .generic_poison => unreachable, - }, - .struct_type => { - const struct_type = ip.loadStructType(ty.toIntern()); - if (strat != .eager and struct_type.assumeRuntimeBitsIfFieldTypesWip(ip, io)) { - // In this case, we guess that hasRuntimeBits() for this type is true, - // and then later if our guess was incorrect, we emit a compile error. - return true; - } - switch (strat) { - .sema => try ty.resolveFields(strat.pt(zcu, tid)), - .eager => assert(struct_type.haveFieldTypes(ip)), - .lazy => if (!struct_type.haveFieldTypes(ip)) return error.NeedLazy, - } - for (0..struct_type.field_types.len) |i| { - if (struct_type.comptime_bits.getBit(ip, i)) continue; - const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); - if (try field_ty.hasRuntimeBitsInner(ignore_comptime_only, strat, zcu, tid)) - return true; - } else { - return false; - } - }, - .tuple_type => |tuple| { - for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| { - if (val != .none) continue; // comptime field - if (try Type.fromInterned(field_ty).hasRuntimeBitsInner( - ignore_comptime_only, - strat, - zcu, - tid, - )) return true; - } - return false; - }, - - .union_type => { - const union_type = ip.loadUnionType(ty.toIntern()); - const union_flags = union_type.flagsUnordered(ip); - switch (union_flags.runtime_tag) { - .none => if (strat != .eager) { - // In this case, we guess that hasRuntimeBits() for this type is true, - // and then later if our guess was incorrect, we emit a compile error. - if (union_type.assumeRuntimeBitsIfFieldTypesWip(ip, io)) return true; - }, - .safety, .tagged => {}, - } - switch (strat) { - .sema => try ty.resolveFields(strat.pt(zcu, tid)), - .eager => assert(union_flags.status.haveFieldTypes()), - .lazy => if (!union_flags.status.haveFieldTypes()) - return error.NeedLazy, - } - switch (union_flags.runtime_tag) { - .none => {}, - .safety, .tagged => { - const tag_ty = union_type.tagTypeUnordered(ip); - assert(tag_ty != .none); // tag_ty should have been resolved above - if (try Type.fromInterned(tag_ty).hasRuntimeBitsInner( - ignore_comptime_only, - strat, - zcu, - tid, - )) { - return true; - } - }, - } - for (0..union_type.field_types.len) |field_index| { - const field_ty = Type.fromInterned(union_type.field_types.get(ip)[field_index]); - if (try field_ty.hasRuntimeBitsInner(ignore_comptime_only, strat, zcu, tid)) - return true; - } else { - return false; - } - }, - - .opaque_type => true, - .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).hasRuntimeBitsInner( - ignore_comptime_only, - strat, - zcu, - tid, - ), - - // values, not types - .undef, - .simple_value, - .variable, - .@"extern", - .func, - .int, - .err, - .error_union, + .void, + .noreturn, + => false, + + // primitive comptime-only types + .type, + .comptime_int, + .comptime_float, + .null, + .undefined, .enum_literal, - .enum_tag, - .empty_enum_value, - .float, - .ptr, - .slice, - .opt, - .aggregate, - .un, - // memoization, not types - .memoized_call, - => unreachable, + => false, + + .generic_poison => unreachable, }, + .struct_type => { + // TODO MLUGG: memoize this state when resolving struct? + const struct_obj = ip.loadStructType(ty.toIntern()); + for (struct_obj.field_types.get(ip), 0..) |field_ty_ip, field_idx| { + if (struct_obj.field_is_comptime_bits.get(ip, field_idx)) continue; + const field_ty: Type = .fromInterned(field_ty_ip); + if (field_ty.hasRuntimeBits(zcu)) return true; + } + return false; + }, + .tuple_type => |tuple| { + for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| { + if (val != .none) continue; // comptime field + if (Type.fromInterned(field_ty).hasRuntimeBits(zcu)) return true; + } + return false; + }, + .union_type => { + // TODO MLUGG: memoize this state when resolving union? + const union_obj = ip.loadUnionType(ty.toIntern()); + switch (union_obj.runtime_tag) { + .none => {}, + .safety, .tagged => { + if (Type.fromInterned(union_obj.enum_tag_type).hasRuntimeBits(zcu)) return true; + }, + } + for (union_obj.field_types.get(ip)) |field_ty_ip| { + const field_ty: Type = .fromInterned(field_ty_ip); + if (field_ty.hasRuntimeBits(zcu)) return true; + } + return false; + }, + + // MLUGG TODO: i think this can go away and the assert move to the defer? + .opaque_type => true, + .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).hasRuntimeBits(zcu), + + // values, not types + .undef, + .simple_value, + .variable, + .@"extern", + .func, + .int, + .err, + .error_union, + .enum_literal, + .enum_tag, + .empty_enum_value, + .float, + .ptr, + .slice, + .opt, + .aggregate, + .un, + // memoization, not types + .memoized_call, + => unreachable, }; } @@ -739,16 +620,15 @@ pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool { }, .struct_type => ip.loadStructType(ty.toIntern()).layout != .auto, .union_type => { - const union_type = ip.loadUnionType(ty.toIntern()); - return switch (union_type.flagsUnordered(ip).runtime_tag) { - .none, .safety => union_type.flagsUnordered(ip).layout != .auto, + const union_obj = ip.loadUnionType(ty.toIntern()); + if (union_obj.layout == .auto) return false; + return switch (union_obj.runtime_tag) { + .none => true, .tagged => false, + .safety => unreachable, // well-defined layout can't have a safety tag }; }, - .enum_type => switch (ip.loadEnumType(ty.toIntern()).tag_mode) { - .auto => false, - .explicit, .nonexhaustive => true, - }, + .enum_type => ip.loadEnumType(ty.toIntern()).int_tag_is_explicit, // values, not types .undef, @@ -774,28 +654,20 @@ pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool { }; } -pub fn fnHasRuntimeBits(ty: Type, zcu: *Zcu) bool { - return ty.fnHasRuntimeBitsInner(.normal, zcu, {}) catch unreachable; -} - -pub fn fnHasRuntimeBitsSema(ty: Type, pt: Zcu.PerThread) SemaError!bool { - return try ty.fnHasRuntimeBitsInner(.sema, pt.zcu, pt.tid); -} - /// Determines whether a function type has runtime bits, i.e. whether a /// function with this type can exist at runtime. /// Asserts that `ty` is a function type. -pub fn fnHasRuntimeBitsInner( - ty: Type, - comptime strat: ResolveStrat, - zcu: strat.ZcuPtr(), - tid: strat.Tid(), -) SemaError!bool { - const fn_info = zcu.typeToFunc(ty).?; - if (fn_info.is_generic) return false; - if (fn_info.is_var_args) return true; +pub fn fnHasRuntimeBits(fn_ty: Type, zcu: *Zcu) bool { + const fn_info = zcu.typeToFunc(fn_ty).?; + if (fn_info.comptime_bits != 0) return false; + for (fn_info.param_types.get(&zcu.intern_pool)) |param_ty| { + if (param_ty == .generic_poison_type) return false; + if (Type.fromInterned(param_ty).comptimeOnly(zcu)) return false; + } + if (fn_info.return_type == .generic_poison_type) return false; + if (Type.fromInterned(fn_info.return_type).comptimeOnly(zcu)) return false; if (fn_info.cc == .@"inline") return false; - return !try Type.fromInterned(fn_info.return_type).comptimeOnlyInner(strat, zcu, tid); + return true; } pub fn isFnOrHasRuntimeBits(ty: Type, zcu: *Zcu) bool { @@ -806,10 +678,11 @@ pub fn isFnOrHasRuntimeBits(ty: Type, zcu: *Zcu) bool { } /// Same as `isFnOrHasRuntimeBits` but comptime-only types may return a false positive. +/// MLUGG TODO: this function is a bit silly now... pub fn isFnOrHasRuntimeBitsIgnoreComptime(ty: Type, zcu: *Zcu) bool { return switch (ty.zigTypeTag(zcu)) { .@"fn" => true, - else => return ty.hasRuntimeBitsIgnoreComptime(zcu), + else => return ty.hasRuntimeBits(zcu), }; } @@ -818,29 +691,15 @@ pub fn isNoReturn(ty: Type, zcu: *const Zcu) bool { } /// Never returns `none`. Asserts that all necessary type resolution is already done. -pub fn ptrAlignment(ty: Type, zcu: *Zcu) Alignment { - return ptrAlignmentInner(ty, .normal, zcu, {}) catch unreachable; -} - -pub fn ptrAlignmentSema(ty: Type, pt: Zcu.PerThread) SemaError!Alignment { - return try ty.ptrAlignmentInner(.sema, pt.zcu, pt.tid); -} - -pub fn ptrAlignmentInner( - ty: Type, - comptime strat: ResolveStrat, - zcu: strat.ZcuPtr(), - tid: strat.Tid(), -) !Alignment { - return switch (zcu.intern_pool.indexToKey(ty.toIntern())) { - .ptr_type => |ptr_type| { - if (ptr_type.flags.alignment != .none) return ptr_type.flags.alignment; - const res = try Type.fromInterned(ptr_type.child).abiAlignmentInner(strat.toLazy(), zcu, tid); - return res.scalar; - }, - .opt_type => |child| Type.fromInterned(child).ptrAlignmentInner(strat, zcu, tid), +pub fn ptrAlignment(ptr_ty: Type, zcu: *Zcu) Alignment { + const ip = &zcu.intern_pool; + const ptr_key: InternPool.Key.PtrType = switch (ip.indexToKey(ptr_ty.toIntern())) { + .ptr_type => |key| key, + .opt_type => |child| ip.indexToKey(child).ptr_type, else => unreachable, }; + if (ptr_key.flags.alignment != .none) return ptr_key.flags.alignment; + return Type.fromInterned(ptr_key.child).abiAlignment(zcu); } pub fn ptrAddressSpace(ty: Type, zcu: *const Zcu) std.builtin.AddressSpace { @@ -851,861 +710,347 @@ pub fn ptrAddressSpace(ty: Type, zcu: *const Zcu) std.builtin.AddressSpace { }; } -/// May capture a reference to `ty`. -/// Returned value has type `comptime_int`. -pub fn lazyAbiAlignment(ty: Type, pt: Zcu.PerThread) !Value { - switch (try ty.abiAlignmentInner(.lazy, pt.zcu, pt.tid)) { - .val => |val| return val, - .scalar => |x| return pt.intValue(Type.comptime_int, x.toByteUnits() orelse 0), - } -} - -pub const AbiAlignmentInner = union(enum) { - scalar: Alignment, - val: Value, -}; - -pub const ResolveStratLazy = enum { - /// Return a `lazy_size` or `lazy_align` value if necessary. - /// This value can be resolved later using `Value.resolveLazy`. - lazy, - /// Return a scalar result, expecting all necessary type resolution to be completed. - /// Backends should typically use this, since they must not perform type resolution. - eager, - /// Return a scalar result, performing type resolution as necessary. - /// This should typically be used from semantic analysis. - sema, - - pub fn Tid(strat: ResolveStratLazy) type { - return switch (strat) { - .lazy, .sema => Zcu.PerThread.Id, - .eager => void, - }; - } - - pub fn ZcuPtr(strat: ResolveStratLazy) type { - return switch (strat) { - .eager => *const Zcu, - .sema, .lazy => *Zcu, - }; - } - - pub fn pt( - comptime strat: ResolveStratLazy, - zcu: strat.ZcuPtr(), - tid: strat.Tid(), - ) switch (strat) { - .lazy, .sema => Zcu.PerThread, - .eager => void, - } { - return switch (strat) { - .lazy, .sema => .{ .tid = tid, .zcu = zcu }, - else => {}, - }; - } -}; - -/// The chosen strategy can be easily optimized away in release builds. -/// However, in debug builds, it helps to avoid accidentally resolving types in backends. -pub const ResolveStrat = enum { - /// Assert that all necessary resolution is completed. - /// Backends should typically use this, since they must not perform type resolution. - normal, - /// Perform type resolution as necessary using `Zcu`. - /// This should typically be used from semantic analysis. - sema, - - pub fn Tid(strat: ResolveStrat) type { - return switch (strat) { - .sema => Zcu.PerThread.Id, - .normal => void, - }; - } - - pub fn ZcuPtr(strat: ResolveStrat) type { - return switch (strat) { - .normal => *const Zcu, - .sema => *Zcu, - }; - } - - pub fn pt(comptime strat: ResolveStrat, zcu: strat.ZcuPtr(), tid: strat.Tid()) switch (strat) { - .sema => Zcu.PerThread, - .normal => void, - } { - return switch (strat) { - .sema => .{ .tid = tid, .zcu = zcu }, - .normal => {}, - }; - } - - pub inline fn toLazy(strat: ResolveStrat) ResolveStratLazy { - return switch (strat) { - .normal => .eager, - .sema => .sema, - }; - } -}; - /// Never returns `none`. Asserts that all necessary type resolution is already done. +/// MLUGG TODO: check that it really does never return `.none` pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment { - return (ty.abiAlignmentInner(.eager, zcu, {}) catch unreachable).scalar; -} - -pub fn abiAlignmentSema(ty: Type, pt: Zcu.PerThread) SemaError!Alignment { - return (try ty.abiAlignmentInner(.sema, pt.zcu, pt.tid)).scalar; -} - -/// If you pass `eager` you will get back `scalar` and assert the type is resolved. -/// In this case there will be no error, guaranteed. -/// If you pass `lazy` you may get back `scalar` or `val`. -/// If `val` is returned, a reference to `ty` has been captured. -/// If you pass `sema` you will get back `scalar` and resolve the type if -/// necessary, possibly returning a CompileError. -pub fn abiAlignmentInner( - ty: Type, - comptime strat: ResolveStratLazy, - zcu: strat.ZcuPtr(), - tid: strat.Tid(), -) SemaError!AbiAlignmentInner { - const pt = strat.pt(zcu, tid); - const target = zcu.getTarget(); const ip = &zcu.intern_pool; - - switch (ty.toIntern()) { - .empty_tuple_type => return .{ .scalar = .@"1" }, - else => switch (ip.indexToKey(ty.toIntern())) { - .int_type => |int_type| { - if (int_type.bits == 0) return .{ .scalar = .@"1" }; - return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, int_type.bits)) }; - }, - .ptr_type, .anyframe_type => { - return .{ .scalar = ptrAbiAlignment(target) }; - }, - .array_type => |array_type| { - return Type.fromInterned(array_type.child).abiAlignmentInner(strat, zcu, tid); - }, - .vector_type => |vector_type| { - if (vector_type.len == 0) return .{ .scalar = .@"1" }; - switch (zcu.comp.getZigBackend()) { - else => { - // This is fine because the child type of a vector always has a bit-size known - // without needing any type resolution. - const elem_bits: u32 = @intCast(Type.fromInterned(vector_type.child).bitSize(zcu)); - if (elem_bits == 0) return .{ .scalar = .@"1" }; - const bytes = ((elem_bits * vector_type.len) + 7) / 8; - const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes); - return .{ .scalar = Alignment.fromByteUnits(alignment) }; - }, - .stage2_c => { - return Type.fromInterned(vector_type.child).abiAlignmentInner(strat, zcu, tid); - }, - .stage2_x86_64 => { - if (vector_type.child == .bool_type) { - if (vector_type.len > 256 and target.cpu.has(.x86, .avx512f)) return .{ .scalar = .@"64" }; - if (vector_type.len > 128 and target.cpu.has(.x86, .avx)) return .{ .scalar = .@"32" }; - if (vector_type.len > 64) return .{ .scalar = .@"16" }; - const bytes = std.math.divCeil(u32, vector_type.len, 8) catch unreachable; - const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes); - return .{ .scalar = Alignment.fromByteUnits(alignment) }; - } - const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeInner(strat, zcu, tid)).scalar); - if (elem_bytes == 0) return .{ .scalar = .@"1" }; - const bytes = elem_bytes * vector_type.len; - if (bytes > 32 and target.cpu.has(.x86, .avx512f)) return .{ .scalar = .@"64" }; - if (bytes > 16 and target.cpu.has(.x86, .avx)) return .{ .scalar = .@"32" }; - return .{ .scalar = .@"16" }; - }, - } - }, - - .opt_type => return ty.abiAlignmentInnerOptional(strat, zcu, tid), - .error_union_type => |info| return ty.abiAlignmentInnerErrorUnion( - strat, - zcu, - tid, - Type.fromInterned(info.payload_type), - ), - - .error_set_type, .inferred_error_set_type => { - const bits = zcu.errorSetBits(); - if (bits == 0) return .{ .scalar = .@"1" }; - return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, bits)) }; - }, - - // represents machine code; not a pointer - .func_type => return .{ .scalar = target_util.minFunctionAlignment(target) }, - - .simple_type => |t| switch (t) { - .bool, - .anyopaque, - => return .{ .scalar = .@"1" }, - - .usize, - .isize, - => return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())) }, - - .c_char => return .{ .scalar = cTypeAlign(target, .char) }, - .c_short => return .{ .scalar = cTypeAlign(target, .short) }, - .c_ushort => return .{ .scalar = cTypeAlign(target, .ushort) }, - .c_int => return .{ .scalar = cTypeAlign(target, .int) }, - .c_uint => return .{ .scalar = cTypeAlign(target, .uint) }, - .c_long => return .{ .scalar = cTypeAlign(target, .long) }, - .c_ulong => return .{ .scalar = cTypeAlign(target, .ulong) }, - .c_longlong => return .{ .scalar = cTypeAlign(target, .longlong) }, - .c_ulonglong => return .{ .scalar = cTypeAlign(target, .ulonglong) }, - .c_longdouble => return .{ .scalar = cTypeAlign(target, .longdouble) }, - - .f16 => return .{ .scalar = .@"2" }, - .f32 => return .{ .scalar = cTypeAlign(target, .float) }, - .f64 => switch (target.cTypeBitSize(.double)) { - 64 => return .{ .scalar = cTypeAlign(target, .double) }, - else => return .{ .scalar = .@"8" }, - }, - .f80 => switch (target.cTypeBitSize(.longdouble)) { - 80 => return .{ .scalar = cTypeAlign(target, .longdouble) }, - else => return .{ .scalar = Type.u80.abiAlignment(zcu) }, + const target = zcu.getTarget(); + assertHasLayout(ty, zcu); + return switch (ip.indexToKey(ty.toIntern())) { + .int_type => |int_type| { + if (int_type.bits == 0) return .@"1"; + return .fromByteUnits(std.zig.target.intAlignment(target, int_type.bits)); + }, + .ptr_type, .anyframe_type => ptrAbiAlignment(target), + .array_type => |array_type| Type.fromInterned(array_type.child).abiAlignment(zcu), + .vector_type => |vector_type| { + if (vector_type.len == 0) return .@"1"; + switch (zcu.comp.getZigBackend()) { + else => { + const elem_bits: u32 = @intCast(Type.fromInterned(vector_type.child).bitSize(zcu)); + if (elem_bits == 0) return .@"1"; + const bytes = ((elem_bits * vector_type.len) + 7) / 8; + return .fromByteUnits(std.math.ceilPowerOfTwoAssert(u32, bytes)); }, - .f128 => switch (target.cTypeBitSize(.longdouble)) { - 128 => return .{ .scalar = cTypeAlign(target, .longdouble) }, - else => return .{ .scalar = .@"16" }, - }, - - .anyerror, .adhoc_inferred_error_set => { - const bits = zcu.errorSetBits(); - if (bits == 0) return .{ .scalar = .@"1" }; - return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, bits)) }; - }, - - .void, - .type, - .comptime_int, - .comptime_float, - .null, - .undefined, - .enum_literal, - => return .{ .scalar = .@"1" }, - - .noreturn => unreachable, - .generic_poison => unreachable, - }, - .struct_type => { - const struct_type = ip.loadStructType(ty.toIntern()); - if (struct_type.layout == .@"packed") { - switch (strat) { - .sema => try ty.resolveLayout(pt), - .lazy => if (struct_type.backingIntTypeUnordered(ip) == .none) return .{ - .val = Value.fromInterned(try pt.intern(.{ .int = .{ - .ty = .comptime_int_type, - .storage = .{ .lazy_align = ty.toIntern() }, - } })), - }, - .eager => {}, - } - return .{ .scalar = Type.fromInterned(struct_type.backingIntTypeUnordered(ip)).abiAlignment(zcu) }; - } - - if (struct_type.flagsUnordered(ip).alignment == .none) switch (strat) { - .eager => unreachable, // struct alignment not resolved - .sema => try ty.resolveStructAlignment(pt), - .lazy => return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ - .ty = .comptime_int_type, - .storage = .{ .lazy_align = ty.toIntern() }, - } })) }, - }; - - return .{ .scalar = struct_type.flagsUnordered(ip).alignment }; - }, - .tuple_type => |tuple| { - var big_align: Alignment = .@"1"; - for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| { - if (val != .none) continue; // comptime field - switch (try Type.fromInterned(field_ty).abiAlignmentInner(strat, zcu, tid)) { - .scalar => |field_align| big_align = big_align.max(field_align), - .val => switch (strat) { - .eager => unreachable, // field type alignment not resolved - .sema => unreachable, // passed to abiAlignmentInner above - .lazy => return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ - .ty = .comptime_int_type, - .storage = .{ .lazy_align = ty.toIntern() }, - } })) }, - }, + .stage2_c => return Type.fromInterned(vector_type.child).abiAlignment(zcu), + .stage2_x86_64 => { + if (vector_type.child == .bool_type) { + if (vector_type.len > 256 and target.cpu.has(.x86, .avx512f)) return .@"64"; + if (vector_type.len > 128 and target.cpu.has(.x86, .avx)) return .@"32"; + if (vector_type.len > 64) return .@"16"; + const bytes = std.math.divCeil(u32, vector_type.len, 8) catch unreachable; + return .fromByteUnits(std.math.ceilPowerOfTwoAssert(u32, bytes)); } - } - return .{ .scalar = big_align }; - }, - .union_type => { - const union_type = ip.loadUnionType(ty.toIntern()); - - if (union_type.flagsUnordered(ip).alignment == .none) switch (strat) { - .eager => unreachable, // union layout not resolved - .sema => try ty.resolveUnionAlignment(pt), - .lazy => return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ - .ty = .comptime_int_type, - .storage = .{ .lazy_align = ty.toIntern() }, - } })) }, - }; - - return .{ .scalar = union_type.flagsUnordered(ip).alignment }; - }, - .opaque_type => return .{ .scalar = .@"1" }, - .enum_type => return .{ - .scalar = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).abiAlignment(zcu), - }, - - // values, not types - .undef, - .simple_value, - .variable, - .@"extern", - .func, - .int, - .err, - .error_union, + const elem_bytes: u32 = @intCast(Type.fromInterned(vector_type.child).abiSize(zcu)); + if (elem_bytes == 0) return .@"1"; + const bytes = elem_bytes * vector_type.len; + if (bytes > 32 and target.cpu.has(.x86, .avx512f)) return .@"64"; + if (bytes > 16 and target.cpu.has(.x86, .avx)) return .@"32"; + return .@"16"; + }, + } + }, + + .opt_type => |child| Type.fromInterned(child).abiAlignment(zcu), + .error_union_type => |eu| Alignment.maxStrict( + Type.fromInterned(eu.payload_type).abiAlignment(zcu), + errorAbiAlignment(zcu), + ), + + .error_set_type, .inferred_error_set_type => errorAbiAlignment(zcu), + + .func_type => target_util.minFunctionAlignment(target), + + .simple_type => |t| switch (t) { + .bool, + .void, + .noreturn, + .anyopaque, + .type, + .comptime_int, + .comptime_float, + .null, + .undefined, .enum_literal, - .enum_tag, - .empty_enum_value, - .float, - .ptr, - .slice, - .opt, - .aggregate, - .un, - // memoization, not types - .memoized_call, - => unreachable, - }, - } -} + => .@"1", -fn abiAlignmentInnerErrorUnion( - ty: Type, - comptime strat: ResolveStratLazy, - zcu: strat.ZcuPtr(), - tid: strat.Tid(), - payload_ty: Type, -) SemaError!AbiAlignmentInner { - // This code needs to be kept in sync with the equivalent switch prong - // in abiSizeInner. - const code_align = Type.anyerror.abiAlignment(zcu); - switch (strat) { - .eager, .sema => { - if (!(payload_ty.hasRuntimeBitsInner(false, strat, zcu, tid) catch |err| switch (err) { - error.NeedLazy => if (strat == .lazy) { - const pt = strat.pt(zcu, tid); - return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ - .ty = .comptime_int_type, - .storage = .{ .lazy_align = ty.toIntern() }, - } })) }; - } else unreachable, - else => |e| return e, - })) { - return .{ .scalar = code_align }; - } - return .{ .scalar = code_align.max( - (try payload_ty.abiAlignmentInner(strat, zcu, tid)).scalar, - ) }; - }, - .lazy => { - const pt = strat.pt(zcu, tid); - switch (try payload_ty.abiAlignmentInner(strat, zcu, tid)) { - .scalar => |payload_align| return .{ .scalar = code_align.max(payload_align) }, - .val => {}, - } - return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ - .ty = .comptime_int_type, - .storage = .{ .lazy_align = ty.toIntern() }, - } })) }; - }, - } -} + .anyerror, .adhoc_inferred_error_set => errorAbiAlignment(zcu), + .usize, .isize => .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())), -fn abiAlignmentInnerOptional( - ty: Type, - comptime strat: ResolveStratLazy, - zcu: strat.ZcuPtr(), - tid: strat.Tid(), -) SemaError!AbiAlignmentInner { - const pt = strat.pt(zcu, tid); - const target = zcu.getTarget(); - const child_type = ty.optionalChild(zcu); + .c_char => cTypeAlign(target, .char), + .c_short => cTypeAlign(target, .short), + .c_ushort => cTypeAlign(target, .ushort), + .c_int => cTypeAlign(target, .int), + .c_uint => cTypeAlign(target, .uint), + .c_long => cTypeAlign(target, .long), + .c_ulong => cTypeAlign(target, .ulong), + .c_longlong => cTypeAlign(target, .longlong), + .c_ulonglong => cTypeAlign(target, .ulonglong), + .c_longdouble => cTypeAlign(target, .longdouble), - switch (child_type.zigTypeTag(zcu)) { - .pointer => return .{ .scalar = ptrAbiAlignment(target) }, - .error_set => return Type.anyerror.abiAlignmentInner(strat, zcu, tid), - .noreturn => return .{ .scalar = .@"1" }, - else => {}, - } + .f16 => .@"2", + .f32 => cTypeAlign(target, .float), + .f64 => switch (target.cTypeBitSize(.double)) { + 64 => cTypeAlign(target, .double), + else => .@"8", + }, + .f80 => switch (target.cTypeBitSize(.longdouble)) { + 80 => cTypeAlign(target, .longdouble), + else => Type.u80.abiAlignment(zcu), + }, + .f128 => switch (target.cTypeBitSize(.longdouble)) { + 128 => cTypeAlign(target, .longdouble), + else => .@"16", + }, - switch (strat) { - .eager, .sema => { - if (!(child_type.hasRuntimeBitsInner(false, strat, zcu, tid) catch |err| switch (err) { - error.NeedLazy => if (strat == .lazy) { - return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ - .ty = .comptime_int_type, - .storage = .{ .lazy_align = ty.toIntern() }, - } })) }; - } else unreachable, - else => |e| return e, - })) { - return .{ .scalar = .@"1" }; + .generic_poison => unreachable, + }, + .tuple_type => |tuple| { + var big_align: Alignment = .@"1"; + for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| { + if (val != .none) continue; // comptime field + const field_align = Type.fromInterned(field_ty).abiAlignment(zcu); + big_align = big_align.max(field_align); } - return child_type.abiAlignmentInner(strat, zcu, tid); + return big_align; }, - .lazy => switch (try child_type.abiAlignmentInner(strat, zcu, tid)) { - .scalar => |x| return .{ .scalar = x.max(.@"1") }, - .val => return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ - .ty = .comptime_int_type, - .storage = .{ .lazy_align = ty.toIntern() }, - } })) }, + .struct_type => { + const struct_obj = ip.loadStructType(ty.toIntern()); + switch (struct_obj.layout) { + .@"packed" => return Type.fromInterned(struct_obj.packed_backing_int_type).abiAlignment(zcu), + .auto, .@"extern" => return struct_obj.alignment, + } }, - } -} + .union_type => { + const union_obj = ip.loadUnionType(ty.toIntern()); + switch (union_obj.layout) { + .@"packed" => return Type.fromInterned(union_obj.packed_backing_int_type).abiAlignment(zcu), + .auto, .@"extern" => return getUnionLayout(union_obj, zcu).abi_align, + } + }, + .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).abiAlignment(zcu), + .opaque_type => .@"1", -const AbiSizeInner = union(enum) { - scalar: u64, - val: Value, -}; + // values, not types + .undef, + .simple_value, + .variable, + .@"extern", + .func, + .int, + .err, + .error_union, + .enum_literal, + .enum_tag, + .empty_enum_value, + .float, + .ptr, + .slice, + .opt, + .aggregate, + .un, + // memoization, not types + .memoized_call, + => unreachable, + }; +} -/// Asserts the type has the ABI size already resolved. -/// Types that return false for hasRuntimeBits() return 0. +/// Asserts that `ty` is not an opaque type. pub fn abiSize(ty: Type, zcu: *const Zcu) u64 { - return (abiSizeInner(ty, .eager, zcu, {}) catch unreachable).scalar; -} - -/// May capture a reference to `ty`. -pub fn abiSizeLazy(ty: Type, pt: Zcu.PerThread) !Value { - switch (try ty.abiSizeInner(.lazy, pt.zcu, pt.tid)) { - .val => |val| return val, - .scalar => |x| return pt.intValue(Type.comptime_int, x), - } -} - -pub fn abiSizeSema(ty: Type, pt: Zcu.PerThread) SemaError!u64 { - return (try abiSizeInner(ty, .sema, pt.zcu, pt.tid)).scalar; -} - -/// If you pass `eager` you will get back `scalar` and assert the type is resolved. -/// In this case there will be no error, guaranteed. -/// If you pass `lazy` you may get back `scalar` or `val`. -/// If `val` is returned, a reference to `ty` has been captured. -/// If you pass `sema` you will get back `scalar` and resolve the type if -/// necessary, possibly returning a CompileError. -pub fn abiSizeInner( - ty: Type, - comptime strat: ResolveStratLazy, - zcu: strat.ZcuPtr(), - tid: strat.Tid(), -) SemaError!AbiSizeInner { - const target = zcu.getTarget(); const ip = &zcu.intern_pool; - - switch (ty.toIntern()) { - .empty_tuple_type => return .{ .scalar = 0 }, - - else => switch (ip.indexToKey(ty.toIntern())) { - .int_type => |int_type| { - if (int_type.bits == 0) return .{ .scalar = 0 }; - return .{ .scalar = std.zig.target.intByteSize(target, int_type.bits) }; - }, - .ptr_type => |ptr_type| switch (ptr_type.flags.size) { - .slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 }, - else => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) }, - }, - .anyframe_type => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) }, - - .array_type => |array_type| { - const len = array_type.lenIncludingSentinel(); - if (len == 0) return .{ .scalar = 0 }; - switch (try Type.fromInterned(array_type.child).abiSizeInner(strat, zcu, tid)) { - .scalar => |elem_size| return .{ .scalar = len * elem_size }, - .val => switch (strat) { - .sema, .eager => unreachable, - .lazy => { - const pt = strat.pt(zcu, tid); - return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ - .ty = .comptime_int_type, - .storage = .{ .lazy_size = ty.toIntern() }, - } })) }; - }, - }, - } - }, - .vector_type => |vector_type| { - const sub_strat: ResolveStrat = switch (strat) { - .sema => .sema, - .eager => .normal, - .lazy => { - const pt = strat.pt(zcu, tid); - return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ - .ty = .comptime_int_type, - .storage = .{ .lazy_size = ty.toIntern() }, - } })) }; - }, - }; - const alignment = (try ty.abiAlignmentInner(strat, zcu, tid)).scalar; - const total_bytes = switch (zcu.comp.getZigBackend()) { - else => total_bytes: { - const elem_bits = try Type.fromInterned(vector_type.child).bitSizeInner(sub_strat, zcu, tid); - const total_bits = elem_bits * vector_type.len; - break :total_bytes (total_bits + 7) / 8; - }, - .stage2_c => total_bytes: { - const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeInner(strat, zcu, tid)).scalar); - break :total_bytes elem_bytes * vector_type.len; - }, - .stage2_x86_64 => total_bytes: { - if (vector_type.child == .bool_type) break :total_bytes std.math.divCeil(u32, vector_type.len, 8) catch unreachable; - const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeInner(strat, zcu, tid)).scalar); - break :total_bytes elem_bytes * vector_type.len; - }, - }; - return .{ .scalar = alignment.forward(total_bytes) }; - }, - - .opt_type => return ty.abiSizeInnerOptional(strat, zcu, tid), - - .error_set_type, .inferred_error_set_type => { - const bits = zcu.errorSetBits(); - if (bits == 0) return .{ .scalar = 0 }; - return .{ .scalar = std.zig.target.intByteSize(target, bits) }; - }, - - .error_union_type => |error_union_type| { - const payload_ty = Type.fromInterned(error_union_type.payload_type); - // This code needs to be kept in sync with the equivalent switch prong - // in abiAlignmentInner. - const code_size = Type.anyerror.abiSize(zcu); - if (!(payload_ty.hasRuntimeBitsInner(false, strat, zcu, tid) catch |err| switch (err) { - error.NeedLazy => if (strat == .lazy) { - const pt = strat.pt(zcu, tid); - return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ - .ty = .comptime_int_type, - .storage = .{ .lazy_size = ty.toIntern() }, - } })) }; - } else unreachable, - else => |e| return e, - })) { - // Same as anyerror. - return .{ .scalar = code_size }; - } - const code_align = Type.anyerror.abiAlignment(zcu); - const payload_align = (try payload_ty.abiAlignmentInner(strat, zcu, tid)).scalar; - const payload_size = switch (try payload_ty.abiSizeInner(strat, zcu, tid)) { - .scalar => |elem_size| elem_size, - .val => switch (strat) { - .sema => unreachable, - .eager => unreachable, - .lazy => { - const pt = strat.pt(zcu, tid); - return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ - .ty = .comptime_int_type, - .storage = .{ .lazy_size = ty.toIntern() }, - } })) }; - }, - }, - }; - - var size: u64 = 0; - if (code_align.compare(.gt, payload_align)) { - size += code_size; - size = payload_align.forward(size); - size += payload_size; - size = code_align.forward(size); - } else { - size += payload_size; - size = code_align.forward(size); - size += code_size; - size = payload_align.forward(size); - } - return .{ .scalar = size }; - }, - .func_type => unreachable, // represents machine code; not a pointer - .simple_type => |t| switch (t) { - .bool => return .{ .scalar = 1 }, - - .f16 => return .{ .scalar = 2 }, - .f32 => return .{ .scalar = 4 }, - .f64 => return .{ .scalar = 8 }, - .f128 => return .{ .scalar = 16 }, - .f80 => switch (target.cTypeBitSize(.longdouble)) { - 80 => return .{ .scalar = target.cTypeByteSize(.longdouble) }, - else => return .{ .scalar = Type.u80.abiSize(zcu) }, + const target = zcu.getTarget(); + assertHasLayout(ty, zcu); + return switch (ip.indexToKey(ty.toIntern())) { + .int_type => |int_type| std.zig.target.intByteSize(target, int_type.bits), + .ptr_type => |ptr_type| switch (ptr_type.flags.size) { + .slice => ptrAbiSize(target) * 2, + .one, .many, .c => ptrAbiSize(target), + }, + .anyframe_type => ptrAbiSize(target), + .array_type => |arr| arr.lenIncludingSentinel() * Type.fromInterned(arr.child).abiSize(zcu), + .vector_type => |vec| { + const elem_ty: Type = .fromInterned(vec.child); + const bytes = switch (zcu.comp.getZigBackend()) { + else => std.math.divCeil(u64, vec.len * elem_ty.bitSize(zcu), 8) catch unreachable, + .stage2_c => vec.len * elem_ty.abiSize(zcu), + .stage2_x86_64 => switch (elem_ty.toIntern()) { + .bool_type => std.math.divCeil(u64, vec.len, 8) catch unreachable, + else => vec.len * elem_ty.abiSize(zcu), }, - - .usize, - .isize, - => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) }, - - .c_char => return .{ .scalar = target.cTypeByteSize(.char) }, - .c_short => return .{ .scalar = target.cTypeByteSize(.short) }, - .c_ushort => return .{ .scalar = target.cTypeByteSize(.ushort) }, - .c_int => return .{ .scalar = target.cTypeByteSize(.int) }, - .c_uint => return .{ .scalar = target.cTypeByteSize(.uint) }, - .c_long => return .{ .scalar = target.cTypeByteSize(.long) }, - .c_ulong => return .{ .scalar = target.cTypeByteSize(.ulong) }, - .c_longlong => return .{ .scalar = target.cTypeByteSize(.longlong) }, - .c_ulonglong => return .{ .scalar = target.cTypeByteSize(.ulonglong) }, - .c_longdouble => return .{ .scalar = target.cTypeByteSize(.longdouble) }, - - .anyopaque, - .void, - .type, - .comptime_int, - .comptime_float, - .null, - .undefined, - .enum_literal, - => return .{ .scalar = 0 }, - - .anyerror, .adhoc_inferred_error_set => { - const bits = zcu.errorSetBits(); - if (bits == 0) return .{ .scalar = 0 }; - return .{ .scalar = std.zig.target.intByteSize(target, bits) }; - }, - - .noreturn => unreachable, - .generic_poison => unreachable, - }, - .struct_type => { - const struct_type = ip.loadStructType(ty.toIntern()); - switch (strat) { - .sema => try ty.resolveLayout(strat.pt(zcu, tid)), - .lazy => { - const pt = strat.pt(zcu, tid); - switch (struct_type.layout) { - .@"packed" => { - if (struct_type.backingIntTypeUnordered(ip) == .none) return .{ - .val = Value.fromInterned(try pt.intern(.{ .int = .{ - .ty = .comptime_int_type, - .storage = .{ .lazy_size = ty.toIntern() }, - } })), - }; - }, - .auto, .@"extern" => { - if (!struct_type.haveLayout(ip)) return .{ - .val = Value.fromInterned(try pt.intern(.{ .int = .{ - .ty = .comptime_int_type, - .storage = .{ .lazy_size = ty.toIntern() }, - } })), - }; - }, - } - }, - .eager => {}, - } - switch (struct_type.layout) { - .@"packed" => return .{ - .scalar = Type.fromInterned(struct_type.backingIntTypeUnordered(ip)).abiSize(zcu), - }, - .auto, .@"extern" => { - assert(struct_type.haveLayout(ip)); - return .{ .scalar = struct_type.sizeUnordered(ip) }; - }, - } - }, - .tuple_type => |tuple| { - switch (strat) { - .sema => try ty.resolveLayout(strat.pt(zcu, tid)), - .lazy, .eager => {}, - } - const field_count = tuple.types.len; - if (field_count == 0) { - return .{ .scalar = 0 }; - } - return .{ .scalar = ty.structFieldOffset(field_count, zcu) }; - }, - - .union_type => { - const union_type = ip.loadUnionType(ty.toIntern()); - switch (strat) { - .sema => try ty.resolveLayout(strat.pt(zcu, tid)), - .lazy => { - const pt = strat.pt(zcu, tid); - if (!union_type.flagsUnordered(ip).status.haveLayout()) return .{ - .val = Value.fromInterned(try pt.intern(.{ .int = .{ - .ty = .comptime_int_type, - .storage = .{ .lazy_size = ty.toIntern() }, - } })), - }; - }, - .eager => {}, - } - - assert(union_type.haveLayout(ip)); - return .{ .scalar = union_type.sizeUnordered(ip) }; - }, - .opaque_type => unreachable, // no size available - .enum_type => return .{ .scalar = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).abiSize(zcu) }, - - // values, not types - .undef, - .simple_value, - .variable, - .@"extern", - .func, - .int, - .err, - .error_union, + }; + return ty.abiAlignment(zcu).forward(bytes); + }, + .opt_type => |child_ty_ip| { + const child_ty: Type = .fromInterned(child_ty_ip); + if (child_ty.isNoReturn(zcu)) return 0; + const child_size = child_ty.abiSize(zcu); + if (ty.optionalReprIsPayload(zcu)) return child_size; + // Optional types are represented as a struct with the child type as the first + // field and a boolean as the second. Since the child type's abi alignment is + // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal + // to the child type's ABI alignment. + return child_size + child_ty.abiAlignment(zcu).toByteUnits().?; + }, + .error_set_type, .inferred_error_set_type => errorAbiSize(zcu), + .error_union_type => |error_union| { + const payload_ty: Type = .fromInterned(error_union.payload_type); + // This code needs to be kept in sync with the equivalent switch prong + // in abiAlignmentInner. + const code_size = errorAbiSize(zcu); + const code_align = errorAbiAlignment(zcu); + const payload_size = payload_ty.abiSize(zcu); + const payload_align = payload_ty.abiAlignment(zcu); + // The layout will either be (code, payload, padding) or (payload, code, padding) + // depending on which has larger alignment. So the overall size is just the code + // and payload sizes added and padded to the larger alignment. + const big_align = code_align.maxStrict(payload_align); + return big_align.forward(payload_size + code_size); + }, + .func_type => 0, + .simple_type => |t| switch (t) { + .void, + .noreturn, + .type, + .comptime_int, + .comptime_float, + .null, + .undefined, .enum_literal, - .enum_tag, - .empty_enum_value, - .float, - .ptr, - .slice, - .opt, - .aggregate, - .un, - // memoization, not types - .memoized_call, - => unreachable, - }, - } -} - -fn abiSizeInnerOptional( - ty: Type, - comptime strat: ResolveStratLazy, - zcu: strat.ZcuPtr(), - tid: strat.Tid(), -) SemaError!AbiSizeInner { - const child_ty = ty.optionalChild(zcu); + => 0, - if (child_ty.isNoReturn(zcu)) { - return .{ .scalar = 0 }; - } + .bool => 1, + .anyerror, .adhoc_inferred_error_set => errorAbiSize(zcu), + .usize, .isize => ptrAbiSize(target), - if (!(child_ty.hasRuntimeBitsInner(false, strat, zcu, tid) catch |err| switch (err) { - error.NeedLazy => if (strat == .lazy) { - const pt = strat.pt(zcu, tid); - return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{ - .ty = .comptime_int_type, - .storage = .{ .lazy_size = ty.toIntern() }, - } })) }; - } else unreachable, - else => |e| return e, - })) return .{ .scalar = 1 }; + .c_char => target.cTypeByteSize(.char), + .c_short => target.cTypeByteSize(.short), + .c_ushort => target.cTypeByteSize(.ushort), + .c_int => target.cTypeByteSize(.int), + .c_uint => target.cTypeByteSize(.uint), + .c_long => target.cTypeByteSize(.long), + .c_ulong => target.cTypeByteSize(.ulong), + .c_longlong => target.cTypeByteSize(.longlong), + .c_ulonglong => target.cTypeByteSize(.ulonglong), + .c_longdouble => target.cTypeByteSize(.longdouble), - if (ty.optionalReprIsPayload(zcu)) { - return child_ty.abiSizeInner(strat, zcu, tid); - } + .f16 => 2, + .f32 => 4, + .f64 => 8, + .f80 => switch (target.cTypeBitSize(.longdouble)) { + 80 => target.cTypeByteSize(.longdouble), + else => Type.u80.abiSize(zcu), + }, + .f128 => 16, - const payload_size = switch (try child_ty.abiSizeInner(strat, zcu, tid)) { - .scalar => |elem_size| elem_size, - .val => switch (strat) { - .sema => unreachable, - .eager => unreachable, - .lazy => return .{ .val = Value.fromInterned(try strat.pt(zcu, tid).intern(.{ .int = .{ - .ty = .comptime_int_type, - .storage = .{ .lazy_size = ty.toIntern() }, - } })) }, + .anyopaque => unreachable, + .generic_poison => unreachable, + }, + .tuple_type => |tuple| ty.structFieldOffset(tuple.types.len, zcu), + .struct_type => { + const struct_obj = ip.loadStructType(ty.toIntern()); + switch (struct_obj.layout) { + .@"packed" => return Type.fromInterned(struct_obj.packed_backing_int_type).abiSize(zcu), + .auto, .@"extern" => return struct_obj.size, + } + }, + .union_type => { + const union_obj = ip.loadUnionType(ty.toIntern()); + switch (union_obj.layout) { + .@"packed" => return Type.fromInterned(union_obj.packed_backing_int_type).abiSize(zcu), + .auto, .@"extern" => return union_obj.size, + } }, - }; + .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).abiSize(zcu), + .opaque_type => unreachable, - // Optional types are represented as a struct with the child type as the first - // field and a boolean as the second. Since the child type's abi alignment is - // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal - // to the child type's ABI alignment. - return .{ - .scalar = (child_ty.abiAlignment(zcu).toByteUnits() orelse 0) + payload_size, + // values, not types + .undef, + .simple_value, + .variable, + .@"extern", + .func, + .int, + .err, + .error_union, + .enum_literal, + .enum_tag, + .empty_enum_value, + .float, + .ptr, + .slice, + .opt, + .aggregate, + .un, + // memoization, not types + .memoized_call, + => unreachable, }; } pub fn ptrAbiAlignment(target: *const Target) Alignment { - return Alignment.fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8)); + return .fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8)); +} +pub fn ptrAbiSize(target: *const Target) u64 { + return @divExact(target.ptrBitWidth(), 8); +} +pub fn errorAbiAlignment(zcu: *const Zcu) Alignment { + return .fromNonzeroByteUnits(std.zig.target.intAlignment(zcu.getTarget(), zcu.errorSetBits())); +} +pub fn errorAbiSize(zcu: *const Zcu) u64 { + return std.zig.target.intByteSize(zcu.getTarget(), zcu.errorSetBits()); } +/// Asserts that `ty` is not an opaque or comptime-only type. +/// Once #19755 is implemented, this query will only work on types with a defined bit-level representation. pub fn bitSize(ty: Type, zcu: *const Zcu) u64 { - return bitSizeInner(ty, .normal, zcu, {}) catch unreachable; -} - -pub fn bitSizeSema(ty: Type, pt: Zcu.PerThread) SemaError!u64 { - return bitSizeInner(ty, .sema, pt.zcu, pt.tid); -} - -pub fn bitSizeInner( - ty: Type, - comptime strat: ResolveStrat, - zcu: strat.ZcuPtr(), - tid: strat.Tid(), -) SemaError!u64 { const target = zcu.getTarget(); const ip = &zcu.intern_pool; - - const strat_lazy: ResolveStratLazy = strat.toLazy(); - - switch (ip.indexToKey(ty.toIntern())) { - .int_type => |int_type| return int_type.bits, + assertHasLayout(ty, zcu); + return switch (ip.indexToKey(ty.toIntern())) { + .int_type => |int_type| int_type.bits, .ptr_type => |ptr_type| switch (ptr_type.flags.size) { - .slice => return target.ptrBitWidth() * 2, - else => return target.ptrBitWidth(), + .slice => target.ptrBitWidth() * 2, + else => target.ptrBitWidth(), }, - .anyframe_type => return target.ptrBitWidth(), - + .anyframe_type => target.ptrBitWidth(), .array_type => |array_type| { - const len = array_type.lenIncludingSentinel(); - if (len == 0) return 0; const elem_ty: Type = .fromInterned(array_type.child); - switch (zcu.comp.getZigBackend()) { - else => { - const elem_size = (try elem_ty.abiSizeInner(strat_lazy, zcu, tid)).scalar; - if (elem_size == 0) return 0; - const elem_bit_size = try elem_ty.bitSizeInner(strat, zcu, tid); - return (len - 1) * 8 * elem_size + elem_bit_size; + const len = array_type.lenIncludingSentinel(); + return switch (zcu.comp.getZigBackend()) { + .stage2_x86_64 => len * elem_ty.bitSize(zcu), + // this case will be removed under #19755 + else => switch (len) { + 0 => 0, + else => (len - 1) * 8 * elem_ty.abiSize(zcu) + elem_ty.bitSize(zcu), }, - .stage2_x86_64 => { - const elem_bit_size = try elem_ty.bitSizeInner(strat, zcu, tid); - return elem_bit_size * len; - }, - } - }, - .vector_type => |vector_type| { - const child_ty: Type = .fromInterned(vector_type.child); - const elem_bit_size = try child_ty.bitSizeInner(strat, zcu, tid); - return elem_bit_size * vector_type.len; - }, - .opt_type => { - // Optionals and error unions are not packed so their bitsize - // includes padding bits. - return (try ty.abiSizeInner(strat_lazy, zcu, tid)).scalar * 8; + }; }, + .vector_type => |vec| vec.len * Type.fromInterned(vec.child).bitSize(zcu), + .error_set_type, .inferred_error_set_type => zcu.errorSetBits(), + .func_type => unreachable, - .error_set_type, .inferred_error_set_type => return zcu.errorSetBits(), - - .error_union_type => { - // Optionals and error unions are not packed so their bitsize - // includes padding bits. - return (try ty.abiSizeInner(strat_lazy, zcu, tid)).scalar * 8; - }, - .func_type => unreachable, // represents machine code; not a pointer .simple_type => |t| switch (t) { - .f16 => return 16, - .f32 => return 32, - .f64 => return 64, - .f80 => return 80, - .f128 => return 128, + .void => 0, + .bool => 1, + .anyerror, .adhoc_inferred_error_set => zcu.errorSetBits(), + .usize, .isize => target.ptrBitWidth(), - .usize, - .isize, - => return target.ptrBitWidth(), + .c_char => target.cTypeBitSize(.char), + .c_short => target.cTypeBitSize(.short), + .c_ushort => target.cTypeBitSize(.ushort), + .c_int => target.cTypeBitSize(.int), + .c_uint => target.cTypeBitSize(.uint), + .c_long => target.cTypeBitSize(.long), + .c_ulong => target.cTypeBitSize(.ulong), + .c_longlong => target.cTypeBitSize(.longlong), + .c_ulonglong => target.cTypeBitSize(.ulonglong), + .c_longdouble => target.cTypeBitSize(.longdouble), - .c_char => return target.cTypeBitSize(.char), - .c_short => return target.cTypeBitSize(.short), - .c_ushort => return target.cTypeBitSize(.ushort), - .c_int => return target.cTypeBitSize(.int), - .c_uint => return target.cTypeBitSize(.uint), - .c_long => return target.cTypeBitSize(.long), - .c_ulong => return target.cTypeBitSize(.ulong), - .c_longlong => return target.cTypeBitSize(.longlong), - .c_ulonglong => return target.cTypeBitSize(.ulonglong), - .c_longdouble => return target.cTypeBitSize(.longdouble), - - .bool => return 1, - .void => return 0, - - .anyerror, - .adhoc_inferred_error_set, - => return zcu.errorSetBits(), + .f16 => 16, + .f32 => 32, + .f64 => 64, + .f80 => 80, + .f128 => 128, .anyopaque => unreachable, .type => unreachable, @@ -1717,49 +1062,30 @@ pub fn bitSizeInner( .enum_literal => unreachable, .generic_poison => unreachable, }, + .struct_type => { - const struct_type = ip.loadStructType(ty.toIntern()); - const is_packed = struct_type.layout == .@"packed"; - if (strat == .sema) { - const pt = strat.pt(zcu, tid); - try ty.resolveFields(pt); - if (is_packed) try ty.resolveLayout(pt); + const struct_obj = ip.loadStructType(ty.toIntern()); + switch (struct_obj.layout) { + .@"packed" => return Type.fromInterned(struct_obj.packed_backing_int_type).bitSize(zcu), + .auto, .@"extern" => return struct_obj.size * 8, // will be `unreachable` under #19755 } - if (is_packed) { - return try Type.fromInterned(struct_type.backingIntTypeUnordered(ip)) - .bitSizeInner(strat, zcu, tid); - } - return (try ty.abiSizeInner(strat_lazy, zcu, tid)).scalar * 8; - }, - - .tuple_type => { - return (try ty.abiSizeInner(strat_lazy, zcu, tid)).scalar * 8; }, - .union_type => { - const union_type = ip.loadUnionType(ty.toIntern()); - const is_packed = ty.containerLayout(zcu) == .@"packed"; - if (strat == .sema) { - const pt = strat.pt(zcu, tid); - try ty.resolveFields(pt); - if (is_packed) try ty.resolveLayout(pt); + const union_obj = ip.loadUnionType(ty.toIntern()); + switch (union_obj.layout) { + .@"packed" => return Type.fromInterned(union_obj.packed_backing_int_type).bitSize(zcu), + .auto, .@"extern" => return union_obj.size * 8, // will be `unreachable` under #19755 } - if (!is_packed) { - return (try ty.abiSizeInner(strat_lazy, zcu, tid)).scalar * 8; - } - assert(union_type.flagsUnordered(ip).status.haveFieldTypes()); - - var size: u64 = 0; - for (0..union_type.field_types.len) |field_index| { - const field_ty = union_type.field_types.get(ip)[field_index]; - size = @max(size, try Type.fromInterned(field_ty).bitSizeInner(strat, zcu, tid)); - } - - return size; }, + .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).bitSize(zcu), + + // will be `unreachable` under #19755 + .opt_type, + .error_union_type, + .tuple_type, + => ty.abiSize(zcu) * 8, + .opaque_type => unreachable, - .enum_type => return Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty) - .bitSizeInner(strat, zcu, tid), // values, not types .undef, @@ -1782,23 +1108,6 @@ pub fn bitSizeInner( // memoization, not types .memoized_call, => unreachable, - } -} - -/// Returns true if the type's layout is already resolved and it is safe -/// to use `abiSize`, `abiAlignment` and `bitSize` on it. -pub fn layoutIsResolved(ty: Type, zcu: *const Zcu) bool { - const ip = &zcu.intern_pool; - return switch (ip.indexToKey(ty.toIntern())) { - .struct_type => ip.loadStructType(ty.toIntern()).haveLayout(ip), - .union_type => ip.loadUnionType(ty.toIntern()).haveLayout(ip), - .array_type => |array_type| { - if (array_type.lenIncludingSentinel() == 0) return true; - return Type.fromInterned(array_type.child).layoutIsResolved(zcu); - }, - .opt_type => |child| Type.fromInterned(child).layoutIsResolved(zcu), - .error_union_type => |k| Type.fromInterned(k.payload_type).layoutIsResolved(zcu), - else => true, }; } @@ -1841,7 +1150,7 @@ pub fn isSliceAtRuntime(ty: Type, zcu: *const Zcu) bool { } pub fn slicePtrFieldType(ty: Type, zcu: *const Zcu) Type { - return Type.fromInterned(zcu.intern_pool.slicePtrType(ty.toIntern())); + return .fromInterned(zcu.intern_pool.slicePtrType(ty.toIntern())); } pub fn isConstPtr(ty: Type, zcu: *const Zcu) bool { @@ -1897,10 +1206,7 @@ pub fn isPtrAtRuntime(ty: Type, zcu: *const Zcu) bool { /// For pointer-like optionals, returns true, otherwise returns the allowzero property /// of pointers. pub fn ptrAllowsZero(ty: Type, zcu: *const Zcu) bool { - if (ty.isPtrLikeOptional(zcu)) { - return true; - } - return ty.ptrInfo(zcu).flags.is_allowzero; + return ty.isPtrLikeOptional(zcu) or ty.ptrInfo(zcu).flags.is_allowzero; } /// See also `isPtrLikeOptional`. @@ -1918,7 +1224,6 @@ pub fn optionalReprIsPayload(ty: Type, zcu: *const Zcu) bool { /// Returns true if the type is optional and would be lowered to a single pointer /// address value, using 0 for null. Note that this returns true for C pointers. -/// This function must be kept in sync with `Sema.typePtrOrOptionalPtrTy`. pub fn isPtrLikeOptional(ty: Type, zcu: *const Zcu) bool { return switch (zcu.intern_pool.indexToKey(ty.toIntern())) { .ptr_type => |ptr_type| ptr_type.flags.size == .c, @@ -1947,52 +1252,75 @@ pub fn childTypeIp(ty: Type, ip: *const InternPool) Type { return Type.fromInterned(ip.childType(ty.toIntern())); } -/// For `*[N]T`, returns `T`. -/// For `?*T`, returns `T`. -/// For `?*[N]T`, returns `T`. -/// For `?[*]T`, returns `T`. -/// For `*T`, returns `T`. -/// For `[*]T`, returns `T`. -/// For `[N]T`, returns `T`. -/// For `[]T`, returns `T`. -/// For `anyframe->T`, returns `T`. -pub fn elemType2(ty: Type, zcu: *const Zcu) Type { - return switch (zcu.intern_pool.indexToKey(ty.toIntern())) { - .ptr_type => |ptr_type| switch (ptr_type.flags.size) { - .one => Type.fromInterned(ptr_type.child).shallowElemType(zcu), - .many, .c, .slice => Type.fromInterned(ptr_type.child), +/// Similar to `childType`, but for pointer-like (or slice-like) optionals, gets the child type +/// of the *pointer* type. Asserts that `ty` is either a pointer or a pointer-like optional. +/// +/// Essentially, unwraps any one of the following into `T`: +/// ``` +/// *T ?*T *allowzero T +/// [*]T ?[*]T [*]allowzero T +/// []T ?[]T []allowzero T +/// [*c]T +/// ``` +/// This is primarily useful in Sema to implement operations which can act on optional pointers. +pub fn nullablePtrElem(ty: Type, zcu: *const Zcu) Type { + switch (ty.zigTypeTag(zcu)) { + .pointer => return ty.childType(zcu), + .optional => { + const ptr_ty = ty.childType(zcu); + const ptr_info = zcu.intern_pool.indexToKey(ptr_ty.toIntern()).ptr_type; + assert(ptr_info.flags.size != .c); + assert(!ptr_info.flags.is_allowzero); + return .fromInterned(ptr_info.child); }, - .anyframe_type => |child| { - assert(child != .none); - return Type.fromInterned(child); - }, - .vector_type => |vector_type| Type.fromInterned(vector_type.child), - .array_type => |array_type| Type.fromInterned(array_type.child), - .opt_type => |child| Type.fromInterned(zcu.intern_pool.childType(child)), else => unreachable, - }; + } } /// Given that `ty` is an indexable pointer, returns its element type. Specifically: /// * for `*[n]T`, returns `T` +/// * for `*@Vector(n, T)`, returns `T` /// * for `[]T`, returns `T` /// * for `[*]T`, returns `T` /// * for `[*c]T`, returns `T` +/// +/// Tuples are not supported because they do not have a single element type. +/// +/// MLUGG TODO: should i even have this one? it's a subset of indexableElem pub fn indexablePtrElem(ty: Type, zcu: *const Zcu) Type { const ip = &zcu.intern_pool; const ptr_type = ip.indexToKey(ty.toIntern()).ptr_type; - switch (ptr_type.flags.size) { + return switch (ptr_type.flags.size) { .many, .slice, .c => return .fromInterned(ptr_type.child), - .one => {}, - } - const array_type = ip.indexToKey(ptr_type.child).array_type; - return .fromInterned(array_type.child); + .one => switch (ip.indexToKey(ptr_type.child)) { + inline .array_type, .vector_type => |arr| return .fromInterned(arr.child), + else => unreachable, + }, + }; } -fn shallowElemType(child_ty: Type, zcu: *const Zcu) Type { - return switch (child_ty.zigTypeTag(zcu)) { - .array, .vector => child_ty.childType(zcu), - else => child_ty, +/// Given that `ty` is an indexable type, returns its element type. Specifically: +/// * for `[n]T`, returns `T` +/// * for `@Vector(n, T)`, returns `T` +/// * for `*[n]T`, returns `T` +/// * for `*@Vector(n, T)`, returns `T` +/// * for `[]T`, returns `T` +/// * for `[*]T`, returns `T` +/// * for `[*c]T`, returns `T` +/// +/// Tuples are not supported because they do not have a single element type. +pub fn indexableElem(ty: Type, zcu: *const Zcu) Type { + const ip = &zcu.intern_pool; + return switch (ip.indexToKey(ty.toIntern())) { + inline .array_type, .vector_type => |arr| .fromInterned(arr.child), + .ptr_type => |ptr_type| switch (ptr_type.flags.size) { + .many, .slice, .c => .fromInterned(ptr_type.child), + .one => switch (ip.indexToKey(ptr_type.child)) { + inline .array_type, .vector_type => |arr| .fromInterned(arr.child), + else => unreachable, + }, + }, + else => unreachable, }; } @@ -2004,17 +1332,17 @@ pub fn scalarType(ty: Type, zcu: *const Zcu) Type { }; } -/// Asserts that the type is an optional. -/// Note that for C pointers this returns the type unmodified. +/// Asserts that the type is an optional, or a C pointer. +/// For C pointers this returns the type unmodified. pub fn optionalChild(ty: Type, zcu: *const Zcu) Type { - return switch (zcu.intern_pool.indexToKey(ty.toIntern())) { - .opt_type => |child| Type.fromInterned(child), - .ptr_type => |ptr_type| b: { + switch (zcu.intern_pool.indexToKey(ty.toIntern())) { + .opt_type => |child| return .fromInterned(child), + .ptr_type => |ptr_type| { assert(ptr_type.flags.size == .c); - break :b ty; + return ty; }, else => unreachable, - }; + } } /// Returns the tag type of a union, if the type is a union and it has a tag type. @@ -2025,15 +1353,11 @@ pub fn unionTagType(ty: Type, zcu: *const Zcu) ?Type { .union_type => {}, else => return null, } - const union_type = ip.loadUnionType(ty.toIntern()); - const union_flags = union_type.flagsUnordered(ip); - switch (union_flags.runtime_tag) { - .tagged => { - assert(union_flags.status.haveFieldTypes()); - return Type.fromInterned(union_type.enum_tag_ty); - }, - else => return null, - } + const union_obj = ip.loadUnionType(ty.toIntern()); + return switch (union_obj.runtime_tag) { + .tagged => .fromInterned(union_obj.enum_tag_type), + .none, .safety => null, + }; } /// Same as `unionTagType` but includes safety tag. @@ -2043,9 +1367,8 @@ pub fn unionTagTypeSafety(ty: Type, zcu: *const Zcu) ?Type { return switch (ip.indexToKey(ty.toIntern())) { .union_type => { const union_type = ip.loadUnionType(ty.toIntern()); - if (!union_type.hasTag(ip)) return null; - assert(union_type.haveFieldTypes(ip)); - return Type.fromInterned(union_type.enum_tag_ty); + if (union_type.runtime_tag == .none) return null; + return Type.fromInterned(union_type.enum_tag_type); }, else => null, }; @@ -2055,7 +1378,7 @@ pub fn unionTagTypeSafety(ty: Type, zcu: *const Zcu) ?Type { /// not be stored at runtime. pub fn unionTagTypeHypothetical(ty: Type, zcu: *const Zcu) Type { const union_obj = zcu.typeToUnion(ty).?; - return Type.fromInterned(union_obj.enum_tag_ty); + return Type.fromInterned(union_obj.enum_tag_type); } pub fn unionFieldType(ty: Type, enum_tag: Value, zcu: *const Zcu) ?Type { @@ -2105,9 +1428,9 @@ pub fn unionGetLayout(ty: Type, zcu: *const Zcu) Zcu.UnionLayout { pub fn containerLayout(ty: Type, zcu: *const Zcu) std.builtin.Type.ContainerLayout { const ip = &zcu.intern_pool; return switch (ip.indexToKey(ty.toIntern())) { - .struct_type => ip.loadStructType(ty.toIntern()).layout, .tuple_type => .auto, - .union_type => ip.loadUnionType(ty.toIntern()).flagsUnordered(ip).layout, + .struct_type => ip.loadStructType(ty.toIntern()).layout, + .union_type => ip.loadUnionType(ty.toIntern()).layout, else => unreachable, }; } @@ -2182,33 +1505,6 @@ pub fn errorSetHasFieldIp( }; } -/// Returns whether ty, which must be an error set, includes an error `name`. -/// Might return a false negative if `ty` is an inferred error set and not fully -/// resolved yet. -pub fn errorSetHasField(ty: Type, name: []const u8, zcu: *const Zcu) bool { - const ip = &zcu.intern_pool; - return switch (ty.toIntern()) { - .anyerror_type => true, - else => switch (ip.indexToKey(ty.toIntern())) { - .error_set_type => |error_set_type| { - // If the string is not interned, then the field certainly is not present. - const field_name_interned = ip.getString(name).unwrap() orelse return false; - return error_set_type.nameIndex(ip, field_name_interned) != null; - }, - .inferred_error_set_type => |i| switch (ip.funcIesResolvedUnordered(i)) { - .anyerror_type => true, - .none => false, - else => |t| { - // If the string is not interned, then the field certainly is not present. - const field_name_interned = ip.getString(name).unwrap() orelse return false; - return ip.indexToKey(t).error_set_type.nameIndex(ip, field_name_interned) != null; - }, - }, - else => unreachable, - }, - }; -} - /// Asserts the type is an array or vector or struct. pub fn arrayLen(ty: Type, zcu: *const Zcu) u64 { return ty.arrayLenIp(&zcu.intern_pool); @@ -2308,8 +1604,12 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType { .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulonglong) }, else => switch (ip.indexToKey(ty.toIntern())) { .int_type => |int_type| return int_type, - .struct_type => ty = Type.fromInterned(ip.loadStructType(ty.toIntern()).backingIntTypeUnordered(ip)), - .enum_type => ty = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty), + .struct_type => { + const struct_obj = ip.loadStructType(ty.toIntern()); + assert(struct_obj.layout == .@"packed"); + ty = .fromInterned(struct_obj.packed_backing_int_type); + }, + .enum_type => ty = .fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type), .vector_type => |vector_type| ty = Type.fromInterned(vector_type.child), .error_set_type, .inferred_error_set_type => { @@ -2355,25 +1655,6 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType { }; } -pub fn isNamedInt(ty: Type) bool { - return switch (ty.toIntern()) { - .usize_type, - .isize_type, - .c_char_type, - .c_short_type, - .c_ushort_type, - .c_int_type, - .c_uint_type, - .c_long_type, - .c_ulong_type, - .c_longlong_type, - .c_ulonglong_type, - => true, - - else => false, - }; -} - /// Returns `false` for `comptime_float`. pub fn isRuntimeFloat(ty: Type) bool { return switch (ty.toIntern()) { @@ -2488,17 +1769,16 @@ pub fn isNumeric(ty: Type, zcu: *const Zcu) bool { }; } -/// During semantic analysis, instead call `Sema.typeHasOnePossibleValue` which -/// resolves field types rather than asserting they are already resolved. +/// MLUGG TODO: deal with our friends structs and unions pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { const zcu = pt.zcu; const comp = zcu.comp; const gpa = comp.gpa; - const io = comp.io; const ip = &zcu.intern_pool; + assertHasLayout(starting_type, zcu); var ty = starting_type; while (true) switch (ty.toIntern()) { - .empty_tuple_type => return Value.empty_tuple, + .empty_tuple_type => return .empty_tuple, else => switch (ip.indexToKey(ty.toIntern())) { .int_type => |int_type| { @@ -2563,31 +1843,37 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { .adhoc_inferred_error_set, => return null, - .void => return Value.void, - .noreturn => return Value.@"unreachable", - .null => return Value.null, - .undefined => return Value.undef, + .void => return .void, + .noreturn => return .@"unreachable", + .null => return .null, + .undefined => return .undef, .generic_poison => unreachable, }, .struct_type => { - const struct_type = ip.loadStructType(ty.toIntern()); - assert(struct_type.haveFieldTypes(ip)); - if (struct_type.knownNonOpv(ip)) - return null; - const field_vals = try zcu.gpa.alloc(InternPool.Index, struct_type.field_types.len); - defer zcu.gpa.free(field_vals); + const struct_obj = ip.loadStructType(ty.toIntern()); + if (struct_obj.layout == .@"packed") { + const backing_ty: Type = .fromInterned(struct_obj.packed_backing_int_type); + const backing_val = try backing_ty.onePossibleValue(pt) orelse return null; + _ = backing_val; // MLUGG TODO: represent unions as their bits! + } else { + if (!struct_obj.has_one_possible_value) return null; + } + // There is an OPV. + const field_vals = try gpa.alloc(InternPool.Index, struct_obj.field_types.len); + defer gpa.free(field_vals); for (field_vals, 0..) |*field_val, i_usize| { const i: u32 = @intCast(i_usize); - if (struct_type.fieldIsComptime(ip, i)) { - assert(struct_type.haveFieldInits(ip)); - field_val.* = struct_type.field_inits.get(ip)[i]; + if (struct_obj.field_is_comptime_bits.get(ip, i)) { + // MLUGG TODO: this is kinda a problem... we don't necessarily know the opv field vals! + // for now i'm just not letting structs with comptime fields be opv :) + if (true) return null; + assertHasInits(ty, zcu); + field_val.* = struct_obj.field_defaults.get(ip)[i]; continue; } - const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); - if (try field_ty.onePossibleValue(pt)) |field_opv| { - field_val.* = field_opv.toIntern(); - } else return null; + const field_ty = Type.fromInterned(struct_obj.field_types.get(ip)[i]); + field_val.* = (try field_ty.onePossibleValue(pt)).?.toIntern(); } // In this case the struct has no runtime-known fields and @@ -2623,12 +1909,13 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { }, .union_type => { + // MLUGG TODO: is this nonsensical or what!!!!!! const union_obj = ip.loadUnionType(ty.toIntern()); - const tag_val = (try Type.fromInterned(union_obj.enum_tag_ty).onePossibleValue(pt)) orelse + const tag_val = (try Type.fromInterned(union_obj.enum_tag_type).onePossibleValue(pt)) orelse return null; if (union_obj.field_types.len == 0) { const only = try pt.intern(.{ .empty_enum_value = ty.toIntern() }); - return Value.fromInterned(only); + return .fromInterned(only); } const only_field_ty = union_obj.field_types.get(ip)[0]; const val_val = (try Type.fromInterned(only_field_ty).onePossibleValue(pt)) orelse @@ -2638,47 +1925,34 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { .tag = tag_val.toIntern(), .val = val_val.toIntern(), }); - return Value.fromInterned(only); + return .fromInterned(only); }, .opaque_type => return null, .enum_type => { - const enum_type = ip.loadEnumType(ty.toIntern()); - switch (enum_type.tag_mode) { - .nonexhaustive => { - if (enum_type.tag_ty == .comptime_int_type) return null; - - if (try Type.fromInterned(enum_type.tag_ty).onePossibleValue(pt)) |int_opv| { - const only = try pt.intern(.{ .enum_tag = .{ - .ty = ty.toIntern(), - .int = int_opv.toIntern(), - } }); - return Value.fromInterned(only); - } - - return null; - }, - .auto, .explicit => { - if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(zcu)) return null; - - return Value.fromInterned(switch (enum_type.names.len) { - 0 => try pt.intern(.{ .empty_enum_value = ty.toIntern() }), - 1 => try pt.intern(.{ .enum_tag = .{ - .ty = ty.toIntern(), - .int = if (enum_type.values.len == 0) - (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern() - else - try ip.getCoercedInts( - gpa, - io, - pt.tid, - ip.indexToKey(enum_type.values.get(ip)[0]).int, - enum_type.tag_ty, - ), - } }), - else => return null, - }); - }, + const enum_obj = ip.loadEnumType(ty.toIntern()); + if (enum_obj.nonexhaustive) { + const int_opv = try Type.fromInterned(enum_obj.int_tag_type).onePossibleValue(pt) orelse return null; + return .fromInterned(try pt.intern(.{ .enum_tag = .{ + .ty = ty.toIntern(), + .int = int_opv.toIntern(), + } })); } + // MLUGG TODO: this is to preserve existing semantics, i REALLY don't fuck with it... + if (enum_obj.int_tag_type == .comptime_int_type) { + return switch (enum_obj.field_names.len) { + 0 => .fromInterned(try pt.intern(.{ .empty_enum_value = ty.toIntern() })), + 1 => try pt.enumValueFieldIndex(ty, 0), + else => null, + }; + } + const int_tag_opv = try Type.fromInterned(enum_obj.int_tag_type).onePossibleValue(pt) orelse return null; + if (enum_obj.field_names.len == 0) { + return .fromInterned(try pt.intern(.{ .empty_enum_value = ty.toIntern() })); + } + return .fromInterned(try pt.intern(.{ .enum_tag = .{ + .ty = ty.toIntern(), + .int = int_tag_opv.toIntern(), + } })); }, // values, not types @@ -2706,211 +1980,106 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { }; } -/// During semantic analysis, instead call `ty.comptimeOnlySema` which -/// resolves field types rather than asserting they are already resolved. +/// Asserts that `ty` has its layout resolved. `generic_poison` will return `false`. pub fn comptimeOnly(ty: Type, zcu: *const Zcu) bool { - return ty.comptimeOnlyInner(.normal, zcu, {}) catch unreachable; -} - -pub fn comptimeOnlySema(ty: Type, pt: Zcu.PerThread) SemaError!bool { - return try ty.comptimeOnlyInner(.sema, pt.zcu, pt.tid); -} - -/// `generic_poison` will return false. -/// May return false negatives when structs and unions are having their field types resolved. -pub fn comptimeOnlyInner( - ty: Type, - comptime strat: ResolveStrat, - zcu: strat.ZcuPtr(), - tid: strat.Tid(), -) SemaError!bool { const ip = &zcu.intern_pool; - const io = zcu.comp.io; - return switch (ty.toIntern()) { - .empty_tuple_type => false, + return switch (ip.indexToKey(ty.toIntern())) { + .array_type => |array_type| return Type.fromInterned(array_type.child).comptimeOnly(zcu), + .vector_type => |vector_type| return Type.fromInterned(vector_type.child).comptimeOnly(zcu), + .opt_type => |child| return Type.fromInterned(child).comptimeOnly(zcu), + .error_union_type => |error_union_type| return Type.fromInterned(error_union_type.payload_type).comptimeOnly(zcu), + .enum_type => return Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).comptimeOnly(zcu), - else => switch (ip.indexToKey(ty.toIntern())) { - .int_type => false, - .ptr_type => |ptr_type| { - const child_ty = Type.fromInterned(ptr_type.child); - switch (child_ty.zigTypeTag(zcu)) { - .@"fn" => return !try child_ty.fnHasRuntimeBitsInner(strat, zcu, tid), - .@"opaque" => return false, - else => return child_ty.comptimeOnlyInner(strat, zcu, tid), - } - }, - .anyframe_type => |child| { - if (child == .none) return false; - return Type.fromInterned(child).comptimeOnlyInner(strat, zcu, tid); - }, - .array_type => |array_type| return Type.fromInterned(array_type.child).comptimeOnlyInner(strat, zcu, tid), - .vector_type => |vector_type| return Type.fromInterned(vector_type.child).comptimeOnlyInner(strat, zcu, tid), - .opt_type => |child| return Type.fromInterned(child).comptimeOnlyInner(strat, zcu, tid), - .error_union_type => |error_union_type| return Type.fromInterned(error_union_type.payload_type).comptimeOnlyInner(strat, zcu, tid), + .int_type, + .ptr_type, + .anyframe_type, + .error_set_type, + .inferred_error_set_type, + .opaque_type, + => false, - .error_set_type, - .inferred_error_set_type, + // These are function bodies, not function pointers. + .func_type => true, + + .simple_type => |t| switch (t) { + .f16, + .f32, + .f64, + .f80, + .f128, + .usize, + .isize, + .c_char, + .c_short, + .c_ushort, + .c_int, + .c_uint, + .c_long, + .c_ulong, + .c_longlong, + .c_ulonglong, + .c_longdouble, + .anyopaque, + .bool, + .void, + .anyerror, + .adhoc_inferred_error_set, + .noreturn, + .generic_poison, => false, - // These are function bodies, not function pointers. - .func_type => true, - - .simple_type => |t| switch (t) { - .f16, - .f32, - .f64, - .f80, - .f128, - .usize, - .isize, - .c_char, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .c_longdouble, - .anyopaque, - .bool, - .void, - .anyerror, - .adhoc_inferred_error_set, - .noreturn, - .generic_poison, - => false, - - .type, - .comptime_int, - .comptime_float, - .null, - .undefined, - .enum_literal, - => true, - }, - .struct_type => { - const struct_type = ip.loadStructType(ty.toIntern()); - // packed structs cannot be comptime-only because they have a well-defined - // memory layout and every field has a well-defined bit pattern. - if (struct_type.layout == .@"packed") - return false; - - return switch (strat) { - .normal => switch (struct_type.requiresComptime(ip)) { - .wip => unreachable, - .no => false, - .yes => true, - .unknown => unreachable, - }, - .sema => switch (struct_type.setRequiresComptimeWip(ip, io)) { - .no, .wip => false, - .yes => true, - .unknown => { - if (struct_type.flagsUnordered(ip).field_types_wip) { - struct_type.setRequiresComptime(ip, io, .unknown); - return false; - } - - errdefer struct_type.setRequiresComptime(ip, io, .unknown); - - const pt = strat.pt(zcu, tid); - try ty.resolveFields(pt); - - for (0..struct_type.field_types.len) |i_usize| { - const i: u32 = @intCast(i_usize); - if (struct_type.fieldIsComptime(ip, i)) continue; - const field_ty = struct_type.field_types.get(ip)[i]; - if (try Type.fromInterned(field_ty).comptimeOnlyInner(strat, zcu, tid)) { - // Note that this does not cause the layout to - // be considered resolved. Comptime-only types - // still maintain a layout of their - // runtime-known fields. - struct_type.setRequiresComptime(ip, io, .yes); - return true; - } - } - - struct_type.setRequiresComptime(ip, io, .no); - return false; - }, - }, - }; - }, - - .tuple_type => |tuple| { - for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| { - const have_comptime_val = val != .none; - if (!have_comptime_val and try Type.fromInterned(field_ty).comptimeOnlyInner(strat, zcu, tid)) return true; - } - return false; - }, - - .union_type => { - const union_type = ip.loadUnionType(ty.toIntern()); - return switch (strat) { - .normal => switch (union_type.requiresComptime(ip)) { - .wip => unreachable, - .no => false, - .yes => true, - .unknown => unreachable, - }, - .sema => switch (union_type.setRequiresComptimeWip(ip, io)) { - .no, .wip => return false, - .yes => return true, - .unknown => { - if (union_type.flagsUnordered(ip).status == .field_types_wip) { - union_type.setRequiresComptime(ip, io, .unknown); - return false; - } - - errdefer union_type.setRequiresComptime(ip, io, .unknown); - - const pt = strat.pt(zcu, tid); - try ty.resolveFields(pt); - - for (0..union_type.field_types.len) |field_idx| { - const field_ty = union_type.field_types.get(ip)[field_idx]; - if (try Type.fromInterned(field_ty).comptimeOnlyInner(strat, zcu, tid)) { - union_type.setRequiresComptime(ip, io, .yes); - return true; - } - } - - union_type.setRequiresComptime(ip, io, .no); - return false; - }, - }, - }; - }, - - .opaque_type => false, - - .enum_type => return Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).comptimeOnlyInner(strat, zcu, tid), - - // values, not types - .undef, - .simple_value, - .variable, - .@"extern", - .func, - .int, - .err, - .error_union, + .type, + .comptime_int, + .comptime_float, + .null, + .undefined, .enum_literal, - .enum_tag, - .empty_enum_value, - .float, - .ptr, - .slice, - .opt, - .aggregate, - .un, - // memoization, not types - .memoized_call, - => unreachable, + => true, }, + .struct_type => { + const struct_obj = ip.loadStructType(ty.toIntern()); + return switch (struct_obj.layout) { + .@"packed" => false, + .auto, .@"extern" => struct_obj.comptime_only, + }; + }, + .union_type => { + const union_obj = ip.loadUnionType(ty.toIntern()); + return switch (union_obj.layout) { + .@"packed" => false, + .auto, .@"extern" => union_obj.comptime_only, + }; + }, + .tuple_type => |tuple| { + for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| { + if (val != .none) continue; + if (!Type.fromInterned(field_ty).comptimeOnly(zcu)) continue; + return true; + } + return false; + }, + + // values, not types + .undef, + .simple_value, + .variable, + .@"extern", + .func, + .int, + .err, + .error_union, + .enum_literal, + .enum_tag, + .empty_enum_value, + .float, + .ptr, + .slice, + .opt, + .aggregate, + .un, + // memoization, not types + .memoized_call, + => unreachable, }; } @@ -3056,20 +2225,18 @@ pub fn maxIntScalar(ty: Type, pt: Zcu.PerThread, dest_ty: Type) !Value { /// Asserts the type is an enum or a union. pub fn intTagType(ty: Type, zcu: *const Zcu) Type { const ip = &zcu.intern_pool; - return switch (ip.indexToKey(ty.toIntern())) { - .union_type => Type.fromInterned(ip.loadUnionType(ty.toIntern()).enum_tag_ty).intTagType(zcu), - .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty), + const enum_ty: Type = switch (ip.indexToKey(ty.toIntern())) { + .union_type => .fromInterned(ip.loadUnionType(ty.toIntern()).enum_tag_type), + .enum_type => ty, else => unreachable, }; + return .fromInterned(ip.loadEnumType(enum_ty.toIntern()).int_tag_type); } pub fn isNonexhaustiveEnum(ty: Type, zcu: *const Zcu) bool { const ip = &zcu.intern_pool; return switch (ip.indexToKey(ty.toIntern())) { - .enum_type => switch (ip.loadEnumType(ty.toIntern()).tag_mode) { - .nonexhaustive => true, - .auto, .explicit => false, - }, + .enum_type => ip.loadEnumType(ty.toIntern()).nonexhaustive, else => false, }; } @@ -3090,16 +2257,16 @@ pub fn errorSetNames(ty: Type, zcu: *const Zcu) InternPool.NullTerminatedString. } pub fn enumFields(ty: Type, zcu: *const Zcu) InternPool.NullTerminatedString.Slice { - return zcu.intern_pool.loadEnumType(ty.toIntern()).names; + return zcu.intern_pool.loadEnumType(ty.toIntern()).field_names; } pub fn enumFieldCount(ty: Type, zcu: *const Zcu) usize { - return zcu.intern_pool.loadEnumType(ty.toIntern()).names.len; + return zcu.intern_pool.loadEnumType(ty.toIntern()).field_names.len; } pub fn enumFieldName(ty: Type, field_index: usize, zcu: *const Zcu) InternPool.NullTerminatedString { const ip = &zcu.intern_pool; - return ip.loadEnumType(ty.toIntern()).names.get(ip)[field_index]; + return ip.loadEnumType(ty.toIntern()).field_names.get(ip)[field_index]; } pub fn enumFieldIndex(ty: Type, field_name: InternPool.NullTerminatedString, zcu: *const Zcu) ?u32 { @@ -3119,7 +2286,7 @@ pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, zcu: *const Zcu) ?u32 { .enum_tag => |info| info.int, else => unreachable, }; - assert(ip.typeOf(int_tag) == enum_type.tag_ty); + assert(ip.typeOf(int_tag) == enum_type.int_tag_type); return enum_type.tagValueIndex(ip, int_tag); } @@ -3127,7 +2294,7 @@ pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, zcu: *const Zcu) ?u32 { pub fn structFieldName(ty: Type, index: usize, zcu: *const Zcu) InternPool.OptionalNullTerminatedString { const ip = &zcu.intern_pool; return switch (ip.indexToKey(ty.toIntern())) { - .struct_type => ip.loadStructType(ty.toIntern()).fieldName(ip, index).toOptional(), + .struct_type => ip.loadStructType(ty.toIntern()).field_names.get(ip)[index].toOptional(), .tuple_type => .none, else => unreachable, }; @@ -3145,174 +2312,95 @@ pub fn structFieldCount(ty: Type, zcu: *const Zcu) u32 { /// Returns the field type. Supports structs and unions. pub fn fieldType(ty: Type, index: usize, zcu: *const Zcu) Type { const ip = &zcu.intern_pool; - return switch (ip.indexToKey(ty.toIntern())) { - .struct_type => Type.fromInterned(ip.loadStructType(ty.toIntern()).field_types.get(ip)[index]), - .union_type => { - const union_obj = ip.loadUnionType(ty.toIntern()); - return Type.fromInterned(union_obj.field_types.get(ip)[index]); - }, - .tuple_type => |tuple| Type.fromInterned(tuple.types.get(ip)[index]), + const types = switch (ip.indexToKey(ty.toIntern())) { + .struct_type => ip.loadStructType(ty.toIntern()).field_types, + .union_type => ip.loadUnionType(ty.toIntern()).field_types, + .tuple_type => |tuple| tuple.types, else => unreachable, }; + return .fromInterned(types.get(ip)[index]); } -pub fn fieldAlignment(ty: Type, index: usize, zcu: *Zcu) Alignment { - return ty.fieldAlignmentInner(index, .normal, zcu, {}) catch unreachable; -} - -pub fn fieldAlignmentSema(ty: Type, index: usize, pt: Zcu.PerThread) SemaError!Alignment { - return try ty.fieldAlignmentInner(index, .sema, pt.zcu, pt.tid); -} +// TODO MLUGG: clean up doc comments and usages of `{resolved,explicit}FieldAlignment` -/// Returns the field alignment. Supports structs and unions. -/// If `strat` is `.sema`, may perform type resolution. -/// Asserts the layout is not packed. -/// -/// Provide the struct field as the `ty`. -pub fn fieldAlignmentInner( - ty: Type, - index: usize, - comptime strat: ResolveStrat, - zcu: strat.ZcuPtr(), - tid: strat.Tid(), -) SemaError!Alignment { - const ip = &zcu.intern_pool; - switch (ip.indexToKey(ty.toIntern())) { - .struct_type => { - const struct_type = ip.loadStructType(ty.toIntern()); - assert(struct_type.layout != .@"packed"); - const explicit_align = struct_type.fieldAlign(ip, index); - const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[index]); - return field_ty.structFieldAlignmentInner(explicit_align, struct_type.layout, strat, zcu, tid); - }, - .tuple_type => |tuple| { - return (try Type.fromInterned(tuple.types.get(ip)[index]).abiAlignmentInner( - strat.toLazy(), - zcu, - tid, - )).scalar; - }, - .union_type => { - const union_obj = ip.loadUnionType(ty.toIntern()); - const layout = union_obj.flagsUnordered(ip).layout; - assert(layout != .@"packed"); - const explicit_align = union_obj.fieldAlign(ip, index); - const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[index]); - return field_ty.unionFieldAlignmentInner(explicit_align, layout, strat, zcu, tid); - }, - else => unreachable, +/// Returns the alignment of the given struct, tuple, or union field. +/// Asserts that the layout of `ty` is resolved. Asserts that `ty` is not packed. +/// Never returns `.none`, even if the field's alignment was not specified. +pub fn resolvedFieldAlignment(ty: Type, index: usize, zcu: *const Zcu) Alignment { + switch (ty.explicitFieldAlignment(index, zcu)) { + .none => {}, + else => |explicit| return explicit, } + const ip = &zcu.intern_pool; + return switch (ip.indexToKey(ty.toIntern())) { + .tuple_type => |tuple| Type.fromInterned(tuple.types.get(ip)[index]).abiAlignment(zcu), + .struct_type => { + const struct_obj = ip.loadStructType(ty.toIntern()); + const field_ty: Type = .fromInterned(struct_obj.field_types.get(ip)[index]); + return field_ty.defaultStructFieldAlignment(struct_obj.layout, zcu); + }, + .union_type => { + const union_obj = ip.loadUnionType(ty.toIntern()); + const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[index]); + return field_ty.abiAlignment(zcu); + }, + else => unreachable, + }; } -/// Returns the alignment of a non-packed struct field. Assert the layout is not packed. -/// -/// Asserts that all resolution needed was done. -pub fn structFieldAlignment( +pub fn explicitFieldAlignment(ty: Type, index: usize, zcu: *const Zcu) Alignment { + const ip = &zcu.intern_pool; + return switch (ip.indexToKey(ty.toIntern())) { + .tuple_type => .none, + .struct_type => { + const struct_obj = ip.loadStructType(ty.toIntern()); + assert(struct_obj.layout != .@"packed"); + if (struct_obj.field_aligns.len == 0) return .none; + return struct_obj.field_aligns.get(ip)[index]; + }, + .union_type => { + const union_obj = ip.loadUnionType(ty.toIntern()); + assert(union_obj.layout != .@"packed"); + if (union_obj.field_aligns.len == 0) return .none; + return union_obj.field_aligns.get(ip)[index]; + }, + else => unreachable, + }; +} + +/// Returns the alignment a struct field will have if not explicitly specified. +/// Asserts that the layout of `field_ty` is resolved. Asserts that `layout` is not `.@"packed"`. +pub fn defaultStructFieldAlignment( field_ty: Type, - explicit_alignment: InternPool.Alignment, layout: std.builtin.Type.ContainerLayout, - zcu: *Zcu, + zcu: *const Zcu, ) Alignment { - return field_ty.structFieldAlignmentInner( - explicit_alignment, - layout, - .normal, - zcu, - {}, - ) catch unreachable; -} - -/// Returns the alignment of a non-packed struct field. Assert the layout is not packed. -/// May do type resolution when needed. -/// Asserts that all resolution needed was done. -pub fn structFieldAlignmentSema( - field_ty: Type, - explicit_alignment: InternPool.Alignment, - layout: std.builtin.Type.ContainerLayout, - pt: Zcu.PerThread, -) SemaError!Alignment { - return try field_ty.structFieldAlignmentInner( - explicit_alignment, - layout, - .sema, - pt.zcu, - pt.tid, - ); -} - -/// Returns the alignment of a non-packed struct field. Asserts the layout is not packed. -/// If `strat` is `.sema`, may perform type resolution. -pub fn structFieldAlignmentInner( - field_ty: Type, - explicit_alignment: Alignment, - layout: std.builtin.Type.ContainerLayout, - comptime strat: Type.ResolveStrat, - zcu: strat.ZcuPtr(), - tid: strat.Tid(), -) SemaError!Alignment { - assert(layout != .@"packed"); - if (explicit_alignment != .none) return explicit_alignment; - const ty_abi_align = (try field_ty.abiAlignmentInner( - strat.toLazy(), - zcu, - tid, - )).scalar; - switch (layout) { + const overalign_big_int = switch (layout) { .@"packed" => unreachable, - .auto => if (zcu.getTarget().ofmt != .c) return ty_abi_align, - .@"extern" => {}, + .auto => zcu.getTarget().ofmt == .c, + .@"extern" => true, + }; + const abi_align = field_ty.abiAlignment(zcu); + assert(abi_align != .none); + if (overalign_big_int and field_ty.isAbiInt(zcu) and field_ty.intInfo(zcu).bits >= 128) { + return abi_align.maxStrict(.@"16"); } - // extern - if (field_ty.isAbiInt(zcu) and field_ty.intInfo(zcu).bits >= 128) { - return ty_abi_align.maxStrict(.@"16"); - } - return ty_abi_align; -} - -pub fn unionFieldAlignmentSema( - field_ty: Type, - explicit_alignment: Alignment, - layout: std.builtin.Type.ContainerLayout, - pt: Zcu.PerThread, -) SemaError!Alignment { - return field_ty.unionFieldAlignmentInner( - explicit_alignment, - layout, - .sema, - pt.zcu, - pt.tid, - ); -} - -pub fn unionFieldAlignmentInner( - field_ty: Type, - explicit_alignment: Alignment, - layout: std.builtin.Type.ContainerLayout, - comptime strat: Type.ResolveStrat, - zcu: strat.ZcuPtr(), - tid: strat.Tid(), -) SemaError!Alignment { - assert(layout != .@"packed"); - if (explicit_alignment != .none) return explicit_alignment; - if (field_ty.isNoReturn(zcu)) return .none; - return (try field_ty.abiAlignmentInner(strat.toLazy(), zcu, tid)).scalar; + return abi_align; } -pub fn structFieldDefaultValue(ty: Type, index: usize, zcu: *const Zcu) Value { +pub fn structFieldDefaultValue(ty: Type, index: usize, zcu: *const Zcu) ?Value { const ip = &zcu.intern_pool; switch (ip.indexToKey(ty.toIntern())) { .struct_type => { - const struct_type = ip.loadStructType(ty.toIntern()); - const val = struct_type.fieldInit(ip, index); - // TODO: avoid using `unreachable` to indicate this. - if (val == .none) return Value.@"unreachable"; - return Value.fromInterned(val); + const field_defaults = ip.loadStructType(ty.toIntern()).field_defaults.get(ip); + if (field_defaults.len == 0) return null; + if (field_defaults[index] == .none) return null; + return .fromInterned(field_defaults[index]); }, .tuple_type => |tuple| { const val = tuple.values.get(ip)[index]; - // TODO: avoid using `unreachable` to indicate this. - if (val == .none) return Value.@"unreachable"; - return Value.fromInterned(val); + if (val == .none) return null; + return .fromInterned(val); }, else => unreachable, } @@ -3324,9 +2412,9 @@ pub fn structFieldValueComptime(ty: Type, pt: Zcu.PerThread, index: usize) !?Val switch (ip.indexToKey(ty.toIntern())) { .struct_type => { const struct_type = ip.loadStructType(ty.toIntern()); - if (struct_type.fieldIsComptime(ip, index)) { - assert(struct_type.haveFieldInits(ip)); - return Value.fromInterned(struct_type.field_inits.get(ip)[index]); + if (struct_type.field_is_comptime_bits.get(ip, index)) { + assertHasInits(ty, zcu); + return .fromInterned(struct_type.field_defaults.get(ip)[index]); } else { return Type.fromInterned(struct_type.field_types.get(ip)[index]).onePossibleValue(pt); } @@ -3336,7 +2424,7 @@ pub fn structFieldValueComptime(ty: Type, pt: Zcu.PerThread, index: usize) !?Val if (val == .none) { return Type.fromInterned(tuple.types.get(ip)[index]).onePossibleValue(pt); } else { - return Value.fromInterned(val); + return .fromInterned(val); } }, else => unreachable, @@ -3346,7 +2434,7 @@ pub fn structFieldValueComptime(ty: Type, pt: Zcu.PerThread, index: usize) !?Val pub fn structFieldIsComptime(ty: Type, index: usize, zcu: *const Zcu) bool { const ip = &zcu.intern_pool; return switch (ip.indexToKey(ty.toIntern())) { - .struct_type => ip.loadStructType(ty.toIntern()).fieldIsComptime(ip, index), + .struct_type => ip.loadStructType(ty.toIntern()).field_is_comptime_bits.get(ip, index), .tuple_type => |tuple| tuple.values.get(ip)[index] != .none, else => unreachable, }; @@ -3357,15 +2445,15 @@ pub const FieldOffset = struct { offset: u64, }; -/// Supports structs and unions. +/// Supports structs, tuples, and unions. pub fn structFieldOffset(ty: Type, index: usize, zcu: *const Zcu) u64 { + assertHasLayout(ty, zcu); const ip = &zcu.intern_pool; switch (ip.indexToKey(ty.toIntern())) { .struct_type => { const struct_type = ip.loadStructType(ty.toIntern()); - assert(struct_type.haveLayout(ip)); assert(struct_type.layout != .@"packed"); - return struct_type.offsets.get(ip)[index]; + return struct_type.field_offsets.get(ip)[index]; }, .tuple_type => |tuple| { @@ -3391,7 +2479,7 @@ pub fn structFieldOffset(ty: Type, index: usize, zcu: *const Zcu) u64 { .union_type => { const union_type = ip.loadUnionType(ty.toIntern()); - if (!union_type.hasTag(ip)) + if (union_type.runtime_tag == .none) return 0; const layout = Type.getUnionLayout(union_type, zcu); if (layout.tag_align.compare(.gte, layout.payload_align)) { @@ -3414,7 +2502,7 @@ pub fn srcLocOrNull(ty: Type, zcu: *Zcu) ?Zcu.LazySrcLoc { .struct_type, .union_type, .opaque_type, .enum_type => |info| switch (info) { .declared => |d| d.zir_index, .reified => |r| r.zir_index, - .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index, + .generated_union_tag => |union_ty| ip.loadUnionType(union_ty).zir_index, }, else => return null, }, @@ -3438,8 +2526,8 @@ pub fn isTuple(ty: Type, zcu: *const Zcu) bool { }; } -/// Traverses optional child types and error union payloads until the type -/// is not a pointer. For `E!?u32`, returns `u32`; for `*u8`, returns `*u8`. +/// Traverses optional child types and error union payloads until the type is neither of those. +/// For `E!?u32`, returns `u32`; for `*u8`, returns `*u8`. pub fn optEuBaseType(ty: Type, zcu: *const Zcu) Type { var cur = ty; while (true) switch (cur.zigTypeTag(zcu)) { @@ -3488,7 +2576,7 @@ pub fn typeDeclInstAllowGeneratedTag(ty: Type, zcu: *const Zcu) ?InternPool.Trac .union_type => ip.loadUnionType(ty.toIntern()).zir_index, .enum_type => |e| switch (e) { .declared, .reified => ip.loadEnumType(ty.toIntern()).zir_index.unwrap().?, - .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index, + .generated_union_tag => |union_ty| ip.loadUnionType(union_ty).zir_index, }, .opaque_type => ip.loadOpaqueType(ty.toIntern()).zir_index, else => null, @@ -3505,7 +2593,7 @@ pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 { .struct_type, .union_type, .opaque_type, .enum_type => |info| switch (info) { .declared => |d| d.zir_index, .reified => |r| r.zir_index, - .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index, + .generated_union_tag => |union_ty| ip.loadUnionType(union_ty).zir_index, }, else => return null, }; @@ -3520,10 +2608,10 @@ pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 { .struct_init, .struct_init_ref => zir.extraData(Zir.Inst.StructInit, inst.data.pl_node.payload_index).data.abs_line, .struct_init_anon => zir.extraData(Zir.Inst.StructInitAnon, inst.data.pl_node.payload_index).data.abs_line, .extended => switch (inst.data.extended.opcode) { - .struct_decl => zir.extraData(Zir.Inst.StructDecl, inst.data.extended.operand).data.src_line, - .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_line, - .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_line, - .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_line, + .struct_decl => zir.getStructDecl(info.inst).src_line, + .union_decl => zir.getUnionDecl(info.inst).src_line, + .enum_decl => zir.getEnumDecl(info.inst).src_line, + .opaque_decl => zir.getOpaqueDecl(info.inst).src_line, .reify_enum => zir.extraData(Zir.Inst.ReifyEnum, inst.data.extended.operand).data.src_line, .reify_struct => zir.extraData(Zir.Inst.ReifyStruct, inst.data.extended.operand).data.src_line, .reify_union => zir.extraData(Zir.Inst.ReifyUnion, inst.data.extended.operand).data.src_line, @@ -3594,330 +2682,8 @@ pub fn packedStructFieldPtrInfo( }; } -pub fn resolveLayout(ty: Type, pt: Zcu.PerThread) SemaError!void { - const zcu = pt.zcu; - const ip = &zcu.intern_pool; - switch (ty.zigTypeTag(zcu)) { - .@"struct" => switch (ip.indexToKey(ty.toIntern())) { - .tuple_type => |tuple_type| for (0..tuple_type.types.len) |i| { - const field_ty = Type.fromInterned(tuple_type.types.get(ip)[i]); - try field_ty.resolveLayout(pt); - }, - .struct_type => return ty.resolveStructInner(pt, .layout), - else => unreachable, - }, - .@"union" => return ty.resolveUnionInner(pt, .layout), - .array => { - if (ty.arrayLenIncludingSentinel(zcu) == 0) return; - const elem_ty = ty.childType(zcu); - return elem_ty.resolveLayout(pt); - }, - .optional => { - const payload_ty = ty.optionalChild(zcu); - return payload_ty.resolveLayout(pt); - }, - .error_union => { - const payload_ty = ty.errorUnionPayload(zcu); - return payload_ty.resolveLayout(pt); - }, - .@"fn" => { - const info = zcu.typeToFunc(ty).?; - if (info.is_generic) { - // Resolving of generic function types is deferred to when - // the function is instantiated. - return; - } - for (0..info.param_types.len) |i| { - const param_ty = info.param_types.get(ip)[i]; - try Type.fromInterned(param_ty).resolveLayout(pt); - } - try Type.fromInterned(info.return_type).resolveLayout(pt); - }, - else => {}, - } -} - -pub fn resolveFields(ty: Type, pt: Zcu.PerThread) SemaError!void { - const ip = &pt.zcu.intern_pool; - const ty_ip = ty.toIntern(); - - switch (ty_ip) { - .none => unreachable, - - .u0_type, - .i0_type, - .u1_type, - .u8_type, - .i8_type, - .u16_type, - .i16_type, - .u29_type, - .u32_type, - .i32_type, - .u64_type, - .i64_type, - .u80_type, - .u128_type, - .i128_type, - .usize_type, - .isize_type, - .c_char_type, - .c_short_type, - .c_ushort_type, - .c_int_type, - .c_uint_type, - .c_long_type, - .c_ulong_type, - .c_longlong_type, - .c_ulonglong_type, - .c_longdouble_type, - .f16_type, - .f32_type, - .f64_type, - .f80_type, - .f128_type, - .anyopaque_type, - .bool_type, - .void_type, - .type_type, - .anyerror_type, - .adhoc_inferred_error_set_type, - .comptime_int_type, - .comptime_float_type, - .noreturn_type, - .anyframe_type, - .null_type, - .undefined_type, - .enum_literal_type, - .ptr_usize_type, - .ptr_const_comptime_int_type, - .manyptr_u8_type, - .manyptr_const_u8_type, - .manyptr_const_u8_sentinel_0_type, - .slice_const_u8_type, - .slice_const_u8_sentinel_0_type, - .optional_noreturn_type, - .anyerror_void_error_union_type, - .generic_poison_type, - .empty_tuple_type, - => {}, - - .undef => unreachable, - .zero => unreachable, - .zero_usize => unreachable, - .zero_u1 => unreachable, - .zero_u8 => unreachable, - .one => unreachable, - .one_usize => unreachable, - .one_u1 => unreachable, - .one_u8 => unreachable, - .four_u8 => unreachable, - .negative_one => unreachable, - .void_value => unreachable, - .unreachable_value => unreachable, - .null_value => unreachable, - .bool_true => unreachable, - .bool_false => unreachable, - .empty_tuple => unreachable, - - else => switch (ty_ip.unwrap(ip).getTag(ip)) { - .type_struct, - .type_struct_packed, - .type_struct_packed_inits, - => return ty.resolveStructInner(pt, .fields), - - .type_union => return ty.resolveUnionInner(pt, .fields), - - else => {}, - }, - } -} - -pub fn resolveFully(ty: Type, pt: Zcu.PerThread) SemaError!void { - const zcu = pt.zcu; - const ip = &zcu.intern_pool; - - switch (ty.zigTypeTag(zcu)) { - .type, - .void, - .bool, - .noreturn, - .int, - .float, - .comptime_float, - .comptime_int, - .undefined, - .null, - .error_set, - .@"enum", - .@"opaque", - .frame, - .@"anyframe", - .vector, - .enum_literal, - => {}, - - .pointer => return ty.childType(zcu).resolveFully(pt), - .array => return ty.childType(zcu).resolveFully(pt), - .optional => return ty.optionalChild(zcu).resolveFully(pt), - .error_union => return ty.errorUnionPayload(zcu).resolveFully(pt), - .@"fn" => { - const info = zcu.typeToFunc(ty).?; - if (info.is_generic) return; - for (0..info.param_types.len) |i| { - const param_ty = info.param_types.get(ip)[i]; - try Type.fromInterned(param_ty).resolveFully(pt); - } - try Type.fromInterned(info.return_type).resolveFully(pt); - }, - - .@"struct" => switch (ip.indexToKey(ty.toIntern())) { - .tuple_type => |tuple_type| for (0..tuple_type.types.len) |i| { - const field_ty = Type.fromInterned(tuple_type.types.get(ip)[i]); - try field_ty.resolveFully(pt); - }, - .struct_type => return ty.resolveStructInner(pt, .full), - else => unreachable, - }, - .@"union" => return ty.resolveUnionInner(pt, .full), - } -} - -pub fn resolveStructFieldInits(ty: Type, pt: Zcu.PerThread) SemaError!void { - // TODO: stop calling this for tuples! - _ = pt.zcu.typeToStruct(ty) orelse return; - return ty.resolveStructInner(pt, .inits); -} - -pub fn resolveStructAlignment(ty: Type, pt: Zcu.PerThread) SemaError!void { - return ty.resolveStructInner(pt, .alignment); -} - -pub fn resolveUnionAlignment(ty: Type, pt: Zcu.PerThread) SemaError!void { - return ty.resolveUnionInner(pt, .alignment); -} - -/// `ty` must be a struct. -fn resolveStructInner( - ty: Type, - pt: Zcu.PerThread, - resolution: enum { fields, inits, alignment, layout, full }, -) SemaError!void { - const zcu = pt.zcu; - const gpa = zcu.gpa; - - const struct_obj = zcu.typeToStruct(ty).?; - const owner: InternPool.AnalUnit = .wrap(.{ .type = ty.toIntern() }); - - if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) { - return error.AnalysisFail; - } - - if (zcu.comp.debugIncremental()) { - const info = try zcu.incremental_debug_state.getUnitInfo(gpa, owner); - info.last_update_gen = zcu.generation; - } - - var analysis_arena = std.heap.ArenaAllocator.init(gpa); - defer analysis_arena.deinit(); - - var comptime_err_ret_trace = std.array_list.Managed(Zcu.LazySrcLoc).init(gpa); - defer comptime_err_ret_trace.deinit(); - - const zir = zcu.namespacePtr(struct_obj.namespace).fileScope(zcu).zir.?; - var sema: Sema = .{ - .pt = pt, - .gpa = gpa, - .arena = analysis_arena.allocator(), - .code = zir, - .owner = owner, - .func_index = .none, - .func_is_naked = false, - .fn_ret_ty = Type.void, - .fn_ret_ty_ies = null, - .comptime_err_ret_trace = &comptime_err_ret_trace, - }; - defer sema.deinit(); - - (switch (resolution) { - .fields => sema.resolveStructFieldTypes(ty.toIntern(), struct_obj), - .inits => sema.resolveStructFieldInits(ty), - .alignment => sema.resolveStructAlignment(ty.toIntern(), struct_obj), - .layout => sema.resolveStructLayout(ty), - .full => sema.resolveStructFully(ty), - }) catch |err| switch (err) { - error.AnalysisFail => { - if (!zcu.failed_analysis.contains(owner)) { - try zcu.transitive_failed_analysis.put(gpa, owner, {}); - } - return error.AnalysisFail; - }, - error.OutOfMemory, error.Canceled => |e| return e, - }; -} - -/// `ty` must be a union. -fn resolveUnionInner( - ty: Type, - pt: Zcu.PerThread, - resolution: enum { fields, alignment, layout, full }, -) SemaError!void { - const zcu = pt.zcu; - const gpa = zcu.gpa; - - const union_obj = zcu.typeToUnion(ty).?; - const owner: InternPool.AnalUnit = .wrap(.{ .type = ty.toIntern() }); - - if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) { - return error.AnalysisFail; - } - - if (zcu.comp.debugIncremental()) { - const info = try zcu.incremental_debug_state.getUnitInfo(gpa, owner); - info.last_update_gen = zcu.generation; - } - - var analysis_arena = std.heap.ArenaAllocator.init(gpa); - defer analysis_arena.deinit(); - - var comptime_err_ret_trace = std.array_list.Managed(Zcu.LazySrcLoc).init(gpa); - defer comptime_err_ret_trace.deinit(); - - const zir = zcu.namespacePtr(union_obj.namespace).fileScope(zcu).zir.?; - var sema: Sema = .{ - .pt = pt, - .gpa = gpa, - .arena = analysis_arena.allocator(), - .code = zir, - .owner = owner, - .func_index = .none, - .func_is_naked = false, - .fn_ret_ty = Type.void, - .fn_ret_ty_ies = null, - .comptime_err_ret_trace = &comptime_err_ret_trace, - }; - defer sema.deinit(); - - (switch (resolution) { - .fields => sema.resolveUnionFieldTypes(ty, union_obj), - .alignment => sema.resolveUnionAlignment(ty, union_obj), - .layout => sema.resolveUnionLayout(ty), - .full => sema.resolveUnionFully(ty), - }) catch |err| switch (err) { - error.AnalysisFail => { - if (!zcu.failed_analysis.contains(owner)) { - try zcu.transitive_failed_analysis.put(gpa, owner, {}); - } - return error.AnalysisFail; - }, - error.OutOfMemory => |e| return e, - error.Canceled => |e| return e, - }; -} - pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) Zcu.UnionLayout { const ip = &zcu.intern_pool; - assert(loaded_union.haveLayout(ip)); var most_aligned_field: u32 = 0; var most_aligned_field_align: InternPool.Alignment = .@"1"; var most_aligned_field_size: u64 = 0; @@ -3928,11 +2694,14 @@ pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) const field_ty: Type = .fromInterned(field_ty_ip_index); if (field_ty.isNoReturn(zcu)) continue; - const explicit_align = loaded_union.fieldAlign(ip, field_index); - const field_align = if (explicit_align != .none) - explicit_align - else - field_ty.abiAlignment(zcu); + const field_align: InternPool.Alignment = a: { + const explicit_aligns = loaded_union.field_aligns.get(ip); + if (explicit_aligns.len > 0) { + const a = explicit_aligns[field_index]; + if (a != .none) break :a a; + } + break :a field_ty.abiAlignment(zcu); + }; if (field_ty.hasRuntimeBits(zcu)) { const field_size = field_ty.abiSize(zcu); if (field_size > payload_size) { @@ -3947,8 +2716,9 @@ pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) } payload_align = payload_align.max(field_align); } - const have_tag = loaded_union.flagsUnordered(ip).runtime_tag.hasTag(); - if (!have_tag or !Type.fromInterned(loaded_union.enum_tag_ty).hasRuntimeBits(zcu)) { + if (loaded_union.runtime_tag == .none or + !Type.fromInterned(loaded_union.enum_tag_type).hasRuntimeBits(zcu)) + { return .{ .abi_size = payload_align.forward(payload_size), .abi_align = payload_align, @@ -3963,10 +2733,10 @@ pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) }; } - const tag_size = Type.fromInterned(loaded_union.enum_tag_ty).abiSize(zcu); - const tag_align = Type.fromInterned(loaded_union.enum_tag_ty).abiAlignment(zcu).max(.@"1"); + const tag_size = Type.fromInterned(loaded_union.enum_tag_type).abiSize(zcu); + const tag_align = Type.fromInterned(loaded_union.enum_tag_type).abiAlignment(zcu).max(.@"1"); return .{ - .abi_size = loaded_union.sizeUnordered(ip), + .abi_size = loaded_union.size, .abi_align = tag_align.max(payload_align), .most_aligned_field = most_aligned_field, .most_aligned_field_size = most_aligned_field_size, @@ -3975,7 +2745,7 @@ pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) .payload_align = payload_align, .tag_align = tag_align, .tag_size = tag_size, - .padding = loaded_union.paddingUnordered(ip), + .padding = loaded_union.padding, }; } @@ -3989,10 +2759,17 @@ pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) /// Handles const-ness and address spaces in particular. /// This code is duplicated in `Sema.analyzePtrArithmetic`. /// May perform type resolution and return a transitive `error.AnalysisFail`. +/// MLUGG TODO audit this shit pub fn elemPtrType(ptr_ty: Type, offset: ?usize, pt: Zcu.PerThread) !Type { const zcu = pt.zcu; const ptr_info = ptr_ty.ptrInfo(zcu); - const elem_ty = ptr_ty.elemType2(zcu); + const elem_ty: Type = switch (ptr_info.flags.size) { + .one => switch (Type.fromInterned(ptr_info.child).zigTypeTag(zcu)) { + .array, .vector => Type.fromInterned(ptr_info.child).childType(zcu), + else => .fromInterned(ptr_info.child), + }, + .many, .c, .slice => .fromInterned(ptr_info.child), + }; const is_allowzero = ptr_info.flags.is_allowzero and (offset orelse 0) == 0; const parent_ty = ptr_ty.childType(zcu); @@ -4024,7 +2801,7 @@ pub fn elemPtrType(ptr_ty: Type, offset: ?usize, pt: Zcu.PerThread) !Type { } // If the addend is not a comptime-known value we can still count on // it being a multiple of the type size. - const elem_size = (try elem_ty.abiSizeInner(.sema, zcu, pt.tid)).scalar; + const elem_size = elem_ty.abiSize(zcu); const addend = if (offset) |off| elem_size * off else elem_size; // The resulting pointer is aligned to the lcd between the offset (an @@ -4037,7 +2814,7 @@ pub fn elemPtrType(ptr_ty: Type, offset: ?usize, pt: Zcu.PerThread) !Type { assert(new_align != .none); break :a new_align; }; - return pt.ptrTypeSema(.{ + return pt.ptrType(.{ .child = elem_ty.toIntern(), .flags = .{ .alignment = alignment, @@ -4069,11 +2846,107 @@ pub fn containerTypeName(ty: Type, ip: *const InternPool) InternPool.NullTermina /// Returns `null` otherwise. pub fn isNullFromType(ty: Type, zcu: *const Zcu) ?bool { if (ty.zigTypeTag(zcu) != .optional and !ty.isCPtr(zcu)) return false; - const child = ty.optionalChild(zcu); - if (child.zigTypeTag(zcu) == .noreturn) return true; // `?noreturn` is always null + if (ty.optionalChild(zcu).isNoReturn(zcu)) return true; // `?noreturn` is always null return null; } +/// Returns true if `ty` is allowed in packed types. +pub fn packable(ty: Type, zcu: *const Zcu) bool { + return switch (ty.zigTypeTag(zcu)) { + .type, + .comptime_float, + .comptime_int, + .enum_literal, + .undefined, + .null, + .error_union, + .error_set, + .frame, + .noreturn, + .@"opaque", + .@"anyframe", + .@"fn", + .array, + => false, + .optional => return ty.isPtrLikeOptional(zcu), + .void, + .bool, + .float, + .int, + .vector, + => true, + .@"enum" => zcu.intern_pool.loadEnumType(ty.toIntern()).int_tag_is_explicit, + .pointer => !ty.isSlice(zcu), + .@"struct", .@"union" => ty.containerLayout(zcu) == .@"packed", + }; +} + +/// Asserts that `ty` has resolved layout. +pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void { + switch (zcu.intern_pool.indexToKey(ty.toIntern())) { + .int_type, + .ptr_type, + .anyframe_type, + .simple_type, + .opaque_type, + .enum_type, + .error_set_type, + .inferred_error_set_type, + => {}, + .func_type => |func_type| { + for (func_type.param_types.get(&zcu.intern_pool)) |param_ty| { + assertHasLayout(.fromInterned(param_ty), zcu); + } + assertHasLayout(.fromInterned(func_type.return_type), zcu); + }, + .array_type => |arr| assertHasLayout(.fromInterned(arr.child), zcu), + .vector_type => |vec| assertHasLayout(.fromInterned(vec.child), zcu), + .opt_type => |child| assertHasLayout(.fromInterned(child), zcu), + .error_union_type => |eu| assertHasLayout(.fromInterned(eu.payload_type), zcu), + .tuple_type => |tuple| for (tuple.types.get(&zcu.intern_pool)) |field_ty| { + assertHasLayout(.fromInterned(field_ty), zcu); + }, + .struct_type, .union_type => { + const unit: InternPool.AnalUnit = .wrap(.{ .type_layout = ty.toIntern() }); + assert(!zcu.outdated.contains(unit)); + assert(!zcu.potentially_outdated.contains(unit)); + }, + else => unreachable, // assertion failure; not a struct or union + + // values, not types + .simple_value, + .variable, + .@"extern", + .func, + .int, + .err, + .error_union, + .enum_literal, + .enum_tag, + .empty_enum_value, + .float, + .ptr, + .slice, + .opt, + .aggregate, + .un, + // memoization, not types + .memoized_call, + => unreachable, + } +} + +/// Asserts that `ty` is an enum or struct type whose field values/defaults are resolved. +pub fn assertHasInits(ty: Type, zcu: *const Zcu) void { + switch (zcu.intern_pool.indexToKey(ty.toIntern())) { + .struct_type, .enum_type => {}, + else => unreachable, + } + const unit: InternPool.AnalUnit = .wrap(.{ .type_inits = ty.toIntern() }); + assert(!zcu.outdated.contains(unit)); + assert(!zcu.potentially_outdated.contains(unit)); +} + /// Recursively walks the type and marks for each subtype how many times it has been seen fn collectSubtypes(ty: Type, pt: Zcu.PerThread, visited: *std.AutoArrayHashMapUnmanaged(Type, u16)) error{OutOfMemory}!void { const zcu = pt.zcu; diff --git a/src/Value.zig b/src/Value.zig index 103140d3c9a3df0878f1ceb254ba2bb483ea2865..5986eee6d652b135fd2b28bfc2f839bdd578486e 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -146,80 +146,22 @@ pub fn toType(self: Value) Type { return Type.fromInterned(self.toIntern()); } -pub fn intFromEnum(val: Value, ty: Type, pt: Zcu.PerThread) Allocator.Error!Value { - const ip = &pt.zcu.intern_pool; - const enum_ty = ip.typeOf(val.toIntern()); - return switch (ip.indexToKey(enum_ty)) { - // Assume it is already an integer and return it directly. - .simple_type, .int_type => val, - .enum_literal => |enum_literal| { - const field_index = ty.enumFieldIndex(enum_literal, pt.zcu).?; - switch (ip.indexToKey(ty.toIntern())) { - // Assume it is already an integer and return it directly. - .simple_type, .int_type => return val, - .enum_type => { - const enum_type = ip.loadEnumType(ty.toIntern()); - if (enum_type.values.len != 0) { - return Value.fromInterned(enum_type.values.get(ip)[field_index]); - } else { - // Field index and integer values are the same. - return pt.intValue(Type.fromInterned(enum_type.tag_ty), field_index); - } - }, - else => unreachable, - } - }, - .enum_type => try pt.getCoerced(val, Type.fromInterned(ip.loadEnumType(enum_ty).tag_ty)), - else => unreachable, - }; +pub fn intFromEnum(val: Value, zcu: *const Zcu) Value { + return .fromInterned(zcu.intern_pool.indexToKey(val.toIntern()).enum_tag.int); } -pub const ResolveStrat = Type.ResolveStrat; - -/// Asserts the value is an integer. +/// Asserts that `val` is an integer. pub fn toBigInt(val: Value, space: *BigIntSpace, zcu: *Zcu) BigIntConst { - return val.toBigIntAdvanced(space, .normal, zcu, {}) catch unreachable; -} - -pub fn toBigIntSema(val: Value, space: *BigIntSpace, pt: Zcu.PerThread) !BigIntConst { - return try val.toBigIntAdvanced(space, .sema, pt.zcu, pt.tid); -} - -/// Asserts the value is an integer. -pub fn toBigIntAdvanced( - val: Value, - space: *BigIntSpace, - comptime strat: ResolveStrat, - zcu: *Zcu, - tid: strat.Tid(), -) Zcu.SemaError!BigIntConst { + if (val.getUnsignedInt(zcu)) |x| { + return BigIntMutable.init(&space.limbs, x).toConst(); + } const ip = &zcu.intern_pool; - return switch (val.toIntern()) { - .bool_false => BigIntMutable.init(&space.limbs, 0).toConst(), - .bool_true => BigIntMutable.init(&space.limbs, 1).toConst(), - .null_value => BigIntMutable.init(&space.limbs, 0).toConst(), - else => switch (ip.indexToKey(val.toIntern())) { - .int => |int| switch (int.storage) { - .u64, .i64, .big_int => int.storage.toBigInt(space), - .lazy_align, .lazy_size => |ty| { - if (strat == .sema) try Type.fromInterned(ty).resolveLayout(strat.pt(zcu, tid)); - const x = switch (int.storage) { - else => unreachable, - .lazy_align => Type.fromInterned(ty).abiAlignment(zcu).toByteUnits() orelse 0, - .lazy_size => Type.fromInterned(ty).abiSize(zcu), - }; - return BigIntMutable.init(&space.limbs, x).toConst(); - }, - }, - .enum_tag => |enum_tag| Value.fromInterned(enum_tag.int).toBigIntAdvanced(space, strat, zcu, tid), - .opt, .ptr => BigIntMutable.init( - &space.limbs, - (try val.getUnsignedIntInner(strat, zcu, tid)).?, - ).toConst(), - .err => |err| BigIntMutable.init(&space.limbs, ip.getErrorValueIfExists(err.name).?).toConst(), - else => unreachable, - }, + const int_key = switch (ip.indexToKey(val.toIntern())) { + .enum_tag => |enum_tag| ip.indexToKey(enum_tag.int).int, + .int => |int| int, + else => unreachable, }; + return int_key.storage.toBigInt(space); } pub fn isFuncBody(val: Value, zcu: *Zcu) bool { @@ -240,31 +182,17 @@ pub fn getVariable(val: Value, mod: *Zcu) ?InternPool.Key.Variable { }; } -/// If the value fits in a u64, return it, otherwise null. -/// Asserts not undefined. -pub fn getUnsignedInt(val: Value, zcu: *const Zcu) ?u64 { - return getUnsignedIntInner(val, .normal, zcu, {}) catch unreachable; -} - -/// Asserts the value is an integer and it fits in a u64 +/// Asserts the value is a (defined) integer and it fits in a u64. pub fn toUnsignedInt(val: Value, zcu: *const Zcu) u64 { return getUnsignedInt(val, zcu).?; } -pub fn getUnsignedIntSema(val: Value, pt: Zcu.PerThread) !?u64 { - return try val.getUnsignedIntInner(.sema, pt.zcu, pt.tid); -} - /// If the value fits in a u64, return it, otherwise null. /// Asserts not undefined. -pub fn getUnsignedIntInner( - val: Value, - comptime strat: ResolveStrat, - zcu: strat.ZcuPtr(), - tid: strat.Tid(), -) !?u64 { +pub fn getUnsignedInt(val: Value, zcu: *const Zcu) ?u64 { return switch (val.toIntern()) { .undef => unreachable, + .null_value => 0, .bool_false => 0, .bool_true => 1, else => switch (zcu.intern_pool.indexToKey(val.toIntern())) { @@ -273,37 +201,27 @@ pub fn getUnsignedIntInner( .big_int => |big_int| big_int.toInt(u64) catch null, .u64 => |x| x, .i64 => |x| std.math.cast(u64, x), - .lazy_align => |ty| (try Type.fromInterned(ty).abiAlignmentInner(strat.toLazy(), zcu, tid)).scalar.toByteUnits() orelse 0, - .lazy_size => |ty| (try Type.fromInterned(ty).abiSizeInner(strat.toLazy(), zcu, tid)).scalar, }, .ptr => |ptr| switch (ptr.base_addr) { .int => ptr.byte_offset, .field => |field| { - const base_addr = (try Value.fromInterned(field.base).getUnsignedIntInner(strat, zcu, tid)) orelse return null; + const base_addr = Value.fromInterned(field.base).getUnsignedInt(zcu) orelse return null; const struct_ty = Value.fromInterned(field.base).typeOf(zcu).childType(zcu); - if (strat == .sema) { - const pt = strat.pt(zcu, tid); - try struct_ty.resolveLayout(pt); - } return base_addr + struct_ty.structFieldOffset(@intCast(field.index), zcu) + ptr.byte_offset; }, else => null, }, .opt => |opt| switch (opt.val) { .none => 0, - else => |payload| Value.fromInterned(payload).getUnsignedIntInner(strat, zcu, tid), + else => |payload| Value.fromInterned(payload).getUnsignedInt(zcu), }, - .enum_tag => |enum_tag| return Value.fromInterned(enum_tag.int).getUnsignedIntInner(strat, zcu, tid), + .enum_tag => |enum_tag| Value.fromInterned(enum_tag.int).getUnsignedInt(zcu), + .err => |err| zcu.intern_pool.getErrorValueIfExists(err.name).?, else => null, }, }; } -/// Asserts the value is an integer and it fits in a u64 -pub fn toUnsignedIntSema(val: Value, pt: Zcu.PerThread) !u64 { - return (try getUnsignedIntInner(val, .sema, pt.zcu, pt.tid)).?; -} - /// Asserts the value is an integer and it fits in a i64 pub fn toSignedInt(val: Value, zcu: *const Zcu) i64 { return switch (val.toIntern()) { @@ -314,8 +232,6 @@ pub fn toSignedInt(val: Value, zcu: *const Zcu) i64 { .big_int => |big_int| big_int.toInt(i64) catch unreachable, .i64 => |x| x, .u64 => |x| @intCast(x), - .lazy_align => |ty| @intCast(Type.fromInterned(ty).abiAlignment(zcu).toByteUnits() orelse 0), - .lazy_size => |ty| @intCast(Type.fromInterned(ty).abiSize(zcu)), }, else => unreachable, }, @@ -487,22 +403,16 @@ pub fn writeToPackedMemory( buffer[byte_index] &= ~(@as(u8, 1) << @as(u3, @intCast(bit_offset % 8))); } }, - .int, .@"enum" => { - if (buffer.len == 0) return; + .@"enum" => { + const int_val = val.intFromEnum(zcu); + return int_val.writeToPackedMemory(int_val.typeOf(zcu), pt, buffer, bit_offset); + }, + .int => { const bits = ty.intInfo(zcu).bits; - if (bits == 0) return; - - switch (ip.indexToKey((try val.intFromEnum(ty, pt)).toIntern()).int.storage) { + if (bits == 0 or buffer.len == 0) return; + switch (ip.indexToKey(val.toIntern()).int.storage) { inline .u64, .i64 => |int| std.mem.writeVarPackedInt(buffer, bit_offset, bits, int, endian), .big_int => |bigint| bigint.writePackedTwosComplement(buffer, bit_offset, bits, endian), - .lazy_align => |lazy_align| { - const num = Type.fromInterned(lazy_align).abiAlignment(zcu).toByteUnits() orelse 0; - std.mem.writeVarPackedInt(buffer, bit_offset, bits, num, endian); - }, - .lazy_size => |lazy_size| { - const num = Type.fromInterned(lazy_size).abiSize(zcu); - std.mem.writeVarPackedInt(buffer, bit_offset, bits, num, endian); - }, } }, .float => switch (ty.floatBits(target)) { @@ -548,19 +458,15 @@ pub fn writeToPackedMemory( }, .@"union" => { const union_obj = zcu.typeToUnion(ty).?; - switch (union_obj.flagsUnordered(ip).layout) { - .auto, .@"extern" => unreachable, // Handled in non-packed writeToMemory - .@"packed" => { - if (val.unionTag(zcu)) |union_tag| { - const field_index = zcu.unionTagFieldIndex(union_obj, union_tag).?; - const field_type = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); - const field_val = try val.fieldValue(pt, field_index); - return field_val.writeToPackedMemory(field_type, pt, buffer, bit_offset); - } else { - const backing_ty = try ty.unionBackingType(pt); - return val.unionValue(zcu).writeToPackedMemory(backing_ty, pt, buffer, bit_offset); - } - }, + assert(union_obj.layout == .@"packed"); + if (val.unionTag(zcu)) |union_tag| { + const field_index = zcu.unionTagFieldIndex(union_obj, union_tag).?; + const field_type = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); + const field_val = try val.fieldValue(pt, field_index); + return field_val.writeToPackedMemory(field_type, pt, buffer, bit_offset); + } else { + const backing_ty = try ty.unionBackingType(pt); + return val.unionValue(zcu).writeToPackedMemory(backing_ty, pt, buffer, bit_offset); } }, .pointer => { @@ -729,24 +635,15 @@ pub fn readFromPackedMemory( }, .pointer => { assert(!ty.isSlice(zcu)); // No well defined layout. - const int_val = try readFromPackedMemory(Type.usize, pt, buffer, bit_offset, arena); - return Value.fromInterned(try pt.intern(.{ .ptr = .{ - .ty = ty.toIntern(), - .base_addr = .int, - .byte_offset = int_val.toUnsignedInt(zcu), - } })); + const addr = (try readFromPackedMemory(Type.usize, pt, buffer, bit_offset, arena)).toUnsignedInt(zcu); + return pt.ptrIntValue(ty, addr); }, .optional => { assert(ty.isPtrLikeOptional(zcu)); - const child_ty = ty.optionalChild(zcu); - const child_val = try readFromPackedMemory(child_ty, pt, buffer, bit_offset, arena); + const addr = (try readFromPackedMemory(Type.usize, pt, buffer, bit_offset, arena)).toUnsignedInt(zcu); return Value.fromInterned(try pt.intern(.{ .opt = .{ .ty = ty.toIntern(), - .val = switch (child_val.orderAgainstZero(zcu)) { - .lt => unreachable, - .eq => .none, - .gt => child_val.toIntern(), - }, + .val = (try pt.ptrIntValue(ty.childType(zcu), addr)).toIntern(), } })); }, else => @panic("TODO implement readFromPackedMemory for more types"), @@ -764,8 +661,6 @@ pub fn toFloat(val: Value, comptime T: type, zcu: *const Zcu) T { } return @floatFromInt(x); }, - .lazy_align => |ty| @floatFromInt(Type.fromInterned(ty).abiAlignment(zcu).toByteUnits() orelse 0), - .lazy_size => |ty| @floatFromInt(Type.fromInterned(ty).abiSize(zcu)), }, .float => |float| switch (float.storage) { inline else => |x| @floatCast(x), @@ -819,110 +714,8 @@ pub fn floatCast(val: Value, dest_ty: Type, pt: Zcu.PerThread) !Value { } })); } -pub fn orderAgainstZero(lhs: Value, zcu: *Zcu) std.math.Order { - return orderAgainstZeroInner(lhs, .normal, zcu, {}) catch unreachable; -} - -pub fn orderAgainstZeroSema(lhs: Value, pt: Zcu.PerThread) !std.math.Order { - return try orderAgainstZeroInner(lhs, .sema, pt.zcu, pt.tid); -} - -pub fn orderAgainstZeroInner( - lhs: Value, - comptime strat: ResolveStrat, - zcu: *Zcu, - tid: strat.Tid(), -) Zcu.SemaError!std.math.Order { - return switch (lhs.toIntern()) { - .bool_false => .eq, - .bool_true => .gt, - else => switch (zcu.intern_pool.indexToKey(lhs.toIntern())) { - .ptr => |ptr| if (ptr.byte_offset > 0) .gt else switch (ptr.base_addr) { - .nav, .comptime_alloc, .comptime_field => .gt, - .int => .eq, - else => unreachable, - }, - .int => |int| switch (int.storage) { - .big_int => |big_int| big_int.orderAgainstScalar(0), - inline .u64, .i64 => |x| std.math.order(x, 0), - .lazy_align => .gt, // alignment is never 0 - .lazy_size => |ty| return if (Type.fromInterned(ty).hasRuntimeBitsInner( - false, - strat.toLazy(), - zcu, - tid, - ) catch |err| switch (err) { - error.NeedLazy => unreachable, - else => |e| return e, - }) .gt else .eq, - }, - .enum_tag => |enum_tag| Value.fromInterned(enum_tag.int).orderAgainstZeroInner(strat, zcu, tid), - .float => |float| switch (float.storage) { - inline else => |x| std.math.order(x, 0), - }, - .err => .gt, // error values cannot be 0 - else => unreachable, - }, - }; -} - -/// Asserts the value is comparable. -pub fn order(lhs: Value, rhs: Value, zcu: *Zcu) std.math.Order { - return orderAdvanced(lhs, rhs, .normal, zcu, {}) catch unreachable; -} - -/// Asserts the value is comparable. -pub fn orderAdvanced( - lhs: Value, - rhs: Value, - comptime strat: ResolveStrat, - zcu: *Zcu, - tid: strat.Tid(), -) !std.math.Order { - const lhs_against_zero = try lhs.orderAgainstZeroInner(strat, zcu, tid); - const rhs_against_zero = try rhs.orderAgainstZeroInner(strat, zcu, tid); - switch (lhs_against_zero) { - .lt => if (rhs_against_zero != .lt) return .lt, - .eq => return rhs_against_zero.invert(), - .gt => {}, - } - switch (rhs_against_zero) { - .lt => if (lhs_against_zero != .lt) return .gt, - .eq => return lhs_against_zero, - .gt => {}, - } - - if (lhs.isFloat(zcu) or rhs.isFloat(zcu)) { - const lhs_f128 = lhs.toFloat(f128, zcu); - const rhs_f128 = rhs.toFloat(f128, zcu); - return std.math.order(lhs_f128, rhs_f128); - } - - var lhs_bigint_space: BigIntSpace = undefined; - var rhs_bigint_space: BigIntSpace = undefined; - const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_bigint_space, strat, zcu, tid); - const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_bigint_space, strat, zcu, tid); - return lhs_bigint.order(rhs_bigint); -} - -/// Asserts the value is comparable. Does not take a type parameter because it supports -/// comparisons between heterogeneous types. +/// Asserts the value is comparable. Supports comparisons between heterogeneous types. pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value, zcu: *Zcu) bool { - return compareHeteroAdvanced(lhs, op, rhs, .normal, zcu, {}) catch unreachable; -} - -pub fn compareHeteroSema(lhs: Value, op: std.math.CompareOperator, rhs: Value, pt: Zcu.PerThread) !bool { - return try compareHeteroAdvanced(lhs, op, rhs, .sema, pt.zcu, pt.tid); -} - -pub fn compareHeteroAdvanced( - lhs: Value, - op: std.math.CompareOperator, - rhs: Value, - comptime strat: ResolveStrat, - zcu: *Zcu, - tid: strat.Tid(), -) !bool { if (lhs.pointerNav(zcu)) |lhs_nav| { if (rhs.pointerNav(zcu)) |rhs_nav| { switch (op) { @@ -944,9 +737,21 @@ pub fn compareHeteroAdvanced( else => {}, } } - if (lhs.isNan(zcu) or rhs.isNan(zcu)) return op == .neq; - return (try orderAdvanced(lhs, rhs, strat, zcu, tid)).compare(op); + return order(lhs, rhs, zcu).compare(op); +} + +pub fn order(lhs: Value, rhs: Value, zcu: *Zcu) std.math.Order { + if (lhs.isFloat(zcu) or rhs.isFloat(zcu)) { + const lhs_f128 = lhs.toFloat(f128, zcu); + const rhs_f128 = rhs.toFloat(f128, zcu); + return std.math.order(lhs_f128, rhs_f128); + } + var lhs_bigint_space: BigIntSpace = undefined; + var rhs_bigint_space: BigIntSpace = undefined; + const lhs_bigint = lhs.toBigInt(&lhs_bigint_space, zcu); + const rhs_bigint = rhs.toBigInt(&rhs_bigint_space, zcu); + return lhs_bigint.order(rhs_bigint); } /// Asserts the values are comparable. Both operands have type `ty`. @@ -987,56 +792,32 @@ pub fn compareScalar( /// Returns `false` if the value or any vector element is undefined. /// /// Note that `!compareAllWithZero(.eq, ...) != compareAllWithZero(.neq, ...)` +/// TODO MLUGG: lowkey wanna delete this pub fn compareAllWithZero(lhs: Value, op: std.math.CompareOperator, zcu: *Zcu) bool { - return compareAllWithZeroAdvancedExtra(lhs, op, .normal, zcu, {}) catch unreachable; -} - -pub fn compareAllWithZeroSema( - lhs: Value, - op: std.math.CompareOperator, - pt: Zcu.PerThread, -) Zcu.CompileError!bool { - return compareAllWithZeroAdvancedExtra(lhs, op, .sema, pt.zcu, pt.tid); -} - -pub fn compareAllWithZeroAdvancedExtra( - lhs: Value, - op: std.math.CompareOperator, - comptime strat: ResolveStrat, - zcu: *Zcu, - tid: strat.Tid(), -) Zcu.CompileError!bool { - if (lhs.isInf(zcu)) { - switch (op) { - .neq => return true, - .eq => return false, - .gt, .gte => return !lhs.isNegativeInf(zcu), - .lt, .lte => return lhs.isNegativeInf(zcu), - } - } - - switch (zcu.intern_pool.indexToKey(lhs.toIntern())) { + return switch (zcu.intern_pool.indexToKey(lhs.toIntern())) { .float => |float| switch (float.storage) { - inline else => |x| if (std.math.isNan(x)) return op == .neq, + inline else => |x| std.math.compare(x, op, 0), }, - .aggregate => |aggregate| return switch (aggregate.storage) { - .bytes => |bytes| for (bytes.toSlice(lhs.typeOf(zcu).arrayLenIncludingSentinel(zcu), &zcu.intern_pool)) |byte| { - if (!std.math.order(byte, 0).compare(op)) break false; + .aggregate => |aggregate| switch (aggregate.storage) { + .bytes => |bytes| for (bytes.toSlice( + lhs.typeOf(zcu).arrayLenIncludingSentinel(zcu), + &zcu.intern_pool, + )) |byte| { + if (!std.math.compare(byte, op, 0)) break false; } else true, .elems => |elems| for (elems) |elem| { - if (!try Value.fromInterned(elem).compareAllWithZeroAdvancedExtra(op, strat, zcu, tid)) break false; + if (!Value.fromInterned(elem).compareAllWithZero(op, zcu)) break false; } else true, - .repeated_elem => |elem| Value.fromInterned(elem).compareAllWithZeroAdvancedExtra(op, strat, zcu, tid), + .repeated_elem => |elem| Value.fromInterned(elem).compareAllWithZero(op, zcu), }, - .undef => return false, - else => {}, - } - return (try orderAgainstZeroInner(lhs, strat, zcu, tid)).compare(op); + .undef => false, + else => order(lhs, .zero_comptime_int, zcu).compare(op), + }; } pub fn eql(a: Value, b: Value, ty: Type, zcu: *Zcu) bool { - assert(zcu.intern_pool.typeOf(a.toIntern()) == ty.toIntern()); - assert(zcu.intern_pool.typeOf(b.toIntern()) == ty.toIntern()); + assert(a.typeOf(zcu).toIntern() == ty.toIntern()); + assert(b.typeOf(zcu).toIntern() == ty.toIntern()); return a.toIntern() == b.toIntern(); } @@ -1088,16 +869,13 @@ pub fn pointerNav(val: Value, zcu: *Zcu) ?InternPool.Nav.Index { pub const slice_ptr_index = 0; pub const slice_len_index = 1; +pub fn sliceLen(val: Value, zcu: *Zcu) u64 { + return Value.fromInterned(zcu.intern_pool.sliceLen(val.toIntern())).toUnsignedInt(zcu); +} pub fn slicePtr(val: Value, zcu: *Zcu) Value { return Value.fromInterned(zcu.intern_pool.slicePtr(val.toIntern())); } -/// Gets the `len` field of a slice value as a `u64`. -/// Resolves the length using `Sema` if necessary. -pub fn sliceLen(val: Value, pt: Zcu.PerThread) !u64 { - return Value.fromInterned(pt.zcu.intern_pool.sliceLen(val.toIntern())).toUnsignedIntSema(pt); -} - /// Asserts the value is an aggregate, and returns the element value at the given index. pub fn elemValue(val: Value, pt: Zcu.PerThread, index: usize) Allocator.Error!Value { const zcu = pt.zcu; @@ -1123,62 +901,6 @@ pub fn elemValue(val: Value, pt: Zcu.PerThread, index: usize) Allocator.Error!Va } } -pub fn isLazyAlign(val: Value, zcu: *Zcu) bool { - return switch (zcu.intern_pool.indexToKey(val.toIntern())) { - .int => |int| int.storage == .lazy_align, - else => false, - }; -} - -pub fn isLazySize(val: Value, zcu: *Zcu) bool { - return switch (zcu.intern_pool.indexToKey(val.toIntern())) { - .int => |int| int.storage == .lazy_size, - else => false, - }; -} - -// Asserts that the provided start/end are in-bounds. -pub fn sliceArray( - val: Value, - sema: *Sema, - start: usize, - end: usize, -) error{OutOfMemory}!Value { - const pt = sema.pt; - const ip = &pt.zcu.intern_pool; - const io = pt.zcu.comp.io; - return Value.fromInterned(try pt.intern(.{ - .aggregate = .{ - .ty = switch (pt.zcu.intern_pool.indexToKey(pt.zcu.intern_pool.typeOf(val.toIntern()))) { - .array_type => |array_type| try pt.arrayType(.{ - .len = @intCast(end - start), - .child = array_type.child, - .sentinel = if (end == array_type.len) array_type.sentinel else .none, - }), - .vector_type => |vector_type| try pt.vectorType(.{ - .len = @intCast(end - start), - .child = vector_type.child, - }), - else => unreachable, - }.toIntern(), - .storage = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { - .bytes => |bytes| storage: { - try ip.string_bytes.ensureUnusedCapacity(sema.gpa, end - start + 1); - break :storage .{ .bytes = try ip.getOrPutString( - sema.gpa, - io, - bytes.toSlice(end, ip)[start..], - .maybe_embedded_nulls, - ) }; - }, - // TODO: write something like getCoercedInts to avoid needing to dupe - .elems => |elems| .{ .elems = try sema.arena.dupe(InternPool.Index, elems[start..end]) }, - .repeated_elem => |elem| .{ .repeated_elem = elem }, - }, - }, - })); -} - pub fn fieldValue(val: Value, pt: Zcu.PerThread, index: usize) !Value { const zcu = pt.zcu; return switch (zcu.intern_pool.indexToKey(val.toIntern())) { @@ -1334,63 +1056,6 @@ pub fn isFloat(self: Value, zcu: *const Zcu) bool { }; } -pub fn floatFromInt(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, zcu: *Zcu) !Value { - return floatFromIntAdvanced(val, arena, int_ty, float_ty, zcu, .normal) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - else => unreachable, - }; -} - -pub fn floatFromIntAdvanced( - val: Value, - arena: Allocator, - int_ty: Type, - float_ty: Type, - pt: Zcu.PerThread, - comptime strat: ResolveStrat, -) !Value { - const zcu = pt.zcu; - if (int_ty.zigTypeTag(zcu) == .vector) { - const result_data = try arena.alloc(InternPool.Index, int_ty.vectorLen(zcu)); - const scalar_ty = float_ty.scalarType(zcu); - for (result_data, 0..) |*scalar, i| { - const elem_val = try val.elemValue(pt, i); - scalar.* = (try floatFromIntScalar(elem_val, scalar_ty, pt, strat)).toIntern(); - } - return pt.aggregateValue(float_ty, result_data); - } - return floatFromIntScalar(val, float_ty, pt, strat); -} - -pub fn floatFromIntScalar(val: Value, float_ty: Type, pt: Zcu.PerThread, comptime strat: ResolveStrat) !Value { - return switch (pt.zcu.intern_pool.indexToKey(val.toIntern())) { - .undef => try pt.undefValue(float_ty), - .int => |int| switch (int.storage) { - .big_int => |big_int| pt.floatValue(float_ty, big_int.toFloat(f128, .nearest_even)[0]), - inline .u64, .i64 => |x| floatFromIntInner(x, float_ty, pt), - .lazy_align => |ty| floatFromIntInner((try Type.fromInterned(ty).abiAlignmentInner(strat.toLazy(), pt.zcu, pt.tid)).scalar.toByteUnits() orelse 0, float_ty, pt), - .lazy_size => |ty| floatFromIntInner((try Type.fromInterned(ty).abiSizeInner(strat.toLazy(), pt.zcu, pt.tid)).scalar, float_ty, pt), - }, - else => unreachable, - }; -} - -fn floatFromIntInner(x: anytype, dest_ty: Type, pt: Zcu.PerThread) !Value { - const target = pt.zcu.getTarget(); - const storage: InternPool.Key.Float.Storage = switch (dest_ty.floatBits(target)) { - 16 => .{ .f16 = @floatFromInt(x) }, - 32 => .{ .f32 = @floatFromInt(x) }, - 64 => .{ .f64 = @floatFromInt(x) }, - 80 => .{ .f80 = @floatFromInt(x) }, - 128 => .{ .f128 = @floatFromInt(x) }, - else => unreachable, - }; - return Value.fromInterned(try pt.intern(.{ .float = .{ - .ty = dest_ty.toIntern(), - .storage = storage, - } })); -} - fn calcLimbLenFloat(scalar: anytype) usize { if (scalar == 0) { return 1; @@ -1410,11 +1075,11 @@ pub fn numberMax(lhs: Value, rhs: Value, zcu: *Zcu) Value { if (lhs.isUndef(zcu) or rhs.isUndef(zcu)) return undef; if (lhs.isNan(zcu)) return rhs; if (rhs.isNan(zcu)) return lhs; - - return switch (order(lhs, rhs, zcu)) { - .lt => rhs, - .gt, .eq => lhs, - }; + if (compareHetero(lhs, .gt, rhs, zcu)) { + return lhs; + } else { + return rhs; + } } /// Supports both floats and ints; handles undefined. @@ -1422,11 +1087,11 @@ pub fn numberMin(lhs: Value, rhs: Value, zcu: *Zcu) Value { if (lhs.isUndef(zcu) or rhs.isUndef(zcu)) return undef; if (lhs.isNan(zcu)) return rhs; if (rhs.isNan(zcu)) return lhs; - - return switch (order(lhs, rhs, zcu)) { - .lt => lhs, - .gt, .eq => rhs, - }; + if (compareHetero(lhs, .lt, rhs, zcu)) { + return lhs; + } else { + return rhs; + } } /// Returns true if the value is a floating point type and is NaN. Returns false otherwise. @@ -2035,6 +1700,7 @@ pub fn makeBool(x: bool) Value { /// Returns a pointer to the payload of the optional. /// /// May perform type resolution. +/// MLUGG TODO audit pub fn ptrOptPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value { const zcu = pt.zcu; const parent_ptr_ty = parent_ptr.typeOf(zcu); @@ -2044,7 +1710,7 @@ pub fn ptrOptPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value { assert(ptr_size == .one or ptr_size == .c); assert(opt_ty.zigTypeTag(zcu) == .optional); - const result_ty = try pt.ptrTypeSema(info: { + const result_ty = try pt.ptrType(info: { var new = parent_ptr_ty.ptrInfo(zcu); // We can correctly preserve alignment `.none`, since an optional has the same // natural alignment as its child type. @@ -2070,6 +1736,7 @@ pub fn ptrOptPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value { /// `parent_ptr` must be a single-pointer to some error union. /// Returns a pointer to the payload of the error union. /// May perform type resolution. +/// MLUGG TODO audit pub fn ptrEuPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value { const zcu = pt.zcu; const parent_ptr_ty = parent_ptr.typeOf(zcu); @@ -2078,7 +1745,7 @@ pub fn ptrEuPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value { assert(parent_ptr_ty.ptrSize(zcu) == .one); assert(eu_ty.zigTypeTag(zcu) == .error_union); - const result_ty = try pt.ptrTypeSema(info: { + const result_ty = try pt.ptrType(info: { var new = parent_ptr_ty.ptrInfo(zcu); // We can correctly preserve alignment `.none`, since an error union has a // natural alignment greater than or equal to that of its payload type. @@ -2096,6 +1763,8 @@ pub fn ptrEuPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value { } })); } +// MLUGG TODO: audit ptrField etc in terms of resolution, and probably move them under sema + /// `parent_ptr` must be a single-pointer or c pointer to a struct, union, or slice. /// /// Returns a pointer to the aggregate field at the specified index. @@ -2112,23 +1781,34 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, pt: Zcu.PerThread) !Value { assert(parent_ptr_info.flags.size == .one or parent_ptr_info.flags.size == .c); // Exiting this `switch` indicates that the `field` pointer representation should be used. - // `field_align` may be `.none` to represent the natural alignment of `field_ty`, but is not necessarily. - const field_ty: Type, const field_align: InternPool.Alignment = switch (aggregate_ty.zigTypeTag(zcu)) { + const field_ty: Type, const new_align: InternPool.Alignment = switch (aggregate_ty.zigTypeTag(zcu)) { .@"struct" => field: { const field_ty = aggregate_ty.fieldType(field_idx, zcu); switch (aggregate_ty.containerLayout(zcu)) { - .auto => break :field .{ field_ty, try aggregate_ty.fieldAlignmentSema(field_idx, pt) }, + .auto => break :field .{ field_ty, a: { + if (parent_ptr_info.flags.alignment == .none) { + break :a aggregate_ty.explicitFieldAlignment(field_idx, zcu); + } + const field_align = aggregate_ty.resolvedFieldAlignment(field_idx, zcu); + break :a field_align.min(parent_ptr_info.flags.alignment); + } }, .@"extern" => { // Well-defined layout, so just offset the pointer appropriately. - try aggregate_ty.resolveLayout(pt); const byte_off = aggregate_ty.structFieldOffset(field_idx, zcu); - const field_align = a: { + const field_align: InternPool.Alignment = a: { + if (byte_off == 0) break :a parent_ptr_info.flags.alignment; + const true_field_align: InternPool.Alignment = .fromLog2Units(@ctz(byte_off)); + if (parent_ptr_info.flags.alignment == .none and + true_field_align == field_ty.abiAlignment(zcu)) + { + break :a .none; + } const parent_align = if (parent_ptr_info.flags.alignment == .none) pa: { - break :pa try aggregate_ty.abiAlignmentSema(pt); + break :pa aggregate_ty.abiAlignment(zcu); } else parent_ptr_info.flags.alignment; - break :a InternPool.Alignment.fromLog2Units(@min(parent_align.toLog2Units(), @ctz(byte_off))); + break :a .minStrict(true_field_align, parent_align); }; - const result_ty = try pt.ptrTypeSema(info: { + const result_ty = try pt.ptrType(info: { var new = parent_ptr_info; new.child = field_ty.toIntern(); new.flags.alignment = field_align; @@ -2143,7 +1823,7 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, pt: Zcu.PerThread) !Value { new.packed_offset = packed_offset; new.child = field_ty.toIntern(); if (new.flags.alignment == .none) { - new.flags.alignment = try aggregate_ty.abiAlignmentSema(pt); + new.flags.alignment = aggregate_ty.abiAlignment(zcu); } break :info new; }); @@ -2155,10 +1835,16 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, pt: Zcu.PerThread) !Value { const union_obj = zcu.typeToUnion(aggregate_ty).?; const field_ty = Type.fromInterned(union_obj.field_types.get(&zcu.intern_pool)[field_idx]); switch (aggregate_ty.containerLayout(zcu)) { - .auto => break :field .{ field_ty, try aggregate_ty.fieldAlignmentSema(field_idx, pt) }, + .auto => break :field .{ field_ty, a: { + if (parent_ptr_info.flags.alignment == .none) { + break :a aggregate_ty.explicitFieldAlignment(field_idx, zcu); + } + const field_align = aggregate_ty.resolvedFieldAlignment(field_idx, zcu); + break :a field_align.min(parent_ptr_info.flags.alignment); + } }, .@"extern" => { // Point to the same address. - const result_ty = try pt.ptrTypeSema(info: { + const result_ty = try pt.ptrType(info: { var new = parent_ptr_info; new.child = field_ty.toIntern(); break :info new; @@ -2166,59 +1852,30 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, pt: Zcu.PerThread) !Value { return pt.getCoerced(parent_ptr, result_ty); }, .@"packed" => { - // If the field has an ABI size matching its bit size, then we can continue to use a - // non-bit pointer if the parent pointer is also a non-bit pointer. - if (parent_ptr_info.packed_offset.host_size == 0 and (try field_ty.abiSizeInner(.sema, zcu, pt.tid)).scalar * 8 == try field_ty.bitSizeSema(pt)) { - // We must offset the pointer on big-endian targets, since the bits of packed memory don't align nicely. - const byte_offset = switch (zcu.getTarget().cpu.arch.endian()) { - .little => 0, - .big => (try aggregate_ty.abiSizeInner(.sema, zcu, pt.tid)).scalar - (try field_ty.abiSizeInner(.sema, zcu, pt.tid)).scalar, - }; - const result_ty = try pt.ptrTypeSema(info: { - var new = parent_ptr_info; - new.child = field_ty.toIntern(); - new.flags.alignment = InternPool.Alignment.fromLog2Units( - @ctz(byte_offset | (try parent_ptr_ty.ptrAlignmentSema(pt)).toByteUnits().?), - ); - break :info new; - }); - return parent_ptr.getOffsetPtr(byte_offset, result_ty, pt); - } else { - // The result must be a bit-pointer if it is not already. - const result_ty = try pt.ptrTypeSema(info: { - var new = parent_ptr_info; - new.child = field_ty.toIntern(); - if (new.packed_offset.host_size == 0) { - new.packed_offset.host_size = @intCast(((try aggregate_ty.bitSizeSema(pt)) + 7) / 8); - assert(new.packed_offset.bit_offset == 0); - } - break :info new; - }); - return pt.getCoerced(parent_ptr, result_ty); - } + const result_ty = try pt.ptrType(info: { + var new = parent_ptr_info; + new.child = field_ty.toIntern(); + break :info new; + }); + return pt.getCoerced(parent_ptr, result_ty); }, } }, .pointer => field_ty: { assert(aggregate_ty.isSlice(zcu)); - break :field_ty switch (field_idx) { - Value.slice_ptr_index => .{ aggregate_ty.slicePtrFieldType(zcu), Type.usize.abiAlignment(zcu) }, - Value.slice_len_index => .{ Type.usize, Type.usize.abiAlignment(zcu) }, + break :field_ty .{ switch (field_idx) { + Value.slice_ptr_index => aggregate_ty.slicePtrFieldType(zcu), + Value.slice_len_index => Type.usize, else => unreachable, - }; + }, switch (parent_ptr_info.flags.alignment) { + .none => .none, + else => Type.usize.abiAlignment(zcu).min(parent_ptr_info.flags.alignment), + } }; }, else => unreachable, }; - const new_align: InternPool.Alignment = if (parent_ptr_info.flags.alignment != .none) a: { - const ty_align = (try field_ty.abiAlignmentInner(.sema, zcu, pt.tid)).scalar; - const true_field_align = if (field_align == .none) ty_align else field_align; - const new_align = true_field_align.min(parent_ptr_info.flags.alignment); - if (new_align == ty_align) break :a .none; - break :a new_align; - } else field_align; - - const result_ty = try pt.ptrTypeSema(info: { + const result_ty = try pt.ptrType(info: { var new = parent_ptr_info; new.child = field_ty.toIntern(); new.flags.alignment = new_align; @@ -2241,6 +1898,7 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, pt: Zcu.PerThread) !Value { /// `orig_parent_ptr` must be either a single-pointer to an array or vector, or a many-pointer or C-pointer or slice. /// Returns a pointer to the element at the specified index. /// May perform type resolution. +/// MLUGG TODO AUDIT pub fn ptrElem(orig_parent_ptr: Value, field_idx: u64, pt: Zcu.PerThread) !Value { const zcu = pt.zcu; const parent_ptr = switch (orig_parent_ptr.typeOf(zcu).ptrSize(zcu)) { @@ -2267,21 +1925,19 @@ pub fn ptrElem(orig_parent_ptr: Value, field_idx: u64, pt: Zcu.PerThread) !Value const strat: PtrStrat = switch (parent_ptr_ty.ptrSize(zcu)) { .one => switch (elem_ty.zigTypeTag(zcu)) { - .vector => .{ .offset = field_idx * @divExact(try elem_ty.childType(zcu).bitSizeSema(pt), 8) }, + .vector => .{ .offset = field_idx * @divExact(elem_ty.childType(zcu).bitSize(zcu), 8) }, .array => strat: { const arr_elem_ty = elem_ty.childType(zcu); - if (try arr_elem_ty.comptimeOnlySema(pt)) { - break :strat .{ .elem_ptr = arr_elem_ty }; - } - break :strat .{ .offset = field_idx * (try arr_elem_ty.abiSizeInner(.sema, zcu, pt.tid)).scalar }; + if (arr_elem_ty.comptimeOnly(zcu)) break :strat .{ .elem_ptr = arr_elem_ty }; + break :strat .{ .offset = field_idx * arr_elem_ty.abiSize(zcu) }; }, else => unreachable, }, - .many, .c => if (try elem_ty.comptimeOnlySema(pt)) + .many, .c => if (elem_ty.comptimeOnly(zcu)) .{ .elem_ptr = elem_ty } else - .{ .offset = field_idx * (try elem_ty.abiSizeInner(.sema, zcu, pt.tid)).scalar }, + .{ .offset = field_idx * elem_ty.abiSize(zcu) }, .slice => unreachable, }; @@ -2430,6 +2086,7 @@ pub fn pointerDerivation(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread) Al /// which prefer field/elem accesses when lowering constant pointer values. /// It is also used by the Value printing logic for pointers. pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread, comptime resolve_types: bool, opt_sema: ?*Sema) !PointerDeriveStep { + // MLUGG TODO: audit tf outta this code const zcu = pt.zcu; const ptr = zcu.intern_pool.indexToKey(ptr_val.toIntern()).ptr; const base_derive: PointerDeriveStep = switch (ptr.base_addr) { @@ -2454,7 +2111,7 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh .comptime_alloc => |idx| base: { const sema = opt_sema.?; const alloc = sema.getComptimeAlloc(idx); - const val = try alloc.val.intern(pt, sema.arena); + const val = try alloc.val.intern(pt, arena); const ty = val.typeOf(zcu); break :base .{ .comptime_alloc_ptr = .{ .idx = idx, @@ -2492,24 +2149,14 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh const base_ptr = Value.fromInterned(field.base); const base_ptr_ty = base_ptr.typeOf(zcu); const agg_ty = base_ptr_ty.childType(zcu); - const field_ty, const field_align = switch (agg_ty.zigTypeTag(zcu)) { - .@"struct" => .{ agg_ty.fieldType(@intCast(field.index), zcu), try agg_ty.fieldAlignmentInner( - @intCast(field.index), - if (resolve_types) .sema else .normal, - pt.zcu, - if (resolve_types) pt.tid else {}, - ) }, - .@"union" => .{ agg_ty.unionFieldTypeByIndex(@intCast(field.index), zcu), try agg_ty.fieldAlignmentInner( - @intCast(field.index), - if (resolve_types) .sema else .normal, - pt.zcu, - if (resolve_types) pt.tid else {}, - ) }, - .pointer => .{ switch (field.index) { - Value.slice_ptr_index => agg_ty.slicePtrFieldType(zcu), - Value.slice_len_index => Type.usize, + if (resolve_types) try opt_sema.?.ensureLayoutResolved(agg_ty); + const field_ty: Type, const field_align: InternPool.Alignment = switch (agg_ty.zigTypeTag(zcu)) { + .@"struct", .@"union" => .{ agg_ty.fieldType(@intCast(field.index), zcu), agg_ty.resolvedFieldAlignment(@intCast(field.index), pt.zcu) }, + .pointer => switch (field.index) { + Value.slice_ptr_index => .{ agg_ty.slicePtrFieldType(zcu), Type.ptrAbiAlignment(zcu.getTarget()) }, + Value.slice_len_index => .{ .usize, Type.abiAlignment(.usize, zcu) }, else => unreachable, - }, Type.usize.abiAlignment(zcu) }, + }, else => unreachable, }; const base_align = base_ptr_ty.ptrAlignment(zcu); @@ -2720,148 +2367,6 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh } }; } -pub fn resolveLazy( - val: Value, - arena: Allocator, - pt: Zcu.PerThread, -) Zcu.SemaError!Value { - switch (pt.zcu.intern_pool.indexToKey(val.toIntern())) { - .int => |int| switch (int.storage) { - .u64, .i64, .big_int => return val, - .lazy_align, .lazy_size => return pt.intValue( - Type.fromInterned(int.ty), - try val.toUnsignedIntSema(pt), - ), - }, - .slice => |slice| { - const ptr = try Value.fromInterned(slice.ptr).resolveLazy(arena, pt); - const len = try Value.fromInterned(slice.len).resolveLazy(arena, pt); - if (ptr.toIntern() == slice.ptr and len.toIntern() == slice.len) return val; - return Value.fromInterned(try pt.intern(.{ .slice = .{ - .ty = slice.ty, - .ptr = ptr.toIntern(), - .len = len.toIntern(), - } })); - }, - .ptr => |ptr| { - switch (ptr.base_addr) { - .nav, .comptime_alloc, .uav, .int => return val, - .comptime_field => |field_val| { - const resolved_field_val = (try Value.fromInterned(field_val).resolveLazy(arena, pt)).toIntern(); - return if (resolved_field_val == field_val) - val - else - Value.fromInterned(try pt.intern(.{ .ptr = .{ - .ty = ptr.ty, - .base_addr = .{ .comptime_field = resolved_field_val }, - .byte_offset = ptr.byte_offset, - } })); - }, - .eu_payload, .opt_payload => |base| { - const resolved_base = (try Value.fromInterned(base).resolveLazy(arena, pt)).toIntern(); - return if (resolved_base == base) - val - else - Value.fromInterned(try pt.intern(.{ .ptr = .{ - .ty = ptr.ty, - .base_addr = switch (ptr.base_addr) { - .eu_payload => .{ .eu_payload = resolved_base }, - .opt_payload => .{ .opt_payload = resolved_base }, - else => unreachable, - }, - .byte_offset = ptr.byte_offset, - } })); - }, - .arr_elem, .field => |base_index| { - const resolved_base = (try Value.fromInterned(base_index.base).resolveLazy(arena, pt)).toIntern(); - return if (resolved_base == base_index.base) - val - else - Value.fromInterned(try pt.intern(.{ .ptr = .{ - .ty = ptr.ty, - .base_addr = switch (ptr.base_addr) { - .arr_elem => .{ .arr_elem = .{ - .base = resolved_base, - .index = base_index.index, - } }, - .field => .{ .field = .{ - .base = resolved_base, - .index = base_index.index, - } }, - else => unreachable, - }, - .byte_offset = ptr.byte_offset, - } })); - }, - } - }, - .aggregate => |aggregate| switch (aggregate.storage) { - .bytes => return val, - .elems => |elems| { - var resolved_elems: []InternPool.Index = &.{}; - for (elems, 0..) |elem, i| { - const resolved_elem = (try Value.fromInterned(elem).resolveLazy(arena, pt)).toIntern(); - if (resolved_elems.len == 0 and resolved_elem != elem) { - resolved_elems = try arena.alloc(InternPool.Index, elems.len); - @memcpy(resolved_elems[0..i], elems[0..i]); - } - if (resolved_elems.len > 0) resolved_elems[i] = resolved_elem; - } - return if (resolved_elems.len == 0) - val - else - pt.aggregateValue(.fromInterned(aggregate.ty), resolved_elems); - }, - .repeated_elem => |elem| { - const resolved_elem = try Value.fromInterned(elem).resolveLazy(arena, pt); - return if (resolved_elem.toIntern() == elem) - val - else - pt.aggregateSplatValue(.fromInterned(aggregate.ty), resolved_elem); - }, - }, - .un => |un| { - const resolved_tag = if (un.tag == .none) - .none - else - (try Value.fromInterned(un.tag).resolveLazy(arena, pt)).toIntern(); - const resolved_val = (try Value.fromInterned(un.val).resolveLazy(arena, pt)).toIntern(); - return if (resolved_tag == un.tag and resolved_val == un.val) - val - else - Value.fromInterned(try pt.internUnion(.{ - .ty = un.ty, - .tag = resolved_tag, - .val = resolved_val, - })); - }, - .error_union => |eu| switch (eu.val) { - .err_name => return val, - .payload => |payload| { - const resolved_payload = try Value.fromInterned(payload).resolveLazy(arena, pt); - if (resolved_payload.toIntern() == payload) return val; - return .fromInterned(try pt.intern(.{ .error_union = .{ - .ty = eu.ty, - .val = .{ .payload = resolved_payload.toIntern() }, - } })); - }, - }, - .opt => |opt| switch (opt.val) { - .none => return val, - else => |payload| { - const resolved_payload = try Value.fromInterned(payload).resolveLazy(arena, pt); - if (resolved_payload.toIntern() == payload) return val; - return .fromInterned(try pt.intern(.{ .opt = .{ - .ty = opt.ty, - .val = resolved_payload.toIntern(), - } })); - }, - }, - - else => return val, - } -} - const InterpretMode = enum { /// In this mode, types are assumed to match what the compiler was built with in terms of field /// order, field types, etc. This improves compiler performance. However, it means that certain @@ -2878,7 +2383,6 @@ const interpret_mode: InterpretMode = @field(InterpretMode, @tagName(build_optio /// Given a `Value` representing a comptime-known value of type `T`, unwrap it into an actual `T` known to the compiler. /// This is useful for accessing `std.builtin` structures received from comptime logic. -/// `val` must be fully resolved. pub fn interpret(val: Value, comptime T: type, pt: Zcu.PerThread) error{ OutOfMemory, UndefinedValue, TypeMismatch }!T { const zcu = pt.zcu; const io = zcu.comp.io; @@ -2917,7 +2421,6 @@ pub fn interpret(val: Value, comptime T: type, pt: Zcu.PerThread) error{ OutOfMe }, .int => switch (ip.indexToKey(val.toIntern()).int.storage) { - .lazy_align, .lazy_size => unreachable, // `val` is fully resolved inline .u64, .i64 => |x| std.math.cast(T, x) orelse return error.TypeMismatch, .big_int => |big| big.toInt(T) catch return error.TypeMismatch, }, diff --git a/src/Zcu.zig b/src/Zcu.zig index f2d6dbf497a1f47faef87d208c082c364867bb9e..e1760fecb95c1871ca3229becbebc6d224e4173a 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -14,6 +14,8 @@ const mem = std.mem; const Allocator = std.mem.Allocator; const assert = std.debug.assert; const log = std.log.scoped(.zcu); +const deps_log = std.log.scoped(.zcu_deps); +const refs_log = std.log.scoped(.zcu_refs); const BigIntConst = std.math.big.int.Const; const BigIntMutable = std.math.big.int.Mutable; const Target = std.Target; @@ -2685,10 +2687,10 @@ pub const LazySrcLoc = struct { .struct_init, .struct_init_ref => zir.extraData(Zir.Inst.StructInit, inst.data.pl_node.payload_index).data.abs_node, .struct_init_anon => zir.extraData(Zir.Inst.StructInitAnon, inst.data.pl_node.payload_index).data.abs_node, .extended => switch (inst.data.extended.opcode) { - .struct_decl => zir.extraData(Zir.Inst.StructDecl, inst.data.extended.operand).data.src_node, - .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_node, - .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_node, - .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_node, + .struct_decl => zir.getStructDecl(zir_inst).src_node, + .union_decl => zir.getUnionDecl(zir_inst).src_node, + .enum_decl => zir.getEnumDecl(zir_inst).src_node, + .opaque_decl => zir.getOpaqueDecl(zir_inst).src_node, .reify_enum => zir.extraData(Zir.Inst.ReifyEnum, inst.data.extended.operand).data.node, .reify_struct => zir.extraData(Zir.Inst.ReifyStruct, inst.data.extended.operand).data.node, .reify_union => zir.extraData(Zir.Inst.ReifyUnion, inst.data.extended.operand).data.node, @@ -3063,7 +3065,7 @@ pub fn markDependeeOutdated( marked_po: enum { not_marked_po, marked_po }, dependee: InternPool.Dependee, ) !void { - log.debug("outdated dependee: {f}", .{zcu.fmtDependee(dependee)}); + deps_log.debug("outdated dependee: {f}", .{zcu.fmtDependee(dependee)}); var it = zcu.intern_pool.dependencyIterator(dependee); while (it.next()) |depender| { if (zcu.outdated.getPtr(depender)) |po_dep_count| { @@ -3071,9 +3073,9 @@ pub fn markDependeeOutdated( .not_marked_po => {}, .marked_po => { po_dep_count.* -= 1; - log.debug("outdated {f} => already outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* }); + deps_log.debug("outdated {f} => already outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* }); if (po_dep_count.* == 0) { - log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); + deps_log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); try zcu.outdated_ready.put(zcu.gpa, depender, {}); } }, @@ -3094,9 +3096,9 @@ pub fn markDependeeOutdated( depender, new_po_dep_count, ); - log.debug("outdated {f} => new outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), new_po_dep_count }); + deps_log.debug("outdated {f} => new outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), new_po_dep_count }); if (new_po_dep_count == 0) { - log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); + deps_log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); try zcu.outdated_ready.put(zcu.gpa, depender, {}); } // If this is a Decl and was not previously PO, we must recursively @@ -3109,16 +3111,16 @@ pub fn markDependeeOutdated( } pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { - log.debug("up-to-date dependee: {f}", .{zcu.fmtDependee(dependee)}); + deps_log.debug("up-to-date dependee: {f}", .{zcu.fmtDependee(dependee)}); var it = zcu.intern_pool.dependencyIterator(dependee); while (it.next()) |depender| { if (zcu.outdated.getPtr(depender)) |po_dep_count| { // This depender is already outdated, but it now has one // less PO dependency! po_dep_count.* -= 1; - log.debug("up-to-date {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* }); + deps_log.debug("up-to-date {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* }); if (po_dep_count.* == 0) { - log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); + deps_log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); try zcu.outdated_ready.put(zcu.gpa, depender, {}); } continue; @@ -3132,11 +3134,11 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { }; if (ptr.* > 1) { ptr.* -= 1; - log.debug("up-to-date {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), ptr.* }); + deps_log.debug("up-to-date {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), ptr.* }); continue; } - log.debug("up-to-date {f} => {f} po_deps=0 (up-to-date)", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender) }); + deps_log.debug("up-to-date {f} => {f} po_deps=0 (up-to-date)", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender) }); // This dependency is no longer PO, i.e. is known to be up-to-date. assert(zcu.potentially_outdated.swapRemove(depender)); @@ -3146,8 +3148,9 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { .@"comptime" => {}, .nav_val => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_val = nav }), .nav_ty => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav }), - .type => |ty| try zcu.markPoDependeeUpToDate(.{ .interned = ty }), - .func => |func| try zcu.markPoDependeeUpToDate(.{ .interned = func }), + .type_layout => |ty| try zcu.markPoDependeeUpToDate(.{ .type_layout = ty }), + .type_inits => |ty| try zcu.markPoDependeeUpToDate(.{ .type_inits = ty }), + .func => |func| try zcu.markPoDependeeUpToDate(.{ .func_ies = func }), .memoized_state => |stage| try zcu.markPoDependeeUpToDate(.{ .memoized_state = stage }), } } @@ -3161,11 +3164,12 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni .@"comptime" => return, // analysis of a comptime decl can't outdate any dependencies .nav_val => |nav| .{ .nav_val = nav }, .nav_ty => |nav| .{ .nav_ty = nav }, - .type => |ty| .{ .interned = ty }, - .func => |func_index| .{ .interned = func_index }, // IES + .type_layout => |ty| .{ .type_layout = ty }, + .type_inits => |ty| .{ .type_inits = ty }, + .func => |func_index| .{ .func_ies = func_index }, .memoized_state => |stage| .{ .memoized_state = stage }, }; - log.debug("potentially outdated dependee: {f}", .{zcu.fmtDependee(dependee)}); + deps_log.debug("potentially outdated dependee: {f}", .{zcu.fmtDependee(dependee)}); var it = ip.dependencyIterator(dependee); while (it.next()) |po| { if (zcu.outdated.getPtr(po)) |po_dep_count| { @@ -3175,17 +3179,17 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni _ = zcu.outdated_ready.swapRemove(po); } po_dep_count.* += 1; - log.debug("po {f} => {f} [outdated] po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), po_dep_count.* }); + deps_log.debug("po {f} => {f} [outdated] po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), po_dep_count.* }); continue; } if (zcu.potentially_outdated.getPtr(po)) |n| { // There is now one more PO dependency. n.* += 1; - log.debug("po {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), n.* }); + deps_log.debug("po {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), n.* }); continue; } try zcu.potentially_outdated.putNoClobber(zcu.gpa, po, 1); - log.debug("po {f} => {f} po_deps=1", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po) }); + deps_log.debug("po {f} => {f} po_deps=1", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po) }); // This AnalUnit was not already PO, so we must recursively mark its dependers as also PO. try zcu.markTransitiveDependersPotentiallyOutdated(po); } @@ -3240,13 +3244,15 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { var chosen_unit: ?AnalUnit = null; var chosen_unit_dependers: u32 = undefined; + // MLUGG TODO: i'm 99% sure this is now impossible. check!!! inline for (.{ zcu.outdated.keys(), zcu.potentially_outdated.keys() }) |outdated_units| { for (outdated_units) |unit| { var n: u32 = 0; var it = ip.dependencyIterator(switch (unit.unwrap()) { .func => continue, // a `func` definitely can't be causing the loop so it is a bad choice .@"comptime" => continue, // a `comptime` block can't even be depended on so it is a terrible choice - .type => |ty| .{ .interned = ty }, + .type_layout => |ty| .{ .type_layout = ty }, + .type_inits => |ty| .{ .type_inits = ty }, .nav_val => |nav| .{ .nav_val = nav }, .nav_ty => |nav| .{ .nav_ty = nav }, .memoized_state => { @@ -3377,25 +3383,21 @@ pub fn mapOldZirToNew( var comptime_decls: std.ArrayList(Zir.Inst.Index) = .empty; defer comptime_decls.deinit(gpa); - { - var old_decl_it = old_zir.declIterator(match_item.old_inst); - while (old_decl_it.next()) |old_decl_inst| { - const old_decl = old_zir.getDeclaration(old_decl_inst); - switch (old_decl.kind) { - .@"comptime" => try comptime_decls.append(gpa, old_decl_inst), - .unnamed_test => try unnamed_tests.append(gpa, old_decl_inst), - .@"test" => try named_tests.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst), - .decltest => try named_decltests.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst), - .@"const", .@"var" => try named_decls.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst), - } + for (old_zir.typeDecls(match_item.old_inst)) |old_decl_inst| { + const old_decl = old_zir.getDeclaration(old_decl_inst); + switch (old_decl.kind) { + .@"comptime" => try comptime_decls.append(gpa, old_decl_inst), + .unnamed_test => try unnamed_tests.append(gpa, old_decl_inst), + .@"test" => try named_tests.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst), + .decltest => try named_decltests.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst), + .@"const", .@"var" => try named_decls.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst), } } var unnamed_test_idx: u32 = 0; var comptime_decl_idx: u32 = 0; - var new_decl_it = new_zir.declIterator(match_item.new_inst); - while (new_decl_it.next()) |new_decl_inst| { + for (new_zir.typeDecls(match_item.new_inst)) |new_decl_inst| { const new_decl = new_zir.getDeclaration(new_decl_inst); // Attempt to match this to a declaration in the old ZIR: // * For named declarations (`const`/`var`/`fn`), we match based on name. @@ -3494,7 +3496,7 @@ pub fn ensureFuncBodyAnalysisQueued(zcu: *Zcu, func_index: InternPool.Index) !vo } try zcu.func_body_analysis_queued.ensureUnusedCapacity(zcu.gpa, 1); - try zcu.comp.queueJob(.{ .analyze_func = func_index }); + try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .func = func_index }) }); zcu.func_body_analysis_queued.putAssumeCapacityNoClobber(func_index, {}); } @@ -3513,7 +3515,7 @@ pub fn ensureNavValAnalysisQueued(zcu: *Zcu, nav_id: InternPool.Nav.Index) !void } try zcu.nav_val_analysis_queued.ensureUnusedCapacity(zcu.gpa, 1); - try zcu.comp.queueJob(.{ .analyze_comptime_unit = .wrap(.{ .nav_val = nav_id }) }); + try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .nav_val = nav_id }) }); zcu.nav_val_analysis_queued.putAssumeCapacityNoClobber(nav_id, {}); } @@ -3908,8 +3910,7 @@ pub fn atomicPtrAlignment( return error.BadType; } -/// Returns null in the following cases: -/// * Not a struct. +/// Returns null if `ty` is not a struct. pub fn typeToStruct(zcu: *const Zcu, ty: Type) ?InternPool.LoadedStructType { if (ty.ip_index == .none) return null; const ip = &zcu.intern_pool; @@ -3936,7 +3937,6 @@ pub fn structPackedFieldBitOffset( ) u16 { const ip = &zcu.intern_pool; assert(struct_type.layout == .@"packed"); - assert(struct_type.haveLayout(ip)); var bit_sum: u64 = 0; for (0..struct_type.field_types.len) |i| { if (i == field_index) { @@ -3995,8 +3995,10 @@ pub const UnionLayout = struct { pub fn unionTagFieldIndex(zcu: *const Zcu, loaded_union: InternPool.LoadedUnionType, enum_tag: Value) ?u32 { const ip = &zcu.intern_pool; if (enum_tag.toIntern() == .none) return null; - assert(ip.typeOf(enum_tag.toIntern()) == loaded_union.enum_tag_ty); - return loaded_union.loadTagType(ip).tagValueIndex(ip, enum_tag.toIntern()); + const enum_tag_key = ip.indexToKey(enum_tag.toIntern()).enum_tag; + assert(enum_tag_key.ty == loaded_union.enum_tag_type); + const loaded_enum = ip.loadEnumType(loaded_union.enum_tag_type); + return loaded_enum.tagValueIndex(ip, enum_tag_key.int); } pub const ResolvedReference = struct { @@ -4049,31 +4051,36 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R const referencer = types.values()[type_idx]; type_idx += 1; - log.debug("handle type '{f}'", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)}); + refs_log.debug("handle type '{f}'", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)}); - // If this type undergoes type resolution, the corresponding `AnalUnit` is automatically referenced. - const has_resolution: bool = switch (ip.indexToKey(ty)) { - .struct_type, .union_type => true, - .enum_type => |k| k != .generated_tag, - .opaque_type => false, + // If this type undergoes type resolution, the corresponding `AnalUnit`s are automatically referenced. + const has_layout: bool, const has_inits: bool = switch (ip.indexToKey(ty)) { + .struct_type => .{ true, true }, + .union_type => .{ true, false }, + .enum_type => .{ false, true }, + .opaque_type => .{ false, false }, else => unreachable, }; - if (has_resolution) { + if (has_layout) { // this should only be referenced by the type - const unit: AnalUnit = .wrap(.{ .type = ty }); + const unit: AnalUnit = .wrap(.{ .type_layout = ty }); + try units.putNoClobber(gpa, unit, referencer); + } + if (has_inits) { + // this should only be referenced by the type + const unit: AnalUnit = .wrap(.{ .type_inits = ty }); try units.putNoClobber(gpa, unit, referencer); } // If this is a union with a generated tag, its tag type is automatically referenced. // We don't add this reference for non-generated tags, as those will already be referenced via the union's type resolution, with a better source location. - if (zcu.typeToUnion(Type.fromInterned(ty))) |union_obj| { - const tag_ty = union_obj.enum_tag_ty; - if (tag_ty != .none) { - if (ip.indexToKey(tag_ty).enum_type == .generated_tag) { - const gop = try types.getOrPut(gpa, tag_ty); - if (!gop.found_existing) gop.value_ptr.* = referencer; - } - } + implicit_tag: { + const loaded_union = zcu.typeToUnion(.fromInterned(ty)) orelse break :implicit_tag; + const tag_ty = loaded_union.enum_tag_type; + if (ip.indexToKey(tag_ty).enum_type != .generated_union_tag) break :implicit_tag; + const gop = try types.getOrPut(gpa, tag_ty); + if (gop.found_existing) break :implicit_tag; + gop.value_ptr.* = referencer; } // Queue any decls within this type which would be automatically analyzed. @@ -4084,7 +4091,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R const unit: AnalUnit = .wrap(.{ .@"comptime" = cu }); const gop = try units.getOrPut(gpa, unit); if (!gop.found_existing) { - log.debug("type '{f}': ref comptime %{}", .{ + refs_log.debug("type '{f}': ref comptime %{}", .{ Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ip.getComptimeUnit(cu).zir_index.resolve(ip) orelse continue), }); @@ -4118,7 +4125,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R { const gop = try units.getOrPut(gpa, .wrap(.{ .nav_val = nav_id })); if (!gop.found_existing) { - log.debug("type '{f}': ref test %{}", .{ + refs_log.debug("type '{f}': ref test %{}", .{ Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(inst_info.inst), }); @@ -4141,7 +4148,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R const unit: AnalUnit = .wrap(.{ .nav_val = nav }); const gop = try units.getOrPut(gpa, unit); if (!gop.found_existing) { - log.debug("type '{f}': ref named %{}", .{ + refs_log.debug("type '{f}': ref named %{}", .{ Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(inst_info.inst), }); @@ -4158,7 +4165,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R const unit: AnalUnit = .wrap(.{ .nav_val = nav }); const gop = try units.getOrPut(gpa, unit); if (!gop.found_existing) { - log.debug("type '{f}': ref named %{}", .{ + refs_log.debug("type '{f}': ref named %{}", .{ Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(inst_info.inst), }); @@ -4177,14 +4184,14 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R const other: AnalUnit = .wrap(switch (unit.unwrap()) { .nav_val => |n| .{ .nav_ty = n }, .nav_ty => |n| .{ .nav_val = n }, - .@"comptime", .type, .func, .memoized_state => break :queue_paired, + .@"comptime", .type_layout, .type_inits, .func, .memoized_state => break :queue_paired, }); const gop = try units.getOrPut(gpa, other); if (gop.found_existing) break :queue_paired; gop.value_ptr.* = units.values()[unit_idx]; // same reference location } - log.debug("handle unit '{f}'", .{zcu.fmtAnalUnit(unit)}); + refs_log.debug("handle unit '{f}'", .{zcu.fmtAnalUnit(unit)}); if (zcu.reference_table.get(unit)) |first_ref_idx| { assert(first_ref_idx != std.math.maxInt(u32)); @@ -4193,7 +4200,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R const ref = zcu.all_references.items[ref_idx]; const gop = try units.getOrPut(gpa, ref.referenced); if (!gop.found_existing) { - log.debug("unit '{f}': ref unit '{f}'", .{ + refs_log.debug("unit '{f}': ref unit '{f}'", .{ zcu.fmtAnalUnit(unit), zcu.fmtAnalUnit(ref.referenced), }); @@ -4213,7 +4220,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R const ref = zcu.all_type_references.items[ref_idx]; const gop = try types.getOrPut(gpa, ref.referenced); if (!gop.found_existing) { - log.debug("unit '{f}': ref type '{f}'", .{ + refs_log.debug("unit '{f}': ref type '{f}'", .{ zcu.fmtAnalUnit(unit), Type.fromInterned(ref.referenced).containerTypeName(ip).fmt(ip), }); @@ -4323,9 +4330,8 @@ fn formatAnalUnit(data: FormatAnalUnit, writer: *Io.Writer) Io.Writer.Error!void return writer.print("comptime(inst= [{}])", .{@intFromEnum(cu_id)}); } }, - .nav_val => |nav| return writer.print("nav_val('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }), - .nav_ty => |nav| return writer.print("nav_ty('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }), - .type => |ty| return writer.print("ty('{f}' [{}])", .{ Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }), + .nav_val, .nav_ty => |nav, tag| return writer.print("{t}('{f}' [{}])", .{ tag, ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }), + .type_layout, .type_inits => |ty, tag| return writer.print("{t}('{f}' [{}])", .{ tag, Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }), .func => |func| { const nav = zcu.funcInfo(func).owner_nav; return writer.print("func('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(func) }); @@ -4347,18 +4353,17 @@ fn formatDependee(data: FormatDependee, writer: *Io.Writer) Io.Writer.Error!void const file_path = zcu.fileByIndex(info.file).path; return writer.print("inst('{f}', %{d})", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst) }); }, - .nav_val => |nav| { + .nav_val, .nav_ty => |nav, tag| { const fqn = ip.getNav(nav).fqn; - return writer.print("nav_val('{f}')", .{fqn.fmt(ip)}); + return writer.print("{t}('{f}')", .{ tag, fqn.fmt(ip) }); }, - .nav_ty => |nav| { - const fqn = ip.getNav(nav).fqn; - return writer.print("nav_ty('{f}')", .{fqn.fmt(ip)}); + .type_layout, .type_inits => |ip_index, tag| { + const name = Type.fromInterned(ip_index).containerTypeName(ip); + return writer.print("{t}('{f}')", .{ tag, name.fmt(ip) }); }, - .interned => |ip_index| switch (ip.indexToKey(ip_index)) { - .struct_type, .union_type, .enum_type => return writer.print("type('{f}')", .{Type.fromInterned(ip_index).containerTypeName(ip).fmt(ip)}), - .func => |f| return writer.print("ies('{f}')", .{ip.getNav(f.owner_nav).fqn.fmt(ip)}), - else => unreachable, + .func_ies => |ip_index| { + const fqn = ip.getNav(ip.indexToKey(ip_index).func.owner_nav).fqn; + return writer.print("func_ies('{f}')", .{fqn.fmt(ip)}); }, .zon_file => |file| { const file_path = zcu.fileByIndex(file).path; diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 5472afc5f02682b3f9083b4d710e1c5616c74d57..f9faef2f7a36f0d77cbf86db7c7e355db8038056 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -598,44 +598,38 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { // Value is whether the declaration is `pub`. var old_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, bool) = .empty; defer old_names.deinit(zcu.gpa); - { - var it = old_zir.declIterator(old_inst); - while (it.next()) |decl_inst| { - const old_decl = old_zir.getDeclaration(decl_inst); - if (old_decl.name == .empty) continue; - const name_ip = try zcu.intern_pool.getOrPutString( - zcu.gpa, - io, - pt.tid, - old_zir.nullTerminatedString(old_decl.name), - .no_embedded_nulls, - ); - try old_names.put(zcu.gpa, name_ip, old_decl.is_pub); - } + for (old_zir.typeDecls(old_inst)) |decl_inst| { + const old_decl = old_zir.getDeclaration(decl_inst); + if (old_decl.name == .empty) continue; + const name_ip = try zcu.intern_pool.getOrPutString( + zcu.gpa, + io, + pt.tid, + old_zir.nullTerminatedString(old_decl.name), + .no_embedded_nulls, + ); + try old_names.put(zcu.gpa, name_ip, old_decl.is_pub); } var any_change = false; - { - var it = new_zir.declIterator(new_inst); - while (it.next()) |decl_inst| { - const new_decl = new_zir.getDeclaration(decl_inst); - if (new_decl.name == .empty) continue; - const name_ip = try zcu.intern_pool.getOrPutString( - zcu.gpa, - io, - pt.tid, - new_zir.nullTerminatedString(new_decl.name), - .no_embedded_nulls, - ); - if (old_names.fetchSwapRemove(name_ip)) |kv| { - if (kv.value == new_decl.is_pub) continue; - } - // Name added, or changed whether it's pub - any_change = true; - try zcu.markDependeeOutdated(.not_marked_po, .{ .namespace_name = .{ - .namespace = tracked_inst_index, - .name = name_ip, - } }); + for (new_zir.typeDecls(new_inst)) |decl_inst| { + const new_decl = new_zir.getDeclaration(decl_inst); + if (new_decl.name == .empty) continue; + const name_ip = try zcu.intern_pool.getOrPutString( + zcu.gpa, + io, + pt.tid, + new_zir.nullTerminatedString(new_decl.name), + .no_embedded_nulls, + ); + if (old_names.fetchSwapRemove(name_ip)) |kv| { + if (kv.value == new_decl.is_pub) continue; } + // Name added, or changed whether it's pub + any_change = true; + try zcu.markDependeeOutdated(.not_marked_po, .{ .namespace_name = .{ + .namespace = tracked_inst_index, + .name = name_ip, + } }); } // The only elements remaining in `old_names` now are any names which were removed. for (old_names.keys()) |name_ip| { @@ -674,24 +668,49 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { } } -/// Ensures that `zcu.fileRootType` on this `file_index` gives an up-to-date answer. -/// Returns `error.AnalysisFail` if the file has an error. -pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void { - const file_root_type = pt.zcu.fileRootType(file_index); - if (file_root_type != .none) { - if (pt.ensureTypeUpToDate(file_root_type)) |_| { - return; - } else |err| switch (err) { - error.AnalysisFail => { - // The file's root `struct_decl` has, at some point, been lost, because the file failed AstGen. - // Clear `file_root_type`, and try the `semaFile` call below, in case the instruction has since - // been discovered under a new `TrackedInst.Index`. - pt.zcu.setFileRootType(file_index, .none); - }, - else => |e| return e, - } - } - return pt.semaFile(file_index); +/// Ensures that `zcu.fileRootType` on this `file_index` is populated (not `.none`). This implies +/// that the file's namespace is scanned, discovering declarations. +/// +/// Typical Zig compilations begin by claling this function on the root source file of the standard +/// library, `lib/std/std.zig`. The resulting namespace scan discovers a `comptime` declaration in +/// that file, which is queued for analysis, and everything goes from there. +pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Allocator.Error || Io.Cancelable)!void { + dev.check(.sema); + + const tracy = trace(@src()); + defer tracy.end(); + + const zcu = pt.zcu; + const comp = zcu.comp; + const io = comp.io; + const gpa = comp.gpa; + const ip = &zcu.intern_pool; + + if (zcu.fileRootType(file_index) != .none) return; // already good + + const file = zcu.fileByIndex(file_index); + assert(file.getMode() == .zig); + const struct_decl = file.zir.?.getStructDecl(.main_struct_inst); + const tracked_inst = try ip.trackZir(gpa, io, pt.tid, .{ + .file = file_index, + .inst = .main_struct_inst, + }); + const file_root_type = try Sema.analyzeStructDecl( + pt, + file_index, + &file.zir.?, + .none, + tracked_inst, + &struct_decl, + null, + &.{}, + .{ .exact = .{ + .name = try file.internFullyQualifiedName(pt), + .nav = .none, + } }, + ); + zcu.setFileRootType(file_index, file_root_type.toIntern()); + if (zcu.comp.time_report) |*tr| tr.stats.n_imported_files += 1; } /// Ensures that all memoized state on `Zcu` is up-to-date, performing re-analysis if necessary. @@ -1012,6 +1031,238 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu try sema.flushExports(); } +/// Ensures that the layout of the given `struct` or `union` type is fully up-to-date, performing +/// re-analysis if necessary. Asserts that `ty` is a struct (not a tuple!) or union. Returns +/// `error.AnalysisFail` if an analysis error is encountered during type resolution; the caller is +/// free to ignore this, since the error is already registered. +pub fn ensureTypeLayoutUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void { + const tracy = trace(@src()); + defer tracy.end(); + + const zcu = pt.zcu; + const gpa = zcu.gpa; + + const anal_unit: AnalUnit = .wrap(.{ .type_layout = ty.toIntern() }); + + log.debug("ensureTypeLayoutUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)}); + + assert(!zcu.analysis_in_progress.contains(anal_unit)); + + // Determine whether or not this type is outdated. For this kind of `AnalUnit`, that's + // the only indicator as to whether or not analysis is required; when a struct/union is + // first created, it's marked as outdated. + // MLUGG TODO: make that actually true, it's a good strategy here! + + const was_outdated = zcu.outdated.swapRemove(anal_unit) or + zcu.potentially_outdated.swapRemove(anal_unit); + + if (was_outdated) { + _ = zcu.outdated_ready.swapRemove(anal_unit); + // `was_outdated` can be true in the initial update for comptime units, so this isn't a `dev.check`. + if (dev.env.supports(.incremental)) { + zcu.deleteUnitExports(anal_unit); + zcu.deleteUnitReferences(anal_unit); + zcu.deleteUnitCompileLogs(anal_unit); + if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| { + kv.value.destroy(gpa); + } + _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); + zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit); + } + // For types, we already know that we have to invalidate all dependees. + // TODO: we actually *could* detect whether everything was the same. should we bother? + try zcu.markDependeeOutdated(.marked_po, .{ .type_layout = ty.toIntern() }); + } else { + // We can trust the current information about this unit. + if (zcu.failed_analysis.contains(anal_unit)) return error.AnalysisFail; + if (zcu.transitive_failed_analysis.contains(anal_unit)) return error.AnalysisFail; + return; + } + + if (zcu.comp.debugIncremental()) { + const info = try zcu.incremental_debug_state.getUnitInfo(gpa, anal_unit); + info.last_update_gen = zcu.generation; + info.deps.clearRetainingCapacity(); + } + + const unit_tracking = zcu.trackUnitSema(ty.containerTypeName(&zcu.intern_pool).toSlice(&zcu.intern_pool), null); + defer unit_tracking.end(zcu); + + try zcu.analysis_in_progress.put(gpa, anal_unit, {}); + defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); + + var analysis_arena: std.heap.ArenaAllocator = .init(gpa); + defer analysis_arena.deinit(); + + var comptime_err_ret_trace: std.array_list.Managed(Zcu.LazySrcLoc) = .init(gpa); + defer comptime_err_ret_trace.deinit(); + + const file = zcu.namespacePtr(ty.getNamespaceIndex(zcu)).fileScope(zcu); + + var sema: Sema = .{ + .pt = pt, + .gpa = gpa, + .arena = analysis_arena.allocator(), + .code = file.zir.?, + .owner = anal_unit, + .func_index = .none, + .func_is_naked = false, + .fn_ret_ty = .void, + .fn_ret_ty_ies = null, + .comptime_err_ret_trace = &comptime_err_ret_trace, + }; + defer sema.deinit(); + + const result = switch (ty.containerLayout(zcu)) { + .auto, .@"extern" => switch (ty.zigTypeTag(zcu)) { + .@"struct" => Sema.type_resolution.resolveStructLayout(&sema, ty), + .@"union" => Sema.type_resolution.resolveUnionLayout(&sema, ty), + else => unreachable, + }, + .@"packed" => switch (ty.zigTypeTag(zcu)) { + .@"struct" => Sema.type_resolution.resolvePackedStructLayout(&sema, ty), + .@"union" => Sema.type_resolution.resolvePackedUnionLayout(&sema, ty), + else => unreachable, + }, + }; + result catch |err| switch (err) { + error.AnalysisFail => { + if (!zcu.failed_analysis.contains(anal_unit)) { + // If this unit caused the error, it would have an entry in `failed_analysis`. + // Since it does not, this must be a transitive failure. + try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); + log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)}); + } + return error.AnalysisFail; + }, + error.OutOfMemory, + error.Canceled, + => |e| return e, + error.ComptimeReturn => unreachable, + error.ComptimeBreak => unreachable, + }; + + sema.flushExports() catch |err| switch (err) { + error.OutOfMemory => |e| return e, + }; + + codegen_type: { + if (zcu.comp.config.use_llvm) break :codegen_type; + if (file.mod.?.strip) break :codegen_type; + zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); + try zcu.comp.queueJob(.{ .link_type = ty.toIntern() }); + } +} + +/// Ensures that the default/tag values of the given `struct` or `enum` type are fully up-to-date, +/// performing re-analysis if necessary. Asserts that `ty` is a struct (not a tuple!) or an enum. +/// Returns `error.AnalysisFail` if an analysis error is encountered during resolution; the caller +/// is free to ignore this, since the error is already registered. +pub fn ensureTypeInitsUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void { + const tracy = trace(@src()); + defer tracy.end(); + + const zcu = pt.zcu; + const gpa = zcu.gpa; + + const anal_unit: AnalUnit = .wrap(.{ .type_inits = ty.toIntern() }); + + log.debug("ensureTypeInitsUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)}); + + assert(!zcu.analysis_in_progress.contains(anal_unit)); + + // Determine whether or not this type is outdated. For this kind of `AnalUnit`, that's + // the only indicator as to whether or not analysis is required; when a struct/enum is + // first created, it's marked as outdated. + // MLUGG TODO: make that actually true, it's a good strategy here! + + const was_outdated = zcu.outdated.swapRemove(anal_unit) or + zcu.potentially_outdated.swapRemove(anal_unit); + + if (was_outdated) { + _ = zcu.outdated_ready.swapRemove(anal_unit); + // `was_outdated` can be true in the initial update for comptime units, so this isn't a `dev.check`. + if (dev.env.supports(.incremental)) { + zcu.deleteUnitExports(anal_unit); + zcu.deleteUnitReferences(anal_unit); + zcu.deleteUnitCompileLogs(anal_unit); + if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| { + kv.value.destroy(gpa); + } + _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); + zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit); + } + // For types, we already know that we have to invalidate all dependees. + // TODO: we actually *could* detect whether everything was the same. should we bother? + try zcu.markDependeeOutdated(.marked_po, .{ .type_inits = ty.toIntern() }); + } else { + // We can trust the current information about this unit. + if (zcu.failed_analysis.contains(anal_unit)) return error.AnalysisFail; + if (zcu.transitive_failed_analysis.contains(anal_unit)) return error.AnalysisFail; + return; + } + + if (zcu.comp.debugIncremental()) { + const info = try zcu.incremental_debug_state.getUnitInfo(gpa, anal_unit); + info.last_update_gen = zcu.generation; + info.deps.clearRetainingCapacity(); + } + + const unit_tracking = zcu.trackUnitSema(ty.containerTypeName(&zcu.intern_pool).toSlice(&zcu.intern_pool), null); + defer unit_tracking.end(zcu); + + try zcu.analysis_in_progress.put(gpa, anal_unit, {}); + defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); + + var analysis_arena: std.heap.ArenaAllocator = .init(gpa); + defer analysis_arena.deinit(); + + var comptime_err_ret_trace: std.array_list.Managed(Zcu.LazySrcLoc) = .init(gpa); + defer comptime_err_ret_trace.deinit(); + + const zir = zcu.namespacePtr(ty.getNamespaceIndex(zcu)).fileScope(zcu).zir.?; + + var sema: Sema = .{ + .pt = pt, + .gpa = gpa, + .arena = analysis_arena.allocator(), + .code = zir, + .owner = anal_unit, + .func_index = .none, + .func_is_naked = false, + .fn_ret_ty = .void, + .fn_ret_ty_ies = null, + .comptime_err_ret_trace = &comptime_err_ret_trace, + }; + defer sema.deinit(); + + const result = switch (ty.zigTypeTag(zcu)) { + .@"struct" => Sema.type_resolution.resolveStructDefaults(&sema, ty), + .@"enum" => Sema.type_resolution.resolveEnumValues(&sema, ty), + else => unreachable, + }; + result catch |err| switch (err) { + error.AnalysisFail => { + if (!zcu.failed_analysis.contains(anal_unit)) { + // If this unit caused the error, it would have an entry in `failed_analysis`. + // Since it does not, this must be a transitive failure. + try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); + log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)}); + } + return error.AnalysisFail; + }, + error.OutOfMemory, + error.Canceled, + => |e| return e, + error.ComptimeReturn => unreachable, + error.ComptimeBreak => unreachable, + }; + + sema.flushExports() catch |err| switch (err) { + error.OutOfMemory => |e| return e, + }; +} + /// Ensures that the resolved value of the given `Nav` is fully up-to-date, performing re-analysis /// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is /// free to ignore this, since the error is already registered. @@ -1360,7 +1611,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr // This resolves the type of the resolved value, not that value itself. If `nav_val` is a struct type, // this resolves the type `type` (which needs no resolution), not the struct itself. - try nav_ty.resolveLayout(pt); + try sema.ensureLayoutResolved(nav_ty); const queue_linker_work, const is_owned_fn = switch (ip.indexToKey(nav_val.toIntern())) { .func => |f| .{ true, f.owner_nav == nav_id }, // note that this lets function aliases reach codegen @@ -1377,7 +1628,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr if (zir_decl.align_body != null and !target_util.supportsFunctionAlignment(zcu.getTarget())) { return sema.fail(&block, align_src, "target does not support function alignment", .{}); } - } else if (try nav_ty.comptimeOnlySema(pt)) { + } else if (nav_ty.comptimeOnly(zcu)) { // alignment, linksection, addrspace annotations are not allowed for comptime-only types. const reason: []const u8 = switch (ip.indexToKey(nav_val.toIntern())) { .func => "function alias", // slightly clearer message, since you *can* specify these on function *declarations* @@ -1420,12 +1671,11 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr queue_codegen: { if (!queue_linker_work) break :queue_codegen; - if (!try nav_ty.hasRuntimeBitsSema(pt)) { + if (!nav_ty.hasRuntimeBits(zcu)) { if (zcu.comp.config.use_llvm) break :queue_codegen; if (file.mod.?.strip) break :queue_codegen; } - // This job depends on any resolve_type_fully jobs queued up before it. zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); try zcu.comp.queueJob(.{ .link_nav = nav_id }); } @@ -1628,7 +1878,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr break :ty .fromInterned(type_ref.toInterned().?); }; - try resolved_ty.resolveLayout(pt); + try sema.ensureLayoutResolved(resolved_ty); // In the case where the type is specified, this function is also responsible for resolving // the pointer modifiers, i.e. alignment, linksection, addrspace. @@ -1765,9 +2015,9 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, func_index: InternPool.Index) Z if (was_outdated) { if (ies_outdated) { - try zcu.markDependeeOutdated(.marked_po, .{ .interned = func_index }); + try zcu.markDependeeOutdated(.marked_po, .{ .func_ies = func_index }); } else { - try zcu.markPoDependeeUpToDate(.{ .interned = func_index }); + try zcu.markPoDependeeUpToDate(.{ .func_ies = func_index }); } } @@ -1817,7 +2067,7 @@ fn analyzeFuncBody( log.debug("analyze and generate fn body {f}", .{zcu.fmtAnalUnit(anal_unit)}); - var air = try pt.analyzeFnBodyInner(func_index); + var air = try pt.analyzeFuncBodyInner(func_index); errdefer air.deinit(gpa); const ies_outdated = !func.analysisUnordered(ip).inferred_error_set or @@ -1833,7 +2083,6 @@ fn analyzeFuncBody( return .{ .ies_outdated = ies_outdated }; } - // This job depends on any resolve_type_fully jobs queued up before it. zcu.codegen_prog_node.increaseEstimatedTotalItems(1); comp.link_prog_node.increaseEstimatedTotalItems(1); try comp.queueJob(.{ .codegen_func = .{ @@ -1844,94 +2093,12 @@ fn analyzeFuncBody( return .{ .ies_outdated = ies_outdated }; } -pub fn semaMod(pt: Zcu.PerThread, mod: *Module) !void { - dev.check(.sema); - const file_index = pt.zcu.module_roots.get(mod).?.unwrap().?; - const root_type = pt.zcu.fileRootType(file_index); - if (root_type == .none) { - return pt.semaFile(file_index); - } -} - -fn createFileRootStruct( - pt: Zcu.PerThread, - file_index: Zcu.File.Index, - namespace_index: Zcu.Namespace.Index, - replace_existing: bool, -) Allocator.Error!InternPool.Index { - const zcu = pt.zcu; - const gpa = zcu.gpa; - const io = zcu.comp.io; - const ip = &zcu.intern_pool; - const file = zcu.fileByIndex(file_index); - const extended = file.zir.?.instructions.items(.data)[@intFromEnum(Zir.Inst.Index.main_struct_inst)].extended; - assert(extended.opcode == .struct_decl); - const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); - assert(!small.has_captures_len); - assert(!small.has_backing_int); - assert(small.layout == .auto); - var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len; - const fields_len = if (small.has_fields_len) blk: { - const fields_len = file.zir.?.extra[extra_index]; - extra_index += 1; - break :blk fields_len; - } else 0; - const decls_len = if (small.has_decls_len) blk: { - const decls_len = file.zir.?.extra[extra_index]; - extra_index += 1; - break :blk decls_len; - } else 0; - const decls = file.zir.?.bodySlice(extra_index, decls_len); - extra_index += decls_len; - - const tracked_inst = try ip.trackZir(gpa, io, pt.tid, .{ - .file = file_index, - .inst = .main_struct_inst, - }); - const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{ - .layout = .auto, - .fields_len = fields_len, - .known_non_opv = small.known_non_opv, - .requires_comptime = if (small.known_comptime_only) .yes else .unknown, - .any_comptime_fields = small.any_comptime_fields, - .any_default_inits = small.any_default_inits, - .inits_resolved = false, - .any_aligned_fields = small.any_aligned_fields, - .key = .{ .declared = .{ - .zir_index = tracked_inst, - .captures = &.{}, - } }, - }, replace_existing)) { - .existing => unreachable, // we wouldn't be analysing the file root if this type existed - .wip => |wip| wip, - }; - errdefer wip_ty.cancel(ip, pt.tid); - - wip_ty.setName(ip, try file.internFullyQualifiedName(pt), .none); - ip.namespacePtr(namespace_index).owner_type = wip_ty.index; - - if (zcu.comp.config.incremental) { - try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = tracked_inst }); - } - - try pt.scanNamespace(namespace_index, decls); - try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); - codegen_type: { - if (file.mod.?.strip) break :codegen_type; - // This job depends on any resolve_type_fully jobs queued up before it. - zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); - try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); - } - zcu.setFileRootType(file_index, wip_ty.index); - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); - return wip_ty.finish(ip, namespace_index); -} - /// Re-scan the namespace of a file's root struct type on an incremental update. /// The file must have successfully populated ZIR. /// If the file's root struct type is not populated (the file is unreferenced), nothing is done. /// This is called by `updateZirRefs` for all updated files before the main work loop. /// This function does not perform any semantic analysis. +/// MLUGG TODO: mmmmm i have no idea if this makes sense... tbhwy i just want to update all *changed* namespaces at the start of an update or something lol fn updateFileNamespace(pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator.Error!void { const zcu = pt.zcu; @@ -1945,48 +2112,11 @@ fn updateFileNamespace(pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator. }); const namespace_index = Type.fromInterned(file_root_type).getNamespaceIndex(zcu); - const decls = decls: { - const extended = file.zir.?.instructions.items(.data)[@intFromEnum(Zir.Inst.Index.main_struct_inst)].extended; - const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); - - var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len; - extra_index += @intFromBool(small.has_fields_len); - const decls_len = if (small.has_decls_len) blk: { - const decls_len = file.zir.?.extra[extra_index]; - extra_index += 1; - break :blk decls_len; - } else 0; - break :decls file.zir.?.bodySlice(extra_index, decls_len); - }; + const decls = file.zir.?.getStructDecl(.main_struct_inst).decls; try pt.scanNamespace(namespace_index, decls); zcu.namespacePtr(namespace_index).generation = zcu.generation; } -fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void { - const tracy = trace(@src()); - defer tracy.end(); - - const zcu = pt.zcu; - const file = zcu.fileByIndex(file_index); - assert(file.getMode() == .zig); - assert(zcu.fileRootType(file_index) == .none); - - assert(file.zir != null); - - const new_namespace_index = try pt.createNamespace(.{ - .parent = .none, - .owner_type = undefined, // set in `createFileRootStruct` - .file_scope = file_index, - .generation = zcu.generation, - }); - const struct_ty = try pt.createFileRootStruct(file_index, new_namespace_index, false); - errdefer zcu.intern_pool.remove(pt.tid, struct_ty); - - if (zcu.comp.time_report) |*tr| { - tr.stats.n_imported_files += 1; - } -} - /// Called by AstGen worker threads when an import is seen. If `new_file` is returned, the caller is /// then responsible for queueing a new AstGen job for the new file. /// Assumes that `comp.mutex` is NOT locked. It will be locked by this function where necessary. @@ -2878,15 +3008,15 @@ const ScanDeclIter = struct { if (existing_unit == null and (want_analysis or decl.linkage == .@"export")) { log.debug( - "scanDecl queue analyze_comptime_unit file='{s}' unit={f}", + "scanDecl queue analyze_unit file='{s}' unit={f}", .{ namespace.fileScope(zcu).sub_file_path, zcu.fmtAnalUnit(unit) }, ); - try comp.queueJob(.{ .analyze_comptime_unit = unit }); + try comp.queueJob(.{ .analyze_unit = unit }); } } }; -fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!Air { +fn analyzeFuncBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!Air { const tracy = trace(@src()); defer tracy.end(); @@ -3020,16 +3150,12 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE const gop = sema.inst_map.getOrPutAssumeCapacity(inst); if (gop.found_existing) continue; // provided above by comptime arg - const param_ty = fn_ty_info.param_types.get(ip)[runtime_param_index]; + const param_ty: Type = .fromInterned(fn_ty_info.param_types.get(ip)[runtime_param_index]); runtime_param_index += 1; - const opt_opv = sema.typeHasOnePossibleValue(Type.fromInterned(param_ty)) catch |err| switch (err) { - error.ComptimeReturn => unreachable, - error.ComptimeBreak => unreachable, - else => |e| return e, - }; - if (opt_opv) |opv| { - gop.value_ptr.* = Air.internedToRef(opv.toIntern()); + try sema.ensureLayoutResolved(param_ty); + if (try param_ty.onePossibleValue(pt)) |opv| { + gop.value_ptr.* = .fromValue(opv); continue; } const arg_index: Air.Inst.Index = @enumFromInt(sema.air_instructions.len); @@ -3038,12 +3164,14 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE sema.air_instructions.appendAssumeCapacity(.{ .tag = .arg, .data = .{ .arg = .{ - .ty = Air.internedToRef(param_ty), + .ty = .fromIntern(param_ty.toIntern()), .zir_param_index = @intCast(zir_param_index), } }, }); } + try sema.ensureLayoutResolved(sema.fn_ret_ty); + const last_arg_index = inner_block.instructions.items.len; // Save the error trace as our first action in the function. @@ -3103,21 +3231,9 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE func.setResolvedErrorSet(ip, io, ies.resolved); } + // MLUGG TODO: i think this can go away and the assert move to the defer? assert(zcu.analysis_in_progress.swapRemove(anal_unit)); - // Finally we must resolve the return type and parameter types so that backends - // have full access to type information. - // Crucially, this happens *after* we set the function state to success above, - // so that dependencies on the function body will now be satisfied rather than - // result in circular dependency errors. - // TODO: this can go away once we fix backends having to resolve `StackTrace`. - // The codegen timing guarantees that the parameter types will be populated. - sema.resolveFnTypes(fn_ty, inner_block.nodeOffset(.zero)) catch |err| switch (err) { - error.ComptimeReturn => unreachable, - error.ComptimeBreak => unreachable, - else => |e| return e, - }; - try sema.flushExports(); defer { @@ -3605,16 +3721,6 @@ pub fn ptrType(pt: Zcu.PerThread, info: InternPool.Key.PtrType) Allocator.Error! if (info.flags.size == .c) canon_info.flags.is_allowzero = true; - // Canonicalize non-zero alignment. If it matches the ABI alignment of the pointee - // type, we change it to 0 here. If this causes an assertion trip because the - // pointee type needs to be resolved more, that needs to be done before calling - // this ptr() function. - if (info.flags.alignment != .none and - info.flags.alignment == Type.fromInterned(info.child).abiAlignment(pt.zcu)) - { - canon_info.flags.alignment = .none; - } - switch (info.flags.vector_index) { // Canonicalize host_size. If it matches the bit size of the pointee type, // we change it to 0 here. If this causes an assertion trip, the pointee type @@ -3632,16 +3738,6 @@ pub fn ptrType(pt: Zcu.PerThread, info: InternPool.Key.PtrType) Allocator.Error! return Type.fromInterned(try pt.intern(.{ .ptr_type = canon_info })); } -/// Like `ptrType`, but if `info` specifies an `alignment`, first ensures the pointer -/// child type's alignment is resolved so that an invalid alignment is not used. -/// In general, prefer this function during semantic analysis. -pub fn ptrTypeSema(pt: Zcu.PerThread, info: InternPool.Key.PtrType) Zcu.SemaError!Type { - if (info.flags.alignment != .none) { - _ = try Type.fromInterned(info.child).abiAlignmentSema(pt); - } - return pt.ptrType(info); -} - pub fn singleMutPtrType(pt: Zcu.PerThread, child_type: Type) Allocator.Error!Type { return pt.ptrType(.{ .child = child_type.toIntern() }); } @@ -3739,31 +3835,37 @@ pub fn enumValue(pt: Zcu.PerThread, ty: Type, tag_int: InternPool.Index) Allocat /// declaration order. pub fn enumValueFieldIndex(pt: Zcu.PerThread, ty: Type, field_index: u32) Allocator.Error!Value { const ip = &pt.zcu.intern_pool; + ty.assertHasInits(pt.zcu); const enum_type = ip.loadEnumType(ty.toIntern()); - if (enum_type.values.len == 0) { + assert(field_index < enum_type.field_names.len); + + if (enum_type.field_values.len == 0) { // Auto-numbered fields. return Value.fromInterned(try pt.intern(.{ .enum_tag = .{ .ty = ty.toIntern(), .int = try pt.intern(.{ .int = .{ - .ty = enum_type.tag_ty, + .ty = enum_type.int_tag_type, .storage = .{ .u64 = field_index }, } }), } })); } - return Value.fromInterned(try pt.intern(.{ .enum_tag = .{ + return .fromInterned(try pt.intern(.{ .enum_tag = .{ .ty = ty.toIntern(), - .int = enum_type.values.get(ip)[field_index], + .int = enum_type.field_values.get(ip)[field_index], } })); } pub fn undefValue(pt: Zcu.PerThread, ty: Type) Allocator.Error!Value { - return Value.fromInterned(try pt.intern(.{ .undef = ty.toIntern() })); + if (std.debug.runtime_safety) { + assert(try ty.onePossibleValue(pt) == null); + } + return .fromInterned(try pt.intern(.{ .undef = ty.toIntern() })); } pub fn undefRef(pt: Zcu.PerThread, ty: Type) Allocator.Error!Air.Inst.Ref { - return Air.internedToRef((try pt.undefValue(ty)).toIntern()); + return .fromValue(try pt.undefValue(ty)); } pub fn intValue(pt: Zcu.PerThread, ty: Type, x: anytype) Allocator.Error!Value { @@ -3916,7 +4018,7 @@ pub fn intFittingRange(pt: Zcu.PerThread, min: Value, max: Value) !Type { assert(Value.order(min, max, zcu).compare(.lte)); } - const sign = min.orderAgainstZero(zcu) == .lt; + const sign = min.compareHetero(.lt, .zero_comptime_int, zcu); const min_val_bits = pt.intBitsForValue(min, sign); const max_val_bits = pt.intBitsForValue(max, sign); @@ -3955,12 +4057,6 @@ pub fn intBitsForValue(pt: Zcu.PerThread, val: Value, sign: bool) u16 { return @as(u16, @intCast(big.bitCountTwosComp())); }, - .lazy_align => |lazy_ty| { - return Type.smallestUnsignedBits(Type.fromInterned(lazy_ty).abiAlignment(pt.zcu).toByteUnits() orelse 0) + @intFromBool(sign); - }, - .lazy_size => |lazy_ty| { - return Type.smallestUnsignedBits(Type.fromInterned(lazy_ty).abiSize(pt.zcu)) + @intFromBool(sign); - }, } } @@ -3993,7 +4089,6 @@ pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) Allocator.Error! const comp = zcu.comp; const result = try zcu.intern_pool.getExtern(comp.gpa, comp.io, pt.tid, key); if (result.new_nav.unwrap()) |nav| { - // This job depends on any resolve_type_fully jobs queued up before it. comp.link_prog_node.increaseEstimatedTotalItems(1); try comp.queueJob(.{ .link_nav = nav }); if (comp.debugIncremental()) try zcu.incremental_debug_state.newNav(zcu, nav); @@ -4013,367 +4108,6 @@ pub fn navAlignment(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) InternPo return ty.abiAlignment(zcu); } -/// `ty` is a container type requiring resolution (struct, union, or enum). -/// If `ty` is outdated, it is recreated at a new `InternPool.Index`, which is returned. -/// If the type cannot be recreated because it has been lost, `error.AnalysisFail` is returned. -/// If `ty` is not outdated, that same `InternPool.Index` is returned. -/// If `ty` has already been replaced by this function, the new index will not be returned again. -/// Also, if `ty` is an enum, this function will resolve the new type if needed, and the call site -/// is responsible for checking `[transitive_]failed_analysis` to detect resolution failures. -pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index) Zcu.SemaError!InternPool.Index { - const zcu = pt.zcu; - const gpa = zcu.gpa; - const ip = &zcu.intern_pool; - - const anal_unit: AnalUnit = .wrap(.{ .type = ty }); - const outdated = zcu.outdated.swapRemove(anal_unit) or - zcu.potentially_outdated.swapRemove(anal_unit); - - if (outdated) { - _ = zcu.outdated_ready.swapRemove(anal_unit); - try zcu.markDependeeOutdated(.marked_po, .{ .interned = ty }); - } - - const ty_key = switch (ip.indexToKey(ty)) { - .struct_type, .union_type, .enum_type => |key| key, - else => unreachable, - }; - const declared_ty_key = switch (ty_key) { - .reified => unreachable, // never outdated - .generated_tag => unreachable, // never outdated - .declared => |d| d, - }; - - if (declared_ty_key.zir_index.resolve(ip) == null) { - // The instruction has been lost -- this type is dead. - return error.AnalysisFail; - } - - if (!outdated) return ty; - - // We will recreate the type at a new `InternPool.Index`. - - // Delete old state which is no longer in use. Technically, this is not necessary: these exports, - // references, etc, will be ignored because the type itself is unreferenced. However, it allows - // reusing the memory which is currently being used to track this state. - zcu.deleteUnitExports(anal_unit); - zcu.deleteUnitReferences(anal_unit); - zcu.deleteUnitCompileLogs(anal_unit); - if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| { - kv.value.destroy(gpa); - } - _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); - zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit); - - if (zcu.comp.debugIncremental()) { - const info = try zcu.incremental_debug_state.getUnitInfo(gpa, anal_unit); - info.last_update_gen = zcu.generation; - info.deps.clearRetainingCapacity(); - } - - switch (ip.indexToKey(ty)) { - .struct_type => return pt.recreateStructType(ty, declared_ty_key), - .union_type => return pt.recreateUnionType(ty, declared_ty_key), - .enum_type => return pt.recreateEnumType(ty, declared_ty_key), - else => unreachable, - } -} - -fn recreateStructType( - pt: Zcu.PerThread, - old_ty: InternPool.Index, - key: InternPool.Key.NamespaceType.Declared, -) Allocator.Error!InternPool.Index { - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const io = comp.io; - const ip = &zcu.intern_pool; - - const inst_info = key.zir_index.resolveFull(ip).?; - const file = zcu.fileByIndex(inst_info.file); - const zir = file.zir.?; - - assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); - const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended; - assert(extended.opcode == .struct_decl); - const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); - const extra = zir.extraData(Zir.Inst.StructDecl, extended.operand); - var extra_index = extra.end; - - const captures_len = if (small.has_captures_len) blk: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - const fields_len = if (small.has_fields_len) blk: { - const fields_len = zir.extra[extra_index]; - extra_index += 1; - break :blk fields_len; - } else 0; - - assert(captures_len == key.captures.owned.len); // synchronises with logic in `Zcu.mapOldZirToNew` - - const struct_obj = ip.loadStructType(old_ty); - - const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{ - .layout = small.layout, - .fields_len = fields_len, - .known_non_opv = small.known_non_opv, - .requires_comptime = if (small.known_comptime_only) .yes else .unknown, - .any_comptime_fields = small.any_comptime_fields, - .any_default_inits = small.any_default_inits, - .inits_resolved = false, - .any_aligned_fields = small.any_aligned_fields, - .key = .{ .declared_owned_captures = .{ - .zir_index = key.zir_index, - .captures = key.captures.owned, - } }, - }, true)) { - .wip => |wip| wip, - .existing => unreachable, // we passed `replace_existing` - }; - errdefer wip_ty.cancel(ip, pt.tid); - - wip_ty.setName(ip, struct_obj.name, struct_obj.name_nav); - try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = key.zir_index }); - zcu.namespacePtr(struct_obj.namespace).owner_type = wip_ty.index; - // No need to re-scan the namespace -- `zirStructDecl` will ultimately do that if the type is still alive. - try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); - - codegen_type: { - if (file.mod.?.strip) break :codegen_type; - // This job depends on any resolve_type_fully jobs queued up before it. - zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); - try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); - } - - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); - const new_ty = wip_ty.finish(ip, struct_obj.namespace); - if (inst_info.inst == .main_struct_inst) { - // This is the root type of a file! Update the reference. - zcu.setFileRootType(inst_info.file, new_ty); - } - return new_ty; -} - -fn recreateUnionType( - pt: Zcu.PerThread, - old_ty: InternPool.Index, - key: InternPool.Key.NamespaceType.Declared, -) Allocator.Error!InternPool.Index { - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const io = comp.io; - const ip = &zcu.intern_pool; - - const inst_info = key.zir_index.resolveFull(ip).?; - const file = zcu.fileByIndex(inst_info.file); - const zir = file.zir.?; - - assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); - const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended; - assert(extended.opcode == .union_decl); - const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); - const extra = zir.extraData(Zir.Inst.UnionDecl, extended.operand); - var extra_index = extra.end; - - extra_index += @intFromBool(small.has_tag_type); - const captures_len = if (small.has_captures_len) blk: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - extra_index += @intFromBool(small.has_body_len); - const fields_len = if (small.has_fields_len) blk: { - const fields_len = zir.extra[extra_index]; - extra_index += 1; - break :blk fields_len; - } else 0; - - assert(captures_len == key.captures.owned.len); // synchronises with logic in `Zcu.mapOldZirToNew` - - const union_obj = ip.loadUnionType(old_ty); - - const namespace_index = union_obj.namespace; - - const wip_ty = switch (try ip.getUnionType(gpa, io, pt.tid, .{ - .flags = .{ - .layout = small.layout, - .status = .none, - .runtime_tag = if (small.has_tag_type or small.auto_enum_tag) - .tagged - else if (small.layout != .auto) - .none - else switch (true) { // TODO - true => .safety, - false => .none, - }, - .any_aligned_fields = small.any_aligned_fields, - .requires_comptime = .unknown, - .assumed_runtime_bits = false, - .assumed_pointer_aligned = false, - .alignment = .none, - }, - .fields_len = fields_len, - .enum_tag_ty = .none, // set later - .field_types = &.{}, // set later - .field_aligns = &.{}, // set later - .key = .{ .declared_owned_captures = .{ - .zir_index = key.zir_index, - .captures = key.captures.owned, - } }, - }, true)) { - .wip => |wip| wip, - .existing => unreachable, // we passed `replace_existing` - }; - errdefer wip_ty.cancel(ip, pt.tid); - - wip_ty.setName(ip, union_obj.name, union_obj.name_nav); - try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = key.zir_index }); - zcu.namespacePtr(namespace_index).owner_type = wip_ty.index; - // No need to re-scan the namespace -- `zirUnionDecl` will ultimately do that if the type is still alive. - try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index }); - - codegen_type: { - if (file.mod.?.strip) break :codegen_type; - // This job depends on any resolve_type_fully jobs queued up before it. - zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); - try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); - } - - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); - return wip_ty.finish(ip, namespace_index); -} - -/// This *does* call `Sema.resolveDeclaredEnum`, but errors from it are not propagated. -/// Call sites are resposible for checking `[transitive_]failed_analysis` after `ensureTypeUpToDate` -/// returns in order to detect resolution failures. -fn recreateEnumType( - pt: Zcu.PerThread, - old_ty: InternPool.Index, - key: InternPool.Key.NamespaceType.Declared, -) (Allocator.Error || Io.Cancelable)!InternPool.Index { - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const io = comp.io; - const ip = &zcu.intern_pool; - - const inst_info = key.zir_index.resolveFull(ip).?; - const file = zcu.fileByIndex(inst_info.file); - const zir = file.zir.?; - - assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); - const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended; - assert(extended.opcode == .enum_decl); - const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small); - const extra = zir.extraData(Zir.Inst.EnumDecl, extended.operand); - var extra_index = extra.end; - - const tag_type_ref = if (small.has_tag_type) blk: { - const tag_type_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]); - extra_index += 1; - break :blk tag_type_ref; - } else .none; - - const captures_len = if (small.has_captures_len) blk: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - - const body_len = if (small.has_body_len) blk: { - const body_len = zir.extra[extra_index]; - extra_index += 1; - break :blk body_len; - } else 0; - - const fields_len = if (small.has_fields_len) blk: { - const fields_len = zir.extra[extra_index]; - extra_index += 1; - break :blk fields_len; - } else 0; - - const decls_len = if (small.has_decls_len) blk: { - const decls_len = zir.extra[extra_index]; - extra_index += 1; - break :blk decls_len; - } else 0; - - assert(captures_len == key.captures.owned.len); // synchronises with logic in `Zcu.mapOldZirToNew` - - extra_index += captures_len * 2; - extra_index += decls_len; - - const body = zir.bodySlice(extra_index, body_len); - extra_index += body.len; - - const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable; - const body_end = extra_index; - extra_index += bit_bags_count; - - const any_values = for (zir.extra[body_end..][0..bit_bags_count]) |bag| { - if (bag != 0) break true; - } else false; - - const enum_obj = ip.loadEnumType(old_ty); - - const namespace_index = enum_obj.namespace; - - const wip_ty = switch (try ip.getEnumType(gpa, io, pt.tid, .{ - .has_values = any_values, - .tag_mode = if (small.nonexhaustive) - .nonexhaustive - else if (tag_type_ref == .none) - .auto - else - .explicit, - .fields_len = fields_len, - .key = .{ .declared_owned_captures = .{ - .zir_index = key.zir_index, - .captures = key.captures.owned, - } }, - }, true)) { - .wip => |wip| wip, - .existing => unreachable, // we passed `replace_existing` - }; - var done = true; - errdefer if (!done) wip_ty.cancel(ip, pt.tid); - - wip_ty.setName(ip, enum_obj.name, enum_obj.name_nav); - - zcu.namespacePtr(namespace_index).owner_type = wip_ty.index; - // No need to re-scan the namespace -- `zirEnumDecl` will ultimately do that if the type is still alive. - - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); - wip_ty.prepare(ip, namespace_index); - done = true; - - Sema.resolveDeclaredEnum( - pt, - wip_ty, - inst_info.inst, - key.zir_index, - namespace_index, - enum_obj.name, - small, - body, - tag_type_ref, - any_values, - fields_len, - zir, - body_end, - ) catch |err| switch (err) { - error.OutOfMemory => |e| return e, - error.Canceled => |e| return e, - error.AnalysisFail => {}, // call sites are responsible for checking `[transitive_]failed_analysis` to detect this - }; - - return wip_ty.index; -} - /// Given a namespace, re-scan its declarations from the type definition if they have not /// yet been re-scanned on this update. /// If the type declaration instruction has been lost, returns `error.AnalysisFail`. @@ -4396,7 +4130,7 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace }; const key = switch (full_key) { - .reified, .generated_tag => { + .reified, .generated_union_tag => { // Namespace always empty, so up-to-date. namespace.generation = zcu.generation; return; @@ -4408,100 +4142,13 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace const inst_info = key.zir_index.resolveFull(ip) orelse return error.AnalysisFail; const file = zcu.fileByIndex(inst_info.file); - const zir = file.zir.?; - - assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended); - const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended; + const zir = &file.zir.?; const decls = switch (container) { - .@"struct" => decls: { - assert(extended.opcode == .struct_decl); - const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); - const extra = zir.extraData(Zir.Inst.StructDecl, extended.operand); - var extra_index = extra.end; - const captures_len = if (small.has_captures_len) blk: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - extra_index += @intFromBool(small.has_fields_len); - const decls_len = if (small.has_decls_len) blk: { - const decls_len = zir.extra[extra_index]; - extra_index += 1; - break :blk decls_len; - } else 0; - extra_index += captures_len * 2; - if (small.has_backing_int) { - const backing_int_body_len = zir.extra[extra_index]; - extra_index += 1; // backing_int_body_len - if (backing_int_body_len == 0) { - extra_index += 1; // backing_int_ref - } else { - extra_index += backing_int_body_len; // backing_int_body_inst - } - } - break :decls zir.bodySlice(extra_index, decls_len); - }, - .@"union" => decls: { - assert(extended.opcode == .union_decl); - const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small); - const extra = zir.extraData(Zir.Inst.UnionDecl, extended.operand); - var extra_index = extra.end; - extra_index += @intFromBool(small.has_tag_type); - const captures_len = if (small.has_captures_len) blk: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - extra_index += @intFromBool(small.has_body_len); - extra_index += @intFromBool(small.has_fields_len); - const decls_len = if (small.has_decls_len) blk: { - const decls_len = zir.extra[extra_index]; - extra_index += 1; - break :blk decls_len; - } else 0; - extra_index += captures_len * 2; - break :decls zir.bodySlice(extra_index, decls_len); - }, - .@"enum" => decls: { - assert(extended.opcode == .enum_decl); - const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small); - const extra = zir.extraData(Zir.Inst.EnumDecl, extended.operand); - var extra_index = extra.end; - extra_index += @intFromBool(small.has_tag_type); - const captures_len = if (small.has_captures_len) blk: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - extra_index += @intFromBool(small.has_body_len); - extra_index += @intFromBool(small.has_fields_len); - const decls_len = if (small.has_decls_len) blk: { - const decls_len = zir.extra[extra_index]; - extra_index += 1; - break :blk decls_len; - } else 0; - extra_index += captures_len * 2; - break :decls zir.bodySlice(extra_index, decls_len); - }, - .@"opaque" => decls: { - assert(extended.opcode == .opaque_decl); - const small: Zir.Inst.OpaqueDecl.Small = @bitCast(extended.small); - const extra = zir.extraData(Zir.Inst.OpaqueDecl, extended.operand); - var extra_index = extra.end; - const captures_len = if (small.has_captures_len) blk: { - const captures_len = zir.extra[extra_index]; - extra_index += 1; - break :blk captures_len; - } else 0; - const decls_len = if (small.has_decls_len) blk: { - const decls_len = zir.extra[extra_index]; - extra_index += 1; - break :blk decls_len; - } else 0; - extra_index += captures_len * 2; - break :decls zir.bodySlice(extra_index, decls_len); - }, + .@"struct" => zir.getStructDecl(inst_info.inst).decls, + .@"union" => zir.getUnionDecl(inst_info.inst).decls, + .@"enum" => zir.getEnumDecl(inst_info.inst).decls, + .@"opaque" => zir.getOpaqueDecl(inst_info.inst).decls, }; try pt.scanNamespace(namespace_index, decls); @@ -4509,7 +4156,7 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace } pub fn refValue(pt: Zcu.PerThread, val: InternPool.Index) Zcu.SemaError!InternPool.Index { - const ptr_ty = (try pt.ptrTypeSema(.{ + const ptr_ty = (try pt.ptrType(.{ .child = pt.zcu.intern_pool.typeOf(val), .flags = .{ .alignment = .none, @@ -4703,3 +4350,466 @@ fn printVerboseAir( try air.write(w, pt, liveness); try w.print("# End Function AIR: {f}\n\n", .{fqn.fmt(ip)}); } + +// MLUGG TODO: these functions are all blatant hacks. See if I can remove them! +pub fn resolveTypeForCodegen(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void { + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + if (ty.isGenericPoison()) return; + switch (ty.zigTypeTag(zcu)) { + .type, + .void, + .bool, + .noreturn, + .int, + .float, + .error_set, + .@"opaque", + .comptime_float, + .comptime_int, + .undefined, + .null, + .enum_literal, + => {}, + + .frame, .@"anyframe" => @panic("TODO resolveTypeForCodegen async frames"), + + .optional => try pt.resolveTypeForCodegen(ty.childType(zcu)), + .error_union => try pt.resolveTypeForCodegen(ty.errorUnionPayload(zcu)), + .pointer => try pt.resolveTypeForCodegen(ty.childType(zcu)), + .array => try pt.resolveTypeForCodegen(ty.childType(zcu)), + .vector => try pt.resolveTypeForCodegen(ty.childType(zcu)), + + .@"fn" => { + const info = zcu.typeToFunc(ty).?; + for (0..info.param_types.len) |i| { + const param_ty = info.param_types.get(ip)[i]; + try pt.resolveTypeForCodegen(.fromInterned(param_ty)); + } + try pt.resolveTypeForCodegen(.fromInterned(info.return_type)); + }, + + .@"struct" => switch (ip.indexToKey(ty.toIntern())) { + .struct_type => { + try pt.ensureTypeLayoutUpToDate(ty); + try pt.ensureTypeInitsUpToDate(ty); + }, + .tuple_type => |tuple| for (0..tuple.types.len) |i| { + const field_is_comptime = tuple.values.get(ip)[i] != .none; + if (field_is_comptime) continue; + const field_ty = tuple.types.get(ip)[i]; + try pt.resolveTypeForCodegen(.fromInterned(field_ty)); + }, + else => unreachable, + }, + + .@"union" => try pt.ensureTypeLayoutUpToDate(ty), + .@"enum" => try pt.ensureTypeInitsUpToDate(ty), + } +} +pub fn resolveValueTypesForCodegen(pt: Zcu.PerThread, val: Value) Zcu.SemaError!void { + const zcu = pt.zcu; + const ty: Type = switch (val.typeOf(zcu).toIntern()) { + .type_type => if (val.isUndef(zcu)) { + return; + } else val.toType(), + else => |ty| .fromInterned(ty), + }; + return pt.resolveTypeForCodegen(ty); +} +pub fn resolveAirTypesForCodegen(pt: Zcu.PerThread, air: *const Air) Zcu.SemaError!void { + return pt.resolveBodyTypesForCodegen(air, air.getMainBody()); +} +fn resolveBodyTypesForCodegen(pt: Zcu.PerThread, air: *const Air, body: []const Air.Inst.Index) Zcu.SemaError!void { + const zcu = pt.zcu; + const tags = air.instructions.items(.tag); + const datas = air.instructions.items(.data); + for (body) |inst| { + const data = datas[@intFromEnum(inst)]; + switch (tags[@intFromEnum(inst)]) { + .inferred_alloc, .inferred_alloc_comptime => unreachable, + + .arg => try pt.resolveTypeForCodegen(data.arg.ty.toType()), + + .add, + .add_safe, + .add_optimized, + .add_wrap, + .add_sat, + .sub, + .sub_safe, + .sub_optimized, + .sub_wrap, + .sub_sat, + .mul, + .mul_safe, + .mul_optimized, + .mul_wrap, + .mul_sat, + .div_float, + .div_float_optimized, + .div_trunc, + .div_trunc_optimized, + .div_floor, + .div_floor_optimized, + .div_exact, + .div_exact_optimized, + .rem, + .rem_optimized, + .mod, + .mod_optimized, + .max, + .min, + .bit_and, + .bit_or, + .shr, + .shr_exact, + .shl, + .shl_exact, + .shl_sat, + .xor, + .cmp_lt, + .cmp_lt_optimized, + .cmp_lte, + .cmp_lte_optimized, + .cmp_eq, + .cmp_eq_optimized, + .cmp_gte, + .cmp_gte_optimized, + .cmp_gt, + .cmp_gt_optimized, + .cmp_neq, + .cmp_neq_optimized, + .bool_and, + .bool_or, + .store, + .store_safe, + .set_union_tag, + .array_elem_val, + .slice_elem_val, + .ptr_elem_val, + .memset, + .memset_safe, + .memcpy, + .memmove, + .atomic_store_unordered, + .atomic_store_monotonic, + .atomic_store_release, + .atomic_store_seq_cst, + .legalize_vec_elem_val, + => { + try pt.resolveRefTypesForCodegen(data.bin_op.lhs); + try pt.resolveRefTypesForCodegen(data.bin_op.rhs); + }, + + .not, + .bitcast, + .clz, + .ctz, + .popcount, + .byte_swap, + .bit_reverse, + .abs, + .load, + .fptrunc, + .fpext, + .intcast, + .intcast_safe, + .trunc, + .optional_payload, + .optional_payload_ptr, + .optional_payload_ptr_set, + .wrap_optional, + .unwrap_errunion_payload, + .unwrap_errunion_err, + .unwrap_errunion_payload_ptr, + .unwrap_errunion_err_ptr, + .errunion_payload_ptr_set, + .wrap_errunion_payload, + .wrap_errunion_err, + .struct_field_ptr_index_0, + .struct_field_ptr_index_1, + .struct_field_ptr_index_2, + .struct_field_ptr_index_3, + .get_union_tag, + .slice_len, + .slice_ptr, + .ptr_slice_len_ptr, + .ptr_slice_ptr_ptr, + .array_to_slice, + .int_from_float, + .int_from_float_optimized, + .int_from_float_safe, + .int_from_float_optimized_safe, + .float_from_int, + .splat, + .error_set_has_value, + .addrspace_cast, + .c_va_arg, + .c_va_copy, + => { + try pt.resolveTypeForCodegen(data.ty_op.ty.toType()); + try pt.resolveRefTypesForCodegen(data.ty_op.operand); + }, + + .alloc, + .ret_ptr, + .c_va_start, + => try pt.resolveTypeForCodegen(data.ty), + + .ptr_add, + .ptr_sub, + .add_with_overflow, + .sub_with_overflow, + .mul_with_overflow, + .shl_with_overflow, + .slice, + .slice_elem_ptr, + .ptr_elem_ptr, + => { + const bin = air.extraData(Air.Bin, data.ty_pl.payload).data; + try pt.resolveTypeForCodegen(data.ty_pl.ty.toType()); + try pt.resolveRefTypesForCodegen(bin.lhs); + try pt.resolveRefTypesForCodegen(bin.rhs); + }, + + .block, + .loop, + => { + const block = air.unwrapBlock(inst); + try pt.resolveTypeForCodegen(block.ty); + try pt.resolveBodyTypesForCodegen(air, block.body); + }, + + .dbg_inline_block => { + const block = air.unwrapDbgBlock(inst); + try pt.resolveTypeForCodegen(block.ty); + try pt.resolveBodyTypesForCodegen(air, block.body); + }, + + .sqrt, + .sin, + .cos, + .tan, + .exp, + .exp2, + .log, + .log2, + .log10, + .floor, + .ceil, + .round, + .trunc_float, + .neg, + .neg_optimized, + .is_null, + .is_non_null, + .is_null_ptr, + .is_non_null_ptr, + .is_err, + .is_non_err, + .is_err_ptr, + .is_non_err_ptr, + .ret, + .ret_safe, + .ret_load, + .is_named_enum_value, + .tag_name, + .error_name, + .cmp_lt_errors_len, + .c_va_end, + .set_err_return_trace, + => try pt.resolveRefTypesForCodegen(data.un_op), + + .br, .switch_dispatch => try pt.resolveRefTypesForCodegen(data.br.operand), + + .cmp_vector, + .cmp_vector_optimized, + => { + const extra = air.extraData(Air.VectorCmp, data.ty_pl.payload).data; + try pt.resolveTypeForCodegen(data.ty_pl.ty.toType()); + try pt.resolveRefTypesForCodegen(extra.lhs); + try pt.resolveRefTypesForCodegen(extra.rhs); + }, + + .reduce, + .reduce_optimized, + => try pt.resolveRefTypesForCodegen(data.reduce.operand), + + .struct_field_ptr, + .struct_field_val, + => { + const extra = air.extraData(Air.StructField, data.ty_pl.payload).data; + try pt.resolveTypeForCodegen(data.ty_pl.ty.toType()); + try pt.resolveRefTypesForCodegen(extra.struct_operand); + }, + + .shuffle_one => { + const unwrapped = air.unwrapShuffleOne(zcu, inst); + try pt.resolveTypeForCodegen(unwrapped.result_ty); + try pt.resolveRefTypesForCodegen(unwrapped.operand); + for (unwrapped.mask) |m| switch (m.unwrap()) { + .elem => {}, + .value => |val| try pt.resolveValueTypesForCodegen(.fromInterned(val)), + }; + }, + + .shuffle_two => { + const unwrapped = air.unwrapShuffleTwo(zcu, inst); + try pt.resolveTypeForCodegen(unwrapped.result_ty); + try pt.resolveRefTypesForCodegen(unwrapped.operand_a); + try pt.resolveRefTypesForCodegen(unwrapped.operand_b); + // No values to check because there are no comptime-known values other than undef + }, + + .cmpxchg_weak, + .cmpxchg_strong, + => { + const extra = air.extraData(Air.Cmpxchg, data.ty_pl.payload).data; + try pt.resolveTypeForCodegen(data.ty_pl.ty.toType()); + try pt.resolveRefTypesForCodegen(extra.ptr); + try pt.resolveRefTypesForCodegen(extra.expected_value); + try pt.resolveRefTypesForCodegen(extra.new_value); + }, + + .aggregate_init => { + const ty = data.ty_pl.ty.toType(); + const elems_len: usize = @intCast(ty.arrayLen(zcu)); + const elems: []const Air.Inst.Ref = @ptrCast(air.extra.items[data.ty_pl.payload..][0..elems_len]); + try pt.resolveTypeForCodegen(ty); + if (ty.zigTypeTag(zcu) == .@"struct") { + for (elems, 0..) |elem, elem_idx| { + if (ty.structFieldIsComptime(elem_idx, zcu)) continue; + try pt.resolveRefTypesForCodegen(elem); + } + } else { + for (elems) |elem| { + try pt.resolveRefTypesForCodegen(elem); + } + } + }, + + .union_init => { + const extra = air.extraData(Air.UnionInit, data.ty_pl.payload).data; + try pt.resolveTypeForCodegen(data.ty_pl.ty.toType()); + try pt.resolveRefTypesForCodegen(extra.init); + }, + + .field_parent_ptr => { + const extra = air.extraData(Air.FieldParentPtr, data.ty_pl.payload).data; + try pt.resolveTypeForCodegen(data.ty_pl.ty.toType()); + try pt.resolveRefTypesForCodegen(extra.field_ptr); + }, + + .atomic_load => try pt.resolveRefTypesForCodegen(data.atomic_load.ptr), + + .prefetch => try pt.resolveRefTypesForCodegen(data.prefetch.ptr), + + .runtime_nav_ptr => try pt.resolveTypeForCodegen(.fromInterned(data.ty_nav.ty)), + + .select, + .mul_add, + .legalize_vec_store_elem, + => { + const bin = air.extraData(Air.Bin, data.pl_op.payload).data; + try pt.resolveRefTypesForCodegen(data.pl_op.operand); + try pt.resolveRefTypesForCodegen(bin.lhs); + try pt.resolveRefTypesForCodegen(bin.rhs); + }, + + .atomic_rmw => { + const extra = air.extraData(Air.AtomicRmw, data.pl_op.payload).data; + try pt.resolveRefTypesForCodegen(data.pl_op.operand); + try pt.resolveRefTypesForCodegen(extra.operand); + }, + + .call, + .call_always_tail, + .call_never_tail, + .call_never_inline, + => { + const call = air.unwrapCall(inst); + try pt.resolveRefTypesForCodegen(call.callee); + for (call.args) |arg| try pt.resolveRefTypesForCodegen(arg); + }, + + .dbg_var_ptr, + .dbg_var_val, + .dbg_arg_inline, + => try pt.resolveRefTypesForCodegen(data.pl_op.operand), + + .@"try", .try_cold => { + const @"try" = air.unwrapTry(inst); + try pt.resolveRefTypesForCodegen(@"try".error_union); + try pt.resolveBodyTypesForCodegen(air, @"try".else_body); + }, + + .try_ptr, .try_ptr_cold => { + const try_ptr = air.unwrapTryPtr(inst); + try pt.resolveTypeForCodegen(try_ptr.error_union_payload_ptr_ty.toType()); + try pt.resolveRefTypesForCodegen(try_ptr.error_union_ptr); + try pt.resolveBodyTypesForCodegen(air, try_ptr.else_body); + }, + + .cond_br => { + const cond_br = air.unwrapCondBr(inst); + try pt.resolveRefTypesForCodegen(cond_br.condition); + try pt.resolveBodyTypesForCodegen(air, cond_br.then_body); + try pt.resolveBodyTypesForCodegen(air, cond_br.else_body); + }, + + .switch_br, .loop_switch_br => { + const switch_br = air.unwrapSwitch(inst); + try pt.resolveRefTypesForCodegen(switch_br.operand); + var it = switch_br.iterateCases(); + while (it.next()) |case| { + for (case.items) |item| { + try pt.resolveRefTypesForCodegen(item); + } + for (case.ranges) |range| { + try pt.resolveRefTypesForCodegen(range[0]); + try pt.resolveRefTypesForCodegen(range[1]); + } + try pt.resolveBodyTypesForCodegen(air, case.body); + } + try pt.resolveBodyTypesForCodegen(air, it.elseBody()); + }, + + .assembly => { + const @"asm" = air.unwrapAsm(inst); + try pt.resolveTypeForCodegen(data.ty_pl.ty.toType()); + for (@"asm".outputs) |output| if (output != .none) try pt.resolveRefTypesForCodegen(output); + for (@"asm".inputs) |input| if (input != .none) try pt.resolveRefTypesForCodegen(input); + }, + + .legalize_compiler_rt_call => { + const compiler_rt_call = air.unwrapCompilerRtCall(inst); + for (compiler_rt_call.args) |arg| try pt.resolveRefTypesForCodegen(arg); + }, + + .trap, + .breakpoint, + .ret_addr, + .frame_addr, + .unreach, + .wasm_memory_size, + .wasm_memory_grow, + .work_item_id, + .work_group_size, + .work_group_id, + .dbg_stmt, + .dbg_empty_stmt, + .err_return_trace, + .save_err_return_trace_index, + .repeat, + => {}, + } + } +} +fn resolveRefTypesForCodegen(pt: Zcu.PerThread, ref: Air.Inst.Ref) Zcu.SemaError!void { + const ip_index = ref.toInterned() orelse { + // `ref` refers to a prior instruction, which we already did the resolution for. + return; + }; + return pt.resolveValueTypesForCodegen(.fromInterned(ip_index)); +} diff --git a/src/codegen.zig b/src/codegen.zig index 6bdfa32f45f277ecd40d18e990f5f7219b81f5e4..176649f5b3d90bfca38ab60da0877734440761ee 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -1088,7 +1088,7 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo return .{ .immediate = fn_ty.abiAlignment(zcu).toByteUnits().? }; } } else if (ty.zigTypeTag(zcu) == .pointer) { - const elem_ty = ty.elemType2(zcu); + const elem_ty = ty.childType(zcu); if (!elem_ty.hasRuntimeBits(zcu)) { return .{ .immediate = elem_ty.abiAlignment(zcu).toByteUnits().? }; } diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig index 55f0d7fcc0e37b35198f01c2ff88c96cfd72aca4..0e6387949aa8d337f9c731db050551f710fa31e9 100644 --- a/src/codegen/aarch64/Select.zig +++ b/src/codegen/aarch64/Select.zig @@ -2464,7 +2464,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, const ty_pl = air.data(air.inst_index).ty_pl; const bin_op = isel.air.extraData(Air.Bin, ty_pl.payload).data; - const elem_size = ty_pl.ty.toType().elemType2(zcu).abiSize(zcu); + const elem_size = ty_pl.ty.toType().childType(zcu).abiSize(zcu); const base_vi = try isel.use(bin_op.lhs); var base_part_it = base_vi.field(ty_pl.ty.toType(), 0, 8); @@ -6145,7 +6145,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, } else { const elem_ptr_ra = try isel.allocIntReg(); defer isel.freeReg(elem_ptr_ra); - if (!try elem_vi.value.load(isel, slice_ty.elemType2(zcu), elem_ptr_ra, .{ + if (!try elem_vi.value.load(isel, slice_ty.childType(zcu), elem_ptr_ra, .{ .@"volatile" = ptr_info.flags.is_volatile, })) break :unused; const slice_vi = try isel.use(bin_op.lhs); @@ -6253,7 +6253,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, } else { const elem_ptr_ra = try isel.allocIntReg(); defer isel.freeReg(elem_ptr_ra); - if (!try elem_vi.value.load(isel, ptr_ty.elemType2(zcu), elem_ptr_ra, .{ + if (!try elem_vi.value.load(isel, ptr_ty.childType(zcu), elem_ptr_ra, .{ .@"volatile" = ptr_info.flags.is_volatile, })) break :unused; const base_vi = try isel.use(bin_op.lhs); @@ -6594,7 +6594,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, if (try isel.hasRepeatedByteRepr(.fromInterned(fill_val))) |fill_byte| break :fill_byte .{ .constant = fill_byte }; } - switch (dst_ty.elemType2(zcu).abiSize(zcu)) { + switch (dst_ty.indexablePtrElem(zcu).abiSize(zcu)) { 0 => unreachable, 1 => break :fill_byte .{ .value = bin_op.rhs }, 2, 4, 8 => |size| { diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 106737a8331c523f9ecddad0e0138f31a10ea06f..831a64779bc423595b5433b4d70eaf8a5c0fbf37 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -3676,7 +3676,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { const inst_ty = f.typeOfIndex(inst); const ptr_ty = f.typeOf(bin_op.lhs); - const elem_has_bits = ptr_ty.elemType2(zcu).hasRuntimeBitsIgnoreComptime(zcu); + const elem_has_bits = ptr_ty.indexablePtrElem(zcu).hasRuntimeBitsIgnoreComptime(zcu); const ptr = try f.resolveInst(bin_op.lhs); const index = try f.resolveInst(bin_op.rhs); @@ -3738,7 +3738,7 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { const inst_ty = f.typeOfIndex(inst); const slice_ty = f.typeOf(bin_op.lhs); - const elem_ty = slice_ty.elemType2(zcu); + const elem_ty = slice_ty.childType(zcu); const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(zcu); const slice = try f.resolveInst(bin_op.lhs); @@ -4502,7 +4502,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { const inst_ty = f.typeOfIndex(inst); const inst_scalar_ty = inst_ty.scalarType(zcu); - const elem_ty = inst_scalar_ty.elemType2(zcu); + const elem_ty = inst_scalar_ty.indexablePtrElem(zcu); if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return f.moveCValue(inst, inst_ty, lhs); const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); @@ -7037,7 +7037,7 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index, function_paren: []const u8) !CV try w.writeAll(", "); try writeArrayLen(f, dest_ptr, dest_ty); try w.writeAll(" * sizeof("); - try f.renderType(w, dest_ty.elemType2(zcu)); + try f.renderType(w, dest_ty.indexablePtrElem(zcu)); try w.writeAll("));"); try f.object.newline(); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 4ef72e8ab7fed1786845aa5b8e08d1ddfe6091fa..1327b7b2e1c9985b30f53c4411a8fcf8afa9f89c 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2112,7 +2112,7 @@ pub const Object = struct { return debug_array_type; }, .vector => { - const elem_ty = ty.elemType2(zcu); + const elem_ty = ty.childType(zcu); // Vector elements cannot be padded since that would make // @bitSizOf(elem) * len > @bitSizOf(vec). // Neither gdb nor lldb seem to be able to display non-byte sized diff --git a/src/codegen/mips/abi.zig b/src/codegen/mips/abi.zig index 02c4c637a4c362ea4b3a826fbd27b72598fcc2cb..6678b74ebc32dceed774331667cdf9d498855947 100644 --- a/src/codegen/mips/abi.zig +++ b/src/codegen/mips/abi.zig @@ -44,7 +44,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { return .byval; }, .vector => { - const elem_type = ty.elemType2(zcu); + const elem_type = ty.childType(zcu); switch (elem_type.zigTypeTag(zcu)) { .bool, .int => { const bit_size = ty.bitSize(zcu); diff --git a/src/codegen/riscv64/CodeGen.zig b/src/codegen/riscv64/CodeGen.zig index 1f70f5f4de379ad0e01f75be35f0d13695f5b766..dd4ca3f88bbc6bc082a00ab1e62a1b685e068e06 100644 --- a/src/codegen/riscv64/CodeGen.zig +++ b/src/codegen/riscv64/CodeGen.zig @@ -2673,7 +2673,7 @@ fn genBinOp( defer func.register_manager.unlockReg(tmp_lock); // RISC-V has no immediate mul, so we copy the size to a temporary register - const elem_size = lhs_ty.elemType2(zcu).abiSize(zcu); + const elem_size = lhs_ty.indexablePtrElem(zcu).abiSize(zcu); const elem_size_reg = try func.copyToTmpRegister(Type.u64, .{ .immediate = elem_size }); try func.genBinOp( @@ -3913,9 +3913,8 @@ fn airPtrElemVal(func: *Func, inst: Air.Inst.Index) !void { const base_ptr_ty = func.typeOf(bin_op.lhs); const result: MCValue = if (!is_volatile and func.liveness.isUnused(inst)) .unreach else result: { - const elem_ty = base_ptr_ty.elemType2(zcu); + const elem_ty = base_ptr_ty.indexablePtrElem(zcu); if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none; - const base_ptr_mcv = try func.resolveInst(bin_op.lhs); const base_ptr_lock: ?RegisterLock = switch (base_ptr_mcv) { .register => |reg| func.register_manager.lockRegAssumeUnused(reg), diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig index 2222bb9a050341495a7ca97f6b5a4b9dd5b189ec..e6850df250db68f6b34050f93cb19717ff90ecb2 100644 --- a/src/codegen/spirv/CodeGen.zig +++ b/src/codegen/spirv/CodeGen.zig @@ -4381,7 +4381,7 @@ fn airSliceElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { fn ptrElemPtr(cg: *CodeGen, ptr_ty: Type, ptr_id: Id, index_id: Id) !Id { const zcu = cg.module.zcu; // Construct new pointer type for the resulting pointer - const elem_ty = ptr_ty.elemType2(zcu); // use elemType() so that we get T for *[N]T. + const elem_ty = ptr_ty.indexablePtrElem(zcu); const elem_ty_id = try cg.resolveType(elem_ty, .indirect); const elem_ptr_ty_id = try cg.module.ptrType(elem_ty_id, cg.module.storageClass(ptr_ty.ptrAddressSpace(zcu))); if (ptr_ty.isSinglePointer(zcu)) { diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index 6144a421c8cb132aebd77f745bff78618a3e7a0f..58987558d218402d252b81ff51901b85bcd74f78 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -43261,7 +43261,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); try ops[0].toSlicePtr(cg); var res: [1]Temp = undefined; - if (!hack_around_sema_opv_bugs or ty_pl.ty.toType().elemType2(zcu).hasRuntimeBitsIgnoreComptime(zcu)) cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{ + if (!hack_around_sema_opv_bugs or ty_pl.ty.toType().childType(zcu).hasRuntimeBitsIgnoreComptime(zcu)) cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{ .patterns = &.{ .{ .src = .{ .to_gpr, .simm32, .none } }, }, @@ -43375,7 +43375,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); try ops[0].toSlicePtr(cg); var res: [1]Temp = undefined; - if (!hack_around_sema_opv_bugs or ty_pl.ty.toType().elemType2(zcu).hasRuntimeBitsIgnoreComptime(zcu)) cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{ + if (!hack_around_sema_opv_bugs or ty_pl.ty.toType().childType(zcu).hasRuntimeBitsIgnoreComptime(zcu)) cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{ .patterns = &.{ .{ .src = .{ .to_gpr, .simm32, .none } }, }, @@ -103926,7 +103926,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .array_elem_val, .legalize_vec_elem_val => { const bin_op = air_datas[@intFromEnum(inst)].bin_op; const array_ty = cg.typeOf(bin_op.lhs); - const res_ty = array_ty.elemType2(zcu); + const res_ty = array_ty.childType(zcu); var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); var res: [1]Temp = undefined; cg.select(&res, &.{res_ty}, &ops, comptime &.{ .{ @@ -104121,7 +104121,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { }, .slice_elem_val, .ptr_elem_val => { const bin_op = air_datas[@intFromEnum(inst)].bin_op; - const res_ty = cg.typeOf(bin_op.lhs).elemType2(zcu); + const res_ty = cg.typeOf(bin_op.lhs).indexablePtrElem(zcu); var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); try ops[0].toSlicePtr(cg); var res: [1]Temp = undefined; @@ -187919,7 +187919,6 @@ const Select = struct { unsigned_int: Memory.Size, elem_size_is: u8, po2_elem_size, - elem_int: Memory.Size, const OfIsSizes = struct { of: Memory.Size, is: Memory.Size }; @@ -188178,12 +188177,8 @@ const Select = struct { .signed => false, .unsigned => size.bitSize(cg.target) >= int_info.bits, } else false, - .elem_size_is => |size| size == ty.elemType2(zcu).abiSize(zcu), - .po2_elem_size => std.math.isPowerOfTwo(ty.elemType2(zcu).abiSize(zcu)), - .elem_int => |size| if (cg.intInfo(ty.elemType2(zcu))) |elem_int_info| - size.bitSize(cg.target) >= elem_int_info.bits - else - false, + .elem_size_is => |size| size == ty.indexablePtrElem(zcu).abiSize(zcu), + .po2_elem_size => std.math.isPowerOfTwo(ty.indexablePtrElem(zcu).abiSize(zcu)), }; } }; @@ -189918,20 +189913,20 @@ const Select = struct { .dst0_size => @intCast(Select.Operand.Ref.dst0.typeOf(s).abiSize(s.cg.pt.zcu)), .delta_size => @intCast(@as(SignedImm, @intCast(op.flags.base.ref.typeOf(s).abiSize(s.cg.pt.zcu))) - @as(SignedImm, @intCast(op.flags.index.ref.typeOf(s).abiSize(s.cg.pt.zcu)))), - .delta_elem_size => @intCast(@as(SignedImm, @intCast(op.flags.base.ref.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu))) - - @as(SignedImm, @intCast(op.flags.index.ref.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)))), + .delta_elem_size => @intCast(@as(SignedImm, @intCast(op.flags.base.ref.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu))) - + @as(SignedImm, @intCast(op.flags.index.ref.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)))), .unaligned_size => @intCast(s.cg.unalignedSize(op.flags.base.ref.typeOf(s))), .unaligned_size_add_elem_size => { const ty = op.flags.base.ref.typeOf(s); - break :lhs @intCast(s.cg.unalignedSize(ty) + ty.elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)); + break :lhs @intCast(s.cg.unalignedSize(ty) + ty.scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)); }, .unaligned_size_sub_elem_size => { const ty = op.flags.base.ref.typeOf(s); - break :lhs @intCast(s.cg.unalignedSize(ty) - ty.elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)); + break :lhs @intCast(s.cg.unalignedSize(ty) - ty.scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)); }, .unaligned_size_sub_2_elem_size => { const ty = op.flags.base.ref.typeOf(s); - break :lhs @intCast(s.cg.unalignedSize(ty) - ty.elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu) * 2); + break :lhs @intCast(s.cg.unalignedSize(ty) - ty.scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu) * 2); }, .bit_size => @intCast(s.cg.nonBoolScalarBitSize(op.flags.base.ref.typeOf(s))), .src0_bit_size => @intCast(s.cg.nonBoolScalarBitSize(Select.Operand.Ref.src0.typeOf(s))), @@ -189944,10 +189939,10 @@ const Select = struct { op.flags.base.ref.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu), @divExact(op.flags.base.size.bitSize(s.cg.target), 8), )), - .elem_size => @intCast(op.flags.base.ref.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)), - .src0_elem_size => @intCast(Select.Operand.Ref.src0.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)), - .dst0_elem_size => @intCast(Select.Operand.Ref.dst0.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)), - .src0_elem_size_mul_src1 => @intCast(Select.Operand.Ref.src0.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu) * + .elem_size => @intCast(op.flags.base.ref.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)), + .src0_elem_size => @intCast(Select.Operand.Ref.src0.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)), + .dst0_elem_size => @intCast(Select.Operand.Ref.dst0.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)), + .src0_elem_size_mul_src1 => @intCast(Select.Operand.Ref.src0.typeOf(s).indexableElem(s.cg.pt.zcu).abiSize(s.cg.pt.zcu) * Select.Operand.Ref.src1.valueOf(s).immediate), .vector_index => switch (op.flags.base.ref.typeOf(s).ptrInfo(s.cg.pt.zcu).flags.vector_index) { .none => unreachable, @@ -189956,7 +189951,7 @@ const Select = struct { .src1 => @intCast(Select.Operand.Ref.src1.valueOf(s).immediate), .src1_sub_bit_size => @as(SignedImm, @intCast(Select.Operand.Ref.src1.valueOf(s).immediate)) - @as(SignedImm, @intCast(s.cg.nonBoolScalarBitSize(op.flags.base.ref.typeOf(s)))), - .log2_src0_elem_size => @intCast(std.math.log2(Select.Operand.Ref.src0.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu))), + .log2_src0_elem_size => @intCast(std.math.log2(Select.Operand.Ref.src0.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu))), .elem_mask => @as(u8, std.math.maxInt(u8)) >> @intCast( 8 - ((s.cg.unalignedSize(op.flags.base.ref.typeOf(s)) - 1) % @divExact(op.flags.base.size.bitSize(s.cg.target), 8) + 1 >> diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 19bbee45b3a12d6883f3e7803475eb960c5a1784..fdd516ff17bc3a2349580cde73a179daa2f51523 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -4575,10 +4575,10 @@ fn updateContainerTypeWriterError( const name_strat: Zir.Inst.NameStrategy = switch (decl_inst.tag) { .struct_init, .struct_init_ref, .struct_init_anon => .anon, .extended => switch (decl_inst.data.extended.opcode) { - .struct_decl => @as(Zir.Inst.StructDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy, - .enum_decl => @as(Zir.Inst.EnumDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy, - .union_decl => @as(Zir.Inst.UnionDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy, - .opaque_decl => @as(Zir.Inst.OpaqueDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy, + .struct_decl => file.zir.?.getStructDecl(inst_info.inst).name_strategy, + .union_decl => file.zir.?.getUnionDecl(inst_info.inst).name_strategy, + .enum_decl => file.zir.?.getEnumDecl(inst_info.inst).name_strategy, + .opaque_decl => file.zir.?.getOpaqueDecl(inst_info.inst).name_strategy, .reify_enum, .reify_struct, diff --git a/src/mutable_value.zig b/src/mutable_value.zig index c9eb993944e15366de31846611b76cd070064fe9..97d6f22b3b90e5d9215ec011760ee6feb9c0d3f1 100644 --- a/src/mutable_value.zig +++ b/src/mutable_value.zig @@ -18,7 +18,7 @@ pub const MutableValue = union(enum) { opt_payload: SubValue, /// An aggregate consisting of a single repeated value. repeated: SubValue, - /// An aggregate of `u8` consisting of "plain" bytes (no lazy or undefined elements). + /// An aggregate of `u8` consisting of "plain" bytes (no undefined elements). bytes: Bytes, /// An aggregate with arbitrary sub-values. aggregate: Aggregate, @@ -415,16 +415,7 @@ pub const MutableValue = union(enum) { } else if (!is_struct and is_trivial_int and Type.fromInterned(a.ty).childType(zcu).toIntern() == .u8_type) { // See if we can switch to `bytes` repr for (a.elems) |e| { - switch (e) { - else => break, - .interned => |ip_index| switch (ip.indexToKey(ip_index)) { - else => break, - .int => |int| switch (int.storage) { - .u64, .i64, .big_int => {}, - .lazy_align, .lazy_size => break, - }, - }, - } + if (!e.isTrivialInt(zcu)) break; } else { const bytes = try arena.alloc(u8, a.elems.len); for (a.elems, bytes) |elem_val, *b| { @@ -494,10 +485,7 @@ pub const MutableValue = union(enum) { else => false, .interned => |ip_index| switch (zcu.intern_pool.indexToKey(ip_index)) { else => false, - .int => |int| switch (int.storage) { - .u64, .i64, .big_int => true, - .lazy_align, .lazy_size => false, - }, + .int => true, }, }; } diff --git a/src/print_value.zig b/src/print_value.zig index 28c25954272bccaa8069ff570043e34625236c6c..e58288a16a999c3ee2c17dbd3b31fd8fec4a59d9 100644 --- a/src/print_value.zig +++ b/src/print_value.zig @@ -81,14 +81,6 @@ pub fn print( .int => |int| switch (int.storage) { inline .u64, .i64 => |x| try writer.print("{d}", .{x}), .big_int => |x| try writer.print("{d}", .{x}), - .lazy_align => |ty| if (opt_sema != null) { - const a = try Type.fromInterned(ty).abiAlignmentSema(pt); - try writer.print("{d}", .{a.toByteUnits() orelse 0}); - } else try writer.print("@alignOf({f})", .{Type.fromInterned(ty).fmt(pt)}), - .lazy_size => |ty| if (opt_sema != null) { - const s = try Type.fromInterned(ty).abiSizeSema(pt); - try writer.print("{d}", .{s}); - } else try writer.print("@sizeOf({f})", .{Type.fromInterned(ty).fmt(pt)}), }, .err => |err| try writer.print("error.{f}", .{ err.name.fmt(ip), @@ -104,8 +96,8 @@ pub fn print( }), .enum_tag => |enum_tag| { const enum_type = ip.loadEnumType(val.typeOf(zcu).toIntern()); - if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| { - return writer.print(".{f}", .{enum_type.names.get(ip)[tag_index].fmt(ip)}); + if (enum_type.tagValueIndex(ip, enum_tag.int)) |tag_index| { + return writer.print(".{f}", .{enum_type.field_names.get(ip)[tag_index].fmt(ip)}); } if (level == 0) { return writer.writeAll("@enumFromInt(...)"); -- 2.54.0 From 792830d69cd335a49de97b617d3f668aa544b181 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 25 Jan 2026 11:12:26 +0000 Subject: [PATCH 03/79] std: work around language changes --- lib/std/elf.zig | 4 ++-- lib/std/meta.zig | 2 +- lib/std/multi_array_list.zig | 22 ++++++++++++++-------- lib/std/os/linux.zig | 2 +- lib/std/testing.zig | 5 ++--- lib/std/zon/Serializer.zig | 4 +++- 6 files changed, 23 insertions(+), 16 deletions(-) diff --git a/lib/std/elf.zig b/lib/std/elf.zig index 962e0ceb9e22f655c9542c94928c98691d63a4fb..b9ddf88123e6a6d6c4aa5b5691e92a0dd6370b3e 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -1071,7 +1071,7 @@ pub const Elf32 = struct { pub const Shdr = extern struct { name: Word, type: SHT, - flags: packed struct { shf: SHF }, + flags: packed struct(Word) { shf: SHF }, addr: Elf32.Addr, offset: Elf32.Off, size: Word, @@ -1161,7 +1161,7 @@ pub const Elf64 = struct { pub const Shdr = extern struct { name: Word, type: SHT, - flags: packed struct { shf: SHF, unused: Word = 0 }, + flags: packed struct(Xword) { shf: SHF, unused: Word = 0 }, addr: Elf64.Addr, offset: Elf64.Off, size: Xword, diff --git a/lib/std/meta.zig b/lib/std/meta.zig index f1afa9bc7a049c5e4e13546e307b551e93e863c9..6236f1a56bfc9c841044d35362699d555df19cff 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -315,7 +315,7 @@ test declarationInfo { try testing.expect(comptime mem.eql(u8, info.name, "a")); } } -pub fn fields(comptime T: type) switch (@typeInfo(T)) { +pub inline fn fields(comptime T: type) switch (@typeInfo(T)) { .@"struct" => []const Type.StructField, .@"union" => []const Type.UnionField, .@"enum" => []const Type.EnumField, diff --git a/lib/std/multi_array_list.zig b/lib/std/multi_array_list.zig index 990b85a238ebf056ad7031c92db088ae366c5eb4..92d094f0cc93e96600b03d33f46db1c298c159c1 100644 --- a/lib/std/multi_array_list.zig +++ b/lib/std/multi_array_list.zig @@ -19,7 +19,11 @@ const testing = std.testing; /// For unions you can call `.items(.tags)` or `.items(.data)`. pub fn MultiArrayList(comptime T: type) type { return struct { - bytes: [*]align(@alignOf(T)) u8 = undefined, + /// This pointer is always aligned to the boundary `sizes.big_align`; this is not specified + /// in the type to avoid `MultiArrayList(T)` depending on the alignment of `T` because this + /// can lead to dependency loops. See `allocatedBytes` which `@alignCast`s this pointer to + /// the correct type. + bytes: [*]u8 = undefined, len: usize = 0, capacity: usize = 0, @@ -133,10 +137,8 @@ pub fn MultiArrayList(comptime T: type) type { if (self.ptrs.len == 0 or self.capacity == 0) { return .{}; } - const unaligned_ptr = self.ptrs[sizes.fields[0]]; - const aligned_ptr: [*]align(@alignOf(Elem)) u8 = @alignCast(unaligned_ptr); return .{ - .bytes = aligned_ptr, + .bytes = self.ptrs[sizes.fields[0]], .len = self.len, .capacity = self.capacity, }; @@ -179,6 +181,7 @@ pub fn MultiArrayList(comptime T: type) type { const fields = meta.fields(Elem); /// `sizes.bytes` is an array of @sizeOf each T field. Sorted by alignment, descending. /// `sizes.fields` is an array mapping from `sizes.bytes` array index to field index. + /// `sizes.big_align` is the overall alignment of the allocation, which equals the maximum field alignment. const sizes = blk: { const Data = struct { size: usize, @@ -186,12 +189,14 @@ pub fn MultiArrayList(comptime T: type) type { alignment: usize, }; var data: [fields.len]Data = undefined; + var big_align: usize = 1; for (fields, 0..) |field_info, i| { data[i] = .{ .size = @sizeOf(field_info.type), .size_index = i, .alignment = if (@sizeOf(field_info.type) == 0) 1 else field_info.alignment, }; + big_align = @max(big_align, @alignOf(field_info.type)); } const Sort = struct { fn lessThan(context: void, lhs: Data, rhs: Data) bool { @@ -210,6 +215,7 @@ pub fn MultiArrayList(comptime T: type) type { break :blk .{ .bytes = sizes_bytes, .fields = field_indexes, + .big_align = mem.Alignment.fromByteUnits(big_align), }; }; @@ -452,7 +458,7 @@ pub fn MultiArrayList(comptime T: type) type { assert(new_len <= self.capacity); assert(new_len <= self.len); - const other_bytes = gpa.alignedAlloc(u8, .of(Elem), capacityInBytes(new_len)) catch { + const other_bytes = gpa.alignedAlloc(u8, sizes.big_align, capacityInBytes(new_len)) catch { const self_slice = self.slice(); inline for (fields, 0..) |field_info, i| { if (@sizeOf(field_info.type) != 0) { @@ -533,7 +539,7 @@ pub fn MultiArrayList(comptime T: type) type { /// `new_capacity` must be greater or equal to `len`. pub fn setCapacity(self: *Self, gpa: Allocator, new_capacity: usize) Allocator.Error!void { assert(new_capacity >= self.len); - const new_bytes = try gpa.alignedAlloc(u8, .of(Elem), capacityInBytes(new_capacity)); + const new_bytes = try gpa.alignedAlloc(u8, sizes.big_align, capacityInBytes(new_capacity)); if (self.len == 0) { gpa.free(self.allocatedBytes()); self.bytes = new_bytes.ptr; @@ -650,8 +656,8 @@ pub fn MultiArrayList(comptime T: type) type { return elem_bytes * capacity; } - fn allocatedBytes(self: Self) []align(@alignOf(Elem)) u8 { - return self.bytes[0..capacityInBytes(self.capacity)]; + fn allocatedBytes(self: Self) []align(sizes.big_align.toByteUnits()) u8 { + return @alignCast(self.bytes[0..capacityInBytes(self.capacity)]); } fn FieldType(comptime field: Field) type { diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index cbe085a3af73ded631610881042cf0ed43844767..b884e8ea793d190ad8684824296656cf7ab86171 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -7113,7 +7113,7 @@ pub const io_uring_buf_reg = extern struct { flags: Flags, resv: [3]u64, - pub const Flags = packed struct { + pub const Flags = packed struct(u16) { _0: u1 = 0, /// Incremental buffer consumption. inc: bool, diff --git a/lib/std/testing.zig b/lib/std/testing.zig index 09919f8b69220c51607e875dee868ea6a048d1a5..bfb50039ea2272242ec911d739b00830bbc4360f 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -950,9 +950,8 @@ test "expectEqualDeep primitive type" { } test "expectEqualDeep pointer" { - const a = 1; - const b = 1; - try expectEqualDeep(&a, &b); + try comptime expectEqualDeep(&1, &1); + try expectEqualDeep(&@as(u32, 1), &@as(u32, 1)); } test "expectEqualDeep composite type" { diff --git a/lib/std/zon/Serializer.zig b/lib/std/zon/Serializer.zig index 6f92a64dbdcf6a48867725780692c39b62e9ee21..c30c0e09d8051c0eafab2e8e4ba2a85d46aa1db2 100644 --- a/lib/std/zon/Serializer.zig +++ b/lib/std/zon/Serializer.zig @@ -793,9 +793,11 @@ test checkValueDepth { try expectValueDepthEquals(2, @as(?u32, 1)); try expectValueDepthEquals(1, @as(?u32, null)); try expectValueDepthEquals(1, null); - try expectValueDepthEquals(2, &1); try expectValueDepthEquals(3, &@as(?u32, 1)); + // The pointer drops the implicit comptime-ness, so we need to specify 'comptime' here + try comptime expectValueDepthEquals(2, &1); + const Union = union(enum) { x: u32, y: struct { x: u32 }, -- 2.54.0 From 6e49697ef576e86799c8365492082fdee9d216a9 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Thu, 22 Jan 2026 16:30:15 +0000 Subject: [PATCH 04/79] backend progress The x86_64 backend now compiles and, with `-fstrip`, kinda works! --- src/InternPool.zig | 14 +++++ src/Zcu/PerThread.zig | 1 + src/codegen.zig | 92 +++++++++++----------------- src/codegen/x86_64/CodeGen.zig | 62 ++++++++++--------- src/codegen/x86_64/abi.zig | 12 ++-- src/link/Dwarf.zig | 108 ++++++++++++++++----------------- 6 files changed, 144 insertions(+), 145 deletions(-) diff --git a/src/InternPool.zig b/src/InternPool.zig index ed4666a5b91a940bab9f91146c2095911c0909ef..28846c3f70ce14a85c09e4ce7d703816f3fe543b 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -4150,6 +4150,13 @@ pub const Index = enum(u32) { const extra = ip.getLocalShared(slice.tid).extra.acquire(); return @ptrCast(extra.view().items(.@"0")[slice.start..][0..slice.len]); } + + /// If `slice` is empty (`slice.len == 0`), returns `.none`. + /// Otherwise, asserts that `index < slice.len`, and returns the value at `index`. + pub fn getOrNone(slice: Slice, ip: *const InternPool, index: usize) Index { + if (slice.len == 0) return .none; + return slice.get(ip)[index]; + } }; /// Used for a map of `Index` values to the index within a list of `Index` values. @@ -5981,6 +5988,13 @@ pub const Alignment = enum(u6) { const bytes: []u8 = @ptrCast(extra.view().items(.@"0")[slice.start..]); return @ptrCast(bytes[0..slice.len]); } + + /// If `slice` is empty (`slice.len == 0`), returns `.none`. + /// Otherwise, asserts that `index < slice.len`, and returns the value at `index`. + pub fn getOrNone(slice: Slice, ip: *const InternPool, index: usize) Alignment { + if (slice.len == 0) return .none; + return slice.get(ip)[index]; + } }; pub fn toRelaxedCompareUnits(a: Alignment) u8 { diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index f9faef2f7a36f0d77cbf86db7c7e355db8038056..e3c0c21244b2ae29b643bcc20b350796f27e25f8 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -4097,6 +4097,7 @@ pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) Allocator.Error! } // TODO: this shouldn't need a `PerThread`! Fix the signature of `Type.abiAlignment`. +// MLUGG TODO: that's done, move it! pub fn navAlignment(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) InternPool.Alignment { const zcu = pt.zcu; const ty: Type, const alignment = switch (zcu.intern_pool.getNav(nav_index).status) { diff --git a/src/codegen.zig b/src/codegen.zig index 176649f5b3d90bfca38ab60da0877734440761ee..67575beb3f6f1a5b55a02fe75c0c8b9a576f906f 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -377,7 +377,7 @@ pub fn generateSymbol( .payload => 0, }; - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { try w.writeInt(u16, err_val, endian); return; } @@ -610,7 +610,7 @@ pub fn generateSymbol( .auto, .@"extern" => { const struct_begin = w.end; const field_types = struct_type.field_types.get(ip); - const offsets = struct_type.offsets.get(ip); + const offsets = struct_type.field_offsets.get(ip); var it = struct_type.iterateRuntimeOrder(ip); while (it.next()) |field_index| { @@ -635,13 +635,11 @@ pub fn generateSymbol( try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), w, reloc_parent); } - const size = struct_type.sizeUnordered(ip); - const alignment = struct_type.flagsUnordered(ip).alignment.toByteUnits().?; + assert(struct_type.alignment.check(struct_type.size)); - const padding = math.cast( - usize, - std.mem.alignForward(u64, size, @max(alignment, 1)) - (w.end - struct_begin), - ) orelse return error.Overflow; + const padding = math.cast(usize, struct_type.size - (w.end - struct_begin)) orelse { + return error.Overflow; + }; if (padding > 0) try w.splatByteAll(0, padding); }, } @@ -1060,51 +1058,38 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo switch (ty.zigTypeTag(zcu)) { .void => return .none, + .bool => return .{ .immediate = @intFromBool(val.toBool()) }, .pointer => switch (ty.ptrSize(zcu)) { .slice => {}, - else => switch (val.toIntern()) { - .null_value => { - return .{ .immediate = 0 }; - }, - else => switch (ip.indexToKey(val.toIntern())) { - .int => { - return .{ .immediate = val.toUnsignedInt(zcu) }; - }, - .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) { - .nav => |nav| { - if (!ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { - const imm: u64 = switch (@divExact(target.ptrBitWidth(), 8)) { - 1 => 0xaa, - 2 => 0xaaaa, - 4 => 0xaaaaaaaa, - 8 => 0xaaaaaaaaaaaaaaaa, - else => unreachable, - }; - return .{ .immediate = imm }; - } + .one, .many, .c => { + const elem_ty = ty.childType(zcu); + const ptr = ip.indexToKey(val.toIntern()).ptr; + if (ptr.base_addr == .int) return .{ .immediate = ptr.byte_offset }; + switch (ptr.base_addr) { + .int => unreachable, // handled above - if (ty.castPtrToFn(zcu)) |fn_ty| { - if (zcu.typeToFunc(fn_ty).?.is_generic) { - return .{ .immediate = fn_ty.abiAlignment(zcu).toByteUnits().? }; - } - } else if (ty.zigTypeTag(zcu) == .pointer) { - const elem_ty = ty.childType(zcu); - if (!elem_ty.hasRuntimeBits(zcu)) { - return .{ .immediate = elem_ty.abiAlignment(zcu).toByteUnits().? }; - } - } + .nav => |nav| if (elem_ty.isFnOrHasRuntimeBits(zcu)) { + return .{ .lea_nav = nav }; + } else { + // Create the 0xaa bit pattern... + const undef_ptr_bits: u64 = @intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() + 1)) / 3); + // ...but align the pointer + const alignment = pt.navAlignment(nav); + return .{ .immediate = alignment.forward(undef_ptr_bits) }; + }, - return .{ .lea_nav = nav }; - }, - .uav => |uav| if (Value.fromInterned(uav.val).typeOf(zcu).hasRuntimeBits(zcu)) - return .{ .lea_uav = uav } - else - return .{ .immediate = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu) - .forward(@intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() | 1)) / 3)) }, - else => {}, + .uav => |uav| if (elem_ty.isFnOrHasRuntimeBits(zcu)) { + return .{ .lea_uav = uav }; + } else { + // Create the 0xaa bit pattern... + const undef_ptr_bits: u64 = @intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() + 1)) / 3); + // ...but align the pointer + const alignment = Type.fromInterned(uav.orig_ty).ptrAlignment(zcu); + return .{ .immediate = alignment.forward(undef_ptr_bits) }; }, + else => {}, - }, + } }, }, .int => { @@ -1117,9 +1102,6 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo return .{ .immediate = unsigned }; } }, - .bool => { - return .{ .immediate = @intFromBool(val.toBool()) }; - }, .optional => { if (ty.isPtrLikeOptional(zcu)) { return lowerValue( @@ -1147,7 +1129,7 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo .error_union => { const err_type = ty.errorUnionSet(zcu); const payload_type = ty.errorUnionPayload(zcu); - if (!payload_type.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_type.hasRuntimeBits(zcu)) { // We use the error type directly as the type. const err_int_ty = try pt.errorIntType(); switch (ip.indexToKey(val.toIntern()).error_union.val) { @@ -1187,10 +1169,10 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo } pub fn errUnionPayloadOffset(payload_ty: Type, zcu: *Zcu) u64 { - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return 0; + if (!payload_ty.hasRuntimeBits(zcu)) return 0; const payload_align = payload_ty.abiAlignment(zcu); const error_align = Type.anyerror.abiAlignment(zcu); - if (payload_align.compare(.gte, error_align) or !payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (payload_align.compare(.gte, error_align) or !payload_ty.hasRuntimeBits(zcu)) { return 0; } else { return payload_align.forward(Type.anyerror.abiSize(zcu)); @@ -1198,10 +1180,10 @@ pub fn errUnionPayloadOffset(payload_ty: Type, zcu: *Zcu) u64 { } pub fn errUnionErrorOffset(payload_ty: Type, zcu: *Zcu) u64 { - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return 0; + if (!payload_ty.hasRuntimeBits(zcu)) return 0; const payload_align = payload_ty.abiAlignment(zcu); const error_align = Type.anyerror.abiAlignment(zcu); - if (payload_align.compare(.gte, error_align) and payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (payload_align.compare(.gte, error_align) and payload_ty.hasRuntimeBits(zcu)) { return error_align.forward(payload_ty.abiSize(zcu)); } else { return 0; diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index 58987558d218402d252b81ff51901b85bcd74f78..872404b71572de6124f68ed84dfbca6b5122152f 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -43261,7 +43261,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); try ops[0].toSlicePtr(cg); var res: [1]Temp = undefined; - if (!hack_around_sema_opv_bugs or ty_pl.ty.toType().childType(zcu).hasRuntimeBitsIgnoreComptime(zcu)) cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{ + if (!hack_around_sema_opv_bugs or ty_pl.ty.toType().childType(zcu).hasRuntimeBits(zcu)) cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{ .patterns = &.{ .{ .src = .{ .to_gpr, .simm32, .none } }, }, @@ -43375,7 +43375,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); try ops[0].toSlicePtr(cg); var res: [1]Temp = undefined; - if (!hack_around_sema_opv_bugs or ty_pl.ty.toType().childType(zcu).hasRuntimeBitsIgnoreComptime(zcu)) cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{ + if (!hack_around_sema_opv_bugs or ty_pl.ty.toType().childType(zcu).hasRuntimeBits(zcu)) cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{ .patterns = &.{ .{ .src = .{ .to_gpr, .simm32, .none } }, }, @@ -103699,7 +103699,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .optional_payload => { const ty_op = air_datas[@intFromEnum(inst)].ty_op; var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); - const pl = if (!hack_around_sema_opv_bugs or ty_op.ty.toType().hasRuntimeBitsIgnoreComptime(zcu)) + const pl = if (!hack_around_sema_opv_bugs or ty_op.ty.toType().hasRuntimeBits(zcu)) try ops[0].read(ty_op.ty.toType(), .{}, cg) else try cg.tempInit(ty_op.ty.toType(), .none); @@ -103745,7 +103745,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { const eu_pl_ty = ty_op.ty.toType(); const eu_pl_off: i32 = @intCast(codegen.errUnionPayloadOffset(eu_pl_ty, zcu)); var ops = try cg.tempsFromOperands(inst, .{ty_op.operand}); - const pl = if (!hack_around_sema_opv_bugs or eu_pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) + const pl = if (!hack_around_sema_opv_bugs or eu_pl_ty.hasRuntimeBits(zcu)) try ops[0].read(eu_pl_ty, .{ .disp = eu_pl_off }, cg) else try cg.tempInit(eu_pl_ty, .none); @@ -103864,7 +103864,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .@"packed" => unreachable, }; var ops = try cg.tempsFromOperands(inst, .{struct_field.struct_operand}); - var res = if (!hack_around_sema_opv_bugs or field_ty.hasRuntimeBitsIgnoreComptime(zcu)) + var res = if (!hack_around_sema_opv_bugs or field_ty.hasRuntimeBits(zcu)) try ops[0].read(field_ty, .{ .disp = field_off }, cg) else try cg.tempInit(field_ty, .none); @@ -104125,7 +104125,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); try ops[0].toSlicePtr(cg); var res: [1]Temp = undefined; - if (!hack_around_sema_opv_bugs or res_ty.hasRuntimeBitsIgnoreComptime(zcu)) cg.select(&res, &.{res_ty}, &ops, comptime &.{ .{ + if (!hack_around_sema_opv_bugs or res_ty.hasRuntimeBits(zcu)) cg.select(&res, &.{res_ty}, &ops, comptime &.{ .{ .dst_constraints = .{ .{ .int = .byte }, .any }, .patterns = &.{ .{ .src = .{ .to_gpr, .simm32, .none } }, @@ -171422,10 +171422,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { .auto, .@"extern" => { for (elems, 0..) |elem_ref, field_index| { const elem_dies = bt.feed(); - if (loaded_struct.fieldIsComptime(ip, field_index)) continue; - if (!hack_around_sema_opv_bugs or Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]).hasRuntimeBitsIgnoreComptime(zcu)) { + if (loaded_struct.field_is_comptime_bits.get(ip, field_index)) continue; + if (!hack_around_sema_opv_bugs or Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]).hasRuntimeBits(zcu)) { var elem = try cg.tempFromOperand(elem_ref, elem_dies); - try res.write(&elem, .{ .disp = @intCast(loaded_struct.offsets.get(ip)[field_index]) }, cg); + try res.write(&elem, .{ .disp = @intCast(loaded_struct.field_offsets.get(ip)[field_index]) }, cg); try elem.die(cg); try cg.resetTemps(reset_index); } @@ -171441,7 +171441,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { const elem_dies = bt.feed(); if (tuple_type.values.get(ip)[field_index] != .none) continue; const field_type = Type.fromInterned(tuple_type.types.get(ip)[field_index]); - if (!hack_around_sema_opv_bugs or field_type.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!hack_around_sema_opv_bugs or field_type.hasRuntimeBits(zcu)) { elem_disp = @intCast(field_type.abiAlignment(zcu).forward(elem_disp)); var elem = try cg.tempFromOperand(elem_ref, elem_dies); try res.write(&elem, .{ .disp = elem_disp }, cg); @@ -173756,7 +173756,7 @@ fn genLazy(cg: *CodeGen, lazy_sym: link.File.LazySymbol) InnerError!void { var data_off: i32 = 0; const reset_index = cg.next_temp_index; - const tag_names = ip.loadEnumType(lazy_sym.ty).names; + const tag_names = ip.loadEnumType(lazy_sym.ty).field_names; for (0..tag_names.len) |tag_index| { var enum_temp = try cg.tempInit(enum_ty, if (enum_ty.abiSize(zcu) <= @as(u4, switch (cg.target.cpu.arch) { else => unreachable, @@ -174334,7 +174334,7 @@ fn genUnwrapErrUnionPayloadMir( const payload_ty = err_union_ty.errorUnionPayload(zcu); const result: MCValue = result: { - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none; + if (!payload_ty.hasRuntimeBits(zcu)) break :result .none; const payload_off: u31 = @intCast(codegen.errUnionPayloadOffset(payload_ty, zcu)); switch (err_union) { @@ -174450,7 +174450,7 @@ fn load(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerE const pt = self.pt; const zcu = pt.zcu; const dst_ty = ptr_ty.childType(zcu); - if (!dst_ty.hasRuntimeBitsIgnoreComptime(zcu)) return; + if (!dst_ty.hasRuntimeBits(zcu)) return; switch (ptr_mcv) { .none, .unreach, @@ -174503,7 +174503,7 @@ fn store( const pt = self.pt; const zcu = pt.zcu; const src_ty = ptr_ty.childType(zcu); - if (!src_ty.hasRuntimeBitsIgnoreComptime(zcu)) return; + if (!src_ty.hasRuntimeBits(zcu)) return; switch (ptr_mcv) { .none, .unreach, @@ -176615,7 +176615,7 @@ fn lowerSwitchBr( break :condition_index condition_index; }; try cg.spillEflagsIfOccupied(); - if (min.?.orderAgainstZero(zcu).compare(.neq)) try cg.genBinOpMir( + if (Value.compareHetero(min.?, .neq, .zero_comptime_int, zcu)) try cg.genBinOpMir( .{ ._, .sub }, condition_ty, condition_index, @@ -176957,7 +176957,7 @@ fn airSwitchDispatch(self: *CodeGen, inst: Air.Inst.Index) !void { const unsigned_condition_ty = try self.pt.intType(.unsigned, self.intInfo(condition_ty).?.bits); const condition_mcv = block_tracking.short; try self.spillEflagsIfOccupied(); - if (table.min.orderAgainstZero(self.pt.zcu).compare(.neq)) try self.genBinOpMir( + if (Value.compareHetero(table.min, .neq, .zero_comptime_int, self.pt.zcu)) try self.genBinOpMir( .{ ._, .sub }, condition_ty, condition_mcv, @@ -177054,8 +177054,7 @@ fn airBr(self: *CodeGen, inst: Air.Inst.Index) !void { const br = self.air.instructions.items(.data)[@intFromEnum(inst)].br; const block_ty = self.typeOfIndex(br.block_inst); - const block_unused = - !block_ty.hasRuntimeBitsIgnoreComptime(zcu) or self.liveness.isUnused(br.block_inst); + const block_unused = !block_ty.hasRuntimeBits(zcu) or self.liveness.isUnused(br.block_inst); const block_tracking = self.inst_tracking.getPtr(br.block_inst).?; const block_data = self.blocks.getPtr(br.block_inst).?; const first_br = block_data.relocs.items.len == 0; @@ -180986,7 +180985,7 @@ fn resolveInst(self: *CodeGen, ref: Air.Inst.Ref) InnerError!MCValue { const ty = self.typeOf(ref); // If the type has no codegen bits, no need to store it. - if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) return .none; + if (!ty.hasRuntimeBits(zcu)) return .none; const mcv: MCValue = if (ref.toIndex()) |inst| mcv: { break :mcv self.inst_tracking.getPtr(inst).?.short; @@ -181105,7 +181104,7 @@ fn resolveCallingConventionValues( // Return values if (ret_ty.isNoReturn(zcu)) { result.return_value = .init(.unreach); - } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + } else if (!ret_ty.hasRuntimeBits(zcu)) { // TODO: is this even possible for C calling convention? result.return_value = .init(.none); } else { @@ -181182,7 +181181,7 @@ fn resolveCallingConventionValues( // Input params params: for (param_types, result.args) |ty, *arg| { - assert(ty.hasRuntimeBitsIgnoreComptime(zcu)); + assert(ty.hasRuntimeBits(zcu)); result.air_arg_count += 1; switch (cc) { .x86_64_sysv => {}, @@ -181327,7 +181326,7 @@ fn resolveCallingConventionValues( // Return values result.return_value = if (ret_ty.isNoReturn(zcu)) .init(.unreach) - else if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) + else if (!ret_ty.hasRuntimeBits(zcu)) .init(.none) else return_value: { const ret_gpr = abi.getCAbiIntReturnRegs(cc); @@ -181357,7 +181356,7 @@ fn resolveCallingConventionValues( // Input params for (param_types, result.args) |param_ty, *arg| { - if (!param_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!param_ty.hasRuntimeBits(zcu)) { arg.* = .none; continue; } @@ -181721,7 +181720,7 @@ fn intInfo(cg: *CodeGen, ty: Type) ?std.builtin.Type.Int { .one, .many, .c => .{ .signedness = .unsigned, .bits = cg.target.ptrBitWidth() }, .slice => null, }, - .opt_type => |opt_child| return if (!Type.fromInterned(opt_child).hasRuntimeBitsIgnoreComptime(zcu)) + .opt_type => |opt_child| return if (!Type.fromInterned(opt_child).hasRuntimeBits(zcu)) .{ .signedness = .unsigned, .bits = 1 } else switch (ip.indexToKey(opt_child)) { .ptr_type => |ptr_type| switch (ptr_type.flags.size) { @@ -181734,7 +181733,7 @@ fn intInfo(cg: *CodeGen, ty: Type) ?std.builtin.Type.Int { else => null, }, .error_union_type => |error_union_type| return if (!Type.fromInterned(error_union_type.payload_type) - .hasRuntimeBitsIgnoreComptime(zcu)) .{ .signedness = .unsigned, .bits = zcu.errorSetBits() } else null, + .hasRuntimeBits(zcu)) .{ .signedness = .unsigned, .bits = zcu.errorSetBits() } else null, .simple_type => |simple_type| return switch (simple_type) { .bool => .{ .signedness = .unsigned, .bits = 1 }, .anyerror => .{ .signedness = .unsigned, .bits = zcu.errorSetBits() }, @@ -181767,14 +181766,17 @@ fn intInfo(cg: *CodeGen, ty: Type) ?std.builtin.Type.Int { const loaded_struct = ip.loadStructType(ty_index); switch (loaded_struct.layout) { .auto, .@"extern" => return null, - .@"packed" => ty_index = loaded_struct.backingIntTypeUnordered(ip), + .@"packed" => ty_index = loaded_struct.packed_backing_int_type, } }, - .union_type => return switch (ip.loadUnionType(ty_index).flagsUnordered(ip).layout) { - .auto, .@"extern" => null, - .@"packed" => .{ .signedness = .unsigned, .bits = @intCast(ty.bitSize(zcu)) }, + .union_type => { + const loaded_union = ip.loadUnionType(ty_index); + switch (loaded_union.layout) { + .auto, .@"extern" => return null, + .@"packed" => ty_index = loaded_union.packed_backing_int_type, + } }, - .enum_type => ty_index = ip.loadEnumType(ty_index).tag_ty, + .enum_type => ty_index = ip.loadEnumType(ty_index).int_tag_type, .error_set_type, .inferred_error_set_type => return .{ .signedness = .unsigned, .bits = zcu.errorSetBits() }, else => return null, }; diff --git a/src/codegen/x86_64/abi.zig b/src/codegen/x86_64/abi.zig index 2a296dc9304266d85d8fd8618c88b8c20c4c4f33..e0838d23264a61048e55ad2567a590075044284b 100644 --- a/src/codegen/x86_64/abi.zig +++ b/src/codegen/x86_64/abi.zig @@ -339,7 +339,7 @@ fn classifySystemVStruct( var field_it = loaded_struct.iterateRuntimeOrder(ip); while (field_it.next()) |field_index| { const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); - const field_align = loaded_struct.fieldAlign(ip, field_index); + const field_align = loaded_struct.field_aligns.getOrNone(ip, field_index); byte_offset = std.mem.alignForward( u64, byte_offset, @@ -355,7 +355,7 @@ fn classifySystemVStruct( .@"packed" => {}, } } else if (zcu.typeToUnion(field_ty)) |field_loaded_union| { - switch (field_loaded_union.flagsUnordered(ip).layout) { + switch (field_loaded_union.layout) { .auto => unreachable, .@"extern" => { byte_offset = classifySystemVUnion(result, byte_offset, field_loaded_union, zcu, target); @@ -369,11 +369,11 @@ fn classifySystemVStruct( result_class.* = result_class.combineSystemV(field_class); byte_offset += field_ty.abiSize(zcu); } - const final_byte_offset = starting_byte_offset + loaded_struct.sizeUnordered(ip); + const final_byte_offset = starting_byte_offset + loaded_struct.size; std.debug.assert(final_byte_offset == std.mem.alignForward( u64, byte_offset, - loaded_struct.flagsUnordered(ip).alignment.toByteUnits().?, + loaded_struct.alignment.toByteUnits().?, )); return final_byte_offset; } @@ -398,7 +398,7 @@ fn classifySystemVUnion( .@"packed" => {}, } } else if (zcu.typeToUnion(field_ty)) |field_loaded_union| { - switch (field_loaded_union.flagsUnordered(ip).layout) { + switch (field_loaded_union.layout) { .auto => unreachable, .@"extern" => { _ = classifySystemVUnion(result, starting_byte_offset, field_loaded_union, zcu, target); @@ -411,7 +411,7 @@ fn classifySystemVUnion( for (result[@intCast(starting_byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class| result_class.* = result_class.combineSystemV(field_class); } - return starting_byte_offset + loaded_union.sizeUnordered(ip); + return starting_byte_offset + loaded_union.size; } pub const zigcc = struct { diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index fdd516ff17bc3a2349580cde73a179daa2f51523..f77518d4655514850cdaab6dfc3cde9ee76a7d4a 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -2243,8 +2243,8 @@ pub const WipNav = struct { const zcu = wip_nav.pt.zcu; const ip = &zcu.intern_pool; var big_int_space: Value.BigIntSpace = undefined; - try wip_nav.bigIntConstValue(abbrev_code, .fromInterned(loaded_enum.tag_ty), if (loaded_enum.values.len > 0) - Value.fromInterned(loaded_enum.values.get(ip)[field_index]).toBigInt(&big_int_space, zcu) + try wip_nav.bigIntConstValue(abbrev_code, .fromInterned(loaded_enum.int_tag_type), if (loaded_enum.field_values.len > 0) + Value.fromInterned(loaded_enum.field_values.get(ip)[field_index]).toBigInt(&big_int_space, zcu) else std.math.big.int.Mutable.init(&big_int_space.limbs, field_index).toConst()); } @@ -3164,8 +3164,8 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo try diw.writeUleb128(nav_val.toType().abiSize(zcu)); try diw.writeUleb128(nav_val.toType().abiAlignment(zcu).toByteUnits().?); for (0..loaded_struct.field_types.len) |field_index| { - const is_comptime = loaded_struct.fieldIsComptime(ip, field_index); - const field_init = loaded_struct.fieldInit(ip, field_index); + const is_comptime = loaded_struct.field_is_comptime_bits.get(ip, field_index); + const field_init = loaded_struct.field_defaults.getOrNone(ip, field_index); assert(!(is_comptime and field_init == .none)); const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); const has_runtime_bits, const has_comptime_state = switch (field_init) { @@ -3191,11 +3191,11 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo .struct_field else .struct_field); - try wip_nav.strp(loaded_struct.fieldName(ip, field_index).toSlice(ip)); + try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip)); try wip_nav.refType(field_type); if (!is_comptime) { - try diw.writeUleb128(loaded_struct.offsets.get(ip)[field_index]); - try diw.writeUleb128(loaded_struct.fieldAlign(ip, field_index).toByteUnits() orelse + try diw.writeUleb128(loaded_struct.field_offsets.get(ip)[field_index]); + try diw.writeUleb128(loaded_struct.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse field_type.abiAlignment(zcu).toByteUnits().?); } if (has_comptime_state) @@ -3212,11 +3212,11 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo .generic_decl = .generic_decl_const, .decl_instance = .decl_instance_packed_struct, }, &nav, inst_info.file, &decl); - try wip_nav.refType(.fromInterned(loaded_struct.backingIntTypeUnordered(ip))); + try wip_nav.refType(.fromInterned(loaded_struct.packed_backing_int_type)); var field_bit_offset: u16 = 0; for (0..loaded_struct.field_types.len) |field_index| { try wip_nav.abbrevCode(.packed_struct_field); - try wip_nav.strp(loaded_struct.fieldName(ip, field_index).toSlice(ip)); + try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip)); const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); try wip_nav.refType(field_type); try diw.writeUleb128(field_bit_offset); @@ -3246,7 +3246,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo } wip_nav.entry = nav_gop.value_ptr.*; const diw = &wip_nav.debug_info.writer; - try wip_nav.declCommon(if (loaded_enum.names.len > 0) .{ + try wip_nav.declCommon(if (loaded_enum.field_names.len > 0) .{ .decl = .decl_enum, .generic_decl = .generic_decl_const, .decl_instance = .decl_instance_enum, @@ -3255,16 +3255,16 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo .generic_decl = .generic_decl_const, .decl_instance = .decl_instance_empty_enum, }, &nav, inst_info.file, &decl); - try wip_nav.refType(.fromInterned(loaded_enum.tag_ty)); - for (0..loaded_enum.names.len) |field_index| { + try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type)); + for (0..loaded_enum.field_names.len) |field_index| { try wip_nav.enumConstValue(loaded_enum, .{ .sdata = .signed_enum_field, .udata = .unsigned_enum_field, .block = .big_enum_field, }, field_index); - try wip_nav.strp(loaded_enum.names.get(ip)[field_index].toSlice(ip)); + try wip_nav.strp(loaded_enum.field_names.get(ip)[field_index].toSlice(ip)); } - if (loaded_enum.names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); + if (loaded_enum.field_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); break :tag .done; }, .union_type => tag: { @@ -3293,8 +3293,8 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo const union_layout = Type.getUnionLayout(loaded_union, zcu); try diw.writeUleb128(union_layout.abi_size); try diw.writeUleb128(union_layout.abi_align.toByteUnits().?); - const loaded_tag = loaded_union.loadTagType(ip); - if (loaded_union.hasTag(ip)) { + const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); + if (loaded_union.runtime_tag != .none) { try wip_nav.abbrevCode(.tagged_union); try wip_nav.infoSectionOffset( .debug_info, @@ -3305,7 +3305,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo { try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("tag"); - try wip_nav.refType(.fromInterned(loaded_union.enum_tag_ty)); + try wip_nav.refType(.fromInterned(loaded_union.enum_tag_type)); try diw.writeUleb128(union_layout.tagOffset()); for (0..loaded_union.field_types.len) |field_index| { @@ -3316,11 +3316,11 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo }, field_index); { try wip_nav.abbrevCode(.struct_field); - try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip)); + try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); try wip_nav.refType(field_type); try diw.writeUleb128(union_layout.payloadOffset()); - try diw.writeUleb128(loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse + try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); } try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); @@ -3329,10 +3329,10 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); } else for (0..loaded_union.field_types.len) |field_index| { try wip_nav.abbrevCode(.untagged_union_field); - try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip)); + try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); try wip_nav.refType(field_type); - try diw.writeUleb128(loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse + try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); } try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); @@ -3877,18 +3877,18 @@ fn updateLazyType( }, .enum_type => { const loaded_enum = ip.loadEnumType(type_index); - try wip_nav.abbrevCode(if (loaded_enum.names.len == 0) .generated_empty_enum_type else .generated_enum_type); + try wip_nav.abbrevCode(if (loaded_enum.field_names.len == 0) .generated_empty_enum_type else .generated_enum_type); try wip_nav.strp(name); - try wip_nav.refType(.fromInterned(loaded_enum.tag_ty)); - for (0..loaded_enum.names.len) |field_index| { + try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type)); + for (0..loaded_enum.field_names.len) |field_index| { try wip_nav.enumConstValue(loaded_enum, .{ .sdata = .signed_enum_field, .udata = .unsigned_enum_field, .block = .big_enum_field, }, field_index); - try wip_nav.strp(loaded_enum.names.get(ip)[field_index].toSlice(ip)); + try wip_nav.strp(loaded_enum.field_names.get(ip)[field_index].toSlice(ip)); } - if (loaded_enum.names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); + if (loaded_enum.field_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); }, .func_type => |func_type| { const is_nullary = func_type.param_types.len == 0 and !func_type.is_var_args; @@ -4349,7 +4349,7 @@ fn updateLazyValue( const loaded_struct_type = ip.loadStructType(aggregate.ty); assert(loaded_struct_type.layout == .auto); for (0..loaded_struct_type.field_types.len) |field_index| { - if (loaded_struct_type.fieldIsComptime(ip, field_index)) continue; + if (loaded_struct_type.field_is_comptime_bits.get(ip, field_index)) continue; const field_type: Type = .fromInterned(loaded_struct_type.field_types.get(ip)[field_index]); const has_runtime_bits = field_type.hasRuntimeBits(zcu); const has_comptime_state = field_type.comptimeOnly(zcu) and try field_type.onePossibleValue(pt) == null; @@ -4359,7 +4359,7 @@ fn updateLazyValue( .comptime_value_field_runtime_bits else continue); - try wip_nav.strp(loaded_struct_type.fieldName(ip, field_index).toSlice(ip)); + try wip_nav.strp(loaded_struct_type.field_names.get(ip)[field_index].toSlice(ip)); const field_value: Value = .fromInterned(switch (aggregate.storage) { .bytes => unreachable, .elems => |elems| elems[field_index], @@ -4427,10 +4427,10 @@ fn updateLazyValue( try wip_nav.refType(.fromInterned(un.ty)); field: { const loaded_union_type = ip.loadUnionType(un.ty); - assert(loaded_union_type.flagsUnordered(ip).layout == .auto); + assert(loaded_union_type.layout == .auto); const field_index = zcu.unionTagFieldIndex(loaded_union_type, Value.fromInterned(un.tag)).?; const field_ty: Type = .fromInterned(loaded_union_type.field_types.get(ip)[field_index]); - const field_name = loaded_union_type.loadTagType(ip).names.get(ip)[field_index]; + const field_name = ip.loadEnumType(loaded_union_type.enum_tag_type).field_names.get(ip)[field_index]; const has_runtime_bits = field_ty.hasRuntimeBits(zcu); const has_comptime_state = field_ty.comptimeOnly(zcu) and try field_ty.onePossibleValue(pt) == null; try wip_nav.abbrevCode(if (has_comptime_state) @@ -4521,8 +4521,8 @@ fn updateContainerTypeWriterError( try diw.writeUleb128(ty.abiSize(zcu)); try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); for (0..loaded_struct.field_types.len) |field_index| { - const is_comptime = loaded_struct.fieldIsComptime(ip, field_index); - const field_init = loaded_struct.fieldInit(ip, field_index); + const is_comptime = loaded_struct.field_is_comptime_bits.get(ip, field_index); + const field_init = loaded_struct.field_defaults.getOrNone(ip, field_index); assert(!(is_comptime and field_init == .none)); const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); const has_runtime_bits, const has_comptime_state = switch (field_init) { @@ -4548,11 +4548,11 @@ fn updateContainerTypeWriterError( .struct_field else .struct_field); - try wip_nav.strp(loaded_struct.fieldName(ip, field_index).toSlice(ip)); + try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip)); try wip_nav.refType(field_type); if (!is_comptime) { - try diw.writeUleb128(loaded_struct.offsets.get(ip)[field_index]); - try diw.writeUleb128(loaded_struct.fieldAlign(ip, field_index).toByteUnits() orelse + try diw.writeUleb128(loaded_struct.field_offsets.get(ip)[field_index]); + try diw.writeUleb128(loaded_struct.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse field_type.abiAlignment(zcu).toByteUnits().?); } if (has_comptime_state) @@ -4628,8 +4628,8 @@ fn updateContainerTypeWriterError( try diw.writeUleb128(ty.abiSize(zcu)); try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); for (0..loaded_struct.field_types.len) |field_index| { - const is_comptime = loaded_struct.fieldIsComptime(ip, field_index); - const field_init = loaded_struct.fieldInit(ip, field_index); + const is_comptime = loaded_struct.field_is_comptime_bits.get(ip, field_index); + const field_init = loaded_struct.field_defaults.getOrNone(ip, field_index); assert(!(is_comptime and field_init == .none)); const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); const has_runtime_bits, const has_comptime_state = switch (field_init) { @@ -4655,11 +4655,11 @@ fn updateContainerTypeWriterError( .struct_field else .struct_field); - try wip_nav.strp(loaded_struct.fieldName(ip, field_index).toSlice(ip)); + try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip)); try wip_nav.refType(field_type); if (!is_comptime) { - try diw.writeUleb128(loaded_struct.offsets.get(ip)[field_index]); - try diw.writeUleb128(loaded_struct.fieldAlign(ip, field_index).toByteUnits() orelse + try diw.writeUleb128(loaded_struct.field_offsets.get(ip)[field_index]); + try diw.writeUleb128(loaded_struct.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse field_type.abiAlignment(zcu).toByteUnits().?); } if (has_comptime_state) @@ -4674,11 +4674,11 @@ fn updateContainerTypeWriterError( try wip_nav.abbrevCode(if (loaded_struct.field_types.len > 0) .packed_struct_type else .empty_packed_struct_type); try diw.writeUleb128(file_gop.index); try wip_nav.strp(name); - try wip_nav.refType(.fromInterned(loaded_struct.backingIntTypeUnordered(ip))); + try wip_nav.refType(.fromInterned(loaded_struct.packed_backing_int_type)); var field_bit_offset: u16 = 0; for (0..loaded_struct.field_types.len) |field_index| { try wip_nav.abbrevCode(.packed_struct_field); - try wip_nav.strp(loaded_struct.fieldName(ip, field_index).toSlice(ip)); + try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip)); const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); try wip_nav.refType(field_type); try diw.writeUleb128(field_bit_offset); @@ -4690,19 +4690,19 @@ fn updateContainerTypeWriterError( }, .enum_type => { const loaded_enum = ip.loadEnumType(type_index); - try wip_nav.abbrevCode(if (loaded_enum.names.len > 0) .enum_type else .empty_enum_type); + try wip_nav.abbrevCode(if (loaded_enum.field_names.len > 0) .enum_type else .empty_enum_type); try diw.writeUleb128(file_gop.index); try wip_nav.strp(name); - try wip_nav.refType(.fromInterned(loaded_enum.tag_ty)); - for (0..loaded_enum.names.len) |field_index| { + try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type)); + for (0..loaded_enum.field_names.len) |field_index| { try wip_nav.enumConstValue(loaded_enum, .{ .sdata = .signed_enum_field, .udata = .unsigned_enum_field, .block = .big_enum_field, }, field_index); - try wip_nav.strp(loaded_enum.names.get(ip)[field_index].toSlice(ip)); + try wip_nav.strp(loaded_enum.field_names.get(ip)[field_index].toSlice(ip)); } - if (loaded_enum.names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); + if (loaded_enum.field_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); }, .union_type => { const loaded_union = ip.loadUnionType(type_index); @@ -4712,8 +4712,8 @@ fn updateContainerTypeWriterError( const union_layout = Type.getUnionLayout(loaded_union, zcu); try diw.writeUleb128(union_layout.abi_size); try diw.writeUleb128(union_layout.abi_align.toByteUnits().?); - const loaded_tag = loaded_union.loadTagType(ip); - if (loaded_union.hasTag(ip)) { + const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); + if (loaded_union.runtime_tag != .none) { try wip_nav.abbrevCode(.tagged_union); try wip_nav.infoSectionOffset( .debug_info, @@ -4724,7 +4724,7 @@ fn updateContainerTypeWriterError( { try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("tag"); - try wip_nav.refType(.fromInterned(loaded_union.enum_tag_ty)); + try wip_nav.refType(.fromInterned(loaded_union.enum_tag_type)); try diw.writeUleb128(union_layout.tagOffset()); for (0..loaded_union.field_types.len) |field_index| { @@ -4735,11 +4735,11 @@ fn updateContainerTypeWriterError( }, field_index); { try wip_nav.abbrevCode(.struct_field); - try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip)); + try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); try wip_nav.refType(field_type); try diw.writeUleb128(union_layout.payloadOffset()); - try diw.writeUleb128(loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse + try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); } try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); @@ -4748,10 +4748,10 @@ fn updateContainerTypeWriterError( try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); } else for (0..loaded_union.field_types.len) |field_index| { try wip_nav.abbrevCode(.untagged_union_field); - try wip_nav.strp(loaded_tag.names.get(ip)[field_index].toSlice(ip)); + try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); try wip_nav.refType(field_type); - try diw.writeUleb128(loaded_union.fieldAlign(ip, field_index).toByteUnits() orelse + try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); } if (loaded_union.field_types.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); -- 2.54.0 From 3086c7977bee8cfe41c385d3ba389971b9a28380 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Fri, 23 Jan 2026 09:59:32 +0000 Subject: [PATCH 05/79] type resolution progress --- lib/std/zig.zig | 9 + lib/std/zig/AstGen.zig | 123 +- lib/std/zig/Zir.zig | 78 +- src/Compilation.zig | 12 +- src/IncrementalDebugServer.zig | 6 +- src/InternPool.zig | 1298 +++++++++++------ src/Sema.zig | 2343 ++++++++++--------------------- src/Sema/LowerZon.zig | 2 +- src/Sema/type_resolution.zig | 1185 ++++++++++------ src/Type.zig | 377 +++-- src/Value.zig | 61 +- src/Zcu.zig | 234 ++- src/Zcu/PerThread.zig | 155 +- src/codegen.zig | 11 +- src/codegen/aarch64/Select.zig | 14 +- src/codegen/c.zig | 17 +- src/codegen/llvm.zig | 15 +- src/codegen/riscv64/CodeGen.zig | 4 +- src/codegen/spirv/CodeGen.zig | 13 +- src/codegen/wasm/CodeGen.zig | 3 +- src/codegen/x86_64/CodeGen.zig | 14 +- src/link/Coff.zig | 2 +- src/link/Elf/ZigObject.zig | 2 +- src/link/Elf2.zig | 2 +- src/link/MachO/ZigObject.zig | 8 +- src/print_value.zig | 38 +- src/print_zir.zig | 26 +- 27 files changed, 3064 insertions(+), 2988 deletions(-) diff --git a/lib/std/zig.zig b/lib/std/zig.zig index ba799c650e74229e4f3812fe67742bc0550b8925..26abf81a11a6b3707b84bd86f2b1a33a4b6b92b9 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -837,6 +837,10 @@ pub const SimpleComptimeReason = enum(u32) { tuple_field_types, enum_field_names, enum_field_values, + union_enum_tag_type, + enum_int_tag_type, + packed_struct_backing_int_type, + packed_union_backing_int_type, // Evaluating at comptime because decl/field name must be comptime-known. decl_name, @@ -925,6 +929,11 @@ pub const SimpleComptimeReason = enum(u32) { .enum_field_names => "enum field names must be comptime-known", .enum_field_values => "enum field values must be comptime-known", + .union_enum_tag_type => "enum tag type of union must be comptime-known", + .enum_int_tag_type => "integer tag type of enum must be comptime-known", + .packed_struct_backing_int_type => "packed struct backing integer type must be comptime-known", + .packed_union_backing_int_type => "packed struct backing integer type must be comptime-known", + .decl_name => "declaration name must be comptime-known", .field_name => "field name must be comptime-known", .tuple_field_index => "tuple field index must be comptime-known", diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index 6a6585192ddb7efd7dc1b6455ce28cdf27425530..046330c46bedffaa8d16036ccb041264373c34b7 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -4922,24 +4922,14 @@ fn structDeclInner( astgen.advanceSourceCursorToNode(node); - const backing_int_type_ref: Zir.Inst.Ref = ty: { - const backing_int_node = maybe_backing_int_node.unwrap() orelse break :ty .none; - if (layout != .@"packed") return astgen.failNode( - backing_int_node, - "non-packed struct does not support backing integer type", - .{}, - ); - break :ty try typeExpr(gz, scope, backing_int_node); - }; - const decl_inst = try gz.reserveInstructionIndex(); - if (container_decl.ast.members.len == 0 and backing_int_type_ref == .none) { + if (container_decl.ast.members.len == 0 and maybe_backing_int_node == .none) { try gz.setStruct(decl_inst, .{ .src_node = node, .name_strat = name_strat, .layout = layout, - .backing_int_type = .none, + .backing_int_type_body_len = null, .decls_len = 0, .fields_len = 0, .any_field_aligns = false, @@ -4993,6 +4983,22 @@ fn structDeclInner( ); if (field_comptime_bits) |bits| @memset(bits.get(astgen), 0); + // Before any field bodies comes the backing int type, if specified. + const backing_int_type_body_len: ?u32 = if (maybe_backing_int_node.unwrap()) |backing_int_node| len: { + if (layout != .@"packed") return astgen.failNode( + backing_int_node, + "non-packed struct does not support backing integer type", + .{}, + ); + const type_ref = try typeExpr(&block_scope, &namespace.base, backing_int_node); + if (!block_scope.endsWithNoReturn()) { + _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref); + } + const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); + block_scope.instructions.items.len = block_scope.instructions_top; + break :len body_len; + } else null; + const old_hasher = astgen.src_hasher; defer astgen.src_hasher = old_hasher; astgen.src_hasher = .init(.{}); @@ -5076,7 +5082,7 @@ fn structDeclInner( .src_node = node, .name_strat = name_strat, .layout = layout, - .backing_int_type = backing_int_type_ref, + .backing_int_type_body_len = backing_int_type_body_len, .decls_len = scan_result.decls_len, .fields_len = scan_result.fields_len, .any_field_aligns = scan_result.any_field_aligns, @@ -5220,11 +5226,6 @@ fn unionDeclInner( astgen.advanceSourceCursorToNode(node); - const arg_type_ref: Zir.Inst.Ref = ref: { - const arg_node = opt_arg_node.unwrap() orelse break :ref .none; - break :ref try typeExpr(gz, scope, arg_node); - }; - const decl_inst = try gz.reserveInstructionIndex(); var namespace: Scope.Namespace = .{ @@ -5262,6 +5263,17 @@ fn unionDeclInner( const field_align_body_lens = try scratch.addOptionalSlice(scan_result.any_field_aligns, scan_result.fields_len); const field_value_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, scan_result.fields_len); + // Before any field bodies comes the tag/backing type, if specified. + const arg_type_body_len: ?u32 = if (opt_arg_node.unwrap()) |arg_node| len: { + const type_ref = try typeExpr(&block_scope, &namespace.base, arg_node); + if (!block_scope.endsWithNoReturn()) { + _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref); + } + const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); + block_scope.instructions.items.len = block_scope.instructions_top; + break :len body_len; + } else null; + const old_hasher = astgen.src_hasher; defer astgen.src_hasher = old_hasher; astgen.src_hasher = .init(.{}); @@ -5358,7 +5370,7 @@ fn unionDeclInner( .@"extern" => .@"extern", .@"packed" => if (opt_arg_node != .none) .packed_explicit else .@"packed", }, - .arg_type = arg_type_ref, + .arg_type_body_len = arg_type_body_len, .decls_len = scan_result.decls_len, .fields_len = scan_result.fields_len, .any_field_aligns = scan_result.any_field_aligns, @@ -5420,11 +5432,6 @@ fn containerDecl( astgen.advanceSourceCursorToNode(node); - const tag_type_ref: Zir.Inst.Ref = ref: { - const arg_node = container_decl.ast.arg.unwrap() orelse break :ref .none; - break :ref try typeExpr(gz, scope, arg_node); - }; - const decl_inst = try gz.reserveInstructionIndex(); var namespace: Scope.Namespace = .{ @@ -5461,6 +5468,17 @@ fn containerDecl( const field_names = try scratch.addSlice(fields_len); const field_value_body_lens = try scratch.addOptionalSlice(scan_result.any_field_values, fields_len); + // Before any field bodies comes the tag type, if specified. + const tag_type_body_len: ?u32 = if (container_decl.ast.arg.unwrap()) |tag_type_node| len: { + const type_ref = try typeExpr(&block_scope, &namespace.base, tag_type_node); + if (!block_scope.endsWithNoReturn()) { + _ = try block_scope.addBreak(.break_inline, decl_inst, type_ref); + } + const body_len = try scratch.appendBodyWithFixups(block_scope.instructionsSlice()); + block_scope.instructions.items.len = block_scope.instructions_top; + break :len body_len; + } else null; + const old_hasher = astgen.src_hasher; defer astgen.src_hasher = old_hasher; astgen.src_hasher = .init(.{}); @@ -5508,7 +5526,7 @@ fn containerDecl( field_names.get(astgen)[field_idx] = @intFromEnum(try astgen.identAsString(member.ast.main_token)); if (member.ast.value_expr.unwrap()) |value_node| { - if (tag_type_ref == .none) { + if (tag_type_body_len == null) { return astgen.failNodeNotes(node, "explicitly valued enum missing integer tag type", .{}, &.{ try astgen.errNoteNode(value_node, "tag value specified here", .{}), }); @@ -5535,7 +5553,7 @@ fn containerDecl( try gz.setEnum(decl_inst, .{ .src_node = node, .name_strat = name_strat, - .tag_type = tag_type_ref, + .tag_type_body_len = tag_type_body_len, .nonexhaustive = scan_result.has_underscore_field, .decls_len = scan_result.decls_len, .fields_len = fields_len, @@ -12406,7 +12424,7 @@ const GenZir = struct { src_node: Ast.Node.Index, name_strat: Zir.Inst.NameStrategy, layout: std.builtin.Type.ContainerLayout, - backing_int_type: Zir.Inst.Ref, + backing_int_type_body_len: ?u32, decls_len: u32, fields_len: u32, any_field_aligns: bool, @@ -12430,7 +12448,7 @@ const GenZir = struct { const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len + - 4 + // `captures_len`, `decls_len`, `fields_len`, `backing_int_type` + 4 + // `captures_len`, `decls_len`, `fields_len`, `backing_int_type_body_len` captures_len * 2 + // `capture`, `capture_name` args.remaining.len); @@ -12446,7 +12464,7 @@ const GenZir = struct { if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len); if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len); if (args.fields_len != 0) astgen.extra.appendAssumeCapacity(args.fields_len); - if (args.backing_int_type != .none) astgen.extra.appendAssumeCapacity(@intFromEnum(args.backing_int_type)); + if (args.backing_int_type_body_len) |n| astgen.extra.appendAssumeCapacity(n); astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures)); astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names)); astgen.extra.appendSliceAssumeCapacity(args.remaining); @@ -12461,7 +12479,7 @@ const GenZir = struct { .has_fields_len = args.fields_len != 0, .name_strategy = args.name_strat, .layout = args.layout, - .has_backing_int_type = args.backing_int_type != .none, + .has_backing_int_type = args.backing_int_type_body_len != null, .any_field_aligns = args.any_field_aligns, .any_field_defaults = args.any_field_defaults, .any_comptime_fields = args.any_comptime_fields, @@ -12475,7 +12493,7 @@ const GenZir = struct { src_node: Ast.Node.Index, name_strat: Zir.Inst.NameStrategy, kind: Zir.Inst.UnionDecl.Kind, - arg_type: Zir.Inst.Ref, + arg_type_body_len: ?u32, decls_len: u32, fields_len: u32, any_field_aligns: bool, @@ -12497,7 +12515,7 @@ const GenZir = struct { const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.UnionDecl).@"struct".fields.len + - 4 + // `captures_len`, `decls_len`, `fields_len`, `backing_int_type` + 4 + // `captures_len`, `decls_len`, `fields_len`, `arg_type_body_len` captures_len * 2 + // `capture`, `capture_name` args.remaining.len); @@ -12514,10 +12532,9 @@ const GenZir = struct { if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len); if (args.fields_len != 0) astgen.extra.appendAssumeCapacity(args.fields_len); if (args.kind.hasArgType()) { - assert(args.arg_type != .none); - astgen.extra.appendAssumeCapacity(@intFromEnum(args.arg_type)); + astgen.extra.appendAssumeCapacity(args.arg_type_body_len.?); } else { - assert(args.arg_type == .none); + assert(args.arg_type_body_len == null); } astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures)); astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names)); @@ -12525,28 +12542,26 @@ const GenZir = struct { astgen.instructions.set(@intFromEnum(inst), .{ .tag = .extended, - .data = .{ - .extended = .{ - .opcode = .union_decl, - .small = @bitCast(Zir.Inst.UnionDecl.Small{ - .has_captures_len = captures_len != 0, - .has_decls_len = args.decls_len != 0, - .has_fields_len = args.fields_len != 0, - .name_strategy = args.name_strat, - .kind = args.kind, - .any_field_aligns = args.any_field_aligns, - .any_field_values = args.any_field_values, - }), - .operand = payload_index, - }, - }, + .data = .{ .extended = .{ + .opcode = .union_decl, + .small = @bitCast(Zir.Inst.UnionDecl.Small{ + .has_captures_len = captures_len != 0, + .has_decls_len = args.decls_len != 0, + .has_fields_len = args.fields_len != 0, + .name_strategy = args.name_strat, + .kind = args.kind, + .any_field_aligns = args.any_field_aligns, + .any_field_values = args.any_field_values, + }), + .operand = payload_index, + } }, }); } fn setEnum(gz: *GenZir, inst: Zir.Inst.Index, args: struct { src_node: Ast.Node.Index, name_strat: Zir.Inst.NameStrategy, - tag_type: Zir.Inst.Ref, + tag_type_body_len: ?u32, nonexhaustive: bool, decls_len: u32, fields_len: u32, @@ -12568,7 +12583,7 @@ const GenZir = struct { const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).@"struct".fields.len + - 4 + // `captures_len`, `decls_len`, `fields_len`, `tag_type` + 4 + // `captures_len`, `decls_len`, `fields_len`, `tag_type_body_len` captures_len * 2 + // `capture`, `capture_name` args.remaining.len); @@ -12584,7 +12599,7 @@ const GenZir = struct { if (captures_len != 0) astgen.extra.appendAssumeCapacity(captures_len); if (args.decls_len != 0) astgen.extra.appendAssumeCapacity(args.decls_len); if (args.fields_len != 0) astgen.extra.appendAssumeCapacity(args.fields_len); - if (args.tag_type != .none) astgen.extra.appendAssumeCapacity(@intFromEnum(args.tag_type)); + if (args.tag_type_body_len) |n| astgen.extra.appendAssumeCapacity(n); astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.captures)); astgen.extra.appendSliceAssumeCapacity(@ptrCast(args.capture_names)); astgen.extra.appendSliceAssumeCapacity(args.remaining); @@ -12598,7 +12613,7 @@ const GenZir = struct { .has_decls_len = args.decls_len != 0, .has_fields_len = args.fields_len != 0, .name_strategy = args.name_strat, - .has_tag_type = args.tag_type != .none, + .has_tag_type = args.tag_type_body_len != null, .nonexhaustive = args.nonexhaustive, .any_field_values = args.any_field_values, }), diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index c0270a9e03e7fe5eca1e0af9d8fdf36e64fc34e3..94c76b429cb49845757ac0f4c0c40bc27d9f0c27 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -3465,7 +3465,7 @@ pub const Inst = struct { /// 0. captures_len: u32 // if `has_captures_len` /// 1. decls_len: u32, // if `has_decls_len` /// 2. fields_len: u32, // if `has_fields_len` - /// 3. backing_int_type: Ref // if `has_backing_int` + /// 3. backing_int_body_len: u32 // if `has_backing_int` /// 4. capture: Capture // for every `captures_len` /// 5. capture_name: NullTerminatedString // for every `captures_len` /// 6. decl: Index, // for every `decls_len`; points to a `declaration` instruction @@ -3475,7 +3475,8 @@ pub const Inst = struct { /// 10. field_default_body_len: u32 // for every `fields_len` if `any_field_defaults` /// 11. field_comptime_bits: u32 // one bit per `fields_len` if `any_comptime_fields` /// // LSB is first field, minimum number of `u32` needed - /// 12. body_inst: Inst.Index // type body, then align body, then default body, for each field + /// 12. backing_int_body_inst: Inst.Index // for each `backing_int_body_len` + /// 13. body_inst: Inst.Index // type body, then align body, then default body, for each field pub const StructDecl = struct { // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`. // This hash contains the source of all fields, and any specified attributes (`extern`, backing type, etc). @@ -3622,13 +3623,14 @@ pub const Inst = struct { /// 0. captures_len: u32, // if has_captures_len /// 1. decls_len: u32, // if has_decls_len /// 2. fields_len: u32, // if has_fields_len - /// 3. tag_type: Ref, // if has_tag_type + /// 3. tag_type_body_len: u32, // if has_tag_type /// 4. capture: Capture // for every `captures_len` /// 5. capture_name: NullTerminatedString // for every `captures_len` /// 6. decl: Index, // for every `decls_len`; points to a `declaration` instruction /// 7. field_name: NullTerminatedString // for every `fields_len` /// 8. field_value_body_len: u32 // for every `fields_len` if `any_field_values` - /// 9. body_inst: Inst.Index // value body for each field + /// 9. tag_type_body_inst: Inst.Index // for each `tag_type_body_len` + /// 10. body_inst: Inst.Index // value body for each field pub const EnumDecl = struct { // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`. // This hash contains the source of all fields, and the backing type if specified. @@ -3656,7 +3658,7 @@ pub const Inst = struct { /// 0. captures_len: u32 // if `has_captures_len` /// 1. decls_len: u32, // if `has_decls_len` /// 2. fields_len: u32, // if `has_fields_len` - /// 3. arg_type: Ref, // if `kind.hasArgType()` + /// 3. arg_type_body_len: u32, // if `kind.hasArgType()` /// 4. capture: Capture // for every `captures_len` /// 5. capture_name: NullTerminatedString // for every `captures_len` /// 6. decl: Index, // for every `decls_len`; points to a `declaration` instruction @@ -3664,7 +3666,8 @@ pub const Inst = struct { /// 8. field_type_body_len: u32 // for every `fields_len` /// 9 . field_align_body_len: u32 // for every `fields_len` if `any_field_aligns` /// 10. field_value_body_len: u32 // for every `fields_len` if `any_field_values` - /// 11. body_inst: Inst.Index // type body, then align body, then value body, for each field + /// 11. arg_type_body_inst: Inst.Index // for each `arg_type_body_len` + /// 12. body_inst: Inst.Index // type body, then align body, then value body, for each field pub const UnionDecl = struct { // These fields should be concatenated and reinterpreted as a `std.zig.SrcHash`. // This hash contains the source of all fields, and any specified attributes (`extern` etc). @@ -5235,18 +5238,6 @@ pub fn assertTrackable(zir: Zir, inst_idx: Zir.Inst.Index) void { } } -/// MLUGG TODO: maybe delete these two? -pub fn typeCapturesLen(zir: Zir, type_decl: Inst.Index) u32 { - const inst = zir.instructions.get(@intFromEnum(type_decl)); - assert(inst.tag == .extended); - return switch (inst.data.extended.opcode) { - .struct_decl => @intCast(zir.getStructDecl(type_decl).captures.len), - .union_decl => @intCast(zir.getUnionDecl(type_decl).captures.len), - .enum_decl => @intCast(zir.getEnumDecl(type_decl).captures.len), - .opaque_decl => @intCast(zir.getOpaqueDecl(type_decl).captures.len), - else => unreachable, - }; -} pub fn typeDecls(zir: Zir, type_decl: Inst.Index) []const Zir.Inst.Index { const inst = zir.instructions.get(@intFromEnum(type_decl)); assert(inst.tag == .extended); @@ -5281,11 +5272,11 @@ pub fn getStructDecl(zir: *const Zir, struct_decl: Inst.Index) UnwrappedStructDe extra_index += 1; break :blk fields_len; } else 0; - const backing_int_type: Inst.Ref = if (small.has_backing_int_type) ty: { - const ty = zir.extra[extra_index]; + const backing_int_type_body_len: u32 = if (small.has_backing_int_type) len: { + const body_len = zir.extra[extra_index]; extra_index += 1; - break :ty @enumFromInt(ty); - } else .none; + break :len body_len; + } else 0; const captures: []const Inst.Capture = @ptrCast(zir.extra[extra_index..][0..captures_len]); extra_index += captures_len; const capture_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..captures_len]); @@ -5312,6 +5303,11 @@ pub fn getStructDecl(zir: *const Zir, struct_decl: Inst.Index) UnwrappedStructDe extra_index += bits_len; break :bits bits; } else null; + const backing_int_type_body: ?[]const Zir.Inst.Index = switch (backing_int_type_body_len) { + 0 => null, + else => |n| zir.bodySlice(extra_index, n), + }; + extra_index += backing_int_type_body_len; const field_bodies_overlong: []const Inst.Index = @ptrCast(zir.extra[extra_index..]); return .{ .src_line = extra.data.src_line, @@ -5321,7 +5317,7 @@ pub fn getStructDecl(zir: *const Zir, struct_decl: Inst.Index) UnwrappedStructDe .capture_names = capture_names, .decls = decls, .layout = small.layout, - .backing_int_type = backing_int_type, + .backing_int_type_body = backing_int_type_body, .field_names = field_names, .field_type_body_lens = field_type_body_lens, .field_align_body_lens = field_align_body_lens, @@ -5341,7 +5337,7 @@ pub const UnwrappedStructDecl = struct { decls: []const Inst.Index, layout: std.builtin.Type.ContainerLayout, - backing_int_type: Inst.Ref, + backing_int_type_body: ?[]const Inst.Index, field_names: []const NullTerminatedString, field_type_body_lens: []const u32, @@ -5427,11 +5423,11 @@ pub fn getUnionDecl(zir: *const Zir, union_decl: Inst.Index) UnwrappedUnionDecl extra_index += 1; break :blk fields_len; } else 0; - const arg_type: Inst.Ref = if (small.kind.hasArgType()) ty: { - const ty = zir.extra[extra_index]; + const arg_type_body_len: u32 = if (small.kind.hasArgType()) len: { + const body_len = zir.extra[extra_index]; extra_index += 1; - break :ty @enumFromInt(ty); - } else .none; + break :len body_len; + } else 0; const captures: []const Inst.Capture = @ptrCast(zir.extra[extra_index..][0..captures_len]); extra_index += captures_len; const capture_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..captures_len]); @@ -5452,6 +5448,11 @@ pub fn getUnionDecl(zir: *const Zir, union_decl: Inst.Index) UnwrappedUnionDecl extra_index += fields_len; break :lens @ptrCast(lens); } else null; + const arg_type_body: ?[]const Zir.Inst.Index = switch (arg_type_body_len) { + 0 => null, + else => |n| zir.bodySlice(extra_index, n), + }; + extra_index += arg_type_body_len; const field_bodies_overlong: []const Inst.Index = @ptrCast(zir.extra[extra_index..]); return .{ .src_line = extra.data.src_line, @@ -5461,7 +5462,7 @@ pub fn getUnionDecl(zir: *const Zir, union_decl: Inst.Index) UnwrappedUnionDecl .capture_names = capture_names, .decls = decls, .kind = small.kind, - .arg_type = arg_type, + .arg_type_body = arg_type_body, .field_names = field_names, .field_type_body_lens = field_type_body_lens, .field_align_body_lens = field_align_body_lens, @@ -5480,7 +5481,7 @@ pub const UnwrappedUnionDecl = struct { decls: []const Inst.Index, kind: Inst.UnionDecl.Kind, - arg_type: Inst.Ref, + arg_type_body: ?[]const Inst.Index, field_names: []const NullTerminatedString, field_type_body_lens: []const u32, @@ -5556,11 +5557,11 @@ pub fn getEnumDecl(zir: *const Zir, enum_decl: Inst.Index) UnwrappedEnumDecl { extra_index += 1; break :blk fields_len; } else 0; - const tag_type: Inst.Ref = if (small.has_tag_type) ty: { - const ty = zir.extra[extra_index]; + const tag_type_body_len: u32 = if (small.has_tag_type) len: { + const body_len = zir.extra[extra_index]; extra_index += 1; - break :ty @enumFromInt(ty); - } else .none; + break :len body_len; + } else 0; const captures: []const Inst.Capture = @ptrCast(zir.extra[extra_index..][0..captures_len]); extra_index += captures_len; const capture_names: []const NullTerminatedString = @ptrCast(zir.extra[extra_index..][0..captures_len]); @@ -5574,6 +5575,11 @@ pub fn getEnumDecl(zir: *const Zir, enum_decl: Inst.Index) UnwrappedEnumDecl { extra_index += fields_len; break :lens @ptrCast(lens); } else null; + const tag_type_body: ?[]const Zir.Inst.Index = switch (tag_type_body_len) { + 0 => null, + else => |n| zir.bodySlice(extra_index, n), + }; + extra_index += tag_type_body_len; const field_bodies_overlong: []const Inst.Index = @ptrCast(zir.extra[extra_index..]); return .{ .src_line = extra.data.src_line, @@ -5582,7 +5588,7 @@ pub fn getEnumDecl(zir: *const Zir, enum_decl: Inst.Index) UnwrappedEnumDecl { .captures = captures, .capture_names = capture_names, .decls = decls, - .tag_type = tag_type, + .tag_type_body = tag_type_body, .nonexhaustive = small.nonexhaustive, .field_names = field_names, .field_value_body_lens = field_value_body_lens, @@ -5599,7 +5605,7 @@ pub const UnwrappedEnumDecl = struct { decls: []const Inst.Index, - tag_type: Inst.Ref, + tag_type_body: ?[]const Inst.Index, nonexhaustive: bool, field_names: []const NullTerminatedString, diff --git a/src/Compilation.zig b/src/Compilation.zig index 14046f38fc2e41c9aa50efa7586f6815ba67aeb6..64afabc76394a03c4b421345213ce9a189be34de 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -3713,7 +3713,7 @@ const Header = extern struct { nav_val_deps_len: u32, nav_ty_deps_len: u32, type_layout_deps_len: u32, - type_inits_deps_len: u32, + struct_defaults_deps_len: u32, func_ies_deps_len: u32, zon_file_deps_len: u32, embed_file_deps_len: u32, @@ -3763,7 +3763,7 @@ pub fn saveState(comp: *Compilation) !void { .nav_val_deps_len = @intCast(ip.nav_val_deps.count()), .nav_ty_deps_len = @intCast(ip.nav_ty_deps.count()), .type_layout_deps_len = @intCast(ip.type_layout_deps.count()), - .type_inits_deps_len = @intCast(ip.type_inits_deps.count()), + .struct_defaults_deps_len = @intCast(ip.struct_defaults_deps.count()), .func_ies_deps_len = @intCast(ip.func_ies_deps.count()), .zon_file_deps_len = @intCast(ip.zon_file_deps.count()), .embed_file_deps_len = @intCast(ip.embed_file_deps.count()), @@ -3800,8 +3800,8 @@ pub fn saveState(comp: *Compilation) !void { addBuf(&bufs, @ptrCast(ip.nav_ty_deps.values())); addBuf(&bufs, @ptrCast(ip.type_layout_deps.keys())); addBuf(&bufs, @ptrCast(ip.type_layout_deps.values())); - addBuf(&bufs, @ptrCast(ip.type_inits_deps.keys())); - addBuf(&bufs, @ptrCast(ip.type_inits_deps.values())); + addBuf(&bufs, @ptrCast(ip.struct_defaults_deps.keys())); + addBuf(&bufs, @ptrCast(ip.struct_defaults_deps.values())); addBuf(&bufs, @ptrCast(ip.func_ies_deps.keys())); addBuf(&bufs, @ptrCast(ip.func_ies_deps.values())); addBuf(&bufs, @ptrCast(ip.zon_file_deps.keys())); @@ -4481,7 +4481,7 @@ pub fn addModuleErrorMsg( const root_name: ?[]const u8 = switch (ref.referencer.unwrap()) { .@"comptime" => "comptime", .nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip), - .type_layout, .type_inits => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), + .type_layout, .struct_defaults => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip), .memoized_state => null, }; @@ -5251,7 +5251,7 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav), .nav_val => |nav| pt.ensureNavValUpToDate(nav), .type_layout => |ty| pt.ensureTypeLayoutUpToDate(.fromInterned(ty)), - .type_inits => |ty| pt.ensureTypeInitsUpToDate(.fromInterned(ty)), + .struct_defaults => |ty| pt.ensureStructDefaultsUpToDate(.fromInterned(ty)), .memoized_state => |stage| pt.ensureMemoizedStateUpToDate(stage), .func => |func| pt.ensureFuncBodyUpToDate(func), }; diff --git a/src/IncrementalDebugServer.zig b/src/IncrementalDebugServer.zig index ce40844057d8e34d409f6ba78eb1b6b59f9085dc..7d0dc8e89b6fd9fd257733839e924de1ce92a25f 100644 --- a/src/IncrementalDebugServer.zig +++ b/src/IncrementalDebugServer.zig @@ -307,7 +307,7 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const switch (dependee) { .src_hash, .namespace, .namespace_name, .zon_file, .embed_file => try w.print("{f}", .{zcu.fmtDependee(dependee)}), .nav_val, .nav_ty => |nav| try w.print("{t} {d}", .{ dependee, @intFromEnum(nav) }), - .type_layout, .type_inits, .func_ies => |ip_index| try w.print("{t} {d}", .{ dependee, @intFromEnum(ip_index) }), + .type_layout, .struct_defaults, .func_ies => |ip_index| try w.print("{t} {d}", .{ dependee, @intFromEnum(ip_index) }), .memoized_state => |stage| try w.print("memoized_state {s}", .{@tagName(stage)}), } try w.writeByte('\n'); @@ -374,8 +374,8 @@ fn parseAnalUnit(str: []const u8) ?AnalUnit { return .wrap(.{ .nav_ty = @enumFromInt(parseIndex(idx_str) orelse return null) }); } else if (std.mem.eql(u8, kind, "type_layout")) { return .wrap(.{ .type_layout = @enumFromInt(parseIndex(idx_str) orelse return null) }); - } else if (std.mem.eql(u8, kind, "type_inits")) { - return .wrap(.{ .type_inits = @enumFromInt(parseIndex(idx_str) orelse return null) }); + } else if (std.mem.eql(u8, kind, "struct_defaults")) { + return .wrap(.{ .struct_defaults = @enumFromInt(parseIndex(idx_str) orelse return null) }); } else if (std.mem.eql(u8, kind, "func")) { return .wrap(.{ .func = @enumFromInt(parseIndex(idx_str) orelse return null) }); } else if (std.mem.eql(u8, kind, "memoized_state")) { diff --git a/src/InternPool.zig b/src/InternPool.zig index 28846c3f70ce14a85c09e4ce7d703816f3fe543b..ce9622e54d57bc0703d9151a5bbd35e3ef57298c 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -50,12 +50,12 @@ nav_ty_deps: std.AutoArrayHashMapUnmanaged(Nav.Index, DepEntry.Index), /// Dependencies on a function's inferred error set. Key is the function body, not the IES. /// Value is index into `dep_entries` of the first dependency on this function's IES. func_ies_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), -/// Dependencies on the resolved layout of a `struct` or `union` type. +/// Dependencies on the resolved layout of a `struct`, `union`, or `enum` type. /// Value is index into `dep_entries` of the first dependency on this type's layout. type_layout_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), -/// Dependencies on the resolved initializers of a `struct` or `enum` type. +/// Dependencies on the resolved default field values of a `struct` type. /// Value is index into `dep_entries` of the first dependency on this type's inits. -type_inits_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), +struct_defaults_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), /// Dependencies on a ZON file. Triggered by `@import` of ZON. /// Value is index into `dep_entries` of the first dependency on this ZON file. zon_file_deps: std.AutoArrayHashMapUnmanaged(FileIndex, DepEntry.Index), @@ -110,7 +110,7 @@ pub const empty: InternPool = .{ .nav_ty_deps = .empty, .func_ies_deps = .empty, .type_layout_deps = .empty, - .type_inits_deps = .empty, + .struct_defaults_deps = .empty, .zon_file_deps = .empty, .embed_file_deps = .empty, .namespace_deps = .empty, @@ -422,7 +422,7 @@ pub const AnalUnit = packed struct(u64) { nav_val, nav_ty, type_layout, - type_inits, + struct_defaults, func, memoized_state, }; @@ -434,11 +434,10 @@ pub const AnalUnit = packed struct(u64) { nav_val: Nav.Index, /// This `AnalUnit` resolves the type of the given `Nav`. nav_ty: Nav.Index, - /// This `AnalUnit` resolves the layout of the given `struct` or `union` type. + /// This `AnalUnit` resolves the layout of the given `struct`, `union`, or `enum` type. type_layout: InternPool.Index, - /// This `AnalUnit` resolves the field inits of the given `struct` or `enum` type. - /// The type may be a union's auto-generated tag enum, if the union has explicit field values. - type_inits: InternPool.Index, + /// This `AnalUnit` resolves the default field values of the given `struct` type. + struct_defaults: InternPool.Index, /// This `AnalUnit` analyzes the body of the given runtime function. func: InternPool.Index, /// This `AnalUnit` resolves all state which is memoized in fields on `Zcu`. @@ -852,7 +851,7 @@ pub const Dependee = union(enum) { /// Index is the function, not its IES. func_ies: Index, type_layout: Index, - type_inits: Index, + struct_defaults: Index, zon_file: FileIndex, embed_file: Zcu.EmbedFile.Index, namespace: TrackedInst.Index, @@ -906,7 +905,7 @@ pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyI .nav_ty => |x| ip.nav_ty_deps.get(x), .func_ies => |x| ip.func_ies_deps.get(x), .type_layout => |x| ip.type_layout_deps.get(x), - .type_inits => |x| ip.type_inits_deps.get(x), + .struct_defaults => |x| ip.struct_defaults_deps.get(x), .zon_file => |x| ip.zon_file_deps.get(x), .embed_file => |x| ip.embed_file_deps.get(x), .namespace => |x| ip.namespace_deps.get(x), @@ -981,7 +980,7 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend .nav_ty => ip.nav_ty_deps, .func_ies => ip.func_ies_deps, .type_layout => ip.type_layout_deps, - .type_inits => ip.type_inits_deps, + .struct_defaults => ip.struct_defaults_deps, .zon_file => ip.zon_file_deps, .embed_file => ip.embed_file_deps, .namespace => ip.namespace_deps, @@ -2248,10 +2247,6 @@ pub const Key = union(enum) { pub const Declared = struct { /// A `struct_decl`, `union_decl`, `enum_decl`, or `opaque_decl` instruction. zir_index: TrackedInst.Index, - /// If the type declaration had an argument type (tag type or packed backing type), this - /// is that type. Otherwise, this is `.none`. It is always `.none` for `opaque` types as - /// `opaque(T)` does not exist. - arg_ty: Index, /// The captured values of this type. These values must be fully resolved per the language spec. captures: union(enum) { owned: CaptureValue.Slice, @@ -2745,7 +2740,6 @@ pub const Key = union(enum) { switch (namespace_type) { .declared => |declared| { std.hash.autoHash(&hasher, declared.zir_index); - std.hash.autoHash(&hasher, declared.arg_ty); const captures = switch (declared.captures) { .owned => |cvs| cvs.get(ip), .external => |cvs| cvs, @@ -3155,7 +3149,6 @@ pub const Key = union(enum) { .declared => |a_d| { const b_d = b_info.declared; if (a_d.zir_index != b_d.zir_index) return false; - if (a_d.arg_ty != b_d.arg_ty) return false; const a_captures = switch (a_d.captures) { .owned => |s| s.get(ip), .external => |cvs| cvs, @@ -3295,7 +3288,6 @@ pub const Key = union(enum) { .void => .void_type, .null => .null_type, .false, .true => .bool_type, - .empty_tuple => .empty_tuple_type, .@"unreachable" => .noreturn_type, }, @@ -3308,6 +3300,7 @@ pub const LoadedStructType = struct { /// Index of the `struct_decl` or `reify` ZIR instruction. zir_index: TrackedInst.Index, captures: CaptureValue.Slice, + is_reified: bool, // TODO: the non-fqn will be needed by the new dwarf structure /// The name of this struct type. @@ -3319,10 +3312,9 @@ pub const LoadedStructType = struct { layout: std.builtin.Type.ContainerLayout, /// May be `undefined` if `layout != .@"packed"`. - packed_backing_mode: PackedBackingMode, - /// May be `undefined` if `layout != .@"packed", - packed_backing_int_type: Index, + packed_backing_mode: BackingTypeMode, + // The remaining fields are only valid once the struct's layout is resolved. field_name_map: MapIndex, field_names: NullTerminatedString.Slice, field_types: Index.Slice, @@ -3331,11 +3323,11 @@ pub const LoadedStructType = struct { field_is_comptime_bits: ComptimeBits, field_runtime_order: RuntimeOrder.Slice, field_offsets: Offsets, - - // These fields are only valid once the layout is resolved, and are never valid for `layout == .@"packed"`. + packed_backing_int_type: Index, has_no_possible_value: bool, has_one_possible_value: bool, comptime_only: bool, + has_runtime_bits: bool, size: u32, alignment: Alignment, @@ -3478,6 +3470,7 @@ pub const LoadedUnionType = struct { /// Index of the `union_decl` or `reify` ZIR instruction. zir_index: TrackedInst.Index, captures: CaptureValue.Slice, + is_reified: bool, // TODO: the non-fqn will be needed by the new dwarf structure /// The name of this union type. @@ -3488,23 +3481,26 @@ pub const LoadedUnionType = struct { namespace: NamespaceIndex, layout: std.builtin.Type.ContainerLayout, + enum_tag_mode: BackingTypeMode, + /// May be `undefined` if `layout != .@"packed"`. + packed_backing_mode: BackingTypeMode, + + /// Only reified unions store field names; typically they should be loaded from `enum_tag_type` + /// instead. Reified unions store them because type resolution needs them in order to validate + /// or populate `enum_tag_type`. + reified_field_names: NullTerminatedString.Slice, + + // The remaining fields are only valid once the union's layout is resolved. + field_types: Index.Slice, + field_aligns: Alignment.Slice, runtime_tag: RuntimeTag, /// Even if `runtime_tag == .none`, this is populated with the union's "hypothetical" tag type. enum_tag_type: Index, - /// May be `undefined` if `layout != .@"packed"`. - packed_backing_mode: PackedBackingMode, - /// May be `undefined` if `layout != .@"packed", packed_backing_int_type: Index, - - // Field names are not stored here, because fields are guaranteed to map one-to-one to the - // fields of the enum tag type. If you need field names, load them from `enum_tag_type`. - field_types: Index.Slice, - field_aligns: Alignment.Slice, - - // These fields are only valid once the layout is resolved, and are never valid for `layout == .@"packed"`. has_no_possible_value: bool, has_one_possible_value: bool, comptime_only: bool, + has_runtime_bits: bool, size: u32, padding: u32, alignment: Alignment, @@ -3523,6 +3519,7 @@ pub const LoadedEnumType = struct { captures: CaptureValue.Slice, /// If `zir_index` is `.none`, this is the union type for which this enum is the tag type. owner_union: Index, + is_reified: bool, // TODO: the non-fqn will be needed by the new dwarf structure /// The name of this enum type. @@ -3532,19 +3529,14 @@ pub const LoadedEnumType = struct { name_nav: Nav.Index.Optional, namespace: NamespaceIndex, - /// An integer type which is used for the numerical value of the enum. Populated immediately, regardless - /// of whether the integer tag type was explicitly provided or inferred by the compiler. - int_tag_type: Index, - int_tag_is_explicit: bool, + int_tag_mode: BackingTypeMode, nonexhaustive: bool, - /// Uses `NullTerminatedString.Adapter` with `field_names`. + // The remaining fields are only valid once the enum's layout is resolved. + int_tag_type: Index, field_name_map: MapIndex, - /// If this is `.none`, the enum tag type is auto-generated and so the fields are auto-numbered. - /// Otherwise, uses `Index.Adapter` with `field_values`. + field_names: NullTerminatedString.Slice, field_value_map: OptionalMapIndex, - field_names: NullTerminatedString.Slice, - /// Empty if `field_value_map` is `.none`. field_values: Index.Slice, /// Look up field index based on field name. @@ -3596,7 +3588,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { const extra_items = extra_list.view().items(.@"0"); const item = unwrapped_index.getItem(ip); // Exiting this `switch` means this is a `packed struct`. - const backing_mode: PackedBackingMode, const any_defaults: bool = switch (item.tag) { + const backing_mode: BackingTypeMode, const any_defaults: bool = switch (item.tag) { .type_struct_packed_auto => .{ .auto, false }, .type_struct_packed_explicit => .{ .explicit, false }, .type_struct_packed_auto_defaults => .{ .auto, true }, @@ -3667,6 +3659,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { return .{ .zir_index = extra.data.zir_index, .captures = captures, + .is_reified = extra.data.flags.any_captures == .reified, .name = extra.data.name, .name_nav = extra.data.name_nav, .namespace = extra.data.namespace, @@ -3675,7 +3668,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { .@"extern" => .@"extern", }, .packed_backing_mode = undefined, - .packed_backing_int_type = undefined, + .field_name_map = extra.data.field_name_map, .field_names = field_names, .field_types = field_types, @@ -3684,9 +3677,11 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { .field_is_comptime_bits = field_is_comptime_bits, .field_runtime_order = field_runtime_order, .field_offsets = field_offsets, + .packed_backing_int_type = .none, .has_no_possible_value = extra.data.flags.has_no_possible_value, .has_one_possible_value = extra.data.flags.has_one_possible_value, .comptime_only = extra.data.flags.comptime_only, + .has_runtime_bits = extra.data.flags.has_runtime_bits, .size = extra.data.size, .alignment = extra.data.flags.alignment, }; @@ -3728,12 +3723,13 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { return .{ .zir_index = extra.data.zir_index, .captures = captures, + .is_reified = extra.data.captures_len == .reified, .name = extra.data.name, .name_nav = extra.data.name_nav, .namespace = extra.data.namespace, .layout = .@"packed", .packed_backing_mode = backing_mode, - .packed_backing_int_type = extra.data.backing_int_type, + .field_name_map = extra.data.field_name_map, .field_names = field_names, .field_types = field_types, @@ -3742,9 +3738,11 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { .field_is_comptime_bits = .empty, .field_runtime_order = .empty, .field_offsets = .empty, + .packed_backing_int_type = extra.data.backing_int_type, .has_no_possible_value = undefined, .has_one_possible_value = undefined, .comptime_only = undefined, + .has_runtime_bits = undefined, .size = undefined, .alignment = undefined, }; @@ -3756,7 +3754,7 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { const extra_items = extra_list.view().items(.@"0"); const item = unwrapped_index.getItem(ip); // Exiting this `switch` means this is a `packed union`. - const backing_mode: PackedBackingMode = switch (item.tag) { + const backing_mode: BackingTypeMode = switch (item.tag) { .type_union_packed_auto => .auto, .type_union_packed_explicit => .explicit, .type_union => { @@ -3779,6 +3777,12 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { }, }; extra_index += captures.len; + const reified_field_names: NullTerminatedString.Slice = if (extra.data.flags.any_captures == .reified) .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = extra.data.fields_len, + } else .empty; + extra_index += reified_field_names.len; const field_types: Index.Slice = .{ .tid = unwrapped_index.tid, .start = extra_index, @@ -3795,6 +3799,7 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { return .{ .zir_index = extra.data.zir_index, .captures = captures, + .is_reified = extra.data.flags.any_captures == .reified, .name = extra.data.name, .name_nav = extra.data.name_nav, .namespace = extra.data.namespace, @@ -3803,14 +3808,17 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { .@"extern" => .@"extern", }, .runtime_tag = extra.data.flags.runtime_tag, + .enum_tag_mode = extra.data.flags.enum_tag_mode, .enum_tag_type = extra.data.enum_tag_type, .packed_backing_mode = undefined, .packed_backing_int_type = undefined, + .reified_field_names = reified_field_names, .field_types = field_types, .field_aligns = field_aligns, .has_no_possible_value = extra.data.flags.has_no_possible_value, .has_one_possible_value = extra.data.flags.has_one_possible_value, .comptime_only = extra.data.flags.comptime_only, + .has_runtime_bits = extra.data.flags.has_runtime_bits, .size = extra.data.size, .padding = extra.data.padding, .alignment = extra.data.flags.alignment, @@ -3832,6 +3840,12 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { }, }; extra_index += captures.len; + const reified_field_names: NullTerminatedString.Slice = if (extra.data.captures_len == .reified) .{ + .tid = unwrapped_index.tid, + .start = extra_index, + .len = extra.data.fields_len, + } else .empty; + extra_index += reified_field_names.len; const field_types: Index.Slice = .{ .tid = unwrapped_index.tid, .start = extra_index, @@ -3841,19 +3855,23 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { return .{ .zir_index = extra.data.zir_index, .captures = captures, + .is_reified = extra.data.captures_len == .reified, .name = extra.data.name, .name_nav = extra.data.name_nav, .namespace = extra.data.namespace, .layout = .@"packed", .runtime_tag = .none, + .enum_tag_mode = .auto, .enum_tag_type = extra.data.enum_tag_type, .packed_backing_mode = backing_mode, .packed_backing_int_type = extra.data.backing_int_type, + .reified_field_names = reified_field_names, .field_types = field_types, .field_aligns = .empty, .has_no_possible_value = undefined, .has_one_possible_value = undefined, .comptime_only = undefined, + .has_runtime_bits = undefined, .size = undefined, .padding = undefined, .alignment = undefined, @@ -3917,12 +3935,13 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType { return .{ .zir_index = zir_index, .captures = captures, + .is_reified = extra.data.captures_len == .reified, .owner_union = owner_union, .name = extra.data.name, .name_nav = extra.data.name_nav, .namespace = extra.data.namespace, .int_tag_type = extra.data.int_tag_type, - .int_tag_is_explicit = explicit_int_tag, + .int_tag_mode = if (explicit_int_tag) .explicit else .auto, .nonexhaustive = nonexhaustive, .field_name_map = extra.data.field_name_map, .field_value_map = field_value_map, @@ -4160,7 +4179,7 @@ pub const Index = enum(u32) { }; /// Used for a map of `Index` values to the index within a list of `Index` values. - pub const Adapter = struct { + const Adapter = struct { indexes: []const Index, pub fn eql(ctx: @This(), a: Index, b_void: void, b_map_index: usize) bool { @@ -4365,7 +4384,7 @@ pub const Index = enum(u32) { }) void { _ = self; const map_fields = @typeInfo(@typeInfo(@TypeOf(tag_to_encoding_map)).pointer.child).@"struct".fields; - @setEvalBranchQuota(2_000); + @setEvalBranchQuota(3_000); inline for (@typeInfo(Tag).@"enum".fields, 0..) |tag, start| { inline for (0..map_fields.len) |offset| { if (comptime std.mem.eql(u8, tag.name, map_fields[(start + offset) % map_fields.len].name)) break; @@ -4797,7 +4816,11 @@ pub const static_keys: [static_len]Key = .{ .{ .simple_value = .null }, .{ .simple_value = .true }, .{ .simple_value = .false }, - .{ .simple_value = .empty_tuple }, + + .{ .aggregate = .{ + .ty = .empty_tuple_type, + .storage = .{ .elems = &.{} }, + } }, }; /// How many items in the InternPool are statically known. @@ -5601,10 +5624,12 @@ pub const Tag = enum(u8) { has_no_possible_value: bool, /// Whether the struct is comptime-only. Always `false` until layout resolved. comptime_only: bool, + /// Whether the struct has runtime bits. Always `false` until layout resolved. + has_runtime_bits: bool, /// Alignment of the whole struct. Always `.none` until layout resolved. alignment: Alignment, - _: u17 = 0, + _: u16 = 0, }; }; @@ -5625,21 +5650,25 @@ pub const Tag = enum(u8) { name_nav: Nav.Index.Optional, namespace: NamespaceIndex, - /// The corresponding `PackedBackingMode` depends on the item's `Tag`. + /// The corresponding `BackingTypeMode` depends on the item's `Tag`. backing_int_type: Index, fields_len: u32, field_name_map: MapIndex, }; - /// Field names are intentionally omitted---they are available in `enum_tag_type`. + /// For declared unions, field names are intentionally omitted because they are available in + /// `enum_tag_type`. However, reified unions do store field names, because they are needed by + /// type resolution to create or validate the enum tag type (type resolution for declared unions + /// instead fetches field names from ZIR). /// /// Trailing: /// 0. type_hash: PackedU64 // if `any_captures == .reified` /// 1. captures_len: u32 // if `any_captures == .true` /// 2. capture: CaptureValue // if `any_captures == .true`; for each `captures_len` - /// 3. field_type: Index // for each `fields_len` - /// 4. field_align: Alignment // for each `fields_len` if `any_field_aligns` + /// 3. reified_field_name: NullTerminatedString // if `any_captures == .reified`; for each `fields_len` + /// 4. field_type: Index // for each `fields_len` + /// 5. field_align: Alignment // for each `fields_len` if `any_field_aligns` pub const TypeUnion = struct { zir_index: TrackedInst.Index, @@ -5652,7 +5681,6 @@ pub const Tag = enum(u8) { /// This could be provided through the tag type, but it is more convenient /// to store it directly. This is also necessary for `dumpStatsFallible` to /// work on unresolved types. - /// MLUGG TODO: reconsider, because we resolve the tag type eagerly now. fields_len: u32, /// Always 0 until layout resolved. @@ -5669,7 +5697,7 @@ pub const Tag = enum(u8) { /// /// For `union(enum(E))` syntax, this is `false`, but the generated enum tag type is /// considered to have an explicitly specified integer tag type. - explicit_tag_type: bool, + enum_tag_mode: BackingTypeMode, /// `packed` layout is represented separately by `TypeStructPacked`. layout: enum(u1) { auto, @"extern" }, @@ -5685,19 +5713,25 @@ pub const Tag = enum(u8) { has_no_possible_value: bool, /// Whether the union is comptime-only. Always `false` until layout resolved. comptime_only: bool, + /// Whether the union has runtime bits. Always `false` until layout resolved. + has_runtime_bits: bool, /// Alignment of the whole union. Always `.none` until layout resolved. alignment: Alignment, - _: u16 = 0, + _: u15 = 0, }; }; - /// Field names are intentionally omitted---they are available in `enum_tag_type`. + /// For declared unions, field names are intentionally omitted because they are available in + /// `enum_tag_type`. However, reified unions do store field names, because they are needed by + /// type resolution to create or validate the enum tag type (type resolution for declared unions + /// instead fetches field names from ZIR). /// /// Trailing: /// 0. type_hash: PackedU64 // if `captures_len == .reified` /// 1. capture: CaptureValue // if `captures_len != .reified`; for each `captures_len` - /// 2. field_type: Index // for each `fields_len` + /// 2. reified_field_name: NullTerminatedString // if `captures_len == .reified`; for each `fields_len` + /// 3. field_type: Index // for each `fields_len` pub const TypeUnionPacked = struct { zir_index: TrackedInst.Index, captures_len: enum(u32) { @@ -5709,7 +5743,7 @@ pub const Tag = enum(u8) { name_nav: Nav.Index.Optional, namespace: NamespaceIndex, - /// The corresponding `PackedBackingMode` depends on the item's `Tag`. + /// The corresponding `BackingTypeMode` depends on the item's `Tag`. backing_int_type: Index, /// Although packed unions do not semantically have a tag type, the compiler still assigns /// them a "hypothetical" tag type. @@ -5718,7 +5752,6 @@ pub const Tag = enum(u8) { /// This could be provided through the tag type, but it is more convenient /// to store it directly. This is also necessary for `dumpStatsFallible` to /// work on unresolved types. - /// MLUGG TODO: reconsider, because we resolve the tag type eagerly now. fields_len: u32, }; @@ -5742,8 +5775,7 @@ pub const Tag = enum(u8) { namespace: NamespaceIndex, /// An integer type which is used for the numerical value of the enum. Whether this was - /// user-provided or inferred by the compiler depends on the tag. Either way, the field - /// is populated immediately (i.e. does not require any type resolution). + /// user-provided or inferred by the compiler depends on the tag. int_tag_type: Index, fields_len: u32, @@ -5762,13 +5794,17 @@ pub const Tag = enum(u8) { }; }; -/// Differentiates between user-provided and compiler-generated backing types for packed aggregates. -pub const PackedBackingMode = enum(u1) { - /// The backing type was explicitly provided by the user, i.e. `packed struct(T)` or `packed union(T)`. - /// Type resolution simply *validates* that type. +/// Differentiates between user-provided and compiler-generated backing types for packed and tagged types. +pub const BackingTypeMode = enum(u1) { + /// The backing type was explicitly provided by the user. For instance: + /// union(T) + /// enum(T) + /// packed struct(T) + /// packed union(T) + /// Type layout resolution will evaluate the user-provided expression and validate that type. explicit, - /// No backing type was explicitly provided by the user. Type layout resolution will populate the - /// backing type based on the field types; before then it is invalid (probably `.none`). + /// No backing type was explicitly provided by the user. Type layout resolution will populate + /// an inferred/generated type. auto, }; @@ -5852,8 +5888,6 @@ pub const SimpleValue = enum(u32) { void = @intFromEnum(Index.void_value), /// This is untyped `null`. null = @intFromEnum(Index.null_value), - /// This is the untyped empty struct/array literal: `.{}` - empty_tuple = @intFromEnum(Index.empty_tuple), true = @intFromEnum(Index.bool_true), false = @intFromEnum(Index.bool_false), @"unreachable" = @intFromEnum(Index.unreachable_value), @@ -6395,7 +6429,7 @@ pub fn deinit(ip: *InternPool, gpa: Allocator, io: Io) void { ip.nav_ty_deps.deinit(gpa); ip.func_ies_deps.deinit(gpa); ip.type_layout_deps.deinit(gpa); - ip.type_inits_deps.deinit(gpa); + ip.struct_defaults_deps.deinit(gpa); ip.zon_file_deps.deinit(gpa); ip.embed_file_deps.deinit(gpa); ip.namespace_deps.deinit(gpa); @@ -6544,12 +6578,10 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { } }, .false => .{ .declared = .{ .zir_index = extra.data.zir_index, - .arg_ty = .none, .captures = .{ .owned = .empty }, } }, .true => .{ .declared = .{ .zir_index = extra.data.zir_index, - .arg_ty = .none, .captures = .{ .owned = .{ .tid = unwrapped_index.tid, .start = extra.end + 1, @@ -6572,11 +6604,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { } }, _ => .{ .declared = .{ .zir_index = extra.data.zir_index, - .arg_ty = switch (item.tag) { - .type_struct_packed_auto, .type_struct_packed_auto_defaults => .none, - .type_struct_packed_explicit, .type_struct_packed_explicit_defaults => extra.data.backing_int_type, - else => unreachable, - }, .captures = .{ .owned = .{ .tid = unwrapped_index.tid, .start = extra.end, @@ -6595,12 +6622,10 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { } }, .false => .{ .declared = .{ .zir_index = extra.data.zir_index, - .arg_ty = if (extra.data.flags.explicit_tag_type) extra.data.enum_tag_type else .none, .captures = .{ .owned = .empty }, } }, .true => .{ .declared = .{ .zir_index = extra.data.zir_index, - .arg_ty = if (extra.data.flags.explicit_tag_type) extra.data.enum_tag_type else .none, .captures = .{ .owned = .{ .tid = unwrapped_index.tid, .start = extra.end + 1, @@ -6619,11 +6644,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { } }, _ => .{ .declared = .{ .zir_index = extra.data.zir_index, - .arg_ty = switch (item.tag) { - .type_union_packed_auto => .none, - .type_union_packed_explicit => extra.data.backing_int_type, - else => unreachable, - }, .captures = .{ .owned = .{ .tid = unwrapped_index.tid, .start = extra.end, @@ -6645,11 +6665,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { } }, _ => .{ .declared = .{ .zir_index = @enumFromInt(extra_list.view().items(.@"0")[extra.end]), - .arg_ty = switch (item.tag) { - .type_enum_auto => .none, - .type_enum_explicit, .type_enum_nonexhaustive => extra.data.int_tag_type, - else => unreachable, - }, .captures = .{ .owned = .{ .tid = unwrapped_index.tid, .start = extra.end + 1, @@ -6662,7 +6677,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { const extra = extraDataTrail(unwrapped_index.getExtra(ip), Tag.TypeOpaque, data); break :ns .{ .declared = .{ .zir_index = extra.data.zir_index, - .arg_ty = .none, .captures = .{ .owned = .{ .tid = unwrapped_index.tid, .start = extra.end, @@ -6883,7 +6897,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { }, .type_array_small, .type_vector, - // MLUGG TODO: is this still possible? also, i hate .only_possible_value, it should die in a fire. .type_struct_packed_auto, .type_struct_packed_explicit, => .{ .aggregate = .{ @@ -6894,7 +6907,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { // There is only one possible value precisely due to the // fact that this values slice is fully populated! .type_struct, - // MLUGG TODO: is this still possible? also, i hate .only_possible_value, it should die in a fire. .type_struct_packed_auto_defaults, .type_struct_packed_explicit_defaults, => { @@ -7445,12 +7457,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: }); }, - .struct_type => unreachable, // use getStructType() instead + .struct_type => unreachable, // instead use: getDeclaredStructType, getReifiedStructType + .union_type => unreachable, // instead use: getDeclaredUnionType, getReifiedUnionType + .enum_type => unreachable, // instead use: getDeclaredEnumType, getReifiedEnumType, getGeneratedEnumTagType + .opaque_type => unreachable, // instead use: getDeclaredOpaqueType + .tuple_type => unreachable, // use getTupleType() instead - .union_type => unreachable, // use getUnionType() instead - .opaque_type => unreachable, // use getOpaqueType() instead - - .enum_type => unreachable, // use getEnumType() instead .func_type => unreachable, // use getFuncType() instead .@"extern" => unreachable, // use getExtern() instead .func => unreachable, // use getFuncInstance() or getFuncDecl() instead @@ -8072,43 +8084,180 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: return gop.put(); } -pub fn getStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct { +pub fn getDeclaredStructType( + ip: *InternPool, + gpa: Allocator, + io: Io, + tid: Zcu.PerThread.Id, + ini: struct { + zir_index: TrackedInst.Index, + captures: []const CaptureValue, + + // If the value of any of the following fields would change on an incremental update, then logic + // in `Zcu.mapOldZirToNew` must detect that (these properties are all trivially known from ZIR) + // and refuse to map the type declaration. This causes `zir_index` to change so that a new type + // will be interned at a fresh index. + // + // In the future, it would be good to remove all of those fields from `ini`, and in fact just + // have a single function `getDeclaredContainer` which is suitable for all container types. + // However, this requires some major changes to how container types are represented in the + // InternPool, so that it is possible for their backing storage to be "reallocated" as needed + // during type resolution. + fields_len: u32, + layout: std.builtin.Type.ContainerLayout, + any_comptime_fields: bool, + any_field_defaults: bool, + any_field_aligns: bool, + packed_backing_mode: BackingTypeMode, + }, +) Allocator.Error!WipContainerType.Result { + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .struct_type = .{ .declared = .{ + .zir_index = ini.zir_index, + .captures = .{ .external = ini.captures }, + } } }); + defer gop.deinit(); + if (gop == .existing) return .{ .existing = gop.existing }; + + const local = ip.getLocal(tid); + const items = local.getMutableItems(gpa, io); + const extra = local.getMutableExtra(gpa, io); + try items.ensureUnusedCapacity(1); + + const field_name_map = try ip.addMap(gpa, io, tid, ini.fields_len); + errdefer local.mutate.maps.len -= 1; + + const is_extern = switch (ini.layout) { + .auto => false, + .@"extern" => true, + .@"packed" => { + try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeStructPacked).@"struct".fields.len + + ini.captures.len + // capture + ini.fields_len + // field_name + ini.fields_len + // field_type + (if (ini.any_field_defaults) ini.fields_len else 0)); // field_default + + const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStructPacked{ + .zir_index = ini.zir_index, + .captures_len = @enumFromInt(ini.captures.len), + .name = undefined, // set by `finish` + .name_nav = undefined, // set by `finish` + .namespace = undefined, // set by `finish` + .backing_int_type = .none, + .fields_len = ini.fields_len, + .field_name_map = field_name_map, + }); + extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)}); // capture + extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name + extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type + if (ini.any_field_defaults) { + extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_default + } + items.appendAssumeCapacity(.{ + .tag = switch (ini.packed_backing_mode) { + .auto => if (ini.any_field_defaults) .type_struct_packed_auto_defaults else .type_struct_packed_auto, + .explicit => if (ini.any_field_defaults) .type_struct_packed_explicit_defaults else .type_struct_packed_explicit, + }, + .data = extra_index, + }); + return .{ .wip = .{ + .index = gop.put(), + .tid = tid, + .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?, + .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?, + .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?, + .field_names = undefined, + .field_types = undefined, + .field_values = undefined, + .field_aligns = undefined, + .field_is_comptime_bits = undefined, + } }; + }, + }; + + try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeStruct).@"struct".fields.len + + 1 + // captures_len + ini.captures.len + // capture + ini.fields_len + // field_name + ini.fields_len + // field_type + (if (ini.any_field_defaults) ini.fields_len else 0) + // field_default + (if (ini.any_field_aligns) (ini.fields_len + 3) / 4 else 0) + // field_align + (if (ini.any_comptime_fields) (ini.fields_len + 31) / 32 else 0) + // field_is_comptime_bits + (if (!is_extern) ini.fields_len else 0) + // field_runtime_order + ini.fields_len); // field_offset + + const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{ + .zir_index = ini.zir_index, + .name = undefined, // set by `finish` + .name_nav = undefined, // set by `finish` + .namespace = undefined, // set by `finish` + .fields_len = ini.fields_len, + .field_name_map = field_name_map, + .size = 0, + .flags = .{ + .any_captures = if (ini.captures.len != 0) .true else .false, + .layout = if (is_extern) .@"extern" else .auto, + .any_comptime_fields = ini.any_comptime_fields, + .any_field_defaults = ini.any_field_defaults, + .any_field_aligns = ini.any_field_aligns, + .has_one_possible_value = false, + .has_no_possible_value = false, + .comptime_only = false, + .has_runtime_bits = false, + .alignment = .none, + }, + }); + if (ini.captures.len != 0) { + extra.appendAssumeCapacity(.{@intCast(ini.captures.len)}); // captures_len + extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)}); // capture + } + extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name + extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type + if (ini.any_field_defaults) { + extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_default + } + if (ini.any_field_aligns) { + extra.appendNTimesAssumeCapacity(.{0}, (ini.fields_len + 3) / 4); // field_align + } + if (ini.any_comptime_fields) { + extra.appendNTimesAssumeCapacity(.{0}, (ini.fields_len + 31) / 32); // field_is_comptime_bits + } + if (!is_extern) { + extra.appendNTimesAssumeCapacity(.{@intFromEnum(LoadedStructType.RuntimeOrder.unresolved)}, ini.fields_len); // field_runtime_order + } + extra.appendNTimesAssumeCapacity(.{0}, ini.fields_len); // field_offset + items.appendAssumeCapacity(.{ + .tag = .type_struct, + .data = extra_index, + }); + return .{ .wip = .{ + .index = gop.put(), + .tid = tid, + .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?, + .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?, + .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?, + .field_names = undefined, + .field_types = undefined, + .field_values = undefined, + .field_aligns = undefined, + .field_is_comptime_bits = undefined, + } }; +} + +pub fn getReifiedStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct { + zir_index: TrackedInst.Index, + type_hash: u64, fields_len: u32, layout: std.builtin.Type.ContainerLayout, - /// The following only applies if `layout == .@"packed"`; this field is ignored otherwise. - /// - /// The explicitly specified backing integer type. `.none` means the backing integer is inferred - /// by the compiler. Asserts that this is an integer type. - explicit_packed_backing_type: Index, any_comptime_fields: bool, any_field_defaults: bool, any_field_aligns: bool, - key: union(enum) { - declared: struct { - zir_index: TrackedInst.Index, - captures: []const CaptureValue, - }, - reified: struct { - zir_index: TrackedInst.Index, - type_hash: u64, - }, - }, + /// Explicitly specified backing int type. `.none` if not packed or if backing type is inferred. + packed_backing_int_type: Index, }) Allocator.Error!WipContainerType.Result { - const key: Key = .{ .struct_type = switch (ini.key) { - .declared => |d| .{ .declared = .{ - .zir_index = d.zir_index, - .arg_ty = switch (ini.layout) { - .auto, .@"extern" => .none, - .@"packed" => ini.explicit_packed_backing_type, - }, - .captures = .{ .external = d.captures }, - } }, - .reified => |r| .{ .reified = .{ - .zir_index = r.zir_index, - .type_hash = r.type_hash, - } }, - } }; - var gop = try ip.getOrPutKey(gpa, io, tid, key); + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .struct_type = .{ .reified = .{ + .zir_index = ini.zir_index, + .type_hash = ini.type_hash, + } } }); defer gop.deinit(); if (gop == .existing) return .{ .existing = gop.existing }; @@ -8120,46 +8269,37 @@ pub fn getStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread const field_name_map = try ip.addMap(gpa, io, tid, ini.fields_len); errdefer local.mutate.maps.len -= 1; - const zir_index, const type_hash_captures_extra_len = switch (ini.key) { - .declared => |d| .{ d.zir_index, d.captures.len + @intFromBool(ini.layout != .@"packed") }, - .reified => |r| .{ r.zir_index, 2 }, - }; - const is_extern = switch (ini.layout) { .auto => false, .@"extern" => true, .@"packed" => { try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeStructPacked).@"struct".fields.len + - type_hash_captures_extra_len + + 2 + // type_hash ini.fields_len + // field_name ini.fields_len + // field_type (if (ini.any_field_defaults) ini.fields_len else 0)); // field_default const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStructPacked{ - .zir_index = zir_index, - .captures_len = switch (ini.key) { - .declared => |d| @enumFromInt(d.captures.len), - .reified => .reified, - }, + .zir_index = ini.zir_index, + .captures_len = .reified, .name = undefined, // set by `finish` .name_nav = undefined, // set by `finish` .namespace = undefined, // set by `finish` - .backing_int_type = ini.explicit_packed_backing_type, + .backing_int_type = ini.packed_backing_int_type, .fields_len = ini.fields_len, .field_name_map = field_name_map, }); - switch (ini.key) { - .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}), - .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)), - } + _ = addExtraAssumeCapacity(extra, PackedU64.init(ini.type_hash)); // type_hash const field_names_start = extra.mutate.len; extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name + const field_types_start = extra.mutate.len; extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type + const field_defaults_start = extra.mutate.len; if (ini.any_field_defaults) { extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_default } items.appendAssumeCapacity(.{ - .tag = switch (ini.explicit_packed_backing_type) { + .tag = switch (ini.packed_backing_int_type) { .none => if (ini.any_field_defaults) .type_struct_packed_auto_defaults else .type_struct_packed_auto, else => if (ini.any_field_defaults) .type_struct_packed_explicit_defaults else .type_struct_packed_explicit, }, @@ -8171,17 +8311,20 @@ pub fn getStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?, .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?, .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?, - .tag_type_index = null, - .fields_len = ini.fields_len, - .field_name_map = field_name_map, - .field_names_start = field_names_start, - .field_comptime_bits_start = null, + .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, + .field_types = .{ .tid = tid, .start = field_types_start, .len = ini.fields_len }, + .field_values = if (ini.any_field_defaults) + .{ .tid = tid, .start = field_defaults_start, .len = ini.fields_len } + else + undefined, + .field_aligns = undefined, + .field_is_comptime_bits = undefined, } }; }, }; try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeStruct).@"struct".fields.len + - type_hash_captures_extra_len + + 2 + // type_hash ini.fields_len + // field_name ini.fields_len + // field_type (if (ini.any_field_defaults) ini.fields_len else 0) + // field_default @@ -8191,7 +8334,7 @@ pub fn getStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread ini.fields_len); // field_offset const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{ - .zir_index = zir_index, + .zir_index = ini.zir_index, .name = undefined, // set by `finish` .name_nav = undefined, // set by `finish` .namespace = undefined, // set by `finish` @@ -8199,10 +8342,7 @@ pub fn getStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread .field_name_map = field_name_map, .size = 0, .flags = .{ - .any_captures = switch (ini.key) { - .declared => |d| if (d.captures.len != 0) .true else .false, - .reified => .reified, - }, + .any_captures = .reified, .layout = if (is_extern) .@"extern" else .auto, .any_comptime_fields = ini.any_comptime_fields, .any_field_defaults = ini.any_field_defaults, @@ -8210,30 +8350,27 @@ pub fn getStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread .has_one_possible_value = false, .has_no_possible_value = false, .comptime_only = false, + .has_runtime_bits = false, .alignment = .none, }, }); - switch (ini.key) { - .declared => |d| if (d.captures.len != 0) { - extra.appendAssumeCapacity(.{@intCast(d.captures.len)}); - extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}); - }, - .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)), - } + _ = addExtraAssumeCapacity(extra, PackedU64.init(ini.type_hash)); // type_hash const field_names_start = extra.mutate.len; extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name + const field_types_start = extra.mutate.len; extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type + const field_defaults_start = extra.mutate.len; if (ini.any_field_defaults) { extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_default } + const field_aligns_start = extra.mutate.len; if (ini.any_field_aligns) { extra.appendNTimesAssumeCapacity(.{0}, (ini.fields_len + 3) / 4); // field_align } - const field_comptime_bits_start: ?u32 = if (ini.any_comptime_fields) start: { - const start = extra.mutate.len; + const field_is_comptime_bits_start = extra.mutate.len; + if (ini.any_comptime_fields) { extra.appendNTimesAssumeCapacity(.{0}, (ini.fields_len + 31) / 32); // field_is_comptime_bits - break :start start; - } else null; + } if (!is_extern) { extra.appendNTimesAssumeCapacity(.{@intFromEnum(LoadedStructType.RuntimeOrder.unresolved)}, ini.fields_len); // field_runtime_order } @@ -8248,58 +8385,174 @@ pub fn getStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?, .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?, .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?, - .tag_type_index = null, + .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, + .field_types = .{ .tid = tid, .start = field_types_start, .len = ini.fields_len }, + .field_values = if (ini.any_field_defaults) + .{ .tid = tid, .start = field_defaults_start, .len = ini.fields_len } + else + undefined, + .field_aligns = if (ini.any_field_aligns) + .{ .tid = tid, .start = field_aligns_start, .len = ini.fields_len } + else + undefined, + .field_is_comptime_bits = if (ini.any_comptime_fields) + .{ .tid = tid, .start = field_is_comptime_bits_start, .len = (ini.fields_len + 31) / 32 } + else + undefined, + } }; +} + +pub fn getDeclaredUnionType( + ip: *InternPool, + gpa: Allocator, + io: Io, + tid: Zcu.PerThread.Id, + ini: struct { + zir_index: TrackedInst.Index, + captures: []const CaptureValue, + + // If the value of any of the following fields would change on an incremental update, then logic + // in `Zcu.mapOldZirToNew` must detect that (these properties are all trivially known from ZIR) + // and refuse to map the type declaration. This causes `zir_index` to change so that a new type + // will be interned at a fresh index. + // + // In the future, it would be good to remove all of those fields from `ini`, and in fact just + // have a single function `getDeclaredContainer` which is suitable for all container types. + // However, this requires some major changes to how container types are represented in the + // InternPool, so that it is possible for their backing storage to be "reallocated" as needed + // during type resolution. + fields_len: u32, + layout: std.builtin.Type.ContainerLayout, + any_field_aligns: bool, + runtime_tag: LoadedUnionType.RuntimeTag, + enum_tag_mode: BackingTypeMode, + packed_backing_mode: BackingTypeMode, + }, +) Allocator.Error!WipContainerType.Result { + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .union_type = .{ .declared = .{ + .zir_index = ini.zir_index, + .captures = .{ .external = ini.captures }, + } } }); + defer gop.deinit(); + if (gop == .existing) return .{ .existing = gop.existing }; + + const local = ip.getLocal(tid); + const items = local.getMutableItems(gpa, io); + const extra = local.getMutableExtra(gpa, io); + try items.ensureUnusedCapacity(1); + + const is_extern = switch (ini.layout) { + .auto => false, + .@"extern" => true, + .@"packed" => { + try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeUnionPacked).@"struct".fields.len + + ini.captures.len + // capture + ini.fields_len); // field_type + + const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnionPacked{ + .zir_index = ini.zir_index, + .captures_len = @enumFromInt(ini.captures.len), + .name = undefined, // set by `finish` + .name_nav = undefined, // set by `finish` + .namespace = undefined, // set by `finish` + .backing_int_type = .none, + .enum_tag_type = .none, + .fields_len = ini.fields_len, + }); + extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)}); // capture + extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type + items.appendAssumeCapacity(.{ + .tag = switch (ini.packed_backing_mode) { + .auto => .type_union_packed_auto, + .explicit => .type_union_packed_explicit, + }, + .data = extra_index, + }); + return .{ .wip = .{ + .index = gop.put(), + .tid = tid, + .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name").?, + .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name_nav").?, + .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "namespace").?, + .field_names = undefined, + .field_types = undefined, + .field_values = undefined, + .field_aligns = undefined, + .field_is_comptime_bits = undefined, + } }; + }, + }; + + try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeUnion).@"struct".fields.len + + 1 + // captures_len + ini.captures.len + // capture + ini.fields_len + // field_type + (if (ini.any_field_aligns) (ini.fields_len + 3) / 4 else 0)); // field_align + + const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnion{ + .zir_index = ini.zir_index, + .name = undefined, // set by `finish` + .name_nav = undefined, // set by `finish` + .namespace = undefined, // set by `finish` + .enum_tag_type = .none, .fields_len = ini.fields_len, - .field_name_map = field_name_map, - .field_names_start = field_names_start, - .field_comptime_bits_start = field_comptime_bits_start, + .size = 0, + .padding = 0, + .flags = .{ + .any_captures = if (ini.captures.len != 0) .true else .false, + .enum_tag_mode = ini.enum_tag_mode, + .layout = if (is_extern) .@"extern" else .auto, + .any_field_aligns = ini.any_field_aligns, + .runtime_tag = ini.runtime_tag, + .has_one_possible_value = false, + .has_no_possible_value = false, + .comptime_only = false, + .has_runtime_bits = false, + .alignment = .none, + }, + }); + if (ini.captures.len > 0) { + extra.appendAssumeCapacity(.{@intCast(ini.captures.len)}); // captures_len + extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)}); // capture + } + extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type + if (ini.any_field_aligns) { + extra.appendNTimesAssumeCapacity(.{0}, (ini.fields_len + 3) / 4); // field_align + } + items.appendAssumeCapacity(.{ + .tag = .type_union, + .data = extra_index, + }); + return .{ .wip = .{ + .index = gop.put(), + .tid = tid, + .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?, + .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name_nav").?, + .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?, + .field_names = undefined, + .field_types = undefined, + .field_values = undefined, + .field_aligns = undefined, + .field_is_comptime_bits = undefined, } }; } -pub fn getUnionType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct { +pub fn getReifiedUnionType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct { + zir_index: TrackedInst.Index, + type_hash: u64, fields_len: u32, layout: std.builtin.Type.ContainerLayout, - /// The explicitly specified backing integer type for a `packed union`. - /// `.none` means the backing integer is inferred by the compiler. If set, - /// must be an integer type. If the union is not packed, must be `.none`. - explicit_packed_backing_type: Index, + any_field_aligns: bool, runtime_tag: LoadedUnionType.RuntimeTag, - /// `true` for `union(T)`, but `false` for anything else, including `union(enum(T))`. - have_explicit_enum_tag: bool, - any_field_aligns: bool, - key: union(enum) { - declared: struct { - zir_index: TrackedInst.Index, - captures: []const CaptureValue, - /// This is the `T` in one of the following: - /// * `union(T)` (enum tag type) - /// * `union(enum(T))` (int tag type) - /// * `packed union(T)` (int backing type) - /// Or `.none` otherwise. - arg_ty: InternPool.Index, - }, - reified: struct { - zir_index: TrackedInst.Index, - type_hash: u64, - }, - }, + /// Explicitly specified enum tag type. `.none` if `runtime_tag != .tagged`. + enum_tag_type: Index, + /// Explicitly specified backing int type. `.none` if not packed or if backing type is inferred. + packed_backing_int_type: Index, }) Allocator.Error!WipContainerType.Result { - if (ini.explicit_packed_backing_type != .none) { - assert(ip.zigTypeTag(ini.explicit_packed_backing_type) == .int); - if (ini.key == .declared) assert(ini.key.declared.arg_ty == ini.explicit_packed_backing_type); - } - const key: Key = .{ .union_type = switch (ini.key) { - .declared => |d| .{ .declared = .{ - .zir_index = d.zir_index, - .arg_ty = d.arg_ty, - .captures = .{ .external = d.captures }, - } }, - .reified => |r| .{ .reified = .{ - .zir_index = r.zir_index, - .type_hash = r.type_hash, - } }, - } }; - var gop = try ip.getOrPutKey(gpa, io, tid, key); + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .union_type = .{ .reified = .{ + .zir_index = ini.zir_index, + .type_hash = ini.type_hash, + } } }); defer gop.deinit(); if (gop == .existing) return .{ .existing = gop.existing }; @@ -8308,98 +8561,86 @@ pub fn getUnionType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread. const extra = local.getMutableExtra(gpa, io); try items.ensureUnusedCapacity(1); - const zir_index, const type_hash_captures_extra_len = switch (ini.key) { - .declared => |d| .{ d.zir_index, d.captures.len + @intFromBool(ini.layout != .@"packed") }, - .reified => |r| .{ r.zir_index, 2 }, - }; - const is_extern = switch (ini.layout) { .auto => false, .@"extern" => true, .@"packed" => { try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeUnionPacked).@"struct".fields.len + - type_hash_captures_extra_len + + 2 + // type_hash + ini.fields_len + // reified_field_name ini.fields_len); // field_type const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnionPacked{ - .zir_index = zir_index, - .captures_len = switch (ini.key) { - .declared => |d| @enumFromInt(d.captures.len), - .reified => .reified, - }, + .zir_index = ini.zir_index, + .captures_len = .reified, .name = undefined, // set by `finish` .name_nav = undefined, // set by `finish` .namespace = undefined, // set by `finish` - .backing_int_type = ini.explicit_packed_backing_type, - .enum_tag_type = .none, // set by `setTagType` + .backing_int_type = ini.packed_backing_int_type, + .enum_tag_type = .none, .fields_len = ini.fields_len, }); - switch (ini.key) { - .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}), - .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)), - } + _ = addExtraAssumeCapacity(extra, PackedU64.init(ini.type_hash)); // type_hash + const field_names_start = extra.mutate.len; + extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // reified_field_name + const field_types_start = extra.mutate.len; extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type items.appendAssumeCapacity(.{ - .tag = switch (ini.explicit_packed_backing_type) { + .tag = switch (ini.packed_backing_int_type) { .none => .type_union_packed_auto, else => .type_union_packed_explicit, }, .data = extra_index, }); - return .{ - .wip = .{ - .index = gop.put(), - .tid = tid, - .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name").?, - .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name_nav").?, - .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "namespace").?, - .tag_type_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "enum_tag_type").?, - .fields_len = 0, // the fields come from the enum, so nothing to set - .field_name_map = undefined, - .field_names_start = undefined, - .field_comptime_bits_start = undefined, - }, - }; + return .{ .wip = .{ + .index = gop.put(), + .tid = tid, + .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name").?, + .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name_nav").?, + .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "namespace").?, + .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, + .field_types = .{ .tid = tid, .start = field_types_start, .len = ini.fields_len }, + .field_values = undefined, + .field_aligns = undefined, + .field_is_comptime_bits = undefined, + } }; }, }; try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeUnion).@"struct".fields.len + - type_hash_captures_extra_len + + 2 + // type_hash + ini.fields_len + // reified_field_name ini.fields_len + // field_type (if (ini.any_field_aligns) (ini.fields_len + 3) / 4 else 0)); // field_align const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnion{ - .zir_index = zir_index, + .zir_index = ini.zir_index, .name = undefined, // set by `finish` .name_nav = undefined, // set by `finish` .namespace = undefined, // set by `finish` - .enum_tag_type = .none, // set by `setTagType` + .enum_tag_type = ini.enum_tag_type, .fields_len = ini.fields_len, .size = 0, .padding = 0, .flags = .{ - .any_captures = switch (ini.key) { - .declared => |d| if (d.captures.len != 0) .true else .false, - .reified => .reified, - }, - .explicit_tag_type = ini.have_explicit_enum_tag, + .any_captures = .reified, + .enum_tag_mode = if (ini.enum_tag_type == .none) .auto else .explicit, .layout = if (is_extern) .@"extern" else .auto, .any_field_aligns = ini.any_field_aligns, .runtime_tag = ini.runtime_tag, .has_one_possible_value = false, .has_no_possible_value = false, .comptime_only = false, + .has_runtime_bits = false, .alignment = .none, }, }); - switch (ini.key) { - .declared => |d| if (d.captures.len != 0) { - extra.appendAssumeCapacity(.{@intCast(d.captures.len)}); - extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}); - }, - .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)), - } + _ = addExtraAssumeCapacity(extra, PackedU64.init(ini.type_hash)); + const field_names_start = extra.mutate.len; + extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // reified_field_name + const field_types_start = extra.mutate.len; extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type + const field_aligns_start = extra.mutate.len; if (ini.any_field_aligns) { extra.appendNTimesAssumeCapacity(.{0}, (ini.fields_len + 3) / 4); // field_align } @@ -8407,53 +8648,124 @@ pub fn getUnionType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread. .tag = .type_union, .data = extra_index, }); - return .{ - .wip = .{ - .index = gop.put(), - .tid = tid, - .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?, - .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name_nav").?, - .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?, - .tag_type_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "enum_tag_type").?, - .fields_len = 0, // the fields come from the enum, so nothing to set - .field_name_map = undefined, - .field_names_start = undefined, - .field_comptime_bits_start = undefined, - }, - }; + return .{ .wip = .{ + .index = gop.put(), + .tid = tid, + .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?, + .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name_nav").?, + .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?, + .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, + .field_types = .{ .tid = tid, .start = field_types_start, .len = ini.fields_len }, + .field_values = undefined, + .field_aligns = if (ini.any_field_aligns) + .{ .tid = tid, .start = field_aligns_start, .len = ini.fields_len } + else + undefined, + .field_is_comptime_bits = undefined, + } }; } -pub fn getEnumType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct { - fields_len: u32, - /// For `enum(T)` or `union(enum(T))`, this is `T`. Asserts `T` is an integer type. - /// Otherwise, `.none`. - explicit_int_tag_type: Index, - nonexhaustive: bool, - key: union(enum) { - declared: struct { - zir_index: TrackedInst.Index, - captures: []const CaptureValue, - }, - reified: struct { - zir_index: TrackedInst.Index, - type_hash: u64, - }, - generated_union_tag: Index, +pub fn getDeclaredEnumType( + ip: *InternPool, + gpa: Allocator, + io: Io, + tid: Zcu.PerThread.Id, + ini: struct { + zir_index: TrackedInst.Index, + captures: []const CaptureValue, + + // If the value of any of the following fields would change on an incremental update, then logic + // in `Zcu.mapOldZirToNew` must detect that (these properties are all trivially known from ZIR) + // and refuse to map the type declaration. This causes `zir_index` to change so that a new type + // will be interned at a fresh index. + // + // In the future, it would be good to remove all of those fields from `ini`, and in fact just + // have a single function `getDeclaredContainer` which is suitable for all container types. + // However, this requires some major changes to how container types are represented in the + // InternPool, so that it is possible for their backing storage to be "reallocated" as needed + // during type resolution. + fields_len: u32, + nonexhaustive: bool, + /// For `enum(T)` this is `.explicit`. Otherwise this is `.none`. + int_tag_mode: BackingTypeMode, }, -}) Allocator.Error!WipContainerType.Result { - const key: Key = .{ .enum_type = switch (ini.key) { - .declared => |d| .{ .declared = .{ - .zir_index = d.zir_index, - .arg_ty = ini.explicit_int_tag_type, - .captures = .{ .external = d.captures }, - } }, - .reified => |r| .{ .reified = .{ - .zir_index = r.zir_index, - .type_hash = r.type_hash, - } }, - .generated_union_tag => |u| .{ .generated_union_tag = u }, +) Allocator.Error!WipContainerType.Result { + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .enum_type = .{ .declared = .{ + .zir_index = ini.zir_index, + .captures = .{ .external = ini.captures }, + } } }); + defer gop.deinit(); + if (gop == .existing) return .{ .existing = gop.existing }; + + const local = ip.getLocal(tid); + const items = local.getMutableItems(gpa, io); + const extra = local.getMutableExtra(gpa, io); + try items.ensureUnusedCapacity(1); + + const tag: Tag, const have_values: bool = if (ini.nonexhaustive) + .{ .type_enum_nonexhaustive, true } + else if (ini.int_tag_mode == .explicit) + .{ .type_enum_explicit, true } + else + .{ .type_enum_auto, false }; + + const field_name_map = try ip.addMap(gpa, io, tid, ini.fields_len); + errdefer local.mutate.maps.len -= 1; + + const field_value_map = if (have_values) try ip.addMap(gpa, io, tid, ini.fields_len) else undefined; + errdefer local.mutate.maps.len -= @intFromBool(have_values); + + try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeEnum).@"struct".fields.len + + 1 + // zir_index + ini.captures.len + // capture + @intFromBool(have_values) + // field_value_map + ini.fields_len + // field_name + (if (have_values) ini.fields_len else 0)); // field_value + + const extra_index = addExtraAssumeCapacity(extra, Tag.TypeEnum{ + .captures_len = @enumFromInt(ini.captures.len), + .name = undefined, // set by `finish` + .name_nav = undefined, // set by `finish` + .namespace = undefined, // set by `finish` + .int_tag_type = .none, + .fields_len = ini.fields_len, + .field_name_map = field_name_map, + }); + extra.appendAssumeCapacity(.{@intFromEnum(ini.zir_index)}); // zir_index + extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)}); // capture + if (have_values) extra.appendAssumeCapacity(.{@intFromEnum(field_value_map)}); // field_value_map + extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name + if (have_values) extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_value + items.appendAssumeCapacity(.{ + .tag = tag, + .data = extra_index, + }); + return .{ .wip = .{ + .index = gop.put(), + .tid = tid, + .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name").?, + .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name_nav").?, + .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "namespace").?, + .field_names = undefined, + .field_types = undefined, + .field_values = undefined, + .field_aligns = undefined, + .field_is_comptime_bits = undefined, } }; - var gop = try ip.getOrPutKey(gpa, io, tid, key); +} + +pub fn getReifiedEnumType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct { + zir_index: TrackedInst.Index, + type_hash: u64, + fields_len: u32, + nonexhaustive: bool, + /// Explicitly specified int tag type, or `.none` if the int tag type is inferred. + int_tag_type: Index, +}) Allocator.Error!WipContainerType.Result { + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .enum_type = .{ .reified = .{ + .zir_index = ini.zir_index, + .type_hash = ini.type_hash, + } } }); defer gop.deinit(); if (gop == .existing) return .{ .existing = gop.existing }; @@ -8464,7 +8776,7 @@ pub fn getEnumType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.I const tag: Tag, const have_values: bool = if (ini.nonexhaustive) .{ .type_enum_nonexhaustive, true } - else if (ini.explicit_int_tag_type != .none) + else if (ini.int_tag_type != .none) .{ .type_enum_explicit, true } else .{ .type_enum_auto, false }; @@ -8476,47 +8788,100 @@ pub fn getEnumType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.I errdefer local.mutate.maps.len -= @intFromBool(have_values); try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeEnum).@"struct".fields.len + - switch (ini.key) { - .declared => |d| 1 + d.captures.len, // `zir_index` and `capture` - .reified => 3, // `zir_index` and `type_hash` - .generated_union_tag => 1, // owner_union - } + + 1 + // zir_index + 2 + // type_hash + @intFromBool(have_values) + // field_value_map + ini.fields_len + // field_name + (if (have_values) ini.fields_len else 0)); // field_value + + const extra_index = addExtraAssumeCapacity(extra, Tag.TypeEnum{ + .captures_len = .reified, + .name = undefined, // set by `finish` + .name_nav = undefined, // set by `finish` + .namespace = undefined, // set by `finish` + .int_tag_type = ini.int_tag_type, + .fields_len = ini.fields_len, + .field_name_map = field_name_map, + }); + extra.appendAssumeCapacity(.{@intFromEnum(ini.zir_index)}); // zir_index + _ = addExtraAssumeCapacity(extra, PackedU64.init(ini.type_hash)); // type_hash + if (have_values) extra.appendAssumeCapacity(.{@intFromEnum(field_value_map)}); // field_value_map + const field_names_start = extra.mutate.len; + extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name + const field_values_start = extra.mutate.len; + if (have_values) extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_value + items.appendAssumeCapacity(.{ + .tag = tag, + .data = extra_index, + }); + return .{ .wip = .{ + .index = gop.put(), + .tid = tid, + .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name").?, + .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name_nav").?, + .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "namespace").?, + .field_names = .{ .tid = tid, .start = field_names_start, .len = ini.fields_len }, + .field_types = undefined, + .field_values = if (have_values) + .{ .tid = tid, .start = field_values_start, .len = ini.fields_len } + else + undefined, + .field_aligns = undefined, + .field_is_comptime_bits = undefined, + } }; +} + +pub fn getGeneratedEnumTagType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct { + /// The union type for which this enum is a generated tag. + union_type: Index, + /// For `union(enum(T))` this is `.explicit`. Otherwise this is `.none`. + int_tag_mode: BackingTypeMode, + fields_len: u32, +}) Allocator.Error!WipContainerType.Result { + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .enum_type = .{ .generated_union_tag = ini.union_type } }); + defer gop.deinit(); + if (gop == .existing) return .{ .existing = gop.existing }; + + const local = ip.getLocal(tid); + const items = local.getMutableItems(gpa, io); + const extra = local.getMutableExtra(gpa, io); + try items.ensureUnusedCapacity(1); + + const field_name_map = try ip.addMap(gpa, io, tid, ini.fields_len); + errdefer local.mutate.maps.len -= 1; + + const have_values = switch (ini.int_tag_mode) { + .explicit => true, + .auto => false, + }; + + const field_value_map = if (have_values) try ip.addMap(gpa, io, tid, ini.fields_len) else undefined; + errdefer local.mutate.maps.len -= @intFromBool(have_values); + + try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeEnum).@"struct".fields.len + + 1 + // owner_union @intFromBool(have_values) + // field_value_map ini.fields_len + // field_name (if (have_values) ini.fields_len else 0)); // field_value const extra_index = addExtraAssumeCapacity(extra, Tag.TypeEnum{ - .captures_len = switch (ini.key) { - .declared => |d| @enumFromInt(d.captures.len), - .reified => .reified, - .generated_union_tag => .generated_union_tag, - }, + .captures_len = .generated_union_tag, .name = undefined, // set by `finish` .name_nav = undefined, // set by `finish` .namespace = undefined, // set by `finish` - .int_tag_type = ini.explicit_int_tag_type, + .int_tag_type = .none, .fields_len = ini.fields_len, .field_name_map = field_name_map, }); - switch (ini.key) { - .declared => |d| { - extra.appendAssumeCapacity(.{@intFromEnum(d.zir_index)}); // zir_index - extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}); // capture - }, - .reified => |r| { - extra.appendAssumeCapacity(.{@intFromEnum(r.zir_index)}); // zir_index - _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)); // type_hash - }, - .generated_union_tag => |owner_union| { - extra.appendAssumeCapacity(.{@intFromEnum(owner_union)}); // owner_union - }, - } + extra.appendAssumeCapacity(.{@intFromEnum(ini.union_type)}); // owner_union if (have_values) extra.appendAssumeCapacity(.{@intFromEnum(field_value_map)}); - const field_names_start = extra.mutate.len; extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name if (have_values) extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_value items.appendAssumeCapacity(.{ - .tag = tag, + .tag = switch (ini.int_tag_mode) { + .auto => .type_enum_auto, + .explicit => .type_enum_explicit, + }, .data = extra_index, }); return .{ .wip = .{ @@ -8525,22 +8890,21 @@ pub fn getEnumType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.I .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name").?, .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name_nav").?, .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "namespace").?, - .tag_type_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "int_tag_type").?, - .fields_len = ini.fields_len, - .field_name_map = field_name_map, - .field_names_start = field_names_start, - .field_comptime_bits_start = null, + .field_names = undefined, + .field_types = undefined, + .field_values = undefined, + .field_aligns = undefined, + .field_is_comptime_bits = undefined, } }; } -pub fn getOpaqueType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct { +pub fn getDeclaredOpaqueType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct { zir_index: TrackedInst.Index, captures: []const CaptureValue, }) Allocator.Error!WipContainerType.Result { var gop = try ip.getOrPutKey(gpa, io, tid, .{ .opaque_type = .{ .declared = .{ .zir_index = ini.zir_index, .captures = .{ .external = ini.captures }, - .arg_ty = .none, } } }); defer gop.deinit(); if (gop == .existing) return .{ .existing = gop.existing }; @@ -8569,11 +8933,11 @@ pub fn getOpaqueType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name").?, .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name_nav").?, .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "namespace").?, - .tag_type_index = null, - .fields_len = 0, - .field_name_map = undefined, - .field_names_start = undefined, - .field_comptime_bits_start = undefined, + .field_names = undefined, + .field_types = undefined, + .field_values = undefined, + .field_aligns = undefined, + .field_is_comptime_bits = undefined, } }; } @@ -8584,12 +8948,15 @@ pub const WipContainerType = struct { name_nav_index: u32, namespace_index: u32, - tag_type_index: ?u32, - - fields_len: u32, - field_name_map: MapIndex, - field_names_start: u32, - field_comptime_bits_start: ?u32, + // These fields are only populated when creating reified types, because reified types populate + // field information immediately, with type resolution only handling validation. This is in + // contrast to declared types, where field information is populated by the type resolution + // process evaluating ZIR expressions. + field_names: NullTerminatedString.Slice, + field_types: Index.Slice, + field_values: Index.Slice, + field_aligns: Alignment.Slice, + field_is_comptime_bits: LoadedStructType.ComptimeBits, pub fn setName( wip: WipContainerType, @@ -8605,48 +8972,6 @@ pub const WipContainerType = struct { extra_items[wip.name_nav_index] = @intFromEnum(name_nav); } - pub fn setTagType( - wip: WipContainerType, - ip: *InternPool, - tag_ty: Index, - ) void { - const extra = ip.getLocalShared(wip.tid).extra.acquire(); - const extra_items = extra.view().items(.@"0"); - const i = wip.tag_type_index.?; - const old_val: InternPool.Index = @enumFromInt(extra_items[i]); - assert(old_val == .none); - assert(tag_ty != .none); - extra_items[i] = @intFromEnum(tag_ty); - } - - /// Returns the already-existing field with the same name, if any. - pub fn nextField( - wip: WipContainerType, - ip: *InternPool, - name: NullTerminatedString, - marked_comptime: bool, - ) ?u32 { - assert(wip.fields_len > 0); - const extra = ip.getLocalShared(wip.tid).extra.acquire(); - const extra_items = extra.view().items(.@"0"); - const map = wip.field_name_map.get(ip); - const field_idx = map.count(); - assert(field_idx < wip.fields_len); - const names: []NullTerminatedString = @ptrCast(extra_items[wip.field_names_start..][0..wip.fields_len]); - const adapter: NullTerminatedString.Adapter = .{ .strings = names[0..field_idx] }; - const gop = map.getOrPutAssumeCapacityAdapted(name, adapter); - if (gop.found_existing) return @intCast(gop.index); - names[field_idx] = name; - if (wip.field_comptime_bits_start) |start_idx| { - if (marked_comptime) { - extra_items[start_idx + field_idx / 32] |= @as(u32, 1) << @intCast(field_idx % 32); - } - } else { - assert(!marked_comptime); - } - return null; - } - pub fn finish( wip: WipContainerType, ip: *InternPool, @@ -8657,14 +8982,6 @@ pub const WipContainerType = struct { extra_items[wip.namespace_index] = @intFromEnum(namespace); - if (wip.fields_len > 0) { - assert(wip.field_name_map.get(ip).count() == wip.fields_len); - } - if (wip.tag_type_index) |i| { - const tag_ty: Index = @enumFromInt(extra_items[i]); - assert(tag_ty != .none); - } - return wip.index; } @@ -9504,19 +9821,6 @@ fn addStringsToMap( } } -fn addIndexesToMap( - ip: *InternPool, - map_index: MapIndex, - indexes: []const Index, -) void { - const map = map_index.get(ip); - const adapter: Index.Adapter = .{ .indexes = indexes }; - for (indexes) |index| { - const gop = map.getOrPutAssumeCapacityAdapted(index, adapter); - assert(!gop.found_existing); - } -} - fn addMap(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, cap: usize) Allocator.Error!MapIndex { const maps = ip.getLocal(tid).getMutableMaps(gpa, io); const unwrapped: MapIndex.Unwrapped = .{ .tid = tid, .index = maps.mutate.len }; @@ -10260,10 +10564,78 @@ pub fn dump(ip: *const InternPool) void { const stderr = std.debug.lockStderr(&buffer); defer std.debug.unlockStderr(); const w = &stderr.file_writer.interface; + dumpDependencyStatsFallible(ip, w) catch return; dumpStatsFallible(ip, w, std.heap.page_allocator) catch return; dumpAllFallible(ip, w) catch return; } +fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void { + const dep_entries_len = ip.dep_entries.items.len - ip.free_dep_entries.items.len; + const src_hash_deps_len = ip.src_hash_deps.count(); + const nav_val_deps_len = ip.nav_val_deps.count(); + const nav_ty_deps_len = ip.nav_ty_deps.count(); + const func_ies_deps_len = ip.func_ies_deps.count(); + const type_layout_deps_len = ip.type_layout_deps.count(); + const struct_defaults_deps_len = ip.struct_defaults_deps.count(); + const zon_file_deps_len = ip.zon_file_deps.count(); + const embed_file_deps_len = ip.embed_file_deps.count(); + const namespace_deps_len = ip.namespace_deps.count(); + const namespace_name_deps_len = ip.namespace_name_deps.count(); + const dep_entries_size = dep_entries_len * @sizeOf(DepEntry); + const src_hash_deps_size = src_hash_deps_len * 8; + const nav_val_deps_size = nav_val_deps_len * 8; + const nav_ty_deps_size = nav_ty_deps_len * 8; + const func_ies_deps_size = func_ies_deps_len * 8; + const type_layout_deps_size = type_layout_deps_len * 8; + const struct_defaults_deps_size = struct_defaults_deps_len * 8; + const zon_file_deps_size = zon_file_deps_len * 8; + const embed_file_deps_size = embed_file_deps_len * 8; + const namespace_deps_size = namespace_deps_len * 8; + const namespace_name_deps_size = namespace_name_deps_len * (@sizeOf(NamespaceNameKey) + 4); + + try w.print( + \\InternPool dependencies: {d} bytes + \\ {d} entries: {d} bytes + \\ {d} src_hash: {d} bytes + \\ {d} nav_val: {d} bytes + \\ {d} nav_ty: {d} bytes + \\ {d} func_ies: {d} bytes + \\ {d} type_layout: {d} bytes + \\ {d} struct_defaults: {d} bytes + \\ {d} zon_file: {d} bytes + \\ {d} embed_file: {d} bytes + \\ {d} namespace: {d} bytes + \\ {d} namespace_name: {d} bytes + \\ + , .{ + dep_entries_size + src_hash_deps_size + nav_val_deps_size + nav_ty_deps_size + + func_ies_deps_size + type_layout_deps_size + struct_defaults_deps_size + zon_file_deps_size + + embed_file_deps_size + namespace_deps_size + namespace_name_deps_size, + dep_entries_len, + dep_entries_size, + src_hash_deps_len, + src_hash_deps_size, + nav_val_deps_len, + nav_val_deps_size, + nav_ty_deps_len, + nav_ty_deps_size, + func_ies_deps_len, + func_ies_deps_size, + type_layout_deps_len, + type_layout_deps_size, + struct_defaults_deps_len, + struct_defaults_deps_size, + zon_file_deps_len, + zon_file_deps_size, + embed_file_deps_len, + embed_file_deps_size, + namespace_deps_len, + namespace_deps_size, + namespace_name_deps_len, + namespace_name_deps_size, + }); +} + fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !void { var items_len: usize = 0; var extra_len: usize = 0; @@ -10278,10 +10650,10 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo const limbs_size = 8 * limbs_len; // TODO: map overhead size is not taken into account - const total_size = @sizeOf(InternPool) + items_size + extra_size + limbs_size; + const total_size = items_size + extra_size + limbs_size; - std.debug.print( - \\InternPool size: {d} bytes + try w.print( + \\InternPool values: {d} bytes \\ {d} items: {d} bytes \\ {d} extra: {d} bytes \\ {d} limbs: {d} bytes @@ -10302,6 +10674,8 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo }; var counts = std.AutoArrayHashMap(Tag, TagStats).init(arena); for (ip.locals) |*local| { + // Early check for length 0, because `view()` is invalid if capacity is 0 + if (local.mutate.items.len == 0) continue; const items = local.shared.items.view().slice(); const extra_list = local.shared.extra; const extra_items = extra_list.view().items(.@"0"); @@ -10562,6 +10936,8 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void { for (ip.locals, 0..) |*local, tid| { + // Early check for length 0, because `view()` is invalid if capacity is 0 + if (local.mutate.items.len == 0) continue; const items = local.shared.items.view(); for ( items.items(.tag)[0..local.mutate.items.len], @@ -11981,22 +12357,42 @@ pub fn unwrapCoercedFunc(ip: *const InternPool, index: Index) Index { }; } -/// Returns the already-existing field with the same name, if any. +/// Puts `name` into `names_slice` at the next index (that being the current length of `map`). +/// Also inserts the name into `map`. If there is an existing field with this name, its index +/// is returned. Otherwise, `null` is returned. pub fn addFieldName( ip: *InternPool, - extra: Local.Extra, - names_map: MapIndex, - names_start: u32, + names: NullTerminatedString.Slice, + map: MapIndex, name: NullTerminatedString, ) ?u32 { - const extra_items = extra.view().items(.@"0"); - const map = names_map.get(ip); - const field_index = map.count(); - const strings = extra_items[names_start..][0..field_index]; - const adapter: NullTerminatedString.Adapter = .{ .strings = @ptrCast(strings) }; - const gop = map.getOrPutAssumeCapacityAdapted(name, adapter); + const m = map.get(ip); + const field_idx = m.count(); + const names_slice = names.get(ip); + names_slice[field_idx] = name; + const adapter: NullTerminatedString.Adapter = .{ .strings = names_slice[0..field_idx] }; + const gop = m.getOrPutAssumeCapacityAdapted(name, adapter); if (gop.found_existing) return @intCast(gop.index); - extra_items[names_start + field_index] = @intFromEnum(name); + assert(gop.index == field_idx); + return null; +} + +/// Like `addFieldName`, but instead of adding a field name to a struct, union, or enum, adds a +/// field tag value for an enum. +pub fn addFieldTagValue( + ip: *InternPool, + values: Index.Slice, + map: MapIndex, + value: Index, +) ?u32 { + const m = map.get(ip); + const field_idx = m.count(); + const values_slice = values.get(ip); + values_slice[field_idx] = value; + const adapter: Index.Adapter = .{ .indexes = values_slice[0..field_idx] }; + const gop = m.getOrPutAssumeCapacityAdapted(value, adapter); + if (gop.found_existing) return @intCast(gop.index); + assert(gop.index == field_idx); return null; } @@ -12295,6 +12691,7 @@ pub fn resolveStructLayout( has_no_possible_value: bool, has_one_possible_value: bool, comptime_only: bool, + has_runtime_bits: bool, ) void { const unwrapped_index = struct_type.unwrap(ip); @@ -12311,6 +12708,7 @@ pub fn resolveStructLayout( flags.has_no_possible_value = has_no_possible_value; flags.has_one_possible_value = has_one_possible_value; flags.comptime_only = comptime_only; + flags.has_runtime_bits = has_runtime_bits; flags.alignment = alignment; } @@ -12322,12 +12720,14 @@ pub fn resolveUnionLayout( ip: *InternPool, io: Io, union_type: Index, + enum_tag_type: Index, size: u32, padding: u32, alignment: Alignment, has_no_possible_value: bool, has_one_possible_value: bool, comptime_only: bool, + has_runtime_bits: bool, ) void { const unwrapped_index = union_type.unwrap(ip); @@ -12339,17 +12739,24 @@ pub fn resolveUnionLayout( const item = unwrapped_index.getItem(ip); assert(item.tag == .type_union); + extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnion, "enum_tag_type").?] = @intFromEnum(enum_tag_type); extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnion, "size").?] = size; extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnion, "padding").?] = padding; const flags: *Tag.TypeUnion.Flags = @ptrCast(&extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnion, "flags").?]); flags.has_no_possible_value = has_no_possible_value; flags.has_one_possible_value = has_one_possible_value; flags.comptime_only = comptime_only; + flags.has_runtime_bits = has_runtime_bits; flags.alignment = alignment; } /// Asserts that `struct_type` is a packed struct type. -pub fn resolvePackedStructBackingInt(ip: *InternPool, io: Io, struct_type: Index, backing_int_type: Index) void { +pub fn resolvePackedStructLayout( + ip: *InternPool, + io: Io, + struct_type: Index, + backing_int_type: Index, +) void { const unwrapped_index = struct_type.unwrap(ip); const local = ip.getLocal(unwrapped_index.tid); @@ -12371,7 +12778,13 @@ pub fn resolvePackedStructBackingInt(ip: *InternPool, io: Io, struct_type: Index } /// Asserts that `union_type` is a packed union type. -pub fn resolvePackedUnionBackingInt(ip: *InternPool, io: Io, union_type: Index, backing_int_type: Index) void { +pub fn resolvePackedUnionLayout( + ip: *InternPool, + io: Io, + union_type: Index, + enum_tag_type: Index, + backing_int_type: Index, +) void { const unwrapped_index = union_type.unwrap(ip); const local = ip.getLocal(unwrapped_index.tid); @@ -12387,5 +12800,32 @@ pub fn resolvePackedUnionBackingInt(ip: *InternPool, io: Io, union_type: Index, else => unreachable, } + extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnionPacked, "enum_tag_type").?] = @intFromEnum(enum_tag_type); extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnionPacked, "backing_int_type").?] = @intFromEnum(backing_int_type); } + +/// Asserts that `enum_type` is an enum type. +pub fn resolveEnumLayout( + ip: *InternPool, + io: Io, + enum_type: Index, + int_tag_type: Index, +) void { + const unwrapped_index = enum_type.unwrap(ip); + + const local = ip.getLocal(unwrapped_index.tid); + local.mutate.extra.mutex.lockUncancelable(io); + defer local.mutate.extra.mutex.unlock(io); + + const extra_items = local.shared.extra.view().items(.@"0"); + const item = unwrapped_index.getItem(ip); + switch (item.tag) { + .type_enum_auto, + .type_enum_explicit, + .type_enum_nonexhaustive, + => {}, + else => unreachable, + } + + extra_items[item.data + std.meta.fieldIndex(Tag.TypeEnum, "int_tag_type").?] = @intFromEnum(int_tag_type); +} diff --git a/src/Sema.zig b/src/Sema.zig index 55fb718a45b989ecac821626638dde9a98ab99b5..d1482b86812e6168d0e4fd75ba90f41016903244 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -397,7 +397,7 @@ pub const Block = struct { /// The name of the current "context" for naming namespace types. /// The interpretation of this depends on the name strategy in ZIR, but the name /// is always incorporated into the type name somehow. - /// See `Sema.createTypeName`. + /// See `Sema.setTypeName`. type_name_ctx: InternPool.NullTerminatedString, /// Create a `LazySrcLoc` based on an `Offset` from the code being analyzed in this block. @@ -1158,7 +1158,7 @@ fn analyzeBodyInner( }, inst }); } - const air_inst: Air.Inst.Ref = inst: switch (tags[@intFromEnum(inst)]) { + const air_ref: Air.Inst.Ref = inst: switch (tags[@intFromEnum(inst)]) { // zig fmt: off .alloc => try sema.zirAlloc(block, inst), .alloc_inferred => try sema.zirAllocInferred(block, true), @@ -1991,31 +1991,33 @@ fn analyzeBodyInner( break :blk .void_value; }, }; - if (sema.isNoReturn(air_inst)) { + if (sema.isNoReturn(air_ref)) { // We're going to assume that the body itself is noreturn, so let's ensure that now assert(block.instructions.items.len > 0); assert(sema.isNoReturn(block.instructions.items[block.instructions.items.len - 1].toRef())); break; } - // - if (air_inst.toIndex()) |air_inst_index| { - switch (sema.air_instructions.items(.tag)[@intFromEnum(air_inst_index)]) { - .inferred_alloc, .inferred_alloc_comptime => {}, - else => { - assert(sema.typeOf(air_inst).onePossibleValue(pt) catch @panic("") == null); - sema.typeOf(air_inst).assertHasLayout(zcu); - }, - } - } else { - switch (tags[@intFromEnum(inst)]) { - // MLUGG TODO: do we actually *want* this exception? we could arguably simplify things without it - // e.g. analyzeNavVal could stop doing ensureLayoutResolved in most cases (`extern` is an exception) and instead do `assertHasLayout` - .func, .func_inferred, .func_fancy => {}, // exception: we're in a func decl, layout will get resolved in a bit by `analyzeNavVal` - else => sema.typeOf(air_inst).assertHasLayout(zcu), + + // We must resolve the layout of a type before creating a value of that type. Therefore, + // the layout of the type of `air_ref` must already be resolved. + check_type: { + if (air_ref.toIndex()) |air_inst| switch (sema.air_instructions.items(.tag)[@intFromEnum(air_inst)]) { + .inferred_alloc, .inferred_alloc_comptime => break :check_type, + else => {}, + }; + sema.typeOf(air_ref).assertHasLayout(zcu); + // If the type has an OPV, `air_ref` must be that OPV: there is no other interned value + // it could be, and it would be a bug for the value to not be comptime-known when it has + // an OPV. Behind a `std.debug.runtime_safety` check because `onePossibleValue` mutates + // the InternPool so cannot be optimized out. + if (std.debug.runtime_safety) { + if (try sema.typeOf(air_ref).onePossibleValue(pt)) |opv| { + assert(air_ref == Air.Inst.Ref.fromValue(opv)); + } } } - // - map.putAssumeCapacity(inst, air_inst); + + map.putAssumeCapacity(inst, air_ref); i += 1; } } @@ -2097,7 +2099,7 @@ pub fn resolveConstStringIntern( fn resolveTypeOrPoison(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !?Type { const air_inst = try sema.resolveInst(zir_ref); - const ty = try sema.analyzeAsType(block, src, air_inst); + const ty = try sema.analyzeAsType(block, src, .type, air_inst); if (ty.isGenericPoison()) return null; return ty; } @@ -2216,11 +2218,12 @@ pub fn analyzeAsType( sema: *Sema, block: *Block, src: LazySrcLoc, + reason: std.zig.SimpleComptimeReason, air_inst: Air.Inst.Ref, ) !Type { const wanted_type: Type = .type; const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src); - const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, .{ .simple = .type }); + const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, .{ .simple = reason }); return val.toType(); } @@ -4112,9 +4115,11 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. /// or error union pointed to, initializing these pointers along the way. /// Given a `*E!?T`, returns a (valid) `*T`. /// May invalidate already-stored payload data. +/// Asserts that the layout of the pointer child type is already resolved. fn optEuBasePtrInit(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, src: LazySrcLoc) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; + sema.typeOf(ptr).childType(zcu).assertHasLayout(zcu); var base_ptr = ptr; while (true) switch (sema.typeOf(base_ptr).childType(zcu).zigTypeTag(zcu)) { .error_union => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true), @@ -4128,6 +4133,7 @@ fn optEuBasePtrInit(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, src: LazySrcL fn zirOptEuBasePtrInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const ptr = try sema.resolveInst(un_node.operand); + try sema.ensureLayoutResolved(sema.typeOf(ptr).childType(sema.pt.zcu)); return sema.optEuBasePtrInit(block, ptr, block.nodeOffset(un_node.src_node)); } @@ -4513,7 +4519,7 @@ fn validateStructInit( if (struct_ty.structFieldIsComptime(i, zcu)) continue; if (!struct_ty.isTuple(zcu)) { - try sema.ensureFieldInitsResolved(struct_ty); + try sema.ensureStructDefaultsResolved(struct_ty); } const default_val = struct_ty.structFieldDefaultValue(i, zcu) orelse { @@ -5737,7 +5743,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void } if (zcu.llvm_object != null and options.linkage == .internal) return; const export_ty = Value.fromInterned(uav.val).typeOf(zcu); - if (!try sema.validateExternType(export_ty, .other)) { + if (!export_ty.validateExtern(.other, zcu)) { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(src, "unable to export type '{f}'", .{export_ty.fmt(pt)}); errdefer msg.destroy(sema.gpa); @@ -5789,7 +5795,7 @@ pub fn analyzeExport( const exported_nav = ip.getNav(exported_nav_index); const export_ty: Type = .fromInterned(exported_nav.typeOf(ip)); - if (!try sema.validateExternType(export_ty, .other)) { + if (!export_ty.validateExtern(.other, zcu)) { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(src, "unable to export type '{f}'", .{export_ty.fmt(pt)}); errdefer msg.destroy(gpa); @@ -5827,7 +5833,7 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void { .nav_val, .nav_ty, .type_layout, - .type_inits, + .struct_defaults, .memoized_state, => return, // does nothing outside a function }; @@ -5846,7 +5852,7 @@ fn zirDisableIntrinsics(sema: *Sema) CompileError!void { .nav_val, .nav_ty, .type_layout, - .type_inits, + .struct_defaults, .memoized_state, => return, // does nothing outside a function }; @@ -6729,8 +6735,28 @@ fn analyzeCall( } else func_src; const func_ty_info = zcu.typeToFunc(func_ty).?; - // MLUGG TODO: this isn't quite the check i want. this includes inline functions, which aren't *generic*... - const func_is_generic = !func_ty.fnHasRuntimeBits(zcu); + const any_comptime_params = func_ty_info.comptime_bits != 0 or ct: { + for (func_ty_info.param_types.get(ip)) |param_ty| { + if (Type.fromInterned(param_ty).comptimeOnly(zcu)) break :ct true; + } + break :ct Type.fromInterned(func_ty_info.return_type).comptimeOnly(zcu); + }; + const any_generic_types = generic: { + for (func_ty_info.param_types.get(ip)) |param_ty| { + if (param_ty == .generic_poison_type) break :generic true; + } + const ret_ty: Type = .fromInterned(func_ty_info.return_type); + if (ret_ty.toIntern() == .generic_poison_type) { + break :generic true; + } + if (ret_ty.zigTypeTag(zcu) == .error_union and + ret_ty.errorUnionPayload(zcu).toIntern() == .generic_poison_type) + { + break :generic true; + } + break :generic false; + }; + if (!callConvIsCallable(func_ty_info.cc)) { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg( @@ -6766,7 +6792,7 @@ fn analyzeCall( else => unreachable, } else .{ null, false }; - if (func_is_generic and func_val == null) { + if ((any_generic_types or any_comptime_params) and func_val == null) { return sema.failWithNeededComptime(block, func_src, .{ .simple = .generic_call_target }); } @@ -6815,13 +6841,13 @@ fn analyzeCall( // This is the `inst_map` used when evaluating generic parameters and return types. var generic_inst_map: InstMap = .{}; defer generic_inst_map.deinit(gpa); - if (func_is_generic) { + if (any_generic_types) { try generic_inst_map.ensureSpaceForInstructions(gpa, fn_zir_info.param_body); } // This exists so that `generic_block` below can include a "called from here" note back to this // call site when analyzing generic parameter/return types. - var generic_inlining: Block.Inlining = if (func_is_generic) .{ + var generic_inlining: Block.Inlining = if (any_generic_types) .{ .call_block = block, .call_src = call_src, .func = func_val.?.toIntern(), @@ -6834,7 +6860,7 @@ fn analyzeCall( // This is the block in which we evaluate generic function components: that is, generic parameter // types and the generic return type. This must not be used if the function is not generic. // `comptime_reason` is set as needed. - var generic_block: Block = if (func_is_generic) .{ + var generic_block: Block = if (any_generic_types) .{ .parent = null, .sema = sema, .namespace = fn_nav.analysis.?.namespace, @@ -6843,9 +6869,9 @@ fn analyzeCall( .src_base_inst = fn_nav.analysis.?.zir_index, .type_name_ctx = fn_nav.fqn, } else undefined; - defer if (func_is_generic) generic_block.instructions.deinit(gpa); + defer if (any_generic_types) generic_block.instructions.deinit(gpa); - if (func_is_generic) { + if (any_generic_types) { // We certainly depend on the generic owner's signature! try sema.declareDependency(.{ .src_hash = fn_tracked_inst }); } @@ -6857,7 +6883,7 @@ fn analyzeCall( if (raw != .generic_poison_type) break :ty .fromInterned(raw); // We must discover the generic parameter type. - assert(func_is_generic); + assert(any_generic_types); const param_inst_idx = fn_zir_info.param_body[arg_idx]; const param_inst = fn_zir.instructions.get(@intFromEnum(param_inst_idx)); switch (param_inst.tag) { @@ -6888,7 +6914,7 @@ fn analyzeCall( } }; const ty_ref = try sema.resolveInlineBody(&generic_block, body, param_inst_idx); - const param_ty = try sema.analyzeAsType(&generic_block, param_src, ty_ref); + const param_ty = try sema.analyzeAsType(&generic_block, param_src, .fn_param_types, ty_ref); if (!param_ty.isValidParamType(zcu)) { const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else ""; @@ -6906,7 +6932,7 @@ fn analyzeCall( return arg.*; // terminate analysis here } - if (func_is_generic) { + if (any_generic_types) { // We need to put the argument into `generic_inst_map` so that other parameters can refer to it. const param_inst_idx = fn_zir_info.param_body[arg_idx]; const declared_comptime = if (std.math.cast(u5, arg_idx)) |i| func_ty_info.paramIsComptime(i) else false; @@ -6948,7 +6974,7 @@ fn analyzeCall( // calls (where it should be the IES of the instantiation). However, it's how we print this // in error messages. const resolved_ret_ty: Type = ret_ty: { - if (!func_is_generic) break :ret_ty .fromInterned(func_ty_info.return_type); + if (!any_generic_types) break :ret_ty .fromInterned(func_ty_info.return_type); const maybe_poison_bare = if (fn_zir_info.inferred_error_set) maybe_poison: { break :maybe_poison ip.errorUnionPayload(func_ty_info.return_type); @@ -6958,7 +6984,7 @@ fn analyzeCall( // Evaluate the generic return type. As with generic parameters, we switch out `sema.code` and `sema.inst_map`. - assert(func_is_generic); + assert(any_generic_types); const old_code = sema.code; const old_inst_map = sema.inst_map; @@ -6981,7 +7007,7 @@ fn analyzeCall( } else bare: { assert(fn_zir_info.ret_ty_body.len != 0); const ty_ref = try sema.resolveInlineBody(&generic_block, fn_zir_info.ret_ty_body, fn_zir_inst); - break :bare try sema.analyzeAsType(&generic_block, func_ret_ty_src, ty_ref); + break :bare try sema.analyzeAsType(&generic_block, func_ret_ty_src, .fn_ret_ty, ty_ref); }; assert(bare_ty.toIntern() != .generic_poison_type); @@ -7035,7 +7061,7 @@ fn analyzeCall( }); if (func_ty_info.cc == .auto) { switch (sema.owner.unwrap()) { - .@"comptime", .nav_ty, .nav_val, .type_layout, .type_inits, .memoized_state => {}, + .@"comptime", .nav_ty, .nav_val, .type_layout, .struct_defaults, .memoized_state => {}, .func => |owner_func| ip.funcSetHasErrorTrace(io, owner_func, true), } } @@ -7043,7 +7069,7 @@ fn analyzeCall( try sema.validateRuntimeValue(block, args_info.argSrc(block, arg_idx), arg); } const runtime_func: Air.Inst.Ref, const runtime_args: []const Air.Inst.Ref = func: { - if (!func_is_generic) break :func .{ callee, args }; + if (!any_generic_types and !any_comptime_params) break :func .{ callee, args }; // Instantiate the generic function! @@ -7512,9 +7538,7 @@ fn zirArrayInitElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil assert(indexable_ty.isIndexable(zcu)); // validated by a previous instruction const elem_ty = switch (indexable_ty.zigTypeTag(zcu)) { .@"struct" => indexable_ty.fieldType(@intFromEnum(bin.rhs), zcu), - .array, .vector => indexable_ty.childType(zcu), - .pointer => indexable_ty.indexablePtrElem(zcu), - else => unreachable, + else => indexable_ty.indexableElem(zcu), }; return .fromType(elem_ty); } @@ -7835,8 +7859,8 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr }; return sema.failWithOwnedErrorMsg(block, msg); } - const lhs_ty = try sema.analyzeAsType(block, lhs_src, lhs); - const rhs_ty = try sema.analyzeAsType(block, rhs_src, rhs); + const lhs_ty = try sema.analyzeAsType(block, lhs_src, .type, lhs); + const rhs_ty = try sema.analyzeAsType(block, rhs_src, .type, rhs); if (lhs_ty.zigTypeTag(zcu) != .error_set) return sema.fail(block, lhs_src, "expected error set type, found '{f}'", .{lhs_ty.fmt(pt)}); if (rhs_ty.zigTypeTag(zcu) != .error_set) @@ -8017,12 +8041,13 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError if (dest_ty.zigTypeTag(zcu) != .@"enum") { return sema.fail(block, src, "expected enum, found '{f}'", .{dest_ty.fmt(pt)}); } + try sema.ensureLayoutResolved(dest_ty); _ = try sema.checkIntType(block, operand_src, operand_ty); if (try sema.resolveValue(operand)) |int_val| { if (dest_ty.isNonexhaustiveEnum(zcu)) { const int_tag_ty = dest_ty.intTagType(zcu); - if (try sema.intFitsInType(int_val, int_tag_ty, null)) { + if (int_val.intFitsInType(int_tag_ty, null, zcu)) { return Air.internedToRef((try pt.getCoerced(int_val, dest_ty)).toIntern()); } return sema.fail(block, src, "int value '{f}' out of range of non-exhaustive enum '{f}'", .{ @@ -8077,10 +8102,14 @@ fn zirOptionalPayloadPtr( const optional_ptr = try sema.resolveInst(inst_data.operand); const src = block.nodeOffset(inst_data.src_node); + const ptr_ty = sema.typeOf(optional_ptr); + assert(ptr_ty.zigTypeTag(sema.pt.zcu) == .pointer); + try sema.ensureLayoutResolved(ptr_ty.childType(sema.pt.zcu)); + return sema.analyzeOptionalPayloadPtr(block, src, optional_ptr, safety_check, false); } -/// MLUGG TODO: pre-resolved child? +/// Asserts that the layout of the pointer child type is already resolved. fn analyzeOptionalPayloadPtr( sema: *Sema, block: *Block, @@ -8095,12 +8124,12 @@ fn analyzeOptionalPayloadPtr( assert(optional_ptr_ty.zigTypeTag(zcu) == .pointer); const opt_type = optional_ptr_ty.childType(zcu); + opt_type.assertHasLayout(zcu); if (opt_type.zigTypeTag(zcu) != .optional) { return sema.failWithExpectedOptionalType(block, src, opt_type); } const child_type = opt_type.optionalChild(zcu); - try sema.ensureLayoutResolved(child_type); const child_pointer = try pt.ptrType(.{ .child = child_type.toIntern(), .flags = .{ @@ -8283,10 +8312,14 @@ fn zirErrUnionPayloadPtr( const operand = try sema.resolveInst(inst_data.operand); const src = block.nodeOffset(inst_data.src_node); + const ptr_ty = sema.typeOf(operand); + assert(ptr_ty.zigTypeTag(sema.pt.zcu) == .pointer); + try sema.ensureLayoutResolved(ptr_ty.childType(sema.pt.zcu)); + return sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false); } -/// MLUGG TODO LAYOUT: already-resolved child? +/// Asserts that the layout of the pointer child type is already resolved. fn analyzeErrUnionPayloadPtr( sema: *Sema, block: *Block, @@ -8307,8 +8340,8 @@ fn analyzeErrUnionPayloadPtr( } const err_union_ty = operand_ty.childType(zcu); + err_union_ty.assertHasLayout(zcu); const payload_ty = err_union_ty.errorUnionPayload(zcu); - try sema.ensureLayoutResolved(payload_ty); const operand_pointer_ty = try pt.ptrType(.{ .child = payload_ty.toIntern(), .flags = .{ @@ -8744,7 +8777,7 @@ fn checkParamTypeCommon( } if (!param_ty.isGenericPoison() and !target_util.fnCallConvAllowsZigTypes(cc) and - !try sema.validateExternType(param_ty, .param_ty)) + !param_ty.validateExtern(.param_ty, zcu)) { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(param_src, "parameter of type '{f}' not allowed in function with calling convention '{s}'", .{ @@ -8818,7 +8851,7 @@ fn checkReturnTypeAndCallConvCommon( } if (!bare_ret_ty.isGenericPoison() and !target_util.fnCallConvAllowsZigTypes(@"callconv") and - (inferred_error_set or !try sema.validateExternType(bare_ret_ty, .ret_ty))) + (inferred_error_set or !bare_ret_ty.validateExtern(.ret_ty, zcu))) { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(ret_ty_src, "return type '{s}{f}' not allowed in function with calling convention '{s}'", .{ @@ -9042,7 +9075,7 @@ fn funcCommon( if (inferred_error_set) { assert(has_body); - return .fromIntern(try ip.getFuncDeclIes(gpa, io, pt.tid, .{ + const func_val: Value = .fromInterned(try ip.getFuncDeclIes(gpa, io, pt.tid, .{ .owner_nav = sema.owner.unwrap().nav_val, .param_types = param_types, @@ -9059,6 +9092,8 @@ fn funcCommon( .lbrace_column = @as(u16, @truncate(src_locs.columns)), .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)), })); + try sema.ensureLayoutResolved(func_val.typeOf(zcu)); + return .fromValue(func_val); } const func_ty = try ip.getFuncType(gpa, io, pt.tid, .{ @@ -9072,6 +9107,7 @@ fn funcCommon( }); if (has_body) { + try sema.ensureLayoutResolved(.fromInterned(func_ty)); return .fromIntern(try ip.getFuncDecl(gpa, io, pt.tid, .{ .owner_nav = sema.owner.unwrap().nav_val, .ty = func_ty, @@ -9109,7 +9145,7 @@ fn zirParam( } const param_ty_inst = try sema.resolveInlineBody(block, body, inst); - break :ty try sema.analyzeAsType(block, src, param_ty_inst); + break :ty try sema.analyzeAsType(block, src, .fn_param_types, param_ty_inst); }; try block.params.append(sema.arena, .{ @@ -9948,6 +9984,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp err_union_ty.fmt(pt), }); } + try sema.ensureLayoutResolved(err_union_ty); const non_err_cond = if (non_err_case.operand_is_ref) try sema.analyzePtrIsNonErr(block, operand_src, eu_maybe_ptr) @@ -12924,7 +12961,7 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. const res_ty: InternPool.Index = b: { if (extra.res_ty == .none) break :b .none; const res_ty_inst = try sema.resolveInst(extra.res_ty); - const res_ty = try sema.analyzeAsType(block, operand_src, res_ty_inst); + const res_ty = try sema.analyzeAsType(block, operand_src, .type, res_ty_inst); if (res_ty.isGenericPoison()) break :b .none; break :b res_ty.toIntern(); }; @@ -15683,8 +15720,8 @@ fn zirCmpEq( return block.addBinOp(air_tag, lhs, rhs); } if (lhs_ty_tag == .type and rhs_ty_tag == .type) { - const lhs_as_type = try sema.analyzeAsType(block, lhs_src, lhs); - const rhs_as_type = try sema.analyzeAsType(block, rhs_src, rhs); + const lhs_as_type = try sema.analyzeAsType(block, lhs_src, .type, lhs); + const rhs_as_type = try sema.analyzeAsType(block, rhs_src, .type, rhs); return if (lhs_as_type.eql(rhs_as_type, zcu) == (op == .eq)) .bool_true else .bool_false; } return sema.analyzeCmp(block, src, lhs, rhs, op, lhs_src, rhs_src, true); @@ -15979,16 +16016,7 @@ fn zirThis( extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { _ = extended; - const zcu = sema.pt.zcu; - const namespace = zcu.namespacePtr(block.namespace); - - switch (zcu.intern_pool.indexToKey(namespace.owner_type)) { - .opaque_type, .struct_type, .union_type => {}, - // Enum inits are resolved eagerly. TODO MLUGG: honestly i don't think they SHOULD be lol - .enum_type => try sema.ensureFieldInitsResolved(.fromInterned(namespace.owner_type)), - else => unreachable, - } - return .fromIntern(namespace.owner_type); + return .fromIntern(sema.pt.zcu.namespacePtr(block.namespace).owner_type); } fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { @@ -16224,12 +16252,12 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const type_info_ty = try sema.getBuiltinType(src, .Type); const type_info_tag_ty = type_info_ty.unionTagType(zcu).?; + try sema.ensureLayoutResolved(ty); + if (ty.typeDeclInst(zcu)) |type_decl_inst| { try sema.declareDependency(.{ .namespace = type_decl_inst }); } - try sema.ensureLayoutResolved(ty); - switch (ty.zigTypeTag(zcu)) { .type, .void, @@ -16240,7 +16268,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .undefined, .null, .enum_literal, - => |type_info_tag| return unionInitFromEnumTag(sema, block, src, type_info_ty, @intFromEnum(type_info_tag), .void_value), + => |type_info_tag| return .fromValue(try pt.unionValue( + type_info_ty, + Value.uninterpret(type_info_tag, type_info_tag_ty, pt) catch |err| switch (err) { + error.TypeMismatch => @panic("std.builtin is corrupt"), + error.OutOfMemory => |e| return e, + }, + .void, + )), .@"fn" => { const fn_info_ty = try sema.getBuiltinType(src, .@"Type.Fn"); @@ -16248,9 +16283,11 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const func_ty_info = zcu.typeToFunc(ty).?; const param_vals = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len); + var func_is_generic = false; for (param_vals, 0..) |*param_val, i| { const param_ty = func_ty_info.param_types.get(ip)[i]; const is_generic = param_ty == .generic_poison_type; + if (is_generic or Type.fromInterned(param_ty).comptimeOnly(zcu)) func_is_generic = true; const param_ty_val = try pt.intern(.{ .opt = .{ .ty = try pt.intern(.{ .opt_type = .type_type }), .val = if (is_generic) .none else param_ty, @@ -16300,18 +16337,21 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai } }); }; + const ret_ty_is_generic = generic: { + const ret_ty: Type = .fromInterned(func_ty_info.return_type); + if (ret_ty.toIntern() == .generic_poison_type) break :generic true; + if (ret_ty.zigTypeTag(zcu) == .error_union) { + if (ret_ty.errorUnionPayload(zcu).toIntern() == .generic_poison_type) { + break :generic true; + } + } + break :generic false; + }; + if (ret_ty_is_generic) func_is_generic = true; + const ret_ty_opt = try pt.intern(.{ .opt = .{ .ty = try pt.intern(.{ .opt_type = .type_type }), - .val = opt_val: { - const ret_ty: Type = .fromInterned(func_ty_info.return_type); - if (ret_ty.toIntern() == .generic_poison_type) break :opt_val .none; - if (ret_ty.zigTypeTag(zcu) == .error_union) { - if (ret_ty.errorUnionPayload(zcu).toIntern() == .generic_poison_type) { - break :opt_val .none; - } - } - break :opt_val ret_ty.toIntern(); - }, + .val = if (ret_ty_is_generic) .none else func_ty_info.return_type, } }); const callconv_ty = try sema.getBuiltinType(src, .CallingConvention); @@ -16320,9 +16360,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai error.OutOfMemory => |e| return e, }; - // MLUGG TODO - const func_is_generic = false; - const field_values: [5]InternPool.Index = .{ // calling_convention: CallingConvention, callconv_val.toIntern(), @@ -16837,7 +16874,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .struct_type => ip.loadStructType(ty.toIntern()), else => unreachable, }; - try sema.ensureFieldInitsResolved(ty); // can't do this sooner, since it's not allowed on tuples + try sema.ensureStructDefaultsResolved(ty); // can't do this sooner, since it's not allowed on tuples struct_field_vals = try gpa.alloc(InternPool.Index, struct_type.field_types.len); for (struct_field_vals, 0..) |*field_val, field_index| { @@ -18193,7 +18230,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const elem_ty = blk: { const air_inst = try sema.resolveInst(extra.data.elem_type); - const ty = sema.analyzeAsType(block, elem_ty_src, air_inst) catch |err| { + const ty = sema.analyzeAsType(block, elem_ty_src, .type, air_inst) catch |err| { if (err == error.AnalysisFail and sema.err != null and sema.typeOf(air_inst).isSinglePointer(zcu)) { try sema.errNote(elem_ty_src, sema.err.?, "use '.*' to dereference pointer", .{}); } @@ -18274,7 +18311,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air } else if (inst_data.size != .one and elem_ty.zigTypeTag(zcu) == .@"opaque") { return sema.fail(block, elem_ty_src, "indexable pointer to opaque type '{f}' not allowed", .{elem_ty.fmt(pt)}); } else if (inst_data.size == .c) { - if (!try sema.validateExternType(elem_ty, .other)) { + if (!elem_ty.validateExtern(.other, zcu)) { const msg = msg: { const msg = try sema.errMsg(elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{f}'", .{elem_ty.fmt(pt)}); errdefer msg.destroy(sema.gpa); @@ -18288,11 +18325,11 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air } } - if (host_size != 0 and !elem_ty.packable(zcu)) { - return sema.failWithOwnedErrorMsg(block, msg: { + if (host_size != 0) { + if (elem_ty.unpackable(zcu)) |reason| return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(elem_ty_src, "bit-pointer cannot refer to value of type '{f}'", .{elem_ty.fmt(pt)}); errdefer msg.destroy(sema.gpa); - try sema.explainWhyTypeIsNotPackable(msg, elem_ty_src, elem_ty); + try sema.explainWhyTypeIsUnpackable(msg, elem_ty_src, reason); break :msg msg; }); } @@ -18455,63 +18492,32 @@ fn arrayInitEmpty(sema: *Sema, block: *Block, src: LazySrcLoc, obj_ty: Type) Com fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const pt = sema.pt; + const zcu = pt.zcu; + const ip = &zcu.intern_pool; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0); const field_src = block.builtinCallArgSrc(inst_data.src_node, 1); - const init_src = block.builtinCallArgSrc(inst_data.src_node, 2); + const payload_src = block.builtinCallArgSrc(inst_data.src_node, 2); const extra = sema.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data; const union_ty = try sema.resolveType(block, ty_src, extra.union_type); if (union_ty.zigTypeTag(pt.zcu) != .@"union") { return sema.fail(block, ty_src, "expected union type, found '{f}'", .{union_ty.fmt(pt)}); } + union_ty.assertHasLayout(zcu); // from a previous `field_type_ref` instruction const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .simple = .union_field_names }); - const init = try sema.resolveInst(extra.init); - return sema.unionInit(block, init, init_src, union_ty, ty_src, field_name, field_src); -} - -fn unionInit( - sema: *Sema, - block: *Block, - uncasted_init: Air.Inst.Ref, - init_src: LazySrcLoc, - union_ty: Type, - union_ty_src: LazySrcLoc, - field_name: InternPool.NullTerminatedString, - field_src: LazySrcLoc, -) CompileError!Air.Inst.Ref { - const pt = sema.pt; - const zcu = pt.zcu; - const ip = &zcu.intern_pool; const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_src); const field_ty: Type = .fromInterned(zcu.typeToUnion(union_ty).?.field_types.get(ip)[field_index]); - const init = try sema.coerce(block, field_ty, uncasted_init, init_src); - _ = union_ty_src; - return unionInitFromEnumTag(sema, block, init_src, union_ty, field_index, init); -} -fn unionInitFromEnumTag( - sema: *Sema, - block: *Block, - init_src: LazySrcLoc, - union_ty: Type, - field_index: u32, - init: Air.Inst.Ref, -) !Air.Inst.Ref { - const pt = sema.pt; - const zcu = pt.zcu; + const payload = try sema.coerce(block, field_ty, try sema.resolveInst(extra.init), payload_src); - if (try sema.resolveValue(init)) |init_val| { + if (try sema.resolveValue(payload)) |payload_val| { const tag_ty = union_ty.unionTagTypeHypothetical(zcu); const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index); - return Air.internedToRef((try pt.internUnion(.{ - .ty = union_ty.toIntern(), - .tag = tag_val.toIntern(), - .val = init_val.toIntern(), - }))); + return .fromValue(try pt.unionValue(union_ty, tag_val, payload_val)); } - try sema.requireRuntimeBlock(block, init_src, null); - return block.addUnionInit(union_ty, field_index, init); + try sema.requireRuntimeBlock(block, payload_src, null); + return block.addUnionInit(union_ty, field_index, payload); } fn zirStructInit( @@ -18588,9 +18594,6 @@ fn zirStructInit( const field_ty = resolved_ty.fieldType(field_index, zcu); field_inits[field_index] = try sema.coerce(block, field_ty, uncoerced_init, field_src); if (resolved_ty.structFieldIsComptime(field_index, zcu)) { - if (!resolved_ty.isTuple(zcu)) { - try sema.ensureFieldInitsResolved(resolved_ty); - } const default_value = (try resolved_ty.structFieldValueComptime(pt, field_index)).?; const init_val = (try sema.resolveValue(field_inits[field_index])) orelse { return sema.failWithNeededComptime(block, field_src, .{ .simple = .stored_to_comptime_field }); @@ -18744,7 +18747,12 @@ fn finishStructInit( continue; } - try sema.ensureFieldInitsResolved(struct_ty); + if (struct_type.field_is_comptime_bits.get(ip, i)) { + field_inits[i] = .fromIntern(struct_type.field_defaults.get(ip)[i]); + continue; + } + + try sema.ensureStructDefaultsResolved(struct_ty); const field_default: InternPool.Index = d: { if (struct_type.field_defaults.len == 0) break :d .none; @@ -18935,55 +18943,54 @@ fn structInitAnon( break :hash hasher.final(); }; const tracked_inst = try block.trackZir(inst); - const struct_ty: Type = switch (try ip.getStructType(gpa, io, pt.tid, .{ + const struct_ty: Type = switch (try ip.getReifiedStructType(gpa, io, pt.tid, .{ + .zir_index = tracked_inst, + .type_hash = type_hash, .fields_len = extra_data.fields_len, .layout = .auto, - .explicit_packed_backing_type = .none, .any_comptime_fields = any_values, .any_field_defaults = any_values, .any_field_aligns = false, - .key = .{ .reified = .{ - .zir_index = tracked_inst, - .type_hash = type_hash, - } }, + .packed_backing_int_type = .none, })) { + .existing => |ty| .fromInterned(ty), .wip => |wip| ty: { errdefer wip.cancel(ip, pt.tid); - // MLUGG TODO obvs this sux - const anon_prefix = (try sema.createTypeName(block, .anon, "struct", inst)).anon_prefix; - wip.setName(ip, try ip.getOrPutStringFmt(gpa, io, pt.tid, "{s}_{d}", .{ anon_prefix, @intFromEnum(wip.index) }, .no_embedded_nulls), .none); + try sema.setTypeName(block, &wip, .anon, "struct", inst); - const struct_type = ip.loadStructType(wip.index); - - for (names, values) |name, init_val| { - assert(wip.nextField(ip, name, init_val != .none) == null); // AstGen validated no duplicates for us + // Reified structs have field information populated immediately. + @memcpy(wip.field_names.get(ip), names); + @memcpy(wip.field_types.get(ip), types); + if (any_values) { + @memcpy(wip.field_values.get(ip), values); + @memset(wip.field_is_comptime_bits.getAll(ip), 0); + for (values, 0..) |val, field_index| { + if (val == .none) continue; + const bit_bag_index = field_index / 32; + const mask = @as(u32, 1) << @intCast(field_index % 32); + wip.field_is_comptime_bits.getAll(ip)[bit_bag_index] |= mask; + } } - // Populating these means the type is already resolved; we don't need to add it to `zcu.outdated` or anything. - // That's important because type resolution relies on types being declared. - @memcpy(struct_type.field_types.get(ip), types); - @memcpy(struct_type.field_defaults.get(ip), if (any_values) values else @as([]const InternPool.Index, &.{})); - - try type_resolution.finishStructLayout(sema, block, src, wip.index, &struct_type); - const new_namespace_index = try pt.createNamespace(.{ .parent = block.namespace.toOptional(), .owner_type = wip.index, .file_scope = block.getFileScopeIndex(zcu), .generation = zcu.generation, }); - codegen_type: { - if (zcu.comp.config.use_llvm) break :codegen_type; - if (block.ownerModule().strip) break :codegen_type; - zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); - try zcu.comp.queueJob(.{ .link_type = wip.index }); - } if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); + + try zcu.outdated.ensureUnusedCapacity(gpa, 1); + try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); + errdefer comptime unreachable; // because we don't remove the `outdated` entries + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); + zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); + break :ty .fromInterned(wip.finish(ip, new_namespace_index)); }, - .existing => |ty| .fromInterned(ty), }; try sema.addTypeReferenceEntry(src, struct_ty); + try sema.ensureLayoutResolved(struct_ty); _ = opt_runtime_index orelse { const struct_val = try pt.aggregateValue(struct_ty, values); @@ -19338,6 +19345,7 @@ fn fieldType( const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; + aggregate_ty.assertHasLayout(zcu); var cur_ty = aggregate_ty; while (true) { switch (cur_ty.zigTypeTag(zcu)) { @@ -19397,7 +19405,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { .func => |func| if (ip.funcAnalysisUnordered(func).has_error_trace and block.ownerModule().error_tracing) { return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty); }, - .@"comptime", .nav_ty, .nav_val, .type_layout, .type_inits, .memoized_state => {}, + .@"comptime", .nav_ty, .nav_val, .type_layout, .struct_defaults, .memoized_state => {}, } return Air.internedToRef(try pt.intern(.{ .opt = .{ .ty = opt_ptr_stack_trace_ty.toIntern(), @@ -19823,7 +19831,7 @@ fn zirReifyPointer( else => {}, } - if (size == .c and !try sema.validateExternType(elem_ty, .other)) { + if (size == .c and !elem_ty.validateExtern(.other, zcu)) { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(src, "C pointers cannot point to non-C-ABI-compatible type '{f}'", .{elem_ty.fmt(pt)}); errdefer msg.destroy(gpa); @@ -19988,6 +19996,7 @@ fn zirReifyStruct( const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small); const extra = sema.code.extraData(Zir.Inst.ReifyStruct, extended.operand).data; const tracked_inst = try block.trackZir(inst); + const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .nodeOffset(.zero), @@ -20039,7 +20048,7 @@ fn zirReifyStruct( const backing_int_ty_uncoerced = try sema.resolveInst(extra.backing_ty); const backing_int_ty_coerced = try sema.coerce(block, .optional_type, backing_int_ty_uncoerced, backing_ty_src); - const backing_int_ty_val = try sema.resolveConstDefinedValue(block, backing_ty_src, backing_int_ty_coerced, .{ .simple = .type }); + const backing_int_ty_val = try sema.resolveConstDefinedValue(block, backing_ty_src, backing_int_ty_coerced, .{ .simple = .packed_struct_backing_int_type }); const field_names_uncoerced = try sema.resolveInst(extra.field_names); const field_names_coerced = try sema.coerce(block, .slice_const_slice_const_u8, field_names_uncoerced, field_names_src); @@ -20079,19 +20088,30 @@ fn zirReifyStruct( return sema.failWithUseOfUndef(block, backing_ty_src, null); } - // The validation work here is non-trivial, and it's possible the type already exists. - // So in this first pass, let's just construct a hash to optimize for this case. If the - // inputs turn out to be invalid, we can cancel the WIP type later. + // Most validation of this type happens during type resolution. We basically need to do the work + // which AstGen would normally do. An exception is checking for duplicate field names, which is + // handled by type resolution---it just simplifies some logic a little. + + // As well as validation, we're going to gather some information about the fields, and construct + // a hash representing the inputs for deduplication purposes. var any_comptime_fields = false; - var any_default_inits = false; - var any_aligned_fields = false; + var any_field_defaults = false; + var any_field_aligns = false; - // For deduplication purposes, we must create a hash including all details of this type. // TODO: use a longer hash! var hasher = std.hash.Wyhash.init(0); std.hash.autoHash(&hasher, layout); std.hash.autoHash(&hasher, backing_int_ty_val); + + const backing_int_ty: ?Type = if (backing_int_ty_val.optionalValue(zcu)) |backing| ty: { + switch (layout) { + .auto, .@"extern" => return sema.fail(block, backing_ty_src, "non-packed struct does not support backing integer type", .{}), + .@"packed" => {}, + } + break :ty backing.toType(); + } else null; + // The field *type* array has already been deduplicated for us thanks to the InternPool! std.hash.autoHash(&hasher, field_types_arr); // However, for field names and attributes, we need to actually iterate the individual fields, @@ -20126,201 +20146,126 @@ fn zirReifyStruct( field_attrs_src, .{ .simple = .struct_field_default_value }, ); + if (deref_val.canMutateComptimeVarState(zcu)) { + return sema.failWithContainsReferenceToComptimeVar(block, field_attrs_src, field_name, "field default value", deref_val); + } + any_field_defaults = true; break :d deref_val.toIntern(); }; + if (field_attr_comptime.toBool()) { + if (field_default == .none) { + return sema.fail(block, field_attrs_src, "comptime field without default initialization value", .{}); + } + if (layout != .auto) { + return sema.fail(block, field_attrs_src, "{t} struct fields cannot be marked comptime", .{layout}); + } + any_comptime_fields = true; + } + + if (field_attr_align.optionalValue(zcu)) |align_val| { + if (layout == .@"packed") { + return sema.fail(block, field_attrs_src, "packed struct fields cannot be aligned", .{}); + } + // Trigger a compile error if the alignment is invalid. + _ = try sema.validateAlign(block, field_attrs_src, align_val.toUnsignedInt(zcu)); + any_field_aligns = true; + } + std.hash.autoHash(&hasher, .{ field_name, field_attr_comptime, field_attr_align, field_default, }); - - if (field_attr_comptime.toBool()) any_comptime_fields = true; - if (field_attr_align.optionalValue(zcu)) |_| any_aligned_fields = true; - if (field_default != .none) any_default_inits = true; - } - - // Some basic validation to avoid a bogus `getStructType` call... - const backing_int_ty: ?Type = if (backing_int_ty_val.optionalValue(zcu)) |backing| ty: { - switch (layout) { - .auto, .@"extern" => return sema.fail(block, backing_ty_src, "non-packed struct does not support backing integer type", .{}), - .@"packed" => {}, - } - break :ty backing.toType(); - } else null; - if (any_aligned_fields and layout == .@"packed") { - return sema.fail(block, field_attrs_src, "packed struct fields cannot be aligned", .{}); - } - if (any_comptime_fields and layout != .auto) { - return sema.fail(block, field_attrs_src, "{t} struct fields cannot be marked comptime", .{layout}); } - const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{ + switch (try ip.getReifiedStructType(gpa, io, pt.tid, .{ + .zir_index = tracked_inst, + .type_hash = hasher.final(), .fields_len = @intCast(fields_len), .layout = layout, - .explicit_packed_backing_type = if (backing_int_ty) |t| t.toIntern() else .none, .any_comptime_fields = any_comptime_fields, - .any_field_defaults = any_default_inits, - .any_field_aligns = any_aligned_fields, - .key = .{ .reified = .{ - .zir_index = tracked_inst, - .type_hash = hasher.final(), - } }, + .any_field_defaults = any_field_defaults, + .any_field_aligns = any_field_aligns, + .packed_backing_int_type = if (backing_int_ty) |ty| ty.toIntern() else .none, })) { - .wip => |wip| wip, .existing => |ty| { try sema.addTypeReferenceEntry(src, .fromInterned(ty)); return .fromIntern(ty); }, - }; - errdefer wip_ty.cancel(ip, pt.tid); + .wip => |wip| { + errdefer wip.cancel(ip, pt.tid); + try sema.setTypeName(block, &wip, name_strategy, "struct", inst); + for (0..fields_len) |field_idx| { + const field_name_val = try field_names_arr.elemValue(pt, field_idx); + const field_attrs_val = try field_attrs_arr.elemValue(pt, field_idx); - _ = try (try sema.createTypeName( - block, - name_strategy, - "struct", - inst, - )).apply(&wip_ty, pt); + // No source location or reason; first loop checked this is valid. + const field_name = try sema.sliceToIpString(block, .unneeded, field_name_val, undefined); + wip.field_names.get(ip)[field_idx] = field_name; - const wip_struct_type = ip.loadStructType(wip_ty.index); + const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType(); + wip.field_types.get(ip)[field_idx] = field_ty.toIntern(); - for (0..fields_len) |field_idx| { - const field_name_val = try field_names_arr.elemValue(pt, field_idx); - const field_attrs_val = try field_attrs_arr.elemValue(pt, field_idx); + const field_attr_comptime = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex( + std.builtin.Type.StructField.Attributes, + "comptime", + ).?); + const field_attr_align = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex( + std.builtin.Type.StructField.Attributes, + "align", + ).?); + const field_attr_default_value_ptr = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex( + std.builtin.Type.StructField.Attributes, + "default_value_ptr", + ).?); - // Don't pass a reason; first loop acts as a check that this is valid. - const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined); - const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType(); - const field_attr_comptime = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex( - std.builtin.Type.StructField.Attributes, - "comptime", - ).?); - const field_attr_align = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex( - std.builtin.Type.StructField.Attributes, - "align", - ).?); - const field_attr_default_value_ptr = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex( - std.builtin.Type.StructField.Attributes, - "default_value_ptr", - ).?); + if (field_attr_comptime.toBool()) { + const bit_bag_index = field_idx / 32; + const mask = @as(u32, 1) << @intCast(field_idx % 32); + wip.field_is_comptime_bits.getAll(ip)[bit_bag_index] |= mask; + } - if (wip_ty.nextField(ip, field_name, field_attr_comptime.toBool())) |prev_index| { - _ = prev_index; // TODO: better source location - return sema.fail(block, field_names_src, "duplicate struct field name {f}", .{field_name.fmt(ip)}); - } + if (field_attr_default_value_ptr.optionalValue(zcu)) |ptr_val| { + const ptr_ty = try pt.singleConstPtrType(field_ty); + // No source location; first loop checked this is valid. + const deref_val = (try sema.pointerDeref(block, .unneeded, ptr_val, ptr_ty)).?; + wip.field_values.get(ip)[field_idx] = deref_val.toIntern(); + } else if (any_field_defaults) { + wip.field_values.get(ip)[field_idx] = .none; + } - const field_default: InternPool.Index = d: { - const ptr_val = field_attr_default_value_ptr.optionalValue(zcu) orelse break :d .none; - assert(any_default_inits); - const ptr_ty = try pt.singleConstPtrType(field_ty); - // The first loop checked that this is comptime-dereferencable. - const deref_val = (try sema.pointerDeref(block, field_attrs_src, ptr_val, ptr_ty)).?; - // ...but we've not checked this yet! - if (deref_val.canMutateComptimeVarState(zcu)) { - return sema.failWithContainsReferenceToComptimeVar(block, field_attrs_src, field_name, "field default value", deref_val); + if (field_attr_align.optionalValue(zcu)) |field_align_val| { + const bytes = field_align_val.toUnsignedInt(zcu); + // No source location; first loop checked this is valid. + const a = try sema.validateAlign(block, .unneeded, bytes); + wip.field_aligns.get(ip)[field_idx] = a; + } else if (any_field_aligns) { + wip.field_aligns.get(ip)[field_idx] = .none; + } } - break :d deref_val.toIntern(); - }; - if (field_attr_comptime.toBool() and field_default == .none) { - return sema.fail(block, field_attrs_src, "comptime field without default initialization value", .{}); - } - - switch (field_ty.zigTypeTag(zcu)) { - .@"opaque" => return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(field_types_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); - errdefer msg.destroy(gpa); - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }), - .noreturn => return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(field_types_src, "struct fields cannot be 'noreturn'", .{}); - errdefer msg.destroy(gpa); - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }), - else => {}, - } - - switch (layout) { - .auto => {}, - .@"extern" => if (!try sema.validateExternType(field_ty, .struct_field)) { - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(field_types_src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); - errdefer msg.destroy(gpa); - try sema.explainWhyTypeIsNotExtern(msg, field_types_src, field_ty, .struct_field); - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }); - }, - .@"packed" => if (!field_ty.packable(zcu)) { - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(field_types_src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); - errdefer msg.destroy(gpa); - try sema.explainWhyTypeIsNotPackable(msg, field_types_src, field_ty); - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }); - }, - } - - wip_struct_type.field_types.get(ip)[field_idx] = field_ty.toIntern(); - if (field_default != .none) { - wip_struct_type.field_defaults.get(ip)[field_idx] = field_default; - } - - if (field_attr_align.optionalValue(zcu)) |field_align_val| { - assert(layout != .@"packed"); - const bytes = field_align_val.toUnsignedInt(zcu); - const a = try sema.validateAlign(block, field_attrs_src, bytes); - wip_struct_type.field_aligns.get(ip)[field_idx] = a; - } else if (any_aligned_fields) { - assert(layout != .@"packed"); - wip_struct_type.field_aligns.get(ip)[field_idx] = .none; - } - } - - if (layout == .@"packed") { - var field_bits: u64 = 0; - for (0..fields_len) |field_idx| { - const field_ty: Type = .fromInterned(wip_struct_type.field_types.get(ip)[field_idx]); - try sema.ensureLayoutResolved(field_ty); - field_bits += field_ty.bitSize(zcu); - } - try type_resolution.resolvePackedStructBackingInt( - sema, - block, - field_bits, - .fromInterned(wip_ty.index), - &wip_struct_type, - ); - } else { - try type_resolution.finishStructLayout( - sema, - block, - src, - wip_ty.index, - &wip_struct_type, - ); - } - - const new_namespace_index = try pt.createNamespace(.{ - .parent = block.namespace.toOptional(), - .owner_type = wip_ty.index, - .file_scope = block.getFileScopeIndex(zcu), - .generation = zcu.generation, - }); - - codegen_type: { - if (zcu.comp.config.use_llvm) break :codegen_type; - if (block.ownerModule().strip) break :codegen_type; - zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); - try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); + const new_namespace_index = try pt.createNamespace(.{ + .parent = block.namespace.toOptional(), + .owner_type = wip.index, + .file_scope = block.getFileScopeIndex(zcu), + .generation = zcu.generation, + }); + try sema.addTypeReferenceEntry(src, .fromInterned(wip.index)); + if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); + // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind + try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) }); + + try zcu.outdated.ensureUnusedCapacity(gpa, 1); + try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); + errdefer comptime unreachable; // because we don't remove the `outdated` entries + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); + zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); + + return .fromIntern(wip.finish(ip, new_namespace_index)); + }, } - try sema.addTypeReferenceEntry(src, .fromInterned(wip_ty.index)); - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); - return .fromIntern(wip_ty.finish(ip, new_namespace_index)); } fn zirReifyUnion( @@ -20390,7 +20335,10 @@ fn zirReifyUnion( const arg_ty_uncoerced = try sema.resolveInst(extra.arg_ty); const arg_ty_coerced = try sema.coerce(block, .optional_type, arg_ty_uncoerced, arg_ty_src); - const arg_ty_val = try sema.resolveConstDefinedValue(block, arg_ty_src, arg_ty_coerced, .{ .simple = .type }); + const arg_ty_val = try sema.resolveConstDefinedValue(block, arg_ty_src, arg_ty_coerced, switch (layout) { + .@"packed" => .{ .simple = .packed_union_backing_int_type }, + .auto, .@"extern" => .{ .simple = .union_enum_tag_type }, + }); const field_names_uncoerced = try sema.resolveInst(extra.field_names); const field_names_coerced = try sema.coerce(block, .slice_const_slice_const_u8, field_names_uncoerced, field_names_src); @@ -20430,39 +20378,20 @@ fn zirReifyUnion( return sema.failWithUseOfUndef(block, arg_ty_src, null); } - // The validation work here is non-trivial, and it's possible the type already exists. - // So in this first pass, let's just construct a hash to optimize for this case. If the - // inputs turn out to be invalid, we can cancel the WIP type later. + // Most validation of this type happens during type resolution. We basically need to do the work + // which AstGen would normally do. An exception is checking for duplicate field names, which is + // handled by type resolution---it just simplifies some logic a little. - var any_aligned_fields = false; + // As well as validation, we're going to gather some information about the fields, and construct + // a hash representing the inputs for deduplication purposes. + + var any_field_aligns = false; - // For deduplication purposes, we must create a hash including all details of this type. // TODO: use a longer hash! var hasher = std.hash.Wyhash.init(0); std.hash.autoHash(&hasher, layout); std.hash.autoHash(&hasher, arg_ty_val); - // `field_types_arr` and `field_attrs_arr` are already deduplicated by the InternPool! - std.hash.autoHash(&hasher, field_types_arr); - std.hash.autoHash(&hasher, field_attrs_arr); - // However, for field names, we need to iterate the individual fields, because the pointers (the - // names are slices) mean that distinct values could ultimately result in the same union type. - for (0..fields_len) |field_idx| { - const field_name_val = try field_names_arr.elemValue(pt, field_idx); - const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, .{ .simple = .union_field_names }); - std.hash.autoHash(&hasher, field_name); - const field_attrs = try sema.interpretBuiltinType( - block, - field_attrs_src, - try field_attrs_arr.elemValue(pt, field_idx), - std.builtin.Type.UnionField.Attributes, - ); - if (field_attrs.@"align" != null) { - any_aligned_fields = true; - } - } - - // Some basic validation to avoid a bogus `getUnionType` call... const explicit_tag_ty: ?Type, const explicit_packed_backing_type: ?Type = ty: { const arg_ty = arg_ty_val.optionalValue(zcu) orelse break :ty .{ null, null }; switch (layout) { @@ -20471,235 +20400,101 @@ fn zirReifyUnion( .auto => break :ty .{ arg_ty.toType(), null }, } }; - if (any_aligned_fields and layout == .@"packed") { - return sema.fail(block, field_attrs_src, "packed union fields cannot be aligned", .{}); + + // `field_types_arr` and `field_attrs_arr` are already deduplicated by the InternPool! + std.hash.autoHash(&hasher, field_types_arr); + std.hash.autoHash(&hasher, field_attrs_arr); + // However, for field names, we need to iterate the individual fields, because the pointers (the + // names are slices) mean that distinct values could ultimately result in the same union type. + for (0..fields_len) |field_idx| { + const field_name_val = try field_names_arr.elemValue(pt, field_idx); + const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, .{ .simple = .union_field_names }); + std.hash.autoHash(&hasher, field_name); + + const field_attrs = try sema.interpretBuiltinType( + block, + field_attrs_src, + try field_attrs_arr.elemValue(pt, field_idx), + std.builtin.Type.UnionField.Attributes, + ); + if (field_attrs.@"align") |bytes| { + if (layout == .@"packed") { + return sema.fail(block, field_attrs_src, "packed union fields cannot be aligned", .{}); + } + // Trigger a compile error if the alignment is invalid. + _ = try sema.validateAlign(block, field_attrs_src, bytes); + any_field_aligns = true; + } } - const wip_ty = switch (try ip.getUnionType(gpa, io, pt.tid, .{ + switch (try ip.getReifiedUnionType(gpa, io, pt.tid, .{ + .zir_index = tracked_inst, + .type_hash = hasher.final(), .fields_len = @intCast(fields_len), .layout = layout, - .explicit_packed_backing_type = if (explicit_packed_backing_type) |t| t.toIntern() else .none, + .any_field_aligns = any_field_aligns, .runtime_tag = rt: { if (explicit_tag_ty != null) break :rt .tagged; if (layout == .auto and block.wantSafeTypes()) break :rt .safety; break :rt .none; }, - .have_explicit_enum_tag = explicit_tag_ty != null, - .any_field_aligns = any_aligned_fields, - .key = .{ .reified = .{ - .zir_index = tracked_inst, - .type_hash = hasher.final(), - } }, + .enum_tag_type = if (explicit_tag_ty) |ty| ty.toIntern() else .none, + .packed_backing_int_type = if (explicit_packed_backing_type) |ty| ty.toIntern() else .none, })) { - .wip => |wip| wip, .existing => |ty| { try sema.addTypeReferenceEntry(src, .fromInterned(ty)); return .fromIntern(ty); }, - }; - errdefer wip_ty.cancel(ip, pt.tid); - - const type_name = try (try sema.createTypeName( - block, - name_strategy, - "union", - inst, - )).apply(&wip_ty, pt); - - const loaded_union = ip.loadUnionType(wip_ty.index); - - const generated_tag_ty: InternPool.Index = if (explicit_tag_ty) |enum_tag_ty| generated_tag: { - if (enum_tag_ty.zigTypeTag(zcu) != .@"enum") { - return sema.fail(block, arg_ty_src, "tag type must be an enum type", .{}); - } - - const tag_ty_fields_len = enum_tag_ty.enumFieldCount(zcu); - - for (0..fields_len) |field_idx| { - const field_name_val = try field_names_arr.elemValue(pt, field_idx); - // Don't pass a reason; first loop acts as a check that this is valid. - const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined); - - if (field_idx >= tag_ty_fields_len) { - return sema.fail(block, field_names_src, "no field named '{f}' in enum '{f}'", .{ - field_name.fmt(ip), enum_tag_ty.fmt(pt), - }); - } - - const enum_field_name = enum_tag_ty.enumFieldName(field_idx, zcu); - if (enum_field_name != field_name) { - return sema.fail(block, field_names_src, "union field name '{f}' does not match enum field name '{f}'", .{ - field_name.fmt(ip), enum_field_name.fmt(ip), - }); - } - } - if (tag_ty_fields_len > fields_len) return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(field_names_src, "{d} enum fields missing in union", .{ - tag_ty_fields_len - fields_len, - }); - errdefer msg.destroy(gpa); - for (fields_len..tag_ty_fields_len) |enum_field_idx| { - try sema.addFieldErrNote(enum_tag_ty, enum_field_idx, msg, "field '{f}' missing, declared here", .{ - enum_tag_ty.enumFieldName(enum_field_idx, zcu).fmt(ip), - }); + .wip => |wip| { + errdefer wip.cancel(ip, pt.tid); + try sema.setTypeName(block, &wip, name_strategy, "union", inst); + + for (0..fields_len) |field_idx| { + const field_name_val = try field_names_arr.elemValue(pt, field_idx); + // No source location or reason; first loop checked this is valid. + const field_name = try sema.sliceToIpString(block, .unneeded, field_name_val, undefined); + wip.field_names.get(ip)[field_idx] = field_name; + + const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType(); + wip.field_types.get(ip)[field_idx] = field_ty.toIntern(); + + // No source location; first loop checked this is valid. + const field_attrs = try sema.interpretBuiltinType( + block, + .unneeded, + try field_attrs_arr.elemValue(pt, field_idx), + std.builtin.Type.UnionField.Attributes, + ); + if (field_attrs.@"align") |bytes| { + // No source location; first loop checked this is valid. + const a = try sema.validateAlign(block, .unneeded, bytes); + wip.field_aligns.get(ip)[field_idx] = a; + } else if (any_field_aligns) { + wip.field_aligns.get(ip)[field_idx] = .none; + } } - try sema.addDeclaredHereNote(msg, enum_tag_ty); - break :msg msg; - }); - wip_ty.setTagType(ip, enum_tag_ty.toIntern()); - break :generated_tag .none; - } else generated_tag: { - // Generate the union's hypothetical tag type. - const wip_tag_ty = switch (try ip.getEnumType(gpa, io, pt.tid, .{ - .fields_len = @intCast(fields_len), - .explicit_int_tag_type = .none, - .nonexhaustive = false, - .key = .{ .generated_union_tag = wip_ty.index }, - })) { - .existing => unreachable, // enum type is keyed on this union type which we're only just creating - .wip => |wip_tag_ty| wip_tag_ty, - }; - errdefer wip_tag_ty.cancel(ip, pt.tid); - - // Set its name based on the union's name - _ = wip_tag_ty.setName(ip, try ip.getOrPutStringFmt( - gpa, - io, - pt.tid, - "@typeInfo({f}).@\"union\".tag_type.?", - .{type_name.fmt(ip)}, - .no_embedded_nulls, - ), .none); - // Populate its fields (and report any duplicates) - for (0..fields_len) |field_idx| { - const field_name_val = try field_names_arr.elemValue(pt, field_idx); - // Don't pass a reason; first loop acts as a check that this is valid. - const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined); - if (wip_tag_ty.nextField(ip, field_name, false)) |prev_field_idx| return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(src, "duplicate union field '{f}' at index '{d}", .{ field_name.fmt(ip), field_idx }); - errdefer msg.destroy(gpa); - try sema.errNote(src, msg, "previous field at index '{d}'", .{prev_field_idx}); - break :msg msg; + const new_namespace_index = try pt.createNamespace(.{ + .parent = block.namespace.toOptional(), + .owner_type = wip.index, + .file_scope = block.getFileScopeIndex(zcu), + .generation = zcu.generation, }); - } - - // Populate the enum tag type's *integer* tag type - wip_tag_ty.setTagType(ip, int_tag_ty: { - // Infer the int tag type from the field count - const bits = Type.smallestUnsignedBits(fields_len -| 1); - break :int_tag_ty (try pt.intType(.unsigned, bits)).toIntern(); - }); - - // Lastly, it needs a dummy namespace - const enum_tag_type_namespace = try pt.createNamespace(.{ - .parent = block.namespace.toOptional(), - .owner_type = wip_tag_ty.index, - .file_scope = block.getFileScopeIndex(zcu), - .generation = zcu.generation, - }); - errdefer pt.destroyNamespace(enum_tag_type_namespace); - - wip_ty.setTagType(ip, wip_tag_ty.index); + if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); + try sema.addTypeReferenceEntry(src, .fromInterned(wip.index)); - break :generated_tag wip_tag_ty.finish(ip, enum_tag_type_namespace); - }; - // If we fail to create the union type, we must delete the generated enum tag type, since it - // would hold a reference to the deleted union. - errdefer if (generated_tag_ty != .none) ip.remove(pt.tid, generated_tag_ty); + // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind + try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) }); - for (0..fields_len) |field_idx| { - const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType(); - const field_attrs = try sema.interpretBuiltinType( - block, - field_attrs_src, - try field_attrs_arr.elemValue(pt, field_idx), - std.builtin.Type.UnionField.Attributes, - ); + try zcu.outdated.ensureUnusedCapacity(gpa, 1); + try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); + errdefer comptime unreachable; // because we don't remove the `outdated` entry + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); + zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); - if (field_ty.zigTypeTag(zcu) == .@"opaque") { - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(field_types_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); - errdefer msg.destroy(gpa); - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }); - } - - switch (layout) { - .auto => {}, - .@"extern" => if (!try sema.validateExternType(field_ty, .union_field)) { - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(field_types_src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); - errdefer msg.destroy(gpa); - - try sema.explainWhyTypeIsNotExtern(msg, field_types_src, field_ty, .union_field); - - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }); - }, - .@"packed" => if (!field_ty.packable(zcu)) { - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(field_types_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); - errdefer msg.destroy(gpa); - - try sema.explainWhyTypeIsNotPackable(msg, field_types_src, field_ty); - - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }); - }, - } - - loaded_union.field_types.get(ip)[field_idx] = field_ty.toIntern(); - if (field_attrs.@"align") |bytes| { - assert(layout != .@"packed"); - const a = try sema.validateAlign(block, field_attrs_src, bytes); - loaded_union.field_aligns.get(ip)[field_idx] = a; - } else if (any_aligned_fields) { - assert(layout != .@"packed"); - loaded_union.field_aligns.get(ip)[field_idx] = .none; - } - } - - if (layout == .@"packed") { - try type_resolution.resolvePackedUnionBackingInt( - sema, - block, - .fromInterned(wip_ty.index), - &loaded_union, - true, - ); - } else { - try type_resolution.finishUnionLayout( - sema, - block, - src, - wip_ty.index, - &loaded_union, - explicit_tag_ty orelse .fromInterned(generated_tag_ty), - ); - } - - const new_namespace_index = try pt.createNamespace(.{ - .parent = block.namespace.toOptional(), - .owner_type = wip_ty.index, - .file_scope = block.getFileScopeIndex(zcu), - .generation = zcu.generation, - }); - - codegen_type: { - if (zcu.comp.config.use_llvm) break :codegen_type; - if (block.ownerModule().strip) break :codegen_type; - zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); - try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); - } - try sema.addTypeReferenceEntry(src, .fromInterned(wip_ty.index)); - if (zcu.comp.debugIncremental()) { - try zcu.incremental_debug_state.newType(zcu, wip_ty.index); + return .fromIntern(wip.finish(ip, new_namespace_index)); + }, } - return .fromIntern(wip_ty.finish(ip, new_namespace_index)); } fn zirReifyEnum( @@ -20754,10 +20549,10 @@ fn zirReifyEnum( const enum_mode_ty = try sema.getBuiltinType(mode_src, .@"Type.Enum.Mode"); - const tag_ty = try sema.resolveType(block, tag_ty_src, extra.tag_ty); - if (tag_ty.zigTypeTag(zcu) != .int) { - return sema.fail(block, tag_ty_src, "tag type must be an integer type", .{}); - } + const tag_ty_uncoerced = try sema.resolveInst(extra.tag_ty); + const tag_ty_coerced = try sema.coerce(block, .type, tag_ty_uncoerced, tag_ty_src); + const tag_ty_val = try sema.resolveConstDefinedValue(block, tag_ty_src, tag_ty_coerced, .{ .simple = .enum_int_tag_type }); + const tag_ty = tag_ty_val.toType(); const mode_uncoerced = try sema.resolveInst(extra.mode); const mode_coerced = try sema.coerce(block, enum_mode_ty, mode_uncoerced, mode_src); @@ -20790,11 +20585,13 @@ fn zirReifyEnum( } // We don't need to check `field_names_arr`, because `sliceToIpString` will check that for us. - // The validation work here is non-trivial, and it's possible the type already exists. - // So in this first pass, let's just construct a hash to optimize for this case. If the - // inputs turn out to be invalid, we can cancel the WIP type later. + // Most validation of this type happens during type resolution. We basically need to do the work + // which AstGen would normally do. An exception is checking for duplicate field names, which is + // handled by type resolution---it just simplifies some logic a little. + + // As well as validation, we're going to gather some information about the fields, and construct + // a hash representing the inputs for deduplication purposes. - // For deduplication purposes, we must create a hash including all details of this type. // TODO: use a longer hash! var hasher = std.hash.Wyhash.init(0); std.hash.autoHash(&hasher, tag_ty.toIntern()); @@ -20810,85 +20607,55 @@ fn zirReifyEnum( std.hash.autoHash(&hasher, field_name); } - const wip_ty = switch (try ip.getEnumType(gpa, io, pt.tid, .{ + switch (try ip.getReifiedEnumType(gpa, io, pt.tid, .{ + .zir_index = tracked_inst, + .type_hash = hasher.final(), .fields_len = @intCast(fields_len), - .explicit_int_tag_type = tag_ty.toIntern(), .nonexhaustive = nonexhaustive, - .key = .{ .reified = .{ - .zir_index = tracked_inst, - .type_hash = hasher.final(), - } }, + .int_tag_type = tag_ty.toIntern(), })) { - .wip => |wip| wip, .existing => |ty| { try sema.addTypeReferenceEntry(src, .fromInterned(ty)); return .fromIntern(ty); }, - }; - errdefer wip_ty.cancel(ip, pt.tid); + .wip => |wip| { + errdefer wip.cancel(ip, pt.tid); - _ = try (try sema.createTypeName( - block, - name_strategy, - "enum", - inst, - )).apply(&wip_ty, pt); + try sema.setTypeName(block, &wip, name_strategy, "enum", inst); - for (0..fields_len) |field_idx| { - const field_name_val = try field_names_arr.elemValue(pt, field_idx); - // Don't pass a reason; first loop acts as a check that this is valid. - const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined); - if (wip_ty.nextField(ip, field_name, false)) |prev_field_idx| return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(field_names_src, "duplicate enum field '{f}' at index '{d}'", .{ field_name.fmt(ip), field_idx }); - errdefer msg.destroy(gpa); - try sema.errNote(field_names_src, msg, "previous field at index '{d}'", .{prev_field_idx}); - break :msg msg; - }); - } + // Populate field names and values. Duplicate checking will be handled by type resolution. + for (0..fields_len) |field_index| { + const field_name_val = try field_names_arr.elemValue(pt, field_index); + // No source location or reason; first loop checked this is valid. + const field_name = try sema.sliceToIpString(block, .unneeded, field_name_val, undefined); + wip.field_names.get(ip)[field_index] = field_name; - const enum_obj = ip.loadEnumType(wip_ty.index); - const field_value_map = enum_obj.field_value_map.unwrap().?; - for (0..fields_len) |field_idx| { - const field_val = try field_values_arr.elemValue(pt, field_idx); - const field_values = enum_obj.field_values.get(ip); - field_values[field_idx] = field_val.toIntern(); - const adapter: InternPool.Index.Adapter = .{ .indexes = field_values[0..field_idx] }; - const gop = field_value_map.get(ip).getOrPutAssumeCapacityAdapted(field_val.toIntern(), adapter); - if (gop.found_existing) return sema.failWithOwnedErrorMsg(block, msg: { - const field_names = enum_obj.field_names.get(ip); - const this_field_name = field_names[field_idx]; - const prev_field_name = field_names[gop.index]; - const msg = try sema.errMsg(field_names_src, "duplicate enum tag value '{f}' in field '{f}'", .{ - field_val.fmtValueSema(pt, sema), - this_field_name.fmt(ip), + const field_val = try field_values_arr.elemValue(pt, field_index); + wip.field_values.get(ip)[field_index] = field_val.toIntern(); + } + + const new_namespace_index = try pt.createNamespace(.{ + .parent = block.namespace.toOptional(), + .owner_type = wip.index, + .file_scope = block.getFileScopeIndex(zcu), + .generation = zcu.generation, }); - errdefer msg.destroy(gpa); - try sema.errNote(field_names_src, msg, "previous usage in field '{f}'", .{prev_field_name.fmt(ip)}); - break :msg msg; - }); - } - if (nonexhaustive and fields_len > 1 and std.math.log2_int(u64, fields_len) == tag_ty.bitSize(zcu)) { - return sema.fail(block, src, "non-exhaustive enum specified every value", .{}); - } + try sema.addTypeReferenceEntry(src, .fromInterned(wip.index)); + if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - const new_namespace_index = try pt.createNamespace(.{ - .parent = block.namespace.toOptional(), - .owner_type = wip_ty.index, - .file_scope = block.getFileScopeIndex(zcu), - .generation = zcu.generation, - }); + // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind + try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) }); - codegen_type: { - if (zcu.comp.config.use_llvm) break :codegen_type; - if (block.ownerModule().strip) break :codegen_type; - zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); - try zcu.comp.queueJob(.{ .link_type = wip_ty.index }); - } + try zcu.outdated.ensureUnusedCapacity(gpa, 1); + try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); + errdefer comptime unreachable; // because we don't remove the `outdated` entry + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); + zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); - try sema.addTypeReferenceEntry(src, .fromInterned(wip_ty.index)); - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index); - return .fromIntern(wip_ty.finish(ip, new_namespace_index)); + return .fromIntern(wip.finish(ip, new_namespace_index)); + }, + } } fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref { @@ -20909,7 +20676,7 @@ fn zirCVaArg(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C const va_list_ref = try sema.resolveVaListRef(block, va_list_src, extra.lhs); const arg_ty = try sema.resolveType(block, ty_src, extra.rhs); - if (!try sema.validateExternType(arg_ty, .param_ty)) { + if (!arg_ty.validateExtern(.param_ty, sema.pt.zcu)) { const msg = msg: { const msg = try sema.errMsg(ty_src, "cannot get '{f}' from variadic argument", .{arg_ty.fmt(sema.pt)}); errdefer msg.destroy(sema.gpa); @@ -24205,8 +23972,8 @@ fn zirMemcpy( return sema.failWithOwnedErrorMsg(block, msg); } - const dest_elem_ty = dest_ty.indexablePtrElem(zcu); - const src_elem_ty = src_ty.indexablePtrElem(zcu); + const dest_elem_ty = dest_ty.indexableElem(zcu); + const src_elem_ty = src_ty.indexableElem(zcu); try sema.ensureLayoutResolved(dest_elem_ty); try sema.ensureLayoutResolved(src_elem_ty); @@ -24906,7 +24673,7 @@ fn zirBuiltinExtern( if (!ty.isPtrAtRuntime(zcu)) { return sema.fail(block, ty_src, "expected (optional) pointer", .{}); } - if (!try sema.validateExternType(ty, .other)) { + if (!ty.validateExtern(.other, zcu)) { const msg = msg: { const msg = try sema.errMsg(ty_src, "extern symbol cannot have type '{f}'", .{ty.fmt(pt)}); errdefer msg.destroy(sema.gpa); @@ -24954,7 +24721,7 @@ fn zirBuiltinExtern( // So, for now, just use our containing `declaration`. .zir_index = switch (sema.owner.unwrap()) { .@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index, - .type_layout, .type_inits => |owner_ty| Type.fromInterned(owner_ty).typeDeclInstAllowGeneratedTag(zcu).?, + .type_layout, .struct_defaults => |owner_ty| Type.fromInterned(owner_ty).typeDeclInstAllowGeneratedTag(zcu).?, .memoized_state => unreachable, .nav_ty, .nav_val => |nav| ip.getNav(nav).analysis.?.zir_index, .func => |func| zir_index: { @@ -25060,6 +24827,7 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD // Values are handled here. .calling_convention_c => { const callconv_ty = try sema.getBuiltinType(src, .CallingConvention); + // Cannot use `Value.uninterpret` because `c` is a *declaration* whose value depends on the target. return try sema.namespaceLookupVal( block, src, @@ -25068,17 +24836,15 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD ) orelse @panic("std.builtin is corrupt"); }, .calling_convention_inline => { - comptime assert(@typeInfo(std.builtin.CallingConvention.Tag).@"enum".tag_type == u8); const callconv_ty = try sema.getBuiltinType(src, .CallingConvention); - const callconv_tag_ty = callconv_ty.unionTagType(zcu) orelse @panic("std.builtin is corrupt"); - const inline_tag_val = try pt.enumValue( - callconv_tag_ty, - (try pt.intValue( - .u8, - @intFromEnum(std.builtin.CallingConvention.@"inline"), - )).toIntern(), - ); - return sema.coerce(block, callconv_ty, Air.internedToRef(inline_tag_val.toIntern()), src); + return .fromValue(Value.uninterpret( + @as(std.builtin.CallingConvention, .@"inline"), + callconv_ty, + pt, + ) catch |err| switch (err) { + error.TypeMismatch => @panic("std.builtin is corrupt"), + error.OutOfMemory => |e| return e, + }); }, }; return .fromType(try sema.getBuiltinType(src, builtin_type)); @@ -25180,7 +24946,7 @@ pub fn validateVarType( const zcu = pt.zcu; var_ty.assertHasLayout(zcu); if (is_extern) { - if (!try sema.validateExternType(var_ty, .other)) { + if (!var_ty.validateExtern(.other, zcu)) { const msg = msg: { const msg = try sema.errMsg(src, "extern variable cannot have type '{f}'", .{var_ty.fmt(pt)}); errdefer msg.destroy(sema.gpa); @@ -25296,124 +25062,17 @@ fn explainWhyTypeIsComptime( } } -const ExternPosition = enum { - ret_ty, - param_ty, - union_field, - struct_field, - element, - other, -}; - -/// Returns true if `ty` is allowed in extern types. -/// Does not require `ty` to be resolved in any way. -pub fn validateExternType( - sema: *Sema, - ty: Type, - position: ExternPosition, -) !bool { - const pt = sema.pt; - const zcu = pt.zcu; - switch (ty.zigTypeTag(zcu)) { - .type, - .comptime_float, - .comptime_int, - .enum_literal, - .undefined, - .null, - .error_union, - .error_set, - .frame, - => return false, - .void => return switch (position) { - .ret_ty, - .union_field, - .struct_field, - .element, - => true, - .param_ty, - .other, - => false, - }, - .noreturn => return position == .ret_ty, - .@"opaque", - .bool, - .float, - .@"anyframe", - => return true, - .pointer => { - if (ty.isSlice(zcu)) return false; - const child_ty = ty.childType(zcu); - if (child_ty.zigTypeTag(zcu) == .@"fn") { - return ty.isConstPtr(zcu) and try sema.validateExternType(child_ty, .other); - } - return true; - }, - .int => switch (ty.intInfo(zcu).bits) { - 0, 8, 16, 32, 64, 128 => return true, - else => return false, - }, - .@"fn" => { - if (position != .other) return false; - // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI. - // The goal is to experiment with more integrated CPU/GPU code. - if (ty.fnCallingConvention(zcu) == .nvptx_kernel) { - return true; - } - return !target_util.fnCallConvAllowsZigTypes(ty.fnCallingConvention(zcu)); - }, - .@"enum" => { - const enum_obj = zcu.intern_pool.loadEnumType(ty.toIntern()); - if (!enum_obj.int_tag_is_explicit) return false; - return sema.validateExternType(.fromInterned(enum_obj.int_tag_type), position); - }, - .@"struct" => { - const struct_obj = zcu.intern_pool.loadStructType(ty.toIntern()); - return switch (struct_obj.layout) { - .auto => false, - .@"extern" => true, - .@"packed" => switch (struct_obj.packed_backing_mode) { - .auto => false, - .explicit => try sema.validateExternType(.fromInterned(struct_obj.packed_backing_int_type), position), - }, - }; - }, - .@"union" => { - const union_obj = zcu.intern_pool.loadUnionType(ty.toIntern()); - return switch (union_obj.layout) { - .auto => false, - .@"extern" => true, - .@"packed" => switch (union_obj.packed_backing_mode) { - .auto => false, - .explicit => try sema.validateExternType(.fromInterned(union_obj.packed_backing_int_type), position), - }, - }; - }, - .array => { - if (position == .ret_ty or position == .param_ty) return false; - return sema.validateExternType(ty.childType(zcu), .element); - }, - .vector => return sema.validateExternType(ty.childType(zcu), .element), - .optional => return ty.isPtrLikeOptional(zcu), - } -} - +/// Keep in sync with `Type.validateExtern`. pub fn explainWhyTypeIsNotExtern( sema: *Sema, msg: *Zcu.ErrorMsg, src_loc: LazySrcLoc, ty: Type, - position: ExternPosition, + position: Type.ExternPosition, ) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; switch (ty.zigTypeTag(zcu)) { - .@"opaque", - .bool, - .float, - .@"anyframe", - => return, - .type, .comptime_float, .comptime_int, @@ -25425,101 +25084,110 @@ pub fn explainWhyTypeIsNotExtern( .frame, => return, - .pointer => { - if (ty.isSlice(zcu)) { - try sema.errNote(src_loc, msg, "slices have no guaranteed in-memory representation", .{}); - } else { - const pointee_ty = ty.childType(zcu); - if (!ty.isConstPtr(zcu) and pointee_ty.zigTypeTag(zcu) == .@"fn") { - try sema.errNote(src_loc, msg, "pointer to extern function must be 'const'", .{}); - } - try sema.explainWhyTypeIsNotExtern(msg, src_loc, pointee_ty, .other); - } - }, - .void => try sema.errNote(src_loc, msg, "'void' is a zero bit type; for C 'void' use 'anyopaque'", .{}), + .void => try sema.errNote(src_loc, msg, "'void' is a zero bit type", .{}), .noreturn => try sema.errNote(src_loc, msg, "'noreturn' is only allowed as a return type", .{}), + + .@"opaque", + .bool, + .float, + .@"anyframe", + => unreachable, // these *are* allowed + + .pointer => if (ty.isSlice(zcu)) { + try sema.errNote(src_loc, msg, "slices have no guaranteed in-memory representation", .{}); + } else { + assert(ty.childType(zcu).zigTypeTag(zcu) == .@"fn"); + if (!ty.isConstPtr(zcu)) { + try sema.errNote(src_loc, msg, "pointer to extern function must be 'const'", .{}); + } else { + try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.childType(zcu), .other); + } + }, .int => if (!std.math.isPowerOfTwo(ty.intInfo(zcu).bits)) { try sema.errNote(src_loc, msg, "only integers with 0 or power of two bits are extern compatible", .{}); } else { try sema.errNote(src_loc, msg, "only integers with 0, 8, 16, 32, 64 and 128 bits are extern compatible", .{}); }, - .@"fn" => { - if (position != .other) { - try sema.errNote(src_loc, msg, "type has no guaranteed in-memory representation", .{}); - try sema.errNote(src_loc, msg, "use '*const ' to make a function pointer type", .{}); - return; - } - switch (ty.fnCallingConvention(zcu)) { - .auto => try sema.errNote(src_loc, msg, "extern function must specify calling convention", .{}), - .async => try sema.errNote(src_loc, msg, "async function cannot be extern", .{}), - .@"inline" => try sema.errNote(src_loc, msg, "inline function cannot be extern", .{}), - else => return, - } + .@"fn" => if (position != .other) { + try sema.errNote(src_loc, msg, "type has no guaranteed in-memory representation", .{}); + try sema.errNote(src_loc, msg, "use '*const ' to make a function pointer type", .{}); + } else switch (ty.fnCallingConvention(zcu)) { + .auto => try sema.errNote(src_loc, msg, "extern function must specify calling convention", .{}), + else => |cc| try sema.errNote(src_loc, msg, "{t} function cannot be extern", .{cc}), }, .@"enum" => { const tag_ty = ty.intTagType(zcu); try sema.errNote(src_loc, msg, "enum tag type '{f}' is not extern compatible", .{tag_ty.fmt(pt)}); try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position); }, - // MLUGG TODO: these notes are bad now (because ABI sized packed type also needs explicit backing type) - .@"struct" => try sema.errNote(src_loc, msg, "only extern structs and ABI sized packed structs are extern compatible", .{}), - .@"union" => try sema.errNote(src_loc, msg, "only extern unions and ABI sized packed unions are extern compatible", .{}), - .array => { - if (position == .ret_ty) { - return sema.errNote(src_loc, msg, "arrays are not allowed as a return type", .{}); - } else if (position == .param_ty) { - return sema.errNote(src_loc, msg, "arrays are not allowed as a parameter type", .{}); + .@"struct" => { + const struct_obj = zcu.intern_pool.loadStructType(ty.toIntern()); + switch (struct_obj.layout) { + .auto => try sema.errNote(src_loc, msg, "struct with automatic layout has no guaranteed in-memory representation", .{}), + .@"extern" => unreachable, + .@"packed" => switch (struct_obj.packed_backing_mode) { + .auto => try sema.errNote(src_loc, msg, "inferred backing integer of packed struct has unspecified signedness", .{}), + .explicit => { + const backing_int_ty: Type = .fromInterned(struct_obj.packed_backing_int_type); + try sema.errNote(src_loc, msg, "packed struct backing integer type '{f}' is not extern compatible", .{backing_int_ty.fmt(pt)}); + try sema.explainWhyTypeIsNotExtern(msg, src_loc, backing_int_ty, position); + }, + }, } - try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.childType(zcu), .element); + }, + .@"union" => { + const union_obj = zcu.intern_pool.loadStructType(ty.toIntern()); + switch (union_obj.layout) { + .auto => try sema.errNote(src_loc, msg, "union with automatic layout has no guaranteed in-memory representation", .{}), + .@"extern" => unreachable, + .@"packed" => switch (union_obj.packed_backing_mode) { + .auto => try sema.errNote(src_loc, msg, "inferred backing integer of packed union has unspecified signedness", .{}), + .explicit => { + const backing_int_ty: Type = .fromInterned(union_obj.packed_backing_int_type); + try sema.errNote(src_loc, msg, "packed union backing integer type '{f}' is not extern compatible", .{backing_int_ty.fmt(pt)}); + try sema.explainWhyTypeIsNotExtern(msg, src_loc, backing_int_ty, position); + }, + }, + } + }, + .array => switch (position) { + .ret_ty => try sema.errNote(src_loc, msg, "arrays are not allowed as a return type", .{}), + .param_ty => try sema.errNote(src_loc, msg, "arrays are not allowed as a parameter type", .{}), + else => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.childType(zcu), .element), }, .vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.childType(zcu), .element), - .optional => try sema.errNote(src_loc, msg, "only pointer like optionals are extern compatible", .{}), + .optional => try sema.errNote(src_loc, msg, "non-pointer optionals have no guaranteed in-memory representation", .{}), } } -pub fn explainWhyTypeIsNotPackable( +pub fn explainWhyTypeIsUnpackable( sema: *Sema, msg: *Zcu.ErrorMsg, - src_loc: LazySrcLoc, - ty: Type, + src: LazySrcLoc, + reason: Type.UnpackableReason, ) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; - switch (ty.zigTypeTag(zcu)) { - .void, - .bool, - .float, - .int, - .vector, - .@"enum", - => return, - .type, - .comptime_float, - .comptime_int, - .enum_literal, - .undefined, - .null, - .frame, - .noreturn, - .@"opaque", - .error_union, - .error_set, - .@"anyframe", - .optional, - .array, - => try sema.errNote(src_loc, msg, "type has no guaranteed in-memory representation", .{}), - .pointer => if (ty.isSlice(zcu)) { - try sema.errNote(src_loc, msg, "slices have no guaranteed in-memory representation", .{}); - } else { - try sema.errNote(src_loc, msg, "comptime-only pointer has no guaranteed in-memory representation", .{}); - try sema.explainWhyTypeIsComptime(msg, src_loc, ty); + switch (reason) { + .comptime_only => try sema.errNote(src, msg, "comptime-only types have no bit-packed representation", .{}), + .pointer => { + try sema.errNote(src, msg, "pointers cannot be directly bitpacked", .{}); + try sema.errNote(src, msg, "consider using 'usize' and '@intFromPtr'", .{}); }, - .@"fn" => { - try sema.errNote(src_loc, msg, "type has no guaranteed in-memory representation", .{}); - try sema.errNote(src_loc, msg, "use '*const ' to make a function pointer type", .{}); + .enum_inferred_int_tag => |enum_ty| { + const enum_src = enum_ty.srcLoc(zcu); + try sema.errNote(enum_src, msg, "integer tag type of enum is inferred", .{}); + try sema.errNote(enum_src, msg, "consider explicitly specifying the integer tag type", .{}); }, - .@"struct" => try sema.errNote(src_loc, msg, "struct in packed type must have packed layout", .{}), - .@"union" => try sema.errNote(src_loc, msg, "union in packed type must have packed layout", .{}), + .non_packed_struct => |struct_ty| { + try sema.errNote(src, msg, "non-packed structs do not have a bit-packed representation", .{}); + try sema.addDeclaredHereNote(msg, struct_ty); + }, + .non_packed_union => |union_ty| { + try sema.errNote(src, msg, "non-packed unions do not have a bit-packed representation", .{}); + try sema.addDeclaredHereNote(msg, union_ty); + }, + .other => try sema.errNote(src, msg, "type does not have a bit-packed representation", .{}), } } @@ -25545,7 +25213,7 @@ fn getPanicIdFunc(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !In try sema.ensureMemoizedStateResolved(src, .panic); const panic_fn_index = zcu.builtin_decl_values.get(panic_id.toBuiltin()); switch (sema.owner.unwrap()) { - .@"comptime", .nav_ty, .nav_val, .type_layout, .type_inits, .memoized_state => {}, + .@"comptime", .nav_ty, .nav_val, .type_layout, .struct_defaults, .memoized_state => {}, .func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(io, owner_func, true), } return panic_fn_index; @@ -25962,6 +25630,7 @@ fn fieldVal( if (try sema.namespaceLookupVal(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { return inst; } + try sema.ensureLayoutResolved(child_type); if (child_type.unionTagType(zcu)) |enum_ty| { if (enum_ty.enumFieldIndex(field_name, zcu)) |field_index_usize| { const field_index: u32 = @intCast(field_index_usize); @@ -25974,6 +25643,7 @@ fn fieldVal( if (try sema.namespaceLookupVal(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { return inst; } + try sema.ensureLayoutResolved(child_type); const field_index_usize = child_type.enumFieldIndex(field_name, zcu) orelse return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name); const field_index: u32 = @intCast(field_index_usize); @@ -26195,6 +25865,7 @@ fn fieldPtr( if (try sema.namespaceLookupRef(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { return inst; } + try sema.ensureLayoutResolved(child_type); if (child_type.unionTagType(zcu)) |enum_ty| { if (enum_ty.enumFieldIndex(field_name, zcu)) |field_index| { const field_index_u32: u32 = @intCast(field_index); @@ -26208,6 +25879,7 @@ fn fieldPtr( if (try sema.namespaceLookupRef(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { return inst; } + try sema.ensureLayoutResolved(child_type); const field_index = child_type.enumFieldIndex(field_name, zcu) orelse { return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name); }; @@ -26444,9 +26116,6 @@ fn finishFieldCallBind( const container_ty = ptr_ty.childType(zcu); if (container_ty.zigTypeTag(zcu) == .@"struct") { if (container_ty.structFieldIsComptime(field_index, zcu)) { - if (!container_ty.isTuple(zcu)) { - try sema.ensureFieldInitsResolved(container_ty); - } const default_val = (try container_ty.structFieldValueComptime(pt, field_index)).?; return .{ .direct = Air.internedToRef(default_val.toIntern()) }; } @@ -26623,7 +26292,7 @@ fn structFieldPtrByIndex( const ptr_field_ty = try pt.ptrType(ptr_ty_data); if (field_is_comptime) { - try sema.ensureFieldInitsResolved(struct_ty); + assert(struct_type.field_defaults.get(ip)[field_index] != .none); const val = try pt.intern(.{ .ptr = .{ .ty = ptr_field_ty.toIntern(), .base_addr = .{ .comptime_field = struct_type.field_defaults.get(ip)[field_index] }, @@ -26647,6 +26316,8 @@ fn structFieldVal( const zcu = pt.zcu; const ip = &zcu.intern_pool; assert(struct_ty.zigTypeTag(zcu) == .@"struct"); + assert(sema.typeOf(struct_byval).toIntern() == struct_ty.toIntern()); + struct_ty.assertHasLayout(zcu); switch (ip.indexToKey(struct_ty.toIntern())) { .struct_type => { @@ -26655,7 +26326,6 @@ fn structFieldVal( const field_index = struct_type.nameIndex(ip, field_name) orelse return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_name_src, field_name); if (struct_type.field_is_comptime_bits.get(ip, field_index)) { - try sema.ensureFieldInitsResolved(struct_ty); return .fromIntern(struct_type.field_defaults.get(ip)[field_index]); } @@ -26886,6 +26556,8 @@ fn unionFieldVal( const zcu = pt.zcu; const ip = &zcu.intern_pool; assert(union_ty.zigTypeTag(zcu) == .@"union"); + assert(sema.typeOf(union_byval).toIntern() == union_ty.toIntern()); + union_ty.assertHasLayout(zcu); const union_obj = zcu.typeToUnion(union_ty).?; const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src); @@ -27149,11 +26821,11 @@ fn validateRuntimeElemAccess( const msg = try sema.errMsg( elem_index_src, "values of type '{f}' must be comptime-known, but index value is runtime-known", - .{parent_ty.fmt(sema.pt)}, + .{elem_ty.fmt(sema.pt)}, ); errdefer msg.destroy(sema.gpa); - try sema.explainWhyTypeIsComptime(msg, parent_src, parent_ty); + try sema.explainWhyTypeIsComptime(msg, parent_src, elem_ty); break :msg msg; }; @@ -27885,18 +27557,14 @@ fn coerceExtra( // empty tuple to zero-length slice // note that this allows coercing to a mutable slice. if (inst_child_ty.structFieldCount(zcu) == 0) { - // TODO MLUGG: this is *unacceptably* stupid. we're resolving the child for the alignment value - try sema.ensureLayoutResolved(dest_ty.childType(zcu)); - const align_val = dest_ty.ptrAlignment(zcu); - return Air.internedToRef(try pt.intern(.{ .slice = .{ - .ty = dest_ty.toIntern(), - .ptr = try pt.intern(.{ .ptr = .{ - .ty = dest_ty.slicePtrFieldType(zcu).toIntern(), - .base_addr = .int, - .byte_offset = align_val.toByteUnits().?, - } }), - .len = .zero_usize, - } })); + const empty_array_ty = try pt.arrayType(.{ + .len = 0, + .child = dest_info.child, + .sentinel = dest_info.sentinel, + }); + const empty_array_val = try pt.aggregateValue(empty_array_ty, &.{}); + const empty_array_ptr = try sema.uavRef(empty_array_val.toIntern()); + return sema.coerceArrayPtrToSlice(block, dest_ty, empty_array_ptr, inst_src); } // pointer to tuple to slice @@ -27955,7 +27623,7 @@ fn coerceExtra( .int, .comptime_int => { if (maybe_inst_val) |val| { // comptime-known integer to other number - if (!(try sema.intFitsInType(val, dest_ty, null))) { + if (!val.intFitsInType(dest_ty, null, zcu)) { if (!opts.report_err) return error.NotCoercible; return sema.fail(block, inst_src, "type '{f}' cannot represent integer value '{f}'", .{ dest_ty.fmt(pt), val.fmtValueSema(pt, sema) }); } @@ -28039,28 +27707,26 @@ fn coerceExtra( } break :int; }; + if (val.isUndef(zcu)) { + return .fromValue(try pt.undefValue(dest_ty)); + } const result_val = try pt.floatValue(dest_ty, val.toFloat(f128, zcu)); - const fits: bool = switch (ip.indexToKey(result_val.toIntern())) { - else => unreachable, - .undef => true, - .float => |float| fits: { - var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined; - const operand_big_int = val.toBigInt(&buffer, zcu); - switch (float.storage) { - inline else => |x| { - if (!std.math.isFinite(x)) break :fits false; - var result_big_int: std.math.big.int.Mutable = .{ - .limbs = try sema.arena.alloc(std.math.big.Limb, std.math.big.int.calcLimbLen(x)), - .len = undefined, - .positive = undefined, - }; - switch (result_big_int.setFloat(x, .nearest_even)) { - .inexact => break :fits false, - .exact => {}, - } - break :fits result_big_int.toConst().eql(operand_big_int); - }, + const float = ip.indexToKey(result_val.toIntern()).float; + var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined; + const operand_big_int = val.toBigInt(&buffer, zcu); + const fits = switch (float.storage) { + inline else => |x| fits: { + if (!std.math.isFinite(x)) break :fits false; + var result_big_int: std.math.big.int.Mutable = .{ + .limbs = try sema.arena.alloc(std.math.big.Limb, std.math.big.int.calcLimbLen(x)), + .len = undefined, + .positive = undefined, + }; + switch (result_big_int.setFloat(x, .nearest_even)) { + .inexact => break :fits false, + .exact => {}, } + break :fits result_big_int.toConst().eql(operand_big_int); }, }; if (!fits) return sema.fail( @@ -28699,7 +28365,7 @@ pub fn coerceInMemoryAllowed( // Comptime int to regular int. if (dest_tag == .int and src_tag == .comptime_int) { if (src_val) |val| { - if (!(try sema.intFitsInType(val, dest_ty, null))) { + if (!val.intFitsInType(dest_ty, null, zcu)) { return .{ .comptime_int_not_coercible = .{ .wanted = dest_ty, .actual = val } }; } } @@ -29333,7 +28999,7 @@ fn coerceVarArgParam( } }, else => if (uncasted_ty.isAbiInt(zcu)) int: { - if (!try sema.validateExternType(uncasted_ty, .param_ty)) break :int inst; + if (!uncasted_ty.validateExtern(.param_ty, zcu)) break :int inst; const target = zcu.getTarget(); const uncasted_info = uncasted_ty.intInfo(zcu); if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) { @@ -29362,7 +29028,7 @@ fn coerceVarArgParam( }; const coerced_ty = sema.typeOf(coerced); - if (!try sema.validateExternType(coerced_ty, .param_ty)) { + if (!coerced_ty.validateExtern(.param_ty, zcu)) { const msg = msg: { const msg = try sema.errMsg(inst_src, "cannot pass '{f}' to variadic function", .{coerced_ty.fmt(pt)}); errdefer msg.destroy(sema.gpa); @@ -33283,12 +32949,12 @@ fn typeIsArrayLike(sema: *Sema, ty: Type) ?ArrayLike { .elem_ty = ty.childType(zcu), }, .@"struct" => { + if (!ty.isTuple(zcu)) return null; const field_count = ty.structFieldCount(zcu); if (field_count == 0) return .{ .len = 0, .elem_ty = .noreturn, }; - if (!ty.isTuple(zcu)) return null; const elem_ty = ty.fieldType(0, zcu); for (1..field_count) |i| { if (!ty.fieldType(i, zcu).eql(elem_ty, zcu)) { @@ -33700,6 +33366,7 @@ fn usizeCast(sema: *Sema, block: *Block, src: LazySrcLoc, int: u64) CompileError return std.math.cast(usize, int) orelse return sema.fail(block, src, "expression produces integer value '{d}' which is too big for this compiler implementation to handle", .{int}); } +/// Asserts that the layout of `union_ty` is already resolved. fn unionFieldIndex( sema: *Sema, block: *Block, @@ -33717,6 +33384,7 @@ fn unionFieldIndex( return @intCast(field_index); } +/// Asserts that the layout of `struct_ty` is already resolved. fn structFieldIndex( sema: *Sema, block: *Block, @@ -33811,64 +33479,6 @@ fn intFromFloatScalar( return pt.getCoerced(cti_result, int_ty); } -/// Asserts the value is an integer, and the destination type is ComptimeInt or Int. -/// Vectors are also accepted. Vector results are reduced with AND. -/// -/// If provided, `vector_index` reports the first element that failed the range check. -/// MLUGG TODO: move to `Value` or `Type`? -fn intFitsInType( - sema: *Sema, - val: Value, - ty: Type, - vector_index: ?*usize, -) CompileError!bool { - const pt = sema.pt; - const zcu = pt.zcu; - if (ty.toIntern() == .comptime_int_type) return true; - const info = ty.intInfo(zcu); - switch (val.toIntern()) { - .zero_usize, .zero_u8 => return true, - else => switch (zcu.intern_pool.indexToKey(val.toIntern())) { - .undef => return true, - .variable, .@"extern", .func, .ptr => { - const target = zcu.getTarget(); - const ptr_bits = target.ptrBitWidth(); - return switch (info.signedness) { - .signed => info.bits > ptr_bits, - .unsigned => info.bits >= ptr_bits, - }; - }, - .int => |int| { - var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined; - const big_int = int.storage.toBigInt(&buffer); - return big_int.fitsInTwosComp(info.signedness, info.bits); - }, - .aggregate => |aggregate| { - assert(ty.zigTypeTag(zcu) == .vector); - return switch (aggregate.storage) { - .bytes => |bytes| for (bytes.toSlice(ty.vectorLen(zcu), &zcu.intern_pool), 0..) |byte, i| { - if (byte == 0) continue; - const actual_needed_bits = std.math.log2(byte) + 1 + @intFromBool(info.signedness == .signed); - if (info.bits >= actual_needed_bits) continue; - if (vector_index) |vi| vi.* = i; - break false; - } else true, - .elems, .repeated_elem => for (switch (aggregate.storage) { - .bytes => unreachable, - .elems => |elems| elems, - .repeated_elem => |elem| @as(*const [1]InternPool.Index, &elem), - }, 0..) |elem, i| { - if (try sema.intFitsInType(Value.fromInterned(elem), ty.scalarType(zcu), null)) continue; - if (vector_index) |vi| vi.* = i; - break false; - } else true, - }; - }, - else => unreachable, - }, - } -} - fn intInRange(sema: *Sema, tag_ty: Type, int_val: Value, end: usize) !bool { const pt = sema.pt; if (!int_val.compareAllWithZero(.gte, pt.zcu)) return false; @@ -33886,7 +33496,7 @@ fn enumHasInt(sema: *Sema, ty: Type, int: Value) CompileError!bool { // The `tagValueIndex` function call below relies on the type being the integer tag type. // `getCoerced` assumes the value will fit the new type. const int_tag_ty: Type = .fromInterned(enum_type.int_tag_type); - if (!try sema.intFitsInType(int, int_tag_ty, null)) return false; + if (!int.intFitsInType(int_tag_ty, null, zcu)) return false; const int_coerced = try pt.getCoerced(int, int_tag_ty); return enum_type.tagValueIndex(&zcu.intern_pool, int_coerced.toIntern()) != null; } @@ -33919,7 +33529,6 @@ fn compareAll( } /// Asserts the values are comparable. Both operands have type `ty`. -/// MLUGG TODO: move to `Value`? fn compareScalar( sema: *Sema, lhs: Value, @@ -34422,7 +34031,7 @@ const ComptimeStoreResult = @import("Sema/comptime_ptr_access.zig").ComptimeStor // MLUGG TODO: decide how to do the namespacing here pub const type_resolution = @import("Sema/type_resolution.zig"); pub const ensureLayoutResolved = type_resolution.ensureLayoutResolved; -pub const ensureFieldInitsResolved = type_resolution.ensureFieldInitsResolved; +pub const ensureStructDefaultsResolved = type_resolution.ensureStructDefaultsResolved; pub fn getBuiltinType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) SemaError!Type { assert(decl.kind() == .type); @@ -34644,48 +34253,14 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.BuiltinDecl) CompileError!Typ }; } -/// TODO MLUGG: this is a gnarly hack -const PartialTypeName = union(enum) { - exact: struct { - name: InternPool.NullTerminatedString, - nav: InternPool.Nav.Index.Optional, - }, - anon_prefix: []const u8, - fn apply( - name: PartialTypeName, - wip: *const InternPool.WipContainerType, - pt: Zcu.PerThread, - ) (Allocator.Error || std.Io.Cancelable)!InternPool.NullTerminatedString { - const zcu = pt.zcu; - const comp = zcu.comp; - const ip = &zcu.intern_pool; - switch (name) { - .exact => |e| { - wip.setName(ip, e.name, e.nav); - return e.name; - }, - .anon_prefix => |prefix| { - const resolved_name = try ip.getOrPutStringFmt( - comp.gpa, - comp.io, - pt.tid, - "{s}_{d}", - .{ prefix, @intFromEnum(wip.index) }, - .no_embedded_nulls, - ); - wip.setName(ip, resolved_name, .none); - return resolved_name; - }, - } - } -}; -pub fn createTypeName( +fn setTypeName( sema: *Sema, block: *Block, + wip: *const InternPool.WipContainerType, name_strategy: Zir.Inst.NameStrategy, anon_prefix: []const u8, inst: Zir.Inst.Index, -) CompileError!PartialTypeName { +) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; @@ -34693,13 +34268,26 @@ pub fn createTypeName( const io = comp.io; const ip = &zcu.intern_pool; - switch (name_strategy) { - .anon => {}, // handled after switch - .parent => return .{ .exact = .{ - .name = block.type_name_ctx, - .nav = sema.owner.unwrap().nav_val.toOptional(), - } }, - .func => func_strat: { + strat: switch (name_strategy) { + .anon => { + // It would be neat to have "struct:line:column" but this name has + // to survive incremental updates, where it may have been shifted down + // or up to a different line, but unchanged, and thus not unnecessarily + // semantically analyzed. + // TODO: that would be possible, by detecting line number changes and renaming + // types appropriately. However, `@typeName` becomes a problem then. If we remove + // that builtin from the language, we can consider this. + wip.setName(ip, try ip.getOrPutStringFmt( + gpa, + io, + pt.tid, + "{f}__{s}_{d}", + .{ block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(wip.index) }, + .no_embedded_nulls, + ), .none); + }, + .parent => wip.setName(ip, block.type_name_ctx, sema.owner.unwrap().nav_val.toOptional()), + .func => { const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse return error.AnalysisFail); const zir_tags = sema.code.instructions.items(.tag); @@ -34717,7 +34305,9 @@ pub fn createTypeName( // If not then this is a struct type being returned from a non-generic // function and the name doesn't matter since it will later // result in a compile error. - const arg_val = try sema.resolveValue(arg) orelse break :func_strat; // fall through to anon strat + const arg_val = try sema.resolveValue(arg) orelse { + continue :strat .anon; + }; if (arg_i != 0) w.writeByte(',') catch return error.OutOfMemory; @@ -34739,174 +34329,133 @@ pub fn createTypeName( }; w.writeByte(')') catch return error.OutOfMemory; - return .{ .exact = .{ - .name = try ip.getOrPutString(gpa, io, pt.tid, aw.written(), .no_embedded_nulls), - .nav = .none, - } }; + const name = try ip.getOrPutString(gpa, io, pt.tid, aw.written(), .no_embedded_nulls); + wip.setName(ip, name, .none); }, .dbg_var => { // TODO: this logic is questionable. We ideally should be traversing the `Block` rather than relying on the order of AstGen instructions. const ref = inst.toRef(); const zir_tags = sema.code.instructions.items(.tag); const zir_data = sema.code.instructions.items(.data); - for (@intFromEnum(inst)..zir_tags.len) |i| switch (zir_tags[i]) { + const var_name = for (@intFromEnum(inst)..zir_tags.len) |i| switch (zir_tags[i]) { .dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) { - return .{ .exact = .{ - .name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}.{s}", .{ - block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code), - }, .no_embedded_nulls), - .nav = .none, - } }; + break zir_data[i].str_op.getStr(sema.code); }, else => {}, + } else { + continue :strat .anon; }; - // fall through to anon strat + const name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}.{s}", .{ + block.type_name_ctx.fmt(ip), var_name, + }, .no_embedded_nulls); + wip.setName(ip, name, .none); }, } - - // anon strat handling - - // It would be neat to have "struct:line:column" but this name has - // to survive incremental updates, where it may have been shifted down - // or up to a different line, but unchanged, and thus not unnecessarily - // semantically analyzed. - // TODO: that would be possible, by detecting line number changes and renaming - // types appropriately. However, `@typeName` becomes a problem then. If we remove - // that builtin from the language, we can consider this. - - return .{ .anon_prefix = try std.fmt.allocPrint( - sema.arena, - "{f}__{s}", - .{ block.type_name_ctx.fmt(ip), anon_prefix }, - ) }; } -pub fn analyzeStructDecl( - pt: Zcu.PerThread, - file_index: Zcu.File.Index, - zir: *const Zir, - parent_namespace: InternPool.OptionalNamespaceIndex, - tracked_inst: InternPool.TrackedInst.Index, - struct_decl: *const Zir.UnwrappedStructDecl, - explicit_backing_type: ?Type, - captures: []const InternPool.CaptureValue, - type_name: PartialTypeName, -) (Allocator.Error || std.Io.Cancelable)!Type { +fn zirStructDecl( + sema: *Sema, + block: *Block, + inst: Zir.Inst.Index, +) CompileError!Air.Inst.Ref { + const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; const gpa = comp.gpa; const io = comp.io; const ip = &zcu.intern_pool; - const wip = switch (try ip.getStructType(gpa, io, pt.tid, .{ + const tracked_inst = try block.trackZir(inst); + + const src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .nodeOffset(.zero), + }; + + const struct_decl = sema.code.getStructDecl(inst); + + const captures = try sema.getCaptures(block, src, struct_decl.captures, struct_decl.capture_names); + + const ty: Type = switch (try ip.getDeclaredStructType(gpa, io, pt.tid, .{ + .zir_index = tracked_inst, + .captures = captures, .fields_len = @intCast(struct_decl.field_names.len), .layout = struct_decl.layout, - .explicit_packed_backing_type = if (explicit_backing_type) |ty| ty.toIntern() else .none, .any_comptime_fields = struct_decl.field_comptime_bits != null, .any_field_defaults = struct_decl.field_default_body_lens != null, .any_field_aligns = struct_decl.field_align_body_lens != null, - .key = .{ .declared = .{ - .zir_index = tracked_inst, - .captures = captures, - } }, + .packed_backing_mode = if (struct_decl.backing_int_type_body != null) .explicit else .auto, })) { - .existing => |ty| return .fromInterned(ty), - .wip => |wip| wip, + .existing => |ty| .fromInterned(ty), + .wip => |wip| ty: { + errdefer wip.cancel(ip, pt.tid); + try sema.setTypeName(block, &wip, struct_decl.name_strategy, "struct", inst); + const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ + .parent = block.namespace.toOptional(), + .owner_type = wip.index, + .file_scope = block.getFileScopeIndex(zcu), + .generation = zcu.generation, + }); + errdefer pt.destroyNamespace(new_namespace_index); + try pt.scanNamespace(new_namespace_index, struct_decl.decls); + // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind + try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) }); + try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .struct_defaults = wip.index }) }); + + if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); + + try zcu.outdated.ensureUnusedCapacity(gpa, 2); + try zcu.outdated_ready.ensureUnusedCapacity(gpa, 2); + errdefer comptime unreachable; // because we don't remove the `outdated` entries + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .struct_defaults = wip.index }), 0); + zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); + zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .struct_defaults = wip.index }), {}); + + break :ty .fromInterned(wip.finish(ip, new_namespace_index)); + }, }; - errdefer wip.cancel(ip, pt.tid); - _ = try type_name.apply(&wip, pt); + try sema.addTypeReferenceEntry(src, ty); - var field_it = struct_decl.iterateFields(); - while (field_it.next()) |field| { - const name_slice = zir.nullTerminatedString(field.name); - const name = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls); - assert(wip.nextField(ip, name, field.is_comptime) == null); // AstGen validated this for us - } + // Make sure we update the namespace if the declaration is re-analyzed, to pick + // up on e.g. changed comptime decls. + // TODO MLUGG: me no likey, maybe model namespaces less badly idk + try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)); - const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ - .parent = parent_namespace, - .owner_type = wip.index, - .file_scope = file_index, - .generation = zcu.generation, - }); - errdefer pt.destroyNamespace(new_namespace_index); - - try pt.scanNamespace(new_namespace_index, struct_decl.decls); - - // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind - try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) }); - try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_inits = wip.index }) }); - - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - - try zcu.outdated.ensureUnusedCapacity(gpa, 2); - try zcu.outdated_ready.ensureUnusedCapacity(gpa, 2); - errdefer comptime unreachable; // because we don't remove the `outdated` entries - zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); - zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_inits = wip.index }), 0); - zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); - zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_inits = wip.index }), {}); - - return .fromInterned(wip.finish(ip, new_namespace_index)); + return .fromIntern(ty.toIntern()); } -const AnalyzeUnionDeclError = error{ - OutOfMemory, - Canceled, - /// `packed union(T)` syntax was used, but `T` was not an integer type. - ExplicitBackingNotInt, - /// `union(enum(T))` syntax was used, but `T` was not an integer type. - ExplicitTagNotInt, - /// `union(T)` syntax was used, but `T` was not an enum type. - ExplicitTagNotEnum, - /// `union(T)` syntax was used, but the fields of the union do not exactly - /// correspond to the fields of the enum `T`. - ExplicitTagFieldMismatch, -}; -fn analyzeUnionDecl( - pt: Zcu.PerThread, - file_index: Zcu.File.Index, - zir: *const Zir, - parent_namespace: InternPool.OptionalNamespaceIndex, - want_safe_types: bool, - tracked_inst: InternPool.TrackedInst.Index, - union_decl: *const Zir.UnwrappedUnionDecl, - arg_type: ?Type, - captures: []const InternPool.CaptureValue, - type_name: PartialTypeName, -) AnalyzeUnionDeclError!Type { +fn zirUnionDecl( + sema: *Sema, + block: *Block, + inst: Zir.Inst.Index, +) CompileError!Air.Inst.Ref { + const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; const gpa = comp.gpa; const io = comp.io; const ip = &zcu.intern_pool; - switch (union_decl.kind) { - .tagged_explicit => if (arg_type.?.zigTypeTag(zcu) != .@"enum") { - return error.ExplicitTagNotEnum; - }, - .tagged_enum_explicit => if (arg_type.?.zigTypeTag(zcu) != .int) { - return error.ExplicitTagNotInt; - }, - .packed_explicit => if (arg_type.?.zigTypeTag(zcu) != .int) { - return error.ExplicitBackingNotInt; - }, - .auto, - .tagged_enum, - .@"extern", - .@"packed", - => assert(arg_type == null), - } + const tracked_inst = try block.trackZir(inst); - const wip = switch (try ip.getUnionType(gpa, io, pt.tid, .{ + const src: LazySrcLoc = .{ + .base_node_inst = tracked_inst, + .offset = .nodeOffset(.zero), + }; + + const union_decl = sema.code.getUnionDecl(inst); + + const captures = try sema.getCaptures(block, src, union_decl.captures, union_decl.capture_names); + + const ty: Type = switch (try ip.getDeclaredUnionType(gpa, io, pt.tid, .{ + .zir_index = tracked_inst, + .captures = captures, .fields_len = @intCast(union_decl.field_names.len), .layout = union_decl.kind.layout(), - .explicit_packed_backing_type = switch (union_decl.kind) { - .packed_explicit => arg_type.?.toIntern(), - else => .none, - }, + .any_field_aligns = union_decl.field_align_body_lens != null, .runtime_tag = switch (union_decl.kind) { - .auto => if (want_safe_types) .safety else .none, + .auto => if (block.wantSafeTypes()) .safety else .none, .tagged_explicit, .tagged_enum, @@ -34918,441 +34467,45 @@ fn analyzeUnionDecl( .packed_explicit, => .none, }, - .have_explicit_enum_tag = union_decl.kind == .tagged_explicit, - .any_field_aligns = union_decl.field_align_body_lens != null, - .key = .{ .declared = .{ - .zir_index = tracked_inst, - .captures = captures, - .arg_ty = if (arg_type) |t| t.toIntern() else .none, - } }, - })) { - .existing => |ty| return .fromInterned(ty), - .wip => |wip| wip, - }; - errdefer wip.cancel(ip, pt.tid); - - const resolved_type_name = try type_name.apply(&wip, pt); - - const generated_tag_ty: InternPool.Index = if (union_decl.kind == .tagged_explicit) generated_tag_ty: { - const tag_type = arg_type.?; - const enum_field_names = ip.loadEnumType(tag_type.toIntern()).field_names; - // Check that the enum field names match the union field names - if (union_decl.field_names.len != enum_field_names.len) { - return error.ExplicitTagFieldMismatch; - } - for (union_decl.field_names, enum_field_names.get(ip)) |union_field_zir, enum_field_ip| { - const union_field_name = zir.nullTerminatedString(union_field_zir); - const enum_field_name = enum_field_ip.toSlice(ip); - if (!std.mem.eql(u8, union_field_name, enum_field_name)) { - return error.ExplicitTagFieldMismatch; - } - } - wip.setTagType(ip, tag_type.toIntern()); - break :generated_tag_ty .none; - } else generated_tag_ty: { - // Generate a tag type. Even if the union is untagged (`.none`), we still generate a - // hypothetical tag type. - const wip_tag_ty = switch (try ip.getEnumType(gpa, io, pt.tid, .{ - .fields_len = @intCast(union_decl.field_names.len), - .explicit_int_tag_type = switch (union_decl.kind) { - .tagged_enum_explicit => arg_type.?.toIntern(), - else => .none, - }, - .nonexhaustive = false, - .key = .{ .generated_union_tag = wip.index }, - })) { - .existing => unreachable, // enum type is keyed on this union type which we're only just creating - .wip => |wip_tag_ty| wip_tag_ty, - }; - errdefer wip_tag_ty.cancel(ip, pt.tid); - // Populate the generated tag type's name - const tag_type_name = try ip.getOrPutStringFmt( - gpa, - io, - pt.tid, - "@typeInfo({f}).@\"union\".tag_type.?", - .{resolved_type_name.fmt(ip)}, - .no_embedded_nulls, - ); - wip_tag_ty.setName(ip, tag_type_name, .none); - // Populate the generated tag type's field names - for (union_decl.field_names) |zir_name| { - const name_slice = zir.nullTerminatedString(zir_name); - const name = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls); - assert(wip_tag_ty.nextField(ip, name, false) == null); // AstGen validated this for us - } - // If not explicitly given, populate the generated tag type's *integer* tag type - switch (union_decl.kind) { - .tagged_enum_explicit => {}, // already set by `getEnumType` - else => { - // Infer the int tag type from the field count - const bits = Type.smallestUnsignedBits(union_decl.field_names.len -| 1); - const int_tag_type = try pt.intType(.unsigned, bits); - wip_tag_ty.setTagType(ip, int_tag_type.toIntern()); - }, - } - // Create a dummy namespace for the generated tag type - const new_namespace_index = try pt.createNamespace(.{ - .parent = parent_namespace, - .owner_type = wip_tag_ty.index, - .file_scope = file_index, - .generation = zcu.generation, - }); - errdefer pt.destroyNamespace(new_namespace_index); - wip.setTagType(ip, wip_tag_ty.index); - break :generated_tag_ty wip_tag_ty.finish(ip, new_namespace_index); - }; - // If we fail to create the union type, we must delete the generated enum tag type, since it - // would hold a reference to the deleted union. - errdefer if (generated_tag_ty != .none) ip.remove(pt.tid, generated_tag_ty); - - const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ - .parent = parent_namespace, - .owner_type = wip.index, - .file_scope = file_index, - .generation = zcu.generation, - }); - errdefer pt.destroyNamespace(new_namespace_index); - - try pt.scanNamespace(new_namespace_index, union_decl.decls); - - // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind - try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) }); - if (generated_tag_ty != .none) { - try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_inits = generated_tag_ty }) }); - } - - if (zcu.comp.debugIncremental()) { - try zcu.incremental_debug_state.newType(zcu, wip.index); - if (generated_tag_ty != .none) { - try zcu.incremental_debug_state.newType(zcu, generated_tag_ty); - } - } - - try zcu.outdated.ensureUnusedCapacity(gpa, 2); - try zcu.outdated_ready.ensureUnusedCapacity(gpa, 2); - errdefer comptime unreachable; // because we don't remove the `outdated` entry - zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); - zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); - if (generated_tag_ty != .none) { - zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_inits = generated_tag_ty }), 0); - zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_inits = generated_tag_ty }), {}); - } - - return .fromInterned(wip.finish(ip, new_namespace_index)); -} -const AnalyzeEnumDeclError = error{ - OutOfMemory, - Canceled, - /// `enum(T)` syntax was used, but `T` was not an integer type. - ExplicitTagNotInt, -}; -fn analyzeEnumDecl( - pt: Zcu.PerThread, - file_index: Zcu.File.Index, - zir: *const Zir, - parent_namespace: InternPool.OptionalNamespaceIndex, - tracked_inst: InternPool.TrackedInst.Index, - enum_decl: *const Zir.UnwrappedEnumDecl, - explicit_tag_type: ?Type, - captures: []const InternPool.CaptureValue, - type_name: PartialTypeName, -) AnalyzeEnumDeclError!Type { - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const io = comp.io; - const ip = &zcu.intern_pool; - - if (explicit_tag_type) |ty| { - // MLUGG TODO: make a final call on whether comptime_int is a valid int tag type, and follow it everywhere. - // i think not in the name of simplicity, but my opinion might depend on whether it's broken in practice today - switch (ty.zigTypeTag(zcu)) { - .int, .comptime_int => {}, - else => return error.ExplicitTagNotInt, - } - } - - const wip = switch (try ip.getEnumType(gpa, io, pt.tid, .{ - .fields_len = @intCast(enum_decl.field_names.len), - .explicit_int_tag_type = if (explicit_tag_type) |ty| ty.toIntern() else .none, - .nonexhaustive = enum_decl.nonexhaustive, - .key = .{ .declared = .{ - .zir_index = tracked_inst, - .captures = captures, - } }, - })) { - .existing => |ty| return .fromInterned(ty), - .wip => |wip| wip, - }; - errdefer wip.cancel(ip, pt.tid); - - _ = try type_name.apply(&wip, pt); - - var field_it = enum_decl.iterateFields(); - while (field_it.next()) |field| { - const name_slice = zir.nullTerminatedString(field.name); - const name = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls); - assert(wip.nextField(ip, name, false) == null); // AstGen validated this for us - } - - if (explicit_tag_type == null) { - // Infer the int tag type from the field count - const bits = Type.smallestUnsignedBits(enum_decl.field_names.len -| 1); - const int_tag_ty = try pt.intType(.unsigned, bits); - wip.setTagType(ip, int_tag_ty.toIntern()); - } - - const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ - .parent = parent_namespace, - .owner_type = wip.index, - .file_scope = file_index, - .generation = zcu.generation, - }); - errdefer pt.destroyNamespace(new_namespace_index); - - try pt.scanNamespace(new_namespace_index, enum_decl.decls); - - // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind - try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_inits = wip.index }) }); - - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - - try zcu.outdated.ensureUnusedCapacity(gpa, 1); - try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); - errdefer comptime unreachable; // because we don't remove the `outdated` entry - zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_inits = wip.index }), 0); - zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_inits = wip.index }), {}); - - return .fromInterned(wip.finish(ip, new_namespace_index)); -} -fn analyzeOpaqueDecl( - pt: Zcu.PerThread, - file_index: Zcu.File.Index, - parent_namespace: InternPool.OptionalNamespaceIndex, - tracked_inst: InternPool.TrackedInst.Index, - opaque_decl: *const Zir.UnwrappedOpaqueDecl, - captures: []const InternPool.CaptureValue, - type_name: PartialTypeName, -) (Allocator.Error || std.Io.Cancelable)!Type { - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const io = comp.io; - const ip = &zcu.intern_pool; - - const wip = switch (try ip.getOpaqueType(gpa, io, pt.tid, .{ - .zir_index = tracked_inst, - .captures = captures, + .enum_tag_mode = switch (union_decl.kind) { + .tagged_explicit => .explicit, + else => .auto, + }, + .packed_backing_mode = switch (union_decl.kind) { + .packed_explicit => .explicit, + else => .auto, + }, })) { - .existing => |ty| return .fromInterned(ty), - .wip => |wip| wip, - }; - errdefer wip.cancel(ip, pt.tid); - - _ = try type_name.apply(&wip, pt); - - const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ - .parent = parent_namespace, - .owner_type = wip.index, - .file_scope = file_index, - .generation = zcu.generation, - }); - errdefer pt.destroyNamespace(new_namespace_index); - - try pt.scanNamespace(new_namespace_index, opaque_decl.decls); - - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - return .fromInterned(wip.finish(ip, new_namespace_index)); -} - -fn zirStructDecl( - sema: *Sema, - block: *Block, - inst: Zir.Inst.Index, -) CompileError!Air.Inst.Ref { - const pt = sema.pt; - const zcu = pt.zcu; + .existing => |ty| .fromInterned(ty), + .wip => |wip| ty: { + errdefer wip.cancel(ip, pt.tid); + try sema.setTypeName(block, &wip, union_decl.name_strategy, "union", inst); - const tracked_inst = try block.trackZir(inst); + const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ + .parent = block.namespace.toOptional(), + .owner_type = wip.index, + .file_scope = block.getFileScopeIndex(zcu), + .generation = zcu.generation, + }); + errdefer pt.destroyNamespace(new_namespace_index); - const src: LazySrcLoc = .{ - .base_node_inst = tracked_inst, - .offset = .nodeOffset(.zero), - }; - const backing_ty_src: LazySrcLoc = .{ - .base_node_inst = tracked_inst, - .offset = .{ .node_offset_container_tag = .zero }, - }; - - const struct_decl = sema.code.getStructDecl(inst); - - const captures = try sema.getCaptures(block, src, struct_decl.captures, struct_decl.capture_names); - - const backing_int_type: ?Type = ty: { - if (struct_decl.backing_int_type == .none) break :ty null; - break :ty try sema.resolveType(block, backing_ty_src, struct_decl.backing_int_type); - // MLUGG TODO validate it's an int! - }; + try pt.scanNamespace(new_namespace_index, union_decl.decls); - const ty = try analyzeStructDecl( - pt, - block.getFileScopeIndex(zcu), - &sema.code, - block.namespace.toOptional(), - tracked_inst, - &struct_decl, - backing_int_type, - captures, - try sema.createTypeName(block, struct_decl.name_strategy, "struct", inst), - ); + // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind + try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) }); - try sema.addTypeReferenceEntry(src, ty); + if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - // Make sure we update the namespace if the declaration is re-analyzed, to pick - // up on e.g. changed comptime decls. - // TODO MLUGG: me no likey, maybe model namespaces less badly idk - try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)); + try zcu.outdated.ensureUnusedCapacity(gpa, 1); + try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); + errdefer comptime unreachable; // because we don't remove the `outdated` entry + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); + zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); - return .fromIntern(ty.toIntern()); -} -fn zirUnionDecl( - sema: *Sema, - block: *Block, - inst: Zir.Inst.Index, -) CompileError!Air.Inst.Ref { - const pt = sema.pt; - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const io = comp.io; - const ip = &zcu.intern_pool; - - const tracked_inst = try block.trackZir(inst); - - const src: LazySrcLoc = .{ - .base_node_inst = tracked_inst, - .offset = .nodeOffset(.zero), - }; - const arg_ty_src: LazySrcLoc = .{ - .base_node_inst = tracked_inst, - .offset = .{ .node_offset_container_tag = .zero }, - }; - - const union_decl = sema.code.getUnionDecl(inst); - - const captures = try sema.getCaptures(block, src, union_decl.captures, union_decl.capture_names); - - const arg_type: ?Type = ty: { - if (union_decl.arg_type == .none) break :ty null; - break :ty try sema.resolveType(block, arg_ty_src, union_decl.arg_type); - }; - - const ty = analyzeUnionDecl( - pt, - block.getFileScopeIndex(zcu), - &sema.code, - block.namespace.toOptional(), - block.wantSafeTypes(), - tracked_inst, - &union_decl, - arg_type, - captures, - try sema.createTypeName(block, union_decl.name_strategy, "union", inst), - ) catch |err| switch (err) { - error.OutOfMemory, - error.Canceled, - => |e| return e, - - error.ExplicitBackingNotInt => return sema.fail( - block, - arg_ty_src, - "expected integer backing type, found '{f}'", - .{arg_type.?.fmt(pt)}, - ), - error.ExplicitTagNotInt => return sema.fail( - block, - arg_ty_src, - "expected integer tag type, found '{f}'", - .{arg_type.?.fmt(pt)}, - ), - error.ExplicitTagNotEnum => return sema.fail( - block, - arg_ty_src, - "expected enum tag type, found '{f}'", - .{arg_type.?.fmt(pt)}, - ), - error.ExplicitTagFieldMismatch => { - const enum_obj = ip.loadEnumType(arg_type.?.toIntern()); - const enum_to_union_map = try sema.arena.alloc(?u32, enum_obj.field_names.len); - @memset(enum_to_union_map, null); - for (union_decl.field_names, 0..) |field_name_zir, union_field_idx| { - const field_name_ip = try ip.getOrPutString(gpa, io, pt.tid, sema.code.nullTerminatedString(field_name_zir), .no_embedded_nulls); - if (enum_obj.nameIndex(ip, field_name_ip)) |enum_field_idx| { - enum_to_union_map[enum_field_idx] = @intCast(union_field_idx); - continue; - } - const union_field_src: LazySrcLoc = .{ - .base_node_inst = tracked_inst, - .offset = .{ .container_field_name = @intCast(union_field_idx) }, - }; - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(union_field_src, "no field named '{f}' in enum '{f}'", .{ field_name_ip.fmt(ip), arg_type.?.fmt(pt) }); - errdefer msg.destroy(gpa); - try sema.addDeclaredHereNote(msg, arg_type.?); - break :msg msg; - }); - } - for (enum_to_union_map, 0..) |union_field_idx, enum_field_idx| { - if (union_field_idx != null) continue; - const field_name_ip = enum_obj.field_names.get(ip)[enum_field_idx]; - const enum_field_src: LazySrcLoc = .{ - .base_node_inst = arg_type.?.typeDeclInstAllowGeneratedTag(zcu).?, - .offset = .{ .container_field_name = @intCast(enum_field_idx) }, - }; - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(src, "enum field '{f}' missing from union", .{field_name_ip.fmt(ip)}); - errdefer msg.destroy(gpa); - try sema.errNote(enum_field_src, msg, "enum field here", .{}); - break :msg msg; - }); - } - for (enum_to_union_map, 0..) |union_field_idx, enum_field_idx| { - if (union_field_idx.? == enum_field_idx) continue; - const field_name = sema.code.nullTerminatedString( - union_decl.field_names[union_field_idx.?], - ); - const union_field_src: LazySrcLoc = .{ - .base_node_inst = tracked_inst, - .offset = .{ .container_field_name = union_field_idx.? }, - }; - const enum_field_src: LazySrcLoc = .{ - .base_node_inst = arg_type.?.typeDeclInstAllowGeneratedTag(zcu).?, - .offset = .{ .container_field_name = @intCast(enum_field_idx) }, - }; - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(src, "union field order does not match tag enum field order", .{}); - errdefer msg.destroy(gpa); - try sema.errNote(union_field_src, msg, "union field '{s}' is index {d}", .{ field_name, union_field_idx.? }); - try sema.errNote(enum_field_src, msg, "enum field '{s}' is index {d}", .{ field_name, enum_field_idx }); - break :msg msg; - }); - } - unreachable; + break :ty .fromInterned(wip.finish(ip, new_namespace_index)); }, }; - const enum_tag_ty = ty.unionTagTypeHypothetical(zcu); - switch (ip.indexToKey(enum_tag_ty.toIntern()).enum_type) { - .declared, .reified => {}, - .generated_union_tag => |owner_union_ty| { - assert(owner_union_ty == ty.toIntern()); - // generated tag type [MLUGG] - // Enum inits are resolved eagerly. TODO MLUGG: honestly i don't think they SHOULD be lol - try sema.ensureFieldInitsResolved(.fromInterned(ip.loadUnionType(ty.toIntern()).enum_tag_type)); - }, - } - try sema.addTypeReferenceEntry(src, ty); // Make sure we update the namespace if the declaration is re-analyzed, to pick @@ -35369,6 +34522,10 @@ fn zirEnumDecl( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &zcu.intern_pool; const tracked_inst = try block.trackZir(inst); @@ -35376,45 +34533,48 @@ fn zirEnumDecl( .base_node_inst = tracked_inst, .offset = .nodeOffset(.zero), }; - const tag_ty_src: LazySrcLoc = .{ - .base_node_inst = tracked_inst, - .offset = .{ .node_offset_container_tag = .zero }, - }; const enum_decl = sema.code.getEnumDecl(inst); const captures = try sema.getCaptures(block, src, enum_decl.captures, enum_decl.capture_names); - const tag_type: ?Type = ty: { - if (enum_decl.tag_type == .none) break :ty null; - break :ty try sema.resolveType(block, tag_ty_src, enum_decl.tag_type); - }; + const ty: Type = switch (try ip.getDeclaredEnumType(gpa, io, pt.tid, .{ + .zir_index = tracked_inst, + .captures = captures, + .fields_len = @intCast(enum_decl.field_names.len), + .nonexhaustive = enum_decl.nonexhaustive, + .int_tag_mode = if (enum_decl.tag_type_body != null) .explicit else .auto, + })) { + .existing => |ty| .fromInterned(ty), + .wip => |wip| ty: { + errdefer wip.cancel(ip, pt.tid); - const ty = analyzeEnumDecl( - pt, - block.getFileScopeIndex(zcu), - &sema.code, - block.namespace.toOptional(), - tracked_inst, - &enum_decl, - tag_type, - captures, - try sema.createTypeName(block, enum_decl.name_strategy, "enum", inst), - ) catch |err| switch (err) { - error.OutOfMemory, - error.Canceled, - => |e| return e, + try sema.setTypeName(block, &wip, enum_decl.name_strategy, "enum", inst); - error.ExplicitTagNotInt => return sema.fail( - block, - tag_ty_src, - "expected integer tag type, found '{f}'", - .{tag_type.?.fmt(pt)}, - ), - }; + const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ + .parent = block.namespace.toOptional(), + .owner_type = wip.index, + .file_scope = block.getFileScopeIndex(zcu), + .generation = zcu.generation, + }); + errdefer pt.destroyNamespace(new_namespace_index); + + try pt.scanNamespace(new_namespace_index, enum_decl.decls); + + // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind + try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) }); - // Enum inits are resolved eagerly. TODO MLUGG: honestly i don't think they SHOULD be lol - try sema.ensureFieldInitsResolved(ty); + if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); + + try zcu.outdated.ensureUnusedCapacity(gpa, 1); + try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); + errdefer comptime unreachable; // because we don't remove the `outdated` entry + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); + zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); + + break :ty .fromInterned(wip.finish(ip, new_namespace_index)); + }, + }; try sema.addTypeReferenceEntry(src, ty); @@ -35432,6 +34592,10 @@ fn zirOpaqueDecl( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const ip = &zcu.intern_pool; const tracked_inst = try block.trackZir(inst); @@ -35444,15 +34608,26 @@ fn zirOpaqueDecl( const captures = try sema.getCaptures(block, src, opaque_decl.captures, opaque_decl.capture_names); - const ty = try analyzeOpaqueDecl( - pt, - block.getFileScopeIndex(zcu), - block.namespace.toOptional(), - tracked_inst, - &opaque_decl, - captures, - try sema.createTypeName(block, opaque_decl.name_strategy, "opaque", inst), - ); + const ty: Type = switch (try ip.getDeclaredOpaqueType(gpa, io, pt.tid, .{ + .zir_index = tracked_inst, + .captures = captures, + })) { + .existing => |ty| .fromInterned(ty), + .wip => |wip| ty: { + errdefer wip.cancel(ip, pt.tid); + try sema.setTypeName(block, &wip, opaque_decl.name_strategy, "opaque", inst); + const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ + .parent = block.namespace.toOptional(), + .owner_type = wip.index, + .file_scope = block.getFileScopeIndex(zcu), + .generation = zcu.generation, + }); + errdefer pt.destroyNamespace(new_namespace_index); + try pt.scanNamespace(new_namespace_index, opaque_decl.decls); + if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); + break :ty .fromInterned(wip.finish(ip, new_namespace_index)); + }, + }; try sema.addTypeReferenceEntry(src, ty); diff --git a/src/Sema/LowerZon.zig b/src/Sema/LowerZon.zig index 78d1d8d1df28af4b827e6d869d0e8352acd168ee..bb10a39729ad41d3e74af62428b671985c13a0cf 100644 --- a/src/Sema/LowerZon.zig +++ b/src/Sema/LowerZon.zig @@ -769,7 +769,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool const ip = &pt.zcu.intern_pool; try self.sema.ensureLayoutResolved(res_ty); - try self.sema.ensureFieldInitsResolved(res_ty); + try self.sema.ensureStructDefaultsResolved(res_ty); const struct_info = self.sema.pt.zcu.typeToStruct(res_ty).?; const fields: @FieldType(Zoir.Node, "struct_literal") = switch (node.get(self.file.zoir.?)) { diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig index f54a7b944e41f3c39161836a49654b177abb7c99..f346d217ae2b361af26498ba5a0f86651c1d6a08 100644 --- a/src/Sema/type_resolution.zig +++ b/src/Sema/type_resolution.zig @@ -18,10 +18,6 @@ const arith = @import("arith.zig"); /// `ty` may be any type; its layout is resolved *recursively* if necessary. /// Adds incremental dependencies tracking any required type resolution. /// MLUGG TODO: to make the langspec non-stupid, we need to call this from WAY fewer places (the conditions need to be less specific). -/// e.g. I think creating the type `fn (A, B) C` should force layout resolution of `A`,`B`,`C`, which will simplify some `analyzeCall` logic. -/// wait i just realised that's probably a terrible idea, fns are a common cause of dep loops rn... so maybe not lol idk... -/// perhaps "layout resolution" for a function should resolve layout of ret ty and stuff, idk. justification: the "layout" of a function is whether -/// fnHasRuntimeBits, which depends whether the ret ty is comptime-only, i.e. the ret ty layout /// MLUGG TODO: to be clear, i should audit EVERY use of this before PRing pub fn ensureLayoutResolved(sema: *Sema, ty: Type) SemaError!void { const pt = sema.pt; @@ -33,7 +29,6 @@ pub fn ensureLayoutResolved(sema: *Sema, ty: Type) SemaError!void { .anyframe_type, .simple_type, .opaque_type, - .enum_type, .error_set_type, .inferred_error_set_type, => {}, @@ -52,7 +47,7 @@ pub fn ensureLayoutResolved(sema: *Sema, ty: Type) SemaError!void { .tuple_type => |tuple| for (tuple.types.get(ip)) |field_ty| { try ensureLayoutResolved(sema, .fromInterned(field_ty)); }, - .struct_type, .union_type => { + .struct_type, .union_type, .enum_type => { try sema.declareDependency(.{ .type_layout = ty.toIntern() }); if (zcu.analysis_in_progress.contains(.wrap(.{ .type_layout = ty.toIntern() }))) { // TODO: better error message @@ -89,36 +84,36 @@ pub fn ensureLayoutResolved(sema: *Sema, ty: Type) SemaError!void { } } -/// Asserts that `ty` is either a `struct` type, or an `enum` type. -/// If `ty` is a struct, ensures that fields' default values are resolved. -/// If `ty` is an enum, ensures that fields' integer tag valus are resolved. -/// Adds incremental dependencies tracking the required type resolution. -pub fn ensureFieldInitsResolved(sema: *Sema, ty: Type) SemaError!void { +/// Asserts that `ty` is a non-tuple `struct` type, and ensures that its fields' default values +/// are resolved. Adds incremental dependencies tracking the required type resolution. +/// +/// It is not necessary to call this function to query the values of comptime fields: those values +/// are available from type *layout* resolution, see `ensureLayoutResolved`. +pub fn ensureStructDefaultsResolved(sema: *Sema, ty: Type) SemaError!void { const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; - switch (ip.indexToKey(ty.toIntern())) { - .struct_type, .enum_type => {}, - else => unreachable, // assertion failure - } + assert(ip.indexToKey(ty.toIntern()) == .struct_type); - try sema.declareDependency(.{ .type_inits = ty.toIntern() }); - if (zcu.analysis_in_progress.contains(.wrap(.{ .type_inits = ty.toIntern() }))) { + try sema.declareDependency(.{ .struct_defaults = ty.toIntern() }); + if (zcu.analysis_in_progress.contains(.wrap(.{ .struct_defaults = ty.toIntern() }))) { // TODO: better error message return sema.failWithOwnedErrorMsg(null, try sema.errMsg( ty.srcLoc(zcu), - "{s} '{f}' depends on itself", - .{ @tagName(ty.zigTypeTag(zcu)), ty.fmt(pt) }, + "struct '{f}' depends on itself", + .{ty.fmt(pt)}, )); } - try pt.ensureTypeInitsUpToDate(ty); + try pt.ensureStructDefaultsUpToDate(ty); } + /// Asserts that `struct_ty` is a non-packed non-tuple struct, and that `sema.owner` is that type. /// This function *does* register the `src_hash` dependency on the struct. pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; + const io = comp.io; const gpa = comp.gpa; const ip = &zcu.intern_pool; @@ -127,10 +122,6 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { const struct_obj = ip.loadStructType(struct_ty.toIntern()); const zir_index = struct_obj.zir_index.resolve(ip).?; - assert(struct_obj.layout != .@"packed"); - - try sema.declareDependency(.{ .src_hash = struct_obj.zir_index }); - var block: Block = .{ .parent = null, .sema = sema, @@ -143,40 +134,93 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { }; defer assert(block.instructions.items.len == 0); - const zir_struct = sema.code.getStructDecl(zir_index); - var field_it = zir_struct.iterateFields(); - while (field_it.next()) |zir_field| { - const field_ty_src: LazySrcLoc = .{ - .base_node_inst = struct_obj.zir_index, - .offset = .{ .container_field_type = zir_field.idx }, - }; - const field_align_src: LazySrcLoc = .{ - .base_node_inst = struct_obj.zir_index, - .offset = .{ .container_field_align = zir_field.idx }, - }; - - const field_ty: Type = field_ty: { - block.comptime_reason = .{ .reason = .{ - .src = field_ty_src, - .r = .{ .simple = .struct_field_types }, - } }; - const type_ref = try sema.resolveInlineBody(&block, zir_field.type_body, zir_index); - break :field_ty try sema.analyzeAsType(&block, field_ty_src, type_ref); - }; + // There may be old field names in here from a previous update. + struct_obj.field_name_map.get(ip).clearRetainingCapacity(); + + if (struct_obj.is_reified) { + // The field names are populated, but we haven't checked for duplicates (nor populated the map) yet. + for (0..struct_obj.field_names.len) |field_index| { + const name = struct_obj.field_names.get(ip)[field_index]; + if (ip.addFieldName(struct_obj.field_names, struct_obj.field_name_map, name)) |prev_field_index| { + return sema.failWithOwnedErrorMsg(&block, msg: { + const src = block.nodeOffset(.zero); + const msg = try sema.errMsg(src, "duplicate struct field '{f}' at index '{d}", .{ name.fmt(ip), field_index }); + errdefer msg.destroy(gpa); + try sema.errNote(src, msg, "previous field at index '{d}'", .{prev_field_index}); + break :msg msg; + }); + } + } + } else { + // Declared structs do not yet have field information populated: + // * field names + // * field comptime-ness + // * field types + // * field aligns + // It's our job to populate these now. + try sema.declareDependency(.{ .src_hash = struct_obj.zir_index }); + + // Likewise, comptime bits may be set. We clear them all first because it avoids needing + // "unset bit with AND" logic below (instead we only need the "set bit with OR" case). + @memset(struct_obj.field_is_comptime_bits.getAll(ip), 0); + + const zir_struct = sema.code.getStructDecl(zir_index); + var field_it = zir_struct.iterateFields(); + while (field_it.next()) |zir_field| { + { + const name_slice = sema.code.nullTerminatedString(zir_field.name); + const name = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls); + assert(ip.addFieldName(struct_obj.field_names, struct_obj.field_name_map, name) == null); // AstGen validated this for us + } + + if (zir_field.is_comptime) { + const bit_bag_index = zir_field.idx / 32; + const mask = @as(u32, 1) << @intCast(zir_field.idx % 32); + struct_obj.field_is_comptime_bits.getAll(ip)[bit_bag_index] |= mask; + } + + { + const field_ty_src = block.src(.{ .container_field_type = zir_field.idx }); + const field_ty: Type = field_ty: { + block.comptime_reason = .{ .reason = .{ + .src = field_ty_src, + .r = .{ .simple = .struct_field_types }, + } }; + const type_ref = try sema.resolveInlineBody(&block, zir_field.type_body, zir_index); + break :field_ty try sema.analyzeAsType(&block, field_ty_src, .struct_field_types, type_ref); + }; + struct_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern(); + } + + if (struct_obj.field_aligns.len == 0) { + assert(zir_field.align_body == null); + } else { + const field_align_src = block.src(.{ .container_field_align = zir_field.idx }); + const field_align: Alignment = a: { + block.comptime_reason = .{ .reason = .{ + .src = field_align_src, + .r = .{ .simple = .struct_field_attrs }, + } }; + const align_body = zir_field.align_body orelse break :a .none; + const align_ref = try sema.resolveInlineBody(&block, align_body, zir_index); + break :a try sema.analyzeAsAlign(&block, field_align_src, align_ref); + }; + struct_obj.field_aligns.get(ip)[zir_field.idx] = field_align; + } + } + } + + if (struct_obj.layout == .@"packed") { + return resolvePackedStructLayout(sema, &block, struct_ty, &struct_obj); + } + + // Resolve the layout of all fields, and check their types are allowed. + for (struct_obj.field_types.get(ip), 0..) |field_ty_ip, field_index| { + const field_ty: Type = .fromInterned(field_ty_ip); assert(!field_ty.isGenericPoison()); - + const field_ty_src = block.src(.{ .container_field_type = @intCast(field_index) }); try sema.ensureLayoutResolved(field_ty); - const explicit_field_align: Alignment = a: { - block.comptime_reason = .{ .reason = .{ - .src = field_align_src, - .r = .{ .simple = .struct_field_attrs }, - } }; - const align_body = zir_field.align_body orelse break :a .none; - const align_ref = try sema.resolveInlineBody(&block, align_body, zir_index); - break :a try sema.analyzeAsAlign(&block, field_align_src, align_ref); - }; - if (field_ty.zigTypeTag(zcu) == .@"opaque") { return sema.failWithOwnedErrorMsg(&block, msg: { const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in struct", .{field_ty.fmt(pt)}); @@ -186,7 +230,8 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { break :msg msg; }); } - if (struct_obj.layout == .@"extern" and !try sema.validateExternType(field_ty, .struct_field)) { + + if (struct_obj.layout == .@"extern" and !field_ty.validateExtern(.struct_field, zcu)) { return sema.failWithOwnedErrorMsg(&block, msg: { const msg = try sema.errMsg(field_ty_src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); errdefer msg.destroy(gpa); @@ -195,35 +240,14 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { break :msg msg; }); } - - struct_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern(); - if (struct_obj.field_aligns.len != 0) { - struct_obj.field_aligns.get(ip)[zir_field.idx] = explicit_field_align; - } else { - assert(explicit_field_align == .none); - } } - try finishStructLayout(sema, &block, struct_ty.srcLoc(zcu), struct_ty.toIntern(), &struct_obj); -} + // Fields are okay. Now we need to resolve the struct's overall layout (size, field offsets, etc). -/// Called after populating field types and alignments; populates field offsets, runtime order, and -/// overall struct layout information (size, alignment, comptime-only state, etc). -pub fn finishStructLayout( - sema: *Sema, - /// Only used to report compile errors. - block: *Block, - struct_src: LazySrcLoc, - struct_ty: InternPool.Index, - struct_obj: *const InternPool.LoadedStructType, -) SemaError!void { - const pt = sema.pt; - const zcu = pt.zcu; - const comp = zcu.comp; - const io = comp.io; - const ip = &zcu.intern_pool; + var any_comptime_fields = false; var comptime_only = false; var one_possible_value = true; + var has_runtime_bits = false; var struct_align: Alignment = .@"1"; // Unlike `struct_obj.field_aligns`, these are not `.none`. const resolved_field_aligns = try sema.arena.alloc(Alignment, struct_obj.field_names.len); @@ -240,12 +264,15 @@ pub fn finishStructLayout( // Non-`comptime` fields contribute to the struct's layout. struct_align = struct_align.maxStrict(field_align); if (field_ty.comptimeOnly(zcu)) comptime_only = true; + if (field_ty.hasRuntimeBits(zcu)) has_runtime_bits = true; if (try field_ty.onePossibleValue(pt) == null) one_possible_value = false; if (struct_obj.layout == .auto) { struct_obj.field_runtime_order.get(ip)[field_idx] = @enumFromInt(field_idx); } - } else if (struct_obj.layout == .auto) { + } else { + assert(struct_obj.layout == .auto); // comptime fields not allowed in extern or packed structs struct_obj.field_runtime_order.get(ip)[field_idx] = .omitted; // comptime fields are not in the runtime order + any_comptime_fields = true; } align_out.* = field_align; } @@ -297,75 +324,53 @@ pub fn finishStructLayout( cur_offset = offset + field_ty.abiSize(zcu); } const struct_size = std.math.cast(u32, struct_align.forward(cur_offset)) orelse return sema.fail( - block, - struct_src, + &block, + struct_ty.srcLoc(zcu), "struct layout requires size {d}, this compiler implementation supports up to {d}", .{ struct_align.forward(cur_offset), std.math.maxInt(u32) }, ); ip.resolveStructLayout( io, - struct_ty, + struct_ty.toIntern(), struct_size, struct_align, false, // MLUGG TODO XXX NPV one_possible_value, comptime_only, + has_runtime_bits, ); + + if (any_comptime_fields and !struct_obj.is_reified) { + // We also resolve field inits in this case. MLUGG TODO: this sucks, see TODO in resolveStructDefaults + return resolveStructDefaultsInner(sema, &block, &struct_obj); + } } /// Asserts that `struct_ty` is a packed struct, and that `sema.owner` is that type. /// This function *does* register the `src_hash` dependency on the struct. -pub fn resolvePackedStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { +fn resolvePackedStructLayout( + sema: *Sema, + block: *Block, + struct_ty: Type, + struct_obj: *const InternPool.LoadedStructType, +) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; + const io = comp.io; const gpa = comp.gpa; const ip = &zcu.intern_pool; - assert(sema.owner.unwrap().type_layout == struct_ty.toIntern()); - - const struct_obj = ip.loadStructType(struct_ty.toIntern()); - const zir_index = struct_obj.zir_index.resolve(ip).?; - - assert(struct_obj.layout == .@"packed"); - - try sema.declareDependency(.{ .src_hash = struct_obj.zir_index }); - - var block: Block = .{ - .parent = null, - .sema = sema, - .namespace = struct_obj.namespace, - .instructions = .{}, - .inlining = null, - .comptime_reason = undefined, // always set before using `block` - .src_base_inst = struct_obj.zir_index, - .type_name_ctx = struct_obj.name, - }; - defer assert(block.instructions.items.len == 0); - + // Resolve the layout of all fields, and check their types are allowed. + // Also count the number of bits while we're at it. var field_bits: u64 = 0; - const zir_struct = sema.code.getStructDecl(zir_index); - var field_it = zir_struct.iterateFields(); - while (field_it.next()) |zir_field| { - const field_ty_src: LazySrcLoc = .{ - .base_node_inst = struct_obj.zir_index, - .offset = .{ .container_field_type = zir_field.idx }, - }; - const field_ty: Type = field_ty: { - block.comptime_reason = .{ .reason = .{ - .src = field_ty_src, - .r = .{ .simple = .struct_field_types }, - } }; - const type_ref = try sema.resolveInlineBody(&block, zir_field.type_body, zir_index); - break :field_ty try sema.analyzeAsType(&block, field_ty_src, type_ref); - }; + for (struct_obj.field_types.get(ip), 0..) |field_ty_ip, field_index| { + const field_ty: Type = .fromInterned(field_ty_ip); assert(!field_ty.isGenericPoison()); - struct_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern(); - + const field_ty_src = block.src(.{ .container_field_type = @intCast(field_index) }); try sema.ensureLayoutResolved(field_ty); - if (field_ty.zigTypeTag(zcu) == .@"opaque") { - return sema.failWithOwnedErrorMsg(&block, msg: { + return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in struct", .{field_ty.fmt(pt)}); errdefer msg.destroy(gpa); try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{}); @@ -373,62 +378,73 @@ pub fn resolvePackedStructLayout(sema: *Sema, struct_ty: Type) CompileError!void break :msg msg; }); } - if (!field_ty.packable(zcu)) { - return sema.failWithOwnedErrorMsg(&block, msg: { - const msg = try sema.errMsg(field_ty_src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); - errdefer msg.destroy(gpa); - try sema.explainWhyTypeIsNotPackable(msg, field_ty_src, field_ty); - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }); - } + if (field_ty.unpackable(zcu)) |reason| return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(field_ty_src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); + errdefer msg.destroy(gpa); + try sema.explainWhyTypeIsUnpackable(msg, field_ty_src, reason); + try sema.addDeclaredHereNote(msg, field_ty); + break :msg msg; + }); assert(!field_ty.comptimeOnly(zcu)); // packable types are not comptime-only field_bits += field_ty.bitSize(zcu); } - try resolvePackedStructBackingInt(sema, &block, field_bits, struct_ty, &struct_obj); -} + const explicit_backing_int_ty: ?Type = if (struct_obj.is_reified) ty: { + break :ty switch (struct_obj.packed_backing_mode) { + .explicit => .fromInterned(struct_obj.packed_backing_int_type), + .auto => null, + }; + } else ty: { + const zir_index = struct_obj.zir_index.resolve(ip).?; + const zir_struct = sema.code.getStructDecl(zir_index); + const backing_int_type_body = zir_struct.backing_int_type_body orelse { + break :ty null; // inferred backing type + }; + // Explicitly specified, so evaluate the backing int type expression. + const backing_int_type_src = block.src(.container_arg); + block.comptime_reason = .{ .reason = .{ + .src = backing_int_type_src, + .r = .{ .simple = .packed_struct_backing_int_type }, + } }; + const type_ref = try sema.resolveInlineBody(block, backing_int_type_body, zir_index); + break :ty try sema.analyzeAsType(block, backing_int_type_src, .packed_struct_backing_int_type, type_ref); + }; -pub fn resolvePackedStructBackingInt( - sema: *Sema, - block: *Block, - field_bits: u64, - struct_ty: Type, - struct_obj: *const InternPool.LoadedStructType, -) SemaError!void { - const pt = sema.pt; - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const io = comp.io; - const ip = &zcu.intern_pool; - - switch (struct_obj.packed_backing_mode) { - .explicit => { - // We only need to validate the type. - const backing_ty: Type = .fromInterned(struct_obj.packed_backing_int_type); - assert(backing_ty.zigTypeTag(zcu) == .int); - if (field_bits != backing_ty.intInfo(zcu).bits) return sema.failWithOwnedErrorMsg(block, msg: { - const src = struct_ty.srcLoc(zcu); - const msg = try sema.errMsg(src, "backing integer bit width does not match total bit width of fields", .{}); - errdefer msg.destroy(gpa); - try sema.errNote(src, msg, "backing integer '{f}' has bit width '{d}'", .{ backing_ty.fmt(pt), backing_ty.bitSize(zcu) }); - try sema.errNote(src, msg, "struct fields have total bit width '{d}'", .{field_bits}); - break :msg msg; - }); - }, - .auto => { - // We need to generate the inferred tag. - const want_bits = std.math.cast(u16, field_bits) orelse return sema.fail( - block, - struct_ty.srcLoc(zcu), - "packed struct bit width '{d}' exceeds maximum bit width of 65535", - .{field_bits}, - ); - const backing_int = try pt.intType(.unsigned, want_bits); - ip.resolvePackedStructBackingInt(io, struct_ty.toIntern(), backing_int.toIntern()); - }, - } + // Finally, either validate or infer the backing int type. + const backing_int_ty: Type = if (explicit_backing_int_ty) |backing_ty| ty: { + // We only need to validate the type. + if (backing_ty.zigTypeTag(zcu) != .int) return sema.failWithOwnedErrorMsg(block, msg: { + const src = struct_ty.srcLoc(zcu); + const msg = try sema.errMsg(src, "expected backing integer type, found '{f}'", .{backing_ty.fmt(pt)}); + errdefer msg.destroy(gpa); + try sema.errNote(src, msg, "backing integer '{f}' has bit width '{d}'", .{ backing_ty.fmt(pt), backing_ty.bitSize(zcu) }); + try sema.errNote(src, msg, "struct fields have total bit width '{d}'", .{field_bits}); + break :msg msg; + }); + if (field_bits != backing_ty.intInfo(zcu).bits) return sema.failWithOwnedErrorMsg(block, msg: { + const src = struct_ty.srcLoc(zcu); + const msg = try sema.errMsg(src, "backing integer bit width does not match total bit width of fields", .{}); + errdefer msg.destroy(gpa); + try sema.errNote(src, msg, "backing integer '{f}' has bit width '{d}'", .{ backing_ty.fmt(pt), backing_ty.bitSize(zcu) }); + try sema.errNote(src, msg, "struct fields have total bit width '{d}'", .{field_bits}); + break :msg msg; + }); + break :ty backing_ty; + } else ty: { + // We need to generate the inferred tag. + const backing_int_bits = std.math.cast(u16, field_bits) orelse return sema.fail( + block, + struct_ty.srcLoc(zcu), + "packed struct bit width '{d}' exceeds maximum bit width of 65535", + .{field_bits}, + ); + break :ty try pt.intType(.unsigned, backing_int_bits); + }; + ip.resolvePackedStructLayout( + io, + struct_ty.toIntern(), + backing_int_ty.toIntern(), + ); } /// Asserts that `struct_ty` is a non-tuple struct, and that `sema.owner` is that type. @@ -436,25 +452,33 @@ pub fn resolvePackedStructBackingInt( pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; const ip = &zcu.intern_pool; - assert(sema.owner.unwrap().type_inits == struct_ty.toIntern()); + assert(sema.owner.unwrap().struct_defaults == struct_ty.toIntern()); try sema.ensureLayoutResolved(struct_ty); const struct_obj = ip.loadStructType(struct_ty.toIntern()); - const zir_index = struct_obj.zir_index.resolve(ip).?; try sema.declareDependency(.{ .src_hash = struct_obj.zir_index }); + // This logic isn't used for reified structs, because the signature of `@Struct` requires that + // default values are populated and correctly typed from the moment the struct type is interned + // (because `Sema.zirReifyStruct` had to dereference the default value from a pointer). + assert(!struct_obj.is_reified); + if (struct_obj.field_defaults.len == 0) { // The struct has no default field values, so the slice has been omitted. return; } - const field_types = struct_obj.field_types.get(ip); + for (struct_obj.field_is_comptime_bits.getAll(ip)) |bit_bag| { + if (bit_bag != 0) { + // There is a comptime field, so layout resolution already filled in the defaults for us! + // MLUGG TODO: perhaps a better idea would be for layout resolution to populate only the defaults *for comptime fields*. + return; + } + } var block: Block = .{ .parent = null, @@ -468,16 +492,30 @@ pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void { }; defer assert(block.instructions.items.len == 0); + return resolveStructDefaultsInner(sema, &block, &struct_obj); +} +/// MLUGG TODO: i dislike this, see the 'TODO' in the prev func +fn resolveStructDefaultsInner( + sema: *Sema, + block: *Block, + struct_obj: *const InternPool.LoadedStructType, +) CompileError!void { + const pt = sema.pt; + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const ip = &zcu.intern_pool; + // We'll need to map the struct decl instruction to provide result types + const zir_index = struct_obj.zir_index.resolve(ip).?; try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index}); + const field_types = struct_obj.field_types.get(ip); + const zir_struct = sema.code.getStructDecl(zir_index); var field_it = zir_struct.iterateFields(); while (field_it.next()) |zir_field| { - const default_val_src: LazySrcLoc = .{ - .base_node_inst = struct_obj.zir_index, - .offset = .{ .container_field_value = zir_field.idx }, - }; + const default_val_src = block.src(.{ .container_field_value = zir_field.idx }); block.comptime_reason = .{ .reason = .{ .src = default_val_src, .r = .{ .simple = .struct_field_default_value }, @@ -491,13 +529,13 @@ pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void { // Provide the result type sema.inst_map.putAssumeCapacity(zir_index, .fromIntern(field_ty.toIntern())); defer assert(sema.inst_map.remove(zir_index)); - break :ref try sema.resolveInlineBody(&block, default_body, zir_index); + break :ref try sema.resolveInlineBody(block, default_body, zir_index); }; - const coerced = try sema.coerce(&block, field_ty, uncoerced, default_val_src); - const default_val = try sema.resolveConstValue(&block, default_val_src, coerced, null); + const coerced = try sema.coerce(block, field_ty, uncoerced, default_val_src); + const default_val = try sema.resolveConstValue(block, default_val_src, coerced, null); if (default_val.canMutateComptimeVarState(zcu)) { const field_name = struct_obj.field_names.get(ip)[zir_field.idx]; - return sema.failWithContainsReferenceToComptimeVar(&block, default_val_src, field_name, "field default value", default_val); + return sema.failWithContainsReferenceToComptimeVar(block, default_val_src, field_name, "field default value", default_val); } struct_obj.field_defaults.get(ip)[zir_field.idx] = default_val.toIntern(); } @@ -508,6 +546,7 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; + const io = comp.io; const gpa = comp.gpa; const ip = &zcu.intern_pool; @@ -516,10 +555,6 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { const union_obj = ip.loadUnionType(union_ty.toIntern()); const zir_index = union_obj.zir_index.resolve(ip).?; - assert(union_obj.layout != .@"packed"); - - try sema.declareDependency(.{ .src_hash = union_obj.zir_index }); - var block: Block = .{ .parent = null, .sema = sema, @@ -532,48 +567,169 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { }; defer assert(block.instructions.items.len == 0); - const zir_union = sema.code.getUnionDecl(zir_index); - var field_it = zir_union.iterateFields(); - while (field_it.next()) |zir_field| { - const field_ty_src: LazySrcLoc = .{ - .base_node_inst = union_obj.zir_index, - .offset = .{ .container_field_type = zir_field.idx }, - }; - const field_align_src: LazySrcLoc = .{ - .base_node_inst = union_obj.zir_index, - .offset = .{ .container_field_align = zir_field.idx }, + // MLUGG TODO: this is fucking ugly bro + const explicit_enum_tag_ty: ?Type = if (union_obj.is_reified) ty: { + break :ty switch (union_obj.enum_tag_mode) { + .explicit => .fromInterned(union_obj.enum_tag_type), + .auto => null, }; + } else ty: { + const zir_union = sema.code.getUnionDecl(zir_index); + if (zir_union.kind != .tagged_explicit) { + break :ty null; // enum tag type will be automatically generated + } + // Explicitly specified, so evaluate the enum tag type expression. + const tag_type_body = zir_union.arg_type_body.?; + const tag_type_src = block.src(.container_arg); + block.comptime_reason = .{ .reason = .{ + .src = tag_type_src, + .r = .{ .simple = .union_enum_tag_type }, + } }; + const type_ref = try sema.resolveInlineBody(&block, tag_type_body, zir_index); + break :ty try sema.analyzeAsType(&block, tag_type_src, .union_enum_tag_type, type_ref); + }; + const enum_tag_ty: Type = if (explicit_enum_tag_ty) |enum_tag_ty| ty: { + if (enum_tag_ty.zigTypeTag(zcu) != .@"enum") return sema.fail( + &block, + block.src(.container_arg), + "expected enum tag type, found '{f}'", + .{enum_tag_ty.fmt(pt)}, + ); + break :ty enum_tag_ty; + } else switch (try ip.getGeneratedEnumTagType(gpa, io, pt.tid, .{ + .union_type = union_ty.toIntern(), + // MLUGG TODO: a bit hacky icl + .int_tag_mode = mode: { + if (union_obj.is_reified) break :mode .auto; + const zir_union = sema.code.getUnionDecl(zir_index); + if (zir_union.kind != .tagged_enum_explicit) break :mode .auto; + break :mode .explicit; + }, + .fields_len = @intCast(union_obj.field_types.len), + })) { + .existing => |tag_ty| .fromInterned(tag_ty), + .wip => |wip| tag_ty: { + errdefer wip.cancel(ip, pt.tid); + _ = wip.setName(ip, try ip.getOrPutStringFmt( + gpa, + io, + pt.tid, + "@typeInfo({f}).@\"union\".tag_type.?", + .{union_obj.name.fmt(ip)}, + .no_embedded_nulls, + ), .none); + const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ + .parent = union_obj.namespace.toOptional(), + .owner_type = wip.index, + .file_scope = zcu.namespacePtr(union_obj.namespace).file_scope, + .generation = zcu.generation, + }); + if (comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); + try zcu.outdated.ensureUnusedCapacity(gpa, 1); + try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); + errdefer comptime unreachable; // because we don't remove the `outdated` entry + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); + zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); + break :tag_ty .fromInterned(wip.finish(ip, new_namespace_index)); + }, + }; - const field_ty: Type = field_ty: { - block.comptime_reason = .{ .reason = .{ - .src = field_ty_src, - .r = .{ .simple = .union_field_types }, - } }; - const type_body = zir_field.type_body orelse break :field_ty .void; - const type_ref = try sema.resolveInlineBody(&block, type_body, zir_index); - break :field_ty try sema.analyzeAsType(&block, field_ty_src, type_ref); - }; + try sema.ensureLayoutResolved(enum_tag_ty); + const enum_obj = ip.loadEnumType(enum_tag_ty.toIntern()); + + if (union_obj.is_reified) { + // We have field names in `union_obj.reified_field_names`, but we haven't + // checked them against the backing type yet. + const union_field_names = union_obj.reified_field_names.get(ip); + match_fields: { + // We can efficiently *check* if the fields match... + if (union_field_names.len == enum_obj.field_names.len) { + for (union_field_names, enum_obj.field_names.get(ip)) |union_field_name, enum_field_name| { + if (!std.mem.eql(u8, union_field_name.toSlice(ip), enum_field_name.toSlice(ip))) break; + } else { + break :match_fields; + } + } + // ...but if they don't, reporting a nice error is a little more involved. If some field + // is present in the enum but not the union, or vice versa, we will report that instead + // of a generic "field order mismatch" error. Of course, this error is impossible for a + // generated tag type, because we populated that from the union ZIR! + assert(enum_obj.owner_union != union_ty.toIntern()); + return failUnionFieldMismatch(sema, &block, union_field_names, enum_tag_ty, &enum_obj); + } + } else { + // Declared unions do not have field types or aligns populated yet. + // We also need to check the field names match the backing enum. + try sema.declareDependency(.{ .src_hash = union_obj.zir_index }); + const zir_union = sema.code.getUnionDecl(zir_index); + + // We'll first check the field names against the backing enum, and only analyze the types + // once we know the fields match one-to-one. + match_fields: { + // We can efficiently *check* if the fields match... + if (zir_union.field_names.len == enum_obj.field_names.len) { + for (zir_union.field_names, enum_obj.field_names.get(ip)) |union_field_name_zir, enum_field_name| { + const union_field_name_slice = sema.code.nullTerminatedString(union_field_name_zir); + if (!std.mem.eql(u8, union_field_name_slice, enum_field_name.toSlice(ip))) break; + } else { + break :match_fields; + } + } + // ...but if they don't, reporting a nice error is a little more involved. If some field + // is present in the enum but not the union, or vice versa, we will report that instead + // of a generic "field order mismatch" error. Of course, this error is impossible for a + // generated tag type, because we populated that from the union ZIR! + assert(enum_obj.owner_union != union_ty.toIntern()); + const union_field_names = try sema.arena.alloc(InternPool.NullTerminatedString, zir_union.field_names.len); + for (zir_union.field_names, union_field_names) |name_zir, *name| { + name.* = try ip.getOrPutString(gpa, io, pt.tid, sema.code.nullTerminatedString(name_zir), .no_embedded_nulls); + } + return failUnionFieldMismatch(sema, &block, union_field_names, enum_tag_ty, &enum_obj); + } + + // Field names okay; populate types and aligns. + var field_it = zir_union.iterateFields(); + while (field_it.next()) |zir_field| { + const field_ty_src = block.src(.{ .container_field_type = zir_field.idx }); + const field_ty: Type = field_ty: { + block.comptime_reason = .{ .reason = .{ + .src = field_ty_src, + .r = .{ .simple = .union_field_types }, + } }; + const type_body = zir_field.type_body orelse break :field_ty .void; + const type_ref = try sema.resolveInlineBody(&block, type_body, zir_index); + break :field_ty try sema.analyzeAsType(&block, field_ty_src, .union_field_types, type_ref); + }; + union_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern(); + + const field_align_src = block.src(.{ .container_field_align = zir_field.idx }); + const explicit_field_align: Alignment = a: { + block.comptime_reason = .{ .reason = .{ + .src = field_align_src, + .r = .{ .simple = .union_field_attrs }, + } }; + const align_body = zir_field.align_body orelse break :a .none; + const align_ref = try sema.resolveInlineBody(&block, align_body, zir_index); + break :a try sema.analyzeAsAlign(&block, field_align_src, align_ref); + }; + if (union_obj.field_aligns.len != 0) { + union_obj.field_aligns.get(ip)[zir_field.idx] = explicit_field_align; + } else { + assert(explicit_field_align == .none); + } + } + } + + if (union_obj.layout == .@"packed") { + return resolvePackedUnionLayout(sema, &block, union_ty, &union_obj, enum_tag_ty); + } + + // Resolve the layout of all fields, and check their types are allowed. + for (union_obj.field_types.get(ip), 0..) |field_ty_ip, field_index| { + const field_ty: Type = .fromInterned(field_ty_ip); assert(!field_ty.isGenericPoison()); - union_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern(); - + const field_ty_src = block.src(.{ .container_field_type = @intCast(field_index) }); try sema.ensureLayoutResolved(field_ty); - - const explicit_field_align: Alignment = a: { - block.comptime_reason = .{ .reason = .{ - .src = field_align_src, - .r = .{ .simple = .union_field_attrs }, - } }; - const align_body = zir_field.align_body orelse break :a .none; - const align_ref = try sema.resolveInlineBody(&block, align_body, zir_index); - break :a try sema.analyzeAsAlign(&block, field_align_src, align_ref); - }; - - if (union_obj.field_aligns.len != 0) { - union_obj.field_aligns.get(ip)[zir_field.idx] = explicit_field_align; - } else { - assert(explicit_field_align == .none); - } - if (field_ty.zigTypeTag(zcu) == .@"opaque") { return sema.failWithOwnedErrorMsg(&block, msg: { const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in union", .{field_ty.fmt(pt)}); @@ -583,7 +739,7 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { break :msg msg; }); } - if (union_obj.layout == .@"extern" and !try sema.validateExternType(field_ty, .union_field)) { + if (union_obj.layout == .@"extern" and !field_ty.validateExtern(.union_field, zcu)) { return sema.failWithOwnedErrorMsg(&block, msg: { const msg = try sema.errMsg(field_ty_src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); errdefer msg.destroy(gpa); @@ -594,36 +750,11 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { } } - try finishUnionLayout( - sema, - &block, - union_ty.srcLoc(zcu), - union_ty.toIntern(), - &union_obj, - .fromInterned(union_obj.enum_tag_type), - ); -} - -/// Called after populating field types and alignments; populates overall union layout -/// information (size, alignment, comptime-only state, etc). -pub fn finishUnionLayout( - sema: *Sema, - /// Only used to report compile errors. - block: *Block, - union_src: LazySrcLoc, - union_ty: InternPool.Index, - union_obj: *const InternPool.LoadedUnionType, - enum_tag_ty: Type, -) SemaError!void { - const pt = sema.pt; - const zcu = pt.zcu; - const comp = zcu.comp; - const io = comp.io; - const ip = &zcu.intern_pool; - + // Fields are okay. Now we need to resolve the union's overall layout (size, alignment, etc). var payload_align: Alignment = .@"1"; var payload_size: u64 = 0; var comptime_only = false; + var has_runtime_bits = union_obj.runtime_tag != .none and enum_tag_ty.hasRuntimeBits(zcu); var possible_values: enum { none, one, many } = .none; for (0..union_obj.field_types.len) |field_idx| { const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]); @@ -637,6 +768,7 @@ pub fn finishUnionLayout( payload_align = payload_align.maxStrict(field_align); payload_size = @max(payload_size, field_ty.abiSize(zcu)); if (field_ty.comptimeOnly(zcu)) comptime_only = true; + if (field_ty.hasRuntimeBits(zcu)) has_runtime_bits = true; if (!field_ty.isNoReturn(zcu)) { if (try field_ty.onePossibleValue(pt) != null) { possible_values = .many; // this field alone has many possible values @@ -664,211 +796,210 @@ pub fn finishUnionLayout( }; const casted_size = std.math.cast(u32, size) orelse return sema.fail( - block, - union_src, + &block, + union_ty.srcLoc(zcu), "union layout requires size {d}, this compiler implementation supports up to {d}", .{ size, std.math.maxInt(u32) }, ); ip.resolveUnionLayout( io, - union_ty, + union_ty.toIntern(), + enum_tag_ty.toIntern(), casted_size, @intCast(padding), // okay because padding is no greater than size alignment, possible_values == .none, // MLUGG TODO: make sure queries use `LoadedUnionType.has_no_possible_value`! possible_values == .one, comptime_only, + has_runtime_bits, ); } - -pub fn resolvePackedUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { +fn failUnionFieldMismatch(sema: *Sema, block: *Block, union_field_names: []const InternPool.NullTerminatedString, enum_tag_ty: Type, enum_obj: *const InternPool.LoadedEnumType) CompileError { const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; const gpa = comp.gpa; const ip = &zcu.intern_pool; - - assert(sema.owner.unwrap().type_layout == union_ty.toIntern()); - - const union_obj = ip.loadUnionType(union_ty.toIntern()); - const zir_index = union_obj.zir_index.resolve(ip).?; - - assert(union_obj.layout == .@"packed"); - - try sema.declareDependency(.{ .src_hash = union_obj.zir_index }); - - var block: Block = .{ - .parent = null, - .sema = sema, - .namespace = union_obj.namespace, - .instructions = .{}, - .inlining = null, - .comptime_reason = undefined, // always set before using `block` - .src_base_inst = union_obj.zir_index, - .type_name_ctx = union_obj.name, - }; - defer assert(block.instructions.items.len == 0); - - const zir_union = sema.code.getUnionDecl(zir_index); - var field_it = zir_union.iterateFields(); - while (field_it.next()) |zir_field| { - const field_ty_src: LazySrcLoc = .{ - .base_node_inst = union_obj.zir_index, - .offset = .{ .container_field_type = zir_field.idx }, + const enum_to_union_map = try sema.arena.alloc(?u32, enum_obj.field_names.len); + @memset(enum_to_union_map, null); + for (union_field_names, 0..) |field_name, union_field_index| { + if (enum_obj.nameIndex(ip, field_name)) |enum_field_index| { + enum_to_union_map[enum_field_index] = @intCast(union_field_index); + continue; + } + const union_field_src = block.src(.{ .container_field_name = @intCast(union_field_index) }); + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(union_field_src, "no field named '{f}' in enum '{f}'", .{ field_name.fmt(ip), enum_tag_ty.fmt(pt) }); + errdefer msg.destroy(gpa); + try sema.addDeclaredHereNote(msg, enum_tag_ty); + break :msg msg; + }); + } + for (enum_to_union_map, 0..) |union_field_index, enum_field_index| { + if (union_field_index != null) continue; + const field_name_ip = enum_obj.field_names.get(ip)[enum_field_index]; + const enum_field_src: LazySrcLoc = .{ + .base_node_inst = enum_tag_ty.typeDeclInstAllowGeneratedTag(zcu).?, + .offset = .{ .container_field_name = @intCast(enum_field_index) }, }; - const field_ty: Type = field_ty: { - block.comptime_reason = .{ .reason = .{ - .src = field_ty_src, - .r = .{ .simple = .union_field_types }, - } }; - // MLUGG TODO: i think this should probably be a compile error? (if so, it's an astgen one, right?) - const type_body = zir_field.type_body orelse break :field_ty .void; - const type_ref = try sema.resolveInlineBody(&block, type_body, zir_index); - break :field_ty try sema.analyzeAsType(&block, field_ty_src, type_ref); + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(block.nodeOffset(.zero), "enum field '{f}' missing from union", .{field_name_ip.fmt(ip)}); + errdefer msg.destroy(gpa); + try sema.errNote(enum_field_src, msg, "enum field here", .{}); + break :msg msg; + }); + } + // The only problem is the field ordering. + for (enum_to_union_map, 0..) |union_field_index, enum_field_index| { + if (union_field_index.? == enum_field_index) continue; + const field_name = enum_obj.field_names.get(ip)[enum_field_index]; + const union_field_src = block.src(.{ .container_field_name = union_field_index.? }); + const enum_field_src: LazySrcLoc = .{ + .base_node_inst = enum_tag_ty.typeDeclInstAllowGeneratedTag(zcu).?, + .offset = .{ .container_field_name = @intCast(enum_field_index) }, }; - assert(!field_ty.isGenericPoison()); - union_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern(); - - assert(zir_field.align_body == null); // packed union fields cannot be aligned - assert(zir_field.value_body == null); // packed union fields cannot have tag values - - try sema.ensureLayoutResolved(field_ty); - - if (field_ty.zigTypeTag(zcu) == .@"opaque") { - return sema.failWithOwnedErrorMsg(&block, msg: { - const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in union", .{field_ty.fmt(pt)}); - errdefer msg.destroy(gpa); - try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{}); - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }); - } - if (!field_ty.packable(zcu)) { - return sema.failWithOwnedErrorMsg(&block, msg: { - const msg = try sema.errMsg(field_ty_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); - errdefer msg.destroy(gpa); - try sema.explainWhyTypeIsNotPackable(msg, field_ty_src, field_ty); - try sema.addDeclaredHereNote(msg, field_ty); - break :msg msg; - }); - } - assert(!field_ty.comptimeOnly(zcu)); // packable types are not comptime-only + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(block.nodeOffset(.zero), "union field order does not match tag enum field order", .{}); + errdefer msg.destroy(gpa); + try sema.errNote(union_field_src, msg, "union field '{f}' is index {d}", .{ field_name.fmt(ip), union_field_index.? }); + try sema.errNote(enum_field_src, msg, "enum field '{f}' is index {d}", .{ field_name.fmt(ip), enum_field_index }); + break :msg msg; + }); } - - try resolvePackedUnionBackingInt(sema, &block, union_ty, &union_obj, false); + unreachable; // we already determined that *something* is wrong } - -/// MLUGG TODO doc comment; asserts all fields are resolved or whatever -pub fn resolvePackedUnionBackingInt( +fn resolvePackedUnionLayout( sema: *Sema, block: *Block, union_ty: Type, union_obj: *const InternPool.LoadedUnionType, - is_reified: bool, -) SemaError!void { + enum_tag_ty: Type, +) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; - const gpa = comp.gpa; const io = comp.io; + const gpa = comp.gpa; const ip = &zcu.intern_pool; - switch (union_obj.packed_backing_mode) { - .explicit => { - const backing_int_type: Type = .fromInterned(union_obj.packed_backing_int_type); - const backing_int_bits = backing_int_type.intInfo(zcu).bits; - for (union_obj.field_types.get(ip), 0..) |field_type_ip, field_idx| { - const field_type: Type = .fromInterned(field_type_ip); - const field_bits = field_type.bitSize(zcu); - if (field_bits != backing_int_bits) return sema.failWithOwnedErrorMsg(block, msg: { - const field_ty_src: LazySrcLoc = .{ - .base_node_inst = union_obj.zir_index, - .offset = if (is_reified) - .nodeOffset(.zero) - else - .{ .container_field_type = @intCast(field_idx) }, - }; - const msg = try sema.errMsg(field_ty_src, "field bit width does not match backing integer", .{}); - errdefer msg.destroy(gpa); - try sema.errNote(field_ty_src, msg, "field type '{f}' has bit width '{d}'", .{ field_type.fmt(pt), field_bits }); - try sema.errNote(field_ty_src, msg, "backing integer '{f}' has bit width '{d}'", .{ backing_int_type.fmt(pt), backing_int_bits }); - try sema.errNote(field_ty_src, msg, "all fields in a packed union must have the same bit width", .{}); - break :msg msg; - }); - } - }, - .auto => switch (union_obj.field_types.len) { - 0 => ip.resolvePackedUnionBackingInt(io, union_ty.toIntern(), .u0_type), - else => { - const field_types = union_obj.field_types.get(ip); - const first_field_type: Type = .fromInterned(field_types[0]); - const first_field_bits = first_field_type.bitSize(zcu); - for (field_types[1..], 1..) |field_type_ip, field_idx| { - const field_type: Type = .fromInterned(field_type_ip); - const field_bits = field_type.bitSize(zcu); - if (field_bits != first_field_bits) return sema.failWithOwnedErrorMsg(block, msg: { - const first_field_ty_src: LazySrcLoc = .{ - .base_node_inst = union_obj.zir_index, - .offset = if (is_reified) - .nodeOffset(.zero) - else - .{ .container_field_type = 0 }, - }; - const field_ty_src: LazySrcLoc = .{ - .base_node_inst = union_obj.zir_index, - .offset = if (is_reified) - .nodeOffset(.zero) - else - .{ .container_field_type = @intCast(field_idx) }, - }; - const msg = try sema.errMsg(field_ty_src, "field bit width does not match earlier field", .{}); - errdefer msg.destroy(gpa); - try sema.errNote(field_ty_src, msg, "field type '{f}' has bit width '{d}'", .{ field_type.fmt(pt), field_bits }); - try sema.errNote(first_field_ty_src, msg, "other field type '{f}' has bit width '{d}'", .{ first_field_type.fmt(pt), first_field_bits }); - try sema.errNote(field_ty_src, msg, "all fields in a packed union must have the same bit width", .{}); - break :msg msg; - }); - } - const backing_int_bits = std.math.cast(u16, first_field_bits) orelse return sema.fail( - block, - block.nodeOffset(.zero), - "packed union bit width '{d}' exceeds maximum bit width of 65535", - .{first_field_bits}, - ); - const backing_int_type = try pt.intType(.unsigned, backing_int_bits); - ip.resolvePackedUnionBackingInt(io, union_ty.toIntern(), backing_int_type.toIntern()); - }, - }, + + // Resolve the layout of all fields, and check their types are allowed. + for (union_obj.field_types.get(ip), 0..) |field_ty_ip, field_index| { + const field_ty: Type = .fromInterned(field_ty_ip); + assert(!field_ty.isGenericPoison()); + const field_ty_src = block.src(.{ .container_field_type = @intCast(field_index) }); + try sema.ensureLayoutResolved(field_ty); + if (field_ty.zigTypeTag(zcu) == .@"opaque") { + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in union", .{field_ty.fmt(pt)}); + errdefer msg.destroy(gpa); + try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{}); + try sema.addDeclaredHereNote(msg, field_ty); + break :msg msg; + }); + } + if (field_ty.unpackable(zcu)) |reason| return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(field_ty_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); + errdefer msg.destroy(gpa); + try sema.explainWhyTypeIsUnpackable(msg, field_ty_src, reason); + try sema.addDeclaredHereNote(msg, field_ty); + break :msg msg; + }); + assert(!field_ty.comptimeOnly(zcu)); // packable types are not comptime-only } + + const explicit_backing_int_ty: ?Type = if (union_obj.is_reified) ty: { + switch (union_obj.packed_backing_mode) { + .explicit => break :ty .fromInterned(union_obj.packed_backing_int_type), + .auto => break :ty null, + } + } else ty: { + const zir_index = union_obj.zir_index.resolve(ip).?; + const zir_union = sema.code.getUnionDecl(zir_index); + const backing_int_type_body = zir_union.arg_type_body orelse { + break :ty null; // inferred backing type + }; + // Explicitly specified, so evaluate the backing int type expression. + const backing_int_type_src = block.src(.container_arg); + block.comptime_reason = .{ .reason = .{ + .src = backing_int_type_src, + .r = .{ .simple = .packed_union_backing_int_type }, + } }; + const type_ref = try sema.resolveInlineBody(block, backing_int_type_body, zir_index); + break :ty try sema.analyzeAsType(block, backing_int_type_src, .packed_union_backing_int_type, type_ref); + }; + + // Finally, either validate or infer the backing int type. + const backing_int_ty: Type = if (explicit_backing_int_ty) |backing_ty| ty: { + const backing_int_bits = backing_ty.intInfo(zcu).bits; + for (union_obj.field_types.get(ip), 0..) |field_type_ip, field_idx| { + const field_type: Type = .fromInterned(field_type_ip); + const field_bits = field_type.bitSize(zcu); + if (field_bits != backing_int_bits) return sema.failWithOwnedErrorMsg(block, msg: { + const field_ty_src = block.src(.{ .container_field_type = @intCast(field_idx) }); + const msg = try sema.errMsg(field_ty_src, "field bit width does not match backing integer", .{}); + errdefer msg.destroy(gpa); + try sema.errNote(field_ty_src, msg, "field type '{f}' has bit width '{d}'", .{ field_type.fmt(pt), field_bits }); + try sema.errNote(field_ty_src, msg, "backing integer '{f}' has bit width '{d}'", .{ backing_ty.fmt(pt), backing_int_bits }); + try sema.errNote(field_ty_src, msg, "all fields in a packed union must have the same bit width", .{}); + break :msg msg; + }); + } + break :ty backing_ty; + } else if (union_obj.field_types.len == 0) ty: { + // Special case: there is no first field to infer the type from. Treat the union as empty (zero-bit). + break :ty .u0; + } else ty: { + const field_types = union_obj.field_types.get(ip); + const first_field_type: Type = .fromInterned(field_types[0]); + const first_field_bits = first_field_type.bitSize(zcu); + for (field_types[1..], 1..) |field_type_ip, field_idx| { + const field_type: Type = .fromInterned(field_type_ip); + const field_bits = field_type.bitSize(zcu); + if (field_bits != first_field_bits) return sema.failWithOwnedErrorMsg(block, msg: { + const first_field_ty_src = block.src(.{ .container_field_type = 0 }); + const field_ty_src = block.src(.{ .container_field_type = @intCast(field_idx) }); + const msg = try sema.errMsg(field_ty_src, "field bit width does not match earlier field", .{}); + errdefer msg.destroy(gpa); + try sema.errNote(field_ty_src, msg, "field type '{f}' has bit width '{d}'", .{ field_type.fmt(pt), field_bits }); + try sema.errNote(first_field_ty_src, msg, "other field type '{f}' has bit width '{d}'", .{ first_field_type.fmt(pt), first_field_bits }); + try sema.errNote(field_ty_src, msg, "all fields in a packed union must have the same bit width", .{}); + break :msg msg; + }); + } + const backing_int_bits = std.math.cast(u16, first_field_bits) orelse return sema.fail( + block, + union_ty.srcLoc(zcu), + "packed union bit width '{d}' exceeds maximum bit width of 65535", + .{first_field_bits}, + ); + break :ty try pt.intType(.unsigned, backing_int_bits); + }; + ip.resolvePackedUnionLayout( + io, + union_ty.toIntern(), + enum_tag_ty.toIntern(), + backing_int_ty.toIntern(), + ); } -/// Asserts that `enum_ty` is an enum and that `sema.owner` is that type. -/// This function *does* register the `src_hash` dependency on the enum. -pub fn resolveEnumValues(sema: *Sema, enum_ty: Type) CompileError!void { +pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; + const io = comp.io; const gpa = comp.gpa; const ip = &zcu.intern_pool; - assert(sema.owner.unwrap().type_inits == enum_ty.toIntern()); + assert(sema.owner.unwrap().type_layout == enum_ty.toIntern()); const enum_obj = ip.loadEnumType(enum_ty.toIntern()); - // We'll populate this map. - const field_value_map = enum_obj.field_value_map.unwrap() orelse { - // The enum has an automatically generated tag and is auto-numbered. We know that we have - // generated a suitably large type in `analyzeEnumDecl`, so we have no work to do. - return; - }; - const maybe_parent_union_obj: ?InternPool.LoadedUnionType = un: { if (enum_obj.owner_union == .none) break :un null; break :un ip.loadUnionType(enum_obj.owner_union); }; + const tracked_inst = enum_obj.zir_index.unwrap() orelse maybe_parent_union_obj.?.zir_index; - const zir_index = tracked_inst.resolve(ip).?; - - try sema.declareDependency(.{ .src_hash = tracked_inst }); var block: Block = .{ .parent = null, @@ -882,7 +1013,139 @@ pub fn resolveEnumValues(sema: *Sema, enum_ty: Type) CompileError!void { }; defer assert(block.instructions.items.len == 0); - const int_tag_ty: Type = .fromInterned(enum_obj.int_tag_type); + // There may be old field names in the map from a previous update. + enum_obj.field_name_map.get(ip).clearRetainingCapacity(); + + if (maybe_parent_union_obj) |*union_obj| { + if (union_obj.is_reified) { + // In the case of reification, the union stores the field names, just for us to copy. + @memcpy(enum_obj.field_names.get(ip), union_obj.reified_field_names.get(ip)); + // The list of field names is now populated, but we haven't checked for duplicates yet, + // nor have we populated the hash map. + for (0..enum_obj.field_names.len) |field_index| { + const name = enum_obj.field_names.get(ip)[field_index]; + if (ip.addFieldName(enum_obj.field_names, enum_obj.field_name_map, name)) |prev_field_index| { + return sema.failWithOwnedErrorMsg(&block, msg: { + const src = block.nodeOffset(.zero); + const msg = try sema.errMsg(src, "duplicate union field '{f}' at index '{d}", .{ name.fmt(ip), field_index }); + errdefer msg.destroy(gpa); + try sema.errNote(src, msg, "previous field at index '{d}'", .{prev_field_index}); + break :msg msg; + }); + } + } + } else { + // Generated tag enums for declared unions do not yet have field names populated. It is + // our job to populate them now. + try sema.declareDependency(.{ .src_hash = union_obj.zir_index }); + const zir_union = sema.code.getUnionDecl(union_obj.zir_index.resolve(ip).?); + for (zir_union.field_names) |zir_field_name| { + const name_slice = sema.code.nullTerminatedString(zir_field_name); + const name = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls); + assert(ip.addFieldName(enum_obj.field_names, enum_obj.field_name_map, name) == null); // AstGen validated this for us + } + } + } else { + if (enum_obj.is_reified) { + // The field names are populated, but we haven't checked for duplicates (nor populated the map) yet. + for (0..enum_obj.field_names.len) |field_index| { + const name = enum_obj.field_names.get(ip)[field_index]; + if (ip.addFieldName(enum_obj.field_names, enum_obj.field_name_map, name)) |prev_field_index| { + return sema.failWithOwnedErrorMsg(&block, msg: { + const src = block.nodeOffset(.zero); + const msg = try sema.errMsg(src, "duplicate enum field '{f}' at index '{d}", .{ name.fmt(ip), field_index }); + errdefer msg.destroy(gpa); + try sema.errNote(src, msg, "previous field at index '{d}'", .{prev_field_index}); + break :msg msg; + }); + } + } + } else { + // Declared enums do not yet have field names populated. It is our job to populate them now. + try sema.declareDependency(.{ .src_hash = enum_obj.zir_index.unwrap().? }); + const zir_enum = sema.code.getEnumDecl(enum_obj.zir_index.unwrap().?.resolve(ip).?); + for (zir_enum.field_names) |zir_field_name| { + const name_slice = sema.code.nullTerminatedString(zir_field_name); + const name = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls); + assert(ip.addFieldName(enum_obj.field_names, enum_obj.field_name_map, name) == null); // AstGen validated this for us + } + } + } + + // Field names populated; now deal with the backing integer type. If explicitly provided, + // validate it; otherwise, infer it. + + const explicit_int_tag_ty: ?Type = if (enum_obj.is_reified) ty: { + break :ty switch (enum_obj.int_tag_mode) { + .explicit => .fromInterned(enum_obj.int_tag_type), + .auto => null, + }; + } else if (maybe_parent_union_obj) |*union_obj| ty: { + if (union_obj.is_reified) { + // Reification has no equivalent of 'union(enum(T))'. + break :ty null; + } + const zir_index = union_obj.zir_index.resolve(ip).?; + const zir_union = sema.code.getUnionDecl(zir_index); + if (zir_union.kind != .tagged_enum_explicit) { + break :ty null; // int tag type will be inferred + } + // Explicitly specified, so evaluate the int tag type expression. + const tag_type_body = zir_union.arg_type_body.?; + const tag_type_src = block.src(.container_arg); + block.comptime_reason = .{ .reason = .{ + .src = tag_type_src, + .r = .{ .simple = .enum_int_tag_type }, + } }; + const type_ref = try sema.resolveInlineBody(&block, tag_type_body, zir_index); + break :ty try sema.analyzeAsType(&block, tag_type_src, .enum_int_tag_type, type_ref); + } else ty: { + const zir_index = enum_obj.zir_index.unwrap().?.resolve(ip).?; + const zir_enum = sema.code.getEnumDecl(zir_index); + const tag_type_body = zir_enum.tag_type_body orelse { + break :ty null; // int tag type will be inferred + }; + // Explicitly specified, so evaluate the int tag type expression. + const tag_type_src = block.src(.container_arg); + block.comptime_reason = .{ .reason = .{ + .src = tag_type_src, + .r = .{ .simple = .enum_int_tag_type }, + } }; + const type_ref = try sema.resolveInlineBody(&block, tag_type_body, zir_index); + break :ty try sema.analyzeAsType(&block, tag_type_src, .enum_int_tag_type, type_ref); + }; + const int_tag_ty: Type = if (explicit_int_tag_ty) |int_tag_ty| ty: { + if (int_tag_ty.zigTypeTag(zcu) != .int) return sema.fail( + &block, + block.src(.container_arg), + "expected integer tag type, found '{f}'", + .{int_tag_ty.fmt(pt)}, + ); + break :ty int_tag_ty; + } else ty: { + // Infer the int tag type from the field count + const bits = Type.smallestUnsignedBits(enum_obj.field_names.len -| 1); + break :ty try pt.intType(.unsigned, bits); + }; + + ip.resolveEnumLayout(io, enum_ty.toIntern(), int_tag_ty.toIntern()); + + // Finally, deal with field values. For declared types we need to analyze the expressions, while + // reified types already have them populated; but either way, we need to populate the hash map + // (and validate the values along the way). + + // We'll populate this map. + const field_value_map = enum_obj.field_value_map.unwrap() orelse { + // The enum is auto-numbered with an inferred tag type. We know that the tag type generated + // earlier is sufficient for the number of fields, so we have nothing more to do. + assert(enum_obj.int_tag_mode == .auto); + return; + }; + + // There may be old field values in here from a previous update. + field_value_map.get(ip).clearRetainingCapacity(); + + const zir_index = tracked_inst.resolve(ip).?; // Map the enum (or union) decl instruction to provide the tag type as the result type try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index}); @@ -891,36 +1154,38 @@ pub fn resolveEnumValues(sema: *Sema, enum_ty: Type) CompileError!void { // First, populate any explicitly provided values. This is the part that actually depends on // the ZIR, and hence depends on whether this is a declared or generated enum. If any explicit - // value is invalid, we'll emit an error here. + // value is straight-up invalid, we'll emit an error here. if (maybe_parent_union_obj) |union_obj| { - const zir_union = sema.code.getUnionDecl(zir_index); - var field_it = zir_union.iterateFields(); - while (field_it.next()) |zir_field| { - const field_val_src: LazySrcLoc = .{ - .base_node_inst = union_obj.zir_index, - .offset = .{ .container_field_value = zir_field.idx }, - }; - block.comptime_reason = .{ .reason = .{ - .src = field_val_src, - .r = .{ .simple = .enum_field_values }, - } }; - const value_body = zir_field.value_body orelse { - enum_obj.field_values.get(ip)[zir_field.idx] = .none; - continue; - }; - const uncoerced = try sema.resolveInlineBody(&block, value_body, zir_index); - const coerced = try sema.coerce(&block, int_tag_ty, uncoerced, field_val_src); - const val = try sema.resolveConstValue(&block, field_val_src, coerced, null); - enum_obj.field_values.get(ip)[zir_field.idx] = val.toIntern(); + if (union_obj.is_reified) { + // Generated tag type for reified union; values already populated. + } else { + // Generated tag type for declared union; evaluate the expressions given in the union declaration. + const zir_union = sema.code.getUnionDecl(zir_index); + var field_it = zir_union.iterateFields(); + while (field_it.next()) |zir_field| { + const field_val_src = block.src(.{ .container_field_value = zir_field.idx }); + block.comptime_reason = .{ .reason = .{ + .src = field_val_src, + .r = .{ .simple = .enum_field_values }, + } }; + const value_body = zir_field.value_body orelse { + enum_obj.field_values.get(ip)[zir_field.idx] = .none; + continue; + }; + const uncoerced = try sema.resolveInlineBody(&block, value_body, zir_index); + const coerced = try sema.coerce(&block, int_tag_ty, uncoerced, field_val_src); + const val = try sema.resolveConstValue(&block, field_val_src, coerced, null); + enum_obj.field_values.get(ip)[zir_field.idx] = val.toIntern(); + } } + } else if (enum_obj.is_reified) { + // Reified enum; values already populated. } else { + // Declared enum; evaluate the expressions given in the enum declaration. const zir_enum = sema.code.getEnumDecl(zir_index); var field_it = zir_enum.iterateFields(); while (field_it.next()) |zir_field| { - const field_val_src: LazySrcLoc = .{ - .base_node_inst = enum_obj.zir_index.unwrap().?, - .offset = .{ .container_field_value = zir_field.idx }, - }; + const field_val_src = block.src(.{ .container_field_value = zir_field.idx }); block.comptime_reason = .{ .reason = .{ .src = field_val_src, .r = .{ .simple = .enum_field_values }, @@ -940,14 +1205,14 @@ pub fn resolveEnumValues(sema: *Sema, enum_ty: Type) CompileError!void { // field values. This is also where we'll detect duplicates. for (0..enum_obj.field_names.len) |field_idx| { - const field_val_src: LazySrcLoc = .{ - .base_node_inst = tracked_inst, - .offset = .{ .container_field_value = @intCast(field_idx) }, - }; + const field_val_src = block.src(.{ .container_field_value = @intCast(field_idx) }); // If the field value was not specified, compute the implicit value. const field_val = val: { const explicit_val = enum_obj.field_values.get(ip)[field_idx]; - if (explicit_val != .none) break :val explicit_val; + if (explicit_val != .none) { + assert(ip.typeOf(explicit_val) == int_tag_ty.toIntern()); + break :val explicit_val; + } if (field_idx == 0) { // Implicit value is 0, which is valid for every integer type. const val = (try pt.intValue(int_tag_ty, 0)).toIntern(); @@ -967,23 +1232,23 @@ pub fn resolveEnumValues(sema: *Sema, enum_ty: Type) CompileError!void { enum_obj.field_values.get(ip)[field_idx] = val; break :val val; }; - const adapter: InternPool.Index.Adapter = .{ .indexes = enum_obj.field_values.get(ip)[0..field_idx] }; - const gop = field_value_map.get(ip).getOrPutAssumeCapacityAdapted(field_val, adapter); - if (!gop.found_existing) continue; - const prev_field_val_src: LazySrcLoc = .{ - .base_node_inst = tracked_inst, - .offset = .{ .container_field_value = @intCast(gop.index) }, - }; - return sema.failWithOwnedErrorMsg(&block, msg: { - const msg = try sema.errMsg(field_val_src, "enum tag value '{f}' already taken", .{ - Value.fromInterned(field_val).fmtValueSema(pt, sema), + if (ip.addFieldTagValue(enum_obj.field_values, field_value_map, field_val)) |prev_field_index| { + return sema.failWithOwnedErrorMsg(&block, msg: { + const prev_field_val_src = block.src(.{ .container_field_value = prev_field_index }); + const msg = try sema.errMsg(field_val_src, "enum tag value '{f}' for field '{f}' already taken", .{ + Value.fromInterned(field_val).fmtValueSema(pt, sema), + enum_obj.field_names.get(ip)[field_idx].fmt(ip), + }); + errdefer msg.destroy(gpa); + try sema.errNote(prev_field_val_src, msg, "previous occurrence in field '{f}'", .{ + enum_obj.field_names.get(ip)[prev_field_index].fmt(ip), + }); + break :msg msg; }); - errdefer msg.destroy(gpa); - try sema.errNote(prev_field_val_src, msg, "previous occurrence here", .{}); - break :msg msg; - }); + } } + // MLUGG TODO: fate of this line rests on whether comptime_int is a valid int tag type if (enum_obj.nonexhaustive and int_tag_ty.toIntern() != .comptime_int_type) { const fields_len = enum_obj.field_names.len; if (fields_len >= 1 and std.math.log2_int(u64, fields_len) == int_tag_ty.bitSize(zcu)) { diff --git a/src/Type.zig b/src/Type.zig index 52dc5ed1ebb7918d930f51d21c65ba68a8178be5..111f6347ed2d0f72cd70db20a59dfc806fe140e8 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -437,6 +437,7 @@ pub fn toValue(self: Type) Value { /// - an enum with an explicit tag type has the ABI size of the integer tag type, /// making it one-possible-value only if the integer tag type has 0 bits. pub fn hasRuntimeBits(ty: Type, zcu: *const Zcu) bool { + ty.assertHasLayout(zcu); const ip = &zcu.intern_pool; return switch (ip.indexToKey(ty.toIntern())) { .int_type => |int_type| int_type.bits != 0, @@ -499,14 +500,18 @@ pub fn hasRuntimeBits(ty: Type, zcu: *const Zcu) bool { .generic_poison => unreachable, }, .struct_type => { - // TODO MLUGG: memoize this state when resolving struct? const struct_obj = ip.loadStructType(ty.toIntern()); - for (struct_obj.field_types.get(ip), 0..) |field_ty_ip, field_idx| { - if (struct_obj.field_is_comptime_bits.get(ip, field_idx)) continue; - const field_ty: Type = .fromInterned(field_ty_ip); - if (field_ty.hasRuntimeBits(zcu)) return true; + switch (struct_obj.layout) { + .auto, .@"extern" => return struct_obj.has_runtime_bits, + .@"packed" => return Type.fromInterned(struct_obj.packed_backing_int_type).hasRuntimeBits(zcu), + } + }, + .union_type => { + const union_obj = ip.loadUnionType(ty.toIntern()); + switch (union_obj.layout) { + .auto, .@"extern" => return union_obj.has_runtime_bits, + .@"packed" => return Type.fromInterned(union_obj.packed_backing_int_type).hasRuntimeBits(zcu), } - return false; }, .tuple_type => |tuple| { for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| { @@ -515,23 +520,8 @@ pub fn hasRuntimeBits(ty: Type, zcu: *const Zcu) bool { } return false; }, - .union_type => { - // TODO MLUGG: memoize this state when resolving union? - const union_obj = ip.loadUnionType(ty.toIntern()); - switch (union_obj.runtime_tag) { - .none => {}, - .safety, .tagged => { - if (Type.fromInterned(union_obj.enum_tag_type).hasRuntimeBits(zcu)) return true; - }, - } - for (union_obj.field_types.get(ip)) |field_ty_ip| { - const field_ty: Type = .fromInterned(field_ty_ip); - if (field_ty.hasRuntimeBits(zcu)) return true; - } - return false; - }, - // MLUGG TODO: i think this can go away and the assert move to the defer? + // MLUGG TODO: this answer was already here but... does it actually make sense? .opaque_type => true, .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).hasRuntimeBits(zcu), @@ -618,17 +608,18 @@ pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool { .generic_poison, => false, }, - .struct_type => ip.loadStructType(ty.toIntern()).layout != .auto, - .union_type => { - const union_obj = ip.loadUnionType(ty.toIntern()); - if (union_obj.layout == .auto) return false; - return switch (union_obj.runtime_tag) { - .none => true, - .tagged => false, - .safety => unreachable, // well-defined layout can't have a safety tag - }; + .struct_type => switch (ip.loadStructType(ty.toIntern()).layout) { + .auto => false, + .@"extern", .@"packed" => true, + }, + .union_type => switch (ip.loadUnionType(ty.toIntern()).layout) { + .auto => false, + .@"extern", .@"packed" => true, + }, + .enum_type => switch (ip.loadEnumType(ty.toIntern()).int_tag_mode) { + .explicit => true, + .auto => false, }, - .enum_type => ip.loadEnumType(ty.toIntern()).int_tag_is_explicit, // values, not types .undef, @@ -664,28 +655,29 @@ pub fn fnHasRuntimeBits(fn_ty: Type, zcu: *Zcu) bool { if (param_ty == .generic_poison_type) return false; if (Type.fromInterned(param_ty).comptimeOnly(zcu)) return false; } + const ret_ty: Type = .fromInterned(fn_info.return_type); + if (ret_ty.toIntern() == .generic_poison_type) { + return false; + } + if (ret_ty.zigTypeTag(zcu) == .error_union and + ret_ty.errorUnionPayload(zcu).toIntern() == .generic_poison_type) + { + return false; + } if (fn_info.return_type == .generic_poison_type) return false; if (Type.fromInterned(fn_info.return_type).comptimeOnly(zcu)) return false; if (fn_info.cc == .@"inline") return false; return true; } -pub fn isFnOrHasRuntimeBits(ty: Type, zcu: *Zcu) bool { +/// Like `hasRuntimeBits`, but also returns `true` for runtime functions. +pub fn isRuntimeFnOrHasRuntimeBits(ty: Type, zcu: *Zcu) bool { switch (ty.zigTypeTag(zcu)) { .@"fn" => return ty.fnHasRuntimeBits(zcu), else => return ty.hasRuntimeBits(zcu), } } -/// Same as `isFnOrHasRuntimeBits` but comptime-only types may return a false positive. -/// MLUGG TODO: this function is a bit silly now... -pub fn isFnOrHasRuntimeBitsIgnoreComptime(ty: Type, zcu: *Zcu) bool { - return switch (ty.zigTypeTag(zcu)) { - .@"fn" => true, - else => return ty.hasRuntimeBits(zcu), - }; -} - pub fn isNoReturn(ty: Type, zcu: *const Zcu) bool { return zcu.intern_pool.isNoReturn(ty.toIntern()); } @@ -711,7 +703,6 @@ pub fn ptrAddressSpace(ty: Type, zcu: *const Zcu) std.builtin.AddressSpace { } /// Never returns `none`. Asserts that all necessary type resolution is already done. -/// MLUGG TODO: check that it really does never return `.none` pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment { const ip = &zcu.intern_pool; const target = zcu.getTarget(); @@ -810,7 +801,7 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment { for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| { if (val != .none) continue; // comptime field const field_align = Type.fromInterned(field_ty).abiAlignment(zcu); - big_align = big_align.max(field_align); + big_align = big_align.maxStrict(field_align); } return big_align; }, @@ -818,14 +809,20 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment { const struct_obj = ip.loadStructType(ty.toIntern()); switch (struct_obj.layout) { .@"packed" => return Type.fromInterned(struct_obj.packed_backing_int_type).abiAlignment(zcu), - .auto, .@"extern" => return struct_obj.alignment, + .auto, .@"extern" => { + assert(struct_obj.alignment != .none); + return struct_obj.alignment; + }, } }, .union_type => { const union_obj = ip.loadUnionType(ty.toIntern()); switch (union_obj.layout) { .@"packed" => return Type.fromInterned(union_obj.packed_backing_int_type).abiAlignment(zcu), - .auto, .@"extern" => return getUnionLayout(union_obj, zcu).abi_align, + .auto, .@"extern" => { + assert(union_obj.alignment != .none); + return union_obj.alignment; + }, } }, .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).abiAlignment(zcu), @@ -1277,38 +1274,17 @@ pub fn nullablePtrElem(ty: Type, zcu: *const Zcu) Type { } } -/// Given that `ty` is an indexable pointer, returns its element type. Specifically: -/// * for `*[n]T`, returns `T` -/// * for `*@Vector(n, T)`, returns `T` -/// * for `[]T`, returns `T` -/// * for `[*]T`, returns `T` -/// * for `[*c]T`, returns `T` +/// Asserts that `ty` is an indexable type, and returns its element type. Tuples (and pointers to +/// tuples) are not supported because they do not have a single element type. /// -/// Tuples are not supported because they do not have a single element type. -/// -/// MLUGG TODO: should i even have this one? it's a subset of indexableElem -pub fn indexablePtrElem(ty: Type, zcu: *const Zcu) Type { - const ip = &zcu.intern_pool; - const ptr_type = ip.indexToKey(ty.toIntern()).ptr_type; - return switch (ptr_type.flags.size) { - .many, .slice, .c => return .fromInterned(ptr_type.child), - .one => switch (ip.indexToKey(ptr_type.child)) { - inline .array_type, .vector_type => |arr| return .fromInterned(arr.child), - else => unreachable, - }, - }; -} - -/// Given that `ty` is an indexable type, returns its element type. Specifically: -/// * for `[n]T`, returns `T` -/// * for `@Vector(n, T)`, returns `T` -/// * for `*[n]T`, returns `T` -/// * for `*@Vector(n, T)`, returns `T` -/// * for `[]T`, returns `T` -/// * for `[*]T`, returns `T` -/// * for `[*c]T`, returns `T` -/// -/// Tuples are not supported because they do not have a single element type. +/// Returns `T` for each of the following types: +/// * `[n]T` +/// * `@Vector(n, T)` +/// * `*[n]T` +/// * `*@Vector(n, T)` +/// * `[]T` +/// * `[*]T` +/// * `[*c]T` pub fn indexableElem(ty: Type, zcu: *const Zcu) Type { const ip = &zcu.intern_pool; return switch (ip.indexToKey(ty.toIntern())) { @@ -1348,6 +1324,7 @@ pub fn optionalChild(ty: Type, zcu: *const Zcu) Type { /// Returns the tag type of a union, if the type is a union and it has a tag type. /// Otherwise, returns `null`. pub fn unionTagType(ty: Type, zcu: *const Zcu) ?Type { + assertHasLayout(ty, zcu); const ip = &zcu.intern_pool; switch (ip.indexToKey(ty.toIntern())) { .union_type => {}, @@ -1363,6 +1340,7 @@ pub fn unionTagType(ty: Type, zcu: *const Zcu) ?Type { /// Same as `unionTagType` but includes safety tag. /// Codegen should use this version. pub fn unionTagTypeSafety(ty: Type, zcu: *const Zcu) ?Type { + assertHasLayout(ty, zcu); const ip = &zcu.intern_pool; return switch (ip.indexToKey(ty.toIntern())) { .union_type => { @@ -1377,11 +1355,13 @@ pub fn unionTagTypeSafety(ty: Type, zcu: *const Zcu) ?Type { /// Asserts the type is a union; returns the tag type, even if the tag will /// not be stored at runtime. pub fn unionTagTypeHypothetical(ty: Type, zcu: *const Zcu) Type { + assertHasLayout(ty, zcu); const union_obj = zcu.typeToUnion(ty).?; return Type.fromInterned(union_obj.enum_tag_type); } pub fn unionFieldType(ty: Type, enum_tag: Value, zcu: *const Zcu) ?Type { + assertHasLayout(ty, zcu); const ip = &zcu.intern_pool; const union_obj = zcu.typeToUnion(ty).?; const union_fields = union_obj.field_types.get(ip); @@ -1390,17 +1370,20 @@ pub fn unionFieldType(ty: Type, enum_tag: Value, zcu: *const Zcu) ?Type { } pub fn unionFieldTypeByIndex(ty: Type, index: usize, zcu: *const Zcu) Type { + assertHasLayout(ty, zcu); const ip = &zcu.intern_pool; const union_obj = zcu.typeToUnion(ty).?; return Type.fromInterned(union_obj.field_types.get(ip)[index]); } pub fn unionTagFieldIndex(ty: Type, enum_tag: Value, zcu: *const Zcu) ?u32 { + assertHasLayout(ty, zcu); const union_obj = zcu.typeToUnion(ty).?; return zcu.unionTagFieldIndex(union_obj, enum_tag); } pub fn unionHasAllZeroBitFieldTypes(ty: Type, zcu: *Zcu) bool { + assertHasLayout(ty, zcu); const ip = &zcu.intern_pool; const union_obj = zcu.typeToUnion(ty).?; for (union_obj.field_types.get(ip)) |field_ty| { @@ -1413,14 +1396,17 @@ pub fn unionHasAllZeroBitFieldTypes(ty: Type, zcu: *Zcu) bool { /// Asserts the type is either an extern or packed union. pub fn unionBackingType(ty: Type, pt: Zcu.PerThread) !Type { const zcu = pt.zcu; - return switch (ty.containerLayout(zcu)) { + assertHasLayout(ty, zcu); + const loaded_union = zcu.intern_pool.loadUnionType(ty.toIntern()); + return switch (loaded_union.layout) { .@"extern" => try pt.arrayType(.{ .len = ty.abiSize(zcu), .child = .u8_type }), - .@"packed" => try pt.intType(.unsigned, @intCast(ty.bitSize(zcu))), + .@"packed" => .fromInterned(loaded_union.packed_backing_int_type), .auto => unreachable, }; } pub fn unionGetLayout(ty: Type, zcu: *const Zcu) Zcu.UnionLayout { + assertHasLayout(ty, zcu); const union_obj = zcu.intern_pool.loadUnionType(ty.toIntern()); return Type.getUnionLayout(union_obj, zcu); } @@ -1865,11 +1851,8 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { for (field_vals, 0..) |*field_val, i_usize| { const i: u32 = @intCast(i_usize); if (struct_obj.field_is_comptime_bits.get(ip, i)) { - // MLUGG TODO: this is kinda a problem... we don't necessarily know the opv field vals! - // for now i'm just not letting structs with comptime fields be opv :) - if (true) return null; - assertHasInits(ty, zcu); field_val.* = struct_obj.field_defaults.get(ip)[i]; + assert(field_val.* != .none); continue; } const field_ty = Type.fromInterned(struct_obj.field_types.get(ip)[i]); @@ -2257,19 +2240,23 @@ pub fn errorSetNames(ty: Type, zcu: *const Zcu) InternPool.NullTerminatedString. } pub fn enumFields(ty: Type, zcu: *const Zcu) InternPool.NullTerminatedString.Slice { + assertHasLayout(ty, zcu); return zcu.intern_pool.loadEnumType(ty.toIntern()).field_names; } pub fn enumFieldCount(ty: Type, zcu: *const Zcu) usize { + assertHasLayout(ty, zcu); return zcu.intern_pool.loadEnumType(ty.toIntern()).field_names.len; } pub fn enumFieldName(ty: Type, field_index: usize, zcu: *const Zcu) InternPool.NullTerminatedString { + assertHasLayout(ty, zcu); const ip = &zcu.intern_pool; return ip.loadEnumType(ty.toIntern()).field_names.get(ip)[field_index]; } pub fn enumFieldIndex(ty: Type, field_name: InternPool.NullTerminatedString, zcu: *const Zcu) ?u32 { + assertHasLayout(ty, zcu); const ip = &zcu.intern_pool; const enum_type = ip.loadEnumType(ty.toIntern()); return enum_type.nameIndex(ip, field_name); @@ -2279,6 +2266,7 @@ pub fn enumFieldIndex(ty: Type, field_name: InternPool.NullTerminatedString, zcu /// an integer which represents the enum value. Returns the field index in /// declaration order, or `null` if `enum_tag` does not match any field. pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, zcu: *const Zcu) ?u32 { + assertHasLayout(ty, zcu); const ip = &zcu.intern_pool; const enum_type = ip.loadEnumType(ty.toIntern()); const int_tag = switch (ip.indexToKey(enum_tag.toIntern())) { @@ -2293,28 +2281,40 @@ pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, zcu: *const Zcu) ?u32 { /// Returns none in the case of a tuple which uses the integer index as the field name. pub fn structFieldName(ty: Type, index: usize, zcu: *const Zcu) InternPool.OptionalNullTerminatedString { const ip = &zcu.intern_pool; - return switch (ip.indexToKey(ty.toIntern())) { - .struct_type => ip.loadStructType(ty.toIntern()).field_names.get(ip)[index].toOptional(), - .tuple_type => .none, + switch (ip.indexToKey(ty.toIntern())) { + .struct_type => { + assertHasLayout(ty, zcu); + return ip.loadStructType(ty.toIntern()).field_names.get(ip)[index].toOptional(); + }, + .tuple_type => return .none, else => unreachable, - }; + } } pub fn structFieldCount(ty: Type, zcu: *const Zcu) u32 { const ip = &zcu.intern_pool; - return switch (ip.indexToKey(ty.toIntern())) { - .struct_type => ip.loadStructType(ty.toIntern()).field_types.len, - .tuple_type => |tuple| tuple.types.len, + switch (ip.indexToKey(ty.toIntern())) { + .struct_type => { + assertHasLayout(ty, zcu); + return ip.loadStructType(ty.toIntern()).field_types.len; + }, + .tuple_type => |tuple| return tuple.types.len, else => unreachable, - }; + } } /// Returns the field type. Supports structs and unions. pub fn fieldType(ty: Type, index: usize, zcu: *const Zcu) Type { const ip = &zcu.intern_pool; const types = switch (ip.indexToKey(ty.toIntern())) { - .struct_type => ip.loadStructType(ty.toIntern()).field_types, - .union_type => ip.loadUnionType(ty.toIntern()).field_types, + .struct_type => types: { + assertHasLayout(ty, zcu); + break :types ip.loadStructType(ty.toIntern()).field_types; + }, + .union_type => types: { + assertHasLayout(ty, zcu); + break :types ip.loadUnionType(ty.toIntern()).field_types; + }, .tuple_type => |tuple| tuple.types, else => unreachable, }; @@ -2335,11 +2335,13 @@ pub fn resolvedFieldAlignment(ty: Type, index: usize, zcu: *const Zcu) Alignment return switch (ip.indexToKey(ty.toIntern())) { .tuple_type => |tuple| Type.fromInterned(tuple.types.get(ip)[index]).abiAlignment(zcu), .struct_type => { + assertHasLayout(ty, zcu); const struct_obj = ip.loadStructType(ty.toIntern()); const field_ty: Type = .fromInterned(struct_obj.field_types.get(ip)[index]); return field_ty.defaultStructFieldAlignment(struct_obj.layout, zcu); }, .union_type => { + assertHasLayout(ty, zcu); const union_obj = ip.loadUnionType(ty.toIntern()); const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[index]); return field_ty.abiAlignment(zcu); @@ -2353,12 +2355,14 @@ pub fn explicitFieldAlignment(ty: Type, index: usize, zcu: *const Zcu) Alignment return switch (ip.indexToKey(ty.toIntern())) { .tuple_type => .none, .struct_type => { + assertHasLayout(ty, zcu); const struct_obj = ip.loadStructType(ty.toIntern()); assert(struct_obj.layout != .@"packed"); if (struct_obj.field_aligns.len == 0) return .none; return struct_obj.field_aligns.get(ip)[index]; }, .union_type => { + assertHasLayout(ty, zcu); const union_obj = ip.loadUnionType(ty.toIntern()); assert(union_obj.layout != .@"packed"); if (union_obj.field_aligns.len == 0) return .none; @@ -2413,7 +2417,6 @@ pub fn structFieldValueComptime(ty: Type, pt: Zcu.PerThread, index: usize) !?Val .struct_type => { const struct_type = ip.loadStructType(ty.toIntern()); if (struct_type.field_is_comptime_bits.get(ip, index)) { - assertHasInits(ty, zcu); return .fromInterned(struct_type.field_defaults.get(ip)[index]); } else { return Type.fromInterned(struct_type.field_types.get(ip)[index]).onePossibleValue(pt); @@ -2433,11 +2436,14 @@ pub fn structFieldValueComptime(ty: Type, pt: Zcu.PerThread, index: usize) !?Val pub fn structFieldIsComptime(ty: Type, index: usize, zcu: *const Zcu) bool { const ip = &zcu.intern_pool; - return switch (ip.indexToKey(ty.toIntern())) { - .struct_type => ip.loadStructType(ty.toIntern()).field_is_comptime_bits.get(ip, index), - .tuple_type => |tuple| tuple.values.get(ip)[index] != .none, + switch (ip.indexToKey(ty.toIntern())) { + .struct_type => { + assertHasLayout(ty, zcu); + return ip.loadStructType(ty.toIntern()).field_is_comptime_bits.get(ip, index); + }, + .tuple_type => |tuple| return tuple.values.get(ip)[index] != .none, else => unreachable, - }; + } } pub const FieldOffset = struct { @@ -2850,34 +2856,166 @@ pub fn isNullFromType(ty: Type, zcu: *const Zcu) ?bool { return null; } -/// Returns true if `ty` is allowed in packed types. -pub fn packable(ty: Type, zcu: *const Zcu) bool { +pub const UnpackableReason = union(enum) { + comptime_only, + pointer, + enum_inferred_int_tag: Type, + non_packed_struct: Type, + non_packed_union: Type, + other, +}; + +/// Returns `null` iff `ty` is allowed in packed types. +pub fn unpackable(ty: Type, zcu: *const Zcu) ?UnpackableReason { return switch (ty.zigTypeTag(zcu)) { + .void, + .bool, + .float, + .int, + => null, + .type, .comptime_float, .comptime_int, .enum_literal, .undefined, .null, + => .comptime_only, + + .noreturn, + .@"opaque", .error_union, .error_set, .frame, - .noreturn, - .@"opaque", .@"anyframe", .@"fn", .array, - => false, - .optional => return ty.isPtrLikeOptional(zcu), - .void, - .bool, - .float, - .int, .vector, + => .other, + + .optional => if (ty.isPtrLikeOptional(zcu)) + .pointer + else + .other, + + .pointer => .pointer, + + .@"enum" => switch (zcu.intern_pool.loadEnumType(ty.toIntern()).int_tag_mode) { + .explicit => null, + .auto => .{ .enum_inferred_int_tag = ty }, + }, + + .@"struct" => switch (ty.containerLayout(zcu)) { + .@"packed" => null, + .auto, .@"extern" => .{ .non_packed_struct = ty }, + }, + .@"union" => switch (ty.containerLayout(zcu)) { + .@"packed" => null, + .auto, .@"extern" => .{ .non_packed_union = ty }, + }, + }; +} + +pub const ExternPosition = enum { + ret_ty, + param_ty, + union_field, + struct_field, + element, + other, +}; + +/// Returns true if `ty` is allowed in extern types. +/// Does not require `ty` to be resolved in any way. +/// Keep in sync with `Sema.explainWhyTypeIsNotExtern`. +pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool { + return switch (ty.zigTypeTag(zcu)) { + .type, + .comptime_float, + .comptime_int, + .enum_literal, + .undefined, + .null, + .error_union, + .error_set, + .frame, + => false, + + .void => switch (position) { + .ret_ty, + .union_field, + .struct_field, + .element, + => true, + .param_ty, + .other, + => false, + }, + + .noreturn => position == .ret_ty, + + .@"opaque", + .bool, + .float, + .@"anyframe", => true, - .@"enum" => zcu.intern_pool.loadEnumType(ty.toIntern()).int_tag_is_explicit, - .pointer => !ty.isSlice(zcu), - .@"struct", .@"union" => ty.containerLayout(zcu) == .@"packed", + + .pointer => { + if (ty.isSlice(zcu)) return false; + const child_ty = ty.childType(zcu); + if (child_ty.zigTypeTag(zcu) == .@"fn") { + return ty.isConstPtr(zcu) and child_ty.validateExtern(.other, zcu); + } + return true; + }, + .int => switch (ty.intInfo(zcu).bits) { + 0, 8, 16, 32, 64, 128 => true, + else => false, + }, + .@"fn" => { + if (position != .other) return false; + // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI. + // The goal is to experiment with more integrated CPU/GPU code. + if (ty.fnCallingConvention(zcu) == .nvptx_kernel) { + return true; + } + return !target_util.fnCallConvAllowsZigTypes(ty.fnCallingConvention(zcu)); + }, + .@"enum" => { + const enum_obj = zcu.intern_pool.loadEnumType(ty.toIntern()); + return switch (enum_obj.int_tag_mode) { + .auto => false, + .explicit => Type.fromInterned(enum_obj.int_tag_type).validateExtern(position, zcu), + }; + }, + .@"struct" => { + const struct_obj = zcu.intern_pool.loadStructType(ty.toIntern()); + return switch (struct_obj.layout) { + .auto => false, + .@"extern" => true, + .@"packed" => switch (struct_obj.packed_backing_mode) { + .auto => false, + .explicit => Type.fromInterned(struct_obj.packed_backing_int_type).validateExtern(position, zcu), + }, + }; + }, + .@"union" => { + const union_obj = zcu.intern_pool.loadUnionType(ty.toIntern()); + return switch (union_obj.layout) { + .auto => false, + .@"extern" => true, + .@"packed" => switch (union_obj.packed_backing_mode) { + .auto => false, + .explicit => Type.fromInterned(union_obj.packed_backing_int_type).validateExtern(position, zcu), + }, + }; + }, + .array => { + if (position == .ret_ty or position == .param_ty) return false; + return ty.childType(zcu).validateExtern(.element, zcu); + }, + .vector => ty.childType(zcu).validateExtern(.element, zcu), + .optional => ty.isPtrLikeOptional(zcu), }; } @@ -2889,7 +3027,6 @@ pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void { .anyframe_type, .simple_type, .opaque_type, - .enum_type, .error_set_type, .inferred_error_set_type, => {}, @@ -2906,12 +3043,11 @@ pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void { .tuple_type => |tuple| for (tuple.types.get(&zcu.intern_pool)) |field_ty| { assertHasLayout(.fromInterned(field_ty), zcu); }, - .struct_type, .union_type => { + .struct_type, .union_type, .enum_type => { const unit: InternPool.AnalUnit = .wrap(.{ .type_layout = ty.toIntern() }); assert(!zcu.outdated.contains(unit)); assert(!zcu.potentially_outdated.contains(unit)); }, - else => unreachable, // assertion failure; not a struct or union // values, not types .simple_value, @@ -2930,23 +3066,13 @@ pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void { .opt, .aggregate, .un, + .undef, // memoization, not types .memoized_call, => unreachable, } } -/// Asserts that `ty` is an enum or struct type whose field values/defaults are resolved. -pub fn assertHasInits(ty: Type, zcu: *const Zcu) void { - switch (zcu.intern_pool.indexToKey(ty.toIntern())) { - .struct_type, .enum_type => {}, - else => unreachable, - } - const unit: InternPool.AnalUnit = .wrap(.{ .type_inits = ty.toIntern() }); - assert(!zcu.outdated.contains(unit)); - assert(!zcu.potentially_outdated.contains(unit)); -} - /// Recursively walks the type and marks for each subtype how many times it has been seen fn collectSubtypes(ty: Type, pt: Zcu.PerThread, visited: *std.AutoArrayHashMapUnmanaged(Type, u16)) error{OutOfMemory}!void { const zcu = pt.zcu; @@ -3116,6 +3242,7 @@ pub const Comparison = struct { }; }; +pub const @"u0": Type = .{ .ip_index = .u0_type }; pub const @"u1": Type = .{ .ip_index = .u1_type }; pub const @"u8": Type = .{ .ip_index = .u8_type }; pub const @"u16": Type = .{ .ip_index = .u16_type }; diff --git a/src/Value.zig b/src/Value.zig index 5986eee6d652b135fd2b28bfc2f839bdd578486e..ca9ef9604627beb12c9014b9372f42eb1aac538a 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -2207,7 +2207,7 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh const ptr_ty_info = Type.fromInterned(ptr.ty).ptrInfo(zcu); const need_child: Type = .fromInterned(ptr_ty_info.child); - if (need_child.comptimeOnly(zcu)) { + if (need_child.comptimeOnly(zcu) or need_child.zigTypeTag(zcu) == .@"opaque") { // No refinement can happen - this pointer is presumably invalid. // Just offset it. const parent = try arena.create(PointerDeriveStep); @@ -2595,8 +2595,8 @@ pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory pub fn doPointersOverlap(ptr_val_a: Value, ptr_val_b: Value, elem_count: u64, zcu: *const Zcu) bool { const ip = &zcu.intern_pool; - const a_elem_ty = ptr_val_a.typeOf(zcu).indexablePtrElem(zcu); - const b_elem_ty = ptr_val_b.typeOf(zcu).indexablePtrElem(zcu); + const a_elem_ty = ptr_val_a.typeOf(zcu).indexableElem(zcu); + const b_elem_ty = ptr_val_b.typeOf(zcu).indexableElem(zcu); const a_ptr = ip.indexToKey(ptr_val_a.toIntern()).ptr; const b_ptr = ip.indexToKey(ptr_val_b.toIntern()).ptr; @@ -2682,3 +2682,58 @@ pub fn eqlScalarNum(lhs: Value, rhs: Value, zcu: *Zcu) bool { const rhs_bigint = rhs.toBigInt(&rhs_bigint_space, zcu); return lhs_bigint.eql(rhs_bigint); } + +/// Asserts the value is an integer, and the destination type is ComptimeInt or Int. +/// Vectors are also accepted. Vector results are reduced with AND. +/// +/// If provided, `vector_index` reports the first element that failed the range check. +pub fn intFitsInType( + val: Value, + ty: Type, + vector_index: ?*usize, + zcu: *const Zcu, +) bool { + if (ty.toIntern() == .comptime_int_type) return true; + const info = ty.intInfo(zcu); + switch (val.toIntern()) { + .zero_usize, .zero_u8 => return true, + else => switch (zcu.intern_pool.indexToKey(val.toIntern())) { + .undef => return true, + .variable, .@"extern", .func, .ptr => { + const target = zcu.getTarget(); + const ptr_bits = target.ptrBitWidth(); + return switch (info.signedness) { + .signed => info.bits > ptr_bits, + .unsigned => info.bits >= ptr_bits, + }; + }, + .int => |int| { + var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined; + const big_int = int.storage.toBigInt(&buffer); + return big_int.fitsInTwosComp(info.signedness, info.bits); + }, + .aggregate => |aggregate| { + assert(ty.zigTypeTag(zcu) == .vector); + return switch (aggregate.storage) { + .bytes => |bytes| for (bytes.toSlice(ty.vectorLen(zcu), &zcu.intern_pool), 0..) |byte, i| { + if (byte == 0) continue; + const actual_needed_bits = std.math.log2(byte) + 1 + @intFromBool(info.signedness == .signed); + if (info.bits >= actual_needed_bits) continue; + if (vector_index) |vi| vi.* = i; + break false; + } else true, + .elems, .repeated_elem => for (switch (aggregate.storage) { + .bytes => unreachable, + .elems => |elems| elems, + .repeated_elem => |elem| @as(*const [1]InternPool.Index, &elem), + }, 0..) |elem, i| { + if (Value.fromInterned(elem).intFitsInType(ty.scalarType(zcu), null, zcu)) continue; + if (vector_index) |vi| vi.* = i; + break false; + } else true, + }; + }, + else => unreachable, + }, + } +} diff --git a/src/Zcu.zig b/src/Zcu.zig index e1760fecb95c1871ca3229becbebc6d224e4173a..5aef6a11d17d13d43176c782d53b3de4287bc2af 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -1912,40 +1912,6 @@ pub const SrcLoc = struct { const full = tree.fullPtrType(parent_node).?; return tree.nodeToSpan(full.ast.bit_range_end.unwrap().?); }, - .node_offset_container_tag => |node_off| { - const tree = try src_loc.file_scope.getTree(zcu); - const parent_node = node_off.toAbsolute(src_loc.base_node); - - switch (tree.nodeTag(parent_node)) { - .container_decl_arg, .container_decl_arg_trailing => { - const full = tree.containerDeclArg(parent_node); - const arg_node = full.ast.arg.unwrap().?; - return tree.nodeToSpan(arg_node); - }, - .tagged_union_enum_tag, .tagged_union_enum_tag_trailing => { - const full = tree.taggedUnionEnumTag(parent_node); - const arg_node = full.ast.arg.unwrap().?; - - return tree.tokensToSpan( - tree.firstToken(arg_node) - 2, - tree.lastToken(arg_node) + 1, - tree.nodeMainToken(arg_node), - ); - }, - else => unreachable, - } - }, - .node_offset_field_default => |node_off| { - const tree = try src_loc.file_scope.getTree(zcu); - const parent_node = node_off.toAbsolute(src_loc.base_node); - - const full: Ast.full.ContainerField = switch (tree.nodeTag(parent_node)) { - .container_field => tree.containerField(parent_node), - .container_field_init => tree.containerFieldInit(parent_node), - else => unreachable, - }; - return tree.nodeToSpan(full.ast.value_expr.unwrap().?); - }, .node_offset_init_ty => |node_off| { const tree = try src_loc.file_scope.getTree(zcu); const parent_node = node_off.toAbsolute(src_loc.base_node); @@ -2021,6 +1987,14 @@ pub const SrcLoc = struct { } return tree.nodeToSpan(node); }, + .container_arg => { + const tree = try src_loc.file_scope.getTree(zcu); + const node = src_loc.base_node; + var buf: [2]Ast.Node.Index = undefined; + const container_decl = tree.fullContainerDecl(&buf, node) orelse return tree.nodeToSpan(node); + const arg_node = container_decl.ast.arg.unwrap() orelse return tree.nodeToSpan(node); + return tree.nodeToSpan(arg_node); + }, .container_field_name, .container_field_value, .container_field_type, @@ -2262,7 +2236,11 @@ pub const SrcLoc = struct { var param_it = full.iterate(tree); for (0..param_idx) |_| assert(param_it.next() != null); const param = param_it.next().?; - return tree.nodeToSpan(param.type_expr.?); + if (param.anytype_ellipsis3) |tok| { + return tree.tokenToSpan(tok); + } else { + return tree.nodeToSpan(param.type_expr.?); + } }, } } @@ -2484,10 +2462,6 @@ pub const LazySrcLoc = struct { node_offset_ptr_bitoffset: Ast.Node.Offset, /// The source location points to the host size of a pointer. node_offset_ptr_hostsize: Ast.Node.Offset, - /// The source location points to the tag type of an union or an enum. - node_offset_container_tag: Ast.Node.Offset, - /// The source location points to the default value of a field. - node_offset_field_default: Ast.Node.Offset, /// The source location points to the type of an array or struct initializer. node_offset_init_ty: Ast.Node.Offset, /// The source location points to the LHS of an assignment (or assign-op, e.g. `+=`). @@ -2532,6 +2506,11 @@ pub const LazySrcLoc = struct { fn_proto_param_type: FnProtoParam, array_cat_lhs: ArrayCat, array_cat_rhs: ArrayCat, + /// The source location points to the backing or tag type expression of + /// the container type declaration at the base node. + /// + /// For 'union(enum(T))', this points to 'T', not 'enum(T)'. + container_arg, /// The source location points to the name of the field at the given index /// of the container type declaration at the base node. container_field_name: u32, @@ -3149,7 +3128,7 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { .nav_val => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_val = nav }), .nav_ty => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav }), .type_layout => |ty| try zcu.markPoDependeeUpToDate(.{ .type_layout = ty }), - .type_inits => |ty| try zcu.markPoDependeeUpToDate(.{ .type_inits = ty }), + .struct_defaults => |ty| try zcu.markPoDependeeUpToDate(.{ .struct_defaults = ty }), .func => |func| try zcu.markPoDependeeUpToDate(.{ .func_ies = func }), .memoized_state => |stage| try zcu.markPoDependeeUpToDate(.{ .memoized_state = stage }), } @@ -3165,7 +3144,7 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni .nav_val => |nav| .{ .nav_val = nav }, .nav_ty => |nav| .{ .nav_ty = nav }, .type_layout => |ty| .{ .type_layout = ty }, - .type_inits => |ty| .{ .type_inits = ty }, + .struct_defaults => |ty| .{ .struct_defaults = ty }, .func => |func_index| .{ .func_ies = func_index }, .memoized_state => |stage| .{ .memoized_state = stage }, }; @@ -3195,88 +3174,44 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni } } +/// Selects an outdated `AnalUnit` to analyze next. Called from the main semantic analysis loop when +/// there is no work immediately queued. The unit is chosen such that it is unlikely to require any +/// recursive analysis (all of its previously-marked dependencies are already up-to-date), because +/// recursive analysis can cause over-analysis on incremental updates. pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { if (!zcu.comp.config.incremental) return null; - if (zcu.outdated.count() == 0) { - // Any units in `potentially_outdated` must just be stuck in loops with one another: none of those - // units have had any outdated dependencies so far, and all of their remaining PO deps are triggered - // by other units in `potentially_outdated`. So, we can safety assume those units up-to-date. - zcu.potentially_outdated.clearRetainingCapacity(); - log.debug("findOutdatedToAnalyze: no outdated depender", .{}); - return null; - } - - // Our goal is to find an outdated AnalUnit which itself has no outdated or - // PO dependencies. Most of the time, such an AnalUnit will exist - we track - // them in the `outdated_ready` set for efficiency. However, this is not - // necessarily the case, since the Decl dependency graph may contain loops - // via mutually recursive definitions: - // pub const A = struct { b: *B }; - // pub const B = struct { b: *A }; - // In this case, we must defer to more complex logic below. - if (zcu.outdated_ready.count() > 0) { const unit = zcu.outdated_ready.keys()[0]; - log.debug("findOutdatedToAnalyze: trivial {f}", .{zcu.fmtAnalUnit(unit)}); + log.debug("findOutdatedToAnalyze: {f}", .{zcu.fmtAnalUnit(unit)}); return unit; } - // There is no single AnalUnit which is ready for re-analysis. Instead, we must assume that some - // AnalUnit with PO dependencies is outdated -- e.g. in the above example we arbitrarily pick one of - // A or B. We should definitely not select a function, since a function can't be responsible for the - // loop (IES dependencies can't have loops). We should also, of course, not select a `comptime` - // declaration, since you can't depend on those! + // Usually, getting here means that everything is up-to-date, so there is no more work to do. We + // will see that `zcu.outdated` and `zcu.potentially_outdated` are both empty. + // + // However, if a previous update had a dependency loop compile error, there is a cycle in the + // dependency graph (which is usually acyclic), which can cause a scenario where no unit appears + // to be ready, because they're all waiting for the next in the loop to be up-to-date. In that + // case, we usually have to just bite the bullet and analyze one of them. An exception is if + // `zcu.outdated` is empty but `zcu.potentially_outdated` is non-empty: in that case, the only + // possible situation is a cycle where everything is actually up-to-date, so we can clear out + // `zcu.potentially_outdated` and we are done. - // The choice of this unit could have a big impact on how much total analysis we perform, since - // if analysis concludes any dependencies on its result are up-to-date, then other PO AnalUnit - // may be resolved as up-to-date. To hopefully avoid doing too much work, let's find a unit - // which the most things depend on - the idea is that this will resolve a lot of loops (but this - // is only a heuristic). + if (zcu.outdated.count() == 0) { + // Everything is up-to-date. There could be lingering entries in `zcu.potentially_outdated` + // from a dependency loop on a previous update. + zcu.potentially_outdated.clearRetainingCapacity(); + log.debug("findOutdatedToAnalyze: all up-to-date", .{}); + return null; + } - log.debug("findOutdatedToAnalyze: no trivial ready, using heuristic; {d} outdated, {d} PO", .{ + const unit = zcu.outdated.keys()[0]; + log.debug("findOutdatedToAnalyze: dependency loop affecting {d} units, selected {f}", .{ zcu.outdated.count(), - zcu.potentially_outdated.count(), + zcu.fmtAnalUnit(unit), }); - - const ip = &zcu.intern_pool; - - var chosen_unit: ?AnalUnit = null; - var chosen_unit_dependers: u32 = undefined; - - // MLUGG TODO: i'm 99% sure this is now impossible. check!!! - inline for (.{ zcu.outdated.keys(), zcu.potentially_outdated.keys() }) |outdated_units| { - for (outdated_units) |unit| { - var n: u32 = 0; - var it = ip.dependencyIterator(switch (unit.unwrap()) { - .func => continue, // a `func` definitely can't be causing the loop so it is a bad choice - .@"comptime" => continue, // a `comptime` block can't even be depended on so it is a terrible choice - .type_layout => |ty| .{ .type_layout = ty }, - .type_inits => |ty| .{ .type_inits = ty }, - .nav_val => |nav| .{ .nav_val = nav }, - .nav_ty => |nav| .{ .nav_ty = nav }, - .memoized_state => { - // If we've hit a loop and some `.memoized_state` is outdated, we should make that choice eagerly. - // In general, it's good to resolve this early on, since -- for instance -- almost every function - // references the panic handler. - return unit; - }, - }); - while (it.next()) |_| n += 1; - - if (chosen_unit == null or n > chosen_unit_dependers) { - chosen_unit = unit; - chosen_unit_dependers = n; - } - } - } - - log.debug("findOutdatedToAnalyze: heuristic returned '{f}' ({d} dependers)", .{ - zcu.fmtAnalUnit(chosen_unit.?), - chosen_unit_dependers, - }); - - return chosen_unit.?; + return unit; } /// During an incremental update, before semantic analysis, call this to flush all values from @@ -3356,12 +3291,59 @@ pub fn mapOldZirToNew( } while (match_stack.pop()) |match_item| { - // First, a check: if the number of captures of this type has changed, we can't map it, because - // we wouldn't know how to correlate type information with the last update. - // Synchronizes with logic in `Zcu.PerThread.recreateStructType` etc. - if (old_zir.typeCapturesLen(match_item.old_inst) != new_zir.typeCapturesLen(match_item.new_inst)) { - // Don't map this type or anything within it. - continue; + // There are some properties of type declarations which cannot change across incremental + // updates. If they have, we need to ignore this mapping. These properties are essentially + // everything passed into `InternPool.getDeclaredStructType` (likewise for unions, enums, + // and opaques). + const old_tag = old_zir.instructions.items(.data)[@intFromEnum(match_item.old_inst)].extended.opcode; + const new_tag = new_zir.instructions.items(.data)[@intFromEnum(match_item.new_inst)].extended.opcode; + if (old_tag != new_tag) continue; + switch (old_tag) { + .struct_decl => { + const old = old_zir.getStructDecl(match_item.old_inst); + const new = new_zir.getStructDecl(match_item.new_inst); + if (old.captures.len != new.captures.len) continue; + if (old.field_names.len != new.field_names.len) continue; + if (old.layout != new.layout) continue; + const old_any_field_aligns = old.field_align_body_lens != null; + const old_any_field_defaults = old.field_default_body_lens != null; + const old_any_comptime_fields = old.field_comptime_bits != null; + const old_explicit_backing_int = old.backing_int_type_body != null; + const new_any_field_aligns = new.field_align_body_lens != null; + const new_any_field_defaults = new.field_default_body_lens != null; + const new_any_comptime_fields = new.field_comptime_bits != null; + const new_explicit_backing_int = new.backing_int_type_body != null; + if (old_any_field_aligns != new_any_field_aligns) continue; + if (old_any_field_defaults != new_any_field_defaults) continue; + if (old_any_comptime_fields != new_any_comptime_fields) continue; + if (old_explicit_backing_int != new_explicit_backing_int) continue; + }, + .union_decl => { + const old = old_zir.getUnionDecl(match_item.old_inst); + const new = new_zir.getUnionDecl(match_item.new_inst); + if (old.captures.len != new.captures.len) continue; + if (old.field_names.len != new.field_names.len) continue; + if (old.kind != new.kind) continue; + const old_any_field_aligns = old.field_align_body_lens != null; + const new_any_field_aligns = new.field_align_body_lens != null; + if (old_any_field_aligns != new_any_field_aligns) continue; + }, + .enum_decl => { + const old = old_zir.getEnumDecl(match_item.old_inst); + const new = new_zir.getEnumDecl(match_item.new_inst); + if (old.captures.len != new.captures.len) continue; + if (old.field_names.len != new.field_names.len) continue; + if (old.nonexhaustive != new.nonexhaustive) continue; + const old_explicit_tag_type = old.tag_type_body != null; + const new_explicit_tag_type = new.tag_type_body != null; + if (old_explicit_tag_type != new_explicit_tag_type) continue; + }, + .opaque_decl => { + const old = old_zir.getOpaqueDecl(match_item.old_inst); + const new = new_zir.getOpaqueDecl(match_item.new_inst); + if (old.captures.len != new.captures.len) continue; + }, + else => unreachable, } // Match the namespace declaration itself @@ -4068,7 +4050,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R } if (has_inits) { // this should only be referenced by the type - const unit: AnalUnit = .wrap(.{ .type_inits = ty }); + const unit: AnalUnit = .wrap(.{ .struct_defaults = ty }); try units.putNoClobber(gpa, unit, referencer); } @@ -4184,7 +4166,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R const other: AnalUnit = .wrap(switch (unit.unwrap()) { .nav_val => |n| .{ .nav_ty = n }, .nav_ty => |n| .{ .nav_val = n }, - .@"comptime", .type_layout, .type_inits, .func, .memoized_state => break :queue_paired, + .@"comptime", .type_layout, .struct_defaults, .func, .memoized_state => break :queue_paired, }); const gop = try units.getOrPut(gpa, other); if (gop.found_existing) break :queue_paired; @@ -4305,6 +4287,16 @@ pub fn navFileScope(zcu: *Zcu, nav: InternPool.Nav.Index) *File { return zcu.fileByIndex(zcu.navFileScopeIndex(nav)); } +pub fn navAlignment(zcu: *Zcu, nav_index: InternPool.Nav.Index) InternPool.Alignment { + const ty: Type, const alignment = switch (zcu.intern_pool.getNav(nav_index).status) { + .unresolved => unreachable, + .type_resolved => |r| .{ .fromInterned(r.type), r.alignment }, + .fully_resolved => |r| .{ Value.fromInterned(r.val).typeOf(zcu), r.alignment }, + }; + if (alignment != .none) return alignment; + return ty.abiAlignment(zcu); +} + pub fn fmtAnalUnit(zcu: *Zcu, unit: AnalUnit) std.fmt.Alt(FormatAnalUnit, formatAnalUnit) { return .{ .data = .{ .unit = unit, .zcu = zcu } }; } @@ -4331,7 +4323,7 @@ fn formatAnalUnit(data: FormatAnalUnit, writer: *Io.Writer) Io.Writer.Error!void } }, .nav_val, .nav_ty => |nav, tag| return writer.print("{t}('{f}' [{}])", .{ tag, ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }), - .type_layout, .type_inits => |ty, tag| return writer.print("{t}('{f}' [{}])", .{ tag, Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }), + .type_layout, .struct_defaults => |ty, tag| return writer.print("{t}('{f}' [{}])", .{ tag, Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }), .func => |func| { const nav = zcu.funcInfo(func).owner_nav; return writer.print("func('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(func) }); @@ -4357,7 +4349,7 @@ fn formatDependee(data: FormatDependee, writer: *Io.Writer) Io.Writer.Error!void const fqn = ip.getNav(nav).fqn; return writer.print("{t}('{f}')", .{ tag, fqn.fmt(ip) }); }, - .type_layout, .type_inits => |ip_index, tag| { + .type_layout, .struct_defaults => |ip_index, tag| { const name = Type.fromInterned(ip_index).containerTypeName(ip); return writer.print("{t}('{f}')", .{ tag, name.fmt(ip) }); }, diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index e3c0c21244b2ae29b643bcc20b350796f27e25f8..d937367c4ac871c61e7bd285e9ddf04f7df175c7 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -695,20 +695,46 @@ pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Alloca .file = file_index, .inst = .main_struct_inst, }); - const file_root_type = try Sema.analyzeStructDecl( - pt, - file_index, - &file.zir.?, - .none, - tracked_inst, - &struct_decl, - null, - &.{}, - .{ .exact = .{ - .name = try file.internFullyQualifiedName(pt), - .nav = .none, - } }, - ); + const wip: InternPool.WipContainerType = switch (try ip.getDeclaredStructType(gpa, io, pt.tid, .{ + .zir_index = tracked_inst, + .captures = &.{}, + .fields_len = @intCast(struct_decl.field_names.len), + .layout = struct_decl.layout, + .any_comptime_fields = struct_decl.field_comptime_bits != null, + .any_field_defaults = struct_decl.field_default_body_lens != null, + .any_field_aligns = struct_decl.field_align_body_lens != null, + .packed_backing_mode = if (struct_decl.backing_int_type_body != null) .explicit else .auto, + })) { + .existing => unreachable, // it would have been set as `zcu.fileRootType` already + .wip => |wip| wip, + }; + errdefer wip.cancel(ip, pt.tid); + + wip.setName(ip, try file.internFullyQualifiedName(pt), .none); + const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ + .parent = .none, + .owner_type = wip.index, + .file_scope = file_index, + .generation = zcu.generation, + }); + errdefer pt.destroyNamespace(new_namespace_index); + try pt.scanNamespace(new_namespace_index, struct_decl.decls); + // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind + try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) }); + try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .struct_defaults = wip.index }) }); + + if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); + + try zcu.outdated.ensureUnusedCapacity(gpa, 2); + try zcu.outdated_ready.ensureUnusedCapacity(gpa, 2); + errdefer comptime unreachable; // because we don't remove the `outdated` entries + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .struct_defaults = wip.index }), 0); + zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); + zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .struct_defaults = wip.index }), {}); + + const file_root_type: Type = .fromInterned(wip.finish(ip, new_namespace_index)); + zcu.setFileRootType(file_index, file_root_type.toIntern()); if (zcu.comp.time_report) |*tr| tr.stats.n_imported_files += 1; } @@ -1048,11 +1074,6 @@ pub fn ensureTypeLayoutUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void assert(!zcu.analysis_in_progress.contains(anal_unit)); - // Determine whether or not this type is outdated. For this kind of `AnalUnit`, that's - // the only indicator as to whether or not analysis is required; when a struct/union is - // first created, it's marked as outdated. - // MLUGG TODO: make that actually true, it's a good strategy here! - const was_outdated = zcu.outdated.swapRemove(anal_unit) or zcu.potentially_outdated.swapRemove(anal_unit); @@ -1113,17 +1134,11 @@ pub fn ensureTypeLayoutUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void }; defer sema.deinit(); - const result = switch (ty.containerLayout(zcu)) { - .auto, .@"extern" => switch (ty.zigTypeTag(zcu)) { - .@"struct" => Sema.type_resolution.resolveStructLayout(&sema, ty), - .@"union" => Sema.type_resolution.resolveUnionLayout(&sema, ty), - else => unreachable, - }, - .@"packed" => switch (ty.zigTypeTag(zcu)) { - .@"struct" => Sema.type_resolution.resolvePackedStructLayout(&sema, ty), - .@"union" => Sema.type_resolution.resolvePackedUnionLayout(&sema, ty), - else => unreachable, - }, + const result = switch (ty.zigTypeTag(zcu)) { + .@"enum" => Sema.type_resolution.resolveEnumLayout(&sema, ty), + .@"struct" => Sema.type_resolution.resolveStructLayout(&sema, ty), + .@"union" => Sema.type_resolution.resolveUnionLayout(&sema, ty), + else => unreachable, }; result catch |err| switch (err) { error.AnalysisFail => { @@ -1145,36 +1160,31 @@ pub fn ensureTypeLayoutUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void sema.flushExports() catch |err| switch (err) { error.OutOfMemory => |e| return e, }; - - codegen_type: { - if (zcu.comp.config.use_llvm) break :codegen_type; - if (file.mod.?.strip) break :codegen_type; - zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); - try zcu.comp.queueJob(.{ .link_type = ty.toIntern() }); - } } -/// Ensures that the default/tag values of the given `struct` or `enum` type are fully up-to-date, -/// performing re-analysis if necessary. Asserts that `ty` is a struct (not a tuple!) or an enum. -/// Returns `error.AnalysisFail` if an analysis error is encountered during resolution; the caller -/// is free to ignore this, since the error is already registered. -pub fn ensureTypeInitsUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void { +/// Ensures that the default values of the given "declared" (not reified) `struct` type are fully +/// up-to-date, performing re-analysis if necessary. Asserts that `ty` is a struct (not tuple) type. +/// Returns `error.AnalysisFail` if an analysis error is encountered while resolving the default +/// field values; the caller is free to ignore this, since the error is already registered. +pub fn ensureStructDefaultsUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void { const tracy = trace(@src()); defer tracy.end(); const zcu = pt.zcu; const gpa = zcu.gpa; - const anal_unit: AnalUnit = .wrap(.{ .type_inits = ty.toIntern() }); + assert(ty.zigTypeTag(zcu) == .@"struct"); + assert(!ty.isTuple(zcu)); - log.debug("ensureTypeInitsUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)}); + const anal_unit: AnalUnit = .wrap(.{ .struct_defaults = ty.toIntern() }); + + log.debug("ensureStructDefaultsUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)}); assert(!zcu.analysis_in_progress.contains(anal_unit)); // Determine whether or not this type is outdated. For this kind of `AnalUnit`, that's // the only indicator as to whether or not analysis is required; when a struct/enum is // first created, it's marked as outdated. - // MLUGG TODO: make that actually true, it's a good strategy here! const was_outdated = zcu.outdated.swapRemove(anal_unit) or zcu.potentially_outdated.swapRemove(anal_unit); @@ -1194,7 +1204,7 @@ pub fn ensureTypeInitsUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void { } // For types, we already know that we have to invalidate all dependees. // TODO: we actually *could* detect whether everything was the same. should we bother? - try zcu.markDependeeOutdated(.marked_po, .{ .type_inits = ty.toIntern() }); + try zcu.markDependeeOutdated(.marked_po, .{ .struct_defaults = ty.toIntern() }); } else { // We can trust the current information about this unit. if (zcu.failed_analysis.contains(anal_unit)) return error.AnalysisFail; @@ -1236,12 +1246,7 @@ pub fn ensureTypeInitsUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void { }; defer sema.deinit(); - const result = switch (ty.zigTypeTag(zcu)) { - .@"struct" => Sema.type_resolution.resolveStructDefaults(&sema, ty), - .@"enum" => Sema.type_resolution.resolveEnumValues(&sema, ty), - else => unreachable, - }; - result catch |err| switch (err) { + Sema.type_resolution.resolveStructDefaults(&sema, ty) catch |err| switch (err) { error.AnalysisFail => { if (!zcu.failed_analysis.contains(anal_unit)) { // If this unit caused the error, it would have an entry in `failed_analysis`. @@ -1270,20 +1275,6 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu const tracy = trace(@src()); defer tracy.end(); - // TODO: document this elsewhere mlugg! - // For my own benefit, here's how a namespace update for a normal (non-file-root) type works: - // `const S = struct { ... };` - // We are adding or removing a declaration within this `struct`. - // * `S` registers a dependency on `.{ .src_hash = (declaration of S) }` - // * Any change to the `struct` body -- including changing a declaration -- invalidates this - // * `S` is re-analyzed, but notes: - // * there is an existing struct instance (at this `TrackedInst` with these captures) - // * the struct's resolution is up-to-date (because nothing about the fields changed) - // * so, it uses the same `struct` - // * but this doesn't stop it from updating the namespace! - // * we basically do `scanDecls`, updating the namespace as needed - // * so everyone lived happily ever after - const zcu = pt.zcu; const gpa = zcu.gpa; const ip = &zcu.intern_pool; @@ -3033,7 +3024,7 @@ fn analyzeFuncBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.Sem const zir = file.zir.?; try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, {}); - errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit); + defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); func.setAnalyzed(ip, io); if (func.analysisUnordered(ip).inferred_error_set) { @@ -3231,9 +3222,6 @@ fn analyzeFuncBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.Sem func.setResolvedErrorSet(ip, io, ies.resolved); } - // MLUGG TODO: i think this can go away and the assert move to the defer? - assert(zcu.analysis_in_progress.swapRemove(anal_unit)); - try sema.flushExports(); defer { @@ -3835,7 +3823,6 @@ pub fn enumValue(pt: Zcu.PerThread, ty: Type, tag_int: InternPool.Index) Allocat /// declaration order. pub fn enumValueFieldIndex(pt: Zcu.PerThread, ty: Type, field_index: u32) Allocator.Error!Value { const ip = &pt.zcu.intern_pool; - ty.assertHasInits(pt.zcu); const enum_type = ip.loadEnumType(ty.toIntern()); assert(field_index < enum_type.field_names.len); @@ -3859,7 +3846,9 @@ pub fn enumValueFieldIndex(pt: Zcu.PerThread, ty: Type, field_index: u32) Alloca pub fn undefValue(pt: Zcu.PerThread, ty: Type) Allocator.Error!Value { if (std.debug.runtime_safety) { - assert(try ty.onePossibleValue(pt) == null); + if (try ty.onePossibleValue(pt)) |opv| { + assert(opv.isUndef(pt.zcu)); + } } return .fromInterned(try pt.intern(.{ .undef = ty.toIntern() })); } @@ -3941,7 +3930,10 @@ pub fn aggregateValue(pt: Zcu.PerThread, ty: Type, elems: []const InternPool.Ind for (elems) |elem| { if (!Value.fromInterned(elem).isUndef(pt.zcu)) break; } else if (elems.len > 0) { - return pt.undefValue(ty); // all-undef + // All undef, so return an undef struct. However, don't use `undefValue`, because its + // non-OPV assertion can loop on `[1]@TypeOf(undefined)`: that type has an OPV of + // `.{undefined}`, which here we normalize to `undefined`. + return .fromInterned(try pt.intern(.{ .undef = ty.toIntern() })); } return .fromInterned(try pt.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -4096,19 +4088,6 @@ pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) Allocator.Error! return result.index; } -// TODO: this shouldn't need a `PerThread`! Fix the signature of `Type.abiAlignment`. -// MLUGG TODO: that's done, move it! -pub fn navAlignment(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) InternPool.Alignment { - const zcu = pt.zcu; - const ty: Type, const alignment = switch (zcu.intern_pool.getNav(nav_index).status) { - .unresolved => unreachable, - .type_resolved => |r| .{ .fromInterned(r.type), r.alignment }, - .fully_resolved => |r| .{ Value.fromInterned(r.val).typeOf(zcu), r.alignment }, - }; - if (alignment != .none) return alignment; - return ty.abiAlignment(zcu); -} - /// Given a namespace, re-scan its declarations from the type definition if they have not /// yet been re-scanned on this update. /// If the type declaration instruction has been lost, returns `error.AnalysisFail`. @@ -4393,7 +4372,7 @@ pub fn resolveTypeForCodegen(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void { .@"struct" => switch (ip.indexToKey(ty.toIntern())) { .struct_type => { try pt.ensureTypeLayoutUpToDate(ty); - try pt.ensureTypeInitsUpToDate(ty); + try pt.ensureStructDefaultsUpToDate(ty); }, .tuple_type => |tuple| for (0..tuple.types.len) |i| { const field_is_comptime = tuple.values.get(ip)[i] != .none; @@ -4405,7 +4384,7 @@ pub fn resolveTypeForCodegen(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void { }, .@"union" => try pt.ensureTypeLayoutUpToDate(ty), - .@"enum" => try pt.ensureTypeInitsUpToDate(ty), + .@"enum" => try pt.ensureTypeLayoutUpToDate(ty), } } pub fn resolveValueTypesForCodegen(pt: Zcu.PerThread, val: Value) Zcu.SemaError!void { diff --git a/src/codegen.zig b/src/codegen.zig index 67575beb3f6f1a5b55a02fe75c0c8b9a576f906f..e9acab66e4c2b8a618447ea6fad9659ab1c39243 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -347,7 +347,6 @@ pub fn generateSymbol( .void => unreachable, // non-runtime value .null => unreachable, // non-runtime value .@"unreachable" => unreachable, // non-runtime value - .empty_tuple => return, .false, .true => try w.writeByte(switch (simple_value) { .false => 0, .true => 1, @@ -1065,20 +1064,20 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo const elem_ty = ty.childType(zcu); const ptr = ip.indexToKey(val.toIntern()).ptr; if (ptr.base_addr == .int) return .{ .immediate = ptr.byte_offset }; - switch (ptr.base_addr) { + if (ptr.byte_offset == 0) switch (ptr.base_addr) { .int => unreachable, // handled above - .nav => |nav| if (elem_ty.isFnOrHasRuntimeBits(zcu)) { + .nav => |nav| if (elem_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { return .{ .lea_nav = nav }; } else { // Create the 0xaa bit pattern... const undef_ptr_bits: u64 = @intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() + 1)) / 3); // ...but align the pointer - const alignment = pt.navAlignment(nav); + const alignment = zcu.navAlignment(nav); return .{ .immediate = alignment.forward(undef_ptr_bits) }; }, - .uav => |uav| if (elem_ty.isFnOrHasRuntimeBits(zcu)) { + .uav => |uav| if (elem_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { return .{ .lea_uav = uav }; } else { // Create the 0xaa bit pattern... @@ -1089,7 +1088,7 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo }, else => {}, - } + }; }, }, .int => { diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig index 0e6387949aa8d337f9c731db050551f710fa31e9..74494649056adbe9d0baeceea5f320c9b12f5d95 100644 --- a/src/codegen/aarch64/Select.zig +++ b/src/codegen/aarch64/Select.zig @@ -6594,7 +6594,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, if (try isel.hasRepeatedByteRepr(.fromInterned(fill_val))) |fill_byte| break :fill_byte .{ .constant = fill_byte }; } - switch (dst_ty.indexablePtrElem(zcu).abiSize(zcu)) { + switch (dst_ty.indexableElem(zcu).abiSize(zcu)) { 0 => unreachable, 1 => break :fill_byte .{ .value = bin_op.rhs }, 2, 4, 8 => |size| { @@ -7217,7 +7217,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, const ptr_ra = try ptr_vi.value.defReg(isel) orelse break :unused; const ty_nav = air.data(air.inst_index).ty_nav; - if (ZigType.fromInterned(ip.getNav(ty_nav.nav).typeOf(ip)).isFnOrHasRuntimeBits(zcu)) switch (true) { + if (ZigType.fromInterned(ip.getNav(ty_nav.nav).typeOf(ip)).isRuntimeFnOrHasRuntimeBits(zcu)) switch (true) { false => { try isel.nav_relocs.append(gpa, .{ .nav = ty_nav.nav, @@ -7240,7 +7240,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, }); try isel.emit(.adrp(ptr_ra.x(), 0)); }, - } else try isel.movImmediate(ptr_ra.x(), isel.pt.navAlignment(ty_nav.nav).forward(0xaaaaaaaaaaaaaaaa)); + } else try isel.movImmediate(ptr_ra.x(), zcu.navAlignment(ty_nav.nav).forward(0xaaaaaaaaaaaaaaaa)); } if (air.next()) |next_air_tag| continue :air_tag next_air_tag; }, @@ -10738,7 +10738,7 @@ pub const Value = struct { } }), }), .simple_value => |simple_value| switch (simple_value) { - .undefined, .void, .null, .empty_tuple, .@"unreachable" => unreachable, + .undefined, .void, .null, .@"unreachable" => unreachable, .true => continue :constant_key .{ .int = .{ .ty = .bool_type, .storage = .{ .u64 = 1 }, @@ -10931,7 +10931,7 @@ pub const Value = struct { .ptr => |ptr| { assert(offset == 0 and size == 8); break :free switch (ptr.base_addr) { - .nav => |nav| if (ZigType.fromInterned(ip.getNav(nav).typeOf(ip)).isFnOrHasRuntimeBits(zcu)) switch (true) { + .nav => |nav| if (ZigType.fromInterned(ip.getNav(nav).typeOf(ip)).isRuntimeFnOrHasRuntimeBits(zcu)) switch (true) { false => { try isel.nav_relocs.append(zcu.gpa, .{ .nav = nav, @@ -10965,9 +10965,9 @@ pub const Value = struct { }, } else continue :constant_key .{ .int = .{ .ty = .usize_type, - .storage = .{ .u64 = isel.pt.navAlignment(nav).forward(0xaaaaaaaaaaaaaaaa) }, + .storage = .{ .u64 = zcu.navAlignment(nav).forward(0xaaaaaaaaaaaaaaaa) }, } }, - .uav => |uav| if (ZigType.fromInterned(ip.typeOf(uav.val)).isFnOrHasRuntimeBits(zcu)) switch (true) { + .uav => |uav| if (ZigType.fromInterned(ip.typeOf(uav.val)).isRuntimeFnOrHasRuntimeBits(zcu)) switch (true) { false => { try isel.uav_relocs.append(zcu.gpa, .{ .uav = uav, diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 831a64779bc423595b5433b4d70eaf8a5c0fbf37..5e9f21e1aada16d7fa98ebd9a9c01d7b11a35d8c 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -789,7 +789,7 @@ pub const DeclGen = struct { // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. const ptr_ty: Type = .fromInterned(uav.orig_ty); - if (ptr_ty.isPtrAtRuntime(zcu) and !uav_ty.isFnOrHasRuntimeBits(zcu)) { + if (ptr_ty.isPtrAtRuntime(zcu) and !uav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { return dg.writeCValue(w, .{ .undef = ptr_ty }); } @@ -862,7 +862,7 @@ pub const DeclGen = struct { // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. const nav_ty: Type = .fromInterned(ip.getNav(owner_nav).typeOf(ip)); const ptr_ty = try pt.navPtrType(owner_nav); - if (!nav_ty.isFnOrHasRuntimeBits(zcu)) { + if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { return dg.writeCValue(w, .{ .undef = ptr_ty }); } @@ -1043,7 +1043,6 @@ pub const DeclGen = struct { .undefined => unreachable, .void => unreachable, .null => unreachable, - .empty_tuple => unreachable, .@"unreachable" => unreachable, .false => try w.writeAll("false"), @@ -3077,7 +3076,7 @@ pub fn genDecl(o: *Object) Error!void { const nav = ip.getNav(o.dg.pass.nav); const nav_ty: Type = .fromInterned(nav.typeOf(ip)); - if (!nav_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return; + if (!nav_ty.hasRuntimeBits(zcu)) return; switch (ip.indexToKey(nav.status.fully_resolved.val)) { .@"extern" => |@"extern"| { if (!ip.isFunctionType(nav_ty.toIntern())) return o.dg.renderFwdDecl(o.dg.pass.nav, .{ @@ -3676,7 +3675,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { const inst_ty = f.typeOfIndex(inst); const ptr_ty = f.typeOf(bin_op.lhs); - const elem_has_bits = ptr_ty.indexablePtrElem(zcu).hasRuntimeBitsIgnoreComptime(zcu); + const elem_has_bits = ptr_ty.indexableElem(zcu).hasRuntimeBitsIgnoreComptime(zcu); const ptr = try f.resolveInst(bin_op.lhs); const index = try f.resolveInst(bin_op.rhs); @@ -3792,7 +3791,7 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { const zcu = pt.zcu; const inst_ty = f.typeOfIndex(inst); const elem_ty = inst_ty.childType(zcu); - if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .{ .undef = inst_ty }; + if (!elem_ty.hasRuntimeBits(zcu)) return .{ .undef = inst_ty }; const local = try f.allocLocalValue(.{ .ctype = try f.ctypeFromType(elem_ty, .complete), @@ -3829,7 +3828,7 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { const zcu = pt.zcu; const inst_ty = f.typeOfIndex(inst); const elem_ty = inst_ty.childType(zcu); - if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .{ .undef = inst_ty }; + if (!elem_ty.hasRuntimeBits(zcu)) return .{ .undef = inst_ty }; const local = try f.allocLocalValue(.{ .ctype = try f.ctypeFromType(elem_ty, .complete), @@ -4502,7 +4501,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { const inst_ty = f.typeOfIndex(inst); const inst_scalar_ty = inst_ty.scalarType(zcu); - const elem_ty = inst_scalar_ty.indexablePtrElem(zcu); + const elem_ty = inst_scalar_ty.indexableElem(zcu); if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return f.moveCValue(inst, inst_ty, lhs); const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); @@ -7037,7 +7036,7 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index, function_paren: []const u8) !CV try w.writeAll(", "); try writeArrayLen(f, dest_ptr, dest_ty); try w.writeAll(" * sizeof("); - try f.renderType(w, dest_ty.indexablePtrElem(zcu)); + try f.renderType(w, dest_ty.indexableElem(zcu)); try w.writeAll("));"); try f.object.newline(); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 1327b7b2e1c9985b30f53c4411a8fcf8afa9f89c..ad115504baec4eaad608f6f3cf9d614a3e9d610d 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3725,7 +3725,6 @@ pub const Object = struct { .undefined => unreachable, // non-runtime value .void => unreachable, // non-runtime value .null => unreachable, // non-runtime value - .empty_tuple => unreachable, // non-runtime value .@"unreachable" => unreachable, // non-runtime value .false => .false, @@ -4604,7 +4603,7 @@ pub const NavGen = struct { _ = try o.resolveLlvmFunction(pt, owner_nav); } else { const variable_index = try o.resolveGlobalNav(pt, nav_index); - variable_index.setAlignment(pt.navAlignment(nav_index).toLlvm(), &o.builder); + variable_index.setAlignment(zcu.navAlignment(nav_index).toLlvm(), &o.builder); if (resolved.@"linksection".toSlice(ip)) |section| variable_index.setSection(try o.builder.string(section), &o.builder); if (is_const) variable_index.setMutability(.constant, &o.builder); @@ -5953,7 +5952,7 @@ pub const FuncGen = struct { return .none; } - const have_block_result = inst_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu); + const have_block_result = inst_ty.hasRuntimeBits(zcu); var breaks: BreakList = if (have_block_result) .{ .list = .{} } else .{ .len = 0 }; defer if (have_block_result) breaks.list.deinit(self.gpa); @@ -6000,7 +5999,7 @@ pub const FuncGen = struct { // Add the values to the lists only if the break provides a value. const operand_ty = self.typeOf(branch.operand); - if (operand_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { + if (operand_ty.hasRuntimeBits(zcu)) { const val = try self.resolveInst(branch.operand); // For the phi node, we need the basic blocks and the values of the @@ -9581,7 +9580,7 @@ pub const FuncGen = struct { const zcu = pt.zcu; const ptr_ty = self.typeOfIndex(inst); const pointee_type = ptr_ty.childType(zcu); - if (!pointee_type.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) + if (!pointee_type.hasRuntimeBits(zcu)) return (try o.lowerPtrToVoid(pt, ptr_ty)).toValue(); const pointee_llvm_ty = try o.lowerType(pt, pointee_type); @@ -9595,7 +9594,7 @@ pub const FuncGen = struct { const zcu = pt.zcu; const ptr_ty = self.typeOfIndex(inst); const ret_ty = ptr_ty.childType(zcu); - if (!ret_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) + if (!ret_ty.hasRuntimeBits(zcu)) return (try o.lowerPtrToVoid(pt, ptr_ty)).toValue(); if (self.ret_ptr != .none) return self.ret_ptr; const ret_llvm_ty = try o.lowerType(pt, ret_ty); @@ -9897,7 +9896,7 @@ pub const FuncGen = struct { const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ptr_ty = self.typeOf(bin_op.lhs); const operand_ty = ptr_ty.childType(zcu); - if (!operand_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .none; + if (!operand_ty.hasRuntimeBits(zcu)) return .none; const ptr = try self.resolveInst(bin_op.lhs); var element = try self.resolveInst(bin_op.rhs); const llvm_abi_ty = try o.getAtomicAbiType(pt, operand_ty, false); @@ -11478,7 +11477,7 @@ pub const FuncGen = struct { const zcu = pt.zcu; const info = ptr_ty.ptrInfo(zcu); const elem_ty = Type.fromInterned(info.child); - if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { + if (!elem_ty.hasRuntimeBits(zcu)) { return; } const ptr_alignment = ptr_ty.ptrAlignment(zcu).toLlvm(); diff --git a/src/codegen/riscv64/CodeGen.zig b/src/codegen/riscv64/CodeGen.zig index dd4ca3f88bbc6bc082a00ab1e62a1b685e068e06..72174554adc862a80034a2af57721703cba0c7a2 100644 --- a/src/codegen/riscv64/CodeGen.zig +++ b/src/codegen/riscv64/CodeGen.zig @@ -2673,7 +2673,7 @@ fn genBinOp( defer func.register_manager.unlockReg(tmp_lock); // RISC-V has no immediate mul, so we copy the size to a temporary register - const elem_size = lhs_ty.indexablePtrElem(zcu).abiSize(zcu); + const elem_size = lhs_ty.indexableElem(zcu).abiSize(zcu); const elem_size_reg = try func.copyToTmpRegister(Type.u64, .{ .immediate = elem_size }); try func.genBinOp( @@ -3913,7 +3913,7 @@ fn airPtrElemVal(func: *Func, inst: Air.Inst.Index) !void { const base_ptr_ty = func.typeOf(bin_op.lhs); const result: MCValue = if (!is_volatile and func.liveness.isUnused(inst)) .unreach else result: { - const elem_ty = base_ptr_ty.indexablePtrElem(zcu); + const elem_ty = base_ptr_ty.indexableElem(zcu); if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none; const base_ptr_mcv = try func.resolveInst(bin_op.lhs); const base_ptr_lock: ?RegisterLock = switch (base_ptr_mcv) { diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig index e6850df250db68f6b34050f93cb19717ff90ecb2..5217002f22ecaa5dc3aad1a2035040baa6132e5c 100644 --- a/src/codegen/spirv/CodeGen.zig +++ b/src/codegen/spirv/CodeGen.zig @@ -821,7 +821,6 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { .undefined, .void, .null, - .empty_tuple, .@"unreachable", => unreachable, // non-runtime values @@ -1150,7 +1149,7 @@ fn constantUavRef( } // const is_fn_body = decl_ty.zigTypeTag(zcu) == .@"fn"; - if (!uav_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { + if (!uav_ty.hasRuntimeBits(zcu)) { // Pointer to nothing - return undefined return cg.module.constUndef(ty_id); } @@ -1196,7 +1195,7 @@ fn constantNavRef(cg: *CodeGen, ty: Type, nav_index: InternPool.Nav.Index) !Id { }, } - if (!nav_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { + if (!nav_ty.hasRuntimeBits(zcu)) { // Pointer to nothing - return undefined. return cg.module.constUndef(ty_id); } @@ -4381,7 +4380,7 @@ fn airSliceElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { fn ptrElemPtr(cg: *CodeGen, ptr_ty: Type, ptr_id: Id, index_id: Id) !Id { const zcu = cg.module.zcu; // Construct new pointer type for the resulting pointer - const elem_ty = ptr_ty.indexablePtrElem(zcu); + const elem_ty = ptr_ty.indexableElem(zcu); const elem_ty_id = try cg.resolveType(elem_ty, .indirect); const elem_ptr_ty_id = try cg.module.ptrType(elem_ty_id, cg.module.storageClass(ptr_ty.ptrAddressSpace(zcu))); if (ptr_ty.isSinglePointer(zcu)) { @@ -5028,7 +5027,7 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index) const gpa = cg.module.gpa; const zcu = cg.module.zcu; const ty = cg.typeOfIndex(inst); - const have_block_result = ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu); + const have_block_result = ty.hasRuntimeBits(zcu); const cf = switch (cg.control_flow) { .structured => |*cf| cf, @@ -5166,7 +5165,7 @@ fn airBr(cg: *CodeGen, inst: Air.Inst.Index) !void { switch (cg.control_flow) { .structured => |*cf| { - if (operand_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { + if (operand_ty.hasRuntimeBits(zcu)) { const operand_id = try cg.resolve(br.operand); const block_result_var_id = cf.block_results.get(br.block_inst).?; try cg.store(operand_ty, block_result_var_id, operand_id, .{}); @@ -5177,7 +5176,7 @@ fn airBr(cg: *CodeGen, inst: Air.Inst.Index) !void { }, .unstructured => |cf| { const block = cf.blocks.get(br.block_inst).?; - if (operand_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { + if (operand_ty.hasRuntimeBits(zcu)) { const operand_id = try cg.resolve(br.operand); // block_label should not be undefined here, lest there // is a br or br_void in the function's body. diff --git a/src/codegen/wasm/CodeGen.zig b/src/codegen/wasm/CodeGen.zig index 90de3461cacbfdb90b07a3f2898598ed27be9ac7..955e9b51d361ec75ea1c1b5ab08c71dc7f2cbd40 100644 --- a/src/codegen/wasm/CodeGen.zig +++ b/src/codegen/wasm/CodeGen.zig @@ -2099,7 +2099,7 @@ fn airRetPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const child_type = cg.typeOfIndex(inst).childType(zcu); const result = result: { - if (!child_type.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) { + if (!child_type.hasRuntimeBits(zcu)) { break :result try cg.allocStack(Type.usize); // create pointer to void } @@ -3161,7 +3161,6 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { .undefined, .void, .null, - .empty_tuple, .@"unreachable", => unreachable, // non-runtime values .false, .true => return .{ .imm32 = switch (simple_value) { diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index 872404b71572de6124f68ed84dfbca6b5122152f..a9898398d7318fc1cf6046fac752c998ae3a5282 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -104121,7 +104121,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { }, .slice_elem_val, .ptr_elem_val => { const bin_op = air_datas[@intFromEnum(inst)].bin_op; - const res_ty = cg.typeOf(bin_op.lhs).indexablePtrElem(zcu); + const res_ty = cg.typeOf(bin_op.lhs).indexableElem(zcu); var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); try ops[0].toSlicePtr(cg); var res: [1]Temp = undefined; @@ -188179,8 +188179,8 @@ const Select = struct { .signed => false, .unsigned => size.bitSize(cg.target) >= int_info.bits, } else false, - .elem_size_is => |size| size == ty.indexablePtrElem(zcu).abiSize(zcu), - .po2_elem_size => std.math.isPowerOfTwo(ty.indexablePtrElem(zcu).abiSize(zcu)), + .elem_size_is => |size| size == ty.indexableElem(zcu).abiSize(zcu), + .po2_elem_size => std.math.isPowerOfTwo(ty.indexableElem(zcu).abiSize(zcu)), }; } }; @@ -189941,9 +189941,9 @@ const Select = struct { op.flags.base.ref.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu), @divExact(op.flags.base.size.bitSize(s.cg.target), 8), )), - .elem_size => @intCast(op.flags.base.ref.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)), - .src0_elem_size => @intCast(Select.Operand.Ref.src0.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)), - .dst0_elem_size => @intCast(Select.Operand.Ref.dst0.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)), + .elem_size => @intCast(op.flags.base.ref.typeOf(s).indexableElem(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)), + .src0_elem_size => @intCast(Select.Operand.Ref.src0.typeOf(s).indexableElem(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)), + .dst0_elem_size => @intCast(Select.Operand.Ref.dst0.typeOf(s).indexableElem(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)), .src0_elem_size_mul_src1 => @intCast(Select.Operand.Ref.src0.typeOf(s).indexableElem(s.cg.pt.zcu).abiSize(s.cg.pt.zcu) * Select.Operand.Ref.src1.valueOf(s).immediate), .vector_index => switch (op.flags.base.ref.typeOf(s).ptrInfo(s.cg.pt.zcu).flags.vector_index) { @@ -189953,7 +189953,7 @@ const Select = struct { .src1 => @intCast(Select.Operand.Ref.src1.valueOf(s).immediate), .src1_sub_bit_size => @as(SignedImm, @intCast(Select.Operand.Ref.src1.valueOf(s).immediate)) - @as(SignedImm, @intCast(s.cg.nonBoolScalarBitSize(op.flags.base.ref.typeOf(s)))), - .log2_src0_elem_size => @intCast(std.math.log2(Select.Operand.Ref.src0.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu))), + .log2_src0_elem_size => @intCast(std.math.log2(Select.Operand.Ref.src0.typeOf(s).indexableElem(s.cg.pt.zcu).abiSize(s.cg.pt.zcu))), .elem_mask => @as(u8, std.math.maxInt(u8)) >> @intCast( 8 - ((s.cg.unalignedSize(op.flags.base.ref.typeOf(s)) - 1) % @divExact(op.flags.base.size.bitSize(s.cg.target), 8) + 1 >> diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 03b757f5b4c9e079cb61c277e305ccc4bdd81472..7440711574f72c47d003f63ff48adee2e522b9e8 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -1552,7 +1552,7 @@ fn updateNavInner(coff: *Coff, pt: Zcu.PerThread, nav_index: InternPool.Nav.Inde const sec_si = try coff.navSection(zcu, nav.status.fully_resolved); try coff.nodes.ensureUnusedCapacity(gpa, 1); const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{ - .alignment = pt.navAlignment(nav_index).toStdMem(), + .alignment = zcu.navAlignment(nav_index).toStdMem(), .moved = true, }); coff.nodes.appendAssumeCapacity(.{ .nav = nmi }); diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 588b4e3fc39a2f2af664b996575157558991db75..96db16681ca6a89c0570ab14f1ae09a7e6d5d91b 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -1479,7 +1479,7 @@ fn updateTlv( log.debug("updateTlv {f}({d})", .{ nav.fqn.fmt(ip), nav_index }); - const required_alignment = pt.navAlignment(nav_index); + const required_alignment = zcu.navAlignment(nav_index); const sym = self.symbol(sym_index); const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig index 81e6c23af82805f96d09409637b0e14e0dc49165..bab805af760d7ea4a5c6433bf6bccb96602dcb5b 100644 --- a/src/link/Elf2.zig +++ b/src/link/Elf2.zig @@ -2906,7 +2906,7 @@ fn updateNavInner(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) try elf.nodes.ensureUnusedCapacity(gpa, 1); const sec_si = elf.navSection(ip, nav.status.fully_resolved); const ni = try elf.mf.addLastChildNode(gpa, sec_si.node(elf), .{ - .alignment = pt.navAlignment(nav_index).toStdMem(), + .alignment = zcu.navAlignment(nav_index).toStdMem(), .moved = true, }); elf.nodes.appendAssumeCapacity(.{ .nav = nmi }); diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index 49555c2746a46dc0ee9617aea5f0de67d35ef313..fc3ac0fca8f5588ad67cd10c9a7a563f16a2aec4 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -925,7 +925,7 @@ pub fn updateNav( const sect_index = try self.getNavOutputSection(macho_file, zcu, nav_index, code); if (isThreadlocal(macho_file, nav_index)) - try self.updateTlv(macho_file, pt, nav_index, sym_index, sect_index, code) + try self.updateTlv(macho_file, zcu, nav_index, sym_index, sect_index, code) else try self.updateNavCode(macho_file, pt, nav_index, sym_index, sect_index, code); @@ -1030,13 +1030,13 @@ fn updateNavCode( fn updateTlv( self: *ZigObject, macho_file: *MachO, - pt: Zcu.PerThread, + zcu: *Zcu, nav_index: InternPool.Nav.Index, sym_index: Symbol.Index, sect_index: u8, code: []const u8, ) !void { - const ip = &pt.zcu.intern_pool; + const ip = &zcu.intern_pool; const nav = ip.getNav(nav_index); log.debug("updateTlv {f} (0x{x})", .{ nav.fqn.fmt(ip), nav_index }); @@ -1045,7 +1045,7 @@ fn updateTlv( const init_sym_index = try self.createTlvInitializer( macho_file, nav.fqn.toSlice(ip), - pt.navAlignment(nav_index), + zcu.navAlignment(nav_index), sect_index, code, ); diff --git a/src/print_value.zig b/src/print_value.zig index e58288a16a999c3ee2c17dbd3b31fd8fec4a59d9..5b29bb04d68d3bf380601e2bed30e2cbe4912e86 100644 --- a/src/print_value.zig +++ b/src/print_value.zig @@ -72,8 +72,13 @@ pub fn print( .undef => try writer.writeAll("undefined"), .simple_value => |simple_value| switch (simple_value) { .void => try writer.writeAll("{}"), - .empty_tuple => try writer.writeAll(".{}"), - else => try writer.writeAll(@tagName(simple_value)), + + .undefined, + .null, + .true, + .false, + .@"unreachable", + => try writer.writeAll(@tagName(simple_value)), }, .variable => try writer.writeAll("(variable)"), .@"extern" => |e| try writer.print("(extern '{f}')", .{e.name.fmt(ip)}), @@ -248,17 +253,26 @@ fn printAggregate( const len = ty.arrayLen(zcu); if (is_ref) try writer.writeByte('&'); - try writer.writeAll(".{ "); - - const max_len = @min(len, max_aggregate_items); - for (0..max_len) |i| { - if (i != 0) try writer.writeAll(", "); - try print(try val.fieldValue(pt, i), writer, level - 1, pt, opt_sema); + switch (len) { + 0 => try writer.writeAll(".{}"), + 1 => { + try writer.writeAll(".{"); + try print(try val.fieldValue(pt, 0), writer, level - 1, pt, opt_sema); + try writer.writeByte('}'); + }, + else => { + try writer.writeAll(".{ "); + const max_len = @min(len, max_aggregate_items); + for (0..max_len) |i| { + if (i != 0) try writer.writeAll(", "); + try print(try val.fieldValue(pt, i), writer, level - 1, pt, opt_sema); + } + if (len > max_aggregate_items) { + try writer.writeAll(", ..."); + } + try writer.writeAll(" }"); + }, } - if (len > max_aggregate_items) { - try writer.writeAll(", ..."); - } - return writer.writeAll(" }"); } fn printPtr( diff --git a/src/print_zir.zig b/src/print_zir.zig index cd7d18351ca48c7c767c1347f52e53589a921404..34c816fad62fc80355601fdbc723d2b3e8d02974 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -1439,10 +1439,10 @@ const Writer = struct { try stream.print("{s}, ", .{@tagName(struct_decl.name_strategy)}); - if (struct_decl.backing_int_type != .none) { + if (struct_decl.backing_int_type_body) |backing_int_type_body| { assert(struct_decl.layout == .@"packed"); try stream.writeAll("packed("); - try self.writeInstRef(stream, struct_decl.backing_int_type); + try self.writeBracedDecl(stream, backing_int_type_body); try stream.writeAll("), "); } else { try stream.print("{s}, ", .{@tagName(struct_decl.layout)}); @@ -1507,18 +1507,18 @@ const Writer = struct { .@"packed" => try stream.writeAll("packed, "), .packed_explicit => { try stream.writeAll("packed("); - try self.writeInstRef(stream, union_decl.arg_type); + try self.writeBracedDecl(stream, union_decl.arg_type_body.?); try stream.writeAll("), "); }, .tagged_explicit => { - try stream.writeAll("auto("); - try self.writeInstRef(stream, union_decl.arg_type); + try stream.writeAll("tagged("); + try self.writeBracedDecl(stream, union_decl.arg_type_body.?); try stream.writeAll("), "); }, - .tagged_enum => try stream.writeAll("auto(enum)"), + .tagged_enum => try stream.writeAll("tagged(enum), "), .tagged_enum_explicit => { - try stream.writeAll("auto(enum("); - try self.writeInstRef(stream, union_decl.arg_type); + try stream.writeAll("tagged(enum("); + try self.writeBracedDecl(stream, union_decl.arg_type_body.?); try stream.writeAll(")), "); }, } @@ -1577,7 +1577,11 @@ const Writer = struct { try stream.print("{s}, ", .{@tagName(enum_decl.name_strategy)}); try self.writeFlag(stream, "nonexhaustive, ", enum_decl.nonexhaustive); - try self.writeInstRef(stream, enum_decl.tag_type); + if (enum_decl.tag_type_body) |tag_type_body| { + try stream.writeAll("tag("); + try self.writeBracedDecl(stream, tag_type_body); + try stream.writeAll("), "); + } try self.writeCaptures(stream, enum_decl.captures, enum_decl.capture_names); try stream.writeAll(", "); @@ -1585,9 +1589,9 @@ const Writer = struct { try stream.writeAll(", "); if (enum_decl.field_names.len == 0) { - try stream.writeAll(", {}) "); + try stream.writeAll("{}) "); } else { - try stream.writeAll(", {\n"); + try stream.writeAll("{\n"); self.indent += 2; var it = enum_decl.iterateFields(); -- 2.54.0 From e3e9ae12bd3a7c08f3ed41e801f6cf34bec01af2 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Mon, 26 Jan 2026 21:14:08 +0000 Subject: [PATCH 06/79] Sema: remove unnecessary error sets from resolveInst and resolveValue --- src/Sema.zig | 821 +++++++++++++++++++++++++-------------------------- 1 file changed, 410 insertions(+), 411 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index d1482b86812e6168d0e4fd75ba90f41016903244..09c974fb256e4709030a8e6540e468140af8131c 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1086,7 +1086,7 @@ fn analyzeInlineBody( // This control flow goes further up the stack. return error.ComptimeBreak; } - return try sema.resolveInst(break_inst.data.@"break".operand); + return sema.resolveInst(break_inst.data.@"break".operand); } /// Like `analyzeInlineBody`, but if the body does not break with a value, returns @@ -1873,7 +1873,7 @@ fn analyzeBodyInner( const break_data = opt_break_data orelse break; if (inst == break_data.block_inst) { - break :blk try sema.resolveInst(break_data.operand); + break :blk sema.resolveInst(break_data.operand); } else { // `comptime_break_inst` preserved from `analyzeBodyInner` above. return error.ComptimeBreak; @@ -1894,7 +1894,7 @@ fn analyzeBodyInner( extra.end + then_body.len, extra.data.else_body_len, ); - const uncasted_cond = try sema.resolveInst(extra.data.condition); + const uncasted_cond = sema.resolveInst(extra.data.condition); const cond = try sema.coerce(block, .bool, uncasted_cond, cond_src); const cond_val = try sema.resolveConstDefinedValue( block, @@ -1920,7 +1920,7 @@ fn analyzeBodyInner( const operand_src = block.src(.{ .node_offset_try_operand = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len); - const err_union = try sema.resolveInst(extra.data.operand); + const err_union = sema.resolveInst(extra.data.operand); const err_union_ty = sema.typeOf(err_union); if (err_union_ty.zigTypeTag(zcu) != .error_union) { return sema.failWithOwnedErrorMsg(block, msg: { @@ -1946,7 +1946,7 @@ fn analyzeBodyInner( const operand_src = block.src(.{ .node_offset_try_operand = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len); - const operand = try sema.resolveInst(extra.data.operand); + const operand = sema.resolveInst(extra.data.operand); const err_union = try sema.analyzeLoad(block, src, operand, operand_src); const is_non_err_val = (try sema.resolveIsNonErrVal(block, operand_src, err_union)).?; if (is_non_err_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, operand_src, null); @@ -1975,7 +1975,7 @@ fn analyzeBodyInner( const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].defer_err_code; const extra = sema.code.extraData(Zir.Inst.DeferErrCode, inst_data.payload_index).data; const defer_body = sema.code.bodySlice(extra.index, extra.len); - const err_code = try sema.resolveInst(inst_data.err_code); + const err_code = sema.resolveInst(inst_data.err_code); try map.ensureSpaceForInstructions(sema.gpa, defer_body); map.putAssumeCapacity(extra.remapped_err_code, err_code); if (sema.analyzeBodyInner(block, defer_body)) { @@ -2022,7 +2022,7 @@ fn analyzeBodyInner( } } -pub fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref { +fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) Air.Inst.Ref { if (zir_ref == .none) { return .none; } else { @@ -2030,7 +2030,7 @@ pub fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref { } } -pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref { +fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) Air.Inst.Ref { assert(zir_ref != .none); if (zir_ref.toIndex()) |i| { return sema.inst_map.get(i).?; @@ -2047,7 +2047,7 @@ fn resolveConstBool( zir_ref: Zir.Inst.Ref, reason: ComptimeReason, ) !bool { - const air_inst = try sema.resolveInst(zir_ref); + const air_inst = sema.resolveInst(zir_ref); const wanted_type: Type = .bool; const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src); const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, reason); @@ -2063,7 +2063,7 @@ fn resolveConstString( /// being comptime-resolved is that the block is being comptime-evaluated. reason: ?ComptimeReason, ) ![]u8 { - const air_inst = try sema.resolveInst(zir_ref); + const air_inst = sema.resolveInst(zir_ref); return sema.toConstString(block, src, air_inst, reason); } @@ -2090,7 +2090,7 @@ pub fn resolveConstStringIntern( zir_ref: Zir.Inst.Ref, reason: ComptimeReason, ) !InternPool.NullTerminatedString { - const air_inst = try sema.resolveInst(zir_ref); + const air_inst = sema.resolveInst(zir_ref); const wanted_type: Type = .slice_const_u8; const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src); const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, reason); @@ -2098,7 +2098,7 @@ pub fn resolveConstStringIntern( } fn resolveTypeOrPoison(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !?Type { - const air_inst = try sema.resolveInst(zir_ref); + const air_inst = sema.resolveInst(zir_ref); const ty = try sema.analyzeAsType(block, src, .type, air_inst); if (ty.isGenericPoison()) return null; return ty; @@ -2192,7 +2192,7 @@ fn genericPoisonReason(sema: *Sema, block: *Block, ref: Zir.Inst.Ref) GenericPoi // There are two cases here: the pointer type may already have been // generic poison, or it may have been an anyopaque pointer. const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const operand_ref = try sema.resolveInst(un_node.operand); + const operand_ref = sema.resolveInst(un_node.operand); const operand_val = operand_ref.toInterned() orelse return .unknown; if (operand_val == .generic_poison_type) { // The pointer was generic poison - keep looking. @@ -2271,8 +2271,7 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) } /// Return the Value corresponding to a given AIR ref, or `null` if it refers to a runtime value. -/// TODO MLUGG: remove the error union return! -fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) error{}!?Value { +fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) ?Value { const zcu = sema.pt.zcu; assert(inst != .none); @@ -2308,7 +2307,7 @@ pub fn resolveConstValue( /// being comptime-resolved is that the block is being comptime-evaluated. reason: ?ComptimeReason, ) CompileError!Value { - return try sema.resolveValue(inst) orelse { + return sema.resolveValue(inst) orelse { return sema.failWithNeededComptime(block, src, reason); }; } @@ -2322,7 +2321,7 @@ fn resolveDefinedValue( ) CompileError!?Value { const pt = sema.pt; const zcu = pt.zcu; - const val = try sema.resolveValue(air_ref) orelse return null; + const val = sema.resolveValue(air_ref) orelse return null; if (val.isUndef(zcu)) return sema.failWithUseOfUndef(block, src, null); return val; } @@ -2795,7 +2794,7 @@ fn resolveAlign( src: LazySrcLoc, zir_ref: Zir.Inst.Ref, ) !Alignment { - const air_ref = try sema.resolveInst(zir_ref); + const air_ref = sema.resolveInst(zir_ref); return sema.analyzeAsAlign(block, src, air_ref); } @@ -2807,7 +2806,7 @@ fn resolveInt( dest_ty: Type, reason: ComptimeReason, ) !u64 { - const air_ref = try sema.resolveInst(zir_ref); + const air_ref = sema.resolveInst(zir_ref); return sema.analyzeAsInt(block, src, air_ref, dest_ty, reason); } @@ -2886,7 +2885,7 @@ fn zirTupleDecl( field_ty.* = field_type.toIntern(); field_init.* = init: { if (zir_field_init != .none) { - const uncoerced_field_init = try sema.resolveInst(zir_field_init); + const uncoerced_field_init = sema.resolveInst(zir_field_init); const coerced_field_init = try sema.coerce(block, field_type, uncoerced_field_init, init_src); const field_init_val = try sema.resolveConstDefinedValue(block, init_src, coerced_field_init, .{ .simple = .tuple_field_default_value }); if (field_init_val.canMutateComptimeVarState(zcu)) { @@ -2959,8 +2958,8 @@ fn getCaptures( capture.* = switch (zir_capture.unwrap()) { .nested => |parent_idx| parent_captures.get(ip)[parent_idx], .instruction_load => |ptr_inst| capture: { - const ptr_ref = try sema.resolveInst(ptr_inst.toRef()); - const ptr_val = try sema.resolveValue(ptr_ref) orelse { + const ptr_ref = sema.resolveInst(ptr_inst.toRef()); + const ptr_val = sema.resolveValue(ptr_ref) orelse { break :capture .wrap(.{ .runtime = sema.typeOf(ptr_ref).childType(zcu).toIntern() }); }; // TODO: better source location @@ -2974,8 +2973,8 @@ fn getCaptures( break :capture .wrap(.{ .@"comptime" = loaded_val.toIntern() }); }, .instruction => |inst| capture: { - const air_ref = try sema.resolveInst(inst.toRef()); - if (try sema.resolveValue(air_ref)) |val| { + const air_ref = sema.resolveInst(inst.toRef()); + if (sema.resolveValue(air_ref)) |val| { if (val.canMutateComptimeVarState(zcu)) { const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_name_slice, .no_embedded_nulls); return sema.failWithContainsReferenceToComptimeVar(block, type_src, field_name, "captured value", val); @@ -3079,7 +3078,7 @@ fn zirRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_tok; - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); return sema.analyzeRef(block, block.tokenOffset(inst_data.src_tok), operand); } @@ -3088,7 +3087,7 @@ fn zirEnsureResultUsed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compile defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const src = block.nodeOffset(inst_data.src_node); return sema.ensureResultUsed(block, sema.typeOf(operand), src); @@ -3134,7 +3133,7 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const src = block.nodeOffset(inst_data.src_node); const operand_ty = sema.typeOf(operand); switch (operand_ty.zigTypeTag(zcu)) { @@ -3160,7 +3159,7 @@ fn zirEnsureErrUnionPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); const err_union_ty = if (operand_ty.zigTypeTag(zcu) == .pointer) operand_ty.childType(zcu) @@ -3185,7 +3184,7 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const object = try sema.resolveInst(inst_data.operand); + const object = sema.resolveInst(inst_data.operand); return indexablePtrLen(sema, block, src, object); } @@ -3331,7 +3330,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const alloc = try sema.resolveInst(inst_data.operand); + const alloc = sema.resolveInst(inst_data.operand); const alloc_ty = sema.typeOf(alloc); const ptr_info = alloc_ty.ptrInfo(zcu); const elem_ty: Type = .fromInterned(ptr_info.child); @@ -3340,7 +3339,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro // However, if the final constructed value does not reference comptime-mutable memory, we wish // to promote it to an anon decl. already_ct: { - const ptr_val = try sema.resolveValue(alloc) orelse break :already_ct; + const ptr_val = sema.resolveValue(alloc) orelse break :already_ct; // If this was a comptime inferred alloc, then `storeToInferredAllocComptime` // might have already done our job and created an anon decl ref. @@ -3526,7 +3525,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, Air.Bin, tmp_air.instructions.items(.data)[@intFromEnum(air_ptr)].ty_pl.payload, ).data; - const idx_val = (try sema.resolveValue(data.rhs)).?; + const idx_val = sema.resolveValue(data.rhs).?; break :blk .{ data.lhs, .{ .elem = idx_val.toUnsignedInt(zcu) }, @@ -3625,7 +3624,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, }, .store, .store_safe => { const air_ptr_inst = store_inst.data.bin_op.lhs.toIndex().?; - const store_val = (try sema.resolveValue(store_inst.data.bin_op.rhs)).?; + const store_val = sema.resolveValue(store_inst.data.bin_op.rhs).?; const new_ptr = ptr_mapping.get(air_ptr_inst).?; try sema.storePtrVal(block, .unneeded, .fromInterned(new_ptr), store_val, store_val.typeOf(zcu)); }, @@ -3708,7 +3707,7 @@ fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Ai const const_ptr_ty = try sema.makePtrTyConst(alloc_ty); // Detect if a comptime value simply needs to have its type changed. - if (try sema.resolveValue(alloc)) |val| { + if (sema.resolveValue(alloc)) |val| { return Air.internedToRef((try sema.pt.getCoerced(val, const_ptr_ty)).toIntern()); } @@ -3840,7 +3839,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); - const ptr = try sema.resolveInst(inst_data.operand); + const ptr = sema.resolveInst(inst_data.operand); const ptr_inst = ptr.toIndex().?; const target = zcu.getTarget(); @@ -4005,7 +4004,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. const arg_len_uncoerced = if (zir_arg_pair[1] == .none) l: { // This argument is an indexable. - const object = try sema.resolveInst(zir_arg_pair[0]); + const object = sema.resolveInst(zir_arg_pair[0]); const object_ty = sema.typeOf(object); if (!object_ty.isIndexable(zcu)) { // Instead of using checkIndexable we customize this error. @@ -4026,8 +4025,8 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. break :l try sema.fieldVal(block, arg_src, object, try ip.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls), arg_src); } else l: { // This argument is a range. - const range_start = try sema.resolveInst(zir_arg_pair[0]); - const range_end = try sema.resolveInst(zir_arg_pair[1]); + const range_start = sema.resolveInst(zir_arg_pair[0]); + const range_end = sema.resolveInst(zir_arg_pair[1]); if (try sema.resolveDefinedValue(block, arg_src, range_start)) |start| { if (try sema.valuesEqual(start, .zero_usize, .usize)) break :l range_end; } @@ -4077,7 +4076,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. const i: u32 = @intCast(i_usize); if (zir_arg_pair[0] == .none) continue; if (zir_arg_pair[1] != .none) continue; - const object = try sema.resolveInst(zir_arg_pair[0]); + const object = sema.resolveInst(zir_arg_pair[0]); const object_ty = sema.typeOf(object); const arg_src = block.src(.{ .for_input = .{ .for_node_offset = inst_data.src_node, @@ -4132,7 +4131,7 @@ fn optEuBasePtrInit(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, src: LazySrcL fn zirOptEuBasePtrInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const ptr = try sema.resolveInst(un_node.operand); + const ptr = sema.resolveInst(un_node.operand); try sema.ensureLayoutResolved(sema.typeOf(ptr).childType(sema.pt.zcu)); return sema.optEuBasePtrInit(block, ptr, block.nodeOffset(un_node.src_node)); } @@ -4143,7 +4142,7 @@ fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(pl_node.src_node); const extra = sema.code.extraData(Zir.Inst.Bin, pl_node.payload_index).data; - const uncoerced_val = try sema.resolveInst(extra.rhs); + const uncoerced_val = sema.resolveInst(extra.rhs); const maybe_wrapped_ptr_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, extra.lhs) orelse return uncoerced_val; const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(zcu); assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction @@ -4259,7 +4258,7 @@ fn zirValidateConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(un_node.src_node); - const init_ref = try sema.resolveInst(un_node.operand); + const init_ref = sema.resolveInst(un_node.operand); if (!try sema.isComptimeKnown(init_ref)) { return sema.failWithNeededComptime(block, src, null); } @@ -4402,7 +4401,7 @@ fn zirValidatePtrStructInit( const instrs = sema.code.bodySlice(validate_extra.end, validate_extra.data.body_len); const field_ptr_data = sema.code.instructions.items(.data)[@intFromEnum(instrs[0])].pl_node; const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data; - const object_ptr = try sema.resolveInst(field_ptr_extra.lhs); + const object_ptr = sema.resolveInst(field_ptr_extra.lhs); const agg_ty = sema.typeOf(object_ptr).childType(zcu).optEuBaseType(zcu); switch (agg_ty.zigTypeTag(zcu)) { .@"struct" => return sema.validateStructInit( @@ -4571,7 +4570,7 @@ fn zirValidatePtrArrayInit( const instrs = sema.code.bodySlice(validate_extra.end, validate_extra.data.body_len); const first_elem_ptr_data = sema.code.instructions.items(.data)[@intFromEnum(instrs[0])].pl_node; const elem_ptr_extra = sema.code.extraData(Zir.Inst.ElemPtrImm, first_elem_ptr_data.payload_index).data; - const array_ptr = try sema.resolveInst(elem_ptr_extra.ptr); + const array_ptr = sema.resolveInst(elem_ptr_extra.ptr); const array_ty = sema.typeOf(array_ptr).childType(zcu).optEuBaseType(zcu); const array_len = array_ty.arrayLen(zcu); @@ -4631,7 +4630,7 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); if (operand_ty.zigTypeTag(zcu) != .pointer) { @@ -4650,7 +4649,7 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr return; } - if (try sema.resolveValue(operand)) |val| { + if (sema.resolveValue(operand)) |val| { if (val.isUndef(zcu)) { return sema.fail(block, src, "cannot dereference undefined value", .{}); } @@ -4685,7 +4684,7 @@ fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp const extra = sema.code.extraData(Zir.Inst.ValidateDestructure, inst_data.payload_index).data; const src = block.nodeOffset(inst_data.src_node); const destructure_src = block.nodeOffset(extra.destructure_node); - const operand = try sema.resolveInst(extra.operand); + const operand = sema.resolveInst(extra.operand); const operand_ty = sema.typeOf(operand); if (!typeIsDestructurable(operand_ty, zcu)) { @@ -4813,8 +4812,8 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(pl_node.src_node); const bin = sema.code.extraData(Zir.Inst.Bin, pl_node.payload_index).data; - const ptr = try sema.resolveInst(bin.lhs); - const operand = try sema.resolveInst(bin.rhs); + const ptr = sema.resolveInst(bin.lhs); + const operand = sema.resolveInst(bin.rhs); const ptr_inst = ptr.toIndex().?; const air_datas = sema.air_instructions.items(.data); @@ -4860,7 +4859,7 @@ fn storeToInferredAllocComptime( const operand_ty = sema.typeOf(operand); // There will be only one store_to_inferred_ptr because we are running at comptime. // The alloc will turn into a Decl or a ComptimeAlloc. - const operand_val = try sema.resolveValue(operand) orelse { + const operand_val = sema.resolveValue(operand) orelse { return sema.failWithNeededComptime(block, src, .{ .simple = .stored_to_comptime_var }); }; const alloc_ty = try pt.ptrType(.{ @@ -4909,8 +4908,8 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v const inst_data = zir_datas[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const ptr = try sema.resolveInst(extra.lhs); - const operand = try sema.resolveInst(extra.rhs); + const ptr = sema.resolveInst(extra.lhs); + const operand = sema.resolveInst(extra.rhs); const is_ret = if (extra.lhs.toIndex()) |ptr_index| zir_tags[@intFromEnum(ptr_index)] == .ret_ptr @@ -5044,9 +5043,9 @@ fn zirCompileLog( for (args, 0..) |arg_ref, i| { if (i != 0) writer.writeAll(", ") catch return error.OutOfMemory; - const arg = try sema.resolveInst(arg_ref); + const arg = sema.resolveInst(arg_ref); const arg_ty = sema.typeOf(arg); - if (try sema.resolveValue(arg)) |val| { + if (sema.resolveValue(arg)) |val| { writer.print("@as({f}, {f})", .{ arg_ty.fmt(pt), val.fmtValueSema(pt, sema), }) catch return error.OutOfMemory; @@ -5094,7 +5093,7 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const msg_inst = try sema.resolveInst(inst_data.operand); + const msg_inst = sema.resolveInst(inst_data.operand); const arg_src = block.builtinCallArgSrc(inst_data.src_node, 0); const coerced_msg = try sema.coerce(block, .slice_const_u8, msg_inst, arg_src); @@ -5464,7 +5463,7 @@ fn resolveBlockBody( const break_data = sema.code.instructions.items(.data)[@intFromEnum(break_inst)].@"break"; const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data; if (extra.block_inst == body_inst) { - return try sema.resolveInst(break_data.operand); + return sema.resolveInst(break_data.operand); } else { return error.ComptimeBreak; } @@ -5555,7 +5554,7 @@ fn resolveAnalyzedBlock( // Okay, we need a runtime block. If the value is comptime-known, the // block should just return void, and we return the merge result // directly. Otherwise, we can defer to the logic below. - if (try sema.resolveValue(merges.results.items[0])) |result_val| { + if (sema.resolveValue(merges.results.items[0])) |result_val| { // Create a block containing all instruction from the body. try parent_block.instructions.append(gpa, merges.block_inst); switch (block_tag) { @@ -5714,7 +5713,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void const ptr_src = block.builtinCallArgSrc(inst_data.src_node, 0); const options_src = block.builtinCallArgSrc(inst_data.src_node, 1); - const ptr = try sema.resolveInst(extra.exported); + const ptr = sema.resolveInst(extra.exported); const ptr_val = try sema.resolveConstDefinedValue(block, ptr_src, ptr, .{ .simple = .export_target }); const ptr_ty = ptr_val.typeOf(zcu); @@ -5878,7 +5877,7 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"break"; const extra = sema.code.extraData(Zir.Inst.Break, inst_data.payload_index).data; - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const zir_block = extra.block_inst; var block = start_block; @@ -5912,7 +5911,7 @@ fn zirSwitchContinue(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) Com const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"break"; const extra = sema.code.extraData(Zir.Inst.Break, inst_data.payload_index).data; const operand_src = start_block.nodeOffset(extra.operand_src_node.unwrap().?); - const uncoerced_operand = try sema.resolveInst(inst_data.operand); + const uncoerced_operand = sema.resolveInst(inst_data.operand); const switch_inst = extra.block_inst; switch (sema.code.instructions.items(.tag)[@intFromEnum(switch_inst)]) { @@ -5921,7 +5920,7 @@ fn zirSwitchContinue(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) Com else => unreachable, // assertion failure } - const operand_ty = (try sema.resolveInst(switch_inst.toRef())).toType(); + const operand_ty = (sema.resolveInst(switch_inst.toRef())).toType(); const operand = try sema.coerce(start_block, operand_ty, uncoerced_operand, operand_src); try sema.validateRuntimeValue(start_block, operand_src, operand); @@ -5988,7 +5987,7 @@ fn zirDbgVar( air_tag: Air.Inst.Tag, ) CompileError!void { const str_op = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_op; - const operand = try sema.resolveInst(str_op.operand); + const operand = sema.resolveInst(str_op.operand); const name = str_op.getStr(sema.code); try sema.addDbgVar(block, operand, air_tag, name); } @@ -6012,7 +6011,7 @@ fn addDbgVar( }; if (val_ty.comptimeOnly(zcu)) return; if (!val_ty.hasRuntimeBits(zcu)) return; - if (try sema.resolveValue(operand)) |operand_val| { + if (sema.resolveValue(operand)) |operand_val| { if (operand_val.canMutateComptimeVarState(zcu)) return; } @@ -6151,7 +6150,7 @@ fn funcDeclSrcInst(sema: *Sema, func_inst: Air.Inst.Ref) !?InternPool.TrackedIns const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; - const func_val = try sema.resolveValue(func_inst) orelse return null; + const func_val = sema.resolveValue(func_inst) orelse return null; if (func_val.isUndef(zcu)) return null; const nav = switch (ip.indexToKey(func_val.toIntern())) { .@"extern" => |e| e.owner_nav, @@ -6323,9 +6322,9 @@ fn zirCall( const pop_error_return_trace = extra.data.flags.pop_error_return_trace; const callee: ResolvedFieldCallee = switch (kind) { - .direct => .{ .direct = try sema.resolveInst(extra.data.callee) }, + .direct => .{ .direct = sema.resolveInst(extra.data.callee) }, .field => blk: { - const object_ptr = try sema.resolveInst(extra.data.obj_ptr); + const object_ptr = sema.resolveInst(extra.data.obj_ptr); const field_name = try zcu.intern_pool.getOrPutString( gpa, io, @@ -7097,7 +7096,7 @@ fn analyzeCall( if (is_comptime) { // We already emitted an error if the argument isn't comptime-known. - comptime_arg.* = (try sema.resolveValue(arg)).?.toIntern(); + comptime_arg.* = sema.resolveValue(arg).?.toIntern(); } else { comptime_arg.* = .none; if (is_noalias) { @@ -7139,7 +7138,7 @@ fn analyzeCall( }; ref_func: { - const runtime_func_val = try sema.resolveValue(runtime_func) orelse break :ref_func; + const runtime_func_val = sema.resolveValue(runtime_func) orelse break :ref_func; if (!ip.isFuncBody(runtime_func_val.toIntern())) break :ref_func; const orig_fn_index = ip.unwrapCoercedFunc(runtime_func_val.toIntern()); try sema.addReferenceEntry(block, call_src, .wrap(.{ .func = orig_fn_index })); @@ -7285,14 +7284,14 @@ fn analyzeCall( if (zcu.comp.config.incremental) break :m false; if (!block.isComptime()) break :m false; for (args) |a| { - const val = (try sema.resolveValue(a)).?; + const val = sema.resolveValue(a).?; if (val.canMutateComptimeVarState(zcu)) break :m false; } break :m true; }; const memoized_arg_values: []const InternPool.Index = if (want_memoize) arg_vals: { const vals = try sema.arena.alloc(InternPool.Index, args.len); - for (vals, args) |*v, a| v.* = (try sema.resolveValue(a)).?.toIntern(); + for (vals, args) |*v, a| v.* = sema.resolveValue(a).?.toIntern(); break :arg_vals vals; } else undefined; if (want_memoize) memoize: { @@ -7453,7 +7452,7 @@ fn analyzeCall( return .unreachable_value; } - const maybe_opv: Air.Inst.Ref = if (try sema.resolveValue(result_raw)) |result_val| r: { + const maybe_opv: Air.Inst.Ref = if (sema.resolveValue(result_raw)) |result_val| r: { const val_resolved = try sema.resolveAdHocInferredErrorSet(block, call_src, result_val.toIntern()); break :r Air.internedToRef(val_resolved); } else r: { @@ -7465,7 +7464,7 @@ fn analyzeCall( }; if (block.isComptime()) { - const result_val = (try sema.resolveValue(maybe_opv)).?; + const result_val = sema.resolveValue(maybe_opv).?; if (want_memoize and sema.allow_memoize and !result_val.canMutateComptimeVarState(zcu)) { _ = try pt.intern(.{ .memoized_call = .{ .func = func_val.?.toIntern(), @@ -7641,7 +7640,7 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil const len = try sema.resolveInt(block, len_src, extra.len, .usize, .{ .simple = .array_length }); const elem_type = try sema.resolveType(block, elem_src, extra.elem_type); try sema.validateArrayElemType(block, elem_type, elem_src); - const uncasted_sentinel = try sema.resolveInst(extra.sentinel); + const uncasted_sentinel = sema.resolveInst(extra.sentinel); const sentinel = try sema.coerce(block, elem_type, uncasted_sentinel, sentinel_src); const sentinel_val = try sema.resolveConstDefinedValue(block, sentinel_src, sentinel, .{ .simple = .array_sentinel }); if (sentinel_val.canMutateComptimeVarState(zcu)) { @@ -7757,11 +7756,11 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; const src = block.nodeOffset(extra.node); const operand_src = block.builtinCallArgSrc(extra.node, 0); - const uncasted_operand = try sema.resolveInst(extra.operand); + const uncasted_operand = sema.resolveInst(extra.operand); const operand = try sema.coerce(block, .anyerror, uncasted_operand, operand_src); const err_int_ty = try pt.errorIntType(); - if (try sema.resolveValue(operand)) |val| { + if (sema.resolveValue(operand)) |val| { if (val.isUndef(zcu)) { return pt.undefRef(err_int_ty); } @@ -7801,7 +7800,7 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; const src = block.nodeOffset(extra.node); const operand_src = block.builtinCallArgSrc(extra.node, 0); - const uncasted_operand = try sema.resolveInst(extra.operand); + const uncasted_operand = sema.resolveInst(extra.operand); const err_int_ty = try pt.errorIntType(); const operand = try sema.coerce(block, err_int_ty, uncasted_operand, operand_src); @@ -7848,8 +7847,8 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr const src = block.src(.{ .node_offset_bin_op = inst_data.src_node }); const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); - const lhs = try sema.resolveInst(extra.lhs); - const rhs = try sema.resolveInst(extra.rhs); + const lhs = sema.resolveInst(extra.lhs); + const rhs = sema.resolveInst(extra.rhs); if (sema.typeOf(lhs).zigTypeTag(zcu) == .bool and sema.typeOf(rhs).zigTypeTag(zcu) == .bool) { const msg = msg: { const msg = try sema.errMsg(lhs_src, "expected error set type, found 'bool'", .{}); @@ -7984,7 +7983,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); const enum_tag: Air.Inst.Ref = switch (operand_ty.zigTypeTag(zcu)) { @@ -8018,7 +8017,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError }); } - if (try sema.resolveValue(enum_tag)) |enum_tag_val| { + if (sema.resolveValue(enum_tag)) |enum_tag_val| { if (enum_tag_val.isUndef(zcu)) return pt.undefRef(int_tag_ty); return .fromValue(enum_tag_val.intFromEnum(zcu)); } @@ -8035,7 +8034,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const src = block.nodeOffset(inst_data.src_node); const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@enumFromInt"); - const operand = try sema.resolveInst(extra.rhs); + const operand = sema.resolveInst(extra.rhs); const operand_ty = sema.typeOf(operand); if (dest_ty.zigTypeTag(zcu) != .@"enum") { @@ -8044,7 +8043,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError try sema.ensureLayoutResolved(dest_ty); _ = try sema.checkIntType(block, operand_src, operand_ty); - if (try sema.resolveValue(operand)) |int_val| { + if (sema.resolveValue(operand)) |int_val| { if (dest_ty.isNonexhaustiveEnum(zcu)) { const int_tag_ty = dest_ty.intTagType(zcu); if (int_val.intFitsInType(int_tag_ty, null, zcu)) { @@ -8099,7 +8098,7 @@ fn zirOptionalPayloadPtr( defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const optional_ptr = try sema.resolveInst(inst_data.operand); + const optional_ptr = sema.resolveInst(inst_data.operand); const src = block.nodeOffset(inst_data.src_node); const ptr_ty = sema.typeOf(optional_ptr); @@ -8193,7 +8192,7 @@ fn zirOptionalPayload( const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); const result_ty = switch (operand_ty.zigTypeTag(zcu)) { .optional => operand_ty.optionalChild(zcu), @@ -8253,7 +8252,7 @@ fn zirErrUnionPayload( const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const operand_src = src; const err_union_ty = sema.typeOf(operand); if (err_union_ty.zigTypeTag(zcu) != .error_union) { @@ -8309,7 +8308,7 @@ fn zirErrUnionPayloadPtr( defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const src = block.nodeOffset(inst_data.src_node); const ptr_ty = sema.typeOf(operand); @@ -8402,7 +8401,7 @@ fn zirErrUnionCode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); return sema.analyzeErrUnionCode(block, src, operand); } @@ -8438,7 +8437,7 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); return sema.analyzeErrUnionCodePtr(block, src, operand); } @@ -9201,7 +9200,7 @@ fn analyzeAs( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - const operand = try sema.resolveInst(zir_operand); + const operand = sema.resolveInst(zir_operand); const dest_ty = try sema.resolveTypeOrPoison(block, src, zir_dest_type) orelse return operand; switch (dest_ty.zigTypeTag(zcu)) { .@"opaque" => return sema.fail(block, src, "cannot cast to opaque type '{f}'", .{dest_ty.fmt(pt)}), @@ -9227,7 +9226,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const ptr_src = block.builtinCallArgSrc(inst_data.src_node, 0); - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); const ptr_ty = operand_ty.scalarType(zcu); const is_vector = operand_ty.zigTypeTag(zcu) == .vector; @@ -9238,7 +9237,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const len = if (is_vector) operand_ty.vectorLen(zcu) else undefined; const dest_ty: Type = if (is_vector) try pt.vectorType(.{ .child = .usize_type, .len = len }) else .usize; - if (try sema.resolveValue(operand)) |operand_val| ct: { + if (sema.resolveValue(operand)) |operand_val| ct: { if (!is_vector) { if (operand_val.isUndef(zcu)) { return .undef_usize; @@ -9297,7 +9296,7 @@ fn zirFieldPtrLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro sema.code.nullTerminatedString(extra.field_name_start), .no_embedded_nulls, ); - const object_ptr = try sema.resolveInst(extra.lhs); + const object_ptr = sema.resolveInst(extra.lhs); return fieldPtrLoad(sema, block, src, object_ptr, field_name, field_name_src); } @@ -9322,7 +9321,7 @@ fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai sema.code.nullTerminatedString(extra.field_name_start), .no_embedded_nulls, ); - const object_ptr = try sema.resolveInst(extra.lhs); + const object_ptr = sema.resolveInst(extra.lhs); return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src, false); } @@ -9347,7 +9346,7 @@ fn zirStructInitFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi sema.code.nullTerminatedString(extra.field_name_start), .no_embedded_nulls, ); - const object_ptr = try sema.resolveInst(extra.lhs); + const object_ptr = sema.resolveInst(extra.lhs); const struct_ty = sema.typeOf(object_ptr).childType(zcu); switch (struct_ty.zigTypeTag(zcu)) { .@"struct", .@"union" => { @@ -9367,7 +9366,7 @@ fn zirFieldPtrNamedLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil const src = block.nodeOffset(inst_data.src_node); const field_name_src = block.builtinCallArgSrc(inst_data.src_node, 1); const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data; - const object_ptr = try sema.resolveInst(extra.lhs); + const object_ptr = sema.resolveInst(extra.lhs); const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.field_name, .{ .simple = .field_name }); return fieldPtrLoad(sema, block, src, object_ptr, field_name, field_name_src); } @@ -9380,7 +9379,7 @@ fn zirFieldPtrNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr const src = block.nodeOffset(inst_data.src_node); const field_name_src = block.builtinCallArgSrc(inst_data.src_node, 1); const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data; - const object_ptr = try sema.resolveInst(extra.lhs); + const object_ptr = sema.resolveInst(extra.lhs); const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.field_name, .{ .simple = .field_name }); return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src, false); } @@ -9395,7 +9394,7 @@ fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@intCast"); - const operand = try sema.resolveInst(extra.rhs); + const operand = sema.resolveInst(extra.rhs); return sema.intCast(block, block.nodeOffset(inst_data.src_node), dest_ty, src, operand, operand_src); } @@ -9470,7 +9469,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@bitCast"); - const operand = try sema.resolveInst(extra.rhs); + const operand = sema.resolveInst(extra.rhs); const operand_ty = sema.typeOf(operand); switch (dest_ty.zigTypeTag(zcu)) { .@"anyframe", @@ -9638,7 +9637,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@floatCast"); const dest_scalar_ty = dest_ty.scalarType(zcu); - const operand = try sema.resolveInst(extra.rhs); + const operand = sema.resolveInst(extra.rhs); const operand_ty = sema.typeOf(operand); const operand_scalar_ty = operand_ty.scalarType(zcu); @@ -9667,7 +9666,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A ), } - if (try sema.resolveValue(operand)) |operand_val| { + if (sema.resolveValue(operand)) |operand_val| { if (!is_vector) { return Air.internedToRef((try operand_val.floatCast(dest_ty, pt)).toIntern()); } @@ -9699,8 +9698,8 @@ fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const array = try sema.resolveInst(extra.lhs); - const elem_index = try sema.resolveInst(extra.rhs); + const array = sema.resolveInst(extra.lhs); + const elem_index = sema.resolveInst(extra.rhs); return sema.elemVal(block, src, array, elem_index, src, false); } @@ -9712,8 +9711,8 @@ fn zirElemPtrLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const src = block.nodeOffset(inst_data.src_node); const elem_index_src = block.src(.{ .node_offset_array_access_index = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const array_ptr = try sema.resolveInst(extra.lhs); - const uncoerced_elem_index = try sema.resolveInst(extra.rhs); + const array_ptr = sema.resolveInst(extra.lhs); + const uncoerced_elem_index = sema.resolveInst(extra.rhs); if (try sema.resolveDefinedValue(block, src, array_ptr)) |array_ptr_val| { const array_ptr_ty = sema.typeOf(array_ptr); if (try sema.pointerDeref(block, src, array_ptr_val, array_ptr_ty)) |array_val| { @@ -9731,7 +9730,7 @@ fn zirElemValImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].elem_val_imm; - const array = try sema.resolveInst(inst_data.operand); + const array = sema.resolveInst(inst_data.operand); const elem_index = try sema.pt.intRef(.usize, inst_data.idx); return sema.elemVal(block, LazySrcLoc.unneeded, array, elem_index, LazySrcLoc.unneeded, false); } @@ -9745,8 +9744,8 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const array_ptr = try sema.resolveInst(extra.lhs); - const elem_index = try sema.resolveInst(extra.rhs); + const array_ptr = sema.resolveInst(extra.lhs); + const elem_index = sema.resolveInst(extra.rhs); const indexable_ty = sema.typeOf(array_ptr); if (indexable_ty.zigTypeTag(zcu) != .pointer) { const capture_src = block.src(.{ .for_capture_from_input = inst_data.src_node }); @@ -9775,8 +9774,8 @@ fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const src = block.nodeOffset(inst_data.src_node); const elem_index_src = block.src(.{ .node_offset_array_access_index = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const array_ptr = try sema.resolveInst(extra.lhs); - const uncoerced_elem_index = try sema.resolveInst(extra.rhs); + const array_ptr = sema.resolveInst(extra.lhs); + const uncoerced_elem_index = sema.resolveInst(extra.rhs); const elem_index = try sema.coerce(block, .usize, uncoerced_elem_index, elem_index_src); return sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src, false, true); } @@ -9790,7 +9789,7 @@ fn zirArrayInitElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compile const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data; - const array_ptr = try sema.resolveInst(extra.ptr); + const array_ptr = sema.resolveInst(extra.ptr); const elem_index = try pt.intRef(.usize, extra.index); const array_ty = sema.typeOf(array_ptr).childType(zcu); switch (array_ty.zigTypeTag(zcu)) { @@ -9809,8 +9808,8 @@ fn zirSliceStart(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.SliceStart, inst_data.payload_index).data; - const array_ptr = try sema.resolveInst(extra.lhs); - const start = try sema.resolveInst(extra.start); + const array_ptr = sema.resolveInst(extra.lhs); + const start = sema.resolveInst(extra.start); const ptr_src = block.src(.{ .node_offset_slice_ptr = inst_data.src_node }); const start_src = block.src(.{ .node_offset_slice_start = inst_data.src_node }); const end_src = block.src(.{ .node_offset_slice_end = inst_data.src_node }); @@ -9825,9 +9824,9 @@ fn zirSliceEnd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.SliceEnd, inst_data.payload_index).data; - const array_ptr = try sema.resolveInst(extra.lhs); - const start = try sema.resolveInst(extra.start); - const end = try sema.resolveInst(extra.end); + const array_ptr = sema.resolveInst(extra.lhs); + const start = sema.resolveInst(extra.start); + const end = sema.resolveInst(extra.end); const ptr_src = block.src(.{ .node_offset_slice_ptr = inst_data.src_node }); const start_src = block.src(.{ .node_offset_slice_start = inst_data.src_node }); const end_src = block.src(.{ .node_offset_slice_end = inst_data.src_node }); @@ -9843,10 +9842,10 @@ fn zirSliceSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr const src = block.nodeOffset(inst_data.src_node); const sentinel_src = block.src(.{ .node_offset_slice_sentinel = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.SliceSentinel, inst_data.payload_index).data; - const array_ptr = try sema.resolveInst(extra.lhs); - const start = try sema.resolveInst(extra.start); - const end: Air.Inst.Ref = if (extra.end == .none) .none else try sema.resolveInst(extra.end); - const sentinel = try sema.resolveInst(extra.sentinel); + const array_ptr = sema.resolveInst(extra.lhs); + const start = sema.resolveInst(extra.start); + const end: Air.Inst.Ref = if (extra.end == .none) .none else sema.resolveInst(extra.end); + const sentinel = sema.resolveInst(extra.sentinel); const ptr_src = block.src(.{ .node_offset_slice_ptr = inst_data.src_node }); const start_src = block.src(.{ .node_offset_slice_start = inst_data.src_node }); const end_src = block.src(.{ .node_offset_slice_end = inst_data.src_node }); @@ -9861,10 +9860,10 @@ fn zirSliceLength(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.SliceLength, inst_data.payload_index).data; - const array_ptr = try sema.resolveInst(extra.lhs); - const start = try sema.resolveInst(extra.start); - const len = try sema.resolveInst(extra.len); - const sentinel = if (extra.sentinel == .none) .none else try sema.resolveInst(extra.sentinel); + const array_ptr = sema.resolveInst(extra.lhs); + const start = sema.resolveInst(extra.start); + const len = sema.resolveInst(extra.len); + const sentinel = if (extra.sentinel == .none) .none else sema.resolveInst(extra.sentinel); const ptr_src = block.src(.{ .node_offset_slice_ptr = inst_data.src_node }); const start_src = block.src(.{ .node_offset_slice_start = extra.start_src_node_offset }); const end_src = block.src(.{ .node_offset_slice_end = inst_data.src_node }); @@ -9892,7 +9891,7 @@ fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE // This is like the logic in `analyzeSlice`; since we've evaluated the LHS as an lvalue, we will // have a double pointer if it was already a pointer. - const lhs_ptr_ty = sema.typeOf(try sema.resolveInst(inst_data.operand)); + const lhs_ptr_ty = sema.typeOf(sema.resolveInst(inst_data.operand)); const lhs_ty = switch (lhs_ptr_ty.zigTypeTag(zcu)) { .pointer => lhs_ptr_ty.childType(zcu), else => return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{lhs_ptr_ty.fmt(pt)}), @@ -9972,7 +9971,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp // Lastly, we analyze the error prong(s) as a regular switch. const raw_switch_operand, const non_err_cond, const non_err_hint = non_err: { - const eu_maybe_ptr = try sema.resolveInst(zir_switch.main_operand); + const eu_maybe_ptr = sema.resolveInst(zir_switch.main_operand); const err_union_ty: Type = err_union_ty: { const raw_operand_ty = sema.typeOf(eu_maybe_ptr); if (!non_err_case.operand_is_ref) break :err_union_ty raw_operand_ty; @@ -10106,7 +10105,7 @@ fn zirSwitchBlock( defer child_block.instructions.deinit(sema.gpa); defer merges.deinit(sema.gpa); - const raw_operand = try sema.resolveInst(zir_switch.main_operand); + const raw_operand = sema.resolveInst(zir_switch.main_operand); const validated_switch = try sema.validateSwitchBlock(block, raw_operand, operand_is_ref, inst, &zir_switch); const maybe_ref = try sema.analyzeSwitchBlock(block, &child_block, raw_operand, operand_is_ref, merges, inst, &zir_switch, &validated_switch); return maybe_ref orelse { @@ -10234,7 +10233,7 @@ fn analyzeSwitchBlock( if (extra.block_inst != switch_inst) return error.ComptimeBreak; // This is a `switch_continue` targeting this block. Change the operand and start over. const new_operand_src = child_block.nodeOffset(extra.operand_src_node.unwrap().?); - const new_operand_uncoerced = try sema.resolveInst(break_inst.data.@"break".operand); + const new_operand_uncoerced = sema.resolveInst(break_inst.data.@"break".operand); const new_operand = try sema.coerce(child_block, raw_operand_ty, new_operand_uncoerced, new_operand_src); try sema.emitBackwardBranch(child_block, src); @@ -12641,7 +12640,7 @@ fn resolveSwitchItem( // We allow prongs with errors which are not part of the error set // being switched on if their prong body is `=> comptime unreachable,`. switch (try sema.coerceInMemoryAllowedErrorSets(block, item_ty, uncoerced_ty, item_src, item_src)) { - .ok => if (try sema.resolveValue(uncoerced)) |uncoerced_val| { + .ok => if (sema.resolveValue(uncoerced)) |uncoerced_val| { break :item_ref try sema.coerceInMemory(uncoerced_val, item_ty); }, .missing_error => if (prong_is_comptime_unreach) { @@ -12805,7 +12804,7 @@ fn maybeErrorUnwrap( }, .panic => { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const msg_inst = try sema.resolveInst(inst_data.operand); + const msg_inst = sema.resolveInst(inst_data.operand); const panic_fn = try getBuiltin(sema, operand_src, .@"panic.call"); const args: [2]Air.Inst.Ref = .{ msg_inst, .null_value }; @@ -12828,7 +12827,7 @@ fn maybeErrorUnwrapCondbr(sema: *Sema, block: *Block, body: []const Zir.Inst.Ind if (sema.code.instructions.items(.tag)[@intFromEnum(index)] != .is_non_err) return; const err_inst_data = sema.code.instructions.items(.data)[@intFromEnum(index)].un_node; - const err_operand = try sema.resolveInst(err_inst_data.operand); + const err_operand = sema.resolveInst(err_inst_data.operand); const operand_ty = sema.typeOf(err_operand); if (operand_ty.zigTypeTag(zcu) == .error_set) { try sema.maybeErrorUnwrapComptime(block, body, err_operand); @@ -12960,7 +12959,7 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. .zon => { const res_ty: InternPool.Index = b: { if (extra.res_ty == .none) break :b .none; - const res_ty_inst = try sema.resolveInst(extra.res_ty); + const res_ty_inst = sema.resolveInst(extra.res_ty); const res_ty = try sema.analyzeAsType(block, operand_src, .type, res_ty_inst); if (res_ty.isGenericPoison()) break :b .none; break :b res_ty.toIntern(); @@ -13048,8 +13047,8 @@ fn zirShl( const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const lhs = try sema.resolveInst(extra.lhs); - const rhs = try sema.resolveInst(extra.rhs); + const lhs = sema.resolveInst(extra.lhs); + const rhs = sema.resolveInst(extra.rhs); const lhs_ty = sema.typeOf(lhs); const rhs_ty = sema.typeOf(rhs); @@ -13075,8 +13074,8 @@ fn zirShl( // we already know `scalar_rhs_ty` is valid for `.shl` -- we only need to validate for `.shl_sat`. if (air_tag == .shl_sat) _ = try sema.checkIntType(block, rhs_src, scalar_rhs_ty); - const maybe_lhs_val = try sema.resolveValue(lhs); - const maybe_rhs_val = try sema.resolveValue(rhs); + const maybe_lhs_val = sema.resolveValue(lhs); + const maybe_rhs_val = sema.resolveValue(rhs); const runtime_src = rs: { if (maybe_rhs_val) |rhs_val| { @@ -13238,8 +13237,8 @@ fn zirShr( const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const lhs = try sema.resolveInst(extra.lhs); - const rhs = try sema.resolveInst(extra.rhs); + const lhs = sema.resolveInst(extra.lhs); + const rhs = sema.resolveInst(extra.rhs); const lhs_ty = sema.typeOf(lhs); const rhs_ty = sema.typeOf(rhs); @@ -13258,8 +13257,8 @@ fn zirShr( try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); const scalar_ty = lhs_ty.scalarType(zcu); - const maybe_lhs_val = try sema.resolveValue(lhs); - const maybe_rhs_val = try sema.resolveValue(rhs); + const maybe_lhs_val = sema.resolveValue(lhs); + const maybe_rhs_val = sema.resolveValue(rhs); const runtime_src = rs: { if (maybe_rhs_val) |rhs_val| { @@ -13371,8 +13370,8 @@ fn zirBitwise( const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const lhs = try sema.resolveInst(extra.lhs); - const rhs = try sema.resolveInst(extra.rhs); + const lhs = sema.resolveInst(extra.lhs); + const rhs = sema.resolveInst(extra.rhs); const lhs_ty = sema.typeOf(lhs); const rhs_ty = sema.typeOf(rhs); try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); @@ -13394,8 +13393,8 @@ fn zirBitwise( const runtime_src = runtime: { // TODO: ask the linker what kind of relocations are available, and // in some cases emit a Value that means "this decl's address AND'd with this operand". - if (try sema.resolveValue(casted_lhs)) |lhs_val| { - if (try sema.resolveValue(casted_rhs)) |rhs_val| { + if (sema.resolveValue(casted_lhs)) |lhs_val| { + if (sema.resolveValue(casted_rhs)) |rhs_val| { const result_val = switch (air_tag) { // zig fmt: off .bit_and => try arith.bitwiseBin(sema, resolved_type, lhs_val, rhs_val, .@"and"), @@ -13423,7 +13422,7 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand_src = block.src(.{ .node_offset_un_op = inst_data.src_node }); const src = block.nodeOffset(inst_data.src_node); - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); const scalar_ty = operand_ty.scalarType(zcu); const scalar_tag = scalar_ty.zigTypeTag(zcu); @@ -13441,7 +13440,7 @@ fn analyzeBitNot( src: LazySrcLoc, ) CompileError!Air.Inst.Ref { const operand_ty = sema.typeOf(operand); - if (try sema.resolveValue(operand)) |operand_val| { + if (sema.resolveValue(operand)) |operand_val| { const result_val = try arith.bitwiseNot(sema, operand_ty, operand_val); return Air.internedToRef(result_val.toIntern()); } @@ -13551,8 +13550,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const lhs = try sema.resolveInst(extra.lhs); - const rhs = try sema.resolveInst(extra.rhs); + const lhs = sema.resolveInst(extra.lhs); + const rhs = sema.resolveInst(extra.rhs); const lhs_ty = sema.typeOf(lhs); const rhs_ty = sema.typeOf(rhs); const src = block.nodeOffset(inst_data.src_node); @@ -13646,12 +13645,12 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai }; const runtime_src = if (switch (lhs_ty.zigTypeTag(zcu)) { - .array, .@"struct" => try sema.resolveValue(lhs), + .array, .@"struct" => sema.resolveValue(lhs), .pointer => try sema.resolveDefinedValue(block, lhs_src, lhs), else => unreachable, }) |lhs_val| rs: { if (switch (rhs_ty.zigTypeTag(zcu)) { - .array, .@"struct" => try sema.resolveValue(rhs), + .array, .@"struct" => sema.resolveValue(rhs), .pointer => try sema.resolveDefinedValue(block, rhs_src, rhs), else => unreachable, }) |rhs_val| { @@ -13989,7 +13988,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.ArrayMul, inst_data.payload_index).data; - const uncoerced_lhs = try sema.resolveInst(extra.lhs); + const uncoerced_lhs = sema.resolveInst(extra.lhs); const uncoerced_lhs_ty = sema.typeOf(uncoerced_lhs); const src: LazySrcLoc = block.nodeOffset(inst_data.src_node); const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); @@ -14068,7 +14067,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const ptr_addrspace = if (lhs_ty.zigTypeTag(zcu) == .pointer) lhs_ty.ptrAddressSpace(zcu) else null; const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len); - if (try sema.resolveValue(lhs)) |lhs_val| ct: { + if (sema.resolveValue(lhs)) |lhs_val| ct: { const lhs_sub_val = if (lhs_ty.isSinglePointer(zcu)) try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty) orelse break :ct else if (lhs_ty.isSlice(zcu)) @@ -14157,7 +14156,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. const lhs_src = src; const rhs_src = block.src(.{ .node_offset_un_op = inst_data.src_node }); - const rhs = try sema.resolveInst(inst_data.operand); + const rhs = sema.resolveInst(inst_data.operand); const rhs_ty = sema.typeOf(rhs); const rhs_scalar_ty = rhs_ty.scalarType(zcu); @@ -14170,7 +14169,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. if (rhs_scalar_ty.isAnyFloat()) { // We handle float negation here to ensure negative zero is represented in the bits. - if (try sema.resolveValue(rhs)) |rhs_val| { + if (sema.resolveValue(rhs)) |rhs_val| { const result = try arith.negateFloat(sema, rhs_ty, rhs_val); return Air.internedToRef(result.toIntern()); } @@ -14190,7 +14189,7 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const lhs_src = src; const rhs_src = block.src(.{ .node_offset_un_op = inst_data.src_node }); - const rhs = try sema.resolveInst(inst_data.operand); + const rhs = sema.resolveInst(inst_data.operand); const rhs_ty = sema.typeOf(rhs); const rhs_scalar_ty = rhs_ty.scalarType(zcu); @@ -14218,8 +14217,8 @@ fn zirArithmetic( const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const lhs = try sema.resolveInst(extra.lhs); - const rhs = try sema.resolveInst(extra.rhs); + const lhs = sema.resolveInst(extra.lhs); + const rhs = sema.resolveInst(extra.rhs); return sema.analyzeArithmetic(block, zir_tag, lhs, rhs, src, lhs_src, rhs_src, safety); } @@ -14232,8 +14231,8 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const lhs = try sema.resolveInst(extra.lhs); - const rhs = try sema.resolveInst(extra.rhs); + const lhs = sema.resolveInst(extra.lhs); + const rhs = sema.resolveInst(extra.rhs); const lhs_ty = sema.typeOf(lhs); const rhs_ty = sema.typeOf(rhs); const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu); @@ -14255,8 +14254,8 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div); - const maybe_lhs_val = try sema.resolveValue(casted_lhs); - const maybe_rhs_val = try sema.resolveValue(casted_rhs); + const maybe_lhs_val = sema.resolveValue(casted_lhs); + const maybe_rhs_val = sema.resolveValue(casted_rhs); if ((lhs_ty.zigTypeTag(zcu) == .comptime_float and rhs_ty.zigTypeTag(zcu) == .comptime_int) or (lhs_ty.zigTypeTag(zcu) == .comptime_int and rhs_ty.zigTypeTag(zcu) == .comptime_float)) @@ -14341,8 +14340,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0); const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const lhs = try sema.resolveInst(extra.lhs); - const rhs = try sema.resolveInst(extra.rhs); + const lhs = sema.resolveInst(extra.lhs); + const rhs = sema.resolveInst(extra.rhs); const lhs_ty = sema.typeOf(lhs); const rhs_ty = sema.typeOf(rhs); const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu); @@ -14364,8 +14363,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_exact); - const maybe_lhs_val = try sema.resolveValue(casted_lhs); - const maybe_rhs_val = try sema.resolveValue(casted_rhs); + const maybe_lhs_val = sema.resolveValue(casted_lhs); + const maybe_rhs_val = sema.resolveValue(casted_rhs); // Because `@divExact` can trigger Illegal Behavior, undefined operands trigger Illegal Behavior. @@ -14437,8 +14436,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0); const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const lhs = try sema.resolveInst(extra.lhs); - const rhs = try sema.resolveInst(extra.rhs); + const lhs = sema.resolveInst(extra.lhs); + const rhs = sema.resolveInst(extra.rhs); const lhs_ty = sema.typeOf(lhs); const rhs_ty = sema.typeOf(rhs); const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu); @@ -14460,8 +14459,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_floor); - const maybe_lhs_val = try sema.resolveValue(casted_lhs); - const maybe_rhs_val = try sema.resolveValue(casted_rhs); + const maybe_lhs_val = sema.resolveValue(casted_lhs); + const maybe_rhs_val = sema.resolveValue(casted_rhs); const allow_div_zero = !is_int and resolved_type.toIntern() != .comptime_float_type and @@ -14502,8 +14501,8 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0); const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const lhs = try sema.resolveInst(extra.lhs); - const rhs = try sema.resolveInst(extra.rhs); + const lhs = sema.resolveInst(extra.lhs); + const rhs = sema.resolveInst(extra.rhs); const lhs_ty = sema.typeOf(lhs); const rhs_ty = sema.typeOf(rhs); const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu); @@ -14525,8 +14524,8 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_trunc); - const maybe_lhs_val = try sema.resolveValue(casted_lhs); - const maybe_rhs_val = try sema.resolveValue(casted_rhs); + const maybe_lhs_val = sema.resolveValue(casted_lhs); + const maybe_rhs_val = sema.resolveValue(casted_rhs); const allow_div_zero = !is_int and resolved_type.toIntern() != .comptime_float_type and @@ -14713,8 +14712,8 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const lhs = try sema.resolveInst(extra.lhs); - const rhs = try sema.resolveInst(extra.rhs); + const lhs = sema.resolveInst(extra.lhs); + const rhs = sema.resolveInst(extra.rhs); const lhs_ty = sema.typeOf(lhs); const rhs_ty = sema.typeOf(rhs); const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu); @@ -14737,8 +14736,8 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .mod_rem); - const maybe_lhs_val = try sema.resolveValue(casted_lhs); - const maybe_rhs_val = try sema.resolveValue(casted_rhs); + const maybe_lhs_val = sema.resolveValue(casted_lhs); + const maybe_rhs_val = sema.resolveValue(casted_rhs); const lhs_maybe_negative = a: { if (lhs_scalar_ty.isUnsignedInt(zcu)) break :a false; @@ -14814,8 +14813,8 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0); const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const lhs = try sema.resolveInst(extra.lhs); - const rhs = try sema.resolveInst(extra.rhs); + const lhs = sema.resolveInst(extra.lhs); + const rhs = sema.resolveInst(extra.rhs); const lhs_ty = sema.typeOf(lhs); const rhs_ty = sema.typeOf(rhs); const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu); @@ -14836,8 +14835,8 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .mod); - const maybe_lhs_val = try sema.resolveValue(casted_lhs); - const maybe_rhs_val = try sema.resolveValue(casted_rhs); + const maybe_lhs_val = sema.resolveValue(casted_lhs); + const maybe_rhs_val = sema.resolveValue(casted_rhs); const allow_div_zero = !is_int and resolved_type.toIntern() != .comptime_float_type and @@ -14878,8 +14877,8 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0); const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; - const lhs = try sema.resolveInst(extra.lhs); - const rhs = try sema.resolveInst(extra.rhs); + const lhs = sema.resolveInst(extra.lhs); + const rhs = sema.resolveInst(extra.rhs); const lhs_ty = sema.typeOf(lhs); const rhs_ty = sema.typeOf(rhs); const lhs_zig_ty_tag = lhs_ty.zigTypeTag(zcu); @@ -14900,8 +14899,8 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .rem); - const maybe_lhs_val = try sema.resolveValue(casted_lhs); - const maybe_rhs_val = try sema.resolveValue(casted_rhs); + const maybe_lhs_val = sema.resolveValue(casted_lhs); + const maybe_rhs_val = sema.resolveValue(casted_rhs); const allow_div_zero = !is_int and resolved_type.toIntern() != .comptime_float_type and @@ -14949,8 +14948,8 @@ fn zirOverflowArithmetic( const lhs_src = block.builtinCallArgSrc(extra.node, 0); const rhs_src = block.builtinCallArgSrc(extra.node, 1); - const uncasted_lhs = try sema.resolveInst(extra.lhs); - const uncasted_rhs = try sema.resolveInst(extra.rhs); + const uncasted_lhs = sema.resolveInst(extra.lhs); + const uncasted_rhs = sema.resolveInst(extra.rhs); const lhs_ty = sema.typeOf(uncasted_lhs); const rhs_ty = sema.typeOf(uncasted_rhs); @@ -14980,8 +14979,8 @@ fn zirOverflowArithmetic( return sema.fail(block, src, "expected vector of integers or integer tag type, found '{f}'", .{dest_ty.fmt(pt)}); } - const maybe_lhs_val = try sema.resolveValue(lhs); - const maybe_rhs_val = try sema.resolveValue(rhs); + const maybe_lhs_val = sema.resolveValue(lhs); + const maybe_rhs_val = sema.resolveValue(rhs); const tuple_ty = try pt.overflowArithmeticTupleType(dest_ty); const overflow_ty: Type = .fromInterned(ip.indexToKey(tuple_ty.toIntern()).tuple_type.types.get(ip)[1]); @@ -15163,7 +15162,7 @@ fn zirOverflowArithmetic( }; if (result.inst != .none) { - if (try sema.resolveValue(result.inst)) |some| { + if (sema.resolveValue(result.inst)) |some| { result.wrapped = some; result.inst = .none; } @@ -15227,8 +15226,8 @@ fn analyzeArithmetic( } const runtime_src = runtime_src: { - if (try sema.resolveValue(lhs)) |lhs_value| { - if (try sema.resolveValue(rhs)) |rhs_value| { + if (sema.resolveValue(lhs)) |lhs_value| { + if (sema.resolveValue(rhs)) |rhs_value| { const lhs_ptr = switch (zcu.intern_pool.indexToKey(lhs_value.toIntern())) { .undef => return sema.failWithUseOfUndef(block, lhs_src, null), .ptr => |ptr| ptr, @@ -15307,8 +15306,8 @@ fn analyzeArithmetic( else => unreachable, }; - const maybe_lhs_val = try sema.resolveValue(casted_lhs); - const maybe_rhs_val = try sema.resolveValue(casted_rhs); + const maybe_lhs_val = sema.resolveValue(casted_lhs); + const maybe_rhs_val = sema.resolveValue(casted_rhs); if (maybe_lhs_val) |lhs_val| { if (maybe_rhs_val) |rhs_val| { @@ -15380,7 +15379,7 @@ fn analyzePtrArithmetic( const offset = try sema.coerce(block, .usize, uncasted_offset, offset_src); const pt = sema.pt; const zcu = pt.zcu; - const opt_ptr_val = try sema.resolveValue(ptr); + const opt_ptr_val = sema.resolveValue(ptr); const opt_off_val = try sema.resolveDefinedValue(block, offset_src, offset); const ptr_ty = sema.typeOf(ptr); const ptr_info = ptr_ty.ptrInfo(zcu); @@ -15473,7 +15472,7 @@ fn zirLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.In const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const ptr_src = src; // TODO better source location - const ptr = try sema.resolveInst(inst_data.operand); + const ptr = sema.resolveInst(inst_data.operand); return sema.analyzeLoad(block, src, ptr, ptr_src); } @@ -15547,7 +15546,7 @@ fn zirAsm( const out_ty = try sema.resolveType(block, ret_ty_src, output.data.operand); expr_ty = Air.internedToRef(out_ty.toIntern()); } else { - const inst = try sema.resolveInst(output.data.operand); + const inst = sema.resolveInst(output.data.operand); if (!sema.checkRuntimeValue(inst)) { const output_name = try ip.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls); return sema.failWithContainsReferenceToComptimeVar(block, output_src, output_name, "assembly output", .fromInterned(inst.toInterned().?)); @@ -15577,7 +15576,7 @@ fn zirAsm( } }); extra_i = input.end; - const uncasted_arg = try sema.resolveInst(input.data.operand); + const uncasted_arg = sema.resolveInst(input.data.operand); const name = sema.code.nullTerminatedString(input.data.name); if (!sema.checkRuntimeValue(uncasted_arg)) { const input_name = try ip.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls); @@ -15600,7 +15599,7 @@ fn zirAsm( const clobbers = if (extra.data.clobbers == .none) empty: { const clobbers_ty = try sema.getBuiltinType(src, .@"assembly.Clobbers"); break :empty try sema.structInitEmpty(block, clobbers_ty, src, src); - } else try sema.resolveInst(extra.data.clobbers); // Already coerced by AstGen. + } else sema.resolveInst(extra.data.clobbers); // Already coerced by AstGen. const clobbers_val = try sema.resolveConstDefinedValue(block, src, clobbers, .{ .simple = .clobber }); needed_capacity += asm_source.len / 4 + 1; @@ -15666,8 +15665,8 @@ fn zirCmpEq( const src: LazySrcLoc = block.nodeOffset(inst_data.src_node); const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); - const lhs = try sema.resolveInst(extra.lhs); - const rhs = try sema.resolveInst(extra.rhs); + const lhs = sema.resolveInst(extra.lhs); + const rhs = sema.resolveInst(extra.rhs); const lhs_ty = sema.typeOf(lhs); const rhs_ty = sema.typeOf(rhs); @@ -15700,8 +15699,8 @@ fn zirCmpEq( if (lhs_ty_tag == .error_set and rhs_ty_tag == .error_set) { const runtime_src: LazySrcLoc = src: { - if (try sema.resolveValue(lhs)) |lval| { - if (try sema.resolveValue(rhs)) |rval| { + if (sema.resolveValue(lhs)) |lval| { + if (sema.resolveValue(rhs)) |rval| { if (lval.isUndef(zcu) or rval.isUndef(zcu)) return .undef_bool; const lkey = zcu.intern_pool.indexToKey(lval.toIntern()); const rkey = zcu.intern_pool.indexToKey(rval.toIntern()); @@ -15754,7 +15753,7 @@ fn analyzeCmpUnionTag( const coerced_tag = try sema.coerce(block, union_tag_ty, tag, tag_src); const coerced_union = try sema.coerce(block, union_tag_ty, un, un_src); - if (try sema.resolveValue(coerced_tag)) |enum_val| { + if (sema.resolveValue(coerced_tag)) |enum_val| { if (enum_val.isUndef(zcu)) return .undef_bool; const field_ty = union_ty.unionFieldType(enum_val, zcu).?; if (field_ty.zigTypeTag(zcu) == .noreturn) { @@ -15780,8 +15779,8 @@ fn zirCmp( const src: LazySrcLoc = block.nodeOffset(inst_data.src_node); const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); - const lhs = try sema.resolveInst(extra.lhs); - const rhs = try sema.resolveInst(extra.rhs); + const lhs = sema.resolveInst(extra.lhs); + const rhs = sema.resolveInst(extra.rhs); return sema.analyzeCmp(block, src, lhs, rhs, op, lhs_src, rhs_src, false); } @@ -15864,8 +15863,8 @@ fn cmpSelf( const zcu = pt.zcu; const resolved_type = sema.typeOf(casted_lhs); - const maybe_lhs_val = try sema.resolveValue(casted_lhs); - const maybe_rhs_val = try sema.resolveValue(casted_rhs); + const maybe_lhs_val = sema.resolveValue(casted_lhs); + const maybe_rhs_val = sema.resolveValue(casted_rhs); if (maybe_lhs_val) |v| if (v.isUndef(zcu)) return .undef_bool; if (maybe_rhs_val) |v| if (v.isUndef(zcu)) return .undef_bool; @@ -17118,7 +17117,7 @@ fn zirTypeof(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. _ = block; const zir_datas = sema.code.instructions.items(.data); const inst_data = zir_datas[@intFromEnum(inst)].un_node; - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); return Air.internedToRef(operand_ty.toIntern()); } @@ -17150,7 +17149,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr fn zirTypeofLog2IntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); const res_ty = try sema.log2IntType(block, operand_ty, src); return Air.internedToRef(res_ty.toIntern()); @@ -17220,7 +17219,7 @@ fn zirTypeofPeer( defer sema.gpa.free(inst_list); for (args, 0..) |arg_ref, i| { - inst_list[i] = try sema.resolveInst(arg_ref); + inst_list[i] = sema.resolveInst(arg_ref); } const result_type = try sema.resolvePeerTypes(block, src, inst_list, .{ .typeof_builtin_call_node_offset = extra.data.src_node }); @@ -17233,7 +17232,7 @@ fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const operand_src = block.src(.{ .node_offset_un_op = inst_data.src_node }); - const uncasted_operand = try sema.resolveInst(inst_data.operand); + const uncasted_operand = sema.resolveInst(inst_data.operand); const uncasted_ty = sema.typeOf(uncasted_operand); if (uncasted_ty.isVector(zcu)) { if (uncasted_ty.scalarType(zcu).zigTypeTag(zcu) != .bool) { @@ -17244,7 +17243,7 @@ fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air return analyzeBitNot(sema, block, uncasted_operand, src); } const operand = try sema.coerce(block, .bool, uncasted_operand, operand_src); - if (try sema.resolveValue(operand)) |val| { + if (sema.resolveValue(operand)) |val| { return if (val.isUndef(zcu)) .undef_bool else if (val.toBool()) .bool_false else .bool_true; } try sema.requireRuntimeBlock(block, src, null); @@ -17268,7 +17267,7 @@ fn zirBoolBr( const inst_data = datas[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.BoolBr, inst_data.payload_index); - const uncoerced_lhs = try sema.resolveInst(extra.data.lhs); + const uncoerced_lhs = sema.resolveInst(extra.data.lhs); const body = sema.code.bodySlice(extra.end, extra.data.body_len); const lhs_src = parent_block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); const rhs_src = parent_block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); @@ -17431,7 +17430,7 @@ fn zirIsNonNull( const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); try sema.checkNullableType(block, src, sema.typeOf(operand)); return sema.analyzeIsNull(block, operand, true); } @@ -17448,12 +17447,12 @@ fn zirIsNonNullPtr( const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const ptr = try sema.resolveInst(inst_data.operand); + const ptr = sema.resolveInst(inst_data.operand); const ptr_ty = sema.typeOf(ptr); assert(ptr_ty.zigTypeTag(zcu) == .pointer); const nullable_ty = ptr_ty.childType(zcu); try sema.checkNullableType(block, src, nullable_ty); - if (try sema.resolveValue(ptr)) |ptr_val| { + if (sema.resolveValue(ptr)) |ptr_val| { if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |nullable_val| { return sema.analyzeIsNull(block, .fromValue(nullable_val), true); } @@ -17481,7 +17480,7 @@ fn zirIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); try sema.checkErrorType(block, src, sema.typeOf(operand)); return sema.analyzeIsNonErr(block, src, operand); } @@ -17494,7 +17493,7 @@ fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const ptr = try sema.resolveInst(inst_data.operand); + const ptr = sema.resolveInst(inst_data.operand); const ptr_ty = sema.typeOf(ptr); assert(ptr_ty.zigTypeTag(zcu) == .pointer); const error_ty = ptr_ty.childType(zcu); @@ -17509,7 +17508,7 @@ fn zirRetIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); return sema.analyzeIsNonErr(block, src, operand); } @@ -17530,7 +17529,7 @@ fn zirCondbr( const then_body = sema.code.bodySlice(extra.end, extra.data.then_body_len); const else_body = sema.code.bodySlice(extra.end + then_body.len, extra.data.else_body_len); - const uncasted_cond = try sema.resolveInst(extra.data.condition); + const uncasted_cond = sema.resolveInst(extra.data.condition); const cond = try sema.coerce(parent_block, .bool, uncasted_cond, cond_src); if (try sema.resolveDefinedValue(parent_block, cond_src, cond)) |cond_val| { @@ -17566,7 +17565,7 @@ fn zirCondbr( if (sema.code.instructions.items(.tag)[@intFromEnum(index)] != .is_non_err) break :blk null; const err_inst_data = sema.code.instructions.items(.data)[@intFromEnum(index)].un_node; - const err_operand = try sema.resolveInst(err_inst_data.operand); + const err_operand = sema.resolveInst(err_inst_data.operand); const operand_ty = sema.typeOf(err_operand); assert(operand_ty.zigTypeTag(zcu) == .error_union); const result_ty = operand_ty.errorUnionSet(zcu); @@ -17614,7 +17613,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError! const operand_src = parent_block.src(.{ .node_offset_try_operand = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); const body = sema.code.bodySlice(extra.end, extra.data.body_len); - const err_union = try sema.resolveInst(extra.data.operand); + const err_union = sema.resolveInst(extra.data.operand); const err_union_ty = sema.typeOf(err_union); const pt = sema.pt; const zcu = pt.zcu; @@ -17681,7 +17680,7 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr const operand_src = parent_block.src(.{ .node_offset_try_operand = inst_data.src_node }); const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); const body = sema.code.bodySlice(extra.end, extra.data.body_len); - const operand = try sema.resolveInst(extra.data.operand); + const operand = sema.resolveInst(extra.data.operand); const err_union = try sema.analyzeLoad(parent_block, src, operand, operand_src); const err_union_ty = sema.typeOf(err_union); const pt = sema.pt; @@ -17802,7 +17801,7 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label fn addRuntimeBreak(sema: *Sema, child_block: *Block, block_inst: Zir.Inst.Index, break_operand: Zir.Inst.Ref) !void { const labeled_block = try sema.ensurePostHoc(child_block, block_inst); - const operand = try sema.resolveInst(break_operand); + const operand = sema.resolveInst(break_operand); const br_ref = try child_block.addBr(labeled_block.label.merges.block_inst, operand); try labeled_block.label.merges.results.append(sema.gpa, operand); @@ -17888,7 +17887,7 @@ fn zirRetImplicit( return; } - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = .zero }); const base_tag = sema.fn_ret_ty.optEuBaseType(zcu).zigTypeTag(zcu); if (base_tag == .noreturn) { @@ -17921,7 +17920,7 @@ fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi defer tracy.end(); const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const src = block.nodeOffset(inst_data.src_node); return sema.analyzeRet(block, operand, src, block.src(.{ .node_offset_return_operand = inst_data.src_node })); @@ -17933,7 +17932,7 @@ fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const ret_ptr = try sema.resolveInst(inst_data.operand); + const ret_ptr = sema.resolveInst(inst_data.operand); if (block.isComptime() or block.inlining != null or sema.func_is_naked) { const operand = try sema.analyzeLoad(block, src, ret_ptr, src); @@ -18030,7 +18029,7 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE if (block.isComptime() or block.is_typeof) return; const save_index = inst_data.operand == .none or b: { - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); break :b operand_ty.isError(zcu); }; @@ -18079,7 +18078,7 @@ fn restoreErrRetIndex(sema: *Sema, start_block: *Block, src: LazySrcLoc, target_ return; // No need to restore }; - const operand = try sema.resolveInstAllowNone(operand_zir); + const operand = sema.resolveInstAllowNone(operand_zir); if (start_block.isComptime() or start_block.is_typeof) { const is_non_error = if (operand != .none) blk: { @@ -18229,7 +18228,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const hostsize_src = block.src(.{ .node_offset_ptr_hostsize = extra.data.src_node }); const elem_ty = blk: { - const air_inst = try sema.resolveInst(extra.data.elem_type); + const air_inst = sema.resolveInst(extra.data.elem_type); const ty = sema.analyzeAsType(block, elem_ty_src, .type, air_inst) catch |err| { if (err == error.AnalysisFail and sema.err != null and sema.typeOf(air_inst).isSinglePointer(zcu)) { try sema.errNote(elem_ty_src, sema.err.?, "use '.*' to dereference pointer", .{}); @@ -18250,7 +18249,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const sentinel = if (inst_data.flags.has_sentinel) blk: { const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]); extra_i += 1; - const coerced = try sema.coerce(block, elem_ty, try sema.resolveInst(ref), sentinel_src); + const coerced = try sema.coerce(block, elem_ty, sema.resolveInst(ref), sentinel_src); const val = try sema.resolveConstDefinedValue(block, sentinel_src, coerced, .{ .simple = .pointer_sentinel }); try checkSentinelType(sema, block, sentinel_src, elem_ty); if (val.canMutateComptimeVarState(zcu)) { @@ -18263,7 +18262,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const abi_align: Alignment = if (inst_data.flags.has_align) blk: { const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]); extra_i += 1; - const coerced = try sema.coerce(block, align_ty, try sema.resolveInst(ref), align_src); + const coerced = try sema.coerce(block, align_ty, sema.resolveInst(ref), align_src); const val = try sema.resolveConstDefinedValue(block, align_src, coerced, .{ .simple = .@"align" }); const align_bytes = val.toUnsignedInt(zcu); break :blk try sema.validateAlign(block, align_src, align_bytes); @@ -18442,7 +18441,7 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is const init_ref = try sema.coerce(block, init_ty, empty_ref, src); if (is_byref) { - const init_val = (try sema.resolveValue(init_ref)).?; + const init_val = sema.resolveValue(init_ref).?; return sema.uavRef(init_val.toIntern()); } else { return init_ref; @@ -18508,9 +18507,9 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_src); const field_ty: Type = .fromInterned(zcu.typeToUnion(union_ty).?.field_types.get(ip)[field_index]); - const payload = try sema.coerce(block, field_ty, try sema.resolveInst(extra.init), payload_src); + const payload = try sema.coerce(block, field_ty, sema.resolveInst(extra.init), payload_src); - if (try sema.resolveValue(payload)) |payload_val| { + if (sema.resolveValue(payload)) |payload_val| { const tag_ty = union_ty.unionTagTypeHypothetical(zcu); const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index); return .fromValue(try pt.unionValue(union_ty, tag_val, payload_val)); @@ -18590,12 +18589,12 @@ fn zirStructInit( assert(field_inits[field_index] == .none); field_assign_idxs[field_index] = field_i; found_fields[field_index] = item.data.field_type; - const uncoerced_init = try sema.resolveInst(item.data.init); + const uncoerced_init = sema.resolveInst(item.data.init); const field_ty = resolved_ty.fieldType(field_index, zcu); field_inits[field_index] = try sema.coerce(block, field_ty, uncoerced_init, field_src); if (resolved_ty.structFieldIsComptime(field_index, zcu)) { const default_value = (try resolved_ty.structFieldValueComptime(pt, field_index)).?; - const init_val = (try sema.resolveValue(field_inits[field_index])) orelse { + const init_val = sema.resolveValue(field_inits[field_index]) orelse { return sema.failWithNeededComptime(block, field_src, .{ .simple = .stored_to_comptime_field }); }; if (!init_val.eql(default_value, resolved_ty.fieldType(field_index, zcu), zcu)) { @@ -18640,17 +18639,17 @@ fn zirStructInit( }); } - const uncoerced_init_inst = try sema.resolveInst(item.data.init); + const uncoerced_init_inst = sema.resolveInst(item.data.init); const init_inst = try sema.coerce(block, field_ty, uncoerced_init_inst, field_src); - if (try sema.resolveValue(init_inst)) |val| { + if (sema.resolveValue(init_inst)) |val| { const struct_val = Value.fromInterned(try pt.internUnion(.{ .ty = resolved_ty.toIntern(), .tag = tag_val.toIntern(), .val = val.toIntern(), })); const final_val_inst = try sema.coerce(block, result_ty, Air.internedToRef(struct_val.toIntern()), src); - const final_val = (try sema.resolveValue(final_val_inst)).?; + const final_val = sema.resolveValue(final_val_inst).?; return sema.addConstantMaybeRef(final_val.toIntern(), is_ref); } @@ -18792,11 +18791,11 @@ fn finishStructInit( const runtime_index = opt_runtime_index orelse { const elems = try sema.arena.alloc(InternPool.Index, field_inits.len); for (elems, field_inits) |*elem, field_init| { - elem.* = (sema.resolveValue(field_init) catch unreachable).?.toIntern(); + elem.* = sema.resolveValue(field_init).?.toIntern(); } const struct_val = try pt.aggregateValue(struct_ty, elems); const final_val_inst = try sema.coerce(block, result_ty, Air.internedToRef(struct_val.toIntern()), init_src); - const final_val = (try sema.resolveValue(final_val_inst)).?; + const final_val = sema.resolveValue(final_val_inst).?; return sema.addConstantMaybeRef(final_val.toIntern(), is_ref); }; @@ -18903,7 +18902,7 @@ fn structInitAnon( field_name.* = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls); - const init = try sema.resolveInst(item.data.init); + const init = sema.resolveInst(item.data.init); field_ty.* = sema.typeOf(init).toIntern(); if (Type.fromInterned(field_ty.*).zigTypeTag(zcu) == .@"opaque") { const msg = msg: { @@ -18919,7 +18918,7 @@ fn structInitAnon( }; return sema.failWithOwnedErrorMsg(block, msg); } - if (try sema.resolveValue(init)) |init_val| { + if (sema.resolveValue(init)) |init_val| { field_val.* = init_val.toIntern(); any_values = true; } else { @@ -19018,7 +19017,7 @@ fn structInitAnon( .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, }); if (values[i] == .none) { - const init = try sema.resolveInst(item.data.init); + const init = sema.resolveInst(item.data.init); const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty); _ = try block.addBinOp(.store, field_ptr, init); } @@ -19035,7 +19034,7 @@ fn structInitAnon( .typed_init => sema.code.extraData(Zir.Inst.StructInit.Item, extra_index), }; extra_index = item.end; - element_refs[i] = try sema.resolveInst(item.data.init); + element_refs[i] = sema.resolveInst(item.data.init); } return block.addAggregateInit(struct_ty, element_refs); @@ -19095,7 +19094,7 @@ fn zirArrayInit( }; const arg = args[i + 1]; - const resolved_arg = try sema.resolveInst(arg); + const resolved_arg = sema.resolveInst(arg); const elem_ty = if (is_tuple) array_ty.fieldType(i, zcu) else @@ -19126,11 +19125,11 @@ fn zirArrayInit( const elem_vals = try sema.arena.alloc(InternPool.Index, resolved_args.len); for (elem_vals, resolved_args) |*val, arg| { // We checked that all args are comptime above. - val.* = (sema.resolveValue(arg) catch unreachable).?.toIntern(); + val.* = sema.resolveValue(arg).?.toIntern(); } const arr_val = try pt.aggregateValue(array_ty, elem_vals); const result_ref = try sema.coerce(block, result_ty, Air.internedToRef(arr_val.toIntern()), src); - const result_val = (try sema.resolveValue(result_ref)).?; + const result_val = (sema.resolveValue(result_ref)).?; return sema.addConstantMaybeRef(result_val.toIntern(), is_ref); }; @@ -19213,7 +19212,7 @@ fn arrayInitAnon( .init_node_offset = src.offset.node_offset.x, .elem_index = @intCast(i), } }); - const elem = try sema.resolveInst(operand); + const elem = sema.resolveInst(operand); types[i] = sema.typeOf(elem).toIntern(); if (Type.fromInterned(types[i]).zigTypeTag(zcu) == .@"opaque") { const msg = msg: { @@ -19225,7 +19224,7 @@ fn arrayInitAnon( }; return sema.failWithOwnedErrorMsg(block, msg); } - if (try sema.resolveValue(elem)) |val| { + if (sema.resolveValue(elem)) |val| { values[i] = val.toIntern(); any_comptime = true; } else { @@ -19265,7 +19264,7 @@ fn arrayInitAnon( .init_node_offset = src.offset.node_offset.x, .elem_index = @intCast(i), } }); - try sema.validateRuntimeValue(block, operand_src, try sema.resolveInst(operand)); + try sema.validateRuntimeValue(block, operand_src, sema.resolveInst(operand)); } if (is_ref) { @@ -19283,7 +19282,7 @@ fn arrayInitAnon( }); if (values[i] == .none) { const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty); - _ = try block.addBinOp(.store, field_ptr, try sema.resolveInst(operand)); + _ = try block.addBinOp(.store, field_ptr, sema.resolveInst(operand)); } } @@ -19292,7 +19291,7 @@ fn arrayInitAnon( const element_refs = try sema.arena.alloc(Air.Inst.Ref, operands.len); for (operands, 0..) |operand, i| { - element_refs[i] = try sema.resolveInst(operand); + element_refs[i] = sema.resolveInst(operand); } return block.addAggregateInit(tuple_ty, element_refs); @@ -19441,7 +19440,7 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); const is_vector = operand_ty.zigTypeTag(zcu) == .vector; const operand_scalar_ty = operand_ty.scalarType(zcu); @@ -19450,7 +19449,7 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError } const len = if (is_vector) operand_ty.vectorLen(zcu) else undefined; const dest_ty: Type = if (is_vector) try pt.vectorType(.{ .child = .u1_type, .len = len }) else .u1; - if (try sema.resolveValue(operand)) |val| { + if (sema.resolveValue(operand)) |val| { if (!is_vector) { return if (val.isUndef(zcu)) .undef_u1 else if (val.toBool()) .one_u1 else .zero_u1; } @@ -19473,7 +19472,7 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); - const uncoerced_operand = try sema.resolveInst(inst_data.operand); + const uncoerced_operand = sema.resolveInst(inst_data.operand); const operand = try sema.coerce(block, .anyerror, uncoerced_operand, operand_src); if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| { @@ -19494,7 +19493,7 @@ fn zirAbs( const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const operand_ty = sema.typeOf(operand); const scalar_ty = operand_ty.scalarType(zcu); @@ -19525,7 +19524,7 @@ fn maybeConstantUnaryMath( const pt = sema.pt; const zcu = pt.zcu; switch (result_ty.zigTypeTag(zcu)) { - .vector => if (try sema.resolveValue(operand)) |val| { + .vector => if (sema.resolveValue(operand)) |val| { const scalar_ty = result_ty.scalarType(zcu); const vec_len = result_ty.vectorLen(zcu); if (val.isUndef(zcu)) @@ -19538,7 +19537,7 @@ fn maybeConstantUnaryMath( } return Air.internedToRef((try pt.aggregateValue(result_ty, elems)).toIntern()); }, - else => if (try sema.resolveValue(operand)) |operand_val| { + else => if (sema.resolveValue(operand)) |operand_val| { if (operand_val.isUndef(zcu)) return try pt.undefRef(result_ty); const result_val = try eval(operand_val, result_ty, sema.arena, pt); @@ -19561,7 +19560,7 @@ fn zirUnaryMath( const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const operand_ty = sema.typeOf(operand); const scalar_ty = operand_ty.scalarType(zcu); @@ -19586,7 +19585,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const src = block.nodeOffset(inst_data.src_node); - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); const pt = sema.pt; const zcu = pt.zcu; @@ -19678,7 +19677,7 @@ fn zirReifySliceArgTy( .flags = .{ .size = .slice, .is_const = true }, }); - const operand_uncoerced = try sema.resolveInst(extra.operand); + const operand_uncoerced = sema.resolveInst(extra.operand); const operand_coerced = try sema.coerce(block, operand_ty, operand_uncoerced, src); const operand_val = try sema.resolveConstDefinedValue(block, src, operand_coerced, .{ .simple = comptime_reason }); const len_val: Value = .fromInterned(zcu.intern_pool.indexToKey(operand_val.toIntern()).slice.len); @@ -19706,7 +19705,7 @@ fn zirReifyEnumValueSliceTy( const int_tag_ty = try sema.resolveType(block, int_tag_ty_src, extra.lhs); - const operand_uncoerced = try sema.resolveInst(extra.rhs); + const operand_uncoerced = sema.resolveInst(extra.rhs); const operand_coerced = try sema.coerce(block, .slice_const_slice_const_u8, operand_uncoerced, field_names_src); const operand_val = try sema.resolveConstDefinedValue(block, field_names_src, operand_coerced, .{ .simple = .enum_field_names }); const len_val: Value = .fromInterned(zcu.intern_pool.indexToKey(operand_val.toIntern()).slice.len); @@ -19751,7 +19750,7 @@ fn zirReifyTuple( const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; const operand_src = block.builtinCallArgSrc(extra.node, 0); - const types_uncoerced = try sema.resolveInst(extra.operand); + const types_uncoerced = sema.resolveInst(extra.operand); const types_coerced = try sema.coerce(block, .slice_const_type, types_uncoerced, operand_src); const types_slice_val = try sema.resolveConstDefinedValue(block, operand_src, types_coerced, .{ .simple = .tuple_field_types }); const types_array_val = try sema.derefSliceAsArray(block, operand_src, types_slice_val, .{ .simple = .tuple_field_types }); @@ -19798,12 +19797,12 @@ fn zirReifyPointer( const size_ty = try sema.getBuiltinType(size_src, .@"Type.Pointer.Size"); const attrs_ty = try sema.getBuiltinType(attrs_src, .@"Type.Pointer.Attributes"); - const size_uncoerced = try sema.resolveInst(extra.size); + const size_uncoerced = sema.resolveInst(extra.size); const size_coerced = try sema.coerce(block, size_ty, size_uncoerced, size_src); const size_val = try sema.resolveConstDefinedValue(block, size_src, size_coerced, .{ .simple = .pointer_size }); const size = try sema.interpretBuiltinType(block, size_src, size_val, std.builtin.Type.Pointer.Size); - const attrs_uncoerced = try sema.resolveInst(extra.attrs); + const attrs_uncoerced = sema.resolveInst(extra.attrs); const attrs_coerced = try sema.coerce(block, attrs_ty, attrs_uncoerced, attrs_src); const attrs_val = try sema.resolveConstDefinedValue(block, attrs_src, attrs_coerced, .{ .simple = .pointer_attrs }); const attrs = try sema.interpretBuiltinType(block, attrs_src, attrs_val, std.builtin.Type.Pointer.Attributes); @@ -19842,7 +19841,7 @@ fn zirReifyPointer( } const sentinel_ty = try pt.optionalType(elem_ty.toIntern()); - const sentinel_uncoerced = try sema.resolveInst(extra.sentinel); + const sentinel_uncoerced = sema.resolveInst(extra.sentinel); const sentinel_coerced = try sema.coerce(block, sentinel_ty, sentinel_uncoerced, sentinel_src); const sentinel_val = try sema.resolveConstDefinedValue(block, sentinel_src, sentinel_coerced, .{ .simple = .pointer_sentinel }); const opt_sentinel = sentinel_val.optionalValue(zcu); @@ -19896,7 +19895,7 @@ fn zirReifyFn( const single_param_attrs_ty = try sema.getBuiltinType(param_attrs_src, .@"Type.Fn.Param.Attributes"); const fn_attrs_ty = try sema.getBuiltinType(fn_attrs_src, .@"Type.Fn.Attributes"); - const param_types_uncoerced = try sema.resolveInst(extra.param_types); + const param_types_uncoerced = sema.resolveInst(extra.param_types); const param_types_coerced = try sema.coerce(block, .slice_const_type, param_types_uncoerced, param_types_src); const param_types_slice = try sema.resolveConstDefinedValue(block, param_types_src, param_types_coerced, .{ .simple = .fn_param_types }); const param_types_arr = try sema.derefSliceAsArray(block, param_types_src, param_types_slice, .{ .simple = .fn_param_types }); @@ -19907,7 +19906,7 @@ fn zirReifyFn( .len = params_len, .child = single_param_attrs_ty.toIntern(), })); - const param_attrs_uncoerced = try sema.resolveInst(extra.param_attrs); + const param_attrs_uncoerced = sema.resolveInst(extra.param_attrs); const param_attrs_coerced = try sema.coerce(block, param_attrs_ty, param_attrs_uncoerced, param_attrs_src); const param_attrs_slice = try sema.resolveConstDefinedValue(block, param_attrs_src, param_attrs_coerced, .{ .simple = .fn_param_attrs }); const param_attrs_arr = try sema.derefSliceAsArray(block, param_attrs_src, param_attrs_slice, .{ .simple = .fn_param_attrs }); @@ -19915,7 +19914,7 @@ fn zirReifyFn( const ret_ty = try sema.resolveType(block, ret_ty_src, extra.ret_ty); try sema.ensureLayoutResolved(ret_ty); - const fn_attrs_uncoerced = try sema.resolveInst(extra.fn_attrs); + const fn_attrs_uncoerced = sema.resolveInst(extra.fn_attrs); const fn_attrs_coerced = try sema.coerce(block, fn_attrs_ty, fn_attrs_uncoerced, fn_attrs_src); const fn_attrs_val = try sema.resolveConstDefinedValue(block, fn_attrs_src, fn_attrs_coerced, .{ .simple = .fn_attrs }); const fn_attrs = try sema.interpretBuiltinType(block, fn_attrs_src, fn_attrs_val, std.builtin.Type.Fn.Attributes); @@ -20041,16 +20040,16 @@ fn zirReifyStruct( const container_layout_ty = try sema.getBuiltinType(layout_src, .@"Type.ContainerLayout"); const single_field_attrs_ty = try sema.getBuiltinType(field_attrs_src, .@"Type.StructField.Attributes"); - const layout_uncoerced = try sema.resolveInst(extra.layout); + const layout_uncoerced = sema.resolveInst(extra.layout); const layout_coerced = try sema.coerce(block, container_layout_ty, layout_uncoerced, layout_src); const layout_val = try sema.resolveConstDefinedValue(block, layout_src, layout_coerced, .{ .simple = .struct_layout }); const layout = try sema.interpretBuiltinType(block, layout_src, layout_val, std.builtin.Type.ContainerLayout); - const backing_int_ty_uncoerced = try sema.resolveInst(extra.backing_ty); + const backing_int_ty_uncoerced = sema.resolveInst(extra.backing_ty); const backing_int_ty_coerced = try sema.coerce(block, .optional_type, backing_int_ty_uncoerced, backing_ty_src); const backing_int_ty_val = try sema.resolveConstDefinedValue(block, backing_ty_src, backing_int_ty_coerced, .{ .simple = .packed_struct_backing_int_type }); - const field_names_uncoerced = try sema.resolveInst(extra.field_names); + const field_names_uncoerced = sema.resolveInst(extra.field_names); const field_names_coerced = try sema.coerce(block, .slice_const_slice_const_u8, field_names_uncoerced, field_names_src); const field_names_slice = try sema.resolveConstDefinedValue(block, field_names_src, field_names_coerced, .{ .simple = .struct_field_names }); const field_names_arr = try sema.derefSliceAsArray(block, field_names_src, field_names_slice, .{ .simple = .struct_field_names }); @@ -20066,12 +20065,12 @@ fn zirReifyStruct( .child = single_field_attrs_ty.toIntern(), })); - const field_types_uncoerced = try sema.resolveInst(extra.field_types); + const field_types_uncoerced = sema.resolveInst(extra.field_types); const field_types_coerced = try sema.coerce(block, field_types_ty, field_types_uncoerced, field_types_src); const field_types_slice = try sema.resolveConstDefinedValue(block, field_types_src, field_types_coerced, .{ .simple = .struct_field_types }); const field_types_arr = try sema.derefSliceAsArray(block, field_types_src, field_types_slice, .{ .simple = .struct_field_types }); - const field_attrs_uncoerced = try sema.resolveInst(extra.field_attrs); + const field_attrs_uncoerced = sema.resolveInst(extra.field_attrs); const field_attrs_coerced = try sema.coerce(block, field_attrs_ty, field_attrs_uncoerced, field_attrs_src); const field_attrs_slice = try sema.resolveConstDefinedValue(block, field_attrs_src, field_attrs_coerced, .{ .simple = .struct_field_attrs }); const field_attrs_arr = try sema.derefSliceAsArray(block, field_attrs_src, field_attrs_slice, .{ .simple = .struct_field_attrs }); @@ -20328,19 +20327,19 @@ fn zirReifyUnion( const container_layout_ty = try sema.getBuiltinType(layout_src, .@"Type.ContainerLayout"); const single_field_attrs_ty = try sema.getBuiltinType(field_attrs_src, .@"Type.UnionField.Attributes"); - const layout_uncoerced = try sema.resolveInst(extra.layout); + const layout_uncoerced = sema.resolveInst(extra.layout); const layout_coerced = try sema.coerce(block, container_layout_ty, layout_uncoerced, layout_src); const layout_val = try sema.resolveConstDefinedValue(block, layout_src, layout_coerced, .{ .simple = .union_layout }); const layout = try sema.interpretBuiltinType(block, layout_src, layout_val, std.builtin.Type.ContainerLayout); - const arg_ty_uncoerced = try sema.resolveInst(extra.arg_ty); + const arg_ty_uncoerced = sema.resolveInst(extra.arg_ty); const arg_ty_coerced = try sema.coerce(block, .optional_type, arg_ty_uncoerced, arg_ty_src); const arg_ty_val = try sema.resolveConstDefinedValue(block, arg_ty_src, arg_ty_coerced, switch (layout) { .@"packed" => .{ .simple = .packed_union_backing_int_type }, .auto, .@"extern" => .{ .simple = .union_enum_tag_type }, }); - const field_names_uncoerced = try sema.resolveInst(extra.field_names); + const field_names_uncoerced = sema.resolveInst(extra.field_names); const field_names_coerced = try sema.coerce(block, .slice_const_slice_const_u8, field_names_uncoerced, field_names_src); const field_names_slice = try sema.resolveConstDefinedValue(block, field_names_src, field_names_coerced, .{ .simple = .union_field_names }); const field_names_arr = try sema.derefSliceAsArray(block, field_names_src, field_names_slice, .{ .simple = .union_field_names }); @@ -20356,12 +20355,12 @@ fn zirReifyUnion( .child = single_field_attrs_ty.toIntern(), })); - const field_types_uncoerced = try sema.resolveInst(extra.field_types); + const field_types_uncoerced = sema.resolveInst(extra.field_types); const field_types_coerced = try sema.coerce(block, field_types_ty, field_types_uncoerced, field_types_src); const field_types_slice = try sema.resolveConstDefinedValue(block, field_types_src, field_types_coerced, .{ .simple = .union_field_types }); const field_types_arr = try sema.derefSliceAsArray(block, field_types_src, field_types_slice, .{ .simple = .union_field_types }); - const field_attrs_uncoerced = try sema.resolveInst(extra.field_attrs); + const field_attrs_uncoerced = sema.resolveInst(extra.field_attrs); const field_attrs_coerced = try sema.coerce(block, field_attrs_ty, field_attrs_uncoerced, field_attrs_src); const field_attrs_slice = try sema.resolveConstDefinedValue(block, field_attrs_src, field_attrs_coerced, .{ .simple = .union_field_attrs }); const field_attrs_arr = try sema.derefSliceAsArray(block, field_attrs_src, field_attrs_slice, .{ .simple = .union_field_attrs }); @@ -20549,12 +20548,12 @@ fn zirReifyEnum( const enum_mode_ty = try sema.getBuiltinType(mode_src, .@"Type.Enum.Mode"); - const tag_ty_uncoerced = try sema.resolveInst(extra.tag_ty); + const tag_ty_uncoerced = sema.resolveInst(extra.tag_ty); const tag_ty_coerced = try sema.coerce(block, .type, tag_ty_uncoerced, tag_ty_src); const tag_ty_val = try sema.resolveConstDefinedValue(block, tag_ty_src, tag_ty_coerced, .{ .simple = .enum_int_tag_type }); const tag_ty = tag_ty_val.toType(); - const mode_uncoerced = try sema.resolveInst(extra.mode); + const mode_uncoerced = sema.resolveInst(extra.mode); const mode_coerced = try sema.coerce(block, enum_mode_ty, mode_uncoerced, mode_src); const mode_val = try sema.resolveConstDefinedValue(block, mode_src, mode_coerced, .{ .simple = .type }); const nonexhaustive = switch (try sema.interpretBuiltinType(block, mode_src, mode_val, std.builtin.Type.Enum.Mode)) { @@ -20562,7 +20561,7 @@ fn zirReifyEnum( .nonexhaustive => true, }; - const field_names_uncoerced = try sema.resolveInst(extra.field_names); + const field_names_uncoerced = sema.resolveInst(extra.field_names); const field_names_coerced = try sema.coerce(block, .slice_const_slice_const_u8, field_names_uncoerced, field_names_src); const field_names_slice = try sema.resolveConstDefinedValue(block, field_names_src, field_names_coerced, .{ .simple = .enum_field_names }); const field_names_arr = try sema.derefSliceAsArray(block, field_names_src, field_names_slice, .{ .simple = .enum_field_names }); @@ -20574,7 +20573,7 @@ fn zirReifyEnum( .child = tag_ty.toIntern(), })); - const field_values_uncoerced = try sema.resolveInst(extra.field_values); + const field_values_uncoerced = sema.resolveInst(extra.field_values); const field_values_coerced = try sema.coerce(block, field_values_ty, field_values_uncoerced, field_values_src); const field_values_slice = try sema.resolveConstDefinedValue(block, field_values_src, field_values_coerced, .{ .simple = .enum_field_values }); const field_values_arr = try sema.derefSliceAsArray(block, field_values_src, field_values_slice, .{ .simple = .enum_field_values }); @@ -20663,7 +20662,7 @@ fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.In const va_list_ty = try sema.getBuiltinType(src, .VaList); const va_list_ptr = try pt.singleMutPtrType(va_list_ty); - const inst = try sema.resolveInst(zir_ref); + const inst = sema.resolveInst(zir_ref); return sema.coerce(block, va_list_ptr, inst, src); } @@ -20759,7 +20758,7 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@intFromFloat"); - const operand = try sema.resolveInst(extra.rhs); + const operand = sema.resolveInst(extra.rhs); const operand_ty = sema.typeOf(operand); try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, src, operand_src); @@ -20771,7 +20770,7 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro _ = try sema.checkIntType(block, src, dest_scalar_ty); try sema.checkFloatType(block, operand_src, operand_scalar_ty); - if (try sema.resolveValue(operand)) |operand_val| { + if (sema.resolveValue(operand)) |operand_val| { const result_val = try sema.intFromFloat(block, operand_src, operand_val, operand_ty, dest_ty, .truncate); return Air.internedToRef(result_val.toIntern()); } else if (dest_scalar_ty.zigTypeTag(zcu) == .comptime_int) { @@ -20812,7 +20811,7 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@floatFromInt"); - const operand = try sema.resolveInst(extra.rhs); + const operand = sema.resolveInst(extra.rhs); const operand_ty = sema.typeOf(operand); try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, src, operand_src); @@ -20823,7 +20822,7 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro try sema.checkFloatType(block, src, dest_scalar_ty); _ = try sema.checkIntType(block, operand_src, operand_scalar_ty); - if (try sema.resolveValue(operand)) |operand_val| { + if (sema.resolveValue(operand)) |operand_val| { if (operand_val.isUndef(zcu)) return .fromValue(try pt.undefValue(dest_ty)); if (dest_ty.zigTypeTag(zcu) != .vector) { return .fromValue(try pt.floatValue(dest_ty, operand_val.toFloat(f128, zcu))); @@ -20855,7 +20854,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); - const operand_res = try sema.resolveInst(extra.rhs); + const operand_res = sema.resolveInst(extra.rhs); const uncoerced_operand_ty = sema.typeOf(operand_res); const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu, "@ptrFromInt"); @@ -20983,7 +20982,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData const src = block.nodeOffset(extra.node); const operand_src = block.builtinCallArgSrc(extra.node, 0); const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_opt, "@errorCast"); - const operand = try sema.resolveInst(extra.rhs); + const operand = sema.resolveInst(extra.rhs); const operand_ty = sema.typeOf(operand); const dest_tag = dest_ty.zigTypeTag(zcu); @@ -21134,7 +21133,7 @@ fn zirPtrCastFull(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDa const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; const src = block.nodeOffset(extra.node); const operand_src = block.src(.{ .node_offset_ptrcast_operand = extra.node }); - const operand = try sema.resolveInst(extra.rhs); + const operand = sema.resolveInst(extra.rhs); const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu, flags.needResultTypeBuiltinName()); return sema.ptrCastFull( block, @@ -21153,7 +21152,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu, "@ptrCast"); - const operand = try sema.resolveInst(extra.rhs); + const operand = sema.resolveInst(extra.rhs); return sema.ptrCastFull( block, @@ -21219,7 +21218,7 @@ fn ptrCastFull( }; }, .slice => src: { - const operand_val = try sema.resolveValue(operand) orelse break :src .{ .fromInterned(src_info.child), null }; + const operand_val = sema.resolveValue(operand) orelse break :src .{ .fromInterned(src_info.child), null }; if (operand_val.isUndef(zcu)) break :len .undef; const slice_val = switch (operand_ty.zigTypeTag(zcu)) { .optional => operand_val.optionalValue(zcu) orelse break :len .undef, @@ -21516,7 +21515,7 @@ fn ptrCastFull( ct: { if (flags.addrspace_cast) break :ct; // cannot `@addrSpaceCast` at comptime - const operand_val = try sema.resolveValue(operand) orelse break :ct; + const operand_val = sema.resolveValue(operand) orelse break :ct; if (operand_val.isUndef(zcu)) { if (!dest_ty.ptrAllowsZero(zcu)) { @@ -21776,7 +21775,7 @@ fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; const src = block.nodeOffset(extra.node); const operand_src = block.src(.{ .node_offset_ptrcast_operand = extra.node }); - const operand = try sema.resolveInst(extra.operand); + const operand = sema.resolveInst(extra.operand); const operand_ty = sema.typeOf(operand); try sema.checkPtrOperand(block, operand_src, operand_ty); @@ -21792,7 +21791,7 @@ fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst break :blk dest_ty; }; - if (try sema.resolveValue(operand)) |operand_val| { + if (sema.resolveValue(operand)) |operand_val| { return Air.internedToRef((try pt.getCoerced(operand_val, dest_ty)).toIntern()); } @@ -21811,7 +21810,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@truncate"); const dest_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, dest_ty, src); - const operand = try sema.resolveInst(extra.rhs); + const operand = sema.resolveInst(extra.rhs); const operand_ty = sema.typeOf(operand); const operand_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, operand_ty, operand_src); @@ -21842,7 +21841,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai } } - if (try sema.resolveValue(operand)) |val| { + if (sema.resolveValue(operand)) |val| { const result_val = try arith.truncate(sema, val, operand_ty, dest_ty, dest_info.signedness, dest_info.bits); return Air.internedToRef(result_val.toIntern()); } @@ -21863,7 +21862,7 @@ fn zirBitCount( const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); _ = try sema.checkIntOrVector(block, operand, operand_src); const bits = operand_ty.intInfo(zcu).bits; @@ -21876,7 +21875,7 @@ fn zirBitCount( .len = vec_len, .child = result_scalar_ty.toIntern(), }); - if (try sema.resolveValue(operand)) |val| { + if (sema.resolveValue(operand)) |val| { if (val.isUndef(zcu)) return pt.undefRef(result_ty); const elems = try sema.arena.alloc(InternPool.Index, vec_len); @@ -21893,7 +21892,7 @@ fn zirBitCount( } }, .int => { - if (try sema.resolveValue(operand)) |val| { + if (sema.resolveValue(operand)) |val| { if (val.isUndef(zcu)) return pt.undefRef(result_scalar_ty); return pt.intRef(result_scalar_ty, comptimeOp(val, operand_ty, zcu)); } else { @@ -21910,7 +21909,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); const scalar_ty = try sema.checkIntOrVector(block, operand, operand_src); const bits = scalar_ty.intInfo(zcu).bits; @@ -21922,7 +21921,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .{ scalar_ty.fmt(pt), bits }, ); } - if (try sema.resolveValue(operand)) |operand_val| { + if (sema.resolveValue(operand)) |operand_val| { return .fromValue(try arith.byteSwap(sema, operand_val, operand_ty)); } return block.addTyOp(.byte_swap, operand_ty, operand); @@ -21931,11 +21930,11 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); - const operand = try sema.resolveInst(inst_data.operand); + const operand = sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); _ = try sema.checkIntOrVector(block, operand, operand_src); - if (try sema.resolveValue(operand)) |operand_val| { + if (sema.resolveValue(operand)) |operand_val| { return .fromValue(try arith.bitReverse(sema, operand_val, operand_ty)); } return block.addTyOp(.bit_reverse, operand_ty, operand); @@ -22359,8 +22358,8 @@ fn checkSimdBinOp( .len = vec_len, .lhs = lhs, .rhs = rhs, - .lhs_val = try sema.resolveValue(lhs), - .rhs_val = try sema.resolveValue(rhs), + .lhs_val = sema.resolveValue(lhs), + .rhs_val = sema.resolveValue(rhs), .result_ty = result_ty, .scalar_ty = result_ty.scalarType(zcu), }; @@ -22452,7 +22451,7 @@ fn resolveExportOptions( const ip = &zcu.intern_pool; const export_options_ty = try sema.getBuiltinType(src, .ExportOptions); - const air_ref = try sema.resolveInst(zir_ref); + const air_ref = sema.resolveInst(zir_ref); const options = try sema.coerce(block, export_options_ty, air_ref, src); const name_src = block.src(.{ .init_field_name = src.offset.node_offset_builtin_call_arg.builtin_call_node }); @@ -22505,7 +22504,7 @@ fn resolveBuiltinEnum( reason: ComptimeReason, ) CompileError!@field(std.builtin, @tagName(name)) { const ty = try sema.getBuiltinType(src, name); - const air_ref = try sema.resolveInst(zir_ref); + const air_ref = sema.resolveInst(zir_ref); const coerced = try sema.coerce(block, ty, air_ref, src); const val = try sema.resolveConstDefinedValue(block, src, coerced, reason); return sema.interpretBuiltinType(block, src, val, @field(std.builtin, @tagName(name))); @@ -22552,7 +22551,7 @@ fn zirCmpxchg( const success_order_src = block.builtinCallArgSrc(extra.node, 4); const failure_order_src = block.builtinCallArgSrc(extra.node, 5); // zig fmt: on - const expected_value = try sema.resolveInst(extra.expected_value); + const expected_value = sema.resolveInst(extra.expected_value); const elem_ty = sema.typeOf(expected_value); if (elem_ty.zigTypeTag(zcu) == .float) { return sema.fail( @@ -22562,9 +22561,9 @@ fn zirCmpxchg( .{elem_ty.fmt(pt)}, ); } - const uncasted_ptr = try sema.resolveInst(extra.ptr); + const uncasted_ptr = sema.resolveInst(extra.ptr); const ptr = try sema.checkAtomicPtrOperand(block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, false); - const new_value = try sema.coerce(block, elem_ty, try sema.resolveInst(extra.new_value), new_value_src); + const new_value = try sema.coerce(block, elem_ty, sema.resolveInst(extra.new_value), new_value_src); const success_order = try sema.resolveAtomicOrder(block, success_order_src, extra.success_order, .{ .simple = .atomic_order }); const failure_order = try sema.resolveAtomicOrder(block, failure_order_src, extra.failure_order, .{ .simple = .atomic_order }); @@ -22589,8 +22588,8 @@ fn zirCmpxchg( } const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: { - if (try sema.resolveValue(expected_value)) |expected_val| { - if (try sema.resolveValue(new_value)) |new_val| { + if (sema.resolveValue(expected_value)) |expected_val| { + if (sema.resolveValue(new_value)) |new_val| { if (expected_val.isUndef(zcu) or new_val.isUndef(zcu)) { // TODO: this should probably cause the memory stored at the pointer // to become undef as well @@ -22642,7 +22641,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I else => return sema.fail(block, src, "expected array or vector type, found '{f}'", .{dest_ty.fmt(pt)}), } - const operand = try sema.resolveInst(extra.rhs); + const operand = sema.resolveInst(extra.rhs); const scalar_ty = dest_ty.childType(zcu); const scalar = try sema.coerce(block, scalar_ty, operand, scalar_src); @@ -22653,7 +22652,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I const maybe_sentinel = dest_ty.sentinel(zcu); - if (try sema.resolveValue(scalar)) |scalar_val| { + if (sema.resolveValue(scalar)) |scalar_val| { full: { if (dest_ty.zigTypeTag(zcu) == .vector) break :full; const sentinel = maybe_sentinel orelse break :full; @@ -22688,7 +22687,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. const op_src = block.builtinCallArgSrc(inst_data.src_node, 0); const operand_src = block.builtinCallArgSrc(inst_data.src_node, 1); const operation = try sema.resolveBuiltinEnum(block, op_src, extra.lhs, .ReduceOp, .{ .simple = .operand_reduce_operation }); - const operand = try sema.resolveInst(extra.rhs); + const operand = sema.resolveInst(extra.rhs); const operand_ty = sema.typeOf(operand); const pt = sema.pt; const zcu = pt.zcu; @@ -22722,7 +22721,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. return sema.fail(block, operand_src, "@reduce operation requires a vector with nonzero length", .{}); } - if (try sema.resolveValue(operand)) |operand_val| { + if (sema.resolveValue(operand)) |operand_val| { if (operand_val.isUndef(zcu)) return pt.undefRef(scalar_ty); var accum: Value = try operand_val.elemValue(pt, 0); @@ -22758,9 +22757,9 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const elem_ty = try sema.resolveType(block, elem_ty_src, extra.elem_type); try sema.checkVectorElemType(block, elem_ty_src, elem_ty); - const a = try sema.resolveInst(extra.a); - const b = try sema.resolveInst(extra.b); - var mask = try sema.resolveInst(extra.mask); + const a = sema.resolveInst(extra.a); + const b = sema.resolveInst(extra.b); + var mask = sema.resolveInst(extra.mask); var mask_ty = sema.typeOf(mask); const mask_len = switch (sema.typeOf(mask).zigTypeTag(zcu)) { @@ -22867,8 +22866,8 @@ fn analyzeShuffle( } } - const maybe_a_val = try sema.resolveValue(a_coerced); - const maybe_b_val = try sema.resolveValue(b_coerced); + const maybe_a_val = sema.resolveValue(a_coerced); + const maybe_b_val = sema.resolveValue(b_coerced); const a_rt = a_used and maybe_a_val == null; const b_rt = b_used and maybe_b_val == null; @@ -22956,7 +22955,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C const elem_ty = try sema.resolveType(block, elem_ty_src, extra.elem_type); try sema.checkVectorElemType(block, elem_ty_src, elem_ty); - const pred_uncoerced = try sema.resolveInst(extra.pred); + const pred_uncoerced = sema.resolveInst(extra.pred); const pred_ty = sema.typeOf(pred_uncoerced); const vec_len_u64 = switch (pred_ty.zigTypeTag(zcu)) { @@ -22975,12 +22974,12 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C .len = vec_len, .child = elem_ty.toIntern(), }); - const a = try sema.coerce(block, vec_ty, try sema.resolveInst(extra.a), a_src); - const b = try sema.coerce(block, vec_ty, try sema.resolveInst(extra.b), b_src); + const a = try sema.coerce(block, vec_ty, sema.resolveInst(extra.a), a_src); + const b = try sema.coerce(block, vec_ty, sema.resolveInst(extra.b), b_src); - const maybe_pred = try sema.resolveValue(pred); - const maybe_a = try sema.resolveValue(a); - const maybe_b = try sema.resolveValue(b); + const maybe_pred = sema.resolveValue(pred); + const maybe_a = sema.resolveValue(a); + const maybe_b = sema.resolveValue(b); const runtime_src = if (maybe_pred) |pred_val| rs: { if (pred_val.isUndef(zcu)) return pt.undefRef(vec_ty); @@ -23041,7 +23040,7 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const order_src = block.builtinCallArgSrc(inst_data.src_node, 2); // zig fmt: on const elem_ty = try sema.resolveType(block, elem_ty_src, extra.elem_type); - const uncasted_ptr = try sema.resolveInst(extra.ptr); + const uncasted_ptr = sema.resolveInst(extra.ptr); const ptr = try sema.checkAtomicPtrOperand(block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, true); const order = try sema.resolveAtomicOrder(block, order_src, extra.ordering, .{ .simple = .atomic_order }); @@ -23090,9 +23089,9 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A const operand_src = block.builtinCallArgSrc(inst_data.src_node, 3); const order_src = block.builtinCallArgSrc(inst_data.src_node, 4); // zig fmt: on - const operand = try sema.resolveInst(extra.operand); + const operand = sema.resolveInst(extra.operand); const elem_ty = sema.typeOf(operand); - const uncasted_ptr = try sema.resolveInst(extra.ptr); + const uncasted_ptr = sema.resolveInst(extra.ptr); const ptr = try sema.checkAtomicPtrOperand(block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, false); const op = try sema.resolveAtomicRmwOp(block, op_src, extra.operation); @@ -23119,7 +23118,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A if (try elem_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: { - const maybe_operand_val = try sema.resolveValue(operand); + const maybe_operand_val = sema.resolveValue(operand); const operand_val = maybe_operand_val orelse { try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src); break :rs operand_src; @@ -23170,9 +23169,9 @@ fn zirAtomicStore(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const operand_src = block.builtinCallArgSrc(inst_data.src_node, 2); const order_src = block.builtinCallArgSrc(inst_data.src_node, 3); // zig fmt: on - const operand = try sema.resolveInst(extra.operand); + const operand = sema.resolveInst(extra.operand); const elem_ty = sema.typeOf(operand); - const uncasted_ptr = try sema.resolveInst(extra.ptr); + const uncasted_ptr = sema.resolveInst(extra.ptr); const ptr = try sema.checkAtomicPtrOperand(block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, false); const order = try sema.resolveAtomicOrder(block, order_src, extra.ordering, .{ .simple = .atomic_order }); @@ -23203,14 +23202,14 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. const mulend2_src = block.builtinCallArgSrc(inst_data.src_node, 2); const addend_src = block.builtinCallArgSrc(inst_data.src_node, 3); - const addend = try sema.resolveInst(extra.addend); + const addend = sema.resolveInst(extra.addend); const ty = sema.typeOf(addend); - const mulend1 = try sema.coerce(block, ty, try sema.resolveInst(extra.mulend1), mulend1_src); - const mulend2 = try sema.coerce(block, ty, try sema.resolveInst(extra.mulend2), mulend2_src); + const mulend1 = try sema.coerce(block, ty, sema.resolveInst(extra.mulend1), mulend1_src); + const mulend2 = try sema.coerce(block, ty, sema.resolveInst(extra.mulend2), mulend2_src); - const maybe_mulend1 = try sema.resolveValue(mulend1); - const maybe_mulend2 = try sema.resolveValue(mulend2); - const maybe_addend = try sema.resolveValue(addend); + const maybe_mulend1 = sema.resolveValue(mulend1); + const maybe_mulend2 = sema.resolveValue(mulend2); + const maybe_addend = sema.resolveValue(addend); const pt = sema.pt; const zcu = pt.zcu; @@ -23272,10 +23271,10 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const call_src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data; - const func = try sema.resolveInst(extra.callee); + const func = sema.resolveInst(extra.callee); const modifier_ty = try sema.getBuiltinType(call_src, .CallModifier); - const air_ref = try sema.resolveInst(extra.modifier); + const air_ref = sema.resolveInst(extra.modifier); const modifier_ref = try sema.coerce(block, modifier_ty, air_ref, modifier_src); const modifier_val = try sema.resolveConstDefinedValue(block, modifier_src, modifier_ref, .{ .simple = .call_modifier }); var modifier = try sema.interpretBuiltinType(block, modifier_src, modifier_val, std.builtin.CallModifier); @@ -23313,7 +23312,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError }, } - const args = try sema.resolveInst(extra.args); + const args = sema.resolveInst(extra.args); const args_ty = sema.typeOf(args); if (!args_ty.isTuple(zcu)) { @@ -23390,7 +23389,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins return sema.fail(block, field_name_src, "cannot get @fieldParentPtr of a comptime field", .{}); } - const field_ptr = try sema.resolveInst(extra.field_ptr); + const field_ptr = sema.resolveInst(extra.field_ptr); const field_ptr_ty = sema.typeOf(field_ptr); try sema.checkPtrOperand(block, field_ptr_src, field_ptr_ty); const field_ptr_info = field_ptr_ty.ptrInfo(zcu); @@ -23555,8 +23554,8 @@ fn zirMinMax( const src = block.nodeOffset(inst_data.src_node); const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0); const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1); - const lhs = try sema.resolveInst(extra.lhs); - const rhs = try sema.resolveInst(extra.rhs); + const lhs = sema.resolveInst(extra.lhs); + const rhs = sema.resolveInst(extra.rhs); return sema.analyzeMinMax(block, src, air_tag, &.{ lhs, rhs }, &.{ lhs_src, rhs_src }); } @@ -23576,7 +23575,7 @@ fn zirMinMaxMulti( for (operands, air_refs, operand_srcs, 0..) |zir_ref, *air_ref, *op_src, i| { op_src.* = block.builtinCallArgSrc(src_node, @intCast(i)); - air_ref.* = try sema.resolveInst(zir_ref); + air_ref.* = sema.resolveInst(zir_ref); } return sema.analyzeMinMax(block, src, air_tag, air_refs, operand_srcs); @@ -23679,7 +23678,7 @@ fn analyzeMinMax( const operand_scalar_ty = sema.typeOf(operand).scalarType(zcu); const want_strat: TypeStrat = switch (operand_scalar_ty.zigTypeTag(zcu)) { .comptime_int => s: { - const val = (try sema.resolveValue(operand)).?; + const val = sema.resolveValue(operand).?; if (val.isUndef(zcu)) break :s .none; break :s .{ .int = .{ .all_comptime_int = true, @@ -23698,7 +23697,7 @@ fn analyzeMinMax( // (replaced with just the simple calls to `Type.minInt`/`Type.maxInt`) so that we only // use the input *types* to determine the result type. const min: Value, const max: Value = bounds: { - if (try sema.resolveValue(operand)) |operand_val| { + if (sema.resolveValue(operand)) |operand_val| { if (vector_len) |len| { var min = try operand_val.elemValue(pt, 0); var max = min; @@ -23804,7 +23803,7 @@ fn analyzeMinMax( var opt_runtime_src: ?LazySrcLoc = null; for (operands, operand_srcs) |operand, operand_src| { - const operand_val = try sema.resolveValue(operand) orelse { + const operand_val = sema.resolveValue(operand) orelse { if (opt_runtime_src == null) opt_runtime_src = operand_src; continue; }; @@ -23944,8 +23943,8 @@ fn zirMemcpy( const src = block.nodeOffset(inst_data.src_node); const dest_src = block.builtinCallArgSrc(inst_data.src_node, 0); const src_src = block.builtinCallArgSrc(inst_data.src_node, 1); - const dest_ptr = try sema.resolveInst(extra.lhs); - const src_ptr = try sema.resolveInst(extra.rhs); + const dest_ptr = sema.resolveInst(extra.lhs); + const src_ptr = sema.resolveInst(extra.rhs); const dest_ty = sema.typeOf(dest_ptr); const src_ty = sema.typeOf(src_ptr); const dest_len = try indexablePtrLenOrNone(sema, block, dest_src, dest_ptr); @@ -24208,8 +24207,8 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void const src = block.nodeOffset(inst_data.src_node); const dest_src = block.builtinCallArgSrc(inst_data.src_node, 0); const value_src = block.builtinCallArgSrc(inst_data.src_node, 1); - const dest_ptr = try sema.resolveInst(extra.lhs); - const uncoerced_elem = try sema.resolveInst(extra.rhs); + const dest_ptr = sema.resolveInst(extra.lhs); + const uncoerced_elem = sema.resolveInst(extra.rhs); const dest_ptr_ty = sema.typeOf(dest_ptr); try checkMemOperand(sema, block, dest_src, dest_ptr_ty); @@ -24252,7 +24251,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void const ptr_val = try sema.resolveDefinedValue(block, dest_src, dest_ptr) orelse break :rs dest_src; if (!sema.isComptimeMutablePtr(ptr_val)) break :rs dest_src; - const elem_val = try sema.resolveValue(elem) orelse break :rs value_src; + const elem_val = sema.resolveValue(elem) orelse break :rs value_src; const array_ty = try pt.arrayType(.{ .child = dest_elem_ty.toIntern(), .len = len_u64, @@ -24322,7 +24321,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A const cc_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); extra_index += 1; const cc_ty = try sema.getBuiltinType(cc_src, .CallingConvention); - const uncoerced_cc = try sema.resolveInst(cc_ref); + const uncoerced_cc = sema.resolveInst(cc_ref); const coerced_cc = try sema.coerce(block, cc_ty, uncoerced_cc, cc_src); const cc_val = try sema.resolveConstDefinedValue(block, cc_src, coerced_cc, .{ .simple = .@"callconv" }); break :blk try sema.analyzeValueAsCallconv(block, cc_src, cc_val); @@ -24439,7 +24438,7 @@ fn zirCDefine( const val_src = block.builtinCallArgSrc(extra.node, 1); const name = try sema.resolveConstString(block, name_src, extra.lhs, .{ .simple = .operand_cDefine_macro_name }); - const rhs = try sema.resolveInst(extra.rhs); + const rhs = sema.resolveInst(extra.rhs); if (sema.typeOf(rhs).zigTypeTag(zcu) != .void) { const value = try sema.resolveConstString(block, val_src, extra.rhs, .{ .simple = .operand_cDefine_macro_value }); try block.c_import_buf.?.print("#define {s} {s}\n", .{ name, value }); @@ -24488,7 +24487,7 @@ fn zirWasmMemoryGrow( } const index: u32 = @intCast(try sema.resolveInt(block, index_src, extra.lhs, .u32, .{ .simple = .wasm_memory_index })); - const delta = try sema.coerce(block, .usize, try sema.resolveInst(extra.rhs), delta_src); + const delta = try sema.coerce(block, .usize, sema.resolveInst(extra.rhs), delta_src); try sema.requireRuntimeBlock(block, builtin_src, null); return block.addInst(.{ @@ -24514,7 +24513,7 @@ fn resolvePrefetchOptions( const ip = &zcu.intern_pool; const options_ty = try sema.getBuiltinType(src, .PrefetchOptions); - const options = try sema.coerce(block, options_ty, try sema.resolveInst(zir_ref), src); + const options = try sema.coerce(block, options_ty, sema.resolveInst(zir_ref), src); const rw_src = block.src(.{ .init_field_rw = src.offset.node_offset_builtin_call_arg.builtin_call_node }); const locality_src = block.src(.{ .init_field_locality = src.offset.node_offset_builtin_call_arg.builtin_call_node }); @@ -24544,7 +24543,7 @@ fn zirPrefetch( const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; const ptr_src = block.builtinCallArgSrc(extra.node, 0); const opts_src = block.builtinCallArgSrc(extra.node, 1); - const ptr = try sema.resolveInst(extra.lhs); + const ptr = sema.resolveInst(extra.lhs); try sema.checkPtrOperand(block, ptr_src, sema.typeOf(ptr)); const options = try sema.resolvePrefetchOptions(block, opts_src, extra.rhs); @@ -24586,7 +24585,7 @@ fn resolveExternOptions( const io = comp.io; const ip = &zcu.intern_pool; - const options_inst = try sema.resolveInst(zir_ref); + const options_inst = sema.resolveInst(zir_ref); const extern_options_ty = try sema.getBuiltinType(src, .ExternOptions); const options = try sema.coerce(block, extern_options_ty, options_inst, src); @@ -24738,7 +24737,7 @@ fn zirBuiltinExtern( const uncasted_ptr = try sema.analyzeNavRef(block, src, ip.indexToKey(extern_val).@"extern".owner_nav); // We want to cast to `ty`, but that isn't necessarily an allowed coercion. - if (try sema.resolveValue(uncasted_ptr)) |uncasted_ptr_val| { + if (sema.resolveValue(uncasted_ptr)) |uncasted_ptr_val| { const casted_ptr_val = try pt.getCoerced(uncasted_ptr_val, ty); return Air.internedToRef(casted_ptr_val.toIntern()); } else { @@ -24854,7 +24853,7 @@ fn zirInplaceArithResultTy(sema: *Sema, extended: Zir.Inst.Extended.InstData) Co const pt = sema.pt; const zcu = pt.zcu; - const lhs = try sema.resolveInst(@enumFromInt(extended.operand)); + const lhs = sema.resolveInst(@enumFromInt(extended.operand)); const lhs_ty = sema.typeOf(lhs); const op: Zir.Inst.InplaceOp = @enumFromInt(extended.small); @@ -24879,7 +24878,7 @@ fn zirInplaceArithResultTy(sema: *Sema, extended: Zir.Inst.Extended.InstData) Co fn zirBranchHint(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; - const uncoerced_hint = try sema.resolveInst(extra.operand); + const uncoerced_hint = sema.resolveInst(extra.operand); const operand_src = block.builtinCallArgSrc(extra.node, 0); const hint_ty = try sema.getBuiltinType(operand_src, .BranchHint); @@ -26333,7 +26332,7 @@ fn structFieldVal( if (try field_ty.onePossibleValue(pt)) |field_val| return .fromValue(field_val); - if (try sema.resolveValue(struct_byval)) |struct_val| { + if (sema.resolveValue(struct_byval)) |struct_val| { if (struct_val.isUndef(zcu)) return pt.undefRef(field_ty); return .fromValue(try struct_val.fieldValue(pt, field_index)); } @@ -26404,7 +26403,7 @@ fn tupleFieldValByIndex( if (try field_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); - if (try sema.resolveValue(tuple_byval)) |tuple_val| { + if (sema.resolveValue(tuple_byval)) |tuple_val| { return switch (zcu.intern_pool.indexToKey(tuple_val.toIntern())) { .undef => pt.undefRef(field_ty), .aggregate => |aggregate| Air.internedToRef(switch (aggregate.storage) { @@ -26564,7 +26563,7 @@ fn unionFieldVal( const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); const enum_field_index: u32 = @intCast(Type.fromInterned(union_obj.enum_tag_type).enumFieldIndex(field_name, zcu).?); - if (try sema.resolveValue(union_byval)) |union_val| { + if (sema.resolveValue(union_byval)) |union_val| { if (union_val.isUndef(zcu)) return pt.undefRef(field_ty); const un = ip.indexToKey(union_val.toIntern()).un; @@ -26895,7 +26894,7 @@ fn tupleFieldPtr( } }))); } - if (try sema.resolveValue(tuple_ptr)) |tuple_ptr_val| { + if (sema.resolveValue(tuple_ptr)) |tuple_ptr_val| { const field_ptr_val = try tuple_ptr_val.ptrField(field_index, pt); return Air.internedToRef(field_ptr_val.toIntern()); } @@ -26936,7 +26935,7 @@ fn tupleField( return Air.internedToRef(default_value.toIntern()); // comptime field } - if (try sema.resolveValue(tuple)) |tuple_val| { + if (sema.resolveValue(tuple)) |tuple_val| { if (tuple_val.isUndef(zcu)) return pt.undefRef(field_ty); return Air.internedToRef((try tuple_val.fieldValue(pt, field_index)).toIntern()); } @@ -26968,7 +26967,7 @@ fn elemValArray( return sema.fail(block, array_src, "indexing into empty array is not allowed", .{}); } - const maybe_undef_array_val = try sema.resolveValue(array); + const maybe_undef_array_val = sema.resolveValue(array); // index must be defined since it can access out of bounds const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); @@ -27035,7 +27034,7 @@ fn elemPtrArray( return sema.fail(block, array_ptr_src, "indexing into empty array is not allowed", .{}); } - const maybe_undef_array_ptr_val = try sema.resolveValue(array_ptr); + const maybe_undef_array_ptr_val = sema.resolveValue(array_ptr); // The index must not be undefined since it can be out of bounds. const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: { const index = try sema.usizeCast(block, elem_index_src, index_val.toUnsignedInt(zcu)); @@ -27159,7 +27158,7 @@ fn elemPtrSlice( slice_ty.childType(zcu).assertHasLayout(zcu); - const maybe_undef_slice_val = try sema.resolveValue(slice); + const maybe_undef_slice_val = sema.resolveValue(slice); // The index must not be undefined since it can be out of bounds. const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: { break :o try sema.usizeCast(block, elem_index_src, index_val.toUnsignedInt(zcu)); @@ -27280,7 +27279,7 @@ fn coerceExtra( if (dest_ty.eql(inst_ty, zcu)) return inst; - const maybe_inst_val = try sema.resolveValue(inst); + const maybe_inst_val = sema.resolveValue(inst); var in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src, maybe_inst_val); if (in_memory_result == .ok) { @@ -29104,7 +29103,7 @@ fn storePtr2( error.NotCoercible => unreachable, else => |e| return e, }; - const maybe_operand_val = try sema.resolveValue(operand); + const maybe_operand_val = sema.resolveValue(operand); const runtime_src = rs: { const ptr_val = try sema.resolveDefinedValue(block, ptr_src, ptr) orelse break :rs ptr_src; @@ -29157,7 +29156,7 @@ fn checkComptimeKnownStore(sema: *Sema, block: *Block, store_inst_ref: Air.Inst. const maybe_base_alloc = sema.base_allocs.get(ptr) orelse break :known; const maybe_comptime_alloc = sema.maybe_comptime_allocs.getPtr(maybe_base_alloc) orelse break :known; - if ((try sema.resolveValue(operand)) != null and + if (sema.resolveValue(operand) != null and block.runtime_index == maybe_comptime_alloc.runtime_index) { try maybe_comptime_alloc.stores.append(sema.arena, .{ @@ -29206,7 +29205,7 @@ fn checkKnownAllocPtr(sema: *Sema, block: *Block, base_ptr: Air.Inst.Ref, new_pt // If the index value is runtime-known, this pointer is also runtime-known, so // we must in turn make the alloc value runtime-known. - if (null == try sema.resolveValue(index_ref)) { + if (null == sema.resolveValue(index_ref)) { try sema.markMaybeComptimeAllocRuntime(block, alloc_inst); } }, @@ -29312,7 +29311,7 @@ fn bitCast( }); } - if (try sema.resolveValue(inst)) |val| { + if (sema.resolveValue(inst)) |val| { if (val.isUndef(zcu)) return pt.undefRef(dest_ty); if (old_ty.zigTypeTag(zcu) == .error_set and dest_ty.zigTypeTag(zcu) == .error_set) { @@ -29338,7 +29337,7 @@ fn coerceArrayPtrToSlice( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - if (try sema.resolveValue(inst)) |val| { + if (sema.resolveValue(inst)) |val| { const ptr_array_ty = sema.typeOf(inst); const array_ty = ptr_array_ty.childType(zcu); const slice_ptr_ty = dest_ty.slicePtrFieldType(zcu); @@ -29433,7 +29432,7 @@ fn coerceCompatiblePtrs( const pt = sema.pt; const zcu = pt.zcu; const inst_ty = sema.typeOf(inst); - if (try sema.resolveValue(inst)) |val| { + if (sema.resolveValue(inst)) |val| { if (!val.isUndef(zcu) and val.isNull(zcu) and !dest_ty.isAllowzeroPtr(zcu)) { return sema.fail(block, inst_src, "null pointer casted to type '{f}'", .{dest_ty.fmt(pt)}); } @@ -29611,7 +29610,7 @@ fn coerceArrayLike( // try coercion of the whole array const in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src, null); if (in_memory_result == .ok) { - if (try sema.resolveValue(inst)) |inst_val| { + if (sema.resolveValue(inst)) |inst_val| { // These types share the same comptime value representation. return sema.coerceInMemory(inst_val, dest_ty); } @@ -29634,7 +29633,7 @@ fn coerceArrayLike( } const dest_elem_ty = dest_ty.childType(zcu); - if (dest_ty.isVector(zcu) and inst_ty.isVector(zcu) and (try sema.resolveValue(inst)) == null) { + if (dest_ty.isVector(zcu) and inst_ty.isVector(zcu) and sema.resolveValue(inst) == null) { const inst_elem_ty = inst_ty.childType(zcu); switch (dest_elem_ty.zigTypeTag(zcu)) { .int => if (inst_elem_ty.isInt(zcu)) { @@ -29674,7 +29673,7 @@ fn coerceArrayLike( const coerced = try sema.coerce(block, dest_elem_ty, elem_ref, elem_src); ref.* = coerced; if (runtime_src == null) { - if (try sema.resolveValue(coerced)) |elem_val| { + if (sema.resolveValue(coerced)) |elem_val| { val.* = elem_val.toIntern(); } else { runtime_src = elem_src; @@ -29735,7 +29734,7 @@ fn coerceTupleToArray( const coerced = try sema.coerce(block, dest_elem_ty, elem_ref, elem_src); ref.* = coerced; if (runtime_src == null) { - if (try sema.resolveValue(coerced)) |elem_val| { + if (sema.resolveValue(coerced)) |elem_val| { val.* = elem_val.toIntern(); } else { runtime_src = elem_src; @@ -29844,7 +29843,7 @@ fn coerceTupleToTuple( const coerced = try sema.coerce(block, .fromInterned(field_ty), elem_ref, field_src); field_refs[field_index] = coerced; if (default_val != .none) { - const init_val = (try sema.resolveValue(coerced)) orelse { + const init_val = sema.resolveValue(coerced) orelse { return sema.failWithNeededComptime(block, field_src, .{ .simple = .stored_to_comptime_field }); }; @@ -29853,7 +29852,7 @@ fn coerceTupleToTuple( } } if (runtime_src == null) { - if (try sema.resolveValue(coerced)) |field_val| { + if (sema.resolveValue(coerced)) |field_val| { field_vals[field_index] = field_val.toIntern(); } else { runtime_src = field_src; @@ -30125,7 +30124,7 @@ fn analyzeRef( const zcu = pt.zcu; const operand_ty = sema.typeOf(operand); - if (try sema.resolveValue(operand)) |val| { + if (sema.resolveValue(operand)) |val| { switch (zcu.intern_pool.indexToKey(val.toIntern())) { .@"extern" => |e| return sema.analyzeNavRef(block, src, e.owner_nav), .func => |f| return sema.analyzeNavRef(block, src, f.owner_nav), @@ -30209,7 +30208,7 @@ fn analyzeSlicePtr( const pt = sema.pt; const zcu = pt.zcu; const result_ty = slice_ty.slicePtrFieldType(zcu); - if (try sema.resolveValue(slice)) |val| { + if (sema.resolveValue(slice)) |val| { if (val.isUndef(zcu)) return pt.undefRef(result_ty); return Air.internedToRef(val.slicePtr(zcu).toIntern()); } @@ -30229,7 +30228,7 @@ fn analyzeOptionalSlicePtr( const slice_ty = opt_slice_ty.optionalChild(zcu); const result_ty = slice_ty.slicePtrFieldType(zcu); - if (try sema.resolveValue(opt_slice)) |opt_val| { + if (sema.resolveValue(opt_slice)) |opt_val| { if (opt_val.isUndef(zcu)) return pt.undefRef(result_ty); const slice_ptr: InternPool.Index = if (opt_val.optionalValue(zcu)) |val| val.slicePtr(zcu).toIntern() @@ -30253,7 +30252,7 @@ fn analyzeSliceLen( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - if (try sema.resolveValue(slice_inst)) |slice_val| { + if (sema.resolveValue(slice_inst)) |slice_val| { if (slice_val.isUndef(zcu)) { return .undef_usize; } @@ -30272,7 +30271,7 @@ fn analyzeIsNull( const pt = sema.pt; const zcu = pt.zcu; const result_ty: Type = .bool; - if (try sema.resolveValue(operand)) |opt_val| { + if (sema.resolveValue(operand)) |opt_val| { if (opt_val.isUndef(zcu)) { return pt.undefRef(result_ty); } @@ -30306,7 +30305,7 @@ fn resolvePtrIsNonErrVal( } assert(child_ty.zigTypeTag(zcu) == .error_union); - if (try sema.resolveValue(operand)) |eu_ptr_val| { + if (sema.resolveValue(operand)) |eu_ptr_val| { if (eu_ptr_val.isUndef(zcu)) return .undef_bool; if (try sema.pointerDeref(block, src, eu_ptr_val, ptr_ty)) |err_union| { if (err_union.isUndef(zcu)) return .undef_bool; @@ -30329,7 +30328,7 @@ fn resolveIsNonErrVal( } assert(sema.typeOf(operand).zigTypeTag(zcu) == .error_union); - if (try sema.resolveValue(operand)) |err_union| { + if (sema.resolveValue(operand)) |err_union| { if (err_union.isUndef(zcu)) return .undef_bool; return .makeBool(err_union.getErrorName(zcu) == .none); } @@ -30681,7 +30680,7 @@ fn analyzeSlice( break :end try sema.coerce(block, .usize, uncasted_end, end_src); } else try sema.coerce(block, .usize, uncasted_end_opt, end_src); if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| { - if (try sema.resolveValue(ptr_or_slice)) |slice_val| { + if (sema.resolveValue(ptr_or_slice)) |slice_val| { if (slice_val.isUndef(zcu)) { return sema.fail(block, src, "slice of undefined", .{}); } @@ -30803,7 +30802,7 @@ fn analyzeSlice( ); } checked_start_lte_end = true; - if (try sema.resolveValue(new_ptr)) |ptr_val| sentinel_check: { + if (sema.resolveValue(new_ptr)) |ptr_val| sentinel_check: { const expected_sentinel = sentinel orelse break :sentinel_check; const start_int = start_val.toUnsignedInt(zcu); const end_int = end_val.toUnsignedInt(zcu); @@ -30887,7 +30886,7 @@ fn analyzeSlice( }, }); - const opt_new_ptr_val = try sema.resolveValue(new_ptr); + const opt_new_ptr_val = sema.resolveValue(new_ptr); const new_ptr_val = opt_new_ptr_val orelse { const result = try block.addBitCast(return_ty, new_ptr); if (block.wantSafety()) { @@ -31034,8 +31033,8 @@ fn cmpNumeric( else uncasted_rhs; - const maybe_lhs_val = try sema.resolveValue(lhs); - const maybe_rhs_val = try sema.resolveValue(rhs); + const maybe_lhs_val = sema.resolveValue(lhs); + const maybe_rhs_val = sema.resolveValue(rhs); // If the LHS is const, check if there is a guaranteed result which does not depend on ths RHS value. if (maybe_lhs_val) |lhs_val| { @@ -31320,8 +31319,8 @@ fn cmpVector( .child = .bool_type, }); - const maybe_lhs_val = try sema.resolveValue(casted_lhs); - const maybe_rhs_val = try sema.resolveValue(casted_rhs); + const maybe_lhs_val = sema.resolveValue(casted_lhs); + const maybe_rhs_val = sema.resolveValue(casted_rhs); if (maybe_lhs_val) |v| if (v.isUndef(zcu)) return pt.undefRef(result_ty); if (maybe_rhs_val) |v| if (v.isUndef(zcu)) return pt.undefRef(result_ty); @@ -31343,7 +31342,7 @@ fn wrapOptional( inst: Air.Inst.Ref, inst_src: LazySrcLoc, ) !Air.Inst.Ref { - if (try sema.resolveValue(inst)) |val| { + if (sema.resolveValue(inst)) |val| { return Air.internedToRef((try sema.pt.intern(.{ .opt = .{ .ty = dest_ty.toIntern(), .val = val.toIntern(), @@ -31365,7 +31364,7 @@ fn wrapErrorUnionPayload( const zcu = pt.zcu; const dest_payload_ty = dest_ty.errorUnionPayload(zcu); const coerced = try sema.coerceExtra(block, dest_payload_ty, inst, inst_src, .{ .report_err = false }); - if (try sema.resolveValue(coerced)) |val| { + if (sema.resolveValue(coerced)) |val| { return Air.internedToRef((try pt.intern(.{ .error_union = .{ .ty = dest_ty.toIntern(), .val = .{ .payload = val.toIntern() }, @@ -31387,7 +31386,7 @@ fn wrapErrorUnionSet( const ip = &zcu.intern_pool; const inst_ty = sema.typeOf(inst); const dest_err_set_ty = dest_ty.errorUnionSet(zcu); - if (try sema.resolveValue(inst)) |val| { + if (sema.resolveValue(inst)) |val| { const expected_name = zcu.intern_pool.indexToKey(val.toIntern()).err.name; switch (dest_err_set_ty.toIntern()) { .anyerror_type => {}, @@ -31449,7 +31448,7 @@ fn unionToTag( const pt = sema.pt; const zcu = pt.zcu; if (try enum_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); - if (try sema.resolveValue(un)) |un_val| { + if (sema.resolveValue(un)) |un_val| { const tag_val = un_val.unionTag(zcu).?; if (tag_val.isUndef(zcu)) return try pt.undefRef(enum_ty); @@ -31796,7 +31795,7 @@ fn resolvePeerTypes( for (instructions, peer_tys, peer_vals) |inst, *ty, *val| { ty.* = sema.typeOf(inst); - val.* = try sema.resolveValue(inst); + val.* = sema.resolveValue(inst); } switch (try sema.resolvePeerTypesInner(block, src, peer_tys, peer_vals)) { @@ -32863,7 +32862,7 @@ fn resolvePeerTypesInner( }, else => |e| return e, }; - const coerced_val = (try sema.resolveValue(coerced_inst)) orelse continue; + const coerced_val = sema.resolveValue(coerced_inst) orelse continue; const existing = comptime_val orelse { comptime_val = coerced_val; continue; @@ -33225,7 +33224,7 @@ fn isComptimeKnown( sema: *Sema, inst: Air.Inst.Ref, ) !bool { - return (try sema.resolveValue(inst)) != null; + return sema.resolveValue(inst) != null; } /// Asserts that the layout of `var_type` has already been resolved. @@ -33275,7 +33274,7 @@ fn resolveAddressSpace( zir_ref: Zir.Inst.Ref, ctx: std.Target.AddressSpaceContext, ) !std.builtin.AddressSpace { - const air_ref = try sema.resolveInst(zir_ref); + const air_ref = sema.resolveInst(zir_ref); return sema.analyzeAsAddressSpace(block, src, air_ref, ctx); } @@ -34305,7 +34304,7 @@ fn setTypeName( // If not then this is a struct type being returned from a non-generic // function and the name doesn't matter since it will later // result in a compile error. - const arg_val = try sema.resolveValue(arg) orelse { + const arg_val = sema.resolveValue(arg) orelse { continue :strat .anon; }; -- 2.54.0 From 334189ce6d20d6d1100f115252d5589fadb064b1 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Tue, 27 Jan 2026 11:46:48 +0000 Subject: [PATCH 07/79] compiler: simplify IESes It is always a bug in Sema to check whether an IES is resolved. This is because whether the IES is resolved depends on whether the function which owns it has been analyzed yet, which depends on the order the compiler analyzes declarations in, which it is incorrect to have any dependency on. Instead, we must always either not look at the resolved set, or resolve it first (with `Sema.ensureFuncIesResolved`) and then look at the definitely-resolved concrete error set. Luckily, removing a bunch of the buggy logic which tried to opportunistically use already-resolved inferred error sets actually didn't regress anything! It seems this logic was mostly left over from before Andrew reworked inferred error sets, and had become essentially dead code. This is because inferred error sets are stricter than they used to be, and in particular, we make no attempt to support mutual recursion. I suspect that most of the logic touching IESes can be simplified even further than I have done here without regressing any existing code; my goal in this commit was just to remove any *buggy* code I could find. --- src/Sema.zig | 560 ++++++++++++++--------------------- src/Sema/type_resolution.zig | 10 +- src/Type.zig | 11 +- src/Value.zig | 4 +- src/Zcu.zig | 27 +- 5 files changed, 232 insertions(+), 380 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 09c974fb256e4709030a8e6540e468140af8131c..2fffe8ae546af74951980c583506ba82647b0d60 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -7870,21 +7870,21 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr return .anyerror_type; } - if (ip.isInferredErrorSetType(lhs_ty.toIntern())) { - switch (try sema.resolveInferredErrorSet(block, src, lhs_ty.toIntern())) { - // isAnyError might have changed from a false negative to a true - // positive after resolution. - .anyerror_type => return .anyerror_type, - else => {}, - } + switch (ip.indexToKey(lhs_ty.toIntern())) { + .inferred_error_set_type => |func_index| { + try sema.ensureFuncIesResolved(block, src, func_index); + if (ip.funcIesResolvedUnordered(func_index) == .anyerror_type) return .anyerror_type; + }, + .error_set_type => {}, + else => unreachable, } - if (ip.isInferredErrorSetType(rhs_ty.toIntern())) { - switch (try sema.resolveInferredErrorSet(block, src, rhs_ty.toIntern())) { - // isAnyError might have changed from a false negative to a true - // positive after resolution. - .anyerror_type => return .anyerror_type, - else => {}, - } + switch (ip.indexToKey(rhs_ty.toIntern())) { + .inferred_error_set_type => |func_index| { + try sema.ensureFuncIesResolved(block, src, func_index); + if (ip.funcIesResolvedUnordered(func_index) == .anyerror_type) return .anyerror_type; + }, + .error_set_type => {}, + else => unreachable, } const err_set_ty = try sema.errorSetMerge(lhs_ty, rhs_ty); @@ -12000,7 +12000,7 @@ fn wantSwitchProngBodyAnalysis( if (err_set and prong_is_comptime_unreach) { const item_val = sema.resolveConstDefinedValue(block, .unneeded, item_ref, undefined) catch unreachable; const err_name = item_val.getErrorName(zcu).unwrap().?; - if (!Type.errorSetHasFieldIp(&zcu.intern_pool, operand_ty.toIntern(), err_name)) return false; + if (!operand_ty.errorSetHasField(err_name, zcu)) return false; } return true; } @@ -21023,34 +21023,61 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData else => unreachable, }; - const disjoint = disjoint: { - // Try avoiding resolving inferred error sets if we can - if (!dest_err_ty.isAnyError(zcu) and dest_err_ty.errorSetIsEmpty(zcu)) break :disjoint true; - if (!operand_err_ty.isAnyError(zcu) and operand_err_ty.errorSetIsEmpty(zcu)) break :disjoint true; - if (dest_err_ty.isAnyError(zcu)) break :disjoint false; - if (operand_err_ty.isAnyError(zcu)) break :disjoint false; - const dest_err_names = dest_err_ty.errorSetNames(zcu); - for (0..dest_err_names.len) |dest_err_index| { - if (Type.errorSetHasFieldIp(ip, operand_err_ty.toIntern(), dest_err_names.get(ip)[dest_err_index])) - break :disjoint false; - } + switch (ip.indexToKey(operand_err_ty.toIntern())) { + .inferred_error_set_type => |func| try sema.ensureFuncIesResolved(block, src, func), + else => {}, + } - if (!ip.isInferredErrorSetType(dest_err_ty.toIntern()) and - !ip.isInferredErrorSetType(operand_err_ty.toIntern())) - { - break :disjoint true; - } - - _ = try sema.resolveInferredErrorSetTy(block, src, dest_err_ty.toIntern()); - _ = try sema.resolveInferredErrorSetTy(block, operand_src, operand_err_ty.toIntern()); - for (0..dest_err_names.len) |dest_err_index| { - if (Type.errorSetHasFieldIp(ip, operand_err_ty.toIntern(), dest_err_names.get(ip)[dest_err_index])) - break :disjoint false; - } - - break :disjoint true; + const result: enum { + /// The operand and destination error sets are disjoint, i.e. have no errors in common. + disjoint, + /// The destination error set is a superset of the operand error set, so the operation is + /// effectively equivalent to a coercion. + superset, + /// The operand and destination error sets have *some* errors in common, but the destination + /// is not a superset of the operand, so a safety check may be needed. + overlap, + } = if (operand_err_ty.errorSetIsEmpty(zcu)) res: { + break :res .disjoint; + } else check: switch (dest_err_ty.toIntern()) { + .anyerror_type => .superset, + .adhoc_inferred_error_set_type => { + // `@errorCast` to this function's own error set. + try sema.fn_ret_ty_ies.?.addErrorSet(operand_err_ty, ip, sema.arena); + break :check .superset; + }, + else => |err_set_ty| switch (ip.indexToKey(err_set_ty)) { + .inferred_error_set_type => |func_index| { + if (sema.fn_ret_ty_ies) |dst_ies| { + if (dst_ies.func == func_index) { + // `@errorCast` to this function's own error set. + try sema.fn_ret_ty_ies.?.addErrorSet(operand_err_ty, ip, sema.arena); + break :check .superset; + } + } + try sema.ensureFuncIesResolved(block, src, func_index); + continue :check ip.funcIesResolvedUnordered(func_index); + }, + .error_set_type => |dest| { + if (operand_err_ty.isAnyError(zcu)) break :check .superset; + var dest_has_all = true; + var dest_has_any = false; + for (operand_err_ty.errorSetNames(zcu).get(ip)) |operand_err_name| { + if (dest.nameIndex(ip, operand_err_name) != null) { + dest_has_any = true; + } else { + dest_has_all = false; + } + } + if (!dest_has_any) break :check .disjoint; + if (dest_has_all) break :check .superset; + break :check .overlap; + }, + else => unreachable, + }, }; - if (disjoint and !(operand_tag == .error_union and dest_tag == .error_union)) { + + if (result == .disjoint and !(operand_tag == .error_union and dest_tag == .error_union)) { return sema.fail(block, src, "error sets '{f}' and '{f}' have no common errors", .{ operand_err_ty.fmt(pt), dest_err_ty.fmt(pt), }); @@ -21058,25 +21085,30 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData // operand must be defined since it can be an invalid error value if (try sema.resolveDefinedValue(block, operand_src, operand)) |operand_val| { - const err_name: InternPool.NullTerminatedString = switch (operand_tag) { - .error_set => ip.indexToKey(operand_val.toIntern()).err.name, - .error_union => switch (ip.indexToKey(operand_val.toIntern()).error_union.val) { + const err_name: InternPool.NullTerminatedString = switch (ip.indexToKey(operand_val.toIntern())) { + .err => |err| err.name, + .error_union => |eu| switch (eu.val) { .err_name => |name| name, .payload => |payload_val| { assert(dest_tag == .error_union); // should be guaranteed from the type checks above - return sema.coerce(block, dest_ty, Air.internedToRef(payload_val), operand_src); + const dest_payload_ty = dest_ty.errorUnionPayload(zcu); + const coerced_payload = try sema.coerce(block, dest_payload_ty, .fromIntern(payload_val), operand_src); + return sema.wrapErrorUnionPayload(block, dest_ty, coerced_payload, operand_src) catch |err| switch (err) { + error.NotCoercible => unreachable, + else => |e| return e, + }; }, }, else => unreachable, }; - if (!dest_err_ty.isAnyError(zcu) and !Type.errorSetHasFieldIp(ip, dest_err_ty.toIntern(), err_name)) { + if (!dest_err_ty.isAnyError(zcu) and !dest_err_ty.errorSetHasField(err_name, zcu)) { return sema.fail(block, src, "'error.{f}' not a member of error set '{f}'", .{ err_name.fmt(ip), dest_err_ty.fmt(pt), }); } - return Air.internedToRef(try pt.intern(switch (dest_tag) { + return .fromIntern(try pt.intern(switch (dest_tag) { .error_set => .{ .err = .{ .ty = dest_ty.toIntern(), .name = err_name, @@ -21090,21 +21122,17 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData } const err_int_ty = try pt.errorIntType(); - if (block.wantSafety() and !dest_err_ty.isAnyError(zcu) and - dest_err_ty.toIntern() != .adhoc_inferred_error_set_type and - zcu.backendSupportsFeature(.error_set_has_value)) - { + if (block.wantSafety() and result != .superset and zcu.backendSupportsFeature(.error_set_has_value)) { const err_code_inst = switch (operand_tag) { .error_set => operand, .error_union => try block.addTyOp(.unwrap_errunion_err, operand_err_ty, operand), else => unreachable, }; const err_int_inst = try block.addBitCast(err_int_ty, err_code_inst); - if (dest_tag == .error_union) { const zero_err = try pt.intRef(err_int_ty, 0); const is_zero = try block.addBinOp(.cmp_eq, err_int_inst, zero_err); - if (disjoint) { + if (result == .disjoint) { // Error must be zero. try sema.addSafetyCheck(block, src, is_zero, .invalid_error_code); } else { @@ -25599,31 +25627,28 @@ fn fieldVal( switch (child_type.zigTypeTag(zcu)) { .error_set => { - switch (ip.indexToKey(child_type.toIntern())) { - .error_set_type => |error_set_type| blk: { - if (error_set_type.nameIndex(ip, field_name) != null) break :blk; + const err_set_ty: Type = err_set: switch (ip.indexToKey(child_type.toIntern())) { + .inferred_error_set_type => |func_index| { + try sema.ensureFuncIesResolved(block, src, func_index); + const resolved_ies = ip.funcIesResolvedUnordered(func_index); + continue :err_set ip.indexToKey(resolved_ies); + }, + .error_set_type => |err_set| if (err_set.nameIndex(ip, field_name) == null) { return sema.fail(block, src, "no error named '{f}' in '{f}'", .{ field_name.fmt(ip), child_type.fmt(pt), }); - }, - .inferred_error_set_type => { - return sema.fail(block, src, "TODO handle inferred error sets here", .{}); - }, + } else child_type, .simple_type => |t| { assert(t == .anyerror); _ = try pt.getErrorValue(field_name); + break :err_set try pt.singleErrorSetType(field_name); }, else => unreachable, - } - - const error_set_type = if (!child_type.isAnyError(zcu)) - child_type - else - try pt.singleErrorSetType(field_name); - return Air.internedToRef((try pt.intern(.{ .err = .{ - .ty = error_set_type.toIntern(), + }; + return .fromIntern(try pt.intern(.{ .err = .{ + .ty = err_set_ty.toIntern(), .name = field_name, - } }))); + } })); }, .@"union" => { if (try sema.namespaceLookupVal(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { @@ -25832,31 +25857,26 @@ fn fieldPtr( switch (child_type.zigTypeTag(zcu)) { .error_set => { - switch (ip.indexToKey(child_type.toIntern())) { - .error_set_type => |error_set_type| blk: { - if (error_set_type.nameIndex(ip, field_name) != null) { - break :blk; - } + const err_set_ty: Type = err_set: switch (ip.indexToKey(child_type.toIntern())) { + .inferred_error_set_type => |func_index| { + try sema.ensureFuncIesResolved(block, src, func_index); + const resolved_ies = ip.funcIesResolvedUnordered(func_index); + continue :err_set ip.indexToKey(resolved_ies); + }, + .error_set_type => |err_set| if (err_set.nameIndex(ip, field_name) == null) { return sema.fail(block, src, "no error named '{f}' in '{f}'", .{ field_name.fmt(ip), child_type.fmt(pt), }); - }, - .inferred_error_set_type => { - return sema.fail(block, src, "TODO handle inferred error sets here", .{}); - }, + } else child_type, .simple_type => |t| { assert(t == .anyerror); _ = try pt.getErrorValue(field_name); + break :err_set try pt.singleErrorSetType(field_name); }, else => unreachable, - } - - const error_set_type = if (!child_type.isAnyError(zcu)) - child_type - else - try pt.singleErrorSetType(field_name); + }; return uavRef(sema, try pt.intern(.{ .err = .{ - .ty = error_set_type.toIntern(), + .ty = err_set_ty.toIntern(), .name = field_name, } })); }, @@ -27760,23 +27780,27 @@ fn coerceExtra( else => {}, }, .error_union => switch (inst_ty.zigTypeTag(zcu)) { - .error_set => { - // E to E!T - return sema.wrapErrorUnionSet(block, dest_ty, inst, inst_src); + // E to E!T + .error_set => if (sema.wrapErrorUnionSet(block, dest_ty, inst, inst_src)) |res| { + return res; + } else |err| switch (err) { + error.NotCoercible => if (in_memory_result == .no_match) { + // Try to give more useful notes + const err_set_type = dest_ty.errorUnionSet(zcu); + in_memory_result = try sema.coerceInMemoryAllowed(block, err_set_type, inst_ty, false, target, dest_ty_src, inst_src, maybe_inst_val); + }, + else => |e| return e, }, - else => eu: { - // T to E!T - return sema.wrapErrorUnionPayload(block, dest_ty, inst, inst_src) catch |err| switch (err) { - error.NotCoercible => { - if (in_memory_result == .no_match) { - const payload_type = dest_ty.errorUnionPayload(zcu); - // Try to give more useful notes - in_memory_result = try sema.coerceInMemoryAllowed(block, payload_type, inst_ty, false, target, dest_ty_src, inst_src, maybe_inst_val); - } - break :eu; - }, - else => |e| return e, - }; + // T to E!T + else => if (sema.wrapErrorUnionPayload(block, dest_ty, inst, inst_src)) |res| { + return res; + } else |err| switch (err) { + error.NotCoercible => if (in_memory_result == .no_match) { + // Try to give more useful notes + const payload_type = dest_ty.errorUnionPayload(zcu); + in_memory_result = try sema.coerceInMemoryAllowed(block, payload_type, inst_ty, false, target, dest_ty_src, inst_src, maybe_inst_val); + }, + else => |e| return e, }, }, .@"union" => switch (inst_ty.zigTypeTag(zcu)) { @@ -28542,89 +28566,62 @@ fn coerceInMemoryAllowedErrorSets( const gpa = sema.gpa; const ip = &zcu.intern_pool; - // Coercion to `anyerror`. Note that this check can return false negatives - // in case the error sets did not get resolved. - if (dest_ty.isAnyError(zcu)) { - return .ok; - } - - if (dest_ty.toIntern() == .adhoc_inferred_error_set_type) { - // We are trying to coerce an error set to the current function's - // inferred error set. - const dst_ies = sema.fn_ret_ty_ies.?; - try dst_ies.addErrorSet(src_ty, ip, sema.arena); - return .ok; - } - - if (ip.isInferredErrorSetType(dest_ty.toIntern())) { - const dst_ies_func_index = ip.iesFuncIndex(dest_ty.toIntern()); - if (sema.fn_ret_ty_ies) |dst_ies| { - if (dst_ies.func == dst_ies_func_index) { - // We are trying to coerce an error set to the current function's - // inferred error set. - try dst_ies.addErrorSet(src_ty, ip, sema.arena); - return .ok; - } - } - switch (try sema.resolveInferredErrorSet(block, dest_src, dest_ty.toIntern())) { - // isAnyError might have changed from a false negative to a true - // positive after resolution. - .anyerror_type => return .ok, - else => {}, - } - } - - var missing_error_buf = std.array_list.Managed(InternPool.NullTerminatedString).init(gpa); - defer missing_error_buf.deinit(); - - switch (src_ty.toIntern()) { - .anyerror_type => switch (ip.indexToKey(dest_ty.toIntern())) { - .simple_type => unreachable, // filtered out above - .error_set_type, .inferred_error_set_type => return .from_anyerror, - else => unreachable, + const dest_set: InternPool.Key.ErrorSetType = err_set: switch (dest_ty.toIntern()) { + .anyerror_type => return .ok, + .adhoc_inferred_error_set_type => { + // We are trying to coerce an error set to the current function's + // inferred error set. + const dst_ies = sema.fn_ret_ty_ies.?; + try dst_ies.addErrorSet(src_ty, ip, sema.arena); + return .ok; }, - - else => switch (ip.indexToKey(src_ty.toIntern())) { - .inferred_error_set_type => { - const resolved_src_ty = try sema.resolveInferredErrorSet(block, src_src, src_ty.toIntern()); - // src anyerror status might have changed after the resolution. - if (resolved_src_ty == .anyerror_type) { - // dest_ty.isAnyError(zcu) == true is already checked for at this point. - return .from_anyerror; - } - - for (ip.indexToKey(resolved_src_ty).error_set_type.names.get(ip)) |key| { - if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), key)) { - try missing_error_buf.append(key); + else => |err_set_ty| switch (ip.indexToKey(err_set_ty)) { + .inferred_error_set_type => |func_index| { + if (sema.fn_ret_ty_ies) |dst_ies| { + if (dst_ies.func == func_index) { + // We are trying to coerce an error set to the current function's + // inferred error set. + try dst_ies.addErrorSet(src_ty, ip, sema.arena); + return .ok; } } - - if (missing_error_buf.items.len != 0) { - return InMemoryCoercionResult{ - .missing_error = try sema.arena.dupe(InternPool.NullTerminatedString, missing_error_buf.items), - }; - } - - return .ok; + try sema.ensureFuncIesResolved(block, dest_src, func_index); + continue :err_set ip.funcIesResolvedUnordered(func_index); }, - .error_set_type => |error_set_type| { - for (error_set_type.names.get(ip)) |name| { - if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), name)) { - try missing_error_buf.append(name); - } - } - - if (missing_error_buf.items.len != 0) { - return InMemoryCoercionResult{ - .missing_error = try sema.arena.dupe(InternPool.NullTerminatedString, missing_error_buf.items), - }; - } - - return .ok; + .error_set_type => |err_set| err_set, + else => unreachable, + }, + }; + + const src_names: InternPool.NullTerminatedString.Slice = err_set: switch (src_ty.toIntern()) { + .anyerror_type => return .from_anyerror, + else => |err_set_ty| switch (ip.indexToKey(err_set_ty)) { + .inferred_error_set_type => |func_index| { + try sema.ensureFuncIesResolved(block, src_src, func_index); + continue :err_set ip.funcIesResolvedUnordered(func_index); }, + .error_set_type => |err_set| err_set.names, else => unreachable, }, + }; + + var missing_error_buf: std.ArrayList(InternPool.NullTerminatedString) = .empty; + defer missing_error_buf.deinit(gpa); + + for (src_names.get(ip)) |name| { + if (dest_set.nameIndex(ip, name) == null) { + try missing_error_buf.append(gpa, name); + } } + + if (missing_error_buf.items.len != 0) { + return .{ .missing_error = try sema.arena.dupe( + InternPool.NullTerminatedString, + missing_error_buf.items, + ) }; + } + + return .ok; } fn coerceInMemoryAllowedFns( @@ -30357,76 +30354,34 @@ fn resolveIsNonErrFromType( // exception if the error union error set is known to be empty, // we allow the comparison but always make it comptime-known. - const set_ty = ip.errorUnionSet(operand_ty.toIntern()); - switch (set_ty) { - .anyerror_type => {}, - .adhoc_inferred_error_set_type => if (sema.fn_ret_ty_ies) |ies| blk: { - // If the error set is empty, we must return a comptime true or false. - // However we want to avoid unnecessarily resolving an inferred error set - // in case it is already non-empty. - switch (ies.resolved) { - .anyerror_type => break :blk, - .none => {}, - else => |i| if (ip.indexToKey(i).error_set_type.names.len != 0) break :blk, - } - - if (ies.errors.count() != 0) return null; - switch (ies.resolved) { - .anyerror_type => return null, - .none => {}, - else => switch (ip.indexToKey(ies.resolved).error_set_type.names.len) { - 0 => return .true, - else => return null, - }, - } - // We do not have a comptime answer because this inferred error - // set is not resolved, and an instruction later in this function - // body may or may not cause an error to be added to this set. - return null; + return err_set: switch (ip.errorUnionSet(operand_ty.toIntern())) { + .anyerror_type => null, + .adhoc_inferred_error_set_type => { + // This is *our* error set; that is, we're currently analyzing the function + // which owns it. Trying to resolve it now would cause a dependency loop. + // Instead, accept that we don't know. + if (true) return null; }, - else => switch (ip.indexToKey(set_ty)) { - .error_set_type => |error_set_type| { - if (error_set_type.names.len == 0) return .true; + else => |set_ty| switch (ip.indexToKey(set_ty)) { + .error_set_type => |error_set_type| switch (error_set_type.names.len) { + 0 => .true, + else => null, }, - .inferred_error_set_type => |func_index| blk: { - // If the error set is empty, we must return a comptime true or false. - // However we want to avoid unnecessarily resolving an inferred error set - // in case it is already non-empty. - try zcu.maybeUnresolveIes(func_index); - switch (ip.funcIesResolvedUnordered(func_index)) { - .anyerror_type => break :blk, - .none => {}, - else => |i| if (ip.indexToKey(i).error_set_type.names.len != 0) break :blk, - } + .inferred_error_set_type => |func_index| { if (sema.fn_ret_ty_ies) |ies| { if (ies.func == func_index) { - // Try to avoid resolving inferred error set if possible. - if (ies.errors.count() != 0) return null; - switch (ies.resolved) { - .anyerror_type => return null, - .none => {}, - else => switch (ip.indexToKey(ies.resolved).error_set_type.names.len) { - 0 => return .true, - else => return null, - }, - } - // We do not have a comptime answer because this inferred error - // set is not resolved, and an instruction later in this function - // body may or may not cause an error to be added to this set. + // This is *our* error set; that is, we're currently analyzing the function + // which owns it. Trying to resolve it now would cause a dependency loop. + // Instead, accept that we don't know. return null; } } - const resolved_ty = try sema.resolveInferredErrorSet(block, src, set_ty); - if (resolved_ty == .anyerror_type) - break :blk; - if (ip.indexToKey(resolved_ty).error_set_type.names.len == 0) - return .true; + try sema.ensureFuncIesResolved(block, src, func_index); + continue :err_set ip.funcIesResolvedUnordered(func_index); }, else => unreachable, }, - } - - return null; + }; } fn analyzeIsNonErr( @@ -31384,58 +31339,16 @@ fn wrapErrorUnionSet( const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; - const inst_ty = sema.typeOf(inst); const dest_err_set_ty = dest_ty.errorUnionSet(zcu); - if (sema.resolveValue(inst)) |val| { - const expected_name = zcu.intern_pool.indexToKey(val.toIntern()).err.name; - switch (dest_err_set_ty.toIntern()) { - .anyerror_type => {}, - .adhoc_inferred_error_set_type => ok: { - const ies = sema.fn_ret_ty_ies.?; - switch (ies.resolved) { - .anyerror_type => break :ok, - .none => if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) { - break :ok; - }, - else => |i| if (ip.indexToKey(i).error_set_type.nameIndex(ip, expected_name) != null) { - break :ok; - }, - } - return sema.failWithTypeMismatch(block, inst_src, dest_err_set_ty, inst_ty); - }, - else => switch (ip.indexToKey(dest_err_set_ty.toIntern())) { - .error_set_type => |error_set_type| ok: { - if (error_set_type.nameIndex(ip, expected_name) != null) break :ok; - return sema.failWithTypeMismatch(block, inst_src, dest_err_set_ty, inst_ty); - }, - .inferred_error_set_type => |func_index| ok: { - // We carefully do this in an order that avoids unnecessarily - // resolving the destination error set type. - try zcu.maybeUnresolveIes(func_index); - switch (ip.funcIesResolvedUnordered(func_index)) { - .anyerror_type => break :ok, - .none => if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) { - break :ok; - }, - else => |i| if (ip.indexToKey(i).error_set_type.nameIndex(ip, expected_name) != null) { - break :ok; - }, - } - - return sema.failWithTypeMismatch(block, inst_src, dest_err_set_ty, inst_ty); - }, - else => unreachable, - }, - } - return Air.internedToRef((try pt.intern(.{ .error_union = .{ + const coerced = try sema.coerceExtra(block, dest_err_set_ty, inst, inst_src, .{ .report_err = false }); + if (try sema.resolveDefinedValue(block, inst_src, coerced)) |error_val| { + return .fromIntern(try pt.intern(.{ .error_union = .{ .ty = dest_ty.toIntern(), - .val = .{ .err_name = expected_name }, - } }))); + .val = .{ .err_name = ip.indexToKey(error_val.toIntern()).err.name }, + } })); + } else { + return block.addTyOp(.wrap_errunion_err, dest_ty, coerced); } - - try sema.requireRuntimeBlock(block, inst_src, null); - const coerced = try sema.coerce(block, dest_err_set_ty, inst, inst_src); - return block.addTyOp(.wrap_errunion_err, dest_ty, coerced); } fn unionToTag( @@ -32969,18 +32882,6 @@ fn typeIsArrayLike(sema: *Sema, ty: Type) ?ArrayLike { }; } -pub fn resolveIes(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError!void { - const pt = sema.pt; - const zcu = pt.zcu; - const ip = &zcu.intern_pool; - - if (sema.fn_ret_ty_ies) |ies| { - try sema.resolveInferredErrorSetPtr(block, src, ies); - assert(ies.resolved != .none); - ip.funcIesResolved(sema.func_index).* = ies.resolved; - } -} - fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { const pt = sema.pt; if (!ty.isIndexable(pt.zcu)) { @@ -33017,63 +32918,31 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void return sema.failWithOwnedErrorMsg(block, msg); } -/// Returns a normal error set corresponding to the fully populated inferred -/// error set. -fn resolveInferredErrorSet( +/// Resolves the inferred error set of the given function, so that the corresponding concrete error +/// set is available by calling `InternPool.funcIesResolvedUnordered` on `func_index`. +/// +/// Asserts that `func_index` is a function. Also asserts that it is not a coerced function, because +/// coerced functions do not own inferred error sets. +fn ensureFuncIesResolved( sema: *Sema, block: *Block, src: LazySrcLoc, - ies_index: InternPool.Index, -) CompileError!InternPool.Index { + func_index: InternPool.Index, +) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; - const func_index = ip.iesFuncIndex(ies_index); - const func = zcu.funcInfo(func_index); + + assert(ip.unwrapCoercedFunc(func_index) == func_index); try sema.declareDependency(.{ .func_ies = func_index }); - - // MLUGG TODO: this feels kinda bad now... instead check for outdated whenver we grab this? - try zcu.maybeUnresolveIes(func_index); - const resolved_ty = func.resolvedErrorSetUnordered(ip); - if (resolved_ty != .none) return resolved_ty; + try sema.addReferenceEntry(block, src, .wrap(.{ .func = func_index })); if (zcu.analysis_in_progress.contains(.wrap(.{ .func = func_index }))) { return sema.fail(block, src, "unable to resolve inferred error set", .{}); } - // In order to ensure that all dependencies are properly added to the set, - // we need to ensure the function body is analyzed of the inferred error - // set. However, in the case of comptime/inline function calls with - // inferred error sets, each call gets an adhoc InferredErrorSet object, which - // has no corresponding function body. - const ies_func_info = zcu.typeToFunc(.fromInterned(func.ty)).?; - // if ies declared by a inline function with generic return type, the return_type should be generic_poison, - // because inline function does not create a new declaration, and the ies has been filled with analyzeCall, - // so here we can simply skip this case. - if (ies_func_info.return_type == .generic_poison_type) { - assert(ies_func_info.cc == .@"inline"); - } else if (ip.errorUnionSet(ies_func_info.return_type) == ies_index) { - if (!Type.fromInterned(func.ty).fnHasRuntimeBits(zcu)) { - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(src, "unable to resolve inferred error set of generic function", .{}); - errdefer msg.destroy(sema.gpa); - try sema.errNote(zcu.navSrcLoc(func.owner_nav), msg, "generic function declared here", .{}); - break :msg msg; - }); - } - // In this case we are dealing with the actual InferredErrorSet object that - // corresponds to the function, not one created to track an inline/comptime call. - const orig_func_index = ip.unwrapCoercedFunc(func_index); - try sema.addReferenceEntry(block, src, .wrap(.{ .func = orig_func_index })); - try pt.ensureFuncBodyUpToDate(orig_func_index); - } - - // This will now have been resolved by the logic at the end of `Zcu.analyzeFnBody` - // which calls `resolveInferredErrorSetPtr`. - const final_resolved_ty = func.resolvedErrorSetUnordered(ip); - assert(final_resolved_ty != .none); - return final_resolved_ty; + try pt.ensureFuncBodyUpToDate(func_index); } pub fn resolveInferredErrorSetPtr( @@ -33091,7 +32960,9 @@ pub fn resolveInferredErrorSetPtr( for (ies.inferred_error_sets.keys()) |other_ies_index| { if (ies_index == other_ies_index) continue; - switch (try sema.resolveInferredErrorSet(block, src, other_ies_index)) { + const other_func_index = ip.iesFuncIndex(other_ies_index); + try sema.ensureFuncIesResolved(block, src, other_func_index); + switch (ip.funcIesResolvedUnordered(other_func_index)) { .anyerror_type => { ies.resolved = .anyerror_type; return; @@ -33164,7 +33035,10 @@ fn resolveInferredErrorSetTy( if (ty == .anyerror_type) return ty; switch (ip.indexToKey(ty)) { .error_set_type => return ty, - .inferred_error_set_type => return sema.resolveInferredErrorSet(block, src, ty), + .inferred_error_set_type => |func_index| { + try sema.ensureFuncIesResolved(block, src, func_index); + return ip.funcIesResolvedUnordered(func_index); + }, else => unreachable, } } diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig index f346d217ae2b361af26498ba5a0f86651c1d6a08..f18cf9aaaeae1557d1a69799516d0f7687096dd0 100644 --- a/src/Sema/type_resolution.zig +++ b/src/Sema/type_resolution.zig @@ -132,7 +132,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { .src_base_inst = struct_obj.zir_index, .type_name_ctx = struct_obj.name, }; - defer assert(block.instructions.items.len == 0); + defer block.instructions.deinit(gpa); // There may be old field names in here from a previous update. struct_obj.field_name_map.get(ip).clearRetainingCapacity(); @@ -452,6 +452,8 @@ fn resolvePackedStructLayout( pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; const ip = &zcu.intern_pool; assert(sema.owner.unwrap().struct_defaults == struct_ty.toIntern()); @@ -490,7 +492,7 @@ pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void { .src_base_inst = struct_obj.zir_index, .type_name_ctx = struct_obj.name, }; - defer assert(block.instructions.items.len == 0); + defer block.instructions.deinit(gpa); return resolveStructDefaultsInner(sema, &block, &struct_obj); } @@ -565,7 +567,7 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { .src_base_inst = union_obj.zir_index, .type_name_ctx = union_obj.name, }; - defer assert(block.instructions.items.len == 0); + defer block.instructions.deinit(gpa); // MLUGG TODO: this is fucking ugly bro const explicit_enum_tag_ty: ?Type = if (union_obj.is_reified) ty: { @@ -1011,7 +1013,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void { .src_base_inst = tracked_inst, .type_name_ctx = enum_obj.name, }; - defer assert(block.instructions.items.len == 0); + defer block.instructions.deinit(gpa); // There may be old field names in the map from a previous update. enum_obj.field_name_map.get(ip).clearRetainingCapacity(); diff --git a/src/Type.zig b/src/Type.zig index 111f6347ed2d0f72cd70db20a59dfc806fe140e8..ca94c09bf04fc00503dc414541a0861194cf4256 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -1472,14 +1472,15 @@ pub fn isError(ty: Type, zcu: *const Zcu) bool { /// Returns whether ty, which must be an error set, includes an error `name`. /// Might return a false negative if `ty` is an inferred error set and not fully /// resolved yet. -pub fn errorSetHasFieldIp( - ip: *const InternPool, - ty: InternPool.Index, +pub fn errorSetHasField( + ty: Type, name: InternPool.NullTerminatedString, + zcu: *const Zcu, ) bool { - return switch (ty) { + const ip = &zcu.intern_pool; + return switch (ty.toIntern()) { .anyerror_type => true, - else => switch (ip.indexToKey(ty)) { + else => switch (ip.indexToKey(ty.toIntern())) { .error_set_type => |error_set_type| error_set_type.nameIndex(ip, name) != null, .inferred_error_set_type => |i| switch (ip.funcIesResolvedUnordered(i)) { .anyerror_type => true, diff --git a/src/Value.zig b/src/Value.zig index ca9ef9604627beb12c9014b9372f42eb1aac538a..de7aacd1e1f2c84737acb243aa1565ac5fc0a94b 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -641,9 +641,9 @@ pub fn readFromPackedMemory( .optional => { assert(ty.isPtrLikeOptional(zcu)); const addr = (try readFromPackedMemory(Type.usize, pt, buffer, bit_offset, arena)).toUnsignedInt(zcu); - return Value.fromInterned(try pt.intern(.{ .opt = .{ + return .fromInterned(try pt.intern(.{ .opt = .{ .ty = ty.toIntern(), - .val = (try pt.ptrIntValue(ty.childType(zcu), addr)).toIntern(), + .val = if (addr == 0) .none else (try pt.ptrIntValue(ty.childType(zcu), addr)).toIntern(), } })); }, else => @panic("TODO implement readFromPackedMemory for more types"), diff --git a/src/Zcu.zig b/src/Zcu.zig index 5aef6a11d17d13d43176c782d53b3de4287bc2af..3b17bc1c0981d1e19f57db43412f4b309484faf4 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -4059,6 +4059,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R implicit_tag: { const loaded_union = zcu.typeToUnion(.fromInterned(ty)) orelse break :implicit_tag; const tag_ty = loaded_union.enum_tag_type; + if (tag_ty == .none) break :implicit_tag; if (ip.indexToKey(tag_ty).enum_type != .generated_union_tag) break :implicit_tag; const gop = try types.getOrPut(gpa, tag_ty); if (gop.found_existing) break :implicit_tag; @@ -4383,32 +4384,6 @@ fn formatDependee(data: FormatDependee, writer: *Io.Writer) Io.Writer.Error!void } } -/// Given the `InternPool.Index` of a function, set its resolved IES to `.none` if it -/// may be outdated. `Sema` should do this before ever loading a resolved IES. -pub fn maybeUnresolveIes(zcu: *Zcu, func_index: InternPool.Index) !void { - const unit = AnalUnit.wrap(.{ .func = func_index }); - if (zcu.outdated.contains(unit) or zcu.potentially_outdated.contains(unit)) { - // We're consulting the resolved IES now, but the function is outdated, so its - // IES may have changed. We have to assume the IES is outdated and set the resolved - // set back to `.none`. - // - // This will cause `PerThread.analyzeFnBody` to mark the IES as outdated when it's - // eventually hit. - // - // Since the IES needs to be resolved, the function body will now definitely need - // re-analysis (even if the IES turns out to be the same!), so mark it as - // definitely-outdated if it's only PO. - if (zcu.potentially_outdated.fetchSwapRemove(unit)) |kv| { - const gpa = zcu.gpa; - try zcu.outdated.putNoClobber(gpa, unit, kv.value); - if (kv.value == 0) { - try zcu.outdated_ready.put(gpa, unit, {}); - } - } - zcu.intern_pool.funcSetIesResolved(zcu.comp.io, func_index, .none); - } -} - pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enum) { ok, bad_arch: []const std.Target.Cpu.Arch, // value is allowed archs for cc -- 2.54.0 From 911294116d5df0db3b431f9117f42bf8074a3b83 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Tue, 27 Jan 2026 17:13:14 +0000 Subject: [PATCH 08/79] compiler: make type resolution lazy ...and rework some of the incremental reference tracking. Almost all kinds of AnalUnit have one property in common: they might never be referenced in any update despite conceptually "existing", in which case we don't want to waste time semantically analyzing them. As of the lazy type resolution introduced in this commit, the only units to which this does not apply are `memoized_state` and `@"comptime"`. Previously, I had a somewhat hacky system in `Zcu` for dealing with this, but I now have a better understanding of the design incremental compilation is converging on, so can implement a better solution. By finding a few unused bits lying around (...or making them), we can represent a single bit of state indicating whether something's corresponding units have ever been referenced. This is akin to the units being in `Zcu.outdated`, with the key difference being that the compiler will *not* attempt to analyze units which are in this state. Once they are first referenced or depended on, the flag is set to true and the unit is added to `outdated` so that it can participate in the normal dependency resolution logic. --- src/InternPool.zig | 412 ++++++++++++++++++++++++++++------- src/Sema.zig | 204 ++++++----------- src/Sema/LowerZon.zig | 11 +- src/Sema/bitcast.zig | 6 +- src/Sema/type_resolution.zig | 68 +++--- src/Type.zig | 15 +- src/Value.zig | 2 +- src/Zcu.zig | 97 ++------- src/Zcu/PerThread.zig | 67 ++---- 9 files changed, 515 insertions(+), 367 deletions(-) diff --git a/src/InternPool.zig b/src/InternPool.zig index ce9622e54d57bc0703d9151a5bbd35e3ef57298c..230ef78d63dd4190c712a6b955b5ea594d89ddb6 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -546,6 +546,8 @@ pub const Nav = struct { analysis: ?struct { namespace: NamespaceIndex, zir_index: TrackedInst.Index, + /// Initially `false`. Set to `true` by `setWantNavAnalysis`. + wanted: bool, }, status: union(enum) { /// This `Nav` is pending semantic analysis. @@ -743,7 +745,7 @@ pub const Nav = struct { const Repr = struct { name: NullTerminatedString, fqn: NullTerminatedString, - // The following 1 fields are either both populated, or both `.none`. + // The following 2 fields are either both populated, or both `.none`. analysis_namespace: OptionalNamespaceIndex, analysis_zir_index: TrackedInst.Index.Optional, /// Populated only if `bits.status != .unresolved`. @@ -762,7 +764,7 @@ pub const Nav = struct { @"addrspace": std.builtin.AddressSpace, /// Populated only if `bits.status == .type_resolved`. is_threadlocal: bool, - _: u1 = 0, + want_analysis: bool, }; fn unpack(repr: Repr) Nav { @@ -772,6 +774,7 @@ pub const Nav = struct { .analysis = if (repr.analysis_namespace.unwrap()) |namespace| .{ .namespace = namespace, .zir_index = repr.analysis_zir_index.unwrap().?, + .wanted = repr.bits.want_analysis, } else a: { assert(repr.analysis_zir_index == .none); break :a null; @@ -824,6 +827,7 @@ pub const Nav = struct { .alignment = .none, .@"addrspace" = .generic, .is_threadlocal = false, + .want_analysis = if (nav.analysis) |a| a.wanted else false, }, .type_resolved => |r| .{ .status = if (r.is_extern_decl) .type_resolved_extern_decl else .type_resolved, @@ -831,6 +835,7 @@ pub const Nav = struct { .alignment = r.alignment, .@"addrspace" = r.@"addrspace", .is_threadlocal = r.is_threadlocal, + .want_analysis = if (nav.analysis) |a| a.wanted else false, }, .fully_resolved => |r| .{ .status = .fully_resolved, @@ -838,6 +843,7 @@ pub const Nav = struct { .alignment = r.alignment, .@"addrspace" = r.@"addrspace", .is_threadlocal = false, + .want_analysis = if (nav.analysis) |a| a.wanted else false, }, }, }; @@ -2412,17 +2418,6 @@ pub const Key = union(enum) { @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); } - pub fn setAnalyzed(func: Func, ip: *InternPool, io: Io) void { - const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex; - extra_mutex.lockUncancelable(io); - defer extra_mutex.unlock(io); - - const analysis_ptr = func.analysisPtr(ip); - var analysis = analysis_ptr.*; - analysis.is_analyzed = true; - @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); - } - /// Returns a pointer that becomes invalid after any additions to the `InternPool`. fn zirBodyInstPtr(func: Func, ip: *const InternPool) *TrackedInst.Index { const extra = ip.getLocalShared(func.tid).extra.acquire(); @@ -3314,6 +3309,25 @@ pub const LoadedStructType = struct { /// May be `undefined` if `layout != .@"packed"`. packed_backing_mode: BackingTypeMode, + /// Initially `false`, and set to `true` once any dependency on or reference to the struct's + /// layout is encountered, after which it is never reset to `false`, even across incremental + /// updates. + /// + /// This field is purely an optimization to avoid resolving the layout of types whose layouts + /// are never demanded. If this field is `true` but the layout is not actually needed, the + /// compiler frontend resolves this by traversing the reference graph at the end of each update + /// with `Zcu.resolveReferences` and hiding compile errors which arise from this analysis. + want_layout: bool, + /// Initially `false`, and set to `true` once any dependency on or reference to the struct's + /// default field values is encountered, after which it is never reset to `false`, even across + /// incremental updates. + /// + /// This field is purely an optimization to avoid resolving the layout of types whose layouts + /// are never demanded. If this field is `true` but the layout is not actually needed, the + /// compiler frontend resolves this by traversing the reference graph at the end of each update + /// with `Zcu.resolveReferences` and hiding compile errors which arise from this analysis. + want_defaults: bool, + // The remaining fields are only valid once the struct's layout is resolved. field_name_map: MapIndex, field_names: NullTerminatedString.Slice, @@ -3490,6 +3504,16 @@ pub const LoadedUnionType = struct { /// or populate `enum_tag_type`. reified_field_names: NullTerminatedString.Slice, + /// Initially `false`, and set to `true` once any dependency on or reference to the struct's + /// layout is encountered, after which it is never reset to `false`, even across incremental + /// updates. + /// + /// This field is purely an optimization to avoid resolving the layout of types whose layouts + /// are never demanded. If this field is `true` but the layout is not actually needed, the + /// compiler frontend resolves this by traversing the reference graph at the end of each update + /// with `Zcu.resolveReferences` and hiding compile errors which arise from this analysis. + want_layout: bool, + // The remaining fields are only valid once the union's layout is resolved. field_types: Index.Slice, field_aligns: Alignment.Slice, @@ -3532,6 +3556,16 @@ pub const LoadedEnumType = struct { int_tag_mode: BackingTypeMode, nonexhaustive: bool, + /// Initially `false`, and set to `true` once any dependency on or reference to the struct's + /// layout is encountered, after which it is never reset to `false`, even across incremental + /// updates. + /// + /// This field is purely an optimization to avoid resolving the layout of types whose layouts + /// are never demanded. If this field is `true` but the layout is not actually needed, the + /// compiler frontend resolves this by traversing the reference graph at the end of each update + /// with `Zcu.resolveReferences` and hiding compile errors which arise from this analysis. + want_layout: bool, + // The remaining fields are only valid once the enum's layout is resolved. int_tag_type: Index, field_name_map: MapIndex, @@ -3669,6 +3703,9 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { }, .packed_backing_mode = undefined, + .want_layout = extra.data.flags.want_layout, + .want_defaults = extra.data.flags.want_defaults, + .field_name_map = extra.data.field_name_map, .field_names = field_names, .field_types = field_types, @@ -3690,15 +3727,15 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { }; const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, item.data); var extra_index = extra.end; - const captures: CaptureValue.Slice = switch (extra.data.captures_len) { + const captures: CaptureValue.Slice = switch (extra.data.bits.captures_len) { .reified => captures: { extra_index += 2; // type_hash: PackedU64 break :captures .empty; }, - _ => .{ + _ => |n| .{ .tid = unwrapped_index.tid, .start = extra_index, - .len = @intFromEnum(extra.data.captures_len), + .len = @intFromEnum(n), }, }; extra_index += captures.len; @@ -3723,13 +3760,16 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { return .{ .zir_index = extra.data.zir_index, .captures = captures, - .is_reified = extra.data.captures_len == .reified, + .is_reified = extra.data.bits.captures_len == .reified, .name = extra.data.name, .name_nav = extra.data.name_nav, .namespace = extra.data.namespace, .layout = .@"packed", .packed_backing_mode = backing_mode, + .want_layout = extra.data.bits.want_layout, + .want_defaults = extra.data.bits.want_defaults, + .field_name_map = extra.data.field_name_map, .field_names = field_names, .field_types = field_types, @@ -3813,6 +3853,7 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { .packed_backing_mode = undefined, .packed_backing_int_type = undefined, .reified_field_names = reified_field_names, + .want_layout = extra.data.flags.want_layout, .field_types = field_types, .field_aligns = field_aligns, .has_no_possible_value = extra.data.flags.has_no_possible_value, @@ -3828,19 +3869,19 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { }; const extra = extraDataTrail(extra_list, Tag.TypeUnionPacked, item.data); var extra_index = extra.end; - const captures: CaptureValue.Slice = switch (extra.data.captures_len) { + const captures: CaptureValue.Slice = switch (extra.data.bits.captures_len) { .reified => captures: { extra_index += 2; // type_hash: PackedU64 break :captures .empty; }, - _ => .{ + _ => |n| .{ .tid = unwrapped_index.tid, .start = extra_index, - .len = @intFromEnum(extra.data.captures_len), + .len = @intFromEnum(n), }, }; extra_index += captures.len; - const reified_field_names: NullTerminatedString.Slice = if (extra.data.captures_len == .reified) .{ + const reified_field_names: NullTerminatedString.Slice = if (extra.data.bits.captures_len == .reified) .{ .tid = unwrapped_index.tid, .start = extra_index, .len = extra.data.fields_len, @@ -3855,7 +3896,7 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { return .{ .zir_index = extra.data.zir_index, .captures = captures, - .is_reified = extra.data.captures_len == .reified, + .is_reified = extra.data.bits.captures_len == .reified, .name = extra.data.name, .name_nav = extra.data.name_nav, .namespace = extra.data.namespace, @@ -3866,6 +3907,7 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { .packed_backing_mode = backing_mode, .packed_backing_int_type = extra.data.backing_int_type, .reified_field_names = reified_field_names, + .want_layout = extra.data.bits.want_layout, .field_types = field_types, .field_aligns = .empty, .has_no_possible_value = undefined, @@ -3891,7 +3933,7 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType { }; const extra = extraDataTrail(extra_list, Tag.TypeEnum, item.data); var extra_index: u32 = @intCast(extra.end); - const zir_index: TrackedInst.Index.Optional, const captures: CaptureValue.Slice, const owner_union: Index = switch (extra.data.captures_len) { + const zir_index: TrackedInst.Index.Optional, const captures: CaptureValue.Slice, const owner_union: Index = switch (extra.data.bits.captures_len) { .reified => info: { const zir_index: TrackedInst.Index = @enumFromInt(extra_items[extra_index]); extra_index += 1; @@ -3903,13 +3945,13 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType { extra_index += 1; break :info .{ .none, .empty, owner_union }; }, - _ => info: { + _ => |n| info: { const zir_index: TrackedInst.Index = @enumFromInt(extra_items[extra_index]); extra_index += 1; const captures: CaptureValue.Slice = .{ .tid = unwrapped_index.tid, .start = extra_index, - .len = @intFromEnum(extra.data.captures_len), + .len = @intFromEnum(n), }; extra_index += captures.len; break :info .{ zir_index.toOptional(), captures, .none }; @@ -3935,7 +3977,7 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType { return .{ .zir_index = zir_index, .captures = captures, - .is_reified = extra.data.captures_len == .reified, + .is_reified = extra.data.bits.captures_len == .reified, .owner_union = owner_union, .name = extra.data.name, .name_nav = extra.data.name_nav, @@ -3943,6 +3985,7 @@ pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType { .int_tag_type = extra.data.int_tag_type, .int_tag_mode = if (explicit_int_tag) .explicit else .auto, .nonexhaustive = nonexhaustive, + .want_layout = extra.data.bits.want_layout, .field_name_map = extra.data.field_name_map, .field_value_map = field_value_map, .field_names = field_names, @@ -5629,7 +5672,10 @@ pub const Tag = enum(u8) { /// Alignment of the whole struct. Always `.none` until layout resolved. alignment: Alignment, - _: u16 = 0, + want_layout: bool, + want_defaults: bool, + + _: u14 = 0, }; }; @@ -5641,10 +5687,7 @@ pub const Tag = enum(u8) { /// 4. field_default: Index // if item tag implies field defaults; for each `fields_len` pub const TypeStructPacked = struct { zir_index: TrackedInst.Index, - captures_len: enum(u32) { - reified = std.math.maxInt(u32), - _, - }, + bits: Bits, name: NullTerminatedString, name_nav: Nav.Index.Optional, @@ -5655,6 +5698,15 @@ pub const Tag = enum(u8) { fields_len: u32, field_name_map: MapIndex, + + const Bits = packed struct(u32) { + captures_len: enum(u30) { + reified = std.math.maxInt(u30), + _, + }, + want_layout: bool, + want_defaults: bool, + }; }; /// For declared unions, field names are intentionally omitted because they are available in @@ -5718,7 +5770,9 @@ pub const Tag = enum(u8) { /// Alignment of the whole union. Always `.none` until layout resolved. alignment: Alignment, - _: u15 = 0, + want_layout: bool, + + _: u14 = 0, }; }; @@ -5734,10 +5788,7 @@ pub const Tag = enum(u8) { /// 3. field_type: Index // for each `fields_len` pub const TypeUnionPacked = struct { zir_index: TrackedInst.Index, - captures_len: enum(u32) { - reified = std.math.maxInt(u32), - _, - }, + bits: Bits, name: NullTerminatedString, name_nav: Nav.Index.Optional, @@ -5753,6 +5804,14 @@ pub const Tag = enum(u8) { /// to store it directly. This is also necessary for `dumpStatsFallible` to /// work on unresolved types. fields_len: u32, + + const Bits = packed struct(u32) { + captures_len: enum(u31) { + reified = std.math.maxInt(u31), + _, + }, + want_layout: bool, + }; }; /// Trailing: @@ -5764,11 +5823,7 @@ pub const Tag = enum(u8) { /// 5. field_name: NullTerminatedString // for each `fields_len` /// 6. field_value: Index // if tag is not `.type_enum_auto`; for each `fields_len` pub const TypeEnum = struct { - captures_len: enum(u32) { - reified = std.math.maxInt(u32), - generated_union_tag = std.math.maxInt(u32) - 1, - _, - }, + bits: Bits, name: NullTerminatedString, name_nav: Nav.Index.Optional, @@ -5780,6 +5835,15 @@ pub const Tag = enum(u8) { fields_len: u32, field_name_map: MapIndex, + + const Bits = packed struct(u32) { + captures_len: enum(u31) { + reified = std.math.maxInt(u31), + generated_union_tag = std.math.maxInt(u31) - 1, + _, + }, + want_layout: bool, + }; }; /// Trailing: @@ -5812,7 +5876,7 @@ pub const BackingTypeMode = enum(u1) { /// equality or hashing, except for `inferred_error_set` which is considered /// to be part of the type of the function. pub const FuncAnalysis = packed struct(u32) { - is_analyzed: bool, + want_runtime_analysis: bool, branch_hint: std.builtin.BranchHint, is_noinline: bool, has_error_trace: bool, @@ -6597,17 +6661,17 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { => .{ .struct_type = ns: { const extra_list = unwrapped_index.getExtra(ip); const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, data); - break :ns switch (extra.data.captures_len) { + break :ns switch (extra.data.bits.captures_len) { .reified => .{ .reified = .{ .zir_index = extra.data.zir_index, .type_hash = extraData(extra_list, PackedU64, extra.end).get(), } }, - _ => .{ .declared = .{ + _ => |len| .{ .declared = .{ .zir_index = extra.data.zir_index, .captures = .{ .owned = .{ .tid = unwrapped_index.tid, .start = extra.end, - .len = @intFromEnum(extra.data.captures_len), + .len = @intFromEnum(len), } }, } }, }; @@ -6637,17 +6701,17 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { .type_union_packed_auto, .type_union_packed_explicit => .{ .union_type = ns: { const extra_list = unwrapped_index.getExtra(ip); const extra = extraDataTrail(extra_list, Tag.TypeUnionPacked, data); - break :ns switch (extra.data.captures_len) { + break :ns switch (extra.data.bits.captures_len) { .reified => .{ .reified = .{ .zir_index = extra.data.zir_index, .type_hash = extraData(extra_list, PackedU64, extra.end).get(), } }, - _ => .{ .declared = .{ + _ => |len| .{ .declared = .{ .zir_index = extra.data.zir_index, .captures = .{ .owned = .{ .tid = unwrapped_index.tid, .start = extra.end, - .len = @intFromEnum(extra.data.captures_len), + .len = @intFromEnum(len), } }, } }, }; @@ -6655,7 +6719,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { .type_enum_auto, .type_enum_explicit, .type_enum_nonexhaustive => .{ .enum_type = ns: { const extra_list = unwrapped_index.getExtra(ip); const extra = extraDataTrail(extra_list, Tag.TypeEnum, data); - break :ns switch (extra.data.captures_len) { + break :ns switch (extra.data.bits.captures_len) { .reified => .{ .reified = .{ .zir_index = @enumFromInt(extra_list.view().items(.@"0")[extra.end]), .type_hash = extraData(extra_list, PackedU64, extra.end + 1).get(), @@ -6663,12 +6727,12 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { .generated_union_tag => .{ .generated_union_tag = owner_union: { break :owner_union @enumFromInt(extra_list.view().items(.@"0")[extra.end]); } }, - _ => .{ .declared = .{ + _ => |len| .{ .declared = .{ .zir_index = @enumFromInt(extra_list.view().items(.@"0")[extra.end]), .captures = .{ .owned = .{ .tid = unwrapped_index.tid, .start = extra.end + 1, - .len = @intFromEnum(extra.data.captures_len), + .len = @intFromEnum(len), } }, } }, }; @@ -8138,7 +8202,11 @@ pub fn getDeclaredStructType( const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStructPacked{ .zir_index = ini.zir_index, - .captures_len = @enumFromInt(ini.captures.len), + .bits = .{ + .captures_len = @enumFromInt(ini.captures.len), + .want_layout = false, + .want_defaults = false, + }, .name = undefined, // set by `finish` .name_nav = undefined, // set by `finish` .namespace = undefined, // set by `finish` @@ -8204,6 +8272,8 @@ pub fn getDeclaredStructType( .comptime_only = false, .has_runtime_bits = false, .alignment = .none, + .want_layout = false, + .want_defaults = false, }, }); if (ini.captures.len != 0) { @@ -8281,7 +8351,11 @@ pub fn getReifiedStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Pe const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStructPacked{ .zir_index = ini.zir_index, - .captures_len = .reified, + .bits = .{ + .captures_len = .reified, + .want_layout = false, + .want_defaults = false, + }, .name = undefined, // set by `finish` .name_nav = undefined, // set by `finish` .namespace = undefined, // set by `finish` @@ -8352,6 +8426,8 @@ pub fn getReifiedStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Pe .comptime_only = false, .has_runtime_bits = false, .alignment = .none, + .want_layout = false, + .want_defaults = false, }, }); _ = addExtraAssumeCapacity(extra, PackedU64.init(ini.type_hash)); // type_hash @@ -8451,7 +8527,10 @@ pub fn getDeclaredUnionType( const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnionPacked{ .zir_index = ini.zir_index, - .captures_len = @enumFromInt(ini.captures.len), + .bits = .{ + .captures_len = @enumFromInt(ini.captures.len), + .want_layout = false, + }, .name = undefined, // set by `finish` .name_nav = undefined, // set by `finish` .namespace = undefined, // set by `finish` @@ -8509,6 +8588,7 @@ pub fn getDeclaredUnionType( .comptime_only = false, .has_runtime_bits = false, .alignment = .none, + .want_layout = false, }, }); if (ini.captures.len > 0) { @@ -8572,7 +8652,10 @@ pub fn getReifiedUnionType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Per const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnionPacked{ .zir_index = ini.zir_index, - .captures_len = .reified, + .bits = .{ + .captures_len = .reified, + .want_layout = false, + }, .name = undefined, // set by `finish` .name_nav = undefined, // set by `finish` .namespace = undefined, // set by `finish` @@ -8633,6 +8716,7 @@ pub fn getReifiedUnionType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Per .comptime_only = false, .has_runtime_bits = false, .alignment = .none, + .want_layout = false, }, }); _ = addExtraAssumeCapacity(extra, PackedU64.init(ini.type_hash)); @@ -8723,7 +8807,10 @@ pub fn getDeclaredEnumType( (if (have_values) ini.fields_len else 0)); // field_value const extra_index = addExtraAssumeCapacity(extra, Tag.TypeEnum{ - .captures_len = @enumFromInt(ini.captures.len), + .bits = .{ + .captures_len = @enumFromInt(ini.captures.len), + .want_layout = false, + }, .name = undefined, // set by `finish` .name_nav = undefined, // set by `finish` .namespace = undefined, // set by `finish` @@ -8795,7 +8882,10 @@ pub fn getReifiedEnumType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerT (if (have_values) ini.fields_len else 0)); // field_value const extra_index = addExtraAssumeCapacity(extra, Tag.TypeEnum{ - .captures_len = .reified, + .bits = .{ + .captures_len = .reified, + .want_layout = false, + }, .name = undefined, // set by `finish` .name_nav = undefined, // set by `finish` .namespace = undefined, // set by `finish` @@ -8865,7 +8955,10 @@ pub fn getGeneratedEnumTagType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu (if (have_values) ini.fields_len else 0)); // field_value const extra_index = addExtraAssumeCapacity(extra, Tag.TypeEnum{ - .captures_len = .generated_union_tag, + .bits = .{ + .captures_len = .generated_union_tag, + .want_layout = false, + }, .name = undefined, // set by `finish` .name_nav = undefined, // set by `finish` .namespace = undefined, // set by `finish` @@ -9249,7 +9342,7 @@ pub fn getFuncDecl( const func_decl_extra_index = addExtraAssumeCapacity(extra, Tag.FuncDecl{ .analysis = .{ - .is_analyzed = false, + .want_runtime_analysis = false, .branch_hint = .none, .is_noinline = key.is_noinline, .has_error_trace = false, @@ -9359,7 +9452,7 @@ pub fn getFuncDeclIes( const func_decl_extra_index = addExtraAssumeCapacity(extra, Tag.FuncDecl{ .analysis = .{ - .is_analyzed = false, + .want_runtime_analysis = false, .branch_hint = .none, .is_noinline = key.is_noinline, .has_error_trace = false, @@ -9557,7 +9650,7 @@ pub fn getFuncInstance( const func_extra_index = addExtraAssumeCapacity(extra, Tag.FuncInstance{ .analysis = .{ - .is_analyzed = false, + .want_runtime_analysis = false, .branch_hint = .none, .is_noinline = arg.is_noinline, .has_error_trace = false, @@ -9658,7 +9751,7 @@ fn getFuncInstanceIes( const func_extra_index = addExtraAssumeCapacity(extra, Tag.FuncInstance{ .analysis = .{ - .is_analyzed = false, + .want_runtime_analysis = false, .branch_hint = .none, .is_noinline = arg.is_noinline, .has_error_trace = false, @@ -9902,9 +9995,6 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 { TrackedInst.Index, TrackedInst.Index.Optional, ComptimeAllocIndex, - @FieldType(Tag.TypeStructPacked, "captures_len"), - @FieldType(Tag.TypeUnionPacked, "captures_len"), - @FieldType(Tag.TypeEnum, "captures_len"), => @intFromEnum(@field(item, field.name)), u32, @@ -9916,6 +10006,9 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 { Tag.TypePointer.PackedOffset, Tag.TypeUnion.Flags, Tag.TypeStruct.Flags, + Tag.TypeStructPacked.Bits, + Tag.TypeUnionPacked.Bits, + Tag.TypeEnum.Bits, => @bitCast(@field(item, field.name)), else => @compileError("bad field type: " ++ @typeName(field.type)), @@ -9967,9 +10060,6 @@ fn extraDataTrail(extra: Local.Extra, comptime T: type, index: u32) struct { dat TrackedInst.Index, TrackedInst.Index.Optional, ComptimeAllocIndex, - @FieldType(Tag.TypeStructPacked, "captures_len"), - @FieldType(Tag.TypeUnionPacked, "captures_len"), - @FieldType(Tag.TypeEnum, "captures_len"), => @enumFromInt(extra_item), u32, @@ -9981,6 +10071,9 @@ fn extraDataTrail(extra: Local.Extra, comptime T: type, index: u32) struct { dat Tag.TypeUnion.Flags, Tag.TypeStruct.Flags, FuncAnalysis, + Tag.TypeStructPacked.Bits, + Tag.TypeUnionPacked.Bits, + Tag.TypeEnum.Bits, => @bitCast(extra_item), else => @compileError("bad field type: " ++ @typeName(field.type)), @@ -10750,7 +10843,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo .type_struct_packed_auto, .type_struct_packed_explicit => b: { var n: usize = @typeInfo(Tag.TypeStructPacked).@"struct".fields.len; const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, data); - switch (extra.data.captures_len) { + switch (extra.data.bits.captures_len) { .reified => n += 2, // type_hash: PackedU64 _ => |len| n += @intFromEnum(len), // capture: CaptureValue } @@ -10761,7 +10854,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo .type_struct_packed_auto_defaults, .type_struct_packed_explicit_defaults => b: { var n: usize = @typeInfo(Tag.TypeStructPacked).@"struct".fields.len; const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, data); - switch (extra.data.captures_len) { + switch (extra.data.bits.captures_len) { .reified => n += 2, // type_hash: PackedU64 _ => |len| n += @intFromEnum(len), // capture: CaptureValue } @@ -10790,7 +10883,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo .type_union_packed_auto, .type_union_packed_explicit => b: { var n: usize = @typeInfo(Tag.TypeUnionPacked).@"struct".fields.len; const extra = extraDataTrail(extra_list, Tag.TypeUnionPacked, data); - switch (extra.data.captures_len) { + switch (extra.data.bits.captures_len) { .reified => n += 2, // type_hash: PackedU64 _ => |len| n += @intFromEnum(len), // capture: CaptureValue } @@ -10800,7 +10893,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo .type_enum_auto => b: { var n: usize = @typeInfo(Tag.TypeEnum).@"struct".fields.len; const extra = extraData(extra_list, Tag.TypeEnum, data); - switch (extra.captures_len) { + switch (extra.bits.captures_len) { .generated_union_tag => n += 1, // owner_union: Index .reified => { n += 1; // zir_index: TrackedInst.Index, @@ -10817,7 +10910,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo .type_enum_explicit, .type_enum_nonexhaustive => b: { var n: usize = @typeInfo(Tag.TypeEnum).@"struct".fields.len; const extra = extraData(extra_list, Tag.TypeEnum, data); - switch (extra.captures_len) { + switch (extra.bits.captures_len) { .generated_union_tag => n += 1, // owner_union: Index .reified => { n += 1; // zir_index: TrackedInst.Index, @@ -11204,6 +11297,7 @@ pub fn createDeclNav( .analysis = .{ .namespace = namespace, .zir_index = zir_index, + .wanted = false, }, .status = .unresolved, })); @@ -12829,3 +12923,175 @@ pub fn resolveEnumLayout( extra_items[item.data + std.meta.fieldIndex(Tag.TypeEnum, "int_tag_type").?] = @intFromEnum(int_tag_type); } + +/// Sets the "want_layout" flag on the given struct, union, or enum type. Returns true if the flag +/// was *not* already set, meaning we have just discovered the first reference to this type's +/// layout. This flag is never reset to false, and exists purely as an optimization; for details, +/// see doc comments in `LoadedStructType`. +pub fn setWantTypeLayout(ip: *InternPool, io: Io, container_type: Index) bool { + const unwrapped_index = container_type.unwrap(ip); + + const local = ip.getLocal(unwrapped_index.tid); + local.mutate.extra.mutex.lockUncancelable(io); + defer local.mutate.extra.mutex.unlock(io); + + const extra_items = local.shared.extra.view().items(.@"0"); + const item = unwrapped_index.getItem(ip); + switch (item.tag) { + .type_struct_packed_auto, + .type_struct_packed_explicit, + .type_struct_packed_auto_defaults, + .type_struct_packed_explicit_defaults, + => { + const bits: *Tag.TypeStructPacked.Bits = @ptrCast(&extra_items[ + item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "bits").? + ]); + if (bits.want_layout) { + return false; + } else { + bits.want_layout = true; + return true; + } + }, + + .type_struct => { + const flags: *Tag.TypeStruct.Flags = @ptrCast(&extra_items[ + item.data + std.meta.fieldIndex(Tag.TypeStruct, "flags").? + ]); + if (flags.want_layout) { + return false; + } else { + flags.want_layout = true; + return true; + } + }, + + .type_union_packed_auto, + .type_union_packed_explicit, + => { + const bits: *Tag.TypeUnionPacked.Bits = @ptrCast(&extra_items[ + item.data + std.meta.fieldIndex(Tag.TypeUnionPacked, "bits").? + ]); + if (bits.want_layout) { + return false; + } else { + bits.want_layout = true; + return true; + } + }, + + .type_union => { + const flags: *Tag.TypeUnion.Flags = @ptrCast(&extra_items[ + item.data + std.meta.fieldIndex(Tag.TypeUnion, "flags").? + ]); + if (flags.want_layout) { + return false; + } else { + flags.want_layout = true; + return true; + } + }, + + .type_enum_auto, + .type_enum_explicit, + .type_enum_nonexhaustive, + => { + const bits: *Tag.TypeEnum.Bits = @ptrCast(&extra_items[ + item.data + std.meta.fieldIndex(Tag.TypeEnum, "bits").? + ]); + if (bits.want_layout) { + return false; + } else { + bits.want_layout = true; + return true; + } + }, + + else => unreachable, + } +} + +/// Like `setWantTypeLayout`, but for the default field values of a struct (so this sets the +/// `want_defaults` flag rather than the `want_layout` flag). +pub fn setWantStructDefaults(ip: *InternPool, io: Io, struct_type: Index) bool { + const unwrapped_index = struct_type.unwrap(ip); + + const local = ip.getLocal(unwrapped_index.tid); + local.mutate.extra.mutex.lockUncancelable(io); + defer local.mutate.extra.mutex.unlock(io); + + const extra_items = local.shared.extra.view().items(.@"0"); + const item = unwrapped_index.getItem(ip); + switch (item.tag) { + .type_struct_packed_auto, + .type_struct_packed_explicit, + .type_struct_packed_auto_defaults, + .type_struct_packed_explicit_defaults, + => { + const bits: *Tag.TypeStructPacked.Bits = @ptrCast(&extra_items[ + item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "bits").? + ]); + if (bits.want_defaults) { + return false; + } else { + bits.want_defaults = true; + return true; + } + }, + + .type_struct => { + const flags: *Tag.TypeStruct.Flags = @ptrCast(&extra_items[ + item.data + std.meta.fieldIndex(Tag.TypeStruct, "flags").? + ]); + if (flags.want_defaults) { + return false; + } else { + flags.want_defaults = true; + return true; + } + }, + + else => unreachable, + } +} + +/// Like `setWantTypeLayout`, but for runtime analysis of a function body, using the +/// `FuncAnalysis.want_runtime_analysis` flag. +pub fn setWantRuntimeFnAnalysis(ip: *InternPool, io: Io, func_index: Index) bool { + const unwrapped_index = func_index.unwrap(ip); + + const local = ip.getLocal(unwrapped_index.tid); + local.mutate.extra.mutex.lockUncancelable(io); + defer local.mutate.extra.mutex.unlock(io); + + const a = funcAnalysisPtr(ip, func_index); + if (a.want_runtime_analysis) { + return false; + } else { + a.want_runtime_analysis = true; + return true; + } +} + +/// Like `setWantTypeLayout`, but for runtime analysis of a `Nav`, using the `Nav.analysis.wanted` flag. +pub fn setWantNavAnalysis(ip: *InternPool, io: Io, nav_index: Nav.Index) bool { + const unwrapped = nav_index.unwrap(ip); + + const local = ip.getLocal(unwrapped.tid); + local.mutate.extra.mutex.lockUncancelable(io); + defer local.mutate.extra.mutex.unlock(io); + + const navs = local.shared.navs.view(); + + if (navs.items(.analysis_namespace)[unwrapped.index] == .none) { + return false; + } + + const bits = &navs.items(.bits)[unwrapped.index]; + if (bits.want_analysis) { + return false; + } else { + bits.want_analysis = true; + return true; + } +} diff --git a/src/Sema.zig b/src/Sema.zig index 2fffe8ae546af74951980c583506ba82647b0d60..a506a7e6bbc369bf6a9906d2cda4dd6b41450317 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -3258,7 +3258,7 @@ fn zirAllocExtended( } else .none; if (small.has_type) { - try sema.ensureLayoutResolved(var_ty); + try sema.ensureLayoutResolved(var_ty, ty_src); if (block.isComptime() or small.is_comptime or var_ty.comptimeOnly(zcu)) { return sema.analyzeComptimeAlloc(block, var_src, var_ty, alignment); } @@ -3322,7 +3322,7 @@ fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); const var_src = block.nodeOffset(inst_data.src_node); const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); - try sema.ensureLayoutResolved(var_ty); + try sema.ensureLayoutResolved(var_ty, ty_src); return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none); } @@ -3743,7 +3743,7 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I const var_src = block.nodeOffset(inst_data.src_node); const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); - try sema.ensureLayoutResolved(var_ty); + try sema.ensureLayoutResolved(var_ty, ty_src); if (block.isComptime() or var_ty.comptimeOnly(zcu)) { return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none); } @@ -3775,7 +3775,7 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const var_src = block.nodeOffset(inst_data.src_node); const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); - try sema.ensureLayoutResolved(var_ty); + try sema.ensureLayoutResolved(var_ty, ty_src); if (block.isComptime()) { return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none); } @@ -4132,8 +4132,9 @@ fn optEuBasePtrInit(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, src: LazySrcL fn zirOptEuBasePtrInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const ptr = sema.resolveInst(un_node.operand); - try sema.ensureLayoutResolved(sema.typeOf(ptr).childType(sema.pt.zcu)); - return sema.optEuBasePtrInit(block, ptr, block.nodeOffset(un_node.src_node)); + const src = block.nodeOffset(un_node.src_node); + try sema.ensureLayoutResolved(sema.typeOf(ptr).childType(sema.pt.zcu), src); + return sema.optEuBasePtrInit(block, ptr, src); } fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -4518,7 +4519,7 @@ fn validateStructInit( if (struct_ty.structFieldIsComptime(i, zcu)) continue; if (!struct_ty.isTuple(zcu)) { - try sema.ensureStructDefaultsResolved(struct_ty); + try sema.ensureStructDefaultsResolved(struct_ty, init_src); } const default_val = struct_ty.structFieldDefaultValue(i, zcu) orelse { @@ -4642,7 +4643,7 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr } const elem_ty = operand_ty.childType(zcu); - try sema.ensureLayoutResolved(elem_ty); + try sema.ensureLayoutResolved(elem_ty, src); if (try elem_ty.onePossibleValue(pt) != null) { // No need to validate the actual pointer value, we don't need it! @@ -7025,7 +7026,7 @@ fn analyzeCall( break :ret_ty full_ty; }; - try sema.ensureLayoutResolved(resolved_ret_ty); + try sema.ensureLayoutResolved(resolved_ret_ty, func_ret_ty_src); // If we've discovered after evaluating arguments that a generic function instantiation is // comptime-only, then we can mark the block as comptime *now*. @@ -7122,7 +7123,7 @@ fn analyzeCall( .generic_owner = func_val.?.toIntern(), .comptime_args = comptime_args, }); - try sema.ensureLayoutResolved(.fromInterned(ip.typeOf(func_instance))); + try sema.ensureLayoutResolved(.fromInterned(ip.typeOf(func_instance)), call_src); if (zcu.comp.debugIncremental()) { const nav = ip.indexToKey(func_instance).func.owner_nav; const gop = try zcu.incremental_debug_state.navs.getOrPut(gpa, nav); @@ -7196,7 +7197,7 @@ fn analyzeCall( return .unreachable_value; } - try sema.ensureLayoutResolved(sema.typeOf(maybe_opv)); + try sema.ensureLayoutResolved(sema.typeOf(maybe_opv), func_ret_ty_src); if (try sema.typeOf(maybe_opv).onePossibleValue(pt)) |opv| { return .fromValue(opv); } else { @@ -7270,7 +7271,7 @@ fn analyzeCall( // We're about to do an inline call; if the return type expression was generic, the return type // may not be resolved yet. It's correct to resolve it because the function is going to return a // value of this type. - try sema.ensureLayoutResolved(resolved_ret_ty); + try sema.ensureLayoutResolved(resolved_ret_ty, func_ret_ty_src); // For an inline call, we depend on the source code of the whole function definition. try sema.declareDependency(.{ .src_hash = fn_nav.analysis.?.zir_index }); @@ -7532,7 +7533,6 @@ fn zirArrayInitElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil const zcu = pt.zcu; const bin = sema.code.instructions.items(.data)[@intFromEnum(inst)].bin; const maybe_wrapped_indexable_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, bin.lhs) orelse return .generic_poison_type; - try sema.ensureLayoutResolved(maybe_wrapped_indexable_ty); const indexable_ty = maybe_wrapped_indexable_ty.optEuBaseType(zcu); assert(indexable_ty.isIndexable(zcu)); // validated by a previous instruction const elem_ty = switch (indexable_ty.zigTypeTag(zcu)) { @@ -8040,7 +8040,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError if (dest_ty.zigTypeTag(zcu) != .@"enum") { return sema.fail(block, src, "expected enum, found '{f}'", .{dest_ty.fmt(pt)}); } - try sema.ensureLayoutResolved(dest_ty); + try sema.ensureLayoutResolved(dest_ty, src); _ = try sema.checkIntType(block, operand_src, operand_ty); if (sema.resolveValue(operand)) |int_val| { @@ -8103,7 +8103,7 @@ fn zirOptionalPayloadPtr( const ptr_ty = sema.typeOf(optional_ptr); assert(ptr_ty.zigTypeTag(sema.pt.zcu) == .pointer); - try sema.ensureLayoutResolved(ptr_ty.childType(sema.pt.zcu)); + try sema.ensureLayoutResolved(ptr_ty.childType(sema.pt.zcu), src); return sema.analyzeOptionalPayloadPtr(block, src, optional_ptr, safety_check, false); } @@ -8313,7 +8313,7 @@ fn zirErrUnionPayloadPtr( const ptr_ty = sema.typeOf(operand); assert(ptr_ty.zigTypeTag(sema.pt.zcu) == .pointer); - try sema.ensureLayoutResolved(ptr_ty.childType(sema.pt.zcu)); + try sema.ensureLayoutResolved(ptr_ty.childType(sema.pt.zcu), src); return sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false); } @@ -9022,6 +9022,7 @@ fn funcCommon( const io = comp.io; const ip = &zcu.intern_pool; + const src = block.nodeOffset(src_node_offset); const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = src_node_offset }); const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset }); @@ -9091,7 +9092,7 @@ fn funcCommon( .lbrace_column = @as(u16, @truncate(src_locs.columns)), .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)), })); - try sema.ensureLayoutResolved(func_val.typeOf(zcu)); + try sema.ensureLayoutResolved(func_val.typeOf(zcu), src); return .fromValue(func_val); } @@ -9106,7 +9107,7 @@ fn funcCommon( }); if (has_body) { - try sema.ensureLayoutResolved(.fromInterned(func_ty)); + try sema.ensureLayoutResolved(.fromInterned(func_ty), src); return .fromIntern(try ip.getFuncDecl(gpa, io, pt.tid, .{ .owner_nav = sema.owner.unwrap().nav_val, .ty = func_ty, @@ -9762,7 +9763,7 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air return sema.failWithOwnedErrorMsg(block, msg); } try sema.checkIndexable(block, src, indexable_ty); - try sema.ensureLayoutResolved(indexable_ty.childType(zcu)); + try sema.ensureLayoutResolved(indexable_ty.childType(zcu), src); return sema.elemPtrOneLayerOnly(block, src, array_ptr, elem_index, src, false, false); } @@ -9983,7 +9984,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp err_union_ty.fmt(pt), }); } - try sema.ensureLayoutResolved(err_union_ty); + try sema.ensureLayoutResolved(err_union_ty, operand_src); const non_err_cond = if (non_err_case.operand_is_ref) try sema.analyzePtrIsNonErr(block, operand_src, eu_maybe_ptr) @@ -11287,7 +11288,7 @@ fn validateSwitchBlock( } break :operand_ty raw_operand_ty; }; - try sema.ensureLayoutResolved(operand_ty); + try sema.ensureLayoutResolved(operand_ty, operand_src); const item_ty: Type = item_ty: { switch (operand_ty.zigTypeTag(zcu)) { @@ -12870,7 +12871,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const name_src = block.builtinCallArgSrc(inst_data.src_node, 1); const ty = try sema.resolveType(block, ty_src, extra.lhs); const field_name = try sema.resolveConstStringIntern(block, name_src, extra.rhs, .{ .simple = .field_name }); - try sema.ensureLayoutResolved(ty); + try sema.ensureLayoutResolved(ty, ty_src); const ip = &zcu.intern_pool; const has_field = hf: { @@ -15270,7 +15271,7 @@ fn analyzeArithmetic( else => return sema.failWithInvalidPtrArithmetic(block, src, "pointer-integer", "addition and subtraction"), }; - try sema.ensureLayoutResolved(lhs_ty.childType(zcu)); + try sema.ensureLayoutResolved(lhs_ty.childType(zcu), src); return sema.analyzePtrArithmetic(block, src, lhs, rhs, air_tag, lhs_src, rhs_src); }, } @@ -15964,7 +15965,7 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. .@"anyframe", => {}, } - try sema.ensureLayoutResolved(ty); + try sema.ensureLayoutResolved(ty, operand_src); return .fromValue(try pt.intValue(.comptime_int, ty.abiSize(zcu))); } @@ -16005,7 +16006,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A .@"anyframe", => {}, } - try sema.ensureLayoutResolved(operand_ty); + try sema.ensureLayoutResolved(operand_ty, operand_src); return .fromValue(try pt.intValue(.comptime_int, operand_ty.bitSize(zcu))); } @@ -16251,7 +16252,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const type_info_ty = try sema.getBuiltinType(src, .Type); const type_info_tag_ty = type_info_ty.unionTagType(zcu).?; - try sema.ensureLayoutResolved(ty); + try sema.ensureLayoutResolved(ty, src); if (ty.typeDeclInst(zcu)) |type_decl_inst| { try sema.declareDependency(.{ .namespace = type_decl_inst }); @@ -16412,7 +16413,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai if (info.flags.alignment.toByteUnits()) |b| break :bytes b; const elem_ty: Type = .fromInterned(info.child); // MLUGG TODO: this resolution is sus, but i doubt i'll solve it in this branch - try sema.ensureLayoutResolved(elem_ty); + try sema.ensureLayoutResolved(elem_ty, src); break :bytes elem_ty.abiAlignment(zcu).toByteUnits().?; }); @@ -16873,7 +16874,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .struct_type => ip.loadStructType(ty.toIntern()), else => unreachable, }; - try sema.ensureStructDefaultsResolved(ty); // can't do this sooner, since it's not allowed on tuples + try sema.ensureStructDefaultsResolved(ty, src); // can't do this sooner, since it's not allowed on tuples struct_field_vals = try gpa.alloc(InternPool.Index, struct_type.field_types.len); for (struct_field_vals, 0..) |*field_val, field_index| { @@ -18294,7 +18295,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air elem_ty.fmt(pt), bit_offset, bit_offset - host_size * 8, host_size, }); } - try sema.ensureLayoutResolved(elem_ty); + try sema.ensureLayoutResolved(elem_ty, elem_ty_src); const elem_bit_size = elem_ty.bitSize(zcu); if (elem_bit_size > host_size * 8 - bit_offset) { return sema.fail(block, bitoffset_src, "packed type '{f}' at bit offset {d} ends {d} bits after the end of a {d} byte host integer", .{ @@ -18363,7 +18364,7 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE const pt = sema.pt; const zcu = pt.zcu; - try sema.ensureLayoutResolved(obj_ty); + try sema.ensureLayoutResolved(obj_ty, ty_src); switch (obj_ty.zigTypeTag(zcu)) { .@"struct" => return sema.structInitEmpty(block, obj_ty, src, src), @@ -18428,7 +18429,7 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is }); } else ty_operand; - try sema.ensureLayoutResolved(init_ty); + try sema.ensureLayoutResolved(init_ty, src); const obj_ty = init_ty.optEuBaseType(zcu); @@ -18544,7 +18545,7 @@ fn zirStructInit( // The type wasn't actually known, so treat this as an anon struct init. return sema.structInitAnon(block, src, inst, .typed_init, extra.data, extra.end, is_ref); }; - try sema.ensureLayoutResolved(result_ty); + try sema.ensureLayoutResolved(result_ty, src); const resolved_ty = result_ty.optEuBaseType(zcu); if (resolved_ty.zigTypeTag(zcu) == .@"struct") { @@ -18751,7 +18752,7 @@ fn finishStructInit( continue; } - try sema.ensureStructDefaultsResolved(struct_ty); + try sema.ensureStructDefaultsResolved(struct_ty, init_src); const field_default: InternPool.Index = d: { if (struct_type.field_defaults.len == 0) break :d .none; @@ -18979,17 +18980,11 @@ fn structInitAnon( }); if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - try zcu.outdated.ensureUnusedCapacity(gpa, 1); - try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); - errdefer comptime unreachable; // because we don't remove the `outdated` entries - zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); - zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); - break :ty .fromInterned(wip.finish(ip, new_namespace_index)); }, }; try sema.addTypeReferenceEntry(src, struct_ty); - try sema.ensureLayoutResolved(struct_ty); + try sema.ensureLayoutResolved(struct_ty, src); _ = opt_runtime_index orelse { const struct_val = try pt.aggregateValue(struct_ty, values); @@ -19308,7 +19303,7 @@ fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro const field_src = block.builtinCallArgSrc(inst_data.src_node, 1); const aggregate_ty = try sema.resolveType(block, ty_src, extra.container_type); const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .simple = .field_name }); - try sema.ensureLayoutResolved(aggregate_ty); + try sema.ensureLayoutResolved(aggregate_ty, ty_src); return sema.fieldType(block, aggregate_ty, field_name, field_src, ty_src); } @@ -19328,7 +19323,7 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp const aggregate_ty = wrapped_aggregate_ty.optEuBaseType(zcu); const zir_field_name = sema.code.nullTerminatedString(extra.name_start); const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_field_name, .no_embedded_nulls); - try sema.ensureLayoutResolved(aggregate_ty); + try sema.ensureLayoutResolved(aggregate_ty, ty_src); return sema.fieldType(block, aggregate_ty, field_name, field_name_src, ty_src); } @@ -19431,7 +19426,7 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air if (ty.isNoReturn(zcu)) { return sema.fail(block, operand_src, "no align available for type '{f}'", .{ty.fmt(sema.pt)}); } - try sema.ensureLayoutResolved(ty); + try sema.ensureLayoutResolved(ty, operand_src); return .fromValue(try pt.intValue(.comptime_int, ty.abiAlignment(zcu).toByteUnits().?)); } @@ -19912,7 +19907,7 @@ fn zirReifyFn( const param_attrs_arr = try sema.derefSliceAsArray(block, param_attrs_src, param_attrs_slice, .{ .simple = .fn_param_attrs }); const ret_ty = try sema.resolveType(block, ret_ty_src, extra.ret_ty); - try sema.ensureLayoutResolved(ret_ty); + try sema.ensureLayoutResolved(ret_ty, ret_ty_src); const fn_attrs_uncoerced = sema.resolveInst(extra.fn_attrs); const fn_attrs_coerced = try sema.coerce(block, fn_attrs_ty, fn_attrs_uncoerced, fn_attrs_src); @@ -19937,7 +19932,7 @@ fn zirReifyFn( param_types_src, fn_attrs.@"callconv", ); - try sema.ensureLayoutResolved(param_ty); + try sema.ensureLayoutResolved(param_ty, param_types_src); if (param_ty.comptimeOnly(zcu)) { return sema.fail(block, param_attrs_src, "cannot reify function type with comptime-only parameter type '{f}'", .{param_ty.fmt(pt)}); } @@ -20253,14 +20248,6 @@ fn zirReifyStruct( }); try sema.addTypeReferenceEntry(src, .fromInterned(wip.index)); if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind - try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) }); - - try zcu.outdated.ensureUnusedCapacity(gpa, 1); - try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); - errdefer comptime unreachable; // because we don't remove the `outdated` entries - zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); - zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); return .fromIntern(wip.finish(ip, new_namespace_index)); }, @@ -20482,15 +20469,6 @@ fn zirReifyUnion( if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); try sema.addTypeReferenceEntry(src, .fromInterned(wip.index)); - // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind - try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) }); - - try zcu.outdated.ensureUnusedCapacity(gpa, 1); - try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); - errdefer comptime unreachable; // because we don't remove the `outdated` entry - zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); - zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); - return .fromIntern(wip.finish(ip, new_namespace_index)); }, } @@ -20643,15 +20621,6 @@ fn zirReifyEnum( try sema.addTypeReferenceEntry(src, .fromInterned(wip.index)); if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind - try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) }); - - try zcu.outdated.ensureUnusedCapacity(gpa, 1); - try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); - errdefer comptime unreachable; // because we don't remove the `outdated` entry - zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); - zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); - return .fromIntern(wip.finish(ip, new_namespace_index)); }, } @@ -20874,7 +20843,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const elem_ty = ptr_ty.nullablePtrElem(zcu); // We'll need to validate the pointer alignment. - try sema.ensureLayoutResolved(elem_ty); + try sema.ensureLayoutResolved(elem_ty, src); const ptr_align = ptr_ty.ptrAlignment(zcu); if (ptr_ty.isSlice(zcu)) { @@ -21217,8 +21186,8 @@ fn ptrCastFull( const src_info = operand_ty.ptrInfo(zcu); const dest_info = dest_ty.ptrInfo(zcu); - try sema.ensureLayoutResolved(.fromInterned(src_info.child)); - try sema.ensureLayoutResolved(.fromInterned(dest_info.child)); + try sema.ensureLayoutResolved(.fromInterned(src_info.child), operand_src); + try sema.ensureLayoutResolved(.fromInterned(dest_info.child), src); const DestSliceLen = union(enum) { undef, @@ -21989,7 +21958,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 const ty = try sema.resolveType(block, ty_src, extra.lhs); const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.rhs, .{ .simple = .field_name }); - try sema.ensureLayoutResolved(ty); + try sema.ensureLayoutResolved(ty, ty_src); const pt = sema.pt; const zcu = pt.zcu; @@ -23072,7 +23041,7 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const ptr = try sema.checkAtomicPtrOperand(block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, true); const order = try sema.resolveAtomicOrder(block, order_src, extra.ordering, .{ .simple = .atomic_order }); - try sema.ensureLayoutResolved(elem_ty); + try sema.ensureLayoutResolved(elem_ty, elem_ty_src); switch (order) { .release, .acq_rel => { @@ -23392,7 +23361,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins return sema.fail(block, inst_src, "expected single pointer type, found '{f}'", .{parent_ptr_ty.fmt(pt)}); } const parent_ty: Type = .fromInterned(parent_ptr_info.child); - try sema.ensureLayoutResolved(parent_ty); + try sema.ensureLayoutResolved(parent_ty, inst_src); switch (parent_ty.zigTypeTag(zcu)) { .@"struct", .@"union" => {}, else => return sema.fail(block, inst_src, "expected pointer to struct or union type, found '{f}'", .{parent_ptr_ty.fmt(pt)}), @@ -24002,8 +23971,8 @@ fn zirMemcpy( const dest_elem_ty = dest_ty.indexableElem(zcu); const src_elem_ty = src_ty.indexableElem(zcu); - try sema.ensureLayoutResolved(dest_elem_ty); - try sema.ensureLayoutResolved(src_elem_ty); + try sema.ensureLayoutResolved(dest_elem_ty, dest_src); + try sema.ensureLayoutResolved(src_elem_ty, src_src); const imc = try sema.coerceInMemoryAllowed( block, @@ -25518,7 +25487,7 @@ fn fieldPtrLoad( const zcu = pt.zcu; const object_ptr_ty = sema.typeOf(object_ptr); const pointee_ty = object_ptr_ty.childType(zcu); - try sema.ensureLayoutResolved(pointee_ty); // MLUGG TODO + try sema.ensureLayoutResolved(pointee_ty, src); // MLUGG TODO if (try pointee_ty.onePossibleValue(pt)) |opv| { const object: Air.Inst.Ref = .fromValue(opv); return fieldVal(sema, block, src, object, field_name, field_name_src); @@ -25654,7 +25623,7 @@ fn fieldVal( if (try sema.namespaceLookupVal(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { return inst; } - try sema.ensureLayoutResolved(child_type); + try sema.ensureLayoutResolved(child_type, src); if (child_type.unionTagType(zcu)) |enum_ty| { if (enum_ty.enumFieldIndex(field_name, zcu)) |field_index_usize| { const field_index: u32 = @intCast(field_index_usize); @@ -25667,7 +25636,7 @@ fn fieldVal( if (try sema.namespaceLookupVal(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { return inst; } - try sema.ensureLayoutResolved(child_type); + try sema.ensureLayoutResolved(child_type, src); const field_index_usize = child_type.enumFieldIndex(field_name, zcu) orelse return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name); const field_index: u32 = @intCast(field_index_usize); @@ -25693,7 +25662,7 @@ fn fieldVal( }, .@"struct" => if (is_pointer_to) { // Avoid loading the entire struct by fetching a pointer and loading that - try sema.ensureLayoutResolved(inner_ty); + try sema.ensureLayoutResolved(inner_ty, src); const field_ptr = try sema.structFieldPtr(block, src, object, field_name, field_name_src, inner_ty, false); return sema.analyzeLoad(block, src, field_ptr, object_src); } else { @@ -25701,7 +25670,7 @@ fn fieldVal( }, .@"union" => if (is_pointer_to) { // Avoid loading the entire union by fetching a pointer and loading that - try sema.ensureLayoutResolved(inner_ty); + try sema.ensureLayoutResolved(inner_ty, src); const field_ptr = try sema.unionFieldPtr(block, src, object, field_name, field_name_src, inner_ty, false); return sema.analyzeLoad(block, src, field_ptr, object_src); } else { @@ -25884,7 +25853,7 @@ fn fieldPtr( if (try sema.namespaceLookupRef(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { return inst; } - try sema.ensureLayoutResolved(child_type); + try sema.ensureLayoutResolved(child_type, src); if (child_type.unionTagType(zcu)) |enum_ty| { if (enum_ty.enumFieldIndex(field_name, zcu)) |field_index| { const field_index_u32: u32 = @intCast(field_index); @@ -25898,7 +25867,7 @@ fn fieldPtr( if (try sema.namespaceLookupRef(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { return inst; } - try sema.ensureLayoutResolved(child_type); + try sema.ensureLayoutResolved(child_type, src); const field_index = child_type.enumFieldIndex(field_name, zcu) orelse { return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name); }; @@ -25920,7 +25889,7 @@ fn fieldPtr( try sema.analyzeLoad(block, src, object_ptr, object_ptr_src) else object_ptr; - try sema.ensureLayoutResolved(inner_ty); + try sema.ensureLayoutResolved(inner_ty, src); const field_ptr = try sema.structFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty, initializing); try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr); return field_ptr; @@ -25930,7 +25899,7 @@ fn fieldPtr( try sema.analyzeLoad(block, src, object_ptr, object_ptr_src) else object_ptr; - try sema.ensureLayoutResolved(inner_ty); + try sema.ensureLayoutResolved(inner_ty, src); const field_ptr = try sema.unionFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty, initializing); try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr); return field_ptr; @@ -25974,7 +25943,7 @@ fn fieldCallBind( // Optionally dereference a second pointer to get the concrete type. const is_double_ptr = inner_ty.zigTypeTag(zcu) == .pointer and inner_ty.ptrSize(zcu) == .one; const concrete_ty = if (is_double_ptr) inner_ty.childType(zcu) else inner_ty; - try sema.ensureLayoutResolved(concrete_ty); + try sema.ensureLayoutResolved(concrete_ty, src); const ptr_ty = if (is_double_ptr) inner_ty else raw_ptr_ty; const object_ptr = if (is_double_ptr) try sema.analyzeLoad(block, src, raw_ptr, src) @@ -26661,7 +26630,7 @@ fn elemPtr( else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{f}'", .{indexable_ptr_ty.fmt(pt)}), }; try sema.checkIndexable(block, src, indexable_ty); - try sema.ensureLayoutResolved(indexable_ty); + try sema.ensureLayoutResolved(indexable_ty, src); const elem_ptr = switch (indexable_ty.zigTypeTag(zcu)) { .array, .vector => try sema.elemPtrArray(block, src, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init, oob_safety), @@ -26673,7 +26642,7 @@ fn elemPtr( }, else => { const indexable = try sema.analyzeLoad(block, indexable_ptr_src, indexable_ptr, indexable_ptr_src); - try sema.ensureLayoutResolved(sema.typeOf(indexable).childType(zcu)); + try sema.ensureLayoutResolved(sema.typeOf(indexable).childType(zcu), src); return elemPtrOneLayerOnly(sema, block, src, indexable, elem_index, elem_index_src, init, oob_safety); }, }; @@ -26769,7 +26738,7 @@ fn elemVal( switch (indexable_ty.zigTypeTag(zcu)) { .pointer => { const child_ty = indexable_ty.childType(zcu); - try sema.ensureLayoutResolved(child_ty); + try sema.ensureLayoutResolved(child_ty, src); switch (indexable_ty.ptrSize(zcu)) { .slice => return sema.elemValSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety), .many, .c => { @@ -27293,7 +27262,7 @@ fn coerceExtra( const target = zcu.getTarget(); inst_ty.assertHasLayout(zcu); - try sema.ensureLayoutResolved(dest_ty); + try sema.ensureLayoutResolved(dest_ty, inst_src); // If the types are the same, we can return the operand. if (dest_ty.eql(inst_ty, zcu)) @@ -28657,8 +28626,8 @@ fn coerceInMemoryAllowedFns( } }; } - try sema.ensureLayoutResolved(src_ty); - try sema.ensureLayoutResolved(dest_ty); + try sema.ensureLayoutResolved(src_ty, src_src); + try sema.ensureLayoutResolved(dest_ty, dest_src); const src_is_runtime = src_ty.fnHasRuntimeBits(zcu); const dest_is_runtime = dest_ty.fnHasRuntimeBits(zcu); if (src_is_runtime != dest_is_runtime) return .{ .fn_generic = !dest_is_runtime }; @@ -28712,7 +28681,7 @@ fn coerceInMemoryAllowedFns( const src_is_comptime = src_info.paramIsComptime(@intCast(param_i)); const dest_is_comptime = dest_info.paramIsComptime(@intCast(param_i)); if (src_is_comptime == dest_is_comptime) break :comptime_param; - try sema.ensureLayoutResolved(dest_param_ty); + try sema.ensureLayoutResolved(dest_param_ty, dest_src); if (!dest_is_mut and src_is_comptime and !dest_is_comptime and dest_param_ty.comptimeOnly(zcu)) { // A parameter which is marked `comptime` can drop that annotation if the type is comptime-only. // The function remains generic, and the parameter is going to be comptime-resolved either way, @@ -28940,11 +28909,11 @@ fn coerceInMemoryAllowedPtrs( dest_info.child != src_info.child) { const src_align = if (src_info.flags.alignment == .none) a: { - try sema.ensureLayoutResolved(src_child); + try sema.ensureLayoutResolved(src_child, src_src); break :a src_child.abiAlignment(zcu); } else src_info.flags.alignment; const dest_align = if (dest_info.flags.alignment == .none) a: { - try sema.ensureLayoutResolved(dest_child); + try sema.ensureLayoutResolved(dest_child, dest_src); break :a dest_child.abiAlignment(zcu); } else dest_info.flags.alignment; if (dest_align.compare(if (dest_is_mut) .neq else .gt, src_align)) { @@ -29294,7 +29263,7 @@ fn bitCast( const old_ty = sema.typeOf(inst); old_ty.assertHasLayout(zcu); - try sema.ensureLayoutResolved(dest_ty); + try sema.ensureLayoutResolved(dest_ty, inst_src); const dest_bits = dest_ty.bitSize(zcu); const old_bits = old_ty.bitSize(zcu); @@ -29908,7 +29877,7 @@ fn analyzeNavVal( return sema.analyzeLoad(block, src, ref, src); } -fn addReferenceEntry( +pub fn addReferenceEntry( sema: *Sema, opt_block: ?*Block, src: LazySrcLoc, @@ -30176,7 +30145,7 @@ fn analyzeLoad( return sema.fail(block, ptr_src, "cannot load opaque type '{f}'", .{elem_ty.fmt(pt)}); } - try sema.ensureLayoutResolved(elem_ty); + try sema.ensureLayoutResolved(elem_ty, src); if (try elem_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { @@ -30561,7 +30530,7 @@ fn analyzeSlice( else => return sema.fail(block, src, "slice of non-array type '{f}'", .{ptr_ptr_child_ty.fmt(pt)}), } - try sema.ensureLayoutResolved(elem_ty); + try sema.ensureLayoutResolved(elem_ty, src); const ptr = if (slice_ty.isSlice(zcu)) try sema.analyzeSlicePtr(block, ptr_src, ptr_or_slice, slice_ty) @@ -34024,7 +33993,7 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, .type => if (uncoerced_val.typeOf(zcu).zigTypeTag(zcu) != .type) { return sema.fail(block, src, "{s}.{s} is not a type", .{ parent_name, name }); } else val: { - try sema.ensureLayoutResolved(uncoerced_val.toType()); + try sema.ensureLayoutResolved(uncoerced_val.toType(), src); break :val uncoerced_val; }, .func => val: { @@ -34271,20 +34240,9 @@ fn zirStructDecl( }); errdefer pt.destroyNamespace(new_namespace_index); try pt.scanNamespace(new_namespace_index, struct_decl.decls); - // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind - try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) }); - try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .struct_defaults = wip.index }) }); if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - try zcu.outdated.ensureUnusedCapacity(gpa, 2); - try zcu.outdated_ready.ensureUnusedCapacity(gpa, 2); - errdefer comptime unreachable; // because we don't remove the `outdated` entries - zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); - zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .struct_defaults = wip.index }), 0); - zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); - zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .struct_defaults = wip.index }), {}); - break :ty .fromInterned(wip.finish(ip, new_namespace_index)); }, }; @@ -34364,17 +34322,8 @@ fn zirUnionDecl( try pt.scanNamespace(new_namespace_index, union_decl.decls); - // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind - try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) }); - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - try zcu.outdated.ensureUnusedCapacity(gpa, 1); - try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); - errdefer comptime unreachable; // because we don't remove the `outdated` entry - zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); - zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); - break :ty .fromInterned(wip.finish(ip, new_namespace_index)); }, }; @@ -34434,17 +34383,8 @@ fn zirEnumDecl( try pt.scanNamespace(new_namespace_index, enum_decl.decls); - // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind - try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) }); - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - try zcu.outdated.ensureUnusedCapacity(gpa, 1); - try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); - errdefer comptime unreachable; // because we don't remove the `outdated` entry - zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); - zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); - break :ty .fromInterned(wip.finish(ip, new_namespace_index)); }, }; diff --git a/src/Sema/LowerZon.zig b/src/Sema/LowerZon.zig index bb10a39729ad41d3e74af62428b671985c13a0cf..71256ae44ddc4e6283171172bfb0cdda3f8eb50e 100644 --- a/src/Sema/LowerZon.zig +++ b/src/Sema/LowerZon.zig @@ -300,7 +300,7 @@ fn checkTypeInner( } else { const gop = try visited.getOrPut(sema.arena, ty.toIntern()); if (gop.found_existing) return; - try sema.ensureLayoutResolved(ty); + try sema.ensureLayoutResolved(ty, self.import_loc); const struct_info = zcu.typeToStruct(ty).?; for (struct_info.field_types.get(ip)) |field_type| { try self.checkTypeInner(.fromInterned(field_type), null, visited); @@ -309,7 +309,7 @@ fn checkTypeInner( .@"union" => { const gop = try visited.getOrPut(sema.arena, ty.toIntern()); if (gop.found_existing) return; - try sema.ensureLayoutResolved(ty); + try sema.ensureLayoutResolved(ty, self.import_loc); const union_info = zcu.typeToUnion(ty).?; for (union_info.field_types.get(ip)) |field_type| { if (field_type != .void_type) { @@ -646,6 +646,7 @@ fn lowerEnum(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.I const gpa = comp.gpa; const io = comp.io; const ip = &pt.zcu.intern_pool; + try self.sema.ensureLayoutResolved(res_ty, self.import_loc); switch (node.get(self.file.zoir.?)) { .enum_literal => |field_name| { const field_name_interned = try ip.getOrPutString( @@ -768,8 +769,8 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool const io = comp.io; const ip = &pt.zcu.intern_pool; - try self.sema.ensureLayoutResolved(res_ty); - try self.sema.ensureStructDefaultsResolved(res_ty); + try self.sema.ensureLayoutResolved(res_ty, self.import_loc); + try self.sema.ensureStructDefaultsResolved(res_ty, self.import_loc); const struct_info = self.sema.pt.zcu.typeToStruct(res_ty).?; const fields: @FieldType(Zoir.Node, "struct_literal") = switch (node.get(self.file.zoir.?)) { @@ -919,7 +920,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. const gpa = comp.gpa; const io = comp.io; const ip = &pt.zcu.intern_pool; - try self.sema.ensureLayoutResolved(res_ty); + try self.sema.ensureLayoutResolved(res_ty, self.import_loc); const union_info = pt.zcu.typeToUnion(res_ty).?; const enum_tag_info = ip.loadEnumType(union_info.enum_tag_type); diff --git a/src/Sema/bitcast.zig b/src/Sema/bitcast.zig index ee70bd1746466aaf57c8812083f37892e69dac59..b496db1ce0e167aad6cacf51568ecc9bb91cde97 100644 --- a/src/Sema/bitcast.zig +++ b/src/Sema/bitcast.zig @@ -80,7 +80,7 @@ fn bitCastInner( const val_ty = val.typeOf(zcu); val_ty.assertHasLayout(zcu); - try sema.ensureLayoutResolved(dest_ty); + dest_ty.assertHasLayout(zcu); assert(val_ty.hasWellDefinedLayout(zcu)); @@ -138,8 +138,8 @@ fn bitCastSpliceInner( const val_ty = val.typeOf(zcu); const splice_val_ty = splice_val.typeOf(zcu); - try sema.ensureLayoutResolved(val_ty); - try sema.ensureLayoutResolved(splice_val_ty); + val_ty.assertHasLayout(zcu); + splice_val_ty.assertHasLayout(zcu); const splice_bits = splice_val_ty.bitSize(zcu); diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig index f18cf9aaaeae1557d1a69799516d0f7687096dd0..970cf4f0116328dc6f84fe4c1e755eb71a4a915a 100644 --- a/src/Sema/type_resolution.zig +++ b/src/Sema/type_resolution.zig @@ -19,7 +19,7 @@ const arith = @import("arith.zig"); /// Adds incremental dependencies tracking any required type resolution. /// MLUGG TODO: to make the langspec non-stupid, we need to call this from WAY fewer places (the conditions need to be less specific). /// MLUGG TODO: to be clear, i should audit EVERY use of this before PRing -pub fn ensureLayoutResolved(sema: *Sema, ty: Type) SemaError!void { +pub fn ensureLayoutResolved(sema: *Sema, ty: Type, src: LazySrcLoc) SemaError!void { const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; @@ -35,20 +35,21 @@ pub fn ensureLayoutResolved(sema: *Sema, ty: Type) SemaError!void { .func_type => |func_type| { for (func_type.param_types.get(ip)) |param_ty| { - try ensureLayoutResolved(sema, .fromInterned(param_ty)); + try ensureLayoutResolved(sema, .fromInterned(param_ty), src); } - try ensureLayoutResolved(sema, .fromInterned(func_type.return_type)); + try ensureLayoutResolved(sema, .fromInterned(func_type.return_type), src); }, - .array_type => |arr| return ensureLayoutResolved(sema, .fromInterned(arr.child)), - .vector_type => |vec| return ensureLayoutResolved(sema, .fromInterned(vec.child)), - .opt_type => |child| return ensureLayoutResolved(sema, .fromInterned(child)), - .error_union_type => |eu| return ensureLayoutResolved(sema, .fromInterned(eu.payload_type)), + .array_type => |arr| return ensureLayoutResolved(sema, .fromInterned(arr.child), src), + .vector_type => |vec| return ensureLayoutResolved(sema, .fromInterned(vec.child), src), + .opt_type => |child| return ensureLayoutResolved(sema, .fromInterned(child), src), + .error_union_type => |eu| return ensureLayoutResolved(sema, .fromInterned(eu.payload_type), src), .tuple_type => |tuple| for (tuple.types.get(ip)) |field_ty| { - try ensureLayoutResolved(sema, .fromInterned(field_ty)); + try ensureLayoutResolved(sema, .fromInterned(field_ty), src); }, .struct_type, .union_type, .enum_type => { try sema.declareDependency(.{ .type_layout = ty.toIntern() }); + try sema.addReferenceEntry(null, src, .wrap(.{ .type_layout = ty.toIntern() })); if (zcu.analysis_in_progress.contains(.wrap(.{ .type_layout = ty.toIntern() }))) { // TODO: better error message return sema.failWithOwnedErrorMsg(null, try sema.errMsg( @@ -89,13 +90,14 @@ pub fn ensureLayoutResolved(sema: *Sema, ty: Type) SemaError!void { /// /// It is not necessary to call this function to query the values of comptime fields: those values /// are available from type *layout* resolution, see `ensureLayoutResolved`. -pub fn ensureStructDefaultsResolved(sema: *Sema, ty: Type) SemaError!void { +pub fn ensureStructDefaultsResolved(sema: *Sema, ty: Type, src: LazySrcLoc) SemaError!void { const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; assert(ip.indexToKey(ty.toIntern()) == .struct_type); try sema.declareDependency(.{ .struct_defaults = ty.toIntern() }); + try sema.addReferenceEntry(null, src, .wrap(.{ .struct_defaults = ty.toIntern() })); if (zcu.analysis_in_progress.contains(.wrap(.{ .struct_defaults = ty.toIntern() }))) { // TODO: better error message return sema.failWithOwnedErrorMsg(null, try sema.errMsg( @@ -120,7 +122,8 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { assert(sema.owner.unwrap().type_layout == struct_ty.toIntern()); const struct_obj = ip.loadStructType(struct_ty.toIntern()); - const zir_index = struct_obj.zir_index.resolve(ip).?; + assert(struct_obj.want_layout); + const zir_index = struct_obj.zir_index.resolve(ip) orelse return error.AnalysisFail; var block: Block = .{ .parent = null, @@ -219,7 +222,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { const field_ty: Type = .fromInterned(field_ty_ip); assert(!field_ty.isGenericPoison()); const field_ty_src = block.src(.{ .container_field_type = @intCast(field_index) }); - try sema.ensureLayoutResolved(field_ty); + try sema.ensureLayoutResolved(field_ty, field_ty_src); if (field_ty.zigTypeTag(zcu) == .@"opaque") { return sema.failWithOwnedErrorMsg(&block, msg: { @@ -368,7 +371,7 @@ fn resolvePackedStructLayout( const field_ty: Type = .fromInterned(field_ty_ip); assert(!field_ty.isGenericPoison()); const field_ty_src = block.src(.{ .container_field_type = @intCast(field_index) }); - try sema.ensureLayoutResolved(field_ty); + try sema.ensureLayoutResolved(field_ty, field_ty_src); if (field_ty.zigTypeTag(zcu) == .@"opaque") { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in struct", .{field_ty.fmt(pt)}); @@ -458,17 +461,20 @@ pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void { assert(sema.owner.unwrap().struct_defaults == struct_ty.toIntern()); - try sema.ensureLayoutResolved(struct_ty); + try sema.ensureLayoutResolved(struct_ty, struct_ty.srcLoc(zcu)); const struct_obj = ip.loadStructType(struct_ty.toIntern()); + assert(struct_obj.want_defaults); + + if (struct_obj.is_reified) { + // `Sema.zirReifyStruct` has already populated the default field values *and* (by loading + // the default values from pointers) validated their types, so we have nothing to do. We + // don't even need to mark any dependencies. + return; + } try sema.declareDependency(.{ .src_hash = struct_obj.zir_index }); - // This logic isn't used for reified structs, because the signature of `@Struct` requires that - // default values are populated and correctly typed from the moment the struct type is interned - // (because `Sema.zirReifyStruct` had to dereference the default value from a pointer). - assert(!struct_obj.is_reified); - if (struct_obj.field_defaults.len == 0) { // The struct has no default field values, so the slice has been omitted. return; @@ -509,7 +515,7 @@ fn resolveStructDefaultsInner( const ip = &zcu.intern_pool; // We'll need to map the struct decl instruction to provide result types - const zir_index = struct_obj.zir_index.resolve(ip).?; + const zir_index = struct_obj.zir_index.resolve(ip) orelse return error.AnalysisFail; try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index}); const field_types = struct_obj.field_types.get(ip); @@ -555,7 +561,8 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { assert(sema.owner.unwrap().type_layout == union_ty.toIntern()); const union_obj = ip.loadUnionType(union_ty.toIntern()); - const zir_index = union_obj.zir_index.resolve(ip).?; + assert(union_obj.want_layout); + const zir_index = union_obj.zir_index.resolve(ip) orelse return error.AnalysisFail; var block: Block = .{ .parent = null, @@ -627,16 +634,11 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { .generation = zcu.generation, }); if (comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - try zcu.outdated.ensureUnusedCapacity(gpa, 1); - try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); - errdefer comptime unreachable; // because we don't remove the `outdated` entry - zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); - zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); break :tag_ty .fromInterned(wip.finish(ip, new_namespace_index)); }, }; - try sema.ensureLayoutResolved(enum_tag_ty); + try sema.ensureLayoutResolved(enum_tag_ty, block.src(.container_arg)); const enum_obj = ip.loadEnumType(enum_tag_ty.toIntern()); if (union_obj.is_reified) { @@ -731,7 +733,7 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { const field_ty: Type = .fromInterned(field_ty_ip); assert(!field_ty.isGenericPoison()); const field_ty_src = block.src(.{ .container_field_type = @intCast(field_index) }); - try sema.ensureLayoutResolved(field_ty); + try sema.ensureLayoutResolved(field_ty, field_ty_src); if (field_ty.zigTypeTag(zcu) == .@"opaque") { return sema.failWithOwnedErrorMsg(&block, msg: { const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in union", .{field_ty.fmt(pt)}); @@ -889,7 +891,7 @@ fn resolvePackedUnionLayout( const field_ty: Type = .fromInterned(field_ty_ip); assert(!field_ty.isGenericPoison()); const field_ty_src = block.src(.{ .container_field_type = @intCast(field_index) }); - try sema.ensureLayoutResolved(field_ty); + try sema.ensureLayoutResolved(field_ty, field_ty_src); if (field_ty.zigTypeTag(zcu) == .@"opaque") { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in union", .{field_ty.fmt(pt)}); @@ -995,6 +997,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void { assert(sema.owner.unwrap().type_layout == enum_ty.toIntern()); const enum_obj = ip.loadEnumType(enum_ty.toIntern()); + assert(enum_obj.want_layout); const maybe_parent_union_obj: ?InternPool.LoadedUnionType = un: { if (enum_obj.owner_union == .none) break :un null; @@ -1002,6 +1005,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void { }; const tracked_inst = enum_obj.zir_index.unwrap() orelse maybe_parent_union_obj.?.zir_index; + const zir_index = tracked_inst.resolve(ip) orelse return error.AnalysisFail; var block: Block = .{ .parent = null, @@ -1040,7 +1044,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void { // Generated tag enums for declared unions do not yet have field names populated. It is // our job to populate them now. try sema.declareDependency(.{ .src_hash = union_obj.zir_index }); - const zir_union = sema.code.getUnionDecl(union_obj.zir_index.resolve(ip).?); + const zir_union = sema.code.getUnionDecl(zir_index); for (zir_union.field_names) |zir_field_name| { const name_slice = sema.code.nullTerminatedString(zir_field_name); const name = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls); @@ -1065,7 +1069,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void { } else { // Declared enums do not yet have field names populated. It is our job to populate them now. try sema.declareDependency(.{ .src_hash = enum_obj.zir_index.unwrap().? }); - const zir_enum = sema.code.getEnumDecl(enum_obj.zir_index.unwrap().?.resolve(ip).?); + const zir_enum = sema.code.getEnumDecl(zir_index); for (zir_enum.field_names) |zir_field_name| { const name_slice = sema.code.nullTerminatedString(zir_field_name); const name = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls); @@ -1087,7 +1091,6 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void { // Reification has no equivalent of 'union(enum(T))'. break :ty null; } - const zir_index = union_obj.zir_index.resolve(ip).?; const zir_union = sema.code.getUnionDecl(zir_index); if (zir_union.kind != .tagged_enum_explicit) { break :ty null; // int tag type will be inferred @@ -1102,7 +1105,6 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void { const type_ref = try sema.resolveInlineBody(&block, tag_type_body, zir_index); break :ty try sema.analyzeAsType(&block, tag_type_src, .enum_int_tag_type, type_ref); } else ty: { - const zir_index = enum_obj.zir_index.unwrap().?.resolve(ip).?; const zir_enum = sema.code.getEnumDecl(zir_index); const tag_type_body = zir_enum.tag_type_body orelse { break :ty null; // int tag type will be inferred @@ -1147,8 +1149,6 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void { // There may be old field values in here from a previous update. field_value_map.get(ip).clearRetainingCapacity(); - const zir_index = tracked_inst.resolve(ip).?; - // Map the enum (or union) decl instruction to provide the tag type as the result type try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index}); sema.inst_map.putAssumeCapacity(zir_index, .fromIntern(int_tag_ty.toIntern())); diff --git a/src/Type.zig b/src/Type.zig index ca94c09bf04fc00503dc414541a0861194cf4256..5b5839cf6f40e5953e182162289aa2e7b05ba96d 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -3044,7 +3044,20 @@ pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void { .tuple_type => |tuple| for (tuple.types.get(&zcu.intern_pool)) |field_ty| { assertHasLayout(.fromInterned(field_ty), zcu); }, - .struct_type, .union_type, .enum_type => { + .struct_type => { + assert(zcu.intern_pool.loadStructType(ty.toIntern()).want_layout); + const unit: InternPool.AnalUnit = .wrap(.{ .type_layout = ty.toIntern() }); + assert(!zcu.outdated.contains(unit)); + assert(!zcu.potentially_outdated.contains(unit)); + }, + .union_type => { + assert(zcu.intern_pool.loadUnionType(ty.toIntern()).want_layout); + const unit: InternPool.AnalUnit = .wrap(.{ .type_layout = ty.toIntern() }); + assert(!zcu.outdated.contains(unit)); + assert(!zcu.potentially_outdated.contains(unit)); + }, + .enum_type => { + assert(zcu.intern_pool.loadEnumType(ty.toIntern()).want_layout); const unit: InternPool.AnalUnit = .wrap(.{ .type_layout = ty.toIntern() }); assert(!zcu.outdated.contains(unit)); assert(!zcu.potentially_outdated.contains(unit)); diff --git a/src/Value.zig b/src/Value.zig index de7aacd1e1f2c84737acb243aa1565ac5fc0a94b..d513e5d07d9d07311a7d15b106e57795b54e92be 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -2149,7 +2149,7 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh const base_ptr = Value.fromInterned(field.base); const base_ptr_ty = base_ptr.typeOf(zcu); const agg_ty = base_ptr_ty.childType(zcu); - if (resolve_types) try opt_sema.?.ensureLayoutResolved(agg_ty); + if (resolve_types) try opt_sema.?.ensureLayoutResolved(agg_ty, .unneeded); // MLUGG TODO: unneeded is a hack const field_ty: Type, const field_align: InternPool.Alignment = switch (agg_ty.zigTypeTag(zcu)) { .@"struct", .@"union" => .{ agg_ty.fieldType(@intCast(field.index), zcu), agg_ty.resolvedFieldAlignment(@intCast(field.index), pt.zcu) }, .pointer => switch (field.index) { diff --git a/src/Zcu.zig b/src/Zcu.zig index 3b17bc1c0981d1e19f57db43412f4b309484faf4..aedbf7043c32aa83d8e7988d8bd3bb2304476632 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -266,9 +266,6 @@ outdated_ready: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .empty, /// it as outdated. retryable_failures: std.ArrayList(AnalUnit) = .empty, -func_body_analysis_queued: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .empty, -nav_val_analysis_queued: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty, - /// These are the modules which we initially queue for analysis in `Compilation.update`. /// `resolveReferences` will use these as the root of its reachability traversal. analysis_roots_buffer: [5]*Package.Module, @@ -2814,9 +2811,6 @@ pub fn deinit(zcu: *Zcu) void { zcu.outdated_ready.deinit(gpa); zcu.retryable_failures.deinit(gpa); - zcu.func_body_analysis_queued.deinit(gpa); - zcu.nav_val_analysis_queued.deinit(gpa); - zcu.test_functions.deinit(gpa); for (zcu.global_assembly.values()) |s| { @@ -3179,8 +3173,6 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni /// recursive analysis (all of its previously-marked dependencies are already up-to-date), because /// recursive analysis can cause over-analysis on incremental updates. pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { - if (!zcu.comp.config.incremental) return null; - if (zcu.outdated_ready.count() > 0) { const unit = zcu.outdated_ready.keys()[0]; log.debug("findOutdatedToAnalyze: {f}", .{zcu.fmtAnalUnit(unit)}); @@ -3458,47 +3450,35 @@ pub fn mapOldZirToNew( /// The caller is responsible for ensuring the function decl itself is already /// analyzed, and for ensuring it can exist at runtime (see /// `Type.fnHasRuntimeBitsSema`). This function does *not* guarantee that the body -/// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`. -pub fn ensureFuncBodyAnalysisQueued(zcu: *Zcu, func_index: InternPool.Index) !void { +/// will be analyzed when it returns: for that, see `PerThread.ensureFuncBodyUpToDate`. +pub fn ensureFuncBodyAnalysisQueued(zcu: *Zcu, func: InternPool.Index) !void { + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; - - const func = zcu.funcInfo(func_index); - - assert(func.ty == func.uncoerced_ty); // analyze the body of the original function, not a coerced one - - if (zcu.func_body_analysis_queued.contains(func_index)) return; - - if (func.analysisUnordered(ip).is_analyzed) { - if (!zcu.outdated.contains(.wrap(.{ .func = func_index })) and - !zcu.potentially_outdated.contains(.wrap(.{ .func = func_index }))) - { - // This function has been analyzed before and is definitely up-to-date. - return; - } + assert(func == ip.unwrapCoercedFunc(func)); // analyze the body of the original function, not a coerced one + if (ip.setWantRuntimeFnAnalysis(io, func)) { + // This is the first reference to this function, so we must ensure it will be analyzed. + const unit: AnalUnit = .wrap(.{ .func = func }); + try zcu.outdated.putNoClobber(gpa, unit, 0); + try zcu.outdated_ready.putNoClobber(gpa, unit, {}); } - - try zcu.func_body_analysis_queued.ensureUnusedCapacity(zcu.gpa, 1); - try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .func = func_index }) }); - zcu.func_body_analysis_queued.putAssumeCapacityNoClobber(func_index, {}); } -pub fn ensureNavValAnalysisQueued(zcu: *Zcu, nav_id: InternPool.Nav.Index) !void { +pub fn ensureNavValAnalysisQueued(zcu: *Zcu, nav: InternPool.Nav.Index) !void { + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; const ip = &zcu.intern_pool; - - if (zcu.nav_val_analysis_queued.contains(nav_id)) return; - - if (ip.getNav(nav_id).status == .fully_resolved) { - if (!zcu.outdated.contains(.wrap(.{ .nav_val = nav_id })) and - !zcu.potentially_outdated.contains(.wrap(.{ .nav_val = nav_id }))) - { - // This `Nav` has been analyzed before and is definitely up-to-date. - return; - } + if (ip.setWantNavAnalysis(io, nav)) { + // This is the first reference to this function, so we must ensure it will be analyzed. + try zcu.outdated.ensureUnusedCapacity(gpa, 2); + try zcu.outdated_ready.ensureUnusedCapacity(gpa, 2); + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .nav_val = nav }), 0); + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .nav_ty = nav }), 0); + zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .nav_val = nav }), {}); + zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .nav_ty = nav }), {}); } - - try zcu.nav_val_analysis_queued.ensureUnusedCapacity(zcu.gpa, 1); - try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .nav_val = nav_id }) }); - zcu.nav_val_analysis_queued.putAssumeCapacityNoClobber(nav_id, {}); } pub const ImportResult = struct { @@ -4035,37 +4015,6 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R refs_log.debug("handle type '{f}'", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)}); - // If this type undergoes type resolution, the corresponding `AnalUnit`s are automatically referenced. - const has_layout: bool, const has_inits: bool = switch (ip.indexToKey(ty)) { - .struct_type => .{ true, true }, - .union_type => .{ true, false }, - .enum_type => .{ false, true }, - .opaque_type => .{ false, false }, - else => unreachable, - }; - if (has_layout) { - // this should only be referenced by the type - const unit: AnalUnit = .wrap(.{ .type_layout = ty }); - try units.putNoClobber(gpa, unit, referencer); - } - if (has_inits) { - // this should only be referenced by the type - const unit: AnalUnit = .wrap(.{ .struct_defaults = ty }); - try units.putNoClobber(gpa, unit, referencer); - } - - // If this is a union with a generated tag, its tag type is automatically referenced. - // We don't add this reference for non-generated tags, as those will already be referenced via the union's type resolution, with a better source location. - implicit_tag: { - const loaded_union = zcu.typeToUnion(.fromInterned(ty)) orelse break :implicit_tag; - const tag_ty = loaded_union.enum_tag_type; - if (tag_ty == .none) break :implicit_tag; - if (ip.indexToKey(tag_ty).enum_type != .generated_union_tag) break :implicit_tag; - const gop = try types.getOrPut(gpa, tag_ty); - if (gop.found_existing) break :implicit_tag; - gop.value_ptr.* = referencer; - } - // Queue any decls within this type which would be automatically analyzed. // Keep in sync with analysis queueing logic in `Zcu.PerThread.ScanDeclIter.scanDecl`. const ns = Type.fromInterned(ty).getNamespace(zcu).unwrap().?; diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index d937367c4ac871c61e7bd285e9ddf04f7df175c7..00c911caf4e67e3a7dcf5691ebe7cf45d53ff002 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -719,20 +719,9 @@ pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Alloca }); errdefer pt.destroyNamespace(new_namespace_index); try pt.scanNamespace(new_namespace_index, struct_decl.decls); - // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind - try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) }); - try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .struct_defaults = wip.index }) }); if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - try zcu.outdated.ensureUnusedCapacity(gpa, 2); - try zcu.outdated_ready.ensureUnusedCapacity(gpa, 2); - errdefer comptime unreachable; // because we don't remove the `outdated` entries - zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0); - zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .struct_defaults = wip.index }), 0); - zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {}); - zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .struct_defaults = wip.index }), {}); - const file_root_type: Type = .fromInterned(wip.finish(ip, new_namespace_index)); zcu.setFileRootType(file_index, file_root_type.toIntern()); @@ -1075,11 +1064,12 @@ pub fn ensureTypeLayoutUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void assert(!zcu.analysis_in_progress.contains(anal_unit)); const was_outdated = zcu.outdated.swapRemove(anal_unit) or - zcu.potentially_outdated.swapRemove(anal_unit); + zcu.potentially_outdated.swapRemove(anal_unit) or + zcu.intern_pool.setWantTypeLayout(zcu.comp.io, ty.toIntern()); if (was_outdated) { _ = zcu.outdated_ready.swapRemove(anal_unit); - // `was_outdated` can be true in the initial update for comptime units, so this isn't a `dev.check`. + // `was_outdated` is true in the initial update, so this isn't a `dev.check`. if (dev.env.supports(.incremental)) { zcu.deleteUnitExports(anal_unit); zcu.deleteUnitReferences(anal_unit); @@ -1182,16 +1172,13 @@ pub fn ensureStructDefaultsUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!v assert(!zcu.analysis_in_progress.contains(anal_unit)); - // Determine whether or not this type is outdated. For this kind of `AnalUnit`, that's - // the only indicator as to whether or not analysis is required; when a struct/enum is - // first created, it's marked as outdated. - const was_outdated = zcu.outdated.swapRemove(anal_unit) or - zcu.potentially_outdated.swapRemove(anal_unit); + zcu.potentially_outdated.swapRemove(anal_unit) or + zcu.intern_pool.setWantStructDefaults(zcu.comp.io, ty.toIntern()); if (was_outdated) { _ = zcu.outdated_ready.swapRemove(anal_unit); - // `was_outdated` can be true in the initial update for comptime units, so this isn't a `dev.check`. + // `was_outdated` is true in the initial update, so this isn't a `dev.check`. if (dev.env.supports(.incremental)) { zcu.deleteUnitExports(anal_unit); zcu.deleteUnitReferences(anal_unit); @@ -1279,8 +1266,6 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu const gpa = zcu.gpa; const ip = &zcu.intern_pool; - _ = zcu.nav_val_analysis_queued.swapRemove(nav_id); - const anal_unit: AnalUnit = .wrap(.{ .nav_val = nav_id }); const nav = ip.getNav(nav_id); @@ -1288,6 +1273,8 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu assert(!zcu.analysis_in_progress.contains(anal_unit)); + try zcu.ensureNavValAnalysisQueued(nav_id); + // Determine whether or not this `Nav`'s value is outdated. This also includes checking if the // status is `.unresolved`, which indicates that the value is outdated because it has *never* // been analyzed so far. @@ -1317,10 +1304,8 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu } else { // We can trust the current information about this unit. if (prev_failed) return error.AnalysisFail; - switch (nav.status) { - .unresolved, .type_resolved => {}, - .fully_resolved => return, - } + assert(nav.status == .fully_resolved); + return; } if (zcu.comp.debugIncremental()) { @@ -1488,9 +1473,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr const maybe_ty: ?Type = if (zir_decl.type_body != null) ty: { // Since we have a type body, the type is resolved separately! - // Of course, we need to make sure we depend on it properly. - try sema.declareDependency(.{ .nav_ty = nav_id }); - try pt.ensureNavTypeUpToDate(nav_id); + try sema.ensureNavResolved(&block, init_src, nav_id, .type); break :ty .fromInterned(ip.getNav(nav_id).typeOf(ip)); } else null; @@ -1602,7 +1585,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr // This resolves the type of the resolved value, not that value itself. If `nav_val` is a struct type, // this resolves the type `type` (which needs no resolution), not the struct itself. - try sema.ensureLayoutResolved(nav_ty); + try sema.ensureLayoutResolved(nav_ty, init_src); const queue_linker_work, const is_owned_fn = switch (ip.indexToKey(nav_val.toIntern())) { .func => |f| .{ true, f.owner_nav == nav_id }, // note that this lets function aliases reach codegen @@ -1692,6 +1675,8 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc assert(!zcu.analysis_in_progress.contains(anal_unit)); + try zcu.ensureNavValAnalysisQueued(nav_id); + const type_resolved_by_value: bool = from_val: { const analysis = nav.analysis orelse break :from_val false; const inst_resolved = analysis.zir_index.resolveFull(ip) orelse break :from_val false; @@ -1733,10 +1718,8 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc } else { // We can trust the current information about this unit. if (prev_failed) return error.AnalysisFail; - switch (nav.status) { - .unresolved => {}, - .type_resolved, .fully_resolved => return, - } + assert(nav.status != .unresolved); + return; } if (zcu.comp.debugIncremental()) { @@ -1869,7 +1852,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr break :ty .fromInterned(type_ref.toInterned().?); }; - try sema.ensureLayoutResolved(resolved_ty); + try sema.ensureLayoutResolved(resolved_ty, ty_src); // In the case where the type is specified, this function is also responsible for resolving // the pointer modifiers, i.e. alignment, linksection, addrspace. @@ -1929,8 +1912,6 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, func_index: InternPool.Index) Z const gpa = zcu.gpa; const ip = &zcu.intern_pool; - _ = zcu.func_body_analysis_queued.swapRemove(func_index); - const anal_unit: AnalUnit = .wrap(.{ .func = func_index }); log.debug("ensureFuncBodyUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)}); @@ -1942,7 +1923,8 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, func_index: InternPool.Index) Z assert(func.ty == func.uncoerced_ty); // analyze the body of the original function, not a coerced one const was_outdated = zcu.outdated.swapRemove(anal_unit) or - zcu.potentially_outdated.swapRemove(anal_unit); + zcu.potentially_outdated.swapRemove(anal_unit) or + ip.setWantRuntimeFnAnalysis(zcu.comp.io, func_index); const prev_failed = zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit); @@ -1958,10 +1940,8 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, func_index: InternPool.Index) Z _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); } else { // We can trust the current information about this function. - if (prev_failed) { - return error.AnalysisFail; - } - if (func.analysisUnordered(ip).is_analyzed) return; + if (prev_failed) return error.AnalysisFail; + return; } if (zcu.comp.debugIncremental()) { @@ -3026,7 +3006,6 @@ fn analyzeFuncBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.Sem try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, {}); defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); - func.setAnalyzed(ip, io); if (func.analysisUnordered(ip).inferred_error_set) { func.setResolvedErrorSet(ip, io, .none); } @@ -3144,7 +3123,7 @@ fn analyzeFuncBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.Sem const param_ty: Type = .fromInterned(fn_ty_info.param_types.get(ip)[runtime_param_index]); runtime_param_index += 1; - try sema.ensureLayoutResolved(param_ty); + try sema.ensureLayoutResolved(param_ty, inner_block.src(.{ .func_decl_param_ty = @intCast(zir_param_index) })); if (try param_ty.onePossibleValue(pt)) |opv| { gop.value_ptr.* = .fromValue(opv); continue; @@ -3161,7 +3140,7 @@ fn analyzeFuncBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.Sem }); } - try sema.ensureLayoutResolved(sema.fn_ret_ty); + try sema.ensureLayoutResolved(sema.fn_ret_ty, inner_block.src(.{ .node_offset_fn_type_ret_ty = .zero })); const last_arg_index = inner_block.instructions.items.len; -- 2.54.0 From b19074d252e7eb833b653263acd20e64a7fe26ff Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Wed, 28 Jan 2026 13:10:07 +0000 Subject: [PATCH 09/79] compiler: represent bitpacks as their backing integer Now that https://github.com/ziglang/zig/issues/24657 has been implemented, the compiler can simplify its internal representation of comptime-known `packed struct` and `packed union` values. Instead of storing them field-wise, we can simply store their backing integer value. This simplifies many operations and improves efficiency in some cases. --- src/Air/print.zig | 44 +++----- src/InternPool.zig | 75 +++++++++++--- src/Sema.zig | 50 +++++++-- src/Sema/bitcast.zig | 169 +++++++++++++++--------------- src/Sema/type_resolution.zig | 1 + src/Type.zig | 41 ++++++-- src/Value.zig | 160 ++++++++++++++-------------- src/Zcu/PerThread.zig | 9 ++ src/codegen.zig | 42 ++------ src/codegen/aarch64/Select.zig | 46 ++++----- src/codegen/c.zig | 178 ++++++++++++-------------------- src/codegen/llvm.zig | 39 +++---- src/codegen/riscv64/CodeGen.zig | 45 ++++---- src/codegen/spirv/CodeGen.zig | 2 +- src/codegen/wasm/CodeGen.zig | 4 +- src/codegen/x86_64/CodeGen.zig | 65 ++++++------ src/link/Dwarf.zig | 11 ++ src/mutable_value.zig | 26 +++-- src/print_value.zig | 28 ++++- 19 files changed, 532 insertions(+), 503 deletions(-) diff --git a/src/Air/print.zig b/src/Air/print.zig index 0c126fab22d364b97c49ed6d896801fe4c66451e..f6c0f5a03b8f1c957b0129978358888977690de7 100644 --- a/src/Air/print.zig +++ b/src/Air/print.zig @@ -692,33 +692,23 @@ const Writer = struct { const zcu = w.pt.zcu; const ip = &zcu.intern_pool; - const aggregate = ip.indexToKey(unwrapped_asm.clobbers).aggregate; - const struct_type: Type = .fromInterned(aggregate.ty); - switch (aggregate.storage) { - .elems => |elems| for (elems, 0..) |elem, i| { - switch (elem) { - .bool_true => { - const clobber = struct_type.structFieldName(i, zcu).toSlice(ip).?; - assert(clobber.len != 0); - try s.writeAll(", ~{"); - try s.writeAll(clobber); - try s.writeAll("}"); - }, - .bool_false => continue, - else => unreachable, - } - }, - .repeated_elem => |elem| { - try s.writeAll(", "); - try s.writeAll(switch (elem) { - .bool_true => "", - .bool_false => "", - else => unreachable, - }); - }, - .bytes => |bytes| { - try s.print(", {x}", .{bytes}); - }, + const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers); + const clobbers_ty = clobbers_val.typeOf(zcu); + var clobbers_bigint_buf: Value.BigIntSpace = undefined; + const clobbers_bigint = clobbers_val.toBigInt(&clobbers_bigint_buf, zcu); + for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { + assert(clobbers_ty.fieldType(field_index, zcu).toIntern() == .bool_type); + const limb_bits = @bitSizeOf(std.math.big.Limb); + if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false + switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { + 0 => continue, // field is false + 1 => {}, // field is true + } + const clobber = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?; + assert(clobber.len != 0); + try s.writeAll(", ~{"); + try s.writeAll(clobber); + try s.writeAll("}"); } const asm_source = unwrapped_asm.source; try s.print(", \"{f}\"", .{std.zig.fmtString(asm_source)}); diff --git a/src/InternPool.zig b/src/InternPool.zig index 230ef78d63dd4190c712a6b955b5ea594d89ddb6..7028d690094d195183e3e33b991ddc2ce17572b1 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -2130,6 +2130,8 @@ pub const Key = union(enum) { aggregate: Aggregate, /// An instance of a union. un: Union, + /// An instance of a `packed struct` or `packed union`. + bitpack: Bitpack, /// A comptime function call with a memoized result. memoized_call: Key.MemoizedCall, @@ -2681,6 +2683,15 @@ pub const Key = union(enum) { }; }; + /// As well as a key, this type doubles as the payload in `extra` for `Tag.bitpack`. + pub const Bitpack = struct { + /// The `packed struct` or `packed union` type. + ty: Index, + /// The contents of the bitpack, represented as the backing integer value. The type of this + /// value is the same as the backing integer type of `ty`. + backing_int_val: Index, + }; + pub const MemoizedCall = struct { func: Index, arg_values: []const Index, @@ -2919,6 +2930,8 @@ pub const Key = union(enum) { asBytes(&e.relocation) ++ asBytes(&e.is_const) ++ asBytes(&e.alignment) ++ asBytes(&e.@"addrspace") ++ asBytes(&e.zir_index) ++ &[1]u8{@intFromEnum(e.source)}), + + .bitpack => |bitpack| Hash.hash(seed, asBytes(&bitpack.ty) ++ asBytes(&bitpack.backing_int_val)), }; } @@ -2996,6 +3009,10 @@ pub const Key = union(enum) { const b_info = b.empty_enum_value; return a_info == b_info; }, + .bitpack => |a_info| { + const b_info = b.bitpack; + return a_info.ty == b_info.ty and a_info.backing_int_val == b_info.backing_int_val; + }, .variable => |a_info| { const b_info = b.variable; @@ -3271,6 +3288,7 @@ pub const Key = union(enum) { .enum_tag, .aggregate, .un, + .bitpack, => |x| x.ty, .enum_literal => .enum_literal_type, @@ -4417,6 +4435,7 @@ pub const Index = enum(u32) { trailing: struct { element_values: []Index }, }, repeated: struct { data: *Repeated }, + bitpack: struct { data: *Key.Bitpack }, memoized_call: struct { const @"data.args_len" = opaque {}; @@ -5152,6 +5171,9 @@ pub const Tag = enum(u8) { /// An instance of an array or vector with every element being the same value. /// data is extra index to `Repeated`. repeated, + /// An instance of a `packed struct` or `packed union`. + /// data is extra index to `Key.Bitpack`. + bitpack, /// A memoized comptime function call result. /// data is extra index to `MemoizedCall` @@ -5485,6 +5507,7 @@ pub const Tag = enum(u8) { .config = .{ .@"trailing.elements.len" = .@"payload.ty.payload.fields_len" }, }, .repeated = .{ .summary = .@"@as({.payload.ty%summary}, @splat({.payload.elem_val%summary}))", .payload = Repeated }, + .bitpack = .{ .summary = .@"@as({.payload.ty%summary}, {})", .payload = Key.Bitpack }, .memoized_call = .{ .summary = .@"@memoize({.payload.func%summary})", @@ -7043,6 +7066,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { }, .enum_literal => .{ .enum_literal = @enumFromInt(data) }, .enum_tag => .{ .enum_tag = extraData(unwrapped_index.getExtra(ip), Tag.EnumTag, data) }, + .bitpack => .{ .bitpack = extraData(unwrapped_index.getExtra(ip), Key.Bitpack, data) }, .memoized_call => { const extra_list = unwrapped_index.getExtra(ip); @@ -7938,15 +7962,14 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: .aggregate => |aggregate| { const ty_key = ip.indexToKey(aggregate.ty); const len = ip.aggregateTypeLen(aggregate.ty); - const child = switch (ty_key) { - .array_type => |array_type| array_type.child, - .vector_type => |vector_type| vector_type.child, - .tuple_type, .struct_type => .none, - else => unreachable, - }; - const sentinel = switch (ty_key) { - .array_type => |array_type| array_type.sentinel, - .vector_type, .tuple_type, .struct_type => .none, + const child: Index, const sentinel: Index = switch (ty_key) { + .array_type => |array_type| .{ array_type.child, array_type.sentinel }, + .vector_type => |vector_type| .{ vector_type.child, .none }, + .tuple_type => .{ .none, .none }, + .struct_type => child: { + assert(ip.loadStructType(aggregate.ty).layout != .@"packed"); + break :child .{ .none, .none }; + }, else => unreachable, }; const len_including_sentinel = len + @intFromBool(sentinel != .none); @@ -8128,6 +8151,18 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: extra.appendSliceAssumeCapacity(.{@ptrCast(aggregate.storage.elems)}); if (sentinel != .none) extra.appendAssumeCapacity(.{@intFromEnum(sentinel)}); }, + .bitpack => |bitpack| { + switch (ip.zigTypeTag(bitpack.ty)) { + .@"struct" => assert(ip.typeOf(bitpack.backing_int_val) == ip.loadStructType(bitpack.ty).packed_backing_int_type), + .@"union" => assert(ip.typeOf(bitpack.backing_int_val) == ip.loadUnionType(bitpack.ty).packed_backing_int_type), + else => unreachable, + } + assert(!ip.isUndef(bitpack.backing_int_val)); + items.appendAssumeCapacity(.{ + .tag = .bitpack, + .data = try addExtra(extra, bitpack), + }); + }, .memoized_call => |memoized_call| { for (memoized_call.arg_values) |arg| assert(arg != .none); @@ -9095,16 +9130,18 @@ pub fn getUnion( tid: Zcu.PerThread.Id, un: Key.Union, ) Allocator.Error!Index { - var gop = try ip.getOrPutKey(gpa, io, tid, .{ .un = un }); - defer gop.deinit(); - if (gop == .existing) return gop.existing; - const local = ip.getLocal(tid); - const items = local.getMutableItems(gpa, io); - const extra = local.getMutableExtra(gpa, io); - try items.ensureUnusedCapacity(1); - assert(un.ty != .none); assert(un.val != .none); + assert(ip.loadUnionType(un.ty).layout != .@"packed"); + + var gop = try ip.getOrPutKey(gpa, io, tid, .{ .un = un }); + defer gop.deinit(); + if (gop == .existing) return gop.existing; + const local = ip.getLocal(tid); + const items = local.getMutableItems(gpa, io); + const extra = local.getMutableExtra(gpa, io); + try items.ensureUnusedCapacity(1); + items.appendAssumeCapacity(.{ .tag = .union_value, .data = try addExtra(extra, un), @@ -11003,6 +11040,7 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo .func_coerced => @sizeOf(Tag.FuncCoerced), .only_possible_value => 0, .union_value => @sizeOf(Key.Union), + .bitpack => 2 * @sizeOf(u32), .memoized_call => b: { const info = extraData(extra_list, MemoizedCall, data); @@ -11117,6 +11155,7 @@ fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void { .func_instance, .func_coerced, .union_value, + .bitpack, .memoized_call, => try w.print("{d}", .{data}), @@ -11871,6 +11910,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { .bytes, .aggregate, .repeated, + .bitpack, => |t| { const extra_list = unwrapped_index.getExtra(ip); return @enumFromInt(extra_list.view().items(.@"0")[item.data + std.meta.fieldIndex(t.Payload(), "ty").?]); @@ -12264,6 +12304,7 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId { .bytes, .aggregate, .repeated, + .bitpack, // memoization, not types .memoized_call, => unreachable, diff --git a/src/Sema.zig b/src/Sema.zig index a506a7e6bbc369bf6a9906d2cda4dd6b41450317..60f04974372927d734327b71cef6118d53bc0797 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -3583,7 +3583,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, }, .field => |idx| ptr: { const maybe_union_ty = Value.fromInterned(decl_parent_ptr).typeOf(zcu).childType(zcu); - if (zcu.typeToUnion(maybe_union_ty)) |union_obj| { + if (zcu.typeToUnion(maybe_union_ty)) |union_obj| if (union_obj.layout == .auto) { // As this is a union field, we must store to the pointer now to set the tag. // The payload value will be stored later, so undef is a sufficent payload for now. const payload_ty: Type = .fromInterned(union_obj.field_types.get(&zcu.intern_pool)[idx]); @@ -3591,7 +3591,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, const tag_val = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_type), idx); const store_val = try pt.unionValue(maybe_union_ty, tag_val, payload_val); try sema.storePtrVal(block, .unneeded, .fromInterned(decl_parent_ptr), store_val, maybe_union_ty); - } + }; break :ptr (try Value.fromInterned(decl_parent_ptr).ptrField(idx, pt)).toIntern(); }, .elem => |idx| (try Value.fromInterned(decl_parent_ptr).ptrElem(idx, pt)).toIntern(), @@ -18510,6 +18510,10 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A const payload = try sema.coerce(block, field_ty, sema.resolveInst(extra.init), payload_src); + if (union_ty.containerLayout(zcu) == .@"packed") { + return sema.bitCast(block, union_ty, payload, block.nodeOffset(inst_data.src_node), payload_src); + } + if (sema.resolveValue(payload)) |payload_val| { const tag_ty = union_ty.unionTagTypeHypothetical(zcu); const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index); @@ -18643,6 +18647,10 @@ fn zirStructInit( const uncoerced_init_inst = sema.resolveInst(item.data.init); const init_inst = try sema.coerce(block, field_ty, uncoerced_init_inst, field_src); + if (resolved_ty.containerLayout(zcu) == .@"packed") { + return sema.bitCast(block, resolved_ty, init_inst, src, field_src); + } + if (sema.resolveValue(init_inst)) |val| { const struct_val = Value.fromInterned(try pt.internUnion(.{ .ty = resolved_ty.toIntern(), @@ -18789,15 +18797,35 @@ fn finishStructInit( } } else null; - const runtime_index = opt_runtime_index orelse { - const elems = try sema.arena.alloc(InternPool.Index, field_inits.len); - for (elems, field_inits) |*elem, field_init| { - elem.* = sema.resolveValue(field_init).?.toIntern(); - } - const struct_val = try pt.aggregateValue(struct_ty, elems); - const final_val_inst = try sema.coerce(block, result_ty, Air.internedToRef(struct_val.toIntern()), init_src); - const final_val = sema.resolveValue(final_val_inst).?; - return sema.addConstantMaybeRef(final_val.toIntern(), is_ref); + const runtime_index = opt_runtime_index orelse switch (struct_ty.containerLayout(zcu)) { + .auto, .@"extern" => { + const elems = try sema.arena.alloc(InternPool.Index, field_inits.len); + for (elems, field_inits) |*elem, field_init| { + elem.* = sema.resolveValue(field_init).?.toIntern(); + } + const struct_val = try pt.aggregateValue(struct_ty, elems); + const final_val_ref = try sema.coerce(block, result_ty, .fromValue(struct_val), init_src); + return sema.addConstantMaybeRef(final_val_ref.toInterned().?, is_ref); + }, + .@"packed" => { + const buf = try sema.arena.alloc(u8, (struct_ty.bitSize(zcu) + 7) / 8); + var bit_offset: u16 = 0; + for (field_inits) |field_init| { + const field_val = sema.resolveValue(field_init).?; + field_val.writeToPackedMemory(pt, buf, bit_offset) catch |err| switch (err) { + error.ReinterpretDeclRef => unreachable, // bitpack fields cannot be pointers + error.OutOfMemory => |e| return e, + }; + bit_offset += @intCast(field_val.typeOf(zcu).bitSize(zcu)); + } + assert(bit_offset == struct_ty.bitSize(zcu)); + const struct_val = Value.readFromPackedMemory(struct_ty, pt, buf, 0, sema.arena) catch |err| switch (err) { + error.IllDefinedMemoryLayout => unreachable, // bitpacks have well-defined layout + error.OutOfMemory => |e| return e, + }; + const final_val_ref = try sema.coerce(block, result_ty, .fromValue(struct_val), init_src); + return sema.addConstantMaybeRef(final_val_ref.toInterned().?, is_ref); + }, }; if (struct_ty.comptimeOnly(zcu)) { diff --git a/src/Sema/bitcast.zig b/src/Sema/bitcast.zig index b496db1ce0e167aad6cacf51568ecc9bb91cde97..f06528b6240f4766730353a6dc50d3b8e3c41607 100644 --- a/src/Sema/bitcast.zig +++ b/src/Sema/bitcast.zig @@ -273,6 +273,8 @@ const UnpackValueBits = struct { .opt, => try unpack.primitive(val), + .bitpack => |bitpack| try unpack.primitive(.fromInterned(bitpack.backing_int_val)), + .aggregate => switch (ty.zigTypeTag(zcu)) { .vector => { const len: usize = @intCast(ty.arrayLen(zcu)); @@ -443,7 +445,7 @@ const UnpackValueBits = struct { // This @intCast is okay because no primitive can exceed the size of a u16. const int_ty = try unpack.pt.intType(.unsigned, @intCast(bit_count)); const buf = try unpack.arena.alloc(u8, @intCast((val_bits + 7) / 8)); - try val.writeToPackedMemory(ty, unpack.pt, buf, 0); + try val.writeToPackedMemory(unpack.pt, buf, 0); const sub_val = try Value.readFromPackedMemory(int_ty, unpack.pt, buf, @intCast(bit_offset), unpack.arena); try unpack.primitive(sub_val); }, @@ -565,102 +567,103 @@ const PackValueBits = struct { return pt.aggregateValue(ty, elems); }, .@"packed" => { - // All fields are in order with no padding. - // This is identical between LE and BE targets. - const elems = try arena.alloc(InternPool.Index, ty.structFieldCount(zcu)); - for (elems, 0..) |*elem, i| { - const field_ty = ty.fieldType(i, zcu); - elem.* = (try pack.get(field_ty)).toIntern(); - } - return pt.aggregateValue(ty, elems); + const backing_int_val = try pack.primitive(ty.bitpackBackingInt(zcu)); + return pt.bitpackValue(ty, backing_int_val); }, }, - .@"union" => { - // We will attempt to read as the backing representation. If this emits - // `error.ReinterpretDeclRef`, we will try each union field, preferring larger ones. - // We will also attempt smaller fields when we get `undefined`, as if some bits are - // defined we want to include them. - // TODO: this is very very bad. We need a more sophisticated union representation. + .@"union" => switch (ty.containerLayout(zcu)) { + .auto => unreachable, // ill-defined layout + .@"extern" => { + // We will attempt to read as the backing representation. If this emits + // `error.ReinterpretDeclRef`, we will try each union field, preferring larger ones. + // We will also attempt smaller fields when we get `undefined`, as if some bits are + // defined we want to include them. + // TODO: this is very very bad. We need a more sophisticated union representation. - const prev_unpacked = pack.unpacked; - const prev_bit_offset = pack.bit_offset; + const prev_unpacked = pack.unpacked; + const prev_bit_offset = pack.bit_offset; - const backing_ty = try ty.unionBackingType(pt); + const backing_ty = try ty.externUnionBackingType(pt); - backing: { - const backing_val = pack.get(backing_ty) catch |err| switch (err) { - error.ReinterpretDeclRef => { + backing: { + const backing_val = pack.get(backing_ty) catch |err| switch (err) { + error.ReinterpretDeclRef => { + pack.unpacked = prev_unpacked; + pack.bit_offset = prev_bit_offset; + break :backing; + }, + else => |e| return e, + }; + if (backing_val.isUndef(zcu)) { pack.unpacked = prev_unpacked; pack.bit_offset = prev_bit_offset; break :backing; - }, - else => |e| return e, + } + return Value.fromInterned(try pt.internUnion(.{ + .ty = ty.toIntern(), + .tag = .none, + .val = backing_val.toIntern(), + })); + } + + const field_order = try pack.arena.alloc(u32, ty.unionTagTypeHypothetical(zcu).enumFieldCount(zcu)); + for (field_order, 0..) |*f, i| f.* = @intCast(i); + // Sort `field_order` to put the fields with the largest bit sizes first. + const SizeSortCtx = struct { + zcu: *Zcu, + field_types: []const InternPool.Index, + fn lessThan(ctx: @This(), a_idx: u32, b_idx: u32) bool { + const a_ty = Type.fromInterned(ctx.field_types[a_idx]); + const b_ty = Type.fromInterned(ctx.field_types[b_idx]); + return a_ty.bitSize(ctx.zcu) > b_ty.bitSize(ctx.zcu); + } }; - if (backing_val.isUndef(zcu)) { - pack.unpacked = prev_unpacked; - pack.bit_offset = prev_bit_offset; - break :backing; + std.mem.sortUnstable(u32, field_order, SizeSortCtx{ + .zcu = zcu, + .field_types = zcu.typeToUnion(ty).?.field_types.get(ip), + }, SizeSortCtx.lessThan); + + const padding_after = endian == .little or ty.containerLayout(zcu) == .@"packed"; + + for (field_order) |field_idx| { + const field_ty = Type.fromInterned(zcu.typeToUnion(ty).?.field_types.get(ip)[field_idx]); + const pad_bits = ty.bitSize(zcu) - field_ty.bitSize(zcu); + if (!padding_after) try pack.padding(pad_bits); + const field_val = pack.get(field_ty) catch |err| switch (err) { + error.ReinterpretDeclRef => { + pack.unpacked = prev_unpacked; + pack.bit_offset = prev_bit_offset; + continue; + }, + else => |e| return e, + }; + if (padding_after) try pack.padding(pad_bits); + if (field_val.isUndef(zcu)) { + pack.unpacked = prev_unpacked; + pack.bit_offset = prev_bit_offset; + continue; + } + const tag_val = try pt.enumValueFieldIndex(ty.unionTagTypeHypothetical(zcu), field_idx); + return Value.fromInterned(try pt.internUnion(.{ + .ty = ty.toIntern(), + .tag = tag_val.toIntern(), + .val = field_val.toIntern(), + })); } + + // No field could represent the value. Just do whatever happens when we try to read + // the backing type - either `undefined` or `error.ReinterpretDeclRef`. + const backing_val = try pack.get(backing_ty); return Value.fromInterned(try pt.internUnion(.{ .ty = ty.toIntern(), .tag = .none, .val = backing_val.toIntern(), })); - } - - const field_order = try pack.arena.alloc(u32, ty.unionTagTypeHypothetical(zcu).enumFieldCount(zcu)); - for (field_order, 0..) |*f, i| f.* = @intCast(i); - // Sort `field_order` to put the fields with the largest bit sizes first. - const SizeSortCtx = struct { - zcu: *Zcu, - field_types: []const InternPool.Index, - fn lessThan(ctx: @This(), a_idx: u32, b_idx: u32) bool { - const a_ty = Type.fromInterned(ctx.field_types[a_idx]); - const b_ty = Type.fromInterned(ctx.field_types[b_idx]); - return a_ty.bitSize(ctx.zcu) > b_ty.bitSize(ctx.zcu); - } - }; - std.mem.sortUnstable(u32, field_order, SizeSortCtx{ - .zcu = zcu, - .field_types = zcu.typeToUnion(ty).?.field_types.get(ip), - }, SizeSortCtx.lessThan); - - const padding_after = endian == .little or ty.containerLayout(zcu) == .@"packed"; - - for (field_order) |field_idx| { - const field_ty = Type.fromInterned(zcu.typeToUnion(ty).?.field_types.get(ip)[field_idx]); - const pad_bits = ty.bitSize(zcu) - field_ty.bitSize(zcu); - if (!padding_after) try pack.padding(pad_bits); - const field_val = pack.get(field_ty) catch |err| switch (err) { - error.ReinterpretDeclRef => { - pack.unpacked = prev_unpacked; - pack.bit_offset = prev_bit_offset; - continue; - }, - else => |e| return e, - }; - if (padding_after) try pack.padding(pad_bits); - if (field_val.isUndef(zcu)) { - pack.unpacked = prev_unpacked; - pack.bit_offset = prev_bit_offset; - continue; - } - const tag_val = try pt.enumValueFieldIndex(ty.unionTagTypeHypothetical(zcu), field_idx); - return Value.fromInterned(try pt.internUnion(.{ - .ty = ty.toIntern(), - .tag = tag_val.toIntern(), - .val = field_val.toIntern(), - })); - } - - // No field could represent the value. Just do whatever happens when we try to read - // the backing type - either `undefined` or `error.ReinterpretDeclRef`. - const backing_val = try pack.get(backing_ty); - return Value.fromInterned(try pt.internUnion(.{ - .ty = ty.toIntern(), - .tag = .none, - .val = backing_val.toIntern(), - })); + }, + .@"packed" => { + const backing_int_val = try pack.primitive(ty.bitpackBackingInt(zcu)); + return pt.bitpackValue(ty, backing_int_val); + }, }, else => return pack.primitive(ty), } @@ -722,7 +725,7 @@ const PackValueBits = struct { const val = Value.fromInterned(ip_val); const ty = val.typeOf(zcu); if (!val.isUndef(zcu)) { - try val.writeToPackedMemory(ty, pt, buf, cur_bit_off); + try val.writeToPackedMemory(pt, buf, cur_bit_off); } cur_bit_off += @intCast(ty.bitSize(zcu)); } diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig index 970cf4f0116328dc6f84fe4c1e755eb71a4a915a..1096c9cbe7d31cbd32958c0dcdfde5eae03b56bf 100644 --- a/src/Sema/type_resolution.zig +++ b/src/Sema/type_resolution.zig @@ -79,6 +79,7 @@ pub fn ensureLayoutResolved(sema: *Sema, ty: Type, src: LazySrcLoc) SemaError!vo .opt, .aggregate, .un, + .bitpack, // memoization, not types .memoized_call, => unreachable, diff --git a/src/Type.zig b/src/Type.zig index 5b5839cf6f40e5953e182162289aa2e7b05ba96d..9cca3d104320edfc2f0fbf63cc64a30d7256fa0b 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -407,6 +407,7 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari .opt, .aggregate, .un, + .bitpack, // memoization, not types .memoized_call, => unreachable, @@ -543,6 +544,7 @@ pub fn hasRuntimeBits(ty: Type, zcu: *const Zcu) bool { .opt, .aggregate, .un, + .bitpack, // memoization, not types .memoized_call, => unreachable, @@ -639,6 +641,7 @@ pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool { .opt, .aggregate, .un, + .bitpack, // memoization, not types .memoized_call, => unreachable, @@ -846,6 +849,7 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment { .opt, .aggregate, .un, + .bitpack, // memoization, not types .memoized_call, => unreachable, @@ -978,6 +982,7 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 { .opt, .aggregate, .un, + .bitpack, // memoization, not types .memoized_call, => unreachable, @@ -1102,6 +1107,7 @@ pub fn bitSize(ty: Type, zcu: *const Zcu) u64 { .opt, .aggregate, .un, + .bitpack, // memoization, not types .memoized_call, => unreachable, @@ -1393,16 +1399,16 @@ pub fn unionHasAllZeroBitFieldTypes(ty: Type, zcu: *Zcu) bool { } /// Returns the type used for backing storage of this union during comptime operations. -/// Asserts the type is either an extern or packed union. -pub fn unionBackingType(ty: Type, pt: Zcu.PerThread) !Type { +/// Asserts the type is an extern union. +pub fn externUnionBackingType(ty: Type, pt: Zcu.PerThread) !Type { const zcu = pt.zcu; assertHasLayout(ty, zcu); const loaded_union = zcu.intern_pool.loadUnionType(ty.toIntern()); - return switch (loaded_union.layout) { - .@"extern" => try pt.arrayType(.{ .len = ty.abiSize(zcu), .child = .u8_type }), - .@"packed" => .fromInterned(loaded_union.packed_backing_int_type), + switch (loaded_union.layout) { + .@"extern" => return pt.arrayType(.{ .len = ty.abiSize(zcu), .child = .u8_type }), + .@"packed" => unreachable, .auto => unreachable, - }; + } } pub fn unionGetLayout(ty: Type, zcu: *const Zcu) Zcu.UnionLayout { @@ -1421,6 +1427,15 @@ pub fn containerLayout(ty: Type, zcu: *const Zcu) std.builtin.Type.ContainerLayo }; } +pub fn bitpackBackingInt(ty: Type, zcu: *const Zcu) Type { + const ip = &zcu.intern_pool; + return switch (ip.indexToKey(ty.toIntern())) { + .struct_type => .fromInterned(ip.loadStructType(ty.toIntern()).packed_backing_int_type), + .union_type => .fromInterned(ip.loadUnionType(ty.toIntern()).packed_backing_int_type), + else => unreachable, + }; +} + /// Asserts that the type is an error union. pub fn errorUnionPayload(ty: Type, zcu: *const Zcu) Type { return Type.fromInterned(zcu.intern_pool.indexToKey(ty.toIntern()).error_union_type.payload_type); @@ -1635,6 +1650,7 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType { .opt, .aggregate, .un, + .bitpack, // memoization, not types .memoized_call, => unreachable, @@ -1842,7 +1858,7 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { if (struct_obj.layout == .@"packed") { const backing_ty: Type = .fromInterned(struct_obj.packed_backing_int_type); const backing_val = try backing_ty.onePossibleValue(pt) orelse return null; - _ = backing_val; // MLUGG TODO: represent unions as their bits! + return try pt.bitpackValue(ty, backing_val); } else { if (!struct_obj.has_one_possible_value) return null; } @@ -1893,8 +1909,13 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { }, .union_type => { - // MLUGG TODO: is this nonsensical or what!!!!!! const union_obj = ip.loadUnionType(ty.toIntern()); + if (union_obj.layout == .@"packed") { + const backing_ty: Type = .fromInterned(union_obj.packed_backing_int_type); + const backing_val = try backing_ty.onePossibleValue(pt) orelse return null; + return try pt.bitpackValue(ty, backing_val); + } + // MLUGG TODO: is this nonsensical or what!!!!!! const tag_val = (try Type.fromInterned(union_obj.enum_tag_type).onePossibleValue(pt)) orelse return null; if (union_obj.field_types.len == 0) { @@ -1957,6 +1978,7 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { .opt, .aggregate, .un, + .bitpack, // memoization, not types .memoized_call, => unreachable, @@ -2061,6 +2083,7 @@ pub fn comptimeOnly(ty: Type, zcu: *const Zcu) bool { .opt, .aggregate, .un, + .bitpack, // memoization, not types .memoized_call, => unreachable, @@ -3080,6 +3103,7 @@ pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void { .opt, .aggregate, .un, + .bitpack, .undef, // memoization, not types .memoized_call, @@ -3158,6 +3182,7 @@ fn collectSubtypes(ty: Type, pt: Zcu.PerThread, visited: *std.AutoArrayHashMapUn .opt, .aggregate, .un, + .bitpack, // memoization, not types .memoized_call, => unreachable, diff --git a/src/Value.zig b/src/Value.zig index d513e5d07d9d07311a7d15b106e57795b54e92be..774a6758ceff8d82fc579f580b33de17ad4fef75 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -158,6 +158,7 @@ pub fn toBigInt(val: Value, space: *BigIntSpace, zcu: *Zcu) BigIntConst { const ip = &zcu.intern_pool; const int_key = switch (ip.indexToKey(val.toIntern())) { .enum_tag => |enum_tag| ip.indexToKey(enum_tag.int).int, + .bitpack => |bitpack| ip.indexToKey(bitpack.backing_int_val).int, .int => |int| int, else => unreachable, }; @@ -216,6 +217,7 @@ pub fn getUnsignedInt(val: Value, zcu: *const Zcu) ?u64 { else => |payload| Value.fromInterned(payload).getUnsignedInt(zcu), }, .enum_tag => |enum_tag| Value.fromInterned(enum_tag.int).getUnsignedInt(zcu), + .bitpack => |bitpack| Value.fromInterned(bitpack.backing_int_val).getUnsignedInt(zcu), .err => |err| zcu.intern_pool.getErrorValueIfExists(err.name).?, else => null, }, @@ -309,7 +311,7 @@ pub fn writeToMemory(val: Value, pt: Zcu.PerThread, buffer: []u8) error{ // We use byte_count instead of abi_size here, so that any padding bytes // follow the data bytes, on both big- and little-endian systems. const byte_count = (@as(usize, @intCast(ty.bitSize(zcu))) + 7) / 8; - return writeToPackedMemory(val, ty, pt, buffer[0..byte_count], 0); + return writeToPackedMemory(val, pt, buffer[0..byte_count], 0); }, .@"struct" => { const struct_type = zcu.typeToStruct(ty) orelse return error.IllDefinedMemoryLayout; @@ -328,8 +330,8 @@ pub fn writeToMemory(val: Value, pt: Zcu.PerThread, buffer: []u8) error{ try writeToMemory(field_val, pt, buffer[off..]); }, .@"packed" => { - const byte_count = (@as(usize, @intCast(ty.bitSize(zcu))) + 7) / 8; - return writeToPackedMemory(val, ty, pt, buffer[0..byte_count], 0); + const int_index = ip.indexToKey(val.toIntern()).bitpack.backing_int_val; + return Value.fromInterned(int_index).writeToMemory(pt, buffer); }, } }, @@ -344,15 +346,14 @@ pub fn writeToMemory(val: Value, pt: Zcu.PerThread, buffer: []u8) error{ const byte_count: usize = @intCast(field_type.abiSize(zcu)); return writeToMemory(field_val, pt, buffer[0..byte_count]); } else { - const backing_ty = try ty.unionBackingType(pt); + const backing_ty = try ty.externUnionBackingType(pt); const byte_count: usize = @intCast(backing_ty.abiSize(zcu)); return writeToMemory(val.unionValue(zcu), pt, buffer[0..byte_count]); } }, .@"packed" => { - const backing_ty = try ty.unionBackingType(pt); - const byte_count: usize = @intCast(backing_ty.abiSize(zcu)); - return writeToPackedMemory(val, ty, pt, buffer[0..byte_count], 0); + const int_val: Value = .fromInterned(ip.indexToKey(val.toIntern()).bitpack.backing_int_val); + return writeToMemory(int_val, pt, buffer); }, }, .optional => { @@ -374,7 +375,6 @@ pub fn writeToMemory(val: Value, pt: Zcu.PerThread, buffer: []u8) error{ /// big-endian packed memory layouts start at the end of the buffer. pub fn writeToPackedMemory( val: Value, - ty: Type, pt: Zcu.PerThread, buffer: []u8, bit_offset: usize, @@ -383,6 +383,7 @@ pub fn writeToPackedMemory( const ip = &zcu.intern_pool; const target = zcu.getTarget(); const endian = target.cpu.arch.endian(); + const ty = val.typeOf(zcu); if (val.isUndef(zcu)) { const bit_size: usize = @intCast(ty.bitSize(zcu)); if (bit_size != 0) { @@ -405,7 +406,13 @@ pub fn writeToPackedMemory( }, .@"enum" => { const int_val = val.intFromEnum(zcu); - return int_val.writeToPackedMemory(int_val.typeOf(zcu), pt, buffer, bit_offset); + return int_val.writeToPackedMemory(pt, buffer, bit_offset); + }, + .pointer => { + assert(!ty.isSlice(zcu)); // No well defined layout. + if (ip.getBackingAddrTag(val.toIntern()).? != .int) return error.ReinterpretDeclRef; + const addr = val.toUnsignedInt(zcu); + std.mem.writeVarPackedInt(buffer, bit_offset, zcu.getTarget().ptrBitWidth(), addr, endian); }, .int => { const bits = ty.intInfo(zcu).bits; @@ -434,54 +441,21 @@ pub fn writeToPackedMemory( // On big-endian systems, LLVM reverses the element order of vectors by default const tgt_elem_i = if (endian == .big) len - elem_i - 1 else elem_i; const elem_val = try val.elemValue(pt, tgt_elem_i); - try elem_val.writeToPackedMemory(elem_ty, pt, buffer, bit_offset + bits); + try elem_val.writeToPackedMemory(pt, buffer, bit_offset + bits); bits += elem_bit_size; } }, - .@"struct" => { - const struct_type = ip.loadStructType(ty.toIntern()); - // Sema is supposed to have emitted a compile error already in the case of Auto, - // and Extern is handled in non-packed writeToMemory. - assert(struct_type.layout == .@"packed"); - var bits: u16 = 0; - for (0..struct_type.field_types.len) |i| { - const field_val = Value.fromInterned(switch (ip.indexToKey(val.toIntern()).aggregate.storage) { - .bytes => unreachable, - .elems => |elems| elems[i], - .repeated_elem => |elem| elem, - }); - const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); - const field_bits: u16 = @intCast(field_ty.bitSize(zcu)); - try field_val.writeToPackedMemory(field_ty, pt, buffer, bit_offset + bits); - bits += field_bits; - } - }, - .@"union" => { - const union_obj = zcu.typeToUnion(ty).?; - assert(union_obj.layout == .@"packed"); - if (val.unionTag(zcu)) |union_tag| { - const field_index = zcu.unionTagFieldIndex(union_obj, union_tag).?; - const field_type = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); - const field_val = try val.fieldValue(pt, field_index); - return field_val.writeToPackedMemory(field_type, pt, buffer, bit_offset); - } else { - const backing_ty = try ty.unionBackingType(pt); - return val.unionValue(zcu).writeToPackedMemory(backing_ty, pt, buffer, bit_offset); - } - }, - .pointer => { - assert(!ty.isSlice(zcu)); // No well defined layout. - if (ip.getBackingAddrTag(val.toIntern()).? != .int) return error.ReinterpretDeclRef; - return val.writeToPackedMemory(Type.usize, pt, buffer, bit_offset); + .@"struct", .@"union" => { + assert(ty.containerLayout(zcu) == .@"packed"); + const int_val: Value = .fromInterned(ip.indexToKey(val.toIntern()).bitpack.backing_int_val); + return int_val.writeToPackedMemory(pt, buffer, bit_offset); }, .optional => { assert(ty.isPtrLikeOptional(zcu)); - const child = ty.optionalChild(zcu); - const opt_val = val.optionalValue(zcu); - if (opt_val) |some| { - return some.writeToPackedMemory(child, pt, buffer, bit_offset); + if (val.optionalValue(zcu)) |ptr_val| { + return ptr_val.writeToPackedMemory(pt, buffer, bit_offset); } else { - return writeToPackedMemory(try pt.intValue(Type.usize, 0), Type.usize, pt, buffer, bit_offset); + return Value.zero_usize.writeToPackedMemory(pt, buffer, bit_offset); } }, else => @panic("TODO implement writeToPackedMemory for more types"), @@ -531,13 +505,12 @@ pub fn readFromPackedMemory( pt: Zcu.PerThread, buffer: []const u8, bit_offset: usize, - arena: Allocator, + gpa: Allocator, ) error{ IllDefinedMemoryLayout, OutOfMemory, }!Value { const zcu = pt.zcu; - const ip = &zcu.intern_pool; const target = zcu.getTarget(); const endian = target.cpu.arch.endian(); switch (ty.zigTypeTag(zcu)) { @@ -571,7 +544,8 @@ pub fn readFromPackedMemory( const abi_size: usize = @intCast(ty.abiSize(zcu)); const Limb = std.math.big.Limb; const limb_count = (abi_size + @sizeOf(Limb) - 1) / @sizeOf(Limb); - const limbs_buffer = try arena.alloc(Limb, limb_count); + const limbs_buffer = try gpa.alloc(Limb, limb_count); + defer gpa.free(limbs_buffer); var bigint = BigIntMutable.init(limbs_buffer, 0); bigint.readPackedTwosComplement(buffer, bit_offset, bits, endian, int_info.signedness); @@ -579,7 +553,7 @@ pub fn readFromPackedMemory( }, .@"enum" => { const int_ty = ty.intTagType(zcu); - const int_val = try Value.readFromPackedMemory(int_ty, pt, buffer, bit_offset, arena); + const int_val = try Value.readFromPackedMemory(int_ty, pt, buffer, bit_offset, gpa); return pt.getCoerced(int_val, ty); }, .float => return Value.fromInterned(try pt.intern(.{ .float = .{ @@ -595,52 +569,32 @@ pub fn readFromPackedMemory( } })), .vector => { const elem_ty = ty.childType(zcu); - const elems = try arena.alloc(InternPool.Index, @intCast(ty.arrayLen(zcu))); + const elems = try gpa.alloc(InternPool.Index, @intCast(ty.arrayLen(zcu))); + defer gpa.free(elems); var bits: u16 = 0; const elem_bit_size: u16 = @intCast(elem_ty.bitSize(zcu)); for (elems, 0..) |_, i| { // On big-endian systems, LLVM reverses the element order of vectors by default const tgt_elem_i = if (endian == .big) elems.len - i - 1 else i; - elems[tgt_elem_i] = (try readFromPackedMemory(elem_ty, pt, buffer, bit_offset + bits, arena)).toIntern(); + elems[tgt_elem_i] = (try readFromPackedMemory(elem_ty, pt, buffer, bit_offset + bits, gpa)).toIntern(); bits += elem_bit_size; } return pt.aggregateValue(ty, elems); }, - .@"struct" => { - // Sema is supposed to have emitted a compile error already for Auto layout structs, - // and Extern is handled by non-packed readFromMemory. - const struct_type = zcu.typeToPackedStruct(ty).?; - var bits: u16 = 0; - const field_vals = try arena.alloc(InternPool.Index, struct_type.field_types.len); - for (field_vals, 0..) |*field_val, i| { - const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); - const field_bits: u16 = @intCast(field_ty.bitSize(zcu)); - field_val.* = (try readFromPackedMemory(field_ty, pt, buffer, bit_offset + bits, arena)).toIntern(); - bits += field_bits; - } - return pt.aggregateValue(ty, field_vals); - }, - .@"union" => switch (ty.containerLayout(zcu)) { - .auto, .@"extern" => unreachable, // Handled by non-packed readFromMemory - .@"packed" => { - const backing_ty = try ty.unionBackingType(pt); - const val = (try readFromPackedMemory(backing_ty, pt, buffer, bit_offset, arena)).toIntern(); - return Value.fromInterned(try pt.internUnion(.{ - .ty = ty.toIntern(), - .tag = .none, - .val = val, - })); - }, + .@"struct", .@"union" => { + assert(ty.containerLayout(zcu) == .@"packed"); + const int_val: Value = try .readFromPackedMemory(ty.bitpackBackingInt(zcu), pt, buffer, bit_offset, gpa); + return pt.bitpackValue(ty, int_val); }, .pointer => { assert(!ty.isSlice(zcu)); // No well defined layout. - const addr = (try readFromPackedMemory(Type.usize, pt, buffer, bit_offset, arena)).toUnsignedInt(zcu); + const addr = (try readFromPackedMemory(Type.usize, pt, buffer, bit_offset, gpa)).toUnsignedInt(zcu); return pt.ptrIntValue(ty, addr); }, .optional => { assert(ty.isPtrLikeOptional(zcu)); - const addr = (try readFromPackedMemory(Type.usize, pt, buffer, bit_offset, arena)).toUnsignedInt(zcu); + const addr = (try readFromPackedMemory(Type.usize, pt, buffer, bit_offset, gpa)).toUnsignedInt(zcu); return .fromInterned(try pt.intern(.{ .opt = .{ .ty = ty.toIntern(), .val = if (addr == 0) .none else (try pt.ptrIntValue(ty.childType(zcu), addr)).toIntern(), @@ -915,8 +869,44 @@ pub fn fieldValue(val: Value, pt: Zcu.PerThread, index: usize) !Value { .elems => |elems| elems[index], .repeated_elem => |elem| elem, }), - // TODO assert the tag is correct - .un => |un| Value.fromInterned(un.val), + .un => |un| { + switch (Type.fromInterned(un.ty).containerLayout(zcu)) { + .auto, .@"extern" => {}, // TODO assert the tag is correct + .@"packed" => unreachable, + } + return .fromInterned(un.val); + }, + .bitpack => |bitpack| { + const ty: Type = .fromInterned(bitpack.ty); + assert(ty.containerLayout(zcu) == .@"packed"); + const int_val: Value = .fromInterned(bitpack.backing_int_val); + assert(!int_val.isUndef(zcu)); + const field_ty = ty.fieldType(index, zcu); + const field_bit_offset: u16 = switch (ty.zigTypeTag(zcu)) { + .@"union" => 0, + .@"struct" => off: { + var off: u16 = 0; + for (0..index) |preceding_field_index| { + off += @intCast(ty.fieldType(preceding_field_index, zcu).bitSize(zcu)); + } + break :off off; + }, + else => unreachable, + }; + // Avoid hitting gpa for accesses to small packed structs + var sfba_state = std.heap.stackFallback(128, zcu.comp.gpa); + const sfba = sfba_state.get(); + const buf = try sfba.alloc(u8, (ty.bitSize(zcu) + 7) / 8); + defer sfba.free(buf); + int_val.writeToPackedMemory(pt, buf, 0) catch |err| switch (err) { + error.ReinterpretDeclRef => unreachable, // it's an integer + error.OutOfMemory => |e| return e, + }; + return Value.readFromPackedMemory(field_ty, pt, buf, field_bit_offset, sfba) catch |err| switch (err) { + error.IllDefinedMemoryLayout => unreachable, // it's a bitpack + error.OutOfMemory => |e| return e, + }; + }, else => unreachable, }; } diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 00c911caf4e67e3a7dcf5691ebe7cf45d53ff002..186d6147d13622463f56d708f07a62d8b0e128c2 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -3950,6 +3950,15 @@ pub fn floatValue(pt: Zcu.PerThread, ty: Type, x: anytype) Allocator.Error!Value } })); } +/// Create a value whose type is a `packed struct` or `packed union`, from the backing integer value. +pub fn bitpackValue(pt: Zcu.PerThread, ty: Type, backing_int_val: Value) Allocator.Error!Value { + assert(backing_int_val.typeOf(pt.zcu).toIntern() == ty.bitpackBackingInt(pt.zcu).toIntern()); + return .fromInterned(try pt.intern(.{ .bitpack = .{ + .ty = ty.toIntern(), + .backing_int_val = backing_int_val.toIntern(), + } })); +} + pub fn nullValue(pt: Zcu.PerThread, opt_ty: Type) Allocator.Error!Value { assert(pt.zcu.intern_pool.isOptionalType(opt_ty.toIntern())); return Value.fromInterned(try pt.intern(.{ .opt = .{ diff --git a/src/codegen.zig b/src/codegen.zig index e9acab66e4c2b8a618447ea6fad9659ab1c39243..9edb90fb51056d9ad56f913982b001ff8750e52b 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -570,42 +570,7 @@ pub fn generateSymbol( .struct_type => { const struct_type = ip.loadStructType(ty.toIntern()); switch (struct_type.layout) { - .@"packed" => { - const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow; - const start = w.end; - const buffer = try w.writableSlice(abi_size); - @memset(buffer, 0); - var bits: u16 = 0; - - for (struct_type.field_types.get(ip), 0..) |field_ty, index| { - const field_val = switch (aggregate.storage) { - .bytes => |bytes| try pt.intern(.{ .int = .{ - .ty = field_ty, - .storage = .{ .u64 = bytes.at(index, ip) }, - } }), - .elems => |elems| elems[index], - .repeated_elem => |elem| elem, - }; - - // pointer may point to a decl which must be marked used - // but can also result in a relocation. Therefore we handle those separately. - if (Type.fromInterned(field_ty).zigTypeTag(zcu) == .pointer) { - const field_offset = std.math.divExact(u16, bits, 8) catch |err| switch (err) { - error.DivisionByZero => unreachable, - error.UnexpectedRemainder => return error.RelocationNotByteAligned, - }; - w.end = start + field_offset; - defer { - assert(w.end == start + field_offset + @divExact(target.ptrBitWidth(), 8)); - w.end = start + abi_size; - } - try generateSymbol(bin_file, pt, src_loc, Value.fromInterned(field_val), w, reloc_parent); - } else { - Value.fromInterned(field_val).writeToPackedMemory(.fromInterned(field_ty), pt, buffer, bits) catch unreachable; - } - bits += @intCast(Type.fromInterned(field_ty).bitSize(zcu)); - } - }, + .@"packed" => unreachable, .auto, .@"extern" => { const struct_begin = w.end; const field_types = struct_type.field_types.get(ip); @@ -683,6 +648,7 @@ pub fn generateSymbol( } } }, + .bitpack => |bitpack| try generateSymbol(bin_file, pt, src_loc, .fromInterned(bitpack.backing_int_val), w, reloc_parent), .memoized_call => unreachable, } } @@ -1120,6 +1086,10 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo target, ); }, + .@"struct", .@"union" => if (ty.containerLayout(zcu) == .@"packed") { + const bitpack = ip.indexToKey(val.toIntern()).bitpack; + return lowerValue(pt, .fromInterned(bitpack.backing_int_val), target); + }, .error_set => { const err_name = ip.indexToKey(val.toIntern()).err.name; const error_index = ip.getErrorValueIfExists(err_name).?; diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig index 74494649056adbe9d0baeceea5f320c9b12f5d95..f9ff7874770ed1bd1b995a3689a89242c7211898 100644 --- a/src/codegen/aarch64/Select.zig +++ b/src/codegen/aarch64/Select.zig @@ -2791,17 +2791,17 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, } else return isel.fail("invalid constraint: '{s}'", .{constraint}); } - const clobbers = ip.indexToKey(unwrapped_asm.clobbers).aggregate; - const clobbers_ty: ZigType = .fromInterned(clobbers.ty); + const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers); + const clobbers_ty = clobbers_val.typeOf(zcu); + var clobbers_bigint_buf: Value.BigIntSpace = undefined; + const clobbers_bigint = clobbers_val.toBigInt(&clobbers_bigint_buf, zcu); for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { - switch (switch (clobbers.storage) { - .bytes => unreachable, - .elems => |elems| elems[field_index], - .repeated_elem => |repeated_elem| repeated_elem, - }) { - else => unreachable, - .bool_false => continue, - .bool_true => {}, + assert(clobbers_ty.fieldType(field_index, zcu).toIntern() == .bool_type); + const limb_bits = @bitSizeOf(std.math.big.Limb); + if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false + switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { + 0 => continue, // field is false + 1 => {}, // field is true } const clobber_name = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?; if (std.mem.eql(u8, clobber_name, "memory")) continue; @@ -2816,14 +2816,11 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, } } for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { - switch (switch (clobbers.storage) { - .bytes => unreachable, - .elems => |elems| elems[field_index], - .repeated_elem => |repeated_elem| repeated_elem, - }) { - else => unreachable, - .bool_false => continue, - .bool_true => {}, + const limb_bits = @bitSizeOf(std.math.big.Limb); + if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false + switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> field_index % limb_bits))) { + 0 => continue, // field is false + 1 => {}, // field is true } const clobber_name = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?; if (std.mem.eql(u8, clobber_name, "memory")) continue; @@ -2872,14 +2869,11 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, } for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { - switch (switch (clobbers.storage) { - .bytes => unreachable, - .elems => |elems| elems[field_index], - .repeated_elem => |repeated_elem| repeated_elem, - }) { - else => unreachable, - .bool_false => continue, - .bool_true => {}, + const limb_bits = @bitSizeOf(std.math.big.Limb); + if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false + switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> field_index % limb_bits))) { + 0 => continue, // field is false + 1 => {}, // field is true } const clobber_name = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?; if (std.mem.eql(u8, clobber_name, "memory")) continue; diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 5e9f21e1aada16d7fa98ebd9a9c01d7b11a35d8c..69c4e91d999c4340e0fe18f299ba88787052a66a 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1362,77 +1362,42 @@ pub const DeclGen = struct { }, .struct_type => { const loaded_struct = ip.loadStructType(ty.toIntern()); - switch (loaded_struct.layout) { - .auto, .@"extern" => { - if (!location.isInitializer()) { - try w.writeByte('('); - try dg.renderCType(w, ctype); - try w.writeByte(')'); - } + assert(loaded_struct.layout != .@"packed"); - try w.writeByte('{'); - var field_it = loaded_struct.iterateRuntimeOrder(ip); - var need_comma = false; - while (field_it.next()) |field_index| { - const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!location.isInitializer()) { + try w.writeByte('('); + try dg.renderCType(w, ctype); + try w.writeByte(')'); + } + + try w.writeByte('{'); + var field_it = loaded_struct.iterateRuntimeOrder(ip); + var need_comma = false; + while (field_it.next()) |field_index| { + const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); + if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; - if (need_comma) try w.writeByte(','); - need_comma = true; - const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { - .bytes => |bytes| try pt.intern(.{ .int = .{ - .ty = field_ty.toIntern(), - .storage = .{ .u64 = bytes.at(field_index, ip) }, - } }), - .elems => |elems| elems[field_index], - .repeated_elem => |elem| elem, - }; - try dg.renderValue(w, Value.fromInterned(field_val), initializer_type); - } - try w.writeByte('}'); - }, - .@"packed" => { - // https://github.com/ziglang/zig/issues/24657 will eliminate most of the - // following logic, leaving only the recursive `renderValue` call. Once - // that proposal is implemented, a `packed struct` will literally be - // represented in the InternPool by its comptime-known backing integer. - var arena: std.heap.ArenaAllocator = .init(zcu.gpa); - defer arena.deinit(); - const backing_ty: Type = .fromInterned(loaded_struct.backingIntTypeUnordered(ip)); - const buf = try arena.allocator().alloc(u8, @intCast(ty.abiSize(zcu))); - val.writeToMemory(pt, buf) catch |err| switch (err) { - error.IllDefinedMemoryLayout => unreachable, - error.OutOfMemory => |e| return e, - error.ReinterpretDeclRef, error.Unimplemented => return dg.fail("TODO: C backend: lower packed struct value", .{}), - }; - const backing_val: Value = try .readUintFromMemory(backing_ty, pt, buf, arena.allocator()); - return dg.renderValue(w, backing_val, location); - }, + if (need_comma) try w.writeByte(','); + need_comma = true; + const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { + .bytes => |bytes| try pt.intern(.{ .int = .{ + .ty = field_ty.toIntern(), + .storage = .{ .u64 = bytes.at(field_index, ip) }, + } }), + .elems => |elems| elems[field_index], + .repeated_elem => |elem| elem, + }; + try dg.renderValue(w, Value.fromInterned(field_val), initializer_type); } + try w.writeByte('}'); }, else => unreachable, }, + .bitpack => |bitpack| return dg.renderValue(w, .fromInterned(bitpack.backing_int_val), location), .un => |un| { const loaded_union = ip.loadUnionType(ty.toIntern()); - if (loaded_union.flagsUnordered(ip).layout == .@"packed") { - // https://github.com/ziglang/zig/issues/24657 will eliminate most of the - // following logic, leaving only the recursive `renderValue` call. Once - // that proposal is implemented, a `packed union` will literally be - // represented in the InternPool by its comptime-known backing integer. - var arena: std.heap.ArenaAllocator = .init(zcu.gpa); - defer arena.deinit(); - const backing_ty = try ty.unionBackingType(pt); - const buf = try arena.allocator().alloc(u8, @intCast(ty.abiSize(zcu))); - val.writeToMemory(pt, buf) catch |err| switch (err) { - error.IllDefinedMemoryLayout => unreachable, - error.OutOfMemory => |e| return e, - error.ReinterpretDeclRef, error.Unimplemented => return dg.fail("TODO: C backend: lower packed union value", .{}), - }; - const backing_val: Value = try .readUintFromMemory(backing_ty, pt, buf, arena.allocator()); - return dg.renderValue(w, backing_val, location); - } if (un.tag == .none) { - const backing_ty = try ty.unionBackingType(pt); + const backing_ty = try ty.externUnionBackingType(pt); assert(loaded_union.flagsUnordered(ip).layout == .@"extern"); if (location == .StaticInitializer) { return dg.fail("TODO: C backend: implement extern union backing type rendering in static initializers", .{}); @@ -1642,11 +1607,7 @@ pub const DeclGen = struct { } return w.writeByte('}'); }, - .@"packed" => return dg.renderUndefValue( - w, - .fromInterned(loaded_struct.backingIntTypeUnordered(ip)), - location, - ), + .@"packed" => return dg.renderUndefValue(w, ty.bitpackBackingInt(zcu), location), } }, .tuple_type => |tuple_info| { @@ -1714,11 +1675,7 @@ pub const DeclGen = struct { } if (has_tag) try w.writeByte('}'); }, - .@"packed" => return dg.renderUndefValue( - w, - try ty.unionBackingType(pt), - location, - ), + .@"packed" => return dg.renderUndefValue(w, ty.bitpackBackingInt(zcu), location), } }, .error_union_type => |error_union_type| switch (ctype.info(ctype_pool)) { @@ -5623,48 +5580,45 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { } try w.writeByte(':'); const ip = &zcu.intern_pool; - const aggregate = ip.indexToKey(unwrapped_asm.clobbers).aggregate; - const struct_type: Type = .fromInterned(aggregate.ty); - switch (aggregate.storage) { - .elems => |elems| for (elems, 0..) |elem, i| switch (elem) { - .bool_true => { - const field_name = struct_type.structFieldName(i, zcu).toSlice(ip).?; - assert(field_name.len != 0); + const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers); + const clobbers_ty = clobbers_val.typeOf(zcu); + var clobbers_bigint_buf: Value.BigIntSpace = undefined; + const clobbers_bigint = clobbers_val.toBigInt(&clobbers_bigint_buf, zcu); + for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { + assert(clobbers_ty.fieldType(field_index, zcu).toIntern() == .bool_type); + const limb_bits = @bitSizeOf(std.math.big.Limb); + if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false + switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { + 0 => continue, // field is false + 1 => {}, // field is true + } + const field_name = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?; + assert(field_name.len != 0); - const target = &f.object.dg.mod.resolved_target.result; - var c_name_buf: [16]u8 = undefined; - const name = - if ((target.cpu.arch.isMIPS() or target.cpu.arch == .alpha) and field_name[0] == 'r') name: { - // Convert "rN" to "$N" - const c_name = (&c_name_buf)[0..field_name.len]; - @memcpy(c_name, field_name); - c_name_buf[0] = '$'; - break :name c_name; - } else if ((target.cpu.arch.isMIPS() and (mem.startsWith(u8, field_name, "fcc") or field_name[0] == 'w')) or - ((target.cpu.arch.isMIPS() or target.cpu.arch == .alpha) and field_name[0] == 'f') or - (target.cpu.arch == .kvx and !mem.eql(u8, field_name, "memory"))) name: { - // "$" prefix for these registers - c_name_buf[0] = '$'; - @memcpy((&c_name_buf)[1..][0..field_name.len], field_name); - break :name (&c_name_buf)[0 .. 1 + field_name.len]; - } else if (target.cpu.arch.isSPARC() and - (mem.eql(u8, field_name, "ccr") or mem.eql(u8, field_name, "icc") or mem.eql(u8, field_name, "xcc"))) name: { - // C compilers just use `icc` to encompass all of these. - break :name "icc"; - } else field_name; + const target = &f.object.dg.mod.resolved_target.result; + var c_name_buf: [16]u8 = undefined; + const name = + if ((target.cpu.arch.isMIPS() or target.cpu.arch == .alpha) and field_name[0] == 'r') name: { + // Convert "rN" to "$N" + const c_name = (&c_name_buf)[0..field_name.len]; + @memcpy(c_name, field_name); + c_name_buf[0] = '$'; + break :name c_name; + } else if ((target.cpu.arch.isMIPS() and (mem.startsWith(u8, field_name, "fcc") or field_name[0] == 'w')) or + ((target.cpu.arch.isMIPS() or target.cpu.arch == .alpha) and field_name[0] == 'f') or + (target.cpu.arch == .kvx and !mem.eql(u8, field_name, "memory"))) name: { + // "$" prefix for these registers + c_name_buf[0] = '$'; + @memcpy((&c_name_buf)[1..][0..field_name.len], field_name); + break :name (&c_name_buf)[0 .. 1 + field_name.len]; + } else if (target.cpu.arch.isSPARC() and + (mem.eql(u8, field_name, "ccr") or mem.eql(u8, field_name, "icc") or mem.eql(u8, field_name, "xcc"))) name: { + // C compilers just use `icc` to encompass all of these. + break :name "icc"; + } else field_name; - try w.print(" {f}", .{fmtStringLiteral(name, null)}); - (try w.writableArray(1))[0] = ','; - }, - .bool_false => continue, - else => unreachable, - }, - .repeated_elem => |elem| switch (elem) { - .bool_true => @panic("TODO"), - .bool_false => {}, - else => unreachable, - }, - .bytes => @panic("TODO"), + try w.print(" {f}", .{fmtStringLiteral(name, null)}); + (try w.writableArray(1))[0] = ','; } w.undo(1); // erase the last comma try w.writeAll(");"); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index ad115504baec4eaad608f6f3cf9d614a3e9d610d..695bb82133aea39b4478c3a9ad4f4ec4c07be6cc 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3680,7 +3680,7 @@ pub const Object = struct { const limbs = try allocator.alloc(std.math.big.Limb, std.math.big.int.calcTwosCompLimbCount(bits)); defer allocator.free(limbs); - val.writeToPackedMemory(ty, pt, buffer, 0) catch unreachable; + val.writeToPackedMemory(pt, buffer, 0) catch unreachable; var big: std.math.big.int.Mutable = .init(limbs, 0); big.readTwosComplement(buffer, bits, target.cpu.arch.endian(), .unsigned); @@ -7467,29 +7467,20 @@ pub const FuncGen = struct { } const ip = &zcu.intern_pool; - const aggregate = ip.indexToKey(unwrapped_asm.clobbers).aggregate; - const struct_type: Type = .fromInterned(aggregate.ty); - if (total_i != 0) try llvm_constraints.append(gpa, ','); - switch (aggregate.storage) { - .elems => |elems| for (elems, 0..) |elem, i| { - switch (elem) { - .bool_true => { - const name = struct_type.structFieldName(i, zcu).toSlice(ip).?; - total_i += try appendConstraints(gpa, &llvm_constraints, name, target); - }, - .bool_false => continue, - else => unreachable, - } - }, - .repeated_elem => |elem| switch (elem) { - .bool_true => for (0..struct_type.structFieldCount(zcu)) |i| { - const name = struct_type.structFieldName(i, zcu).toSlice(ip).?; - total_i += try appendConstraints(gpa, &llvm_constraints, name, target); - }, - .bool_false => {}, - else => unreachable, - }, - .bytes => @panic("TODO"), + const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers); + const clobbers_ty = clobbers_val.typeOf(zcu); + var clobbers_bigint_buf: Value.BigIntSpace = undefined; + const clobbers_bigint = clobbers_val.toBigInt(&clobbers_bigint_buf, zcu); + for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { + assert(clobbers_ty.fieldType(field_index, zcu).toIntern() == .bool_type); + const limb_bits = @bitSizeOf(std.math.big.Limb); + if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false + switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { + 0 => continue, // field is false + 1 => {}, // field is true + } + const name = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?; + total_i += try appendConstraints(gpa, &llvm_constraints, name, target); } // We have finished scanning through all inputs/outputs, so the number of diff --git a/src/codegen/riscv64/CodeGen.zig b/src/codegen/riscv64/CodeGen.zig index 72174554adc862a80034a2af57721703cba0c7a2..1f5b6224d7ef7fbe1cfe1aaa2fc55889db0676ca 100644 --- a/src/codegen/riscv64/CodeGen.zig +++ b/src/codegen/riscv64/CodeGen.zig @@ -6149,31 +6149,26 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void { const zcu = func.pt.zcu; const ip = &zcu.intern_pool; - const aggregate = ip.indexToKey(unwrapped_asm.clobbers).aggregate; - const struct_type: Type = .fromInterned(aggregate.ty); - switch (aggregate.storage) { - .elems => |elems| for (elems, 0..) |elem, i| { - switch (elem) { - .bool_true => { - const clobber = struct_type.structFieldName(i, zcu).toSlice(ip).?; - assert(clobber.len != 0); - if (std.mem.eql(u8, clobber, "memory")) { - // nothing really to do - } else { - try func.register_manager.getReg(parseRegName(clobber) orelse - return func.fail("invalid clobber: '{s}'", .{clobber}), null); - } - }, - .bool_false => continue, - else => unreachable, - } - }, - .repeated_elem => |elem| switch (elem) { - .bool_true => @panic("TODO"), - .bool_false => {}, - else => unreachable, - }, - .bytes => @panic("TODO"), + const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers); + const clobbers_ty = clobbers_val.typeOf(zcu); + var clobbers_bigint_buf: Value.BigIntSpace = undefined; + const clobbers_bigint = clobbers_val.toBigInt(&clobbers_bigint_buf, zcu); + for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { + assert(clobbers_ty.fieldType(field_index, zcu).toIntern() == .bool_type); + const limb_bits = @bitSizeOf(std.math.big.Limb); + if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false + switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { + 0 => continue, // field is false + 1 => {}, // field is true + } + const clobber = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?; + assert(clobber.len != 0); + if (std.mem.eql(u8, clobber, "memory")) { + // nothing really to do + } else { + try func.register_manager.getReg(parseRegName(clobber) orelse + return func.fail("invalid clobber: '{s}'", .{clobber}), null); + } } const Label = struct { diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig index 5217002f22ecaa5dc3aad1a2035040baa6132e5c..709de66a412e409ea6017d0a15a631156fe133e4 100644 --- a/src/codegen/spirv/CodeGen.zig +++ b/src/codegen/spirv/CodeGen.zig @@ -969,7 +969,7 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { const bytes = std.mem.alignForward(u16, cg.module.backingIntBits(bits).@"0", 8) / 8; var limbs: [8]u8 = undefined; @memset(&limbs, 0); - val.writeToPackedMemory(ty, pt, limbs[0..bytes], 0) catch unreachable; + val.writeToPackedMemory(pt, limbs[0..bytes], 0) catch unreachable; const backing_ty: Type = .fromInterned(struct_type.backingIntTypeUnordered(ip)); return try cg.constInt(backing_ty, @as(u64, @bitCast(limbs))); } diff --git a/src/codegen/wasm/CodeGen.zig b/src/codegen/wasm/CodeGen.zig index 955e9b51d361ec75ea1c1b5ab08c71dc7f2cbd40..cdcaac93025a4902f1d123c485e80076558a84ed 100644 --- a/src/codegen/wasm/CodeGen.zig +++ b/src/codegen/wasm/CodeGen.zig @@ -3253,7 +3253,7 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { // are by-ref types. assert(struct_type.layout == .@"packed"); var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer - val.writeToPackedMemory(ty, pt, &buf, 0) catch unreachable; + val.writeToPackedMemory(pt, &buf, 0) catch unreachable; const backing_int_ty = Type.fromInterned(struct_type.backingIntTypeUnordered(ip)); const int_val = try pt.intValue( backing_int_ty, @@ -3267,7 +3267,7 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { const int_type = try pt.intType(.unsigned, @intCast(ty.bitSize(zcu))); var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer - val.writeToPackedMemory(ty, pt, &buf, 0) catch unreachable; + val.writeToPackedMemory(pt, &buf, 0) catch unreachable; const int_val = try pt.intValue( int_type, mem.readInt(u64, &buf, .little), diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index a9898398d7318fc1cf6046fac752c998ae3a5282..2a7558505b3c4b1bedad6466d7c15452534c78c1 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -177294,41 +177294,38 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { } const ip = &zcu.intern_pool; - const aggregate = ip.indexToKey(unwrapped_asm.clobbers).aggregate; - const struct_type: Type = .fromInterned(aggregate.ty); - switch (aggregate.storage) { - .elems => |elems| for (elems, 0..) |elem, i| switch (elem) { - .bool_true => { - const clobber = struct_type.structFieldName(i, zcu).toSlice(ip).?; - assert(clobber.len != 0); + const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers); + const clobbers_ty = clobbers_val.typeOf(zcu); + var clobbers_bigint_buf: Value.BigIntSpace = undefined; + const clobbers_bigint = clobbers_val.toBigInt(&clobbers_bigint_buf, zcu); + for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { + assert(clobbers_ty.fieldType(field_index, zcu).toIntern() == .bool_type); + const limb_bits = @bitSizeOf(std.math.big.Limb); + if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false + switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { + 0 => continue, // field is false + 1 => {}, // field is true + } + const clobber = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?; + assert(clobber.len != 0); - if (std.mem.eql(u8, clobber, "memory") or - std.mem.eql(u8, clobber, "fpsr") or - std.mem.eql(u8, clobber, "fpcr") or - std.mem.eql(u8, clobber, "mxcsr") or - std.mem.eql(u8, clobber, "dirflag")) - { - // ok, sure - } else if (std.mem.eql(u8, clobber, "cc") or - std.mem.eql(u8, clobber, "flags") or - std.mem.eql(u8, clobber, "eflags") or - std.mem.eql(u8, clobber, "rflags")) - { - try self.spillEflagsIfOccupied(); - } else { - try self.register_manager.getReg(parseRegName(clobber) orelse - return self.fail("invalid clobber: '{s}'", .{clobber}), null); - } - }, - .bool_false => continue, - else => unreachable, - }, - .repeated_elem => |elem| switch (elem) { - .bool_true => @panic("TODO"), - .bool_false => {}, - else => unreachable, - }, - .bytes => @panic("TODO"), + if (std.mem.eql(u8, clobber, "memory") or + std.mem.eql(u8, clobber, "fpsr") or + std.mem.eql(u8, clobber, "fpcr") or + std.mem.eql(u8, clobber, "mxcsr") or + std.mem.eql(u8, clobber, "dirflag")) + { + // ok, sure + } else if (std.mem.eql(u8, clobber, "cc") or + std.mem.eql(u8, clobber, "flags") or + std.mem.eql(u8, clobber, "eflags") or + std.mem.eql(u8, clobber, "rflags")) + { + try self.spillEflagsIfOccupied(); + } else { + try self.register_manager.getReg(parseRegName(clobber) orelse + return self.fail("invalid clobber: '{s}'", .{clobber}), null); + } } const Label = struct { diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index f77518d4655514850cdaab6dfc3cde9ee76a7d4a..027d5391a56231bc342f6cfe7e8d55a5a08379fa 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -3378,6 +3378,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo .opt, .aggregate, .un, + .bitpack, => .decl_const, .variable => .decl_var, .@"extern" => unreachable, @@ -4014,6 +4015,7 @@ fn updateLazyType( .opt, .aggregate, .un, + .bitpack, // memoization, not types .memoized_call, => unreachable, @@ -4092,6 +4094,15 @@ fn updateLazyValue( }, .fromInterned(int.ty), Value.fromInterned(value_index).toBigInt(&big_int_space, zcu)); try wip_nav.refType(.fromInterned(int.ty)); }, + .bitpack => |bitpack| { + const backing_int_val: Value = .fromInterned(bitpack.backing_int_val); + try wip_nav.bigIntConstValue(.{ + .sdata = .sdata_comptime_value, + .udata = .udata_comptime_value, + .block = .block_comptime_value, + }, backing_int_val.typeOf(zcu), backing_int_val.toBigInt(&big_int_space, zcu)); + try wip_nav.refType(.fromInterned(bitpack.ty)); + }, .err => |err| { try wip_nav.abbrevCode(.udata_comptime_value); try wip_nav.refType(.fromInterned(err.ty)); diff --git a/src/mutable_value.zig b/src/mutable_value.zig index 97d6f22b3b90e5d9215ec011760ee6feb9c0d3f1..8ddd434837ea2d1036229757d8ec20c3df5a45e5 100644 --- a/src/mutable_value.zig +++ b/src/mutable_value.zig @@ -97,8 +97,8 @@ pub const MutableValue = union(enum) { /// * Non-error error unions use `eu_payload` /// * Non-null optionals use `eu_payload /// * Slices use `slice` - /// * Unions use `un` - /// * Aggregates use `repeated` or `bytes` or `aggregate` + /// * Unions use `un` (excluding packed unions) + /// * Aggregates use `repeated` or `bytes` or `aggregate` (excluding packed structs) /// If `!allow_bytes`, the `bytes` representation will not be used. /// If `!allow_repeated`, the `repeated` representation will not be used. pub fn unintern( @@ -209,6 +209,7 @@ pub const MutableValue = union(enum) { .undef => |ty_ip| switch (Type.fromInterned(ty_ip).zigTypeTag(zcu)) { .@"struct", .array, .vector => |type_tag| { const ty = Type.fromInterned(ty_ip); + if (type_tag == .@"struct" and ty.containerLayout(zcu) == .@"packed") return; const opt_sent = ty.sentinel(zcu); if (type_tag == .@"struct" or opt_sent != null or !allow_repeated) { const len_no_sent = ip.aggregateTypeLen(ty_ip); @@ -241,15 +242,18 @@ pub const MutableValue = union(enum) { } }; } }, - .@"union" => { - const payload = try arena.create(MutableValue); - const backing_ty = try Type.fromInterned(ty_ip).unionBackingType(pt); - payload.* = .{ .interned = try pt.intern(.{ .undef = backing_ty.toIntern() }) }; - mv.* = .{ .un = .{ - .ty = ty_ip, - .tag = .none, - .payload = payload, - } }; + .@"union" => switch (Type.fromInterned(ty_ip).containerLayout(zcu)) { + .auto, .@"packed" => {}, + .@"extern" => { + const payload = try arena.create(MutableValue); + const backing_ty = try Type.fromInterned(ty_ip).externUnionBackingType(pt); + payload.* = .{ .interned = try pt.intern(.{ .undef = backing_ty.toIntern() }) }; + mv.* = .{ .un = .{ + .ty = ty_ip, + .tag = .none, + .payload = payload, + } }; + }, }, .pointer => { const ptr_ty = ip.indexToKey(ty_ip).ptr_type; diff --git a/src/print_value.zig b/src/print_value.zig index 5b29bb04d68d3bf380601e2bed30e2cbe4912e86..d472472481350ff57a47ed3277c6a54cc161d374 100644 --- a/src/print_value.zig +++ b/src/print_value.zig @@ -164,7 +164,7 @@ pub fn print( return; } if (un.tag == .none) { - const backing_ty = try val.typeOf(zcu).unionBackingType(pt); + const backing_ty = try val.typeOf(zcu).externUnionBackingType(pt); try writer.print("@bitCast(@as({f}, ", .{backing_ty.fmt(pt)}); try print(Value.fromInterned(un.val), writer, level - 1, pt, opt_sema); try writer.writeAll("))"); @@ -176,6 +176,32 @@ pub fn print( try writer.writeAll(" }"); } }, + .bitpack => |bitpack| { + const ty: Type = .fromInterned(bitpack.ty); + switch (ty.zigTypeTag(zcu)) { + .@"struct" => { + if (ty.structFieldCount(zcu) == 0) { + return writer.writeAll(".{}"); + } + try writer.writeAll(".{ "); + const max_len = @min(ty.structFieldCount(zcu), max_aggregate_items); + for (0..max_len) |i| { + if (i != 0) try writer.writeAll(", "); + const field_name = ty.structFieldName(@intCast(i), zcu).unwrap().?; + try writer.print(".{f} = ", .{field_name.fmt(ip)}); + try print(try val.fieldValue(pt, i), writer, level - 1, pt, opt_sema); + } + try writer.writeAll(" }"); + return; + }, + .@"union" => { + try writer.print("@bitCast(@as({f}, ", .{ty.bitpackBackingInt(zcu).fmt(pt)}); + try print(.fromInterned(bitpack.backing_int_val), writer, level - 1, pt, opt_sema); + try writer.writeAll("))"); + }, + else => unreachable, + } + }, .memoized_call => unreachable, } } -- 2.54.0 From 187fef209f73336163337474dc02f46c7c89ac3a Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Thu, 29 Jan 2026 08:54:59 +0000 Subject: [PATCH 10/79] compiler: rework OPV and noreturn-like types --- src/Air/Liveness.zig | 2 +- src/Air/Liveness/Verify.zig | 2 +- src/InternPool.zig | 169 ++---- src/Sema.zig | 438 +++++++--------- src/Sema/bitcast.zig | 2 - src/Sema/type_resolution.zig | 122 +++-- src/Type.zig | 917 ++++++++++++++++----------------- src/Value.zig | 7 +- src/Zcu/PerThread.zig | 9 +- src/codegen.zig | 2 - src/codegen/aarch64/Select.zig | 8 +- src/codegen/c.zig | 28 +- src/codegen/c/Type.zig | 14 +- src/codegen/llvm.zig | 3 - src/codegen/spirv/CodeGen.zig | 6 +- src/codegen/wasm/CodeGen.zig | 12 +- src/codegen/x86_64/CodeGen.zig | 2 +- src/link/Dwarf.zig | 41 +- src/print_value.zig | 2 - 19 files changed, 827 insertions(+), 959 deletions(-) diff --git a/src/Air/Liveness.zig b/src/Air/Liveness.zig index a85944c4678455126d04403e1c48486db9d6e860..5c98dc96fca8c54208556eff486475cede9513a6 100644 --- a/src/Air/Liveness.zig +++ b/src/Air/Liveness.zig @@ -999,7 +999,7 @@ fn analyzeInstBlock( // If the block is noreturn, block deaths not only aren't useful, they're impossible to // find: there could be more stuff alive after the block than before it! - if (!a.intern_pool.isNoReturn(ty.toIntern())) { + if (!ty.isNoReturn(a.zcu)) { // The block kills the difference in the live sets const block_scope = data.block_scopes.get(inst).?; const num_deaths = data.live_set.count() - block_scope.live_set.count(); diff --git a/src/Air/Liveness/Verify.zig b/src/Air/Liveness/Verify.zig index fc83574d070c018fc54ed095d4c67f0bf7698fb2..7f820e65981b1d4247b363c061269c8d893ce239 100644 --- a/src/Air/Liveness/Verify.zig +++ b/src/Air/Liveness/Verify.zig @@ -465,7 +465,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { for (block_liveness.deaths) |death| try self.verifyDeath(inst, death); - if (ip.isNoReturn(block_ty.toIntern())) { + if (block_ty.isNoReturn(self.zcu)) { assert(!self.blocks.contains(inst)); } else { var live = if (self.blocks.fetchRemove(inst)) |kv| kv.value else { diff --git a/src/InternPool.zig b/src/InternPool.zig index 7028d690094d195183e3e33b991ddc2ce17572b1..31e37dd98e80f38e1141ce70d86940511cfe1914 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -17,6 +17,7 @@ const Hash = std.hash.Wyhash; const Zir = std.zig.Zir; const Zcu = @import("Zcu.zig"); +const TypeClass = @import("Type.zig").Class; /// One item per thread, indexed by `tid`, which is dense and unique per thread. locals: []Local, @@ -2113,10 +2114,6 @@ pub const Key = union(enum) { enum_literal: NullTerminatedString, /// A specific enum tag, indicated by the integer tag value. enum_tag: EnumTag, - /// An empty enum or union. TODO: this value's existence is strange, because such a type in - /// reality has no values. See #15909. - /// Payload is the type for which we are an empty value. - empty_enum_value: Index, float: Float, ptr: Ptr, slice: Slice, @@ -2722,7 +2719,6 @@ pub const Key = union(enum) { .err, .enum_literal, .enum_tag, - .empty_enum_value, .inferred_error_set_type, .un, => |x| Hash.hash(seed, asBytes(&x)), @@ -3005,10 +3001,6 @@ pub const Key = union(enum) { const b_info = b.enum_tag; return std.meta.eql(a_info, b_info); }, - .empty_enum_value => |a_info| { - const b_info = b.empty_enum_value; - return a_info == b_info; - }, .bitpack => |a_info| { const b_info = b.bitpack; return a_info.ty == b_info.ty and a_info.backing_int_val == b_info.backing_int_val; @@ -3294,10 +3286,8 @@ pub const Key = union(enum) { .enum_literal => .enum_literal_type, .undef => |x| x, - .empty_enum_value => |x| x, .simple_value => |s| switch (s) { - .undefined => .undefined_type, .void => .void_type, .null => .null_type, .false, .true => .bool_type, @@ -3356,10 +3346,7 @@ pub const LoadedStructType = struct { field_runtime_order: RuntimeOrder.Slice, field_offsets: Offsets, packed_backing_int_type: Index, - has_no_possible_value: bool, - has_one_possible_value: bool, - comptime_only: bool, - has_runtime_bits: bool, + class: TypeClass, size: u32, alignment: Alignment, @@ -3535,19 +3522,21 @@ pub const LoadedUnionType = struct { // The remaining fields are only valid once the union's layout is resolved. field_types: Index.Slice, field_aligns: Alignment.Slice, - runtime_tag: RuntimeTag, - /// Even if `runtime_tag == .none`, this is populated with the union's "hypothetical" tag type. + tag_usage: TagUsage, + /// While `tag_usage` indicates whether the union should logically contain a tag, it may be + /// omitted if the union layout is resolved as OPV or NPV. This field is `true` iff there is an + /// actual runtime tag in the union layout. + has_runtime_tag: bool, + /// Even if `tag_usage == .none` and `has_runtime_tag == false`, this is still populated with + /// the union's "hypothetical" tag type. enum_tag_type: Index, packed_backing_int_type: Index, - has_no_possible_value: bool, - has_one_possible_value: bool, - comptime_only: bool, - has_runtime_bits: bool, + class: TypeClass, size: u32, padding: u32, alignment: Alignment, - pub const RuntimeTag = enum(u2) { + pub const TagUsage = enum(u2) { none, safety, tagged, @@ -3733,10 +3722,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { .field_runtime_order = field_runtime_order, .field_offsets = field_offsets, .packed_backing_int_type = .none, - .has_no_possible_value = extra.data.flags.has_no_possible_value, - .has_one_possible_value = extra.data.flags.has_one_possible_value, - .comptime_only = extra.data.flags.comptime_only, - .has_runtime_bits = extra.data.flags.has_runtime_bits, + .class = extra.data.flags.class, .size = extra.data.size, .alignment = extra.data.flags.alignment, }; @@ -3797,10 +3783,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { .field_runtime_order = .empty, .field_offsets = .empty, .packed_backing_int_type = extra.data.backing_int_type, - .has_no_possible_value = undefined, - .has_one_possible_value = undefined, - .comptime_only = undefined, - .has_runtime_bits = undefined, + .class = undefined, .size = undefined, .alignment = undefined, }; @@ -3865,7 +3848,7 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { .auto => .auto, .@"extern" => .@"extern", }, - .runtime_tag = extra.data.flags.runtime_tag, + .tag_usage = extra.data.flags.tag_usage, .enum_tag_mode = extra.data.flags.enum_tag_mode, .enum_tag_type = extra.data.enum_tag_type, .packed_backing_mode = undefined, @@ -3874,10 +3857,8 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { .want_layout = extra.data.flags.want_layout, .field_types = field_types, .field_aligns = field_aligns, - .has_no_possible_value = extra.data.flags.has_no_possible_value, - .has_one_possible_value = extra.data.flags.has_one_possible_value, - .comptime_only = extra.data.flags.comptime_only, - .has_runtime_bits = extra.data.flags.has_runtime_bits, + .has_runtime_tag = extra.data.flags.has_runtime_tag, + .class = extra.data.flags.class, .size = extra.data.size, .padding = extra.data.padding, .alignment = extra.data.flags.alignment, @@ -3919,7 +3900,7 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { .name_nav = extra.data.name_nav, .namespace = extra.data.namespace, .layout = .@"packed", - .runtime_tag = .none, + .tag_usage = .none, .enum_tag_mode = .auto, .enum_tag_type = extra.data.enum_tag_type, .packed_backing_mode = backing_mode, @@ -3928,10 +3909,8 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { .want_layout = extra.data.bits.want_layout, .field_types = field_types, .field_aligns = .empty, - .has_no_possible_value = undefined, - .has_one_possible_value = undefined, - .comptime_only = undefined, - .has_runtime_bits = undefined, + .has_runtime_tag = undefined, + .class = undefined, .size = undefined, .padding = undefined, .alignment = undefined, @@ -4818,7 +4797,7 @@ pub const static_keys: [static_len]Key = .{ .values = .empty, } }, - .{ .simple_value = .undefined }, + .{ .undef = .undefined_type }, .{ .undef = .bool_type }, .{ .undef = .usize_type }, .{ .undef = .u1_type }, @@ -5682,23 +5661,14 @@ pub const Tag = enum(u8) { any_field_defaults: bool, any_field_aligns: bool, - /// Whether the struct is an OPV type. Always `false` until layout resolved. - /// The actual OPV is not cached, but caching this bit of state means we avoid - /// repeatedly doing redundant checks to find that the struct is not OPV! - has_one_possible_value: bool, - /// Like `has_one_possible_value`, but for a "noreturn" union (where all fields are noreturn). - has_no_possible_value: bool, - /// Whether the struct is comptime-only. Always `false` until layout resolved. - comptime_only: bool, - /// Whether the struct has runtime bits. Always `false` until layout resolved. - has_runtime_bits: bool, + class: TypeClass, /// Alignment of the whole struct. Always `.none` until layout resolved. alignment: Alignment, want_layout: bool, want_defaults: bool, - _: u14 = 0, + _: u15 = 0, }; }; @@ -5778,18 +5748,11 @@ pub const Tag = enum(u8) { layout: enum(u1) { auto, @"extern" }, any_field_aligns: bool, - runtime_tag: LoadedUnionType.RuntimeTag, + tag_usage: LoadedUnionType.TagUsage, + + class: TypeClass, + has_runtime_tag: bool, - /// Whether the union is an OPV type. Always `false` until layout resolved. - /// The actual OPV is not cached, but caching this bit of state means we avoid - /// repeatedly doing redundant checks to find that the union is not OPV! - has_one_possible_value: bool, - /// Like `has_one_possible_value`, but for a "noreturn" union (where all fields are noreturn). - has_no_possible_value: bool, - /// Whether the union is comptime-only. Always `false` until layout resolved. - comptime_only: bool, - /// Whether the union has runtime bits. Always `false` until layout resolved. - has_runtime_bits: bool, /// Alignment of the whole union. Always `.none` until layout resolved. alignment: Alignment, @@ -5970,8 +5933,6 @@ pub const SimpleType = enum(u32) { }; pub const SimpleValue = enum(u32) { - /// This is untyped `undefined`. - undefined = @intFromEnum(Index.undef), void = @intFromEnum(Index.void_value), /// This is untyped `null`. null = @intFromEnum(Index.null_value), @@ -7016,11 +6977,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { } }; }, - .type_enum_auto, - .type_enum_explicit, - .type_union, - => .{ .empty_enum_value = ty }, - else => unreachable, }; }, @@ -7914,11 +7870,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: }); }, - .empty_enum_value => |enum_or_union_ty| items.appendAssumeCapacity(.{ - .tag = .only_possible_value, - .data = @intFromEnum(enum_or_union_ty), - }), - .float => |float| { switch (float.ty) { .f16_type => items.appendAssumeCapacity(.{ @@ -8302,10 +8253,7 @@ pub fn getDeclaredStructType( .any_comptime_fields = ini.any_comptime_fields, .any_field_defaults = ini.any_field_defaults, .any_field_aligns = ini.any_field_aligns, - .has_one_possible_value = false, - .has_no_possible_value = false, - .comptime_only = false, - .has_runtime_bits = false, + .class = .no_possible_value, .alignment = .none, .want_layout = false, .want_defaults = false, @@ -8456,10 +8404,7 @@ pub fn getReifiedStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Pe .any_comptime_fields = ini.any_comptime_fields, .any_field_defaults = ini.any_field_defaults, .any_field_aligns = ini.any_field_aligns, - .has_one_possible_value = false, - .has_no_possible_value = false, - .comptime_only = false, - .has_runtime_bits = false, + .class = .no_possible_value, .alignment = .none, .want_layout = false, .want_defaults = false, @@ -8535,7 +8480,7 @@ pub fn getDeclaredUnionType( fields_len: u32, layout: std.builtin.Type.ContainerLayout, any_field_aligns: bool, - runtime_tag: LoadedUnionType.RuntimeTag, + tag_usage: LoadedUnionType.TagUsage, enum_tag_mode: BackingTypeMode, packed_backing_mode: BackingTypeMode, }, @@ -8617,11 +8562,9 @@ pub fn getDeclaredUnionType( .enum_tag_mode = ini.enum_tag_mode, .layout = if (is_extern) .@"extern" else .auto, .any_field_aligns = ini.any_field_aligns, - .runtime_tag = ini.runtime_tag, - .has_one_possible_value = false, - .has_no_possible_value = false, - .comptime_only = false, - .has_runtime_bits = false, + .tag_usage = ini.tag_usage, + .class = .no_possible_value, + .has_runtime_tag = false, .alignment = .none, .want_layout = false, }, @@ -8658,8 +8601,8 @@ pub fn getReifiedUnionType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Per fields_len: u32, layout: std.builtin.Type.ContainerLayout, any_field_aligns: bool, - runtime_tag: LoadedUnionType.RuntimeTag, - /// Explicitly specified enum tag type. `.none` if `runtime_tag != .tagged`. + tag_usage: LoadedUnionType.TagUsage, + /// Explicitly specified enum tag type. `.none` if `tag_usage != .tagged`. enum_tag_type: Index, /// Explicitly specified backing int type. `.none` if not packed or if backing type is inferred. packed_backing_int_type: Index, @@ -8745,11 +8688,9 @@ pub fn getReifiedUnionType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Per .enum_tag_mode = if (ini.enum_tag_type == .none) .auto else .explicit, .layout = if (is_extern) .@"extern" else .auto, .any_field_aligns = ini.any_field_aligns, - .runtime_tag = ini.runtime_tag, - .has_one_possible_value = false, - .has_no_possible_value = false, - .comptime_only = false, - .has_runtime_bits = false, + .tag_usage = ini.tag_usage, + .class = .no_possible_value, + .has_runtime_tag = false, .alignment = .none, .want_layout = false, }, @@ -12007,20 +11948,6 @@ pub fn funcTypeReturnType(ip: *const InternPool, ty: Index) Index { ]); } -pub fn isNoReturn(ip: *const InternPool, ty: Index) bool { - switch (ty) { - .noreturn_type => return true, - else => { - const unwrapped_ty = ty.unwrap(ip); - const ty_item = unwrapped_ty.getItem(ip); - return switch (ty_item.tag) { - .type_error_set => unwrapped_ty.getExtra(ip).view().items(.@"0")[ty_item.data + std.meta.fieldIndex(Tag.ErrorSet, "names_len").?] == 0, - else => false, - }; - }, - } -} - pub fn isUndef(ip: *const InternPool, val: Index) bool { return val == .undef or val.unwrap(ip).getTag(ip) == .undef; } @@ -12823,10 +12750,7 @@ pub fn resolveStructLayout( struct_type: Index, size: u32, alignment: Alignment, - has_no_possible_value: bool, - has_one_possible_value: bool, - comptime_only: bool, - has_runtime_bits: bool, + class: TypeClass, ) void { const unwrapped_index = struct_type.unwrap(ip); @@ -12840,10 +12764,7 @@ pub fn resolveStructLayout( extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "size").?] = size; const flags: *Tag.TypeStruct.Flags = @ptrCast(&extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "flags").?]); - flags.has_no_possible_value = has_no_possible_value; - flags.has_one_possible_value = has_one_possible_value; - flags.comptime_only = comptime_only; - flags.has_runtime_bits = has_runtime_bits; + flags.class = class; flags.alignment = alignment; } @@ -12856,13 +12777,11 @@ pub fn resolveUnionLayout( io: Io, union_type: Index, enum_tag_type: Index, + class: TypeClass, + has_runtime_tag: bool, size: u32, padding: u32, alignment: Alignment, - has_no_possible_value: bool, - has_one_possible_value: bool, - comptime_only: bool, - has_runtime_bits: bool, ) void { const unwrapped_index = union_type.unwrap(ip); @@ -12878,10 +12797,8 @@ pub fn resolveUnionLayout( extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnion, "size").?] = size; extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnion, "padding").?] = padding; const flags: *Tag.TypeUnion.Flags = @ptrCast(&extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnion, "flags").?]); - flags.has_no_possible_value = has_no_possible_value; - flags.has_one_possible_value = has_one_possible_value; - flags.comptime_only = comptime_only; - flags.has_runtime_bits = has_runtime_bits; + flags.class = class; + flags.has_runtime_tag = has_runtime_tag; flags.alignment = alignment; } diff --git a/src/Sema.zig b/src/Sema.zig index 60f04974372927d734327b71cef6118d53bc0797..cd6625fdaba233ed72cdbd31b9d79617dd40267d 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -178,8 +178,11 @@ const ComptimeAlloc = struct { fn newComptimeAlloc(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type, alignment: Alignment) !ComptimeAllocIndex { const pt = sema.pt; - // Explicit guard because this call mutates the InternPool so cannot be optimized out. - if (std.debug.runtime_safety) assert(ty.onePossibleValue(pt) catch @panic("") == null); + switch (ty.classify(pt.zcu)) { + .no_possible_value => unreachable, + .one_possible_value => unreachable, + else => {}, + } const idx = sema.comptime_allocs.items.len; try sema.comptime_allocs.append(sema.gpa, .{ @@ -1991,31 +1994,28 @@ fn analyzeBodyInner( break :blk .void_value; }, }; - if (sema.isNoReturn(air_ref)) { - // We're going to assume that the body itself is noreturn, so let's ensure that now - assert(block.instructions.items.len > 0); - assert(sema.isNoReturn(block.instructions.items[block.instructions.items.len - 1].toRef())); - break; - } + const is_inferred_alloc = if (air_ref.toIndex()) |air_inst| switch (sema.air_instructions.items(.tag)[@intFromEnum(air_inst)]) { + .inferred_alloc, .inferred_alloc_comptime => true, + else => false, + } else false; // We must resolve the layout of a type before creating a value of that type. Therefore, - // the layout of the type of `air_ref` must already be resolved. - check_type: { - if (air_ref.toIndex()) |air_inst| switch (sema.air_instructions.items(.tag)[@intFromEnum(air_inst)]) { - .inferred_alloc, .inferred_alloc_comptime => break :check_type, - else => {}, - }; - sema.typeOf(air_ref).assertHasLayout(zcu); - // If the type has an OPV, `air_ref` must be that OPV: there is no other interned value - // it could be, and it would be a bug for the value to not be comptime-known when it has - // an OPV. Behind a `std.debug.runtime_safety` check because `onePossibleValue` mutates - // the InternPool so cannot be optimized out. - if (std.debug.runtime_safety) { - if (try sema.typeOf(air_ref).onePossibleValue(pt)) |opv| { - assert(air_ref == Air.Inst.Ref.fromValue(opv)); - } - } - } + // the layout of the type of `air_ref` must already be resolved. The call to `classify` + // doubles as an assertion of this. + if (!is_inferred_alloc) switch (sema.typeOf(air_ref).classify(zcu)) { + .no_possible_value => { + // The instruction result was noreturn, which should mean that the body itself now + // ends with a noreturn instruction. Let's confirm that. + const last_inst = block.instructions.items[block.instructions.items.len - 1]; + const last_inst_ty = sema.typeOf(last_inst.toRef()); + assert(last_inst_ty.classify(zcu) == .no_possible_value); + break; + }, + .one_possible_value => assert(air_ref.toInterned() != null), // the value should be comptime-known + .partially_comptime => assert(air_ref.toInterned() != null), // the value should be comptime-known + .fully_comptime => assert(air_ref.toInterned() != null), // the value should be comptime-known + .runtime => {}, + }; map.putAssumeCapacity(inst, air_ref); i += 1; @@ -2287,11 +2287,12 @@ fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) ?Value { .inferred_alloc_comptime => unreachable, // assertion failure else => {}, } - // Assert that the type is not OPV -- if it was, the value would have been comptime-known. - // Explicit guard because this could add to the InternPool so cannot be optimized away. - if (std.debug.runtime_safety) { - const opv = sema.typeOf(inst).onePossibleValue(sema.pt) catch @panic("oom in assert"); - assert(opv == null); + switch (sema.typeOf(inst).classify(zcu)) { + .no_possible_value => unreachable, // values of this type do not exist + .one_possible_value => unreachable, // the value should be comptime-known + .partially_comptime => unreachable, // the value should be comptime-known + .fully_comptime => unreachable, // the value should be comptime-known + .runtime => {}, } return null; } @@ -4645,16 +4646,21 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr const elem_ty = operand_ty.childType(zcu); try sema.ensureLayoutResolved(elem_ty, src); - if (try elem_ty.onePossibleValue(pt) != null) { - // No need to validate the actual pointer value, we don't need it! - return; - } + const need_comptime = switch (elem_ty.classify(zcu)) { + .no_possible_value => return sema.fail(block, src, "cannot load {s} type '{f}'", .{ + if (elem_ty.zigTypeTag(zcu) == .@"opaque") "opaque" else "uninstantiable", + elem_ty.fmt(pt), + }), + .one_possible_value => return, // no need to validate the actual pointer value! + .runtime => false, + .partially_comptime, .fully_comptime => true, + }; if (sema.resolveValue(operand)) |val| { if (val.isUndef(zcu)) { return sema.fail(block, src, "cannot dereference undefined value", .{}); } - } else if (elem_ty.comptimeOnly(zcu)) { + } else if (need_comptime) { const msg = msg: { const msg = try sema.errMsg( src, @@ -4870,7 +4876,7 @@ fn storeToInferredAllocComptime( .is_const = iac.is_const, }, }); - if (try operand_ty.onePossibleValue(pt) != null or + if (operand_ty.classify(zcu) == .one_possible_value or (iac.is_const and !operand_val.canMutateComptimeVarState(zcu))) { iac.ptr = try pt.intern(.{ .ptr = .{ @@ -6672,7 +6678,7 @@ const CallArgsInfo = union(enum) { return sema.failWithNeededComptime(block, cai.argSrc(block, arg_index), null); } - if (sema.typeOf(uncoerced_arg).zigTypeTag(zcu) == .noreturn) { + if (sema.typeOf(uncoerced_arg).classify(zcu) == .no_possible_value) { // This terminates resolution of arguments. The caller should // propagate this. return uncoerced_arg; @@ -6928,7 +6934,7 @@ fn analyzeCall( arg.* = try args_info.analyzeArg(sema, block, arg_idx, param_ty, func_ty_info, callee, maybe_func_inst); const arg_ty = sema.typeOf(arg.*); - if (arg_ty.zigTypeTag(zcu) == .noreturn) { + if (arg_ty.classify(zcu) == .no_possible_value) { return arg.*; // terminate analysis here } @@ -7183,7 +7189,7 @@ fn analyzeCall( return sema.handleTailCall(block, call_src, runtime_func_ty, maybe_opv); } - if (ip.isNoReturn(resolved_ret_ty.toIntern())) { + if (resolved_ret_ty.isNoReturn(zcu)) { const want_check = c: { if (!block.wantSafety()) break :c false; if (func_val != null) break :c false; @@ -7989,16 +7995,16 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const enum_tag: Air.Inst.Ref = switch (operand_ty.zigTypeTag(zcu)) { .@"enum" => operand, .@"union" => blk: { - const tag_ty = operand_ty.unionTagType(zcu) orelse { + if (operand_ty.unionTagType(zcu) == null) { return sema.fail( block, operand_src, "untagged union '{f}' cannot be converted to integer", .{operand_ty.fmt(pt)}, ); - }; + } - break :blk try sema.unionToTag(block, tag_ty, operand, operand_src); + break :blk try sema.unionToTag(block, operand); }, else => { return sema.fail(block, operand_src, "expected enum or tagged union, found '{f}'", .{ @@ -10151,9 +10157,8 @@ fn analyzeSwitchBlock( const maybe_operand_opv = try operand_ty.onePossibleValue(pt); const init_cond: Air.Inst.Ref, const item_ty: Type = switch (operand_ty.zigTypeTag(zcu)) { .@"union" => tag: { - const tag_ty = operand_ty.unionTagType(zcu).?; - const tag_val = try sema.unionToTag(block, tag_ty, val, operand_src); - break :tag .{ tag_val, tag_ty }; + const tag_val = try sema.unionToTag(block, val); + break :tag .{ tag_val, sema.typeOf(tag_val) }; }, else => .{ if (maybe_operand_opv) |operand_opv| .fromValue(operand_opv) else val, @@ -10245,7 +10250,7 @@ fn analyzeSwitchBlock( .{ new_operand, .none }; const new_cond_ref = if (union_originally) - try sema.unionToTag(child_block, item_ty, new_val, src) + try sema.unionToTag(child_block, new_val) else new_val; @@ -12147,8 +12152,7 @@ fn analyzeSwitchTagCapture( .item_refs => |refs| if (refs.len == 1) return refs[0], .special => {}, } - const tag_ty = operand_ty.unionTagType(zcu).?; - return sema.unionToTag(case_block, tag_ty, operand_val, tag_capture_src); + return sema.unionToTag(case_block, operand_val); } fn analyzeSwitchPayloadCapture( @@ -15389,9 +15393,12 @@ fn analyzePtrArithmetic( const elem_ty: Type = .fromInterned(ptr_info.child); elem_ty.assertHasLayout(zcu); - if (elem_ty.abiSize(zcu) == 0) { - // Offset will be multiplied by zero, so result is the same as the base pointer. - return ptr; + switch (elem_ty.classify(zcu)) { + .no_possible_value, .one_possible_value => { + // Offset will be multiplied by zero, so result is the same as the base pointer. + return ptr; + }, + else => {}, } const new_ptr_ty = t: { @@ -15757,7 +15764,7 @@ fn analyzeCmpUnionTag( if (sema.resolveValue(coerced_tag)) |enum_val| { if (enum_val.isUndef(zcu)) return .undef_bool; const field_ty = union_ty.unionFieldType(enum_val, zcu).?; - if (field_ty.zigTypeTag(zcu) == .noreturn) { + if (field_ty.classify(zcu) == .no_possible_value) { return .bool_false; } } @@ -15934,39 +15941,22 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const ty = try sema.resolveType(block, operand_src, inst_data.operand); - switch (ty.zigTypeTag(zcu)) { - .@"fn", - .noreturn, - .undefined, - .null, - .@"opaque", - => return sema.fail(block, operand_src, "no size available for type '{f}'", .{ty.fmt(pt)}), - - .type, - .enum_literal, - .comptime_float, - .comptime_int, - .void, - => return .zero, - - .bool, - .int, - .float, - .pointer, - .array, - .@"struct", - .optional, - .error_union, - .error_set, - .@"enum", - .@"union", - .vector, - .frame, - .@"anyframe", - => {}, - } try sema.ensureLayoutResolved(ty, operand_src); - return .fromValue(try pt.intValue(.comptime_int, ty.abiSize(zcu))); + switch (ty.classify(zcu)) { + .no_possible_value, + => return sema.fail(block, operand_src, "no size available for uninstantiable type '{f}'", .{ty.fmt(pt)}), + + .partially_comptime, + .fully_comptime, + => return sema.fail(block, operand_src, "no size available for comptime-only type '{f}'", .{ty.fmt(pt)}), + + .one_possible_value => { + assert(ty.abiSize(zcu) == 0); + return .zero; + }, + + .runtime => return .fromValue(try pt.intValue(.comptime_int, ty.abiSize(zcu))), + } } fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -18631,9 +18621,9 @@ fn zirStructInit( const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index); const field_ty: Type = .fromInterned(zcu.typeToUnion(resolved_ty).?.field_types.get(ip)[field_index]); - if (field_ty.zigTypeTag(zcu) == .noreturn) { + if (field_ty.classify(zcu) == .no_possible_value) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{}); + const msg = try sema.errMsg(src, "cannot initialize union field with uninstantiable type '{f}'", .{field_ty.fmt(pt)}); errdefer msg.destroy(sema.gpa); try sema.addFieldErrNote(resolved_ty, field_index, msg, "field '{f}' declared here", .{ @@ -18648,7 +18638,13 @@ fn zirStructInit( const init_inst = try sema.coerce(block, field_ty, uncoerced_init_inst, field_src); if (resolved_ty.containerLayout(zcu) == .@"packed") { - return sema.bitCast(block, resolved_ty, init_inst, src, field_src); + const union_val = try sema.bitCast(block, resolved_ty, init_inst, src, field_src); + const result_val = try sema.coerce(block, result_ty, union_val, src); + if (is_ref) { + return sema.analyzeRef(block, src, result_val); + } else { + return result_val; + } } if (sema.resolveValue(init_inst)) |val| { @@ -18681,9 +18677,6 @@ fn zirStructInit( const base_ptr = try sema.optEuBasePtrInit(block, alloc, src); const field_ptr = try sema.unionFieldPtr(block, field_src, base_ptr, field_name, field_src, resolved_ty, true); try sema.storePtr(block, src, field_ptr, init_inst); - if (try tag_ty.onePossibleValue(pt) == null) { - _ = try block.addBinOp(.set_union_tag, base_ptr, .fromValue(tag_val)); - } return sema.makePtrConst(block, alloc); } @@ -19451,10 +19444,10 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const ty = try sema.resolveType(block, operand_src, inst_data.operand); + try sema.ensureLayoutResolved(ty, operand_src); if (ty.isNoReturn(zcu)) { return sema.fail(block, operand_src, "no align available for type '{f}'", .{ty.fmt(sema.pt)}); } - try sema.ensureLayoutResolved(ty, operand_src); return .fromValue(try pt.intValue(.comptime_int, ty.abiAlignment(zcu).toByteUnits().?)); } @@ -20447,10 +20440,10 @@ fn zirReifyUnion( .fields_len = @intCast(fields_len), .layout = layout, .any_field_aligns = any_field_aligns, - .runtime_tag = rt: { - if (explicit_tag_ty != null) break :rt .tagged; - if (layout == .auto and block.wantSafeTypes()) break :rt .safety; - break :rt .none; + .tag_usage = tag: { + if (explicit_tag_ty != null) break :tag .tagged; + if (layout == .auto and block.wantSafeTypes()) break :tag .safety; + break :tag .none; }, .enum_tag_type = if (explicit_tag_ty) |ty| ty.toIntern() else .none, .packed_backing_int_type = if (explicit_packed_backing_type) |ty| ty.toIntern() else .none, @@ -22608,7 +22601,7 @@ fn zirCmpxchg( const result_ty = try pt.optionalType(elem_ty.toIntern()); // special case zero bit types - if (try elem_ty.onePossibleValue(pt) != null) { + if (elem_ty.classify(zcu) == .one_possible_value) { return .fromValue(try pt.nullValue(result_ty)); } @@ -25514,8 +25507,9 @@ fn fieldPtrLoad( const pt = sema.pt; const zcu = pt.zcu; const object_ptr_ty = sema.typeOf(object_ptr); + assert(object_ptr_ty.zigTypeTag(zcu) == .pointer); const pointee_ty = object_ptr_ty.childType(zcu); - try sema.ensureLayoutResolved(pointee_ty, src); // MLUGG TODO + try sema.ensureLayoutResolved(pointee_ty, src); if (try pointee_ty.onePossibleValue(pt)) |opv| { const object: Air.Inst.Ref = .fromValue(opv); return fieldVal(sema, block, src, object, field_name, field_name_src); @@ -26477,9 +26471,9 @@ fn unionFieldPtr( }); const enum_field_index: u32 = @intCast(Type.fromInterned(union_obj.enum_tag_type).enumFieldIndex(field_name, zcu).?); - if (initializing and field_ty.zigTypeTag(zcu) == .noreturn) { + if (initializing and field_ty.classify(zcu) == .no_possible_value) { const msg = msg: { - const msg = try sema.errMsg(src, "cannot initialize 'noreturn' field of union", .{}); + const msg = try sema.errMsg(src, "cannot initialize union field with uninstantiable type '{f}'", .{field_ty.fmt(pt)}); errdefer msg.destroy(sema.gpa); try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{ @@ -26529,30 +26523,29 @@ fn unionFieldPtr( }, .@"packed", .@"extern" => {}, } - const field_ptr_val = try union_ptr_val.ptrField(field_index, pt); - return Air.internedToRef(field_ptr_val.toIntern()); + return .fromValue(try union_ptr_val.ptrField(field_index, pt)); } // If the union has a tag, we must either set or or safety check it depending on `initializing`. tag: { if (union_ty.containerLayout(zcu) != .auto) break :tag; const tag_ty: Type = .fromInterned(union_obj.enum_tag_type); - if (try tag_ty.onePossibleValue(pt) != null) break :tag; + if (tag_ty.classify(zcu) == .one_possible_value) break :tag; // There is a hypothetical non-trivial tag. We must set it even if not there at runtime, but // only emit a safety check if it's available at runtime (i.e. it's safety-tagged). const want_tag = try pt.enumValueFieldIndex(tag_ty, enum_field_index); if (initializing) { const set_tag_inst = try block.addBinOp(.set_union_tag, union_ptr, .fromValue(want_tag)); try sema.checkComptimeKnownStore(block, set_tag_inst, .unneeded); // `unneeded` since this isn't a "proper" store - } else if (block.wantSafety() and union_obj.runtime_tag != .none) { - // The tag exists at runtime (safety tag), so emit a safety check. + } else if (block.wantSafety() and union_obj.has_runtime_tag) { + // The tag exists at runtime (actual or safety tag), so emit a safety check. // TODO would it be better if get_union_tag supported pointers to unions? const union_val = try block.addTyOp(.load, union_ty, union_ptr); const active_tag = try block.addTyOp(.get_union_tag, tag_ty, union_val); try sema.addSafetyCheckInactiveUnionField(block, src, active_tag, .fromValue(want_tag)); } } - if (field_ty.zigTypeTag(zcu) == .noreturn) { + if (field_ty.classify(zcu) == .no_possible_value) { _ = try block.addNoOp(.unreach); return .unreachable_value; } @@ -26578,57 +26571,40 @@ fn unionFieldVal( const union_obj = zcu.typeToUnion(union_ty).?; const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src); const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); - const enum_field_index: u32 = @intCast(Type.fromInterned(union_obj.enum_tag_type).enumFieldIndex(field_name, zcu).?); + const enum_tag_ty: Type = .fromInterned(union_obj.enum_tag_type); if (sema.resolveValue(union_byval)) |union_val| { if (union_val.isUndef(zcu)) return pt.undefRef(field_ty); - - const un = ip.indexToKey(union_val.toIntern()).un; - const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_type), enum_field_index); - const tag_matches = un.tag == field_tag.toIntern(); switch (union_obj.layout) { .auto => { - if (tag_matches) { - return Air.internedToRef(un.val); - } else { - const msg = msg: { - const active_index = Type.fromInterned(union_obj.enum_tag_type).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?; - const active_field_name = Type.fromInterned(union_obj.enum_tag_type).enumFieldName(active_index, zcu); - const msg = try sema.errMsg(src, "access of union field '{f}' while field '{f}' is active", .{ - field_name.fmt(ip), active_field_name.fmt(ip), - }); - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, union_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); - } + const active_tag_val = union_val.unionTag(zcu).?; + const active_index = enum_tag_ty.enumTagFieldIndex(active_tag_val, zcu).?; + if (active_index == field_index) return .fromValue(union_val.unionPayload(zcu)); + return sema.fail(block, src, "access of union field '{f}' while field '{f}' is active", .{ + field_name.fmt(ip), enum_tag_ty.enumFieldName(active_index, zcu).fmt(ip), + }); }, - .@"extern" => if (tag_matches) { - // Fast path - no need to use bitcast logic. - return Air.internedToRef(un.val); - } else if (try sema.bitCastVal(union_val, field_ty, 0, 0, 0)) |field_val| { - return Air.internedToRef(field_val.toIntern()); + .@"extern" => if (try sema.bitCastVal(union_val, field_ty, 0, 0, 0)) |field_val| { + return .fromValue(field_val); + } else { + // Runtime-known due to a pointer-to-integer conversion. }, - .@"packed" => if (tag_matches) { - // Fast path - no need to use bitcast logic. - return Air.internedToRef(un.val); - } else if (try sema.bitCastVal(union_val, field_ty, 0, union_ty.bitSize(zcu), 0)) |field_val| { - return Air.internedToRef(field_val.toIntern()); + .@"packed" => { + const field_val = try sema.bitCastVal(union_val, field_ty, 0, union_ty.bitSize(zcu), 0) orelse { + unreachable; // `null` is only possible if the input value contains a pointer, which a packed union cannot. + }; + return .fromValue(field_val); }, } } - if (union_obj.layout == .auto and block.wantSafety() and - union_ty.unionTagTypeSafety(zcu) != null and union_obj.field_types.len > 1) - { - const wanted_tag_val = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_type), enum_field_index); - const wanted_tag = Air.internedToRef(wanted_tag_val.toIntern()); - const active_tag = try block.addTyOp(.get_union_tag, .fromInterned(union_obj.enum_tag_type), union_byval); - try sema.addSafetyCheckInactiveUnionField(block, src, active_tag, wanted_tag); + if (union_obj.layout == .auto and block.wantSafety() and union_obj.has_runtime_tag) { + const wanted_tag_val = try pt.enumValueFieldIndex(enum_tag_ty, field_index); + const active_tag = try block.addTyOp(.get_union_tag, enum_tag_ty, union_byval); + try sema.addSafetyCheckInactiveUnionField(block, src, active_tag, .fromValue(wanted_tag_val)); } - if (field_ty.zigTypeTag(zcu) == .noreturn) { + if (field_ty.classify(zcu) == .no_possible_value) { _ = try block.addNoOp(.unreach); return .unreachable_value; } @@ -27767,11 +27743,10 @@ fn coerceExtra( }; return Air.internedToRef((try pt.enumValueFieldIndex(dest_ty, @intCast(field_index))).toIntern()); }, - .@"union" => blk: { + .@"union" => if (inst_ty.unionTagType(zcu)) |enum_tag_ty| { // union to its own tag type - const union_tag_ty = inst_ty.unionTagType(zcu) orelse break :blk; - if (union_tag_ty.eql(dest_ty, zcu)) { - return sema.unionToTag(block, dest_ty, inst, inst_src); + if (enum_tag_ty.toIntern() == dest_ty.toIntern()) { + return sema.unionToTag(block, inst); } }, else => {}, @@ -27857,18 +27832,16 @@ fn coerceExtra( else => {}, } - const can_coerce_to = switch (dest_ty.zigTypeTag(zcu)) { - .noreturn, .@"opaque" => false, - else => true, + const dest_is_npv = switch (dest_ty.classify(zcu)) { + .no_possible_value => true, + .one_possible_value => if (inst == .undef) { + return .fromValue((try dest_ty.onePossibleValue(pt)).?); + } else false, + .runtime, .fully_comptime, .partially_comptime => if (inst == .undef) { + return .fromValue(try pt.undefValue(dest_ty)); + } else false, }; - if (can_coerce_to and inst == .undef) { - // undefined to anything. We do this after the big switch above so that - // special logic has a chance to run first, such as `*[N]T` to `[]T` which - // should initialize the length field of the slice. - return .fromValue(try dest_ty.onePossibleValue(pt) orelse try pt.undefValue(dest_ty)); - } - if (!opts.report_err) return error.NotCoercible; if (opts.is_ret and dest_ty.zigTypeTag(zcu) == .noreturn) { @@ -27890,8 +27863,8 @@ fn coerceExtra( const msg = try sema.typeMismatchErrMsg(inst_src, dest_ty, inst_ty); errdefer msg.destroy(sema.gpa); - if (!can_coerce_to) { - try sema.errNote(inst_src, msg, "cannot coerce to '{f}'", .{dest_ty.fmt(pt)}); + if (dest_is_npv) { + try sema.errNote(inst_src, msg, "cannot coerce to uninstantiable type '{f}'", .{dest_ty.fmt(pt)}); } // E!T to T @@ -29099,6 +29072,13 @@ fn storePtr2( }; const maybe_operand_val = sema.resolveValue(operand); + const comptime_only = switch (elem_ty.classify(zcu)) { + .no_possible_value => unreachable, // the coercion should have failed + .one_possible_value => return, // no actual store operation is necessary + .runtime => false, + .partially_comptime, .fully_comptime => true, + }; + const runtime_src = rs: { const ptr_val = try sema.resolveDefinedValue(block, ptr_src, ptr) orelse break :rs ptr_src; if (!sema.isComptimeMutablePtr(ptr_val)) break :rs ptr_src; @@ -29106,16 +29086,9 @@ fn storePtr2( return sema.storePtrVal(block, src, ptr_val, operand_val, elem_ty); }; - // We do this after the possible comptime store above, for the case of field_ptr stores - // to unions because we want the comptime tag to be set, even if the field type is void. - // MLUGG TODO: that's insane, the runtime and comptime sematics should be the same. just set the tag at the same damn time - if (try elem_ty.onePossibleValue(pt) != null) { - return; - } - // We're performing the store at runtime; as such, we need to make sure the pointee type // is not comptime-only. We can hit this case with a `@ptrFromInt` pointer. - if (elem_ty.comptimeOnly(zcu)) { + if (comptime_only) { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(src, "cannot store comptime-only type '{f}' at runtime", .{elem_ty.fmt(pt)}); errdefer msg.destroy(sema.gpa); @@ -29477,7 +29450,7 @@ fn coerceEnumToUnion( const enum_ty: Type = .fromInterned(union_obj.enum_tag_type); const enum_obj = ip.loadEnumType(enum_ty.toIntern()); - if (union_obj.runtime_tag != .tagged) return sema.failWithOwnedErrorMsg(block, msg: { + if (union_obj.tag_usage != .tagged) return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.typeMismatchErrMsg(inst_src, union_ty, inst_ty); errdefer msg.destroy(sema.gpa); try sema.errNote(union_ty_src, msg, "cannot coerce enum to untagged union", .{}); @@ -29495,31 +29468,35 @@ fn coerceEnumToUnion( const field_name = enum_obj.field_names.get(ip)[field_index]; const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); - if (field_ty.zigTypeTag(zcu) == .noreturn) { - const msg = msg: { - const msg = try sema.errMsg(inst_src, "cannot initialize 'noreturn' field of union", .{}); + switch (field_ty.classify(zcu)) { + .one_possible_value => return .fromValue(try pt.unionValue( + union_ty, + val, + (try field_ty.onePossibleValue(pt)).?, + )), + + .no_possible_value => return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(inst_src, "cannot initialize union field with uninstantiable type '{f}'", .{field_ty.fmt(pt)}); errdefer msg.destroy(sema.gpa); try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{ field_name.fmt(ip), }); try sema.addDeclaredHereNote(msg, union_ty); break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + }), + + else => return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(inst_src, "coercion from enum '{f}' to union '{f}' must initialize '{f}' field '{f}'", .{ + inst_ty.fmt(pt), union_ty.fmt(pt), + field_ty.fmt(pt), field_name.fmt(ip), + }); + errdefer msg.destroy(sema.gpa); + + try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{field_name.fmt(ip)}); + try sema.addDeclaredHereNote(msg, union_ty); + break :msg msg; + }), } - const opv = try field_ty.onePossibleValue(pt) orelse return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(inst_src, "coercion from enum '{f}' to union '{f}' must initialize '{f}' field '{f}'", .{ - inst_ty.fmt(pt), union_ty.fmt(pt), - field_ty.fmt(pt), field_name.fmt(ip), - }); - errdefer msg.destroy(sema.gpa); - - try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{field_name.fmt(ip)}); - try sema.addDeclaredHereNote(msg, union_ty); - break :msg msg; - }); - - return Air.internedToRef((try pt.unionValue(union_ty, val, opv)).toIntern()); } try sema.requireRuntimeBlock(block, inst_src, null); @@ -29536,32 +29513,14 @@ fn coerceEnumToUnion( return sema.failWithOwnedErrorMsg(block, msg); } - { - var msg: ?*Zcu.ErrorMsg = null; - errdefer if (msg) |some| some.destroy(sema.gpa); - - for (union_obj.field_types.get(ip), 0..) |field_ty, field_index| { - if (Type.fromInterned(field_ty).zigTypeTag(zcu) == .noreturn) { - const err_msg = msg orelse try sema.errMsg( - inst_src, - "runtime coercion from enum '{f}' to union '{f}' which has a 'noreturn' field", - .{ enum_ty.fmt(pt), union_ty.fmt(pt) }, - ); - msg = err_msg; - - try sema.addFieldErrNote(union_ty, field_index, err_msg, "'noreturn' field here", .{}); - } - } - if (msg) |some| { - msg = null; - try sema.addDeclaredHereNote(some, union_ty); - return sema.failWithOwnedErrorMsg(block, some); - } - } - - // If the union has all fields 0 bits, the union value is just the enum value. if (union_ty.unionHasAllZeroBitFieldTypes(zcu)) { - return block.addBitCast(union_ty, enum_tag); + if (try union_ty.onePossibleValue(pt)) |opv| { + // 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. + return .fromValue(opv); + } else { + // The union layout is just the tag, so we can bitcast the enum straight to the union. + return block.addBitCast(union_ty, enum_tag); + } } const msg = msg: { @@ -29575,9 +29534,15 @@ fn coerceEnumToUnion( for (0..union_obj.field_types.len) |field_index| { const field_name = enum_obj.field_names.get(ip)[field_index]; const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); - if (try field_ty.onePossibleValue(pt) != null) continue; - try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' has type '{f}'", .{ + const ty_description: []const u8 = switch (field_ty.classify(zcu)) { + .one_possible_value => continue, + .no_possible_value => "uninstantiable type", + else => "type", + }; + if (field_ty.classify(zcu) == .one_possible_value) continue; + try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' has {s} '{f}'", .{ field_name.fmt(ip), + ty_description, field_ty.fmt(pt), }); } @@ -30345,7 +30310,7 @@ fn resolveIsNonErrFromType( assert(ot == .error_union); const payload_ty = operand_ty.errorUnionPayload(zcu); - if (payload_ty.zigTypeTag(zcu) == .noreturn) { + if (payload_ty.classify(zcu) == .no_possible_value) { return .false; } @@ -31348,24 +31313,28 @@ fn wrapErrorUnionSet( } } -fn unionToTag( - sema: *Sema, - block: *Block, - enum_ty: Type, - un: Air.Inst.Ref, - un_src: LazySrcLoc, -) !Air.Inst.Ref { +/// Returns the enum tag value for the active tag of a tagged union value. +/// +/// Asserts that the type of `un` is a tagged union type. +fn unionToTag(sema: *Sema, block: *Block, un: Air.Inst.Ref) !Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - if (try enum_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); + const ip = &zcu.intern_pool; + const union_obj = ip.loadUnionType(sema.typeOf(un).toIntern()); + assert(union_obj.tag_usage == .tagged); if (sema.resolveValue(un)) |un_val| { - const tag_val = un_val.unionTag(zcu).?; - if (tag_val.isUndef(zcu)) - return try pt.undefRef(enum_ty); - return Air.internedToRef(tag_val.toIntern()); + return .fromValue(un_val.unionTag(zcu).?); } - try sema.requireRuntimeBlock(block, un_src, null); - return block.addTyOp(.get_union_tag, enum_ty, un); + const enum_tag_ty: Type = .fromInterned(union_obj.enum_tag_type); + if (!union_obj.has_runtime_tag) { + // This means that only one field is possible. + const field_index = for (union_obj.field_types.get(ip), 0..) |field_ty_ip, field_index| { + const field_ty: Type = .fromInterned(field_ty_ip); + if (field_ty.classify(zcu) != .no_possible_value) break field_index; + } else unreachable; + return .fromValue(try pt.enumValueFieldIndex(enum_tag_ty, @intCast(field_index))); + } + return block.addTyOp(.get_union_tag, enum_tag_ty, un); } const PeerResolveStrategy = enum { @@ -33491,15 +33460,6 @@ fn isNoReturn(sema: *Sema, ref: Air.Inst.Ref) bool { return sema.typeOf(ref).isNoReturn(sema.pt.zcu); } -/// Avoids crashing the compiler when asking if inferred allocations are known to be a certain zig type. -fn isKnownZigType(sema: *Sema, ref: Air.Inst.Ref, tag: std.builtin.TypeId) bool { - if (ref.toIndex()) |inst| switch (sema.air_instructions.items(.tag)[@intFromEnum(inst)]) { - .inferred_alloc, .inferred_alloc_comptime => return false, - else => {}, - }; - return sema.typeOf(ref).zigTypeTag(sema.pt.zcu) == tag; -} - pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void { const pt = sema.pt; if (!pt.zcu.comp.config.incremental) return; @@ -33744,7 +33704,6 @@ fn anyUndef(sema: *Sema, block: *Block, src: LazySrcLoc, val: Value) !bool { const zcu = pt.zcu; return switch (zcu.intern_pool.indexToKey(val.toIntern())) { .undef => true, - .simple_value => |v| v == .undefined, .slice => { // If the slice contents are runtime-known, reification will fail later on with a // specific error message. @@ -33898,7 +33857,6 @@ const ComptimeLoadResult = @import("Sema/comptime_ptr_access.zig").ComptimeLoadR const storeComptimePtr = @import("Sema/comptime_ptr_access.zig").storeComptimePtr; const ComptimeStoreResult = @import("Sema/comptime_ptr_access.zig").ComptimeStoreResult; -// MLUGG TODO: decide how to do the namespacing here pub const type_resolution = @import("Sema/type_resolution.zig"); pub const ensureLayoutResolved = type_resolution.ensureLayoutResolved; pub const ensureStructDefaultsResolved = type_resolution.ensureStructDefaultsResolved; @@ -34313,7 +34271,7 @@ fn zirUnionDecl( .fields_len = @intCast(union_decl.field_names.len), .layout = union_decl.kind.layout(), .any_field_aligns = union_decl.field_align_body_lens != null, - .runtime_tag = switch (union_decl.kind) { + .tag_usage = switch (union_decl.kind) { .auto => if (block.wantSafeTypes()) .safety else .none, .tagged_explicit, diff --git a/src/Sema/bitcast.zig b/src/Sema/bitcast.zig index f06528b6240f4766730353a6dc50d3b8e3c41607..43456c218ba08f987b444d35b8ef5dc8ad053cb7 100644 --- a/src/Sema/bitcast.zig +++ b/src/Sema/bitcast.zig @@ -267,7 +267,6 @@ const UnpackValueBits = struct { .int, .enum_tag, .simple_value, - .empty_enum_value, .float, .ptr, .opt, @@ -453,7 +452,6 @@ const UnpackValueBits = struct { // The only values here with runtime bits are `true` and `false. // These are both 1 bit, so will never need truncating. .simple_value => unreachable, - .empty_enum_value => unreachable, // zero-bit else => unreachable, // zero-bit or not primitives } } diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig index 1096c9cbe7d31cbd32958c0dcdfde5eae03b56bf..50f0f7e3156921fa42cae5e80768d067e245b941 100644 --- a/src/Sema/type_resolution.zig +++ b/src/Sema/type_resolution.zig @@ -72,7 +72,6 @@ pub fn ensureLayoutResolved(sema: *Sema, ty: Type, src: LazySrcLoc) SemaError!vo .error_union, .enum_literal, .enum_tag, - .empty_enum_value, .float, .ptr, .slice, @@ -249,10 +248,10 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { // Fields are okay. Now we need to resolve the struct's overall layout (size, field offsets, etc). var any_comptime_fields = false; - var comptime_only = false; - var one_possible_value = true; - var has_runtime_bits = false; var struct_align: Alignment = .@"1"; + var has_no_possible_value = false; + var has_runtime_state = false; + var has_comptime_state = false; // Unlike `struct_obj.field_aligns`, these are not `.none`. const resolved_field_aligns = try sema.arena.alloc(Alignment, struct_obj.field_names.len); for (resolved_field_aligns, 0..) |*align_out, field_idx| { @@ -264,22 +263,37 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { } break :a field_ty.defaultStructFieldAlignment(struct_obj.layout, zcu); }; - if (!struct_obj.field_is_comptime_bits.get(ip, field_idx)) { - // Non-`comptime` fields contribute to the struct's layout. - struct_align = struct_align.maxStrict(field_align); - if (field_ty.comptimeOnly(zcu)) comptime_only = true; - if (field_ty.hasRuntimeBits(zcu)) has_runtime_bits = true; - if (try field_ty.onePossibleValue(pt) == null) one_possible_value = false; - if (struct_obj.layout == .auto) { - struct_obj.field_runtime_order.get(ip)[field_idx] = @enumFromInt(field_idx); - } - } else { + align_out.* = field_align; + if (struct_obj.field_is_comptime_bits.get(ip, field_idx)) { assert(struct_obj.layout == .auto); // comptime fields not allowed in extern or packed structs struct_obj.field_runtime_order.get(ip)[field_idx] = .omitted; // comptime fields are not in the runtime order any_comptime_fields = true; + continue; // `comptime` fields do not contribute to the struct layout + } + struct_align = struct_align.maxStrict(field_align); + if (struct_obj.layout == .auto) { + struct_obj.field_runtime_order.get(ip)[field_idx] = @enumFromInt(field_idx); + } + switch (field_ty.classify(zcu)) { + .one_possible_value => {}, + .no_possible_value => has_no_possible_value = true, + .runtime => has_runtime_state = true, + .fully_comptime => has_comptime_state = true, + .partially_comptime => { + has_runtime_state = true; + has_comptime_state = true; + }, } - align_out.* = field_align; } + const class: Type.Class = class: { + if (has_no_possible_value) break :class .no_possible_value; + if (has_comptime_state) { + break :class if (has_runtime_state) .partially_comptime else .fully_comptime; + } else { + break :class if (has_runtime_state) .runtime else .one_possible_value; + } + }; + if (struct_obj.layout == .auto) { const runtime_order = struct_obj.field_runtime_order.get(ip); // This logic does not reorder fields; it only moves the omitted ones to the end so that logic @@ -327,21 +341,21 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { struct_obj.field_offsets.get(ip)[field_idx] = @truncate(offset); // truncate because the overflow is handled below cur_offset = offset + field_ty.abiSize(zcu); } - const struct_size = std.math.cast(u32, struct_align.forward(cur_offset)) orelse return sema.fail( - &block, - struct_ty.srcLoc(zcu), - "struct layout requires size {d}, this compiler implementation supports up to {d}", - .{ struct_align.forward(cur_offset), std.math.maxInt(u32) }, - ); + const struct_size: u32 = switch (class) { + .no_possible_value => 0, + else => std.math.cast(u32, struct_align.forward(cur_offset)) orelse return sema.fail( + &block, + struct_ty.srcLoc(zcu), + "struct layout requires size {d}, this compiler implementation supports up to {d}", + .{ struct_align.forward(cur_offset), std.math.maxInt(u32) }, + ), + }; ip.resolveStructLayout( io, struct_ty.toIntern(), struct_size, struct_align, - false, // MLUGG TODO XXX NPV - one_possible_value, - comptime_only, - has_runtime_bits, + class, ); if (any_comptime_fields and !struct_obj.is_reified) { @@ -758,9 +772,8 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { // Fields are okay. Now we need to resolve the union's overall layout (size, alignment, etc). var payload_align: Alignment = .@"1"; var payload_size: u64 = 0; - var comptime_only = false; - var has_runtime_bits = union_obj.runtime_tag != .none and enum_tag_ty.hasRuntimeBits(zcu); - var possible_values: enum { none, one, many } = .none; + var possible_tags: u32 = 0; + var payload_has_comptime_state = false; for (0..union_obj.field_types.len) |field_idx| { const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]); const field_align: Alignment = a: { @@ -772,21 +785,41 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { }; payload_align = payload_align.maxStrict(field_align); payload_size = @max(payload_size, field_ty.abiSize(zcu)); - if (field_ty.comptimeOnly(zcu)) comptime_only = true; - if (field_ty.hasRuntimeBits(zcu)) has_runtime_bits = true; - if (!field_ty.isNoReturn(zcu)) { - if (try field_ty.onePossibleValue(pt) != null) { - possible_values = .many; // this field alone has many possible values - } else switch (possible_values) { - .none => possible_values = .one, // there were none, now there is this field's OPV - .one => possible_values = .many, // there was one, now there are two - .many => {}, - } + + switch (field_ty.classify(zcu)) { + .no_possible_value => {}, // uninstantiable field has no effect + .one_possible_value, .runtime => { + possible_tags += 1; + }, + .partially_comptime, .fully_comptime => { + possible_tags += 1; + payload_has_comptime_state = true; + }, } } + // We only need a runtime tag if there are multiple possible active fields *and* the union is + // not going to be comptime-only. Even if there are still runtime bits in the payload, the tag + // does not require runtime bits in a comptime-only union, because it is impossible to get a + // pointer to a union's tag. + const has_runtime_tag = switch (possible_tags) { + 0, 1 => false, + else => union_obj.tag_usage != .none and !payload_has_comptime_state, + }; + + const class: Type.Class = class: { + if (possible_tags == 0) { + break :class .no_possible_value; + } + if (payload_has_comptime_state) { + break :class if (payload_size > 0) .partially_comptime else .fully_comptime; + } + const have_runtime_bits = has_runtime_tag or payload_size > 0; + break :class if (have_runtime_bits) .runtime else .one_possible_value; + }; + const size: u64, const padding: u64, const alignment: Alignment = layout: { - if (union_obj.runtime_tag == .none) { + if (!has_runtime_tag) { break :layout .{ payload_align.forward(payload_size), 0, payload_align }; } const tag_align = enum_tag_ty.abiAlignment(zcu); @@ -800,6 +833,11 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { break :layout .{ size, size - unpadded_size, alignment }; }; + if (class == .no_possible_value or class == .one_possible_value) { + assert(size == 0); + assert(padding == 0); + } + const casted_size = std.math.cast(u32, size) orelse return sema.fail( &block, union_ty.srcLoc(zcu), @@ -810,13 +848,11 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { io, union_ty.toIntern(), enum_tag_ty.toIntern(), + class, + has_runtime_tag, casted_size, @intCast(padding), // okay because padding is no greater than size alignment, - possible_values == .none, // MLUGG TODO: make sure queries use `LoadedUnionType.has_no_possible_value`! - possible_values == .one, - comptime_only, - has_runtime_bits, ); } fn failUnionFieldMismatch(sema: *Sema, block: *Block, union_field_names: []const InternPool.NullTerminatedString, enum_tag_ty: Type, enum_obj: *const InternPool.LoadedEnumType) CompileError { diff --git a/src/Type.zig b/src/Type.zig index 9cca3d104320edfc2f0fbf63cc64a30d7256fa0b..8b1c71cc9631a8085c4b8908ce09d1c9d69a057b 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -23,6 +23,240 @@ pub fn zigTypeTag(ty: Type, zcu: *const Zcu) std.builtin.TypeId { return zcu.intern_pool.zigTypeTag(ty.toIntern()); } +/// Every type is a member of exactly one "class" which determines: +/// * whether values of the type can exist at all +/// * whether values of the type can be runtime-knwon +/// * whether the type is considered comptime-only +/// * whether the type has runtime bits (nonzero ABI size) +pub const Class = enum(u3) { + /// Values of this type cannot exist because the type semantically has no values. Attempting to + /// create a value of this type (such as by coercing `undefined`) always emits a compile error. + /// + /// Not comptime-only. No runtime bits, i.e. ABI size is 0. + /// + /// Exhaustive list of no-possible-value ("NPV") types: + /// * `noreturn` + /// * `anyopaque`, and any `opaque` type + /// * `[n]T` where `n` is non-zero and `T` is NPV + /// * Any tuple where at least one non-`comptime` field has an NPV type + /// * Any enum whose backing type is `noreturn` + /// * Any struct where at least one non-`comptime` field has an NPV type + /// * Any union where every field has an NPV type (including unions with no fields) + /// * If the union would typically have a runtime tag, even if that tag would have runtime + /// bits, the union type is still NPV; the runtime tag is effectively omitted. + no_possible_value, + + /// Values of this type are always comptime-known because there is only one value inhabiting the + /// type. This matches the colloquial understanding of a "zero-bit type". + /// + /// Not comptime-only (although always comptime-known). No runtime bits, i.e. ABI size is 0. + /// + /// Exhaustive list of one-possible-value ("OPV") types: + /// * `void` + /// * `u0`, `i0` + /// * `[0]T` for any `T` + /// * `[n]T` where `T` is OPV + /// * `[n:s]T` where `T` is OPV + /// * `@Vector(0, T)` for any `T` + /// * `@Vector(n, T)` where `T` is OPV + /// * Any tuple where every non-`comptime` field has an OPV type (including tuples with no fields) + /// * Any enum whose backing type is OPV + /// * Any struct where every non-`comptime` field has an OPV type (including structs with no fields) + /// * Any union with no runtime tag where all fields have OPV + /// * Any union where one field has an OPV type, and either: + /// * All other fields have NPV types (in this case, if there would be a runtime tag, it is omitted) + /// * All other fields have NPV or OPV types, and the union has no runtime tag + one_possible_value, + + /// The type holds state (so it is neither NPV nor OPV), but contains no comptime-only state, so + /// values may be runtime-known. + /// + /// Not comptime-only. Has runtime bits, i.e. ABI size is non-zero. + /// + /// Most types which are typically used in Zig inhabit this class. For instance, all pointer + /// types, all integer types other than `u0` and `i0`, and most user-defined aggregates fall + /// into this category. + runtime, + + /// The type holds state (so it is neither NPV nor OPV). Some, but not all, of the contained + /// state is comptime-only. + /// + /// Comptime-only. Has runtime bits, i.e. ABI size is non-zero. + /// + /// Partially-comptime types arise from aggregates (`struct`s, `union`s, or tuples) which have + /// some fields with fully-comptime types (such as `comptime_int`) and some fields with runtime + /// types (such as `u8`). Because the user may acquire pointers to these fields, pointers to the + /// embedded runtime state must be valid, so backends are required to lower the runtime state + /// within the type. + /// + /// Note that logically-runtime state which cannot be directly referenced by the user (such as + /// the enum tag of a tagged union type, or the "populated" bit of an optional type) does not + /// cause a type to be partially-comptime. + partially_comptime, + + /// The type contains exclusively comptime-only state. + /// + /// Comptime-only. No runtime bits, i.e. ABI size is 0. + /// + /// Fully-comptime types arise from a handful of primitive fully-comptime types: + /// * `type` + /// * `comptime_int` + /// * `comptime_float` + /// * `@EnumLiteral()` + /// * `@TypeOf(null)` + /// * `@TypeOf(undefined)` + /// + /// Then, aggregates containing fully-comptime types may themselves be either fully-comptime or + /// partially-comptime; see the doc comment on `.partially_comptime` for details. + fully_comptime, +}; + +/// Returns the `Class` for the type `ty`. Asserts that the layout of `ty` is resolved. +pub fn classify(ty: Type, zcu: *const Zcu) Class { + ty.assertHasLayout(zcu); + const ip = &zcu.intern_pool; + return switch (ip.indexToKey(ty.toIntern())) { + .simple_type => |t| switch (t) { + .f16, + .f32, + .f64, + .f80, + .f128, + .usize, + .isize, + .c_char, + .c_short, + .c_ushort, + .c_int, + .c_uint, + .c_long, + .c_ulong, + .c_longlong, + .c_ulonglong, + .c_longdouble, + .bool, + .anyerror, + .adhoc_inferred_error_set, + => .runtime, + + .anyopaque => .no_possible_value, + + .type, + .comptime_int, + .comptime_float, + .enum_literal, + .null, + .undefined, + => .fully_comptime, + + .void => .one_possible_value, + .noreturn => .no_possible_value, + + .generic_poison => unreachable, + }, + + .error_set_type, + .inferred_error_set_type, + .ptr_type, + .anyframe_type, + => .runtime, + + .func_type => .fully_comptime, + + .opaque_type => .no_possible_value, + + .error_union_type => |eu| switch (Type.fromInterned(eu.payload_type).classify(zcu)) { + .no_possible_value, + .one_possible_value, + .runtime, + => .runtime, + + .partially_comptime => .partially_comptime, + // It may seem that this should be `.partially_comptime` due to the error set, however + // there is no way to take a pointer to the error set of an error union, so it does not + // actually necessitate runtime bits. + .fully_comptime => .fully_comptime, + }, + + .int_type => |int| switch (int.bits) { + 0 => .one_possible_value, + else => .runtime, + }, + .array_type => |arr| { + if (arr.len == 0 and arr.sentinel == .none) return .one_possible_value; + return Type.fromInterned(arr.child).classify(zcu); + }, + .vector_type => |vec| { + if (vec.len == 0) return .one_possible_value; + return Type.fromInterned(vec.child).classify(zcu); + }, + .opt_type => |child| switch (Type.fromInterned(child).classify(zcu)) { + .no_possible_value => .one_possible_value, + .one_possible_value => .runtime, + else => |class| class, + }, + .tuple_type => |tuple| { + var has_runtime_state = false; + var has_comptime_state = false; + for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, field_comptime_val| { + if (field_comptime_val != .none) continue; + switch (Type.fromInterned(field_ty).classify(zcu)) { + .no_possible_value => return .no_possible_value, + .one_possible_value => {}, + .runtime => has_runtime_state = true, + .fully_comptime => has_comptime_state = true, + .partially_comptime => { + has_runtime_state = true; + has_comptime_state = true; + }, + } + } + if (has_comptime_state) { + return if (has_runtime_state) .partially_comptime else .fully_comptime; + } else { + return if (has_runtime_state) .runtime else .one_possible_value; + } + }, + .struct_type => { + const struct_obj = ip.loadStructType(ty.toIntern()); + return switch (struct_obj.layout) { + .auto, .@"extern" => struct_obj.class, + .@"packed" => Type.fromInterned(struct_obj.packed_backing_int_type).classify(zcu), + }; + }, + .union_type => { + const union_obj = ip.loadUnionType(ty.toIntern()); + return switch (union_obj.layout) { + .auto, .@"extern" => union_obj.class, + .@"packed" => Type.fromInterned(union_obj.packed_backing_int_type).classify(zcu), + }; + }, + .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).classify(zcu), + + // values, not types + .undef, + .simple_value, + .variable, + .@"extern", + .func, + .int, + .err, + .error_union, + .enum_literal, + .enum_tag, + .float, + .ptr, + .slice, + .opt, + .aggregate, + .un, + .bitpack, + // memoization, not types + .memoized_call, + => unreachable, + }; +} + /// Asserts the type is resolved. pub fn isSelfComparable(ty: Type, zcu: *const Zcu, is_equality_cmp: bool) bool { return switch (ty.zigTypeTag(zcu)) { @@ -400,7 +634,6 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari .error_union, .enum_literal, .enum_tag, - .empty_enum_value, .float, .ptr, .slice, @@ -438,116 +671,9 @@ pub fn toValue(self: Type) Value { /// - an enum with an explicit tag type has the ABI size of the integer tag type, /// making it one-possible-value only if the integer tag type has 0 bits. pub fn hasRuntimeBits(ty: Type, zcu: *const Zcu) bool { - ty.assertHasLayout(zcu); - const ip = &zcu.intern_pool; - return switch (ip.indexToKey(ty.toIntern())) { - .int_type => |int_type| int_type.bits != 0, - .ptr_type => true, - .anyframe_type => true, - .array_type => |array_type| array_type.lenIncludingSentinel() > 0 and - Type.fromInterned(array_type.child).hasRuntimeBits(zcu), - .vector_type => |vector_type| vector_type.len > 0 and - Type.fromInterned(vector_type.child).hasRuntimeBits(zcu), - .opt_type => |child| !Type.fromInterned(child).isNoReturn(zcu), - - .error_union_type, - .error_set_type, - .inferred_error_set_type, - => true, - - // These are function *bodies*, not pointers. - // They return false here because they are comptime-only types. - // Special exceptions have to be made when emitting functions due to - // this returning false. - .func_type => false, - - .simple_type => |t| switch (t) { - .f16, - .f32, - .f64, - .f80, - .f128, - .usize, - .isize, - .c_char, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .c_longdouble, - .bool, - .anyerror, - .adhoc_inferred_error_set, - .anyopaque, - => true, - - .void, - .noreturn, - => false, - - // primitive comptime-only types - .type, - .comptime_int, - .comptime_float, - .null, - .undefined, - .enum_literal, - => false, - - .generic_poison => unreachable, - }, - .struct_type => { - const struct_obj = ip.loadStructType(ty.toIntern()); - switch (struct_obj.layout) { - .auto, .@"extern" => return struct_obj.has_runtime_bits, - .@"packed" => return Type.fromInterned(struct_obj.packed_backing_int_type).hasRuntimeBits(zcu), - } - }, - .union_type => { - const union_obj = ip.loadUnionType(ty.toIntern()); - switch (union_obj.layout) { - .auto, .@"extern" => return union_obj.has_runtime_bits, - .@"packed" => return Type.fromInterned(union_obj.packed_backing_int_type).hasRuntimeBits(zcu), - } - }, - .tuple_type => |tuple| { - for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| { - if (val != .none) continue; // comptime field - if (Type.fromInterned(field_ty).hasRuntimeBits(zcu)) return true; - } - return false; - }, - - // MLUGG TODO: this answer was already here but... does it actually make sense? - .opaque_type => true, - .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).hasRuntimeBits(zcu), - - // values, not types - .undef, - .simple_value, - .variable, - .@"extern", - .func, - .int, - .err, - .error_union, - .enum_literal, - .enum_tag, - .empty_enum_value, - .float, - .ptr, - .slice, - .opt, - .aggregate, - .un, - .bitpack, - // memoization, not types - .memoized_call, - => unreachable, + return switch (ty.classify(zcu)) { + .no_possible_value, .one_possible_value, .fully_comptime => false, + .runtime, .partially_comptime => true, }; } @@ -634,7 +760,6 @@ pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool { .error_union, .enum_literal, .enum_tag, - .empty_enum_value, .float, .ptr, .slice, @@ -681,8 +806,12 @@ pub fn isRuntimeFnOrHasRuntimeBits(ty: Type, zcu: *Zcu) bool { } } +/// Returns whether `ty` is NPV, meaning it is "like `noreturn`" in a sense. See doc comments on +/// `Class` for more details. +/// +/// Exactly equivalent to `ty.classify(zcu) == .no_possible_value`. pub fn isNoReturn(ty: Type, zcu: *const Zcu) bool { - return zcu.intern_pool.isNoReturn(ty.toIntern()); + return ty.classify(zcu) == .no_possible_value; } /// Never returns `none`. Asserts that all necessary type resolution is already done. @@ -705,7 +834,10 @@ pub fn ptrAddressSpace(ty: Type, zcu: *const Zcu) std.builtin.AddressSpace { }; } -/// Never returns `none`. Asserts that all necessary type resolution is already done. +/// Never returns `.none`. Asserts that the layout of `ty` is resolved. +/// +/// Unlike ABI size, a type's ABI alignment is not affected by its `Class`. In other words, any +/// alignment is possible regardless of the result of `ty.classify(zcu)`. pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment { const ip = &zcu.intern_pool; const target = zcu.getTarget(); @@ -842,7 +974,6 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment { .error_union, .enum_literal, .enum_tag, - .empty_enum_value, .float, .ptr, .slice, @@ -856,7 +987,11 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment { }; } -/// Asserts that `ty` is not an opaque type. +/// Asserts that `ty` is not an opaque type, and that the layout of `ty` is resolved. +/// +/// If the type is NPV, OPV, or fully-comptime (see `Class`), the return value of this function is +/// guaranteed to be zero. Otherwise (if the type is runtime or partially-comptime) the return value +/// is guaranteed to be non-zero. pub fn abiSize(ty: Type, zcu: *const Zcu) u64 { const ip = &zcu.intern_pool; const target = zcu.getTarget(); @@ -883,29 +1018,26 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 { }, .opt_type => |child_ty_ip| { const child_ty: Type = .fromInterned(child_ty_ip); - if (child_ty.isNoReturn(zcu)) return 0; - const child_size = child_ty.abiSize(zcu); - if (ty.optionalReprIsPayload(zcu)) return child_size; + if (child_ty.classify(zcu) == .no_possible_value) return 0; + if (ty.optionalReprIsPayload(zcu)) return child_ty.abiSize(zcu); // Optional types are represented as a struct with the child type as the first // field and a boolean as the second. Since the child type's abi alignment is // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal // to the child type's ABI alignment. - return child_size + child_ty.abiAlignment(zcu).toByteUnits().?; + return child_ty.abiSize(zcu) + child_ty.abiAlignment(zcu).toByteUnits().?; }, .error_set_type, .inferred_error_set_type => errorAbiSize(zcu), .error_union_type => |error_union| { const payload_ty: Type = .fromInterned(error_union.payload_type); - // This code needs to be kept in sync with the equivalent switch prong - // in abiAlignmentInner. - const code_size = errorAbiSize(zcu); - const code_align = errorAbiAlignment(zcu); - const payload_size = payload_ty.abiSize(zcu); - const payload_align = payload_ty.abiAlignment(zcu); + switch (payload_ty.classify(zcu)) { + .fully_comptime => return 0, // error set does not require runtime bits, see comment in `classify` + else => {}, + } // The layout will either be (code, payload, padding) or (payload, code, padding) // depending on which has larger alignment. So the overall size is just the code // and payload sizes added and padded to the larger alignment. - const big_align = code_align.maxStrict(payload_align); - return big_align.forward(payload_size + code_size); + const big_align: Alignment = .maxStrict(errorAbiAlignment(zcu), payload_ty.abiAlignment(zcu)); + return big_align.forward(errorAbiSize(zcu) + payload_ty.abiSize(zcu)); }, .func_type => 0, .simple_type => |t| switch (t) { @@ -946,7 +1078,12 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 { .anyopaque => unreachable, .generic_poison => unreachable, }, - .tuple_type => |tuple| ty.structFieldOffset(tuple.types.len, zcu), + .tuple_type => |tuple| switch (ty.classify(zcu)) { + // `structFieldOffset` is bogus on NPV tuples, because there may be some fields with + // non-zero size. + .no_possible_value => 0, + else => ty.structFieldOffset(tuple.types.len, zcu), + }, .struct_type => { const struct_obj = ip.loadStructType(ty.toIntern()); switch (struct_obj.layout) { @@ -975,7 +1112,6 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 { .error_union, .enum_literal, .enum_tag, - .empty_enum_value, .float, .ptr, .slice, @@ -1100,7 +1236,6 @@ pub fn bitSize(ty: Type, zcu: *const Zcu) u64 { .error_union, .enum_literal, .enum_tag, - .empty_enum_value, .float, .ptr, .slice, @@ -1327,8 +1462,7 @@ pub fn optionalChild(ty: Type, zcu: *const Zcu) Type { } } -/// Returns the tag type of a union, if the type is a union and it has a tag type. -/// Otherwise, returns `null`. +/// If `ty` is a tagged union, returns its tag type. Otherwise, returns `null`. pub fn unionTagType(ty: Type, zcu: *const Zcu) ?Type { assertHasLayout(ty, zcu); const ip = &zcu.intern_pool; @@ -1337,33 +1471,28 @@ pub fn unionTagType(ty: Type, zcu: *const Zcu) ?Type { else => return null, } const union_obj = ip.loadUnionType(ty.toIntern()); - return switch (union_obj.runtime_tag) { + return switch (union_obj.tag_usage) { .tagged => .fromInterned(union_obj.enum_tag_type), .none, .safety => null, }; } -/// Same as `unionTagType` but includes safety tag. -/// Codegen should use this version. -pub fn unionTagTypeSafety(ty: Type, zcu: *const Zcu) ?Type { +/// If the given union type contains a tag (including a safety tag) in its runtime layout, returns +/// its enum tag type. Otherwise, returns null. Asserts that `ty` is a union type. +/// +/// In general, codegen logic should call this function instead of `unionTagType`. +pub fn unionTagTypeRuntime(ty: Type, zcu: *const Zcu) ?Type { assertHasLayout(ty, zcu); - const ip = &zcu.intern_pool; - return switch (ip.indexToKey(ty.toIntern())) { - .union_type => { - const union_type = ip.loadUnionType(ty.toIntern()); - if (union_type.runtime_tag == .none) return null; - return Type.fromInterned(union_type.enum_tag_type); - }, - else => null, - }; + const union_type = zcu.intern_pool.loadUnionType(ty.toIntern()); + if (!union_type.has_runtime_tag) return null; + return .fromInterned(union_type.enum_tag_type); } -/// Asserts the type is a union; returns the tag type, even if the tag will -/// not be stored at runtime. +/// Asserts that `ty` is a union type, and returns its tag type, even if the tag will not be stored at runtime. pub fn unionTagTypeHypothetical(ty: Type, zcu: *const Zcu) Type { assertHasLayout(ty, zcu); - const union_obj = zcu.typeToUnion(ty).?; - return Type.fromInterned(union_obj.enum_tag_type); + const union_obj = zcu.intern_pool.loadUnionType(ty.toIntern()); + return .fromInterned(union_obj.enum_tag_type); } pub fn unionFieldType(ty: Type, enum_tag: Value, zcu: *const Zcu) ?Type { @@ -1573,12 +1702,12 @@ pub fn isUnsignedInt(ty: Type, zcu: *const Zcu) bool { }; } -/// Returns true for integers, enums, error sets, and packed structs. +/// Returns true for integers, enums, error sets, and packed structs/unions. /// If this function returns true, then intInfo() can be called on the type. pub fn isAbiInt(ty: Type, zcu: *const Zcu) bool { return switch (ty.zigTypeTag(zcu)) { .int, .@"enum", .error_set => true, - .@"struct" => ty.containerLayout(zcu) == .@"packed", + .@"struct", .@"union" => ty.containerLayout(zcu) == .@"packed", else => false, }; } @@ -1611,6 +1740,11 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType { assert(struct_obj.layout == .@"packed"); ty = .fromInterned(struct_obj.packed_backing_int_type); }, + .union_type => { + const union_obj = ip.loadUnionType(ty.toIntern()); + assert(union_obj.layout == .@"packed"); + ty = .fromInterned(union_obj.packed_backing_int_type); + }, .enum_type => ty = .fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type), .vector_type => |vector_type| ty = Type.fromInterned(vector_type.child), @@ -1629,7 +1763,6 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType { .func_type => unreachable, .simple_type => unreachable, // handled via Index enum tag above - .union_type => unreachable, .opaque_type => unreachable, // values, not types @@ -1643,7 +1776,6 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType { .error_union, .enum_literal, .enum_tag, - .empty_enum_value, .float, .ptr, .slice, @@ -1772,321 +1904,181 @@ pub fn isNumeric(ty: Type, zcu: *const Zcu) bool { }; } -/// MLUGG TODO: deal with our friends structs and unions -pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { +/// If the type's classification is `Class.one_possible_value` (see `classify`), returns the only +/// possible value for the type. Otherwise, returns `null`. +pub fn onePossibleValue(ty: Type, pt: Zcu.PerThread) !?Value { const zcu = pt.zcu; const comp = zcu.comp; const gpa = comp.gpa; const ip = &zcu.intern_pool; - assertHasLayout(starting_type, zcu); - var ty = starting_type; - while (true) switch (ty.toIntern()) { - .empty_tuple_type => return .empty_tuple, + assertHasLayout(ty, zcu); + return switch (ip.indexToKey(ty.toIntern())) { + .ptr_type, + .error_union_type, + .func_type, + .anyframe_type, + .error_set_type, + .inferred_error_set_type, + .opaque_type, + => null, - else => switch (ip.indexToKey(ty.toIntern())) { - .int_type => |int_type| { - if (int_type.bits == 0) { - return try pt.intValue(ty, 0); - } else { - return null; - } - }, + .simple_type => |t| switch (t) { + .f16, + .f32, + .f64, + .f80, + .f128, + .usize, + .isize, + .c_char, + .c_short, + .c_ushort, + .c_int, + .c_uint, + .c_long, + .c_ulong, + .c_longlong, + .c_ulonglong, + .c_longdouble, + .anyopaque, + .bool, + .type, + .anyerror, + .comptime_int, + .comptime_float, + .enum_literal, + .adhoc_inferred_error_set, + .null, + .undefined, + .noreturn, + => null, - .ptr_type, - .error_union_type, - .func_type, - .anyframe_type, - .error_set_type, - .inferred_error_set_type, - => return null, + .void => .void, - inline .array_type, .vector_type => |seq_type, seq_tag| { - const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none; - if (seq_type.len + @intFromBool(has_sentinel) == 0) { - return try pt.aggregateValue(ty, &.{}); - } - if (try Type.fromInterned(seq_type.child).onePossibleValue(pt)) |opv| { - return try pt.aggregateSplatValue(ty, opv); - } - return null; - }, - .opt_type => |child| { - if (child == .noreturn_type) { - return try pt.nullValue(ty); - } else { - return null; - } - }, + .generic_poison => unreachable, + }, - .simple_type => |t| switch (t) { - .f16, - .f32, - .f64, - .f80, - .f128, - .usize, - .isize, - .c_char, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .c_longdouble, - .anyopaque, - .bool, - .type, - .anyerror, - .comptime_int, - .comptime_float, - .enum_literal, - .adhoc_inferred_error_set, - => return null, + .int_type => |int_type| switch (int_type.bits) { + 0 => try pt.intValue(ty, 0), + else => null, + }, - .void => return .void, - .noreturn => return .@"unreachable", - .null => return .null, - .undefined => return .undef, - - .generic_poison => unreachable, - }, - .struct_type => { - const struct_obj = ip.loadStructType(ty.toIntern()); - if (struct_obj.layout == .@"packed") { + inline .array_type, .vector_type => |seq_type, seq_tag| { + const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none; + if (seq_type.len + @intFromBool(has_sentinel) == 0) { + return try pt.aggregateValue(ty, &.{}); + } + if (try Type.fromInterned(seq_type.child).onePossibleValue(pt)) |opv| { + return try pt.aggregateSplatValue(ty, opv); + } + return null; + }, + .opt_type => |child| switch (Type.fromInterned(child).classify(zcu)) { + .no_possible_value => try pt.nullValue(ty), + else => null, + }, + .tuple_type => |tuple| { + // Check *whether* the OPV exists first, because constructing it is a little more expensive. + if (ty.classify(zcu) != .one_possible_value) return null; + const field_vals = try zcu.gpa.dupe(InternPool.Index, tuple.values.get(ip)); + defer zcu.gpa.free(field_vals); + for (field_vals, tuple.types.get(ip)) |*field_val, field_ty_ip| { + if (field_val.* != .none) continue; // comptime field value + const field_ty: Type = .fromInterned(field_ty_ip); + field_val.* = (try field_ty.onePossibleValue(pt)).?.toIntern(); + } + return try pt.aggregateValue(ty, field_vals); + }, + .struct_type => { + const struct_obj = ip.loadStructType(ty.toIntern()); + switch (struct_obj.layout) { + .auto, .@"extern" => {}, + .@"packed" => { const backing_ty: Type = .fromInterned(struct_obj.packed_backing_int_type); const backing_val = try backing_ty.onePossibleValue(pt) orelse return null; return try pt.bitpackValue(ty, backing_val); - } else { - if (!struct_obj.has_one_possible_value) return null; + }, + } + // Type resolution already figured out whether there is an OPV, but if there is, it's + // our job to compute it. + if (struct_obj.class != .one_possible_value) return null; + const field_vals = try gpa.alloc(InternPool.Index, struct_obj.field_types.len); + defer gpa.free(field_vals); + for (field_vals, 0..) |*field_val, i_usize| { + const i: u32 = @intCast(i_usize); + if (struct_obj.field_is_comptime_bits.get(ip, i)) { + field_val.* = struct_obj.field_defaults.get(ip)[i]; + assert(field_val.* != .none); + continue; } - // There is an OPV. - const field_vals = try gpa.alloc(InternPool.Index, struct_obj.field_types.len); - defer gpa.free(field_vals); - for (field_vals, 0..) |*field_val, i_usize| { - const i: u32 = @intCast(i_usize); - if (struct_obj.field_is_comptime_bits.get(ip, i)) { - field_val.* = struct_obj.field_defaults.get(ip)[i]; - assert(field_val.* != .none); - continue; - } - const field_ty = Type.fromInterned(struct_obj.field_types.get(ip)[i]); - field_val.* = (try field_ty.onePossibleValue(pt)).?.toIntern(); - } - - // In this case the struct has no runtime-known fields and - // therefore has one possible value. - return try pt.aggregateValue(ty, field_vals); - }, - - .tuple_type => |tuple| { - if (tuple.types.len == 0) { - return try pt.aggregateValue(ty, &.{}); - } - - const field_vals = try zcu.gpa.alloc( - InternPool.Index, - tuple.types.len, - ); - defer zcu.gpa.free(field_vals); - for ( - field_vals, - tuple.types.get(ip), - tuple.values.get(ip), - ) |*field_val, field_ty, field_comptime_val| { - if (field_comptime_val != .none) { - field_val.* = field_comptime_val; - continue; - } - if (try Type.fromInterned(field_ty).onePossibleValue(pt)) |opv| { - field_val.* = opv.toIntern(); - } else return null; - } - - return try pt.aggregateValue(ty, field_vals); - }, - - .union_type => { - const union_obj = ip.loadUnionType(ty.toIntern()); - if (union_obj.layout == .@"packed") { - const backing_ty: Type = .fromInterned(union_obj.packed_backing_int_type); - const backing_val = try backing_ty.onePossibleValue(pt) orelse return null; - return try pt.bitpackValue(ty, backing_val); - } - // MLUGG TODO: is this nonsensical or what!!!!!! - const tag_val = (try Type.fromInterned(union_obj.enum_tag_type).onePossibleValue(pt)) orelse - return null; - if (union_obj.field_types.len == 0) { - const only = try pt.intern(.{ .empty_enum_value = ty.toIntern() }); - return .fromInterned(only); - } - const only_field_ty = union_obj.field_types.get(ip)[0]; - const val_val = (try Type.fromInterned(only_field_ty).onePossibleValue(pt)) orelse - return null; - const only = try pt.internUnion(.{ - .ty = ty.toIntern(), - .tag = tag_val.toIntern(), - .val = val_val.toIntern(), - }); - return .fromInterned(only); - }, - .opaque_type => return null, - .enum_type => { - const enum_obj = ip.loadEnumType(ty.toIntern()); - if (enum_obj.nonexhaustive) { - const int_opv = try Type.fromInterned(enum_obj.int_tag_type).onePossibleValue(pt) orelse return null; - return .fromInterned(try pt.intern(.{ .enum_tag = .{ - .ty = ty.toIntern(), - .int = int_opv.toIntern(), - } })); - } - // MLUGG TODO: this is to preserve existing semantics, i REALLY don't fuck with it... - if (enum_obj.int_tag_type == .comptime_int_type) { - return switch (enum_obj.field_names.len) { - 0 => .fromInterned(try pt.intern(.{ .empty_enum_value = ty.toIntern() })), - 1 => try pt.enumValueFieldIndex(ty, 0), - else => null, - }; - } - const int_tag_opv = try Type.fromInterned(enum_obj.int_tag_type).onePossibleValue(pt) orelse return null; - if (enum_obj.field_names.len == 0) { - return .fromInterned(try pt.intern(.{ .empty_enum_value = ty.toIntern() })); + const field_ty: Type = .fromInterned(struct_obj.field_types.get(ip)[i]); + field_val.* = (try field_ty.onePossibleValue(pt)).?.toIntern(); + } + return try pt.aggregateValue(ty, field_vals); + }, + .union_type => { + const union_obj = ip.loadUnionType(ty.toIntern()); + if (union_obj.layout == .@"packed") { + const backing_ty: Type = .fromInterned(union_obj.packed_backing_int_type); + const backing_val = try backing_ty.onePossibleValue(pt) orelse return null; + return try pt.bitpackValue(ty, backing_val); + } + // Type resolution already figured out whether there is an OPV, but if there is, it's + // our job to compute it. + if (union_obj.class != .one_possible_value) return null; + // The OPV comes from exactly one field whose type is OPV, while all others are NPV. + for (union_obj.field_types.get(ip), 0..) |field_ty_ip, field_index| { + const field_ty: Type = .fromInterned(field_ty_ip); + switch (field_ty.classify(zcu)) { + .no_possible_value => continue, + .one_possible_value => {}, + else => unreachable, } - return .fromInterned(try pt.intern(.{ .enum_tag = .{ - .ty = ty.toIntern(), - .int = int_tag_opv.toIntern(), - } })); - }, - - // values, not types - .undef, - .simple_value, - .variable, - .@"extern", - .func, - .int, - .err, - .error_union, - .enum_literal, - .enum_tag, - .empty_enum_value, - .float, - .ptr, - .slice, - .opt, - .aggregate, - .un, - .bitpack, - // memoization, not types - .memoized_call, - => unreachable, + // This field is the one! + const enum_tag_ty: Type = .fromInterned(union_obj.enum_tag_type); + const tag_val = try pt.enumValueFieldIndex(enum_tag_ty, @intCast(field_index)); + const payload_val = (try field_ty.onePossibleValue(pt)).?; + return try pt.unionValue(ty, tag_val, payload_val); + } else unreachable; }, + .enum_type => if (try ty.intTagType(zcu).onePossibleValue(pt)) |int_tag_opv| { + return .fromInterned(try pt.intern(.{ .enum_tag = .{ + .ty = ty.toIntern(), + .int = int_tag_opv.toIntern(), + } })); + } else null, + + // values, not types + .undef, + .simple_value, + .variable, + .@"extern", + .func, + .int, + .err, + .error_union, + .enum_literal, + .enum_tag, + .float, + .ptr, + .slice, + .opt, + .aggregate, + .un, + .bitpack, + // memoization, not types + .memoized_call, + => unreachable, }; } /// Asserts that `ty` has its layout resolved. `generic_poison` will return `false`. pub fn comptimeOnly(ty: Type, zcu: *const Zcu) bool { - const ip = &zcu.intern_pool; - return switch (ip.indexToKey(ty.toIntern())) { - .array_type => |array_type| return Type.fromInterned(array_type.child).comptimeOnly(zcu), - .vector_type => |vector_type| return Type.fromInterned(vector_type.child).comptimeOnly(zcu), - .opt_type => |child| return Type.fromInterned(child).comptimeOnly(zcu), - .error_union_type => |error_union_type| return Type.fromInterned(error_union_type.payload_type).comptimeOnly(zcu), - .enum_type => return Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).comptimeOnly(zcu), - - .int_type, - .ptr_type, - .anyframe_type, - .error_set_type, - .inferred_error_set_type, - .opaque_type, - => false, - - // These are function bodies, not function pointers. - .func_type => true, - - .simple_type => |t| switch (t) { - .f16, - .f32, - .f64, - .f80, - .f128, - .usize, - .isize, - .c_char, - .c_short, - .c_ushort, - .c_int, - .c_uint, - .c_long, - .c_ulong, - .c_longlong, - .c_ulonglong, - .c_longdouble, - .anyopaque, - .bool, - .void, - .anyerror, - .adhoc_inferred_error_set, - .noreturn, - .generic_poison, - => false, - - .type, - .comptime_int, - .comptime_float, - .null, - .undefined, - .enum_literal, - => true, - }, - .struct_type => { - const struct_obj = ip.loadStructType(ty.toIntern()); - return switch (struct_obj.layout) { - .@"packed" => false, - .auto, .@"extern" => struct_obj.comptime_only, - }; - }, - .union_type => { - const union_obj = ip.loadUnionType(ty.toIntern()); - return switch (union_obj.layout) { - .@"packed" => false, - .auto, .@"extern" => union_obj.comptime_only, - }; - }, - .tuple_type => |tuple| { - for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| { - if (val != .none) continue; - if (!Type.fromInterned(field_ty).comptimeOnly(zcu)) continue; - return true; - } - return false; - }, - - // values, not types - .undef, - .simple_value, - .variable, - .@"extern", - .func, - .int, - .err, - .error_union, - .enum_literal, - .enum_tag, - .empty_enum_value, - .float, - .ptr, - .slice, - .opt, - .aggregate, - .un, - .bitpack, - // memoization, not types - .memoized_call, - => unreachable, + if (ty.toIntern() == .generic_poison_type) return false; + if (ty.zigTypeTag(zcu) == .error_union and ty.errorUnionPayload(zcu).toIntern() == .generic_poison_type) return false; + return switch (ty.classify(zcu)) { + .no_possible_value, .one_possible_value, .runtime => false, + .partially_comptime, .fully_comptime => true, }; } @@ -2286,8 +2278,8 @@ pub fn enumFieldIndex(ty: Type, field_name: InternPool.NullTerminatedString, zcu return enum_type.nameIndex(ip, field_name); } -/// Asserts `ty` is an enum. `enum_tag` can either be `enum_field_index` or -/// an integer which represents the enum value. Returns the field index in +/// Asserts `ty` is an enum. `enum_tag` can either be the actual enum tag value +/// or an integer which represents the enum value. Returns the field index in /// declaration order, or `null` if `enum_tag` does not match any field. pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, zcu: *const Zcu) ?u32 { assertHasLayout(ty, zcu); @@ -2327,7 +2319,7 @@ pub fn structFieldCount(ty: Type, zcu: *const Zcu) u32 { } } -/// Returns the field type. Supports structs and unions. +/// Returns the field type. Supports tuples, structs, and unions. pub fn fieldType(ty: Type, index: usize, zcu: *const Zcu) Type { const ip = &zcu.intern_pool; const types = switch (ip.indexToKey(ty.toIntern())) { @@ -2493,7 +2485,7 @@ pub fn structFieldOffset(ty: Type, index: usize, zcu: *const Zcu) u64 { for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| { if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(zcu)) { // comptime field - if (i == index) return offset; + if (i == index) return 0; continue; } @@ -2509,8 +2501,7 @@ pub fn structFieldOffset(ty: Type, index: usize, zcu: *const Zcu) u64 { .union_type => { const union_type = ip.loadUnionType(ty.toIntern()); - if (union_type.runtime_tag == .none) - return 0; + if (!union_type.has_runtime_tag) return 0; const layout = Type.getUnionLayout(union_type, zcu); if (layout.tag_align.compare(.gte, layout.payload_align)) { // {Tag, Payload} @@ -2746,7 +2737,7 @@ pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) } payload_align = payload_align.max(field_align); } - if (loaded_union.runtime_tag == .none or + if (!loaded_union.has_runtime_tag or !Type.fromInterned(loaded_union.enum_tag_type).hasRuntimeBits(zcu)) { return .{ @@ -2872,11 +2863,19 @@ pub fn containerTypeName(ty: Type, ip: *const InternPool) InternPool.NullTermina } /// Returns `true` if a value of this type is always `null`. -/// Returns `false` if a value of this type is neve `null`. +/// Returns `false` if a value of this type is never `null`. /// Returns `null` otherwise. pub fn isNullFromType(ty: Type, zcu: *const Zcu) ?bool { if (ty.zigTypeTag(zcu) != .optional and !ty.isCPtr(zcu)) return false; - if (ty.optionalChild(zcu).isNoReturn(zcu)) return true; // `?noreturn` is always null + const payload_ty = ty.optionalChild(zcu); + if (payload_ty.classify(zcu) == .no_possible_value) return true; // `?noreturn` etc + + // Although it has runtime bits, `?error{}` is always null. MLUGG TODO: think for a bit... + switch (zcu.intern_pool.indexToKey(payload_ty.toIntern())) { + .error_set_type => |error_set| if (error_set.names.len == 0) return true, + else => {}, + } + return null; } @@ -3096,7 +3095,6 @@ pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void { .error_union, .enum_literal, .enum_tag, - .empty_enum_value, .float, .ptr, .slice, @@ -3175,7 +3173,6 @@ fn collectSubtypes(ty: Type, pt: Zcu.PerThread, visited: *std.AutoArrayHashMapUn .error_union, .enum_literal, .enum_tag, - .empty_enum_value, .float, .ptr, .slice, diff --git a/src/Value.zig b/src/Value.zig index 774a6758ceff8d82fc579f580b33de17ad4fef75..d158aa558c1c63a5cab26832774270680a61e5e7 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -348,7 +348,7 @@ pub fn writeToMemory(val: Value, pt: Zcu.PerThread, buffer: []u8) error{ } else { const backing_ty = try ty.externUnionBackingType(pt); const byte_count: usize = @intCast(backing_ty.abiSize(zcu)); - return writeToMemory(val.unionValue(zcu), pt, buffer[0..byte_count]); + return writeToMemory(val.unionPayload(zcu), pt, buffer[0..byte_count]); } }, .@"packed" => { @@ -746,7 +746,6 @@ pub fn compareScalar( /// Returns `false` if the value or any vector element is undefined. /// /// Note that `!compareAllWithZero(.eq, ...) != compareAllWithZero(.neq, ...)` -/// TODO MLUGG: lowkey wanna delete this pub fn compareAllWithZero(lhs: Value, op: std.math.CompareOperator, zcu: *Zcu) bool { return switch (zcu.intern_pool.indexToKey(lhs.toIntern())) { .float => |float| switch (float.storage) { @@ -919,7 +918,7 @@ pub fn unionTag(val: Value, zcu: *Zcu) ?Value { }; } -pub fn unionValue(val: Value, zcu: *Zcu) Value { +pub fn unionPayload(val: Value, zcu: *Zcu) Value { return switch (zcu.intern_pool.indexToKey(val.toIntern())) { .un => |un| Value.fromInterned(un.val), else => unreachable, @@ -2442,7 +2441,7 @@ pub fn interpret(val: Value, comptime T: type, pt: Zcu.PerThread) error{ OutOfMe inline else => |tag_comptime| @unionInit( T, @tagName(tag_comptime), - try val.unionValue(zcu).interpret(@FieldType(T, @tagName(tag_comptime)), pt), + try val.unionPayload(zcu).interpret(@FieldType(T, @tagName(tag_comptime)), pt), ), }; }, diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 186d6147d13622463f56d708f07a62d8b0e128c2..46e275045ac39d580acc8bf33dd45e671d19d39f 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -3825,9 +3825,7 @@ pub fn enumValueFieldIndex(pt: Zcu.PerThread, ty: Type, field_index: u32) Alloca pub fn undefValue(pt: Zcu.PerThread, ty: Type) Allocator.Error!Value { if (std.debug.runtime_safety) { - if (try ty.onePossibleValue(pt)) |opv| { - assert(opv.isUndef(pt.zcu)); - } + assert(ty.classify(pt.zcu) != .one_possible_value); } return .fromInterned(try pt.intern(.{ .undef = ty.toIntern() })); } @@ -3909,10 +3907,7 @@ pub fn aggregateValue(pt: Zcu.PerThread, ty: Type, elems: []const InternPool.Ind for (elems) |elem| { if (!Value.fromInterned(elem).isUndef(pt.zcu)) break; } else if (elems.len > 0) { - // All undef, so return an undef struct. However, don't use `undefValue`, because its - // non-OPV assertion can loop on `[1]@TypeOf(undefined)`: that type has an OPV of - // `.{undefined}`, which here we normalize to `undefined`. - return .fromInterned(try pt.intern(.{ .undef = ty.toIntern() })); + return pt.undefValue(ty); } return .fromInterned(try pt.intern(.{ .aggregate = .{ .ty = ty.toIntern(), diff --git a/src/codegen.zig b/src/codegen.zig index 9edb90fb51056d9ad56f913982b001ff8750e52b..45b70dee2ac19600117a0a08eec0087b234c7013 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -343,7 +343,6 @@ pub fn generateSymbol( .undef => unreachable, // handled above .simple_value => |simple_value| switch (simple_value) { - .undefined => unreachable, // non-runtime value .void => unreachable, // non-runtime value .null => unreachable, // non-runtime value .@"unreachable" => unreachable, // non-runtime value @@ -357,7 +356,6 @@ pub fn generateSymbol( .@"extern", .func, .enum_literal, - .empty_enum_value, => unreachable, // non-runtime values .int => { const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow; diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig index f9ff7874770ed1bd1b995a3689a89242c7211898..a95faca765385b3b4b879b0cf5b0e7885adf4e49 100644 --- a/src/codegen/aarch64/Select.zig +++ b/src/codegen/aarch64/Select.zig @@ -10588,7 +10588,6 @@ pub const Value = struct { .error_union, .enum_literal, .enum_tag, - .empty_enum_value, .float, .ptr, .slice, @@ -10711,7 +10710,6 @@ pub const Value = struct { .inferred_error_set_type, .enum_literal, - .empty_enum_value, .memoized_call, => unreachable, // not a runtime value .undef => break :free try isel.emit(if (mat.ra.isVector()) .movi(switch (size) { @@ -10732,7 +10730,7 @@ pub const Value = struct { } }), }), .simple_value => |simple_value| switch (simple_value) { - .undefined, .void, .null, .@"unreachable" => unreachable, + .void, .null, .@"unreachable" => unreachable, .true => continue :constant_key .{ .int = .{ .ty = .bool_type, .storage = .{ .u64 = 1 }, @@ -11408,7 +11406,6 @@ fn writeKeyToMemory(isel: *Select, constant_key: InternPool.Key, buffer: []u8) e .inferred_error_set_type, .enum_literal, - .empty_enum_value, .memoized_call, => unreachable, // not a runtime value .err => |err| { @@ -12085,7 +12082,7 @@ pub const CallAbiIterator = struct { const zcu = isel.pt.zcu; const ip = &zcu.intern_pool; - if (ty.isNoReturn(zcu) or !ty.hasRuntimeBitsIgnoreComptime(zcu)) return null; + if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) return null; try isel.values.ensureUnusedCapacity(zcu.gpa, Value.max_parts); const wip_vi = isel.initValue(ty); type_key: switch (ip.indexToKey(ty.toIntern())) { @@ -12326,7 +12323,6 @@ pub const CallAbiIterator = struct { .error_union, .enum_literal, .enum_tag, - .empty_enum_value, .float, .ptr, .slice, diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 69c4e91d999c4340e0fe18f299ba88787052a66a..f0df1aa1c0d0f072944a1f6d6dbd2bfc5f462f75 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1040,7 +1040,6 @@ pub const DeclGen = struct { .undef => unreachable, // handled above .simple_value => |simple_value| switch (simple_value) { // non-runtime values - .undefined => unreachable, .void => unreachable, .null => unreachable, .@"unreachable" => unreachable, @@ -1052,7 +1051,6 @@ pub const DeclGen = struct { .@"extern", .func, .enum_literal, - .empty_enum_value, => unreachable, // non-runtime values .int => |int| switch (int.storage) { .u64, .i64, .big_int => try w.print("{f}", .{try dg.fmtIntLiteralDec(val, location)}), @@ -1756,7 +1754,6 @@ pub const DeclGen = struct { .error_union, .enum_literal, .enum_tag, - .empty_enum_value, .float, .ptr, .slice, @@ -5848,7 +5845,7 @@ fn fieldLocation( .auto, .@"extern" => { const field_ty: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) - return if (loaded_union.hasTag(ip) and !container_ty.unionHasAllZeroBitFieldTypes(zcu)) + return if (loaded_union.has_runtime_tag and !container_ty.unionHasAllZeroBitFieldTypes(zcu)) .{ .field = .{ .identifier = "payload" } } else .begin; @@ -7022,7 +7019,7 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { const union_ty = f.typeOf(bin_op.lhs).childType(zcu); const layout = union_ty.unionGetLayout(zcu); if (layout.tag_size == 0) return .none; - const tag_ty = union_ty.unionTagTypeSafety(zcu).?; + const tag_ty = union_ty.unionTagTypeRuntime(zcu).?; const w = &f.object.code.writer; const a = try Assignment.start(f, w, try f.ctypeFromType(tag_ty, .complete)); @@ -7462,18 +7459,15 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { const local = try f.allocLocal(inst, union_ty); - const field: CValue = if (union_ty.unionTagTypeSafety(zcu)) |tag_ty| field: { - const layout = union_ty.unionGetLayout(zcu); - if (layout.tag_size != 0) { - const field_index = tag_ty.enumFieldIndex(field_name, zcu).?; - const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index); - - const a = try Assignment.start(f, w, try f.ctypeFromType(tag_ty, .complete)); - try f.writeCValueMember(w, local, .{ .identifier = "tag" }); - try a.assign(f, w); - try w.print("{f}", .{try f.fmtIntLiteralDec(try tag_val.intFromEnum(tag_ty, pt))}); - try a.end(f, w); - } + const field: CValue = if (union_ty.unionTagTypeRuntime(zcu)) |tag_ty| field: { + assert(union_ty.unionGetLayout(zcu).tag_size != 0); + const field_index = tag_ty.enumFieldIndex(field_name, zcu).?; + const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index); + const a = try Assignment.start(f, w, try f.ctypeFromType(tag_ty, .complete)); + try f.writeCValueMember(w, local, .{ .identifier = "tag" }); + try a.assign(f, w); + try w.print("{f}", .{try f.fmtIntLiteralDec(try tag_val.intFromEnum(tag_ty, pt))}); + try a.end(f, w); break :field .{ .payload_identifier = field_name.toSlice(ip) }; } else .{ .identifier = field_name.toSlice(ip) }; diff --git a/src/codegen/c/Type.zig b/src/codegen/c/Type.zig index 0bcdb207fc693b3acb38cd2a2c458dee9d61dbe3..3ee61a90b656759d0848af6f74e0ab313f9c34c2 100644 --- a/src/codegen/c/Type.zig +++ b/src/codegen/c/Type.zig @@ -2479,7 +2479,7 @@ pub const Pool = struct { return pool.fromFields(allocator, .@"struct", &fields, kind); }, .opt_type => |payload_type| { - if (ip.isNoReturn(payload_type)) return .void; + if (Type.fromInterned(payload_type).isNoReturn(zcu)) return .void; const payload_ctype = try pool.fromType( allocator, scratch, @@ -2521,7 +2521,7 @@ pub const Pool = struct { .signedness = .unsigned, .bits = error_set_bits, }, mod, kind); - if (ip.isNoReturn(error_union_info.payload_type)) return error_set_ctype; + if (Type.fromInterned(error_union_info.payload_type).isNoReturn(zcu)) return error_set_ctype; const payload_type = Type.fromInterned(error_union_info.payload_type); const payload_ctype = try pool.fromType( allocator, @@ -2684,9 +2684,8 @@ pub const Pool = struct { const loaded_union = ip.loadUnionType(ip_index); switch (loaded_union.flagsUnordered(ip).layout) { .auto, .@"extern" => { - const has_tag = loaded_union.hasTag(ip); const fwd_decl = try pool.getFwdDecl(allocator, .{ - .tag = if (has_tag) .@"struct" else .@"union", + .tag = if (loaded_union.has_runtime_tag) .@"struct" else .@"union", .name = .{ .index = ip_index }, }); if (kind.isForward()) return if (ty.hasRuntimeBitsIgnoreComptime(zcu)) @@ -2707,7 +2706,7 @@ pub const Pool = struct { const field_type = Type.fromInterned( loaded_union.field_types.get(ip)[field_index], ); - if (ip.isNoReturn(field_type.toIntern())) continue; + if (field_type.isNoReturn(zcu)) continue; const field_ctype = try pool.fromType( allocator, scratch, @@ -2738,7 +2737,7 @@ pub const Pool = struct { scratch.items.len - scratch_top, @typeInfo(Field).@"struct".fields.len, )); - if (!has_tag) { + if (!loaded_union.has_runtime_tag) { if (fields_len == 0) return .void; try pool.ensureUnusedCapacity(allocator, 1); const extra_index = try pool.addHashedExtra( @@ -2836,7 +2835,7 @@ pub const Pool = struct { var hasher = Hasher.init; const return_type = Type.fromInterned(func_info.return_type); const return_ctype: CType = - if (!ip.isNoReturn(func_info.return_type)) try pool.fromType( + if (!Type.fromInterned(func_info.return_type).isNoReturn(zcu)) try pool.fromType( allocator, scratch, return_type, @@ -2889,7 +2888,6 @@ pub const Pool = struct { .error_union, .enum_literal, .enum_tag, - .empty_enum_value, .float, .ptr, .slice, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 695bb82133aea39b4478c3a9ad4f4ec4c07be6cc..b952f8c22567527c10c76afcd7c8970481418263 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3516,7 +3516,6 @@ pub const Object = struct { .error_union, .enum_literal, .enum_tag, - .empty_enum_value, .float, .ptr, .slice, @@ -3722,7 +3721,6 @@ pub const Object = struct { .undef => unreachable, // handled above .simple_value => |simple_value| switch (simple_value) { - .undefined => unreachable, // non-runtime value .void => unreachable, // non-runtime value .null => unreachable, // non-runtime value .@"unreachable" => unreachable, // non-runtime value @@ -3732,7 +3730,6 @@ pub const Object = struct { }, .variable, .enum_literal, - .empty_enum_value, => unreachable, // non-runtime values .@"extern" => |@"extern"| { const function_index = try o.resolveLlvmFunction(pt, @"extern".owner_nav); diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig index 709de66a412e409ea6017d0a15a631156fe133e4..217581a72ce28eb36f6f0a08a78640124ad2e293 100644 --- a/src/codegen/spirv/CodeGen.zig +++ b/src/codegen/spirv/CodeGen.zig @@ -814,11 +814,9 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { .@"extern", .func, .enum_literal, - .empty_enum_value, => unreachable, // non-runtime values .simple_value => |simple_value| switch (simple_value) { - .undefined, .void, .null, .@"unreachable", @@ -4482,7 +4480,7 @@ fn airSetUnionTag(cg: *CodeGen, inst: Air.Inst.Index) !void { if (layout.tag_size == 0) return; - const tag_ty = un_ty.unionTagTypeSafety(zcu).?; + const tag_ty = un_ty.unionTagTypeRuntime(zcu).?; const tag_ty_id = try cg.resolveType(tag_ty, .indirect); const tag_ptr_ty_id = try cg.module.ptrType(tag_ty_id, cg.module.storageClass(un_ptr_ty.ptrAddressSpace(zcu))); @@ -4508,7 +4506,7 @@ fn airGetUnionTag(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const union_handle = try cg.resolve(ty_op.operand); if (!layout.has_payload) return union_handle; - const tag_ty = un_ty.unionTagTypeSafety(zcu).?; + const tag_ty = un_ty.unionTagTypeRuntime(zcu).?; return try cg.extractField(tag_ty, union_handle, layout.tag_index); } diff --git a/src/codegen/wasm/CodeGen.zig b/src/codegen/wasm/CodeGen.zig index cdcaac93025a4902f1d123c485e80076558a84ed..6b5cd3c1c556aaf63343a2fe33e4966f96203a01 100644 --- a/src/codegen/wasm/CodeGen.zig +++ b/src/codegen/wasm/CodeGen.zig @@ -1244,7 +1244,7 @@ fn generateInner(cg: *CodeGen, any_returns: bool) InnerError!Mir { if (any_returns and cg.air.instructions.len > 0) { const inst: Air.Inst.Index = @enumFromInt(cg.air.instructions.len - 1); const last_inst_ty = cg.typeOfIndex(inst); - if (!last_inst_ty.hasRuntimeBitsIgnoreComptime(zcu) or last_inst_ty.isNoReturn(zcu)) { + if (!last_inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { try cg.addTag(.@"unreachable"); } } @@ -2201,9 +2201,6 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie const result_value = result_value: { if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu) and !ret_ty.isError(zcu)) { break :result_value .none; - } else if (ret_ty.isNoReturn(zcu)) { - try cg.addTag(.@"unreachable"); - break :result_value .none; } else if (first_param_sret) { break :result_value sret; } else if (zcu.typeToFunc(fn_ty).?.cc == .wasm_mvp) { @@ -3158,7 +3155,6 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { .undef => unreachable, // handled above .simple_value => |simple_value| switch (simple_value) { - .undefined, .void, .null, .@"unreachable", @@ -3173,7 +3169,6 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { .@"extern", .func, .enum_literal, - .empty_enum_value, => unreachable, // non-runtime values .int => { const int_info = ty.intInfo(zcu); @@ -5340,7 +5335,7 @@ fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index]; const tag_int = blk: { - const tag_ty = union_ty.unionTagTypeHypothetical(zcu); + const tag_ty = union_ty.unionTagTypeRuntime(zcu).?; const enum_field_index = tag_ty.enumFieldIndex(field_name, zcu).?; const tag_val = try pt.enumValueFieldIndex(tag_ty, enum_field_index); break :blk try cg.lowerConstant(tag_val, tag_ty); @@ -7109,9 +7104,6 @@ fn callIntrinsic( if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) { return .none; - } else if (return_type.isNoReturn(zcu)) { - try cg.addTag(.@"unreachable"); - return .none; } else if (want_sret_param) { return sret; } else { diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index 2a7558505b3c4b1bedad6466d7c15452534c78c1..f46f87ccff5846df798fc470fbb97e06c3cd59e7 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -171467,7 +171467,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { const union_layout = union_ty.unionGetLayout(zcu); if (union_layout.tag_size > 0) { var tag_temp = try cg.tempFromValue(try pt.enumValueFieldIndex( - union_ty.unionTagTypeSafety(zcu).?, + union_ty.unionTagTypeRuntime(zcu).?, union_init.field_index, )); try res.write(&tag_temp, .{ diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 027d5391a56231bc342f6cfe7e8d55a5a08379fa..1d87a42601427050245a3c1f6b2e314b515b0d0b 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -1603,7 +1603,7 @@ pub const WipNav = struct { const zcu = pt.zcu; const ty = val.typeOf(zcu); const has_runtime_bits = ty.hasRuntimeBits(zcu); - const has_comptime_state = ty.comptimeOnly(zcu) and try ty.onePossibleValue(pt) == null; + const has_comptime_state = ty.comptimeOnly(zcu); try wip_nav.abbrevCode(if (has_runtime_bits and has_comptime_state) switch (tag) { .comptime_arg => if (opt_name) |_| .comptime_arg_runtime_bits_comptime_state else .unnamed_comptime_arg_runtime_bits_comptime_state, .local_const => if (opt_name) |_| .local_const_runtime_bits_comptime_state else unreachable, @@ -2108,7 +2108,7 @@ pub const WipNav = struct { const zcu = wip_nav.pt.zcu; const ip = &zcu.intern_pool; const ty = value.typeOf(zcu); - if (std.debug.runtime_safety) assert(ty.comptimeOnly(zcu) and try ty.onePossibleValue(wip_nav.pt) == null); + if (std.debug.runtime_safety) assert(ty.comptimeOnly(zcu)); if (ty.toIntern() == .type_type) return wip_nav.getTypeEntry(value.toType()); if (ip.isFunctionType(ty.toIntern()) and !value.isUndef(zcu)) return wip_nav.getNavEntry(switch (ip.indexToKey(value.toIntern())) { else => unreachable, @@ -2705,7 +2705,7 @@ fn initWipNavInner( try wip_nav.refType(.fromInterned(if (maybe_func_type) |func_type| func_type.return_type else @"extern".ty)); if (maybe_func_type) |func_type| { try wip_nav.infoAddrSym(sym_index, 0); - try diw.writeByte(@intFromBool(ip.isNoReturn(func_type.return_type))); + try diw.writeByte(@intFromBool(Type.fromInterned(func_type.return_type).isNoReturn(zcu))); if (func_type.param_types.len > 0 or func_type.is_var_args) { for (func_type.param_types.get(ip)) |param_type| { try wip_nav.abbrevCode(.extern_param); @@ -2733,7 +2733,7 @@ fn initWipNavInner( try wip_nav.strp(@"extern".name.toSlice(ip)); try wip_nav.refType(.fromInterned(func_type.return_type)); try wip_nav.infoAddrSym(sym_index, 0); - try diw.writeByte(@intFromBool(ip.isNoReturn(func_type.return_type))); + try diw.writeByte(@intFromBool(Type.fromInterned(func_type.return_type).isNoReturn(zcu))); if (func_type.param_types.len > 0 or func_type.is_var_args) { for (func_type.param_types.get(ip)) |param_type| { try wip_nav.abbrevCode(.extern_param); @@ -2818,7 +2818,7 @@ fn initWipNavInner( else => |a| a.maxStrict(target_info.minFunctionAlignment(target)), }.toByteUnits().?); try diw.writeByte(@intFromBool(decl.linkage != .normal)); - try diw.writeByte(@intFromBool(ip.isNoReturn(func_type.return_type))); + try diw.writeByte(@intFromBool(Type.fromInterned(func_type.return_type).isNoReturn(zcu))); const dlw = &wip_nav.debug_line.writer; try dlw.writeByte(DW.LNS.extended_op); @@ -3172,7 +3172,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo .none => .{ false, false }, else => .{ field_type.hasRuntimeBits(zcu), - field_type.comptimeOnly(zcu) and try field_type.onePossibleValue(pt) == null, + field_type.comptimeOnly(zcu), }, }; try wip_nav.abbrevCode(if (is_comptime) @@ -3294,7 +3294,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo try diw.writeUleb128(union_layout.abi_size); try diw.writeUleb128(union_layout.abi_align.toByteUnits().?); const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); - if (loaded_union.runtime_tag != .none) { + if (loaded_union.has_runtime_tag) { try wip_nav.abbrevCode(.tagged_union); try wip_nav.infoSectionOffset( .debug_info, @@ -3371,7 +3371,6 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo .error_union, .enum_literal, .enum_tag, - .empty_enum_value, .float, .ptr, .slice, @@ -3465,7 +3464,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo const diw = &wip_nav.debug_info.writer; const nav_ty = nav_val.typeOf(zcu); const has_runtime_bits = nav_ty.hasRuntimeBits(zcu); - const has_comptime_state = nav_ty.comptimeOnly(zcu) and try nav_ty.onePossibleValue(pt) == null; + const has_comptime_state = nav_ty.comptimeOnly(zcu); try wip_nav.declCommon(if (has_runtime_bits and has_comptime_state) .{ .decl = .decl_const_runtime_bits_comptime_state, .generic_decl = .generic_decl_const, @@ -3845,7 +3844,7 @@ fn updateLazyType( .none => .{ false, false }, else => .{ field_type.hasRuntimeBits(zcu), - field_type.comptimeOnly(zcu) and try field_type.onePossibleValue(pt) == null, + field_type.comptimeOnly(zcu), }, }; try wip_nav.abbrevCode(if (has_comptime_state) @@ -4008,7 +4007,6 @@ fn updateLazyType( .error_union, .enum_literal, .enum_tag, - .empty_enum_value, .float, .ptr, .slice, @@ -4128,7 +4126,7 @@ fn updateLazyValue( .payload => |payload_val| { const payload_type: Type = .fromInterned(ip.typeOf(payload_val)); const has_runtime_bits = payload_type.hasRuntimeBits(zcu); - const has_comptime_state = payload_type.comptimeOnly(zcu) and try payload_type.onePossibleValue(pt) == null; + const has_comptime_state = payload_type.comptimeOnly(zcu); try wip_nav.abbrevCode(if (has_comptime_state) .comptime_value_field_comptime_state else if (has_runtime_bits) @@ -4164,7 +4162,6 @@ fn updateLazyValue( }, .fromInterned(int.ty), Value.fromInterned(value_index).toBigInt(&big_int_space, zcu)); try wip_nav.refType(.fromInterned(enum_tag.ty)); }, - .empty_enum_value => unreachable, .float => |float| { switch (float.storage) { .f16 => |f16_val| { @@ -4209,7 +4206,7 @@ fn updateLazyValue( .comptime_alloc, .comptime_field => unreachable, .uav => |uav| { const uav_ty: Type = .fromInterned(ip.typeOf(uav.val)); - if (try uav_ty.onePossibleValue(pt)) |_| { + if (uav_ty.classify(zcu) == .one_possible_value) { try wip_nav.abbrevCode(if (zero_bit_accesses.items.len > 0) .aggregate_udata_comptime_value else @@ -4337,7 +4334,7 @@ fn updateLazyValue( } if (opt.val != .none) child_field: { const has_runtime_bits = opt_child_type.hasRuntimeBits(zcu); - const has_comptime_state = opt_child_type.comptimeOnly(zcu) and try opt_child_type.onePossibleValue(pt) == null; + const has_comptime_state = opt_child_type.comptimeOnly(zcu); try wip_nav.abbrevCode(if (has_comptime_state) .comptime_value_field_comptime_state else if (has_runtime_bits) @@ -4363,7 +4360,7 @@ fn updateLazyValue( if (loaded_struct_type.field_is_comptime_bits.get(ip, field_index)) continue; const field_type: Type = .fromInterned(loaded_struct_type.field_types.get(ip)[field_index]); const has_runtime_bits = field_type.hasRuntimeBits(zcu); - const has_comptime_state = field_type.comptimeOnly(zcu) and try field_type.onePossibleValue(pt) == null; + const has_comptime_state = field_type.comptimeOnly(zcu); try wip_nav.abbrevCode(if (has_comptime_state) .comptime_value_field_comptime_state else if (has_runtime_bits) @@ -4386,7 +4383,7 @@ fn updateLazyValue( if (tuple_type.values.get(ip)[field_index] != .none) continue; const field_type: Type = .fromInterned(tuple_type.types.get(ip)[field_index]); const has_runtime_bits = field_type.hasRuntimeBits(zcu); - const has_comptime_state = field_type.comptimeOnly(zcu) and try field_type.onePossibleValue(pt) == null; + const has_comptime_state = field_type.comptimeOnly(zcu); try wip_nav.abbrevCode(if (has_comptime_state) .comptime_value_field_comptime_state else if (has_runtime_bits) @@ -4411,7 +4408,7 @@ fn updateLazyValue( inline .array_type, .vector_type => |sequence_type| { const child_type: Type = .fromInterned(sequence_type.child); const has_runtime_bits = child_type.hasRuntimeBits(zcu); - const has_comptime_state = child_type.comptimeOnly(zcu) and try child_type.onePossibleValue(pt) == null; + const has_comptime_state = child_type.comptimeOnly(zcu); for (switch (aggregate.storage) { .bytes => unreachable, .elems => |elems| elems, @@ -4443,7 +4440,7 @@ fn updateLazyValue( const field_ty: Type = .fromInterned(loaded_union_type.field_types.get(ip)[field_index]); const field_name = ip.loadEnumType(loaded_union_type.enum_tag_type).field_names.get(ip)[field_index]; const has_runtime_bits = field_ty.hasRuntimeBits(zcu); - const has_comptime_state = field_ty.comptimeOnly(zcu) and try field_ty.onePossibleValue(pt) == null; + const has_comptime_state = field_ty.comptimeOnly(zcu); try wip_nav.abbrevCode(if (has_comptime_state) .comptime_value_field_comptime_state else if (has_runtime_bits) @@ -4540,7 +4537,7 @@ fn updateContainerTypeWriterError( .none => .{ false, false }, else => .{ field_type.hasRuntimeBits(zcu), - field_type.comptimeOnly(zcu) and try field_type.onePossibleValue(pt) == null, + field_type.comptimeOnly(zcu), }, }; try wip_nav.abbrevCode(if (is_comptime) @@ -4647,7 +4644,7 @@ fn updateContainerTypeWriterError( .none => .{ false, false }, else => .{ field_type.hasRuntimeBits(zcu), - field_type.comptimeOnly(zcu) and try field_type.onePossibleValue(pt) == null, + field_type.comptimeOnly(zcu), }, }; try wip_nav.abbrevCode(if (is_comptime) @@ -4724,7 +4721,7 @@ fn updateContainerTypeWriterError( try diw.writeUleb128(union_layout.abi_size); try diw.writeUleb128(union_layout.abi_align.toByteUnits().?); const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); - if (loaded_union.runtime_tag != .none) { + if (loaded_union.has_runtime_tag) { try wip_nav.abbrevCode(.tagged_union); try wip_nav.infoSectionOffset( .debug_info, diff --git a/src/print_value.zig b/src/print_value.zig index d472472481350ff57a47ed3277c6a54cc161d374..d05fe09ec15416b21e5adfe7324f6375fd6d6ff5 100644 --- a/src/print_value.zig +++ b/src/print_value.zig @@ -73,7 +73,6 @@ pub fn print( .simple_value => |simple_value| switch (simple_value) { .void => try writer.writeAll("{}"), - .undefined, .null, .true, .false, @@ -111,7 +110,6 @@ pub fn print( try print(Value.fromInterned(enum_tag.int), writer, level - 1, pt, opt_sema); try writer.writeAll(")"); }, - .empty_enum_value => try writer.writeAll("(empty enum value)"), .float => |float| switch (float.storage) { inline else => |x| try writer.print("{d}", .{@as(f64, @floatCast(x))}), }, -- 2.54.0 From 8eefe86939e917e4e85049325bff8c5a43f50f95 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Thu, 29 Jan 2026 18:11:19 +0000 Subject: [PATCH 11/79] std: remove default values from ArrayList These were deprecated in the 0.14.0 release cycle almost a year ago, so they can definitely be deleted now. --- lib/std/Build/Fuzz.zig | 4 ++-- lib/std/Build/Module.zig | 14 +++++++------- lib/std/Build/Step.zig | 2 +- lib/std/Build/Step/Run.zig | 8 ++++---- lib/std/Build/Step/UpdateSourceFiles.zig | 2 +- lib/std/Build/Step/WriteFile.zig | 4 ++-- lib/std/Io/Dir.zig | 2 +- lib/std/array_list.zig | 4 ++-- lib/std/compress/lzma.zig | 2 +- lib/std/compress/lzma2.zig | 2 +- lib/std/debug/Coverage.zig | 6 +++--- lib/std/zig/Ast.zig | 8 ++++---- lib/std/zig/AstGen.zig | 2 +- lib/std/zig/ErrorBundle.zig | 12 ++++++------ src/Package/Manifest.zig | 6 +++--- 15 files changed, 39 insertions(+), 39 deletions(-) diff --git a/lib/std/Build/Fuzz.zig b/lib/std/Build/Fuzz.zig index b2477f50884b34100e772960ca4a2c387ddd0008..e4104661add503c549ef09fbb3b16244683a9ce4 100644 --- a/lib/std/Build/Fuzz.zig +++ b/lib/std/Build/Fuzz.zig @@ -390,7 +390,7 @@ fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutO .coverage = std.debug.Coverage.init, .mapped_memory = undefined, // populated below .source_locations = undefined, // populated below - .entry_points = .{}, + .entry_points = .empty, .start_timestamp = ws.now(), .start_n_runs = undefined, // populated below }; @@ -450,7 +450,7 @@ fn prepareTables(fuzz: *Fuzz, run_step: *Step.Run, coverage_id: u64) error{ OutO // Unfortunately the PCs array that LLVM gives us from the 8-bit PC // counters feature is not sorted. - var sorted_pcs: std.MultiArrayList(struct { pc: u64, index: u32, sl: Coverage.SourceLocation }) = .{}; + var sorted_pcs: std.MultiArrayList(struct { pc: u64, index: u32, sl: Coverage.SourceLocation }) = .empty; defer sorted_pcs.deinit(gpa); try sorted_pcs.resize(gpa, pcs.len); @memcpy(sorted_pcs.items(.pc), pcs); diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig index 657f8bb74eed1773400caa86c66e0b36211fbe1c..959e110c4ad47a5ddd95a508f91a3b49c66636ea 100644 --- a/lib/std/Build/Module.zig +++ b/lib/std/Build/Module.zig @@ -275,18 +275,18 @@ pub fn init( m.* = .{ .owner = owner, .root_source_file = if (options.root_source_file) |lp| lp.dupe(owner) else null, - .import_table = .{}, + .import_table = .empty, .resolved_target = options.target, .optimize = options.optimize, .link_libc = options.link_libc, .link_libcpp = options.link_libcpp, .dwarf_format = options.dwarf_format, - .c_macros = .{}, - .include_dirs = .{}, - .lib_paths = .{}, - .rpaths = .{}, - .frameworks = .{}, - .link_objects = .{}, + .c_macros = .empty, + .include_dirs = .empty, + .lib_paths = .empty, + .rpaths = .empty, + .frameworks = .empty, + .link_objects = .empty, .strip = options.strip, .unwind_tables = options.unwind_tables, .single_threaded = options.single_threaded, diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index b518826843caad753b23051f92840af7b6143a22..5876614099b38b9608006650b464978a87443b6f 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -250,7 +250,7 @@ pub fn init(options: StepOptions) Step { const first_ret_addr = options.first_ret_addr orelse @returnAddress(); break :blk std.debug.captureCurrentStackTrace(.{ .first_address = first_ret_addr }, addr_buf); }, - .result_error_msgs = .{}, + .result_error_msgs = .empty, .result_error_bundle = std.zig.ErrorBundle.empty, .result_stderr = "", .result_cached = false, diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 8a21e6fef9b3da523b2ad087008b805c7da0e676..63c9f4e6d4c823a32d0d348935c44be2cec84eb9 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -213,13 +213,13 @@ pub fn create(owner: *std.Build, name: []const u8) *Run { .owner = owner, .makeFn = make, }), - .argv = .{}, + .argv = .empty, .cwd = null, .environ_map = null, .disable_zig_progress = false, .stdio = .infer_from_args, .stdin = .none, - .file_inputs = .{}, + .file_inputs = .empty, .rename_step_with_output_arg = true, .skip_foreign_checks = false, .failing_to_execute_foreign_is_an_error = true, @@ -228,7 +228,7 @@ pub fn create(owner: *std.Build, name: []const u8) *Run { .captured_stderr = null, .dep_output_file = null, .has_side_effects = false, - .fuzz_tests = .{}, + .fuzz_tests = .empty, .rebuilt_executable = null, .producer = null, }; @@ -642,7 +642,7 @@ pub fn addCheck(run: *Run, new_check: StdIo.Check) void { switch (run.stdio) { .infer_from_args => { - run.stdio = .{ .check = .{} }; + run.stdio = .{ .check = .empty }; run.stdio.check.append(b.allocator, new_check) catch @panic("OOM"); }, .check => |*checks| checks.append(b.allocator, new_check) catch @panic("OOM"), diff --git a/lib/std/Build/Step/UpdateSourceFiles.zig b/lib/std/Build/Step/UpdateSourceFiles.zig index 1c4c94f9cf65c1167d72a0ac92c8c5c9ec17a805..0cc3b787c3f8416c284b0977ea9e73b9bf405fd7 100644 --- a/lib/std/Build/Step/UpdateSourceFiles.zig +++ b/lib/std/Build/Step/UpdateSourceFiles.zig @@ -35,7 +35,7 @@ pub fn create(owner: *std.Build) *UpdateSourceFiles { .owner = owner, .makeFn = make, }), - .output_source_files = .{}, + .output_source_files = .empty, }; return usf; } diff --git a/lib/std/Build/Step/WriteFile.zig b/lib/std/Build/Step/WriteFile.zig index 0c0e2b5d8637c10a5c6acae515927c84d690c371..3613fa3fef8fa5ac1a5587a4c4cdcca96661b7b6 100644 --- a/lib/std/Build/Step/WriteFile.zig +++ b/lib/std/Build/Step/WriteFile.zig @@ -94,8 +94,8 @@ pub fn create(owner: *std.Build) *WriteFile { .owner = owner, .makeFn = make, }), - .files = .{}, - .directories = .{}, + .files = .empty, + .directories = .empty, .generated_directory = .{ .step = &write_file.step }, }; return write_file; diff --git a/lib/std/Io/Dir.zig b/lib/std/Io/Dir.zig index 85ab6b77d4990420c32086efaf634dc0fc830938..3e38849f7f60fa80cdd4b3903ccc4e5f07ad4d12 100644 --- a/lib/std/Io/Dir.zig +++ b/lib/std/Io/Dir.zig @@ -334,7 +334,7 @@ pub fn walkSelectively(dir: Dir, allocator: Allocator) !SelectiveWalker { return .{ .stack = stack, - .name_buffer = .{}, + .name_buffer = .empty, .allocator = allocator, }; } diff --git a/lib/std/array_list.zig b/lib/std/array_list.zig index f15388d7b5df62c3112b4ab0902ee587425c0442..d763233beda0ec7805ed71af07932bfe88fecf8a 100644 --- a/lib/std/array_list.zig +++ b/lib/std/array_list.zig @@ -582,10 +582,10 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { /// functions of this ArrayList in accordance with the respective /// documentation. In all cases, "invalidated" means that the memory /// has been passed to an allocator's resize or free function. - items: Slice = &[_]T{}, + items: Slice, /// How many T values this list can hold without allocating /// additional memory. - capacity: usize = 0, + capacity: usize, /// An ArrayList containing no elements. pub const empty: Self = .{ diff --git a/lib/std/compress/lzma.zig b/lib/std/compress/lzma.zig index 7a586298bea5f7b3db346ce9e5cccb834cb05e47..4e3c6146167868e04f257cdec38cb9eb83ae642a 100644 --- a/lib/std/compress/lzma.zig +++ b/lib/std/compress/lzma.zig @@ -349,7 +349,7 @@ pub const Decode = struct { pub fn init(dict_size: usize, mem_limit: usize) CircularBuffer { return .{ - .buf = .{}, + .buf = .empty, .dict_size = dict_size, .mem_limit = mem_limit, .cursor = 0, diff --git a/lib/std/compress/lzma2.zig b/lib/std/compress/lzma2.zig index 7d743f9a1b6c87c06b0aeca93cd8019eb0b75404..42c887c042bac9b239036e2f7bbfbb1657966b20 100644 --- a/lib/std/compress/lzma2.zig +++ b/lib/std/compress/lzma2.zig @@ -16,7 +16,7 @@ pub const AccumBuffer = struct { pub fn init(memlimit: usize) AccumBuffer { return .{ - .buf = .{}, + .buf = .empty, .memlimit = memlimit, .len = 0, }; diff --git a/lib/std/debug/Coverage.zig b/lib/std/debug/Coverage.zig index 81dfce853e0e66c706be73f09407de80d37f339f..b3e16382cc45dff17d34b9bf57f7accb63d918e5 100644 --- a/lib/std/debug/Coverage.zig +++ b/lib/std/debug/Coverage.zig @@ -27,10 +27,10 @@ string_bytes: std.ArrayList(u8), mutex: Io.Mutex, pub const init: Coverage = .{ - .directories = .{}, - .files = .{}, + .directories = .empty, + .files = .empty, .mutex = .init, - .string_bytes = .{}, + .string_bytes = .empty, }; pub const String = enum(u32) { diff --git a/lib/std/zig/Ast.zig b/lib/std/zig/Ast.zig index 3c039b5fe5a54be45e0ca9c4bcee2ba9699a7f57..8620df51fa0dea04e3c075951bf0df0c161dd363 100644 --- a/lib/std/zig/Ast.zig +++ b/lib/std/zig/Ast.zig @@ -175,10 +175,10 @@ pub fn parseTokens( .source = source, .gpa = gpa, .tokens = tokens, - .errors = .{}, - .nodes = .{}, - .extra_data = .{}, - .scratch = .{}, + .errors = .empty, + .nodes = .empty, + .extra_data = .empty, + .scratch = .empty, .tok_i = 0, }; defer parser.errors.deinit(gpa); diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index 046330c46bedffaa8d16036ccb041264373c34b7..1fcb9f5eb2aac77802763ac742913899c71ede4e 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -1780,7 +1780,7 @@ fn structInitExpr( try gop.value_ptr.append(sfba_allocator, name_token); any_duplicate = true; } else { - gop.value_ptr.* = .{}; + gop.value_ptr.* = .empty; try gop.value_ptr.append(sfba_allocator, name_token); } } diff --git a/lib/std/zig/ErrorBundle.zig b/lib/std/zig/ErrorBundle.zig index c5275729ae5f1a6efd58ff65b813cc98863b49ff..64aafd110efb9a4d8247450ac85049286871e05a 100644 --- a/lib/std/zig/ErrorBundle.zig +++ b/lib/std/zig/ErrorBundle.zig @@ -340,9 +340,9 @@ pub const Wip = struct { pub fn init(wip: *Wip, gpa: Allocator) !void { wip.* = .{ .gpa = gpa, - .string_bytes = .{}, - .extra = .{}, - .root_list = .{}, + .string_bytes = .empty, + .extra = .empty, + .root_list = .empty, }; // So that 0 can be used to indicate a null string. @@ -371,9 +371,9 @@ pub const Wip = struct { wip.deinit(); wip.* = .{ .gpa = gpa, - .string_bytes = .{}, - .extra = .{}, - .root_list = .{}, + .string_bytes = .empty, + .extra = .empty, + .root_list = .empty, }; return empty; } diff --git a/src/Package/Manifest.zig b/src/Package/Manifest.zig index 3370ef1d47dd6c771c5428adabe7160ea4964992..90d61c963b8a6ac8d6f62028f1e37f4d38a70fb5 100644 --- a/src/Package/Manifest.zig +++ b/src/Package/Manifest.zig @@ -66,7 +66,7 @@ pub fn parse(gpa: Allocator, ast: *const Ast, rng: std.Random, options: ParseOpt .gpa = gpa, .ast = ast.*, .arena = arena_instance.allocator(), - .errors = .{}, + .errors = .empty, .name = undefined, .id = 0, @@ -74,10 +74,10 @@ pub fn parse(gpa: Allocator, ast: *const Ast, rng: std.Random, options: ParseOpt .version_node = undefined, .dependencies = .{}, .dependencies_node = .none, - .paths = .{}, + .paths = .empty, .allow_missing_paths_field = options.allow_missing_paths_field, .minimum_zig_version = null, - .buf = .{}, + .buf = .empty, }; defer p.buf.deinit(gpa); defer p.errors.deinit(gpa); -- 2.54.0 From 650185692dc6fb6b9c2c4e591d37cb94410972e1 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Thu, 29 Jan 2026 18:44:25 +0000 Subject: [PATCH 12/79] compiler: merge struct default value resolution into layout resolution This actually doesn't cause any dependency loops in std, which is pretty much my benchmark for it being acceptable. This can be reverted if it turns out to be problematic, but for now, let's err on the side of language simplicity. To be clear, this *does* regress some cases which previously worked: I will have to remove some behavior tests as a result of this commit. To be honest, the tests which look to be failing as a result of this are things which I think are generally unadvisable; I actually reckon a bit more friction to use default field values in non-trivial ways might be a good thing to stop people from misusing them as much. Struct fields should very rarely have default values; about the only common situation where they make sense is "options" structs. --- src/Air/Liveness.zig | 8 +- src/Compilation.zig | 9 +- src/IncrementalDebugServer.zig | 4 +- src/InternPool.zig | 87 +-------------- src/Sema.zig | 68 +++++------- src/Sema/LowerZon.zig | 1 - src/Sema/type_resolution.zig | 189 ++++++++------------------------- src/Zcu.zig | 8 +- src/Zcu/PerThread.zig | 122 ++------------------- src/codegen/c/Type.zig | 12 +-- src/link/Elf/Object.zig | 2 +- src/link/Elf/ZigObject.zig | 6 +- src/link/MachO/ZigObject.zig | 4 +- src/link/Wasm.zig | 4 +- src/main.zig | 18 ++-- 15 files changed, 120 insertions(+), 422 deletions(-) diff --git a/src/Air/Liveness.zig b/src/Air/Liveness.zig index 5c98dc96fca8c54208556eff486475cede9513a6..384a056988b40b6a59fc4f9a582c7869bf994d3e 100644 --- a/src/Air/Liveness.zig +++ b/src/Air/Liveness.zig @@ -153,8 +153,8 @@ pub fn analyze(zcu: *Zcu, air: Air, intern_pool: *InternPool) Allocator.Error!Li usize, (air.instructions.len * bpi + @bitSizeOf(usize) - 1) / @bitSizeOf(usize), ), - .extra = .{}, - .special = .{}, + .extra = .empty, + .special = .empty, .intern_pool = intern_pool, }; errdefer gpa.free(a.tomb_bits); @@ -175,7 +175,7 @@ pub fn analyze(zcu: *Zcu, air: Air, intern_pool: *InternPool) Allocator.Error!Li var data: LivenessPassData(.main_analysis) = .{}; defer data.deinit(gpa); data.old_extra = a.extra; - a.extra = .{}; + a.extra = .empty; try analyzeBody(&a, .main_analysis, &data, main_body); assert(data.live_set.count() == 0); } @@ -1360,7 +1360,7 @@ fn analyzeInstSwitchBr( const mirrored_deaths = try gpa.alloc(DeathList, ncases + 1); defer gpa.free(mirrored_deaths); - @memset(mirrored_deaths, .{}); + @memset(mirrored_deaths, .empty); defer for (mirrored_deaths) |*md| md.deinit(gpa); { diff --git a/src/Compilation.zig b/src/Compilation.zig index 64afabc76394a03c4b421345213ce9a189be34de..ba8a2907f9116e618941b6bad6e1cf2f35f76a7f 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -3713,7 +3713,6 @@ const Header = extern struct { nav_val_deps_len: u32, nav_ty_deps_len: u32, type_layout_deps_len: u32, - struct_defaults_deps_len: u32, func_ies_deps_len: u32, zon_file_deps_len: u32, embed_file_deps_len: u32, @@ -3763,7 +3762,6 @@ pub fn saveState(comp: *Compilation) !void { .nav_val_deps_len = @intCast(ip.nav_val_deps.count()), .nav_ty_deps_len = @intCast(ip.nav_ty_deps.count()), .type_layout_deps_len = @intCast(ip.type_layout_deps.count()), - .struct_defaults_deps_len = @intCast(ip.struct_defaults_deps.count()), .func_ies_deps_len = @intCast(ip.func_ies_deps.count()), .zon_file_deps_len = @intCast(ip.zon_file_deps.count()), .embed_file_deps_len = @intCast(ip.embed_file_deps.count()), @@ -3788,7 +3786,7 @@ pub fn saveState(comp: *Compilation) !void { }, }); - try bufs.ensureTotalCapacityPrecise(26 + 9 * pt_headers.items.len); + try bufs.ensureTotalCapacityPrecise(24 + 9 * pt_headers.items.len); addBuf(&bufs, mem.asBytes(&header)); addBuf(&bufs, @ptrCast(pt_headers.items)); @@ -3800,8 +3798,6 @@ pub fn saveState(comp: *Compilation) !void { addBuf(&bufs, @ptrCast(ip.nav_ty_deps.values())); addBuf(&bufs, @ptrCast(ip.type_layout_deps.keys())); addBuf(&bufs, @ptrCast(ip.type_layout_deps.values())); - addBuf(&bufs, @ptrCast(ip.struct_defaults_deps.keys())); - addBuf(&bufs, @ptrCast(ip.struct_defaults_deps.values())); addBuf(&bufs, @ptrCast(ip.func_ies_deps.keys())); addBuf(&bufs, @ptrCast(ip.func_ies_deps.values())); addBuf(&bufs, @ptrCast(ip.zon_file_deps.keys())); @@ -4481,7 +4477,7 @@ pub fn addModuleErrorMsg( const root_name: ?[]const u8 = switch (ref.referencer.unwrap()) { .@"comptime" => "comptime", .nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip), - .type_layout, .struct_defaults => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), + .type_layout => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip), .memoized_state => null, }; @@ -5251,7 +5247,6 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav), .nav_val => |nav| pt.ensureNavValUpToDate(nav), .type_layout => |ty| pt.ensureTypeLayoutUpToDate(.fromInterned(ty)), - .struct_defaults => |ty| pt.ensureStructDefaultsUpToDate(.fromInterned(ty)), .memoized_state => |stage| pt.ensureMemoizedStateUpToDate(stage), .func => |func| pt.ensureFuncBodyUpToDate(func), }; diff --git a/src/IncrementalDebugServer.zig b/src/IncrementalDebugServer.zig index 7d0dc8e89b6fd9fd257733839e924de1ce92a25f..782b34320586299b259336e70cca63d9fba32376 100644 --- a/src/IncrementalDebugServer.zig +++ b/src/IncrementalDebugServer.zig @@ -307,7 +307,7 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const switch (dependee) { .src_hash, .namespace, .namespace_name, .zon_file, .embed_file => try w.print("{f}", .{zcu.fmtDependee(dependee)}), .nav_val, .nav_ty => |nav| try w.print("{t} {d}", .{ dependee, @intFromEnum(nav) }), - .type_layout, .struct_defaults, .func_ies => |ip_index| try w.print("{t} {d}", .{ dependee, @intFromEnum(ip_index) }), + .type_layout, .func_ies => |ip_index| try w.print("{t} {d}", .{ dependee, @intFromEnum(ip_index) }), .memoized_state => |stage| try w.print("memoized_state {s}", .{@tagName(stage)}), } try w.writeByte('\n'); @@ -374,8 +374,6 @@ fn parseAnalUnit(str: []const u8) ?AnalUnit { return .wrap(.{ .nav_ty = @enumFromInt(parseIndex(idx_str) orelse return null) }); } else if (std.mem.eql(u8, kind, "type_layout")) { return .wrap(.{ .type_layout = @enumFromInt(parseIndex(idx_str) orelse return null) }); - } else if (std.mem.eql(u8, kind, "struct_defaults")) { - return .wrap(.{ .struct_defaults = @enumFromInt(parseIndex(idx_str) orelse return null) }); } else if (std.mem.eql(u8, kind, "func")) { return .wrap(.{ .func = @enumFromInt(parseIndex(idx_str) orelse return null) }); } else if (std.mem.eql(u8, kind, "memoized_state")) { diff --git a/src/InternPool.zig b/src/InternPool.zig index 31e37dd98e80f38e1141ce70d86940511cfe1914..388d0a04f74fd88f6b479395044c84a90d351469 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -54,9 +54,6 @@ func_ies_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), /// Dependencies on the resolved layout of a `struct`, `union`, or `enum` type. /// Value is index into `dep_entries` of the first dependency on this type's layout. type_layout_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), -/// Dependencies on the resolved default field values of a `struct` type. -/// Value is index into `dep_entries` of the first dependency on this type's inits. -struct_defaults_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), /// Dependencies on a ZON file. Triggered by `@import` of ZON. /// Value is index into `dep_entries` of the first dependency on this ZON file. zon_file_deps: std.AutoArrayHashMapUnmanaged(FileIndex, DepEntry.Index), @@ -111,7 +108,6 @@ pub const empty: InternPool = .{ .nav_ty_deps = .empty, .func_ies_deps = .empty, .type_layout_deps = .empty, - .struct_defaults_deps = .empty, .zon_file_deps = .empty, .embed_file_deps = .empty, .namespace_deps = .empty, @@ -423,7 +419,6 @@ pub const AnalUnit = packed struct(u64) { nav_val, nav_ty, type_layout, - struct_defaults, func, memoized_state, }; @@ -437,8 +432,6 @@ pub const AnalUnit = packed struct(u64) { nav_ty: Nav.Index, /// This `AnalUnit` resolves the layout of the given `struct`, `union`, or `enum` type. type_layout: InternPool.Index, - /// This `AnalUnit` resolves the default field values of the given `struct` type. - struct_defaults: InternPool.Index, /// This `AnalUnit` analyzes the body of the given runtime function. func: InternPool.Index, /// This `AnalUnit` resolves all state which is memoized in fields on `Zcu`. @@ -858,7 +851,6 @@ pub const Dependee = union(enum) { /// Index is the function, not its IES. func_ies: Index, type_layout: Index, - struct_defaults: Index, zon_file: FileIndex, embed_file: Zcu.EmbedFile.Index, namespace: TrackedInst.Index, @@ -912,7 +904,6 @@ pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyI .nav_ty => |x| ip.nav_ty_deps.get(x), .func_ies => |x| ip.func_ies_deps.get(x), .type_layout => |x| ip.type_layout_deps.get(x), - .struct_defaults => |x| ip.struct_defaults_deps.get(x), .zon_file => |x| ip.zon_file_deps.get(x), .embed_file => |x| ip.embed_file_deps.get(x), .namespace => |x| ip.namespace_deps.get(x), @@ -987,7 +978,6 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend .nav_ty => ip.nav_ty_deps, .func_ies => ip.func_ies_deps, .type_layout => ip.type_layout_deps, - .struct_defaults => ip.struct_defaults_deps, .zon_file => ip.zon_file_deps, .embed_file => ip.embed_file_deps, .namespace => ip.namespace_deps, @@ -3326,15 +3316,6 @@ pub const LoadedStructType = struct { /// compiler frontend resolves this by traversing the reference graph at the end of each update /// with `Zcu.resolveReferences` and hiding compile errors which arise from this analysis. want_layout: bool, - /// Initially `false`, and set to `true` once any dependency on or reference to the struct's - /// default field values is encountered, after which it is never reset to `false`, even across - /// incremental updates. - /// - /// This field is purely an optimization to avoid resolving the layout of types whose layouts - /// are never demanded. If this field is `true` but the layout is not actually needed, the - /// compiler frontend resolves this by traversing the reference graph at the end of each update - /// with `Zcu.resolveReferences` and hiding compile errors which arise from this analysis. - want_defaults: bool, // The remaining fields are only valid once the struct's layout is resolved. field_name_map: MapIndex, @@ -3711,7 +3692,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { .packed_backing_mode = undefined, .want_layout = extra.data.flags.want_layout, - .want_defaults = extra.data.flags.want_defaults, .field_name_map = extra.data.field_name_map, .field_names = field_names, @@ -3772,7 +3752,6 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { .packed_backing_mode = backing_mode, .want_layout = extra.data.bits.want_layout, - .want_defaults = extra.data.bits.want_defaults, .field_name_map = extra.data.field_name_map, .field_names = field_names, @@ -5666,9 +5645,8 @@ pub const Tag = enum(u8) { alignment: Alignment, want_layout: bool, - want_defaults: bool, - _: u15 = 0, + _: u16 = 0, }; }; @@ -5693,12 +5671,11 @@ pub const Tag = enum(u8) { field_name_map: MapIndex, const Bits = packed struct(u32) { - captures_len: enum(u30) { - reified = std.math.maxInt(u30), + captures_len: enum(u31) { + reified = std.math.maxInt(u31), _, }, want_layout: bool, - want_defaults: bool, }; }; @@ -6477,7 +6454,6 @@ pub fn deinit(ip: *InternPool, gpa: Allocator, io: Io) void { ip.nav_ty_deps.deinit(gpa); ip.func_ies_deps.deinit(gpa); ip.type_layout_deps.deinit(gpa); - ip.struct_defaults_deps.deinit(gpa); ip.zon_file_deps.deinit(gpa); ip.embed_file_deps.deinit(gpa); ip.namespace_deps.deinit(gpa); @@ -8191,7 +8167,6 @@ pub fn getDeclaredStructType( .bits = .{ .captures_len = @enumFromInt(ini.captures.len), .want_layout = false, - .want_defaults = false, }, .name = undefined, // set by `finish` .name_nav = undefined, // set by `finish` @@ -8256,7 +8231,6 @@ pub fn getDeclaredStructType( .class = .no_possible_value, .alignment = .none, .want_layout = false, - .want_defaults = false, }, }); if (ini.captures.len != 0) { @@ -8337,7 +8311,6 @@ pub fn getReifiedStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Pe .bits = .{ .captures_len = .reified, .want_layout = false, - .want_defaults = false, }, .name = undefined, // set by `finish` .name_nav = undefined, // set by `finish` @@ -8407,7 +8380,6 @@ pub fn getReifiedStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.Pe .class = .no_possible_value, .alignment = .none, .want_layout = false, - .want_defaults = false, }, }); _ = addExtraAssumeCapacity(extra, PackedU64.init(ini.type_hash)); // type_hash @@ -10647,7 +10619,6 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void { const nav_ty_deps_len = ip.nav_ty_deps.count(); const func_ies_deps_len = ip.func_ies_deps.count(); const type_layout_deps_len = ip.type_layout_deps.count(); - const struct_defaults_deps_len = ip.struct_defaults_deps.count(); const zon_file_deps_len = ip.zon_file_deps.count(); const embed_file_deps_len = ip.embed_file_deps.count(); const namespace_deps_len = ip.namespace_deps.count(); @@ -10658,7 +10629,6 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void { const nav_ty_deps_size = nav_ty_deps_len * 8; const func_ies_deps_size = func_ies_deps_len * 8; const type_layout_deps_size = type_layout_deps_len * 8; - const struct_defaults_deps_size = struct_defaults_deps_len * 8; const zon_file_deps_size = zon_file_deps_len * 8; const embed_file_deps_size = embed_file_deps_len * 8; const namespace_deps_size = namespace_deps_len * 8; @@ -10672,7 +10642,6 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void { \\ {d} nav_ty: {d} bytes \\ {d} func_ies: {d} bytes \\ {d} type_layout: {d} bytes - \\ {d} struct_defaults: {d} bytes \\ {d} zon_file: {d} bytes \\ {d} embed_file: {d} bytes \\ {d} namespace: {d} bytes @@ -10680,7 +10649,7 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void { \\ , .{ dep_entries_size + src_hash_deps_size + nav_val_deps_size + nav_ty_deps_size + - func_ies_deps_size + type_layout_deps_size + struct_defaults_deps_size + zon_file_deps_size + + func_ies_deps_size + type_layout_deps_size + zon_file_deps_size + embed_file_deps_size + namespace_deps_size + namespace_name_deps_size, dep_entries_len, dep_entries_size, @@ -10694,8 +10663,6 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void { func_ies_deps_size, type_layout_deps_len, type_layout_deps_size, - struct_defaults_deps_len, - struct_defaults_deps_size, zon_file_deps_len, zon_file_deps_size, embed_file_deps_len, @@ -11136,7 +11103,7 @@ pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator, const info = extraData(extra_list, Tag.FuncInstance, data); const gop = try instances.getOrPut(arena, info.generic_owner); - if (!gop.found_existing) gop.value_ptr.* = .{}; + if (!gop.found_existing) gop.value_ptr.* = .empty; try gop.value_ptr.append( arena, @@ -12969,50 +12936,6 @@ pub fn setWantTypeLayout(ip: *InternPool, io: Io, container_type: Index) bool { } } -/// Like `setWantTypeLayout`, but for the default field values of a struct (so this sets the -/// `want_defaults` flag rather than the `want_layout` flag). -pub fn setWantStructDefaults(ip: *InternPool, io: Io, struct_type: Index) bool { - const unwrapped_index = struct_type.unwrap(ip); - - const local = ip.getLocal(unwrapped_index.tid); - local.mutate.extra.mutex.lockUncancelable(io); - defer local.mutate.extra.mutex.unlock(io); - - const extra_items = local.shared.extra.view().items(.@"0"); - const item = unwrapped_index.getItem(ip); - switch (item.tag) { - .type_struct_packed_auto, - .type_struct_packed_explicit, - .type_struct_packed_auto_defaults, - .type_struct_packed_explicit_defaults, - => { - const bits: *Tag.TypeStructPacked.Bits = @ptrCast(&extra_items[ - item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "bits").? - ]); - if (bits.want_defaults) { - return false; - } else { - bits.want_defaults = true; - return true; - } - }, - - .type_struct => { - const flags: *Tag.TypeStruct.Flags = @ptrCast(&extra_items[ - item.data + std.meta.fieldIndex(Tag.TypeStruct, "flags").? - ]); - if (flags.want_defaults) { - return false; - } else { - flags.want_defaults = true; - return true; - } - }, - - else => unreachable, - } -} - /// Like `setWantTypeLayout`, but for runtime analysis of a function body, using the /// `FuncAnalysis.want_runtime_analysis` flag. pub fn setWantRuntimeFnAnalysis(ip: *InternPool, io: Io, func_index: Index) bool { diff --git a/src/Sema.zig b/src/Sema.zig index cd6625fdaba233ed72cdbd31b9d79617dd40267d..276a06a938b0c868a183ee2626db940d22cf866d 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -4519,10 +4519,6 @@ fn validateStructInit( if (explicit) continue; if (struct_ty.structFieldIsComptime(i, zcu)) continue; - if (!struct_ty.isTuple(zcu)) { - try sema.ensureStructDefaultsResolved(struct_ty, init_src); - } - const default_val = struct_ty.structFieldDefaultValue(i, zcu) orelse { const field_name = struct_ty.structFieldName(i, zcu).unwrap() orelse { const template = "missing tuple field with index {d}"; @@ -5180,9 +5176,9 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError var label: Block.Label = .{ .zir_block = inst, .merges = .{ - .src_locs = .{}, - .results = .{}, - .br_list = .{}, + .src_locs = .empty, + .results = .empty, + .br_list = .empty, .block_inst = block_inst, }, }; @@ -5254,7 +5250,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr .parent = parent_block, .sema = sema, .namespace = parent_block.namespace, - .instructions = .{}, + .instructions = .empty, .inlining = parent_block.inlining, .comptime_reason = .{ .reason = .{ .src = src, @@ -5389,9 +5385,9 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro var label: Block.Label = .{ .zir_block = inst, .merges = .{ - .src_locs = .{}, - .results = .{}, - .br_list = .{}, + .src_locs = .empty, + .results = .empty, + .br_list = .empty, .block_inst = block_inst, }, }; @@ -5400,7 +5396,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro .parent = parent_block, .sema = sema, .namespace = parent_block.namespace, - .instructions = .{}, + .instructions = .empty, .label = &label, .inlining = parent_block.inlining, .comptime_reason = parent_block.comptime_reason, @@ -5839,7 +5835,6 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void { .nav_val, .nav_ty, .type_layout, - .struct_defaults, .memoized_state, => return, // does nothing outside a function }; @@ -5858,7 +5853,6 @@ fn zirDisableIntrinsics(sema: *Sema) CompileError!void { .nav_val, .nav_ty, .type_layout, - .struct_defaults, .memoized_state, => return, // does nothing outside a function }; @@ -6870,7 +6864,7 @@ fn analyzeCall( .parent = null, .sema = sema, .namespace = fn_nav.analysis.?.namespace, - .instructions = .{}, + .instructions = .empty, .inlining = &generic_inlining, .src_base_inst = fn_nav.analysis.?.zir_index, .type_name_ctx = fn_nav.fqn, @@ -7067,7 +7061,7 @@ fn analyzeCall( }); if (func_ty_info.cc == .auto) { switch (sema.owner.unwrap()) { - .@"comptime", .nav_ty, .nav_val, .type_layout, .struct_defaults, .memoized_state => {}, + .@"comptime", .nav_ty, .nav_val, .type_layout, .memoized_state => {}, .func => |owner_func| ip.funcSetHasErrorTrace(io, owner_func, true), } } @@ -7382,7 +7376,7 @@ fn analyzeCall( .parent = null, .sema = sema, .namespace = fn_nav.analysis.?.namespace, - .instructions = .{}, + .instructions = .empty, .inlining = &inlining, .is_typeof = block.is_typeof, .comptime_reason = if (block.isComptime()) .inlining_parent else null, @@ -9945,9 +9939,9 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp var label: Block.Label = .{ .zir_block = inst, .merges = .{ - .src_locs = .{}, - .results = .{}, - .br_list = .{}, + .src_locs = .empty, + .results = .empty, + .br_list = .empty, .block_inst = block_inst, }, }; @@ -10100,9 +10094,9 @@ fn zirSwitchBlock( var label: Block.Label = .{ .zir_block = inst, .merges = .{ - .src_locs = .{}, - .results = .{}, - .br_list = .{}, + .src_locs = .empty, + .results = .empty, + .br_list = .empty, .block_inst = block_inst, }, }; @@ -16864,7 +16858,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .struct_type => ip.loadStructType(ty.toIntern()), else => unreachable, }; - try sema.ensureStructDefaultsResolved(ty, src); // can't do this sooner, since it's not allowed on tuples struct_field_vals = try gpa.alloc(InternPool.Index, struct_type.field_types.len); for (struct_field_vals, 0..) |*field_val, field_index| { @@ -17122,7 +17115,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr .parent = block, .sema = sema, .namespace = block.namespace, - .instructions = .{}, + .instructions = .empty, .inlining = block.inlining, .comptime_reason = null, .is_typeof = true, @@ -17190,7 +17183,7 @@ fn zirTypeofPeer( .parent = block, .sema = sema, .namespace = block.namespace, - .instructions = .{}, + .instructions = .empty, .inlining = block.inlining, .comptime_reason = null, .is_typeof = true, @@ -17764,9 +17757,9 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label .label = .{ .zir_block = dest_block, .merges = .{ - .src_locs = .{}, - .results = .{}, - .br_list = .{}, + .src_locs = .empty, + .results = .empty, + .br_list = .empty, .block_inst = new_block_inst, }, }, @@ -17774,7 +17767,7 @@ fn ensurePostHoc(sema: *Sema, block: *Block, dest_block: Zir.Inst.Index) !*Label .parent = block, .sema = sema, .namespace = block.namespace, - .instructions = .{}, + .instructions = .empty, .label = &labeled_block.label, .inlining = block.inlining, .comptime_reason = block.comptime_reason, @@ -18753,8 +18746,6 @@ fn finishStructInit( continue; } - try sema.ensureStructDefaultsResolved(struct_ty, init_src); - const field_default: InternPool.Index = d: { if (struct_type.field_defaults.len == 0) break :d .none; break :d struct_type.field_defaults.get(ip)[i]; @@ -19420,7 +19411,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { .func => |func| if (ip.funcAnalysisUnordered(func).has_error_trace and block.ownerModule().error_tracing) { return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty); }, - .@"comptime", .nav_ty, .nav_val, .type_layout, .struct_defaults, .memoized_state => {}, + .@"comptime", .nav_ty, .nav_val, .type_layout, .memoized_state => {}, } return Air.internedToRef(try pt.intern(.{ .opt = .{ .ty = opt_ptr_stack_trace_ty.toIntern(), @@ -24738,7 +24729,7 @@ fn zirBuiltinExtern( // So, for now, just use our containing `declaration`. .zir_index = switch (sema.owner.unwrap()) { .@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index, - .type_layout, .struct_defaults => |owner_ty| Type.fromInterned(owner_ty).typeDeclInstAllowGeneratedTag(zcu).?, + .type_layout => |owner_ty| Type.fromInterned(owner_ty).typeDeclInstAllowGeneratedTag(zcu).?, .memoized_state => unreachable, .nav_ty, .nav_val => |nav| ip.getNav(nav).analysis.?.zir_index, .func => |func| zir_index: { @@ -25230,7 +25221,7 @@ fn getPanicIdFunc(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !In try sema.ensureMemoizedStateResolved(src, .panic); const panic_fn_index = zcu.builtin_decl_values.get(panic_id.toBuiltin()); switch (sema.owner.unwrap()) { - .@"comptime", .nav_ty, .nav_val, .type_layout, .struct_defaults, .memoized_state => {}, + .@"comptime", .nav_ty, .nav_val, .type_layout, .memoized_state => {}, .func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(io, owner_func, true), } return panic_fn_index; @@ -25250,7 +25241,7 @@ fn addSafetyCheck( .parent = parent_block, .sema = sema, .namespace = parent_block.namespace, - .instructions = .{}, + .instructions = .empty, .inlining = parent_block.inlining, .comptime_reason = null, .src_base_inst = parent_block.src_base_inst, @@ -25344,7 +25335,7 @@ fn addSafetyCheckUnwrapError( .parent = parent_block, .sema = sema, .namespace = parent_block.namespace, - .instructions = .{}, + .instructions = .empty, .inlining = parent_block.inlining, .comptime_reason = null, .src_base_inst = parent_block.src_base_inst, @@ -25449,7 +25440,7 @@ fn addSafetyCheckCall( .parent = parent_block, .sema = sema, .namespace = parent_block.namespace, - .instructions = .{}, + .instructions = .empty, .inlining = parent_block.inlining, .comptime_reason = null, .src_base_inst = parent_block.src_base_inst, @@ -33859,7 +33850,6 @@ const ComptimeStoreResult = @import("Sema/comptime_ptr_access.zig").ComptimeStor pub const type_resolution = @import("Sema/type_resolution.zig"); pub const ensureLayoutResolved = type_resolution.ensureLayoutResolved; -pub const ensureStructDefaultsResolved = type_resolution.ensureStructDefaultsResolved; pub fn getBuiltinType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) SemaError!Type { assert(decl.kind() == .type); diff --git a/src/Sema/LowerZon.zig b/src/Sema/LowerZon.zig index 71256ae44ddc4e6283171172bfb0cdda3f8eb50e..b755c5daaae8f6ed6688b2529ad563f347b445d4 100644 --- a/src/Sema/LowerZon.zig +++ b/src/Sema/LowerZon.zig @@ -770,7 +770,6 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool const ip = &pt.zcu.intern_pool; try self.sema.ensureLayoutResolved(res_ty, self.import_loc); - try self.sema.ensureStructDefaultsResolved(res_ty, self.import_loc); const struct_info = self.sema.pt.zcu.typeToStruct(res_ty).?; const fields: @FieldType(Zoir.Node, "struct_literal") = switch (node.get(self.file.zoir.?)) { diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig index 50f0f7e3156921fa42cae5e80768d067e245b941..2a28d7aa0456e2cdb0d545ff7208ca4e0e615c4f 100644 --- a/src/Sema/type_resolution.zig +++ b/src/Sema/type_resolution.zig @@ -85,30 +85,6 @@ pub fn ensureLayoutResolved(sema: *Sema, ty: Type, src: LazySrcLoc) SemaError!vo } } -/// Asserts that `ty` is a non-tuple `struct` type, and ensures that its fields' default values -/// are resolved. Adds incremental dependencies tracking the required type resolution. -/// -/// It is not necessary to call this function to query the values of comptime fields: those values -/// are available from type *layout* resolution, see `ensureLayoutResolved`. -pub fn ensureStructDefaultsResolved(sema: *Sema, ty: Type, src: LazySrcLoc) SemaError!void { - const pt = sema.pt; - const zcu = pt.zcu; - const ip = &zcu.intern_pool; - assert(ip.indexToKey(ty.toIntern()) == .struct_type); - - try sema.declareDependency(.{ .struct_defaults = ty.toIntern() }); - try sema.addReferenceEntry(null, src, .wrap(.{ .struct_defaults = ty.toIntern() })); - if (zcu.analysis_in_progress.contains(.wrap(.{ .struct_defaults = ty.toIntern() }))) { - // TODO: better error message - return sema.failWithOwnedErrorMsg(null, try sema.errMsg( - ty.srcLoc(zcu), - "struct '{f}' depends on itself", - .{ty.fmt(pt)}, - )); - } - try pt.ensureStructDefaultsUpToDate(ty); -} - /// Asserts that `struct_ty` is a non-packed non-tuple struct, and that `sema.owner` is that type. /// This function *does* register the `src_hash` dependency on the struct. pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { @@ -129,7 +105,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { .parent = null, .sema = sema, .namespace = struct_obj.namespace, - .instructions = .{}, + .instructions = .empty, .inlining = null, .comptime_reason = undefined, // always set before using `block` .src_base_inst = struct_obj.zir_index, @@ -168,6 +144,13 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { @memset(struct_obj.field_is_comptime_bits.getAll(ip), 0); const zir_struct = sema.code.getStructDecl(zir_index); + + // If we have any default values to resolve, we'll need to map the struct decl instruction + // to the result type. + if (zir_struct.field_default_body_lens != null) { + try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index}); + } + var field_it = zir_struct.iterateFields(); while (field_it.next()) |zir_field| { { @@ -182,18 +165,16 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { struct_obj.field_is_comptime_bits.getAll(ip)[bit_bag_index] |= mask; } - { + const field_ty: Type = field_ty: { const field_ty_src = block.src(.{ .container_field_type = zir_field.idx }); - const field_ty: Type = field_ty: { - block.comptime_reason = .{ .reason = .{ - .src = field_ty_src, - .r = .{ .simple = .struct_field_types }, - } }; - const type_ref = try sema.resolveInlineBody(&block, zir_field.type_body, zir_index); - break :field_ty try sema.analyzeAsType(&block, field_ty_src, .struct_field_types, type_ref); - }; - struct_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern(); - } + block.comptime_reason = .{ .reason = .{ + .src = field_ty_src, + .r = .{ .simple = .struct_field_types }, + } }; + const type_ref = try sema.resolveInlineBody(&block, zir_field.type_body, zir_index); + break :field_ty try sema.analyzeAsType(&block, field_ty_src, .struct_field_types, type_ref); + }; + struct_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern(); if (struct_obj.field_aligns.len == 0) { assert(zir_field.align_body == null); @@ -210,6 +191,31 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { }; struct_obj.field_aligns.get(ip)[zir_field.idx] = field_align; } + + if (struct_obj.field_defaults.len == 0) { + assert(zir_field.default_body == null); + } else { + const field_default_src = block.src(.{ .container_field_value = zir_field.idx }); + const field_default: InternPool.Index = d: { + block.comptime_reason = .{ .reason = .{ + .src = field_default_src, + .r = .{ .simple = .struct_field_default_value }, + } }; + const default_body = zir_field.default_body orelse break :d .none; + // Provide the result type + sema.inst_map.putAssumeCapacity(zir_index, .fromType(field_ty)); + defer assert(sema.inst_map.remove(zir_index)); + const uncoerced_default_val = try sema.resolveInlineBody(&block, default_body, zir_index); + const coerced_default_val = try sema.coerce(&block, field_ty, uncoerced_default_val, field_default_src); + const default_val = try sema.resolveConstValue(&block, field_default_src, coerced_default_val, null); + if (default_val.canMutateComptimeVarState(zcu)) { + const field_name = struct_obj.field_names.get(ip)[zir_field.idx]; + return sema.failWithContainsReferenceToComptimeVar(&block, field_default_src, field_name, "field default value", default_val); + } + break :d default_val.toIntern(); + }; + struct_obj.field_defaults.get(ip)[zir_field.idx] = field_default; + } } } @@ -357,11 +363,6 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { struct_align, class, ); - - if (any_comptime_fields and !struct_obj.is_reified) { - // We also resolve field inits in this case. MLUGG TODO: this sucks, see TODO in resolveStructDefaults - return resolveStructDefaultsInner(sema, &block, &struct_obj); - } } /// Asserts that `struct_ty` is a packed struct, and that `sema.owner` is that type. @@ -465,105 +466,6 @@ fn resolvePackedStructLayout( ); } -/// Asserts that `struct_ty` is a non-tuple struct, and that `sema.owner` is that type. -/// This function *does* register the `src_hash` dependency on the struct. -pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void { - const pt = sema.pt; - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const ip = &zcu.intern_pool; - - assert(sema.owner.unwrap().struct_defaults == struct_ty.toIntern()); - - try sema.ensureLayoutResolved(struct_ty, struct_ty.srcLoc(zcu)); - - const struct_obj = ip.loadStructType(struct_ty.toIntern()); - assert(struct_obj.want_defaults); - - if (struct_obj.is_reified) { - // `Sema.zirReifyStruct` has already populated the default field values *and* (by loading - // the default values from pointers) validated their types, so we have nothing to do. We - // don't even need to mark any dependencies. - return; - } - - try sema.declareDependency(.{ .src_hash = struct_obj.zir_index }); - - if (struct_obj.field_defaults.len == 0) { - // The struct has no default field values, so the slice has been omitted. - return; - } - - for (struct_obj.field_is_comptime_bits.getAll(ip)) |bit_bag| { - if (bit_bag != 0) { - // There is a comptime field, so layout resolution already filled in the defaults for us! - // MLUGG TODO: perhaps a better idea would be for layout resolution to populate only the defaults *for comptime fields*. - return; - } - } - - var block: Block = .{ - .parent = null, - .sema = sema, - .namespace = struct_obj.namespace, - .instructions = .{}, - .inlining = null, - .comptime_reason = undefined, // always set before using `block` - .src_base_inst = struct_obj.zir_index, - .type_name_ctx = struct_obj.name, - }; - defer block.instructions.deinit(gpa); - - return resolveStructDefaultsInner(sema, &block, &struct_obj); -} -/// MLUGG TODO: i dislike this, see the 'TODO' in the prev func -fn resolveStructDefaultsInner( - sema: *Sema, - block: *Block, - struct_obj: *const InternPool.LoadedStructType, -) CompileError!void { - const pt = sema.pt; - const zcu = pt.zcu; - const comp = zcu.comp; - const gpa = comp.gpa; - const ip = &zcu.intern_pool; - - // We'll need to map the struct decl instruction to provide result types - const zir_index = struct_obj.zir_index.resolve(ip) orelse return error.AnalysisFail; - try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index}); - - const field_types = struct_obj.field_types.get(ip); - - const zir_struct = sema.code.getStructDecl(zir_index); - var field_it = zir_struct.iterateFields(); - while (field_it.next()) |zir_field| { - const default_val_src = block.src(.{ .container_field_value = zir_field.idx }); - block.comptime_reason = .{ .reason = .{ - .src = default_val_src, - .r = .{ .simple = .struct_field_default_value }, - } }; - const default_body = zir_field.default_body orelse { - struct_obj.field_defaults.get(ip)[zir_field.idx] = .none; - continue; - }; - const field_ty: Type = .fromInterned(field_types[zir_field.idx]); - const uncoerced = ref: { - // Provide the result type - sema.inst_map.putAssumeCapacity(zir_index, .fromIntern(field_ty.toIntern())); - defer assert(sema.inst_map.remove(zir_index)); - break :ref try sema.resolveInlineBody(block, default_body, zir_index); - }; - const coerced = try sema.coerce(block, field_ty, uncoerced, default_val_src); - const default_val = try sema.resolveConstValue(block, default_val_src, coerced, null); - if (default_val.canMutateComptimeVarState(zcu)) { - const field_name = struct_obj.field_names.get(ip)[zir_field.idx]; - return sema.failWithContainsReferenceToComptimeVar(block, default_val_src, field_name, "field default value", default_val); - } - struct_obj.field_defaults.get(ip)[zir_field.idx] = default_val.toIntern(); - } -} - /// This logic must be kept in sync with `Type.getUnionLayout`. pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { const pt = sema.pt; @@ -583,7 +485,7 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { .parent = null, .sema = sema, .namespace = union_obj.namespace, - .instructions = .{}, + .instructions = .empty, .inlining = null, .comptime_reason = undefined, // always set before using `block` .src_base_inst = union_obj.zir_index, @@ -1048,7 +950,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void { .parent = null, .sema = sema, .namespace = enum_obj.namespace, - .instructions = .{}, + .instructions = .empty, .inlining = null, .comptime_reason = undefined, // always set before using `block` .src_base_inst = tracked_inst, @@ -1287,8 +1189,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void { } } - // MLUGG TODO: fate of this line rests on whether comptime_int is a valid int tag type - if (enum_obj.nonexhaustive and int_tag_ty.toIntern() != .comptime_int_type) { + if (enum_obj.nonexhaustive) { const fields_len = enum_obj.field_names.len; if (fields_len >= 1 and std.math.log2_int(u64, fields_len) == int_tag_ty.bitSize(zcu)) { return sema.fail(&block, block.nodeOffset(.zero), "non-exhaustive enum specifies every value", .{}); diff --git a/src/Zcu.zig b/src/Zcu.zig index aedbf7043c32aa83d8e7988d8bd3bb2304476632..9ae8e47a754aaf88121af4c800f2601b38fe0589 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -3122,7 +3122,6 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { .nav_val => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_val = nav }), .nav_ty => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav }), .type_layout => |ty| try zcu.markPoDependeeUpToDate(.{ .type_layout = ty }), - .struct_defaults => |ty| try zcu.markPoDependeeUpToDate(.{ .struct_defaults = ty }), .func => |func| try zcu.markPoDependeeUpToDate(.{ .func_ies = func }), .memoized_state => |stage| try zcu.markPoDependeeUpToDate(.{ .memoized_state = stage }), } @@ -3138,7 +3137,6 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni .nav_val => |nav| .{ .nav_val = nav }, .nav_ty => |nav| .{ .nav_ty = nav }, .type_layout => |ty| .{ .type_layout = ty }, - .struct_defaults => |ty| .{ .struct_defaults = ty }, .func => |func_index| .{ .func_ies = func_index }, .memoized_state => |stage| .{ .memoized_state = stage }, }; @@ -4116,7 +4114,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R const other: AnalUnit = .wrap(switch (unit.unwrap()) { .nav_val => |n| .{ .nav_ty = n }, .nav_ty => |n| .{ .nav_val = n }, - .@"comptime", .type_layout, .struct_defaults, .func, .memoized_state => break :queue_paired, + .@"comptime", .type_layout, .func, .memoized_state => break :queue_paired, }); const gop = try units.getOrPut(gpa, other); if (gop.found_existing) break :queue_paired; @@ -4273,7 +4271,7 @@ fn formatAnalUnit(data: FormatAnalUnit, writer: *Io.Writer) Io.Writer.Error!void } }, .nav_val, .nav_ty => |nav, tag| return writer.print("{t}('{f}' [{}])", .{ tag, ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }), - .type_layout, .struct_defaults => |ty, tag| return writer.print("{t}('{f}' [{}])", .{ tag, Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }), + .type_layout => |ty, tag| return writer.print("{t}('{f}' [{}])", .{ tag, Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }), .func => |func| { const nav = zcu.funcInfo(func).owner_nav; return writer.print("func('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(func) }); @@ -4299,7 +4297,7 @@ fn formatDependee(data: FormatDependee, writer: *Io.Writer) Io.Writer.Error!void const fqn = ip.getNav(nav).fqn; return writer.print("{t}('{f}')", .{ tag, fqn.fmt(ip) }); }, - .type_layout, .struct_defaults => |ip_index, tag| { + .type_layout => |ip_index, tag| { const name = Type.fromInterned(ip_index).containerTypeName(ip); return writer.print("{t}('{f}')", .{ tag, name.fmt(ip) }); }, diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 46e275045ac39d580acc8bf33dd45e671d19d39f..7de74743c3540370784ee7e26d50f052fa4a679e 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -865,7 +865,7 @@ fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage) .parent = null, .sema = &sema, .namespace = std_namespace, - .instructions = .{}, + .instructions = .empty, .inlining = null, .comptime_reason = .{ .reason = .{ .src = src, @@ -1014,7 +1014,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu .parent = null, .sema = &sema, .namespace = comptime_unit.namespace, - .instructions = .{}, + .instructions = .empty, .inlining = null, .comptime_reason = .{ .reason = .{ .src = .{ @@ -1152,109 +1152,6 @@ pub fn ensureTypeLayoutUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void }; } -/// Ensures that the default values of the given "declared" (not reified) `struct` type are fully -/// up-to-date, performing re-analysis if necessary. Asserts that `ty` is a struct (not tuple) type. -/// Returns `error.AnalysisFail` if an analysis error is encountered while resolving the default -/// field values; the caller is free to ignore this, since the error is already registered. -pub fn ensureStructDefaultsUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void { - const tracy = trace(@src()); - defer tracy.end(); - - const zcu = pt.zcu; - const gpa = zcu.gpa; - - assert(ty.zigTypeTag(zcu) == .@"struct"); - assert(!ty.isTuple(zcu)); - - const anal_unit: AnalUnit = .wrap(.{ .struct_defaults = ty.toIntern() }); - - log.debug("ensureStructDefaultsUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)}); - - assert(!zcu.analysis_in_progress.contains(anal_unit)); - - const was_outdated = zcu.outdated.swapRemove(anal_unit) or - zcu.potentially_outdated.swapRemove(anal_unit) or - zcu.intern_pool.setWantStructDefaults(zcu.comp.io, ty.toIntern()); - - if (was_outdated) { - _ = zcu.outdated_ready.swapRemove(anal_unit); - // `was_outdated` is true in the initial update, so this isn't a `dev.check`. - if (dev.env.supports(.incremental)) { - zcu.deleteUnitExports(anal_unit); - zcu.deleteUnitReferences(anal_unit); - zcu.deleteUnitCompileLogs(anal_unit); - if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| { - kv.value.destroy(gpa); - } - _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); - zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit); - } - // For types, we already know that we have to invalidate all dependees. - // TODO: we actually *could* detect whether everything was the same. should we bother? - try zcu.markDependeeOutdated(.marked_po, .{ .struct_defaults = ty.toIntern() }); - } else { - // We can trust the current information about this unit. - if (zcu.failed_analysis.contains(anal_unit)) return error.AnalysisFail; - if (zcu.transitive_failed_analysis.contains(anal_unit)) return error.AnalysisFail; - return; - } - - if (zcu.comp.debugIncremental()) { - const info = try zcu.incremental_debug_state.getUnitInfo(gpa, anal_unit); - info.last_update_gen = zcu.generation; - info.deps.clearRetainingCapacity(); - } - - const unit_tracking = zcu.trackUnitSema(ty.containerTypeName(&zcu.intern_pool).toSlice(&zcu.intern_pool), null); - defer unit_tracking.end(zcu); - - try zcu.analysis_in_progress.put(gpa, anal_unit, {}); - defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); - - var analysis_arena: std.heap.ArenaAllocator = .init(gpa); - defer analysis_arena.deinit(); - - var comptime_err_ret_trace: std.array_list.Managed(Zcu.LazySrcLoc) = .init(gpa); - defer comptime_err_ret_trace.deinit(); - - const zir = zcu.namespacePtr(ty.getNamespaceIndex(zcu)).fileScope(zcu).zir.?; - - var sema: Sema = .{ - .pt = pt, - .gpa = gpa, - .arena = analysis_arena.allocator(), - .code = zir, - .owner = anal_unit, - .func_index = .none, - .func_is_naked = false, - .fn_ret_ty = .void, - .fn_ret_ty_ies = null, - .comptime_err_ret_trace = &comptime_err_ret_trace, - }; - defer sema.deinit(); - - Sema.type_resolution.resolveStructDefaults(&sema, ty) catch |err| switch (err) { - error.AnalysisFail => { - if (!zcu.failed_analysis.contains(anal_unit)) { - // If this unit caused the error, it would have an entry in `failed_analysis`. - // Since it does not, this must be a transitive failure. - try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); - log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)}); - } - return error.AnalysisFail; - }, - error.OutOfMemory, - error.Canceled, - => |e| return e, - error.ComptimeReturn => unreachable, - error.ComptimeBreak => unreachable, - }; - - sema.flushExports() catch |err| switch (err) { - error.OutOfMemory => |e| return e, - }; -} - /// Ensures that the resolved value of the given `Nav` is fully up-to-date, performing re-analysis /// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is /// free to ignore this, since the error is already registered. @@ -1452,7 +1349,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr .parent = null, .sema = &sema, .namespace = old_nav.analysis.?.namespace, - .instructions = .{}, + .instructions = .empty, .inlining = null, .comptime_reason = undefined, // set below .src_base_inst = old_nav.analysis.?.zir_index, @@ -1831,7 +1728,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr .parent = null, .sema = &sema, .namespace = old_nav.analysis.?.namespace, - .instructions = .{}, + .instructions = .empty, .inlining = null, .comptime_reason = undefined, // set below .src_base_inst = old_nav.analysis.?.zir_index, @@ -3078,7 +2975,7 @@ fn analyzeFuncBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.Sem .parent = null, .sema = &sema, .namespace = decl_nav.analysis.?.namespace, - .instructions = .{}, + .instructions = .empty, .inlining = null, .comptime_reason = null, .src_base_inst = decl_nav.analysis.?.zir_index, @@ -3327,7 +3224,7 @@ pub fn processExports(pt: Zcu.PerThread) !void { break :gop .{ gop.value_ptr, gop.found_existing }; }, }; - if (!found_existing) value_ptr.* = .{}; + if (!found_existing) value_ptr.* = .empty; try value_ptr.append(gpa, export_idx); } @@ -3356,7 +3253,7 @@ pub fn processExports(pt: Zcu.PerThread) !void { break :gop .{ gop.value_ptr, gop.found_existing }; }, }; - if (!found_existing) value_ptr.* = .{}; + if (!found_existing) value_ptr.* = .empty; try value_ptr.append(gpa, @enumFromInt(export_idx)); } } @@ -4353,10 +4250,7 @@ pub fn resolveTypeForCodegen(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void { }, .@"struct" => switch (ip.indexToKey(ty.toIntern())) { - .struct_type => { - try pt.ensureTypeLayoutUpToDate(ty); - try pt.ensureStructDefaultsUpToDate(ty); - }, + .struct_type => try pt.ensureTypeLayoutUpToDate(ty), .tuple_type => |tuple| for (0..tuple.types.len) |i| { const field_is_comptime = tuple.values.get(ip)[i] != .none; if (field_is_comptime) continue; diff --git a/src/codegen/c/Type.zig b/src/codegen/c/Type.zig index 3ee61a90b656759d0848af6f74e0ab313f9c34c2..f28dd48a1775ad0f4deea189ba22121b0c62af10 100644 --- a/src/codegen/c/Type.zig +++ b/src/codegen/c/Type.zig @@ -1054,13 +1054,13 @@ pub const Pool = struct { }; pub const empty: Pool = .{ - .map = .{}, - .items = .{}, - .extra = .{}, + .map = .empty, + .items = .empty, + .extra = .empty, - .string_map = .{}, - .string_indices = .{}, - .string_bytes = .{}, + .string_map = .empty, + .string_indices = .empty, + .string_bytes = .empty, }; pub fn init(pool: *Pool, allocator: std.mem.Allocator) !void { diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index ebdd1f20989a897c831738289772906a98afe0fd..d17b0b7b17d4bd28db40bf57f561f02a19d4c988 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -775,7 +775,7 @@ pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutO const gop = try dupes.getOrPut(self.symbols_resolver.items[i]); if (!gop.found_existing) { - gop.value_ptr.* = .{}; + gop.value_ptr.* = .empty; } try gop.value_ptr.append(elf_file.base.comp.gpa, self.index); } diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 96db16681ca6a89c0570ab14f1ae09a7e6d5d91b..9bf352c1b10bbf2ee85215dcba1f4225c5e843b9 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -84,7 +84,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { const ptr_size = elf_file.ptrWidthBytes(); try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) }); // null input section - try self.relocs.append(gpa, .{}); // null relocs section + try self.relocs.append(gpa, .empty); // null relocs section try self.strtab.buffer.append(gpa, 0); { @@ -546,7 +546,7 @@ fn newAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Atom.Index { atom_ptr.name_offset = name_off; const relocs_index: u32 = @intCast(self.relocs.items.len); - self.relocs.addOneAssumeCapacity().* = .{}; + self.relocs.addOneAssumeCapacity().* = .empty; atom_ptr.relocs_section_index = relocs_index; return index; @@ -730,7 +730,7 @@ pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{O const gop = try dupes.getOrPut(self.symbols_resolver.items[i]); if (!gop.found_existing) { - gop.value_ptr.* = .{}; + gop.value_ptr.* = .empty; } try gop.value_ptr.append(elf_file.base.comp.gpa, self.index); } diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index fc3ac0fca8f5588ad67cd10c9a7a563f16a2aec4..b17dc099077f15af9be3f6913419b0a4507eb7d9 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -3,7 +3,7 @@ data: std.ArrayList(u8) = .empty, basename: []const u8, index: File.Index, -symtab: std.MultiArrayList(Nlist) = .{}, +symtab: std.MultiArrayList(Nlist) = .empty, strtab: StringTable = .{}, symbols: std.ArrayList(Symbol) = .empty, @@ -29,7 +29,7 @@ uavs: UavTable = .{}, tlv_initializers: TlvInitializerTable = .{}, /// A table of relocations. -relocs: RelocationTable = .{}, +relocs: RelocationTable = .empty, dwarf: ?Dwarf = null, diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index af800d77d263b0a99a43833494ad90884a2dd260..a9e7f35c2118d313cdcd40d99a4dd6aa1141cea5 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -78,7 +78,7 @@ export_table: bool, /// Output name of the file name: []const u8, /// List of relocatable files to be linked into the final binary. -objects: std.ArrayList(Object) = .{}, +objects: std.ArrayList(Object) = .empty, func_types: std.AutoArrayHashMapUnmanaged(FunctionType, void) = .empty, /// Provides a mapping of both imports and provided functions to symbol name. @@ -278,7 +278,7 @@ any_tls_relocs: bool = false, any_passive_inits: bool = false, /// All MIR instructions for all Zcu functions. -mir_instructions: std.MultiArrayList(Mir.Inst) = .{}, +mir_instructions: std.MultiArrayList(Mir.Inst) = .empty, /// Corresponds to `mir_instructions`. mir_extra: std.ArrayList(u32) = .empty, /// All local types for all Zcu functions. diff --git a/src/main.zig b/src/main.zig index bb36d00376d5410ed4612feab04b9128871bacd8..7167cae4e29b3e36b4c46589e0be178f1e4f501b 100644 --- a/src/main.zig +++ b/src/main.zig @@ -979,7 +979,7 @@ fn buildOutputType( .dirs = undefined, .object_format = null, .dynamic_linker = null, - .modules = .{}, + .modules = .empty, .opts = .{ .is_test = switch (arg_mode) { .zig_test, .zig_test_obj => true, @@ -1006,18 +1006,18 @@ fn buildOutputType( .windows_libs = .empty, .link_inputs = .empty, - .c_source_files = .{}, - .rc_source_files = .{}, + .c_source_files = .empty, + .rc_source_files = .empty, - .llvm_m_args = .{}, + .llvm_m_args = .empty, .sysroot = null, - .lib_directories = .{}, // populated by createModule() - .lib_dir_args = .{}, // populated from CLI arg parsing + .lib_directories = .empty, // populated by createModule() + .lib_dir_args = .empty, // populated from CLI arg parsing .libc_installation = null, .want_native_include_dirs = false, - .frameworks = .{}, - .framework_dirs = .{}, - .rpath_list = .{}, + .frameworks = .empty, + .framework_dirs = .empty, + .rpath_list = .empty, .each_lib_rpath = null, .libc_paths_file = EnvVar.ZIG_LIBC.get(environ_map), .native_system_include_paths = &.{}, -- 2.54.0 From 38fdced8bb255d3460afefaacce9dc89dab97def Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sat, 31 Jan 2026 10:19:12 +0000 Subject: [PATCH 13/79] Sema: small cleanup --- src/Sema/type_resolution.zig | 118 ++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 58 deletions(-) diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig index 2a28d7aa0456e2cdb0d545ff7208ca4e0e615c4f..a7b862289b6de72b34e2739a684effcddc6a60fc 100644 --- a/src/Sema/type_resolution.zig +++ b/src/Sema/type_resolution.zig @@ -493,65 +493,67 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { }; defer block.instructions.deinit(gpa); - // MLUGG TODO: this is fucking ugly bro - const explicit_enum_tag_ty: ?Type = if (union_obj.is_reified) ty: { - break :ty switch (union_obj.enum_tag_mode) { - .explicit => .fromInterned(union_obj.enum_tag_type), - .auto => null, - }; - } else ty: { - const zir_union = sema.code.getUnionDecl(zir_index); - if (zir_union.kind != .tagged_explicit) { - break :ty null; // enum tag type will be automatically generated - } - // Explicitly specified, so evaluate the enum tag type expression. - const tag_type_body = zir_union.arg_type_body.?; - const tag_type_src = block.src(.container_arg); - block.comptime_reason = .{ .reason = .{ - .src = tag_type_src, - .r = .{ .simple = .union_enum_tag_type }, - } }; - const type_ref = try sema.resolveInlineBody(&block, tag_type_body, zir_index); - break :ty try sema.analyzeAsType(&block, tag_type_src, .union_enum_tag_type, type_ref); - }; - const enum_tag_ty: Type = if (explicit_enum_tag_ty) |enum_tag_ty| ty: { - if (enum_tag_ty.zigTypeTag(zcu) != .@"enum") return sema.fail( - &block, - block.src(.container_arg), - "expected enum tag type, found '{f}'", - .{enum_tag_ty.fmt(pt)}, - ); - break :ty enum_tag_ty; - } else switch (try ip.getGeneratedEnumTagType(gpa, io, pt.tid, .{ - .union_type = union_ty.toIntern(), - // MLUGG TODO: a bit hacky icl - .int_tag_mode = mode: { - if (union_obj.is_reified) break :mode .auto; - const zir_union = sema.code.getUnionDecl(zir_index); - if (zir_union.kind != .tagged_enum_explicit) break :mode .auto; - break :mode .explicit; + const enum_tag_ty: Type = switch (union_obj.enum_tag_mode) { + .explicit => validated_tag_ty: { + // If the union is reified, its enum tag type is already populated. If the union is + // declared, we need to evaluate the enum tag type expression (the `E` in `union(E)`). + const tag_ty: Type = switch (union_obj.is_reified) { + true => .fromInterned(union_obj.enum_tag_type), + false => tag_ty: { + const zir_union = sema.code.getUnionDecl(zir_index); + assert(zir_union.kind == .tagged_explicit); // `Zcu.mapOldZirToNew` guarantees that the ZIR mapping preserves `kind` + const tag_type_body = zir_union.arg_type_body.?; + const tag_type_src = block.src(.container_arg); + block.comptime_reason = .{ .reason = .{ + .src = tag_type_src, + .r = .{ .simple = .union_enum_tag_type }, + } }; + const type_ref = try sema.resolveInlineBody(&block, tag_type_body, zir_index); + break :tag_ty try sema.analyzeAsType(&block, tag_type_src, .union_enum_tag_type, type_ref); + }, + }; + // Because the type is explicitly specified, we need to validate it. + if (tag_ty.zigTypeTag(zcu) != .@"enum") return sema.fail( + &block, + block.src(.container_arg), + "expected enum tag type, found '{f}'", + .{tag_ty.fmt(pt)}, + ); + break :validated_tag_ty tag_ty; }, - .fields_len = @intCast(union_obj.field_types.len), - })) { - .existing => |tag_ty| .fromInterned(tag_ty), - .wip => |wip| tag_ty: { - errdefer wip.cancel(ip, pt.tid); - _ = wip.setName(ip, try ip.getOrPutStringFmt( - gpa, - io, - pt.tid, - "@typeInfo({f}).@\"union\".tag_type.?", - .{union_obj.name.fmt(ip)}, - .no_embedded_nulls, - ), .none); - const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ - .parent = union_obj.namespace.toOptional(), - .owner_type = wip.index, - .file_scope = zcu.namespacePtr(union_obj.namespace).file_scope, - .generation = zcu.generation, - }); - if (comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - break :tag_ty .fromInterned(wip.finish(ip, new_namespace_index)); + // If no tag type was specified, we generate one keyed on this union type. + .auto => switch (try ip.getGeneratedEnumTagType(gpa, io, pt.tid, .{ + .union_type = union_ty.toIntern(), + // The int tag for this enum is usually inferred---the exception is `union(enum(T))`. + .int_tag_mode = switch (union_obj.is_reified) { + true => .auto, + false => switch (sema.code.getUnionDecl(zir_index).kind) { + .tagged_enum_explicit => .auto, + else => .explicit, + }, + }, + .fields_len = @intCast(union_obj.field_types.len), + })) { + .existing => |tag_ty| .fromInterned(tag_ty), + .wip => |wip| tag_ty: { + errdefer wip.cancel(ip, pt.tid); + _ = wip.setName(ip, try ip.getOrPutStringFmt( + gpa, + io, + pt.tid, + "@typeInfo({f}).@\"union\".tag_type.?", + .{union_obj.name.fmt(ip)}, + .no_embedded_nulls, + ), .none); + const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ + .parent = union_obj.namespace.toOptional(), + .owner_type = wip.index, + .file_scope = zcu.namespacePtr(union_obj.namespace).file_scope, + .generation = zcu.generation, + }); + if (comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); + break :tag_ty .fromInterned(wip.finish(ip, new_namespace_index)); + }, }, }; -- 2.54.0 From b8997f871fc63cee28d94168330d84f177543f2c Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sat, 31 Jan 2026 18:14:31 +0000 Subject: [PATCH 14/79] Sema: clean up and fix alignment handling --- src/Sema.zig | 935 ++++++++++++++++------------------ src/Type.zig | 345 ++++++++----- src/Value.zig | 304 +++-------- src/Zcu.zig | 6 +- src/Zcu/PerThread.zig | 24 +- src/codegen/c.zig | 2 +- src/codegen/spirv/CodeGen.zig | 2 +- src/print_value.zig | 20 +- 8 files changed, 740 insertions(+), 898 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 276a06a938b0c868a183ee2626db940d22cf866d..fd4e067fe37d0705fb8c5722b970b777981ee7c4 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -3595,7 +3595,20 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, }; break :ptr (try Value.fromInterned(decl_parent_ptr).ptrField(idx, pt)).toIntern(); }, - .elem => |idx| (try Value.fromInterned(decl_parent_ptr).ptrElem(idx, pt)).toIntern(), + .elem => |idx| ptr: { + const parent_ptr_val: Value = .fromInterned(decl_parent_ptr); + if (parent_ptr_val.typeOf(zcu).childType(zcu).zigTypeTag(zcu) == .vector) { + const elem_ptr_ty: Type = .fromInterned(new_ptr_ty); + // Vectors are a bit weird; see logic in `elemPtrVector`. + if (elem_ptr_ty.ptrInfo(zcu).flags.vector_index != .none) { + break :ptr (try pt.getCoerced(parent_ptr_val, elem_ptr_ty)).toIntern(); + } else { + const bit_offset = idx * @divExact(elem_ptr_ty.childType(zcu).bitSize(zcu), 8); + break :ptr (try parent_ptr_val.getOffsetPtr(bit_offset, elem_ptr_ty, pt)).toIntern(); + } + } + break :ptr (try parent_ptr_val.ptrElem(idx, pt)).toIntern(); + }, }; try ptr_mapping.put(air_ptr, new_ptr); } @@ -4540,10 +4553,7 @@ fn validateStructInit( }; const field_src = init_src; // TODO better source location - const default_field_ptr = if (struct_ty.isTuple(zcu)) - try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(i), true) - else - try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(i), struct_ty); + const default_field_ptr = try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(i), struct_ty); try sema.checkKnownAllocPtr(block, struct_ptr, default_field_ptr); try sema.storePtr2(block, init_src, default_field_ptr, init_src, .fromValue(default_val), field_src, .store); } @@ -4959,11 +4969,11 @@ pub fn addStrLit(sema: *Sema, string: InternPool.String, len: u64) CompileError! .ty = array_ty.toIntern(), .storage = .{ .bytes = string }, } }); - return sema.uavRef(val); + return sema.uavRef(.fromInterned(val)); } -fn uavRef(sema: *Sema, val: InternPool.Index) CompileError!Air.Inst.Ref { - return Air.internedToRef(try sema.pt.refValue(val)); +fn uavRef(sema: *Sema, val: Value) CompileError!Air.Inst.Ref { + return .fromValue(try sema.pt.uavValue(val)); } fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -6226,7 +6236,7 @@ fn popErrorReturnTrace( const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty); const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); - const field_ptr = try sema.structFieldPtr(block, src, err_return_trace, field_name, src, stack_trace_ty, true); + const field_ptr = try sema.structFieldPtr(block, src, err_return_trace, field_name, src, stack_trace_ty); try sema.storePtr2(block, src, field_ptr, src, saved_error_trace_index, src, .store); } else if (is_non_error == null) { // The result might be an error. If it is, we leave the error trace alone. If it isn't, we need @@ -6251,7 +6261,7 @@ fn popErrorReturnTrace( const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); const err_return_trace = try then_block.addTy(.err_return_trace, ptr_stack_trace_ty); const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); - const field_ptr = try sema.structFieldPtr(&then_block, src, err_return_trace, field_name, src, stack_trace_ty, true); + const field_ptr = try sema.structFieldPtr(&then_block, src, err_return_trace, field_name, src, stack_trace_ty); try sema.storePtr2(&then_block, src, field_ptr, src, saved_error_trace_index, src, .store); _ = try then_block.addBr(cond_block_inst, .void_value); @@ -8196,23 +8206,10 @@ fn zirOptionalPayload( const operand_ty = sema.typeOf(operand); const result_ty = switch (operand_ty.zigTypeTag(zcu)) { .optional => operand_ty.optionalChild(zcu), - .pointer => t: { - if (operand_ty.ptrSize(zcu) != .c) { - return sema.failWithExpectedOptionalType(block, src, operand_ty); - } - // TODO https://github.com/ziglang/zig/issues/6597 - if (true) break :t operand_ty; - const ptr_info = operand_ty.ptrInfo(zcu); - break :t try pt.ptrType(.{ - .child = ptr_info.child, - .flags = .{ - .alignment = ptr_info.flags.alignment, - .is_const = ptr_info.flags.is_const, - .is_volatile = ptr_info.flags.is_volatile, - .is_allowzero = ptr_info.flags.is_allowzero, - .address_space = ptr_info.flags.address_space, - }, - }); + // TODO: https://github.com/ziglang/zig/issues/6597 will eliminate this branch so that we only need to handle optionals. + .pointer => switch (operand_ty.ptrSize(zcu)) { + .c => operand_ty, // if `ptr` is a `[*c]T`, then `ptr.?` is also a `[*c]T` + .one, .many, .slice => return sema.failWithExpectedOptionalType(block, src, operand_ty), }, else => return sema.failWithExpectedOptionalType(block, src, operand_ty), }; @@ -10322,10 +10319,10 @@ fn analyzeSwitchBlock( const payload_inst: Zir.Inst.Index = if (capture != .none) inst: { const payload_inst = zir_switch.payload_capture_placeholder.unwrap() orelse switch_inst; const payload_ref: Air.Inst.Ref = payload_ref: { - const item_val: InternPool.Index = switch (operand_ty.zigTypeTag(zcu)) { + const item_val: Value = switch (operand_ty.zigTypeTag(zcu)) { .@"union" => item_val: { if (maybe_operand_opv) |operand_opv| { - break :item_val zcu.intern_pool.indexToKey(operand_opv.toIntern()).un.val; + break :item_val .fromInterned(zcu.intern_pool.indexToKey(operand_opv.toIntern()).un.val); } assert(union_originally); // operand type must be union, otherwise it would be an OPV type here assert(zir_switch.any_maybe_runtime_capture); // there's a payload capture @@ -10362,10 +10359,10 @@ fn analyzeSwitchBlock( validated_switch.else_err_ty, ); }, - else => item_opv.toIntern(), + else => item_opv, }; break :payload_ref switch (capture) { - .by_val => .fromIntern(item_val), + .by_val => .fromValue(item_val), .by_ref => try sema.uavRef(item_val), .none => unreachable, }; @@ -12198,7 +12195,7 @@ fn analyzeSwitchPayloadCapture( return case_block.addStructFieldVal(operand_val, field_index, field_ty); } } else if (capture_by_ref) { - return sema.uavRef(item_val.toIntern()); + return sema.uavRef(item_val); } else { return kind.inline_ref; } @@ -12280,37 +12277,14 @@ fn analyzeSwitchPayloadCapture( // By-reference captures have some further restrictions which make them easier to emit if (capture_by_ref) { - const operand_ptr_info = sema.typeOf(operand_ptr).ptrInfo(zcu); + const operand_ptr_ty = sema.typeOf(operand_ptr); const capture_ptr_ty = resolve: { // By-ref captures of hetereogeneous types are only allowed if all field // pointer types are peer resolvable to each other. // We need values to run PTR on, so make a bunch of undef constants. const dummy_captures = try sema.arena.alloc(Air.Inst.Ref, case_vals.len); - for (field_indices, dummy_captures) |field_idx, *dummy| { - const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]); - const field_ptr_ty = try pt.ptrType(.{ - .child = field_ty.toIntern(), - .flags = .{ - .is_const = operand_ptr_info.flags.is_const, - .is_volatile = operand_ptr_info.flags.is_volatile, - .address_space = operand_ptr_info.flags.address_space, - // TODO MLUGG: double-check this. and, um, EVERYWHERE we do ptr alignment... - .alignment = a: { - if (operand_ty.explicitFieldAlignment(field_idx, zcu) == .none and - operand_ptr_info.flags.alignment == .none) - { - break :a .none; - } - - const union_align = switch (operand_ptr_info.flags.alignment) { - .none => operand_ty.abiAlignment(zcu), - else => |a| a, - }; - const field_align = operand_ty.resolvedFieldAlignment(field_idx, zcu); - break :a .minStrict(union_align, field_align); - }, - }, - }); + for (field_indices, dummy_captures) |field_index, *dummy| { + const field_ptr_ty = try operand_ptr_ty.fieldPtrType(field_index, pt); dummy.* = try pt.undefRef(field_ptr_ty); } const case_srcs = try sema.arena.alloc(?LazySrcLoc, case_vals.len); @@ -13696,7 +13670,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai element_vals[elem_i] = coerced_elem_val.toIntern(); } return sema.addConstantMaybeRef( - (try pt.aggregateValue(result_ty, element_vals)).toIntern(), + try pt.aggregateValue(result_ty, element_vals), ptr_addrspace != null, ); } else break :rs rhs_src; @@ -14094,7 +14068,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai } break :v try pt.aggregateValue(result_ty, element_vals); }; - return sema.addConstantMaybeRef(val.toIntern(), ptr_addrspace != null); + return sema.addConstantMaybeRef(val, ptr_addrspace != null); } try sema.requireRuntimeBlock(block, src, lhs_src); @@ -15270,7 +15244,7 @@ fn analyzeArithmetic( }; try sema.ensureLayoutResolved(lhs_ty.childType(zcu), src); - return sema.analyzePtrArithmetic(block, src, lhs, rhs, air_tag, lhs_src, rhs_src); + return sema.analyzePtrArithmetic(block, src, lhs, rhs, air_tag, rhs_src); }, } } @@ -15370,7 +15344,6 @@ fn analyzePtrArithmetic( ptr: Air.Inst.Ref, uncasted_offset: Air.Inst.Ref, air_tag: Air.Inst.Tag, - ptr_src: LazySrcLoc, offset_src: LazySrcLoc, ) CompileError!Air.Inst.Ref { // TODO if the operand is comptime-known to be negative, or is a negative int, @@ -15378,12 +15351,14 @@ fn analyzePtrArithmetic( const offset = try sema.coerce(block, .usize, uncasted_offset, offset_src); const pt = sema.pt; const zcu = pt.zcu; - const opt_ptr_val = sema.resolveValue(ptr); - const opt_off_val = try sema.resolveDefinedValue(block, offset_src, offset); const ptr_ty = sema.typeOf(ptr); const ptr_info = ptr_ty.ptrInfo(zcu); assert(ptr_info.flags.size == .many or ptr_info.flags.size == .c); + const maybe_index: ?u64 = if (try sema.resolveDefinedValue(block, offset_src, offset)) |val| off: { + break :off val.toUnsignedInt(zcu); + } else null; + const elem_ty: Type = .fromInterned(ptr_info.child); elem_ty.assertHasLayout(zcu); @@ -15395,70 +15370,36 @@ fn analyzePtrArithmetic( else => {}, } - const new_ptr_ty = t: { - // Calculate the new pointer alignment. - // This code is duplicated in `Type.elemPtrType`. - if (ptr_info.flags.alignment == .none) { - // ABI-aligned pointer. Any pointer arithmetic maintains the same ABI-alignedness. - break :t ptr_ty; + const elem_ptr_ty = try ptr_ty.elemPtrType(maybe_index, pt); + // `elem_ptr_ty` is a single-item pointer, but we want a many-item or C pointer, and to preserve + // any input sentinel. + const new_ptr_ty = try pt.ptrType(info: { + var info = elem_ptr_ty.ptrInfo(zcu); + info.flags.size = ptr_info.flags.size; + info.sentinel = ptr_info.sentinel; + break :info info; + }); + + ct: { + const ptr_val = sema.resolveValue(ptr) orelse break :ct; + if (ptr_val.isUndef(zcu)) return pt.undefRef(new_ptr_ty); + const index = maybe_index orelse break :ct; + + if (index == 0) return ptr; + if (air_tag == .ptr_sub) { + const elem_size = elem_ty.abiSize(zcu); + return .fromValue(try sema.ptrSubtract(block, op_src, ptr_val, index * elem_size, new_ptr_ty)); + } else { + return .fromValue(try pt.getCoerced(try ptr_val.ptrElem(index, pt), new_ptr_ty)); } - // If the addend is not a comptime-known value we can still count on - // it being a multiple of the type size. - const elem_size = elem_ty.abiSize(zcu); - const addend = if (opt_off_val) |off_val| a: { - const off_int = try sema.usizeCast(block, offset_src, off_val.toUnsignedInt(zcu)); - break :a elem_size * off_int; - } else elem_size; + } - // The resulting pointer is aligned to the lcd between the offset (an - // arbitrary number) and the alignment factor (always a power of two, - // non zero). - const new_align: Alignment = @enumFromInt(@min( - @ctz(addend), - @intFromEnum(ptr_info.flags.alignment), - )); - assert(new_align != .none); - - break :t try pt.ptrType(.{ - .child = ptr_info.child, - .sentinel = ptr_info.sentinel, - .flags = .{ - .size = ptr_info.flags.size, - .alignment = new_align, - .is_const = ptr_info.flags.is_const, - .is_volatile = ptr_info.flags.is_volatile, - .is_allowzero = ptr_info.flags.is_allowzero, - .address_space = ptr_info.flags.address_space, - }, - }); - }; - - const runtime_src = rs: { - if (opt_ptr_val) |ptr_val| { - if (opt_off_val) |offset_val| { - if (ptr_val.isUndef(zcu)) return pt.undefRef(new_ptr_ty); - - const offset_int = try sema.usizeCast(block, offset_src, offset_val.toUnsignedInt(zcu)); - if (offset_int == 0) return ptr; - if (air_tag == .ptr_sub) { - const elem_size = elem_ty.abiSize(zcu); - const new_ptr_val = try sema.ptrSubtract(block, op_src, ptr_val, offset_int * elem_size, new_ptr_ty); - return Air.internedToRef(new_ptr_val.toIntern()); - } else { - const new_ptr_val = try pt.getCoerced(try ptr_val.ptrElem(offset_int, pt), new_ptr_ty); - return Air.internedToRef(new_ptr_val.toIntern()); - } - } else break :rs offset_src; - } else break :rs ptr_src; - }; - - try sema.requireRuntimeBlock(block, op_src, runtime_src); try sema.checkLogicalPtrOperation(block, op_src, ptr_ty); return block.addInst(.{ .tag = air_tag, .data = .{ .ty_pl = .{ - .ty = Air.internedToRef(new_ptr_ty.toIntern()), + .ty = .fromType(new_ptr_ty), .payload = try sema.addExtra(Air.Bin{ .lhs = ptr, .rhs = offset, @@ -16222,6 +16163,11 @@ fn zirBuiltinSrc( return Air.internedToRef((try pt.aggregateValue(src_loc_ty, &fields)).toIntern()); } +/// MLUGG TODO: once this branch is in a more stable state, I need to make a language change so that +/// `std.builtin.Type` makes all `alignment` fields `?usize` instead of `comptime_int`, to prevent +/// explicit alignment annotations from sneaking in without the user requesting any; but doing that +/// right now would be really annoying because it would break the base compiler. I need to have the +/// compiler more-or-less fully migrated first. fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; @@ -16726,17 +16672,21 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai } }); }; + const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); + const alignment = switch (layout) { - .auto, .@"extern" => ty.resolvedFieldAlignment(field_index, zcu), + .auto, .@"extern" => switch (ty.explicitFieldAlignment(field_index, zcu)) { + .none => field_ty.abiAlignment(zcu), + else => |a| a, + }, .@"packed" => .none, }; - const field_ty = union_obj.field_types.get(ip)[field_index]; const union_field_fields = .{ // name: [:0]const u8, name_val, // type: type, - field_ty, + field_ty.toIntern(), // alignment: comptime_int, (try pt.intValue(.comptime_int, alignment.toByteUnits() orelse 0)).toIntern(), }; @@ -16895,7 +16845,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const opt_default_val: ?Value = if (field_default == .none) null else .fromInterned(field_default); const default_val_ptr = try sema.optRefValue(opt_default_val); const alignment = switch (struct_type.layout) { - .auto, .@"extern" => ty.resolvedFieldAlignment(field_index, zcu), + .auto, .@"extern" => switch (ty.explicitFieldAlignment(field_index, zcu)) { + .none => field_ty.defaultStructFieldAlignment(struct_type.layout, zcu), + else => |a| a, + }, .@"packed" => .none, }; @@ -18425,8 +18378,7 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is const init_ref = try sema.coerce(block, init_ty, empty_ref, src); if (is_byref) { - const init_val = sema.resolveValue(init_ref).?; - return sema.uavRef(init_val.toIntern()); + return sema.uavRef(sema.resolveValue(init_ref).?); } else { return init_ref; } @@ -18648,7 +18600,7 @@ fn zirStructInit( })); const final_val_inst = try sema.coerce(block, result_ty, Air.internedToRef(struct_val.toIntern()), src); const final_val = sema.resolveValue(final_val_inst).?; - return sema.addConstantMaybeRef(final_val.toIntern(), is_ref); + return sema.addConstantMaybeRef(final_val, is_ref); } if (resolved_ty.comptimeOnly(zcu)) { @@ -18789,7 +18741,7 @@ fn finishStructInit( } const struct_val = try pt.aggregateValue(struct_ty, elems); const final_val_ref = try sema.coerce(block, result_ty, .fromValue(struct_val), init_src); - return sema.addConstantMaybeRef(final_val_ref.toInterned().?, is_ref); + return sema.addConstantMaybeRef(sema.resolveValue(final_val_ref).?, is_ref); }, .@"packed" => { const buf = try sema.arena.alloc(u8, (struct_ty.bitSize(zcu) + 7) / 8); @@ -18808,7 +18760,7 @@ fn finishStructInit( error.OutOfMemory => |e| return e, }; const final_val_ref = try sema.coerce(block, result_ty, .fromValue(struct_val), init_src); - return sema.addConstantMaybeRef(final_val_ref.toInterned().?, is_ref); + return sema.addConstantMaybeRef(sema.resolveValue(final_val_ref).?, is_ref); }, }; @@ -19000,7 +18952,7 @@ fn structInitAnon( _ = opt_runtime_index orelse { const struct_val = try pt.aggregateValue(struct_ty, values); - return sema.addConstantMaybeRef(struct_val.toIntern(), is_ref); + return sema.addConstantMaybeRef(struct_val, is_ref); }; if (is_ref) { @@ -19137,7 +19089,7 @@ fn zirArrayInit( const arr_val = try pt.aggregateValue(array_ty, elem_vals); const result_ref = try sema.coerce(block, result_ty, Air.internedToRef(arr_val.toIntern()), src); const result_val = (sema.resolveValue(result_ref)).?; - return sema.addConstantMaybeRef(result_val.toIntern(), is_ref); + return sema.addConstantMaybeRef(result_val, is_ref); }; if (is_ref) { @@ -19261,7 +19213,7 @@ fn arrayInitAnon( const runtime_src = opt_runtime_src orelse { const tuple_val = try pt.aggregateValue(tuple_ty, values); - return sema.addConstantMaybeRef(tuple_val.toIntern(), is_ref); + return sema.addConstantMaybeRef(tuple_val, is_ref); }; try sema.requireRuntimeBlock(block, src, runtime_src); @@ -19304,8 +19256,8 @@ fn arrayInitAnon( return block.addAggregateInit(tuple_ty, element_refs); } -fn addConstantMaybeRef(sema: *Sema, val: InternPool.Index, is_ref: bool) !Air.Inst.Ref { - return if (is_ref) sema.uavRef(val) else Air.internedToRef(val); +fn addConstantMaybeRef(sema: *Sema, val: Value, is_ref: bool) !Air.Inst.Ref { + return if (is_ref) sema.uavRef(val) else .fromValue(val); } fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -23401,125 +23353,74 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins const field_ptr = sema.resolveInst(extra.field_ptr); const field_ptr_ty = sema.typeOf(field_ptr); try sema.checkPtrOperand(block, field_ptr_src, field_ptr_ty); - const field_ptr_info = field_ptr_ty.ptrInfo(zcu); - var actual_parent_ptr_info: InternPool.Key.PtrType = .{ - .child = parent_ty.toIntern(), - .flags = .{ - .alignment = parent_ptr_ty.ptrAlignment(zcu), - .is_const = field_ptr_info.flags.is_const, - .is_volatile = field_ptr_info.flags.is_volatile, - .is_allowzero = field_ptr_info.flags.is_allowzero, - .address_space = field_ptr_info.flags.address_space, - }, - .packed_offset = parent_ptr_info.packed_offset, - }; - const field_ty = parent_ty.fieldType(field_index, zcu); - var actual_field_ptr_info: InternPool.Key.PtrType = .{ - .child = field_ty.toIntern(), - .flags = .{ - .alignment = field_ptr_ty.ptrAlignment(zcu), - .is_const = field_ptr_info.flags.is_const, - .is_volatile = field_ptr_info.flags.is_volatile, - .is_allowzero = field_ptr_info.flags.is_allowzero, - .address_space = field_ptr_info.flags.address_space, - }, - .packed_offset = field_ptr_info.packed_offset, - }; - switch (parent_ty.containerLayout(zcu)) { - .auto => { - actual_parent_ptr_info.flags.alignment = parent_ty.resolvedFieldAlignment(field_index, zcu); - actual_parent_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 }; - actual_field_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 }; - }, - .@"extern" => { - const field_offset = parent_ty.structFieldOffset(field_index, zcu); - actual_parent_ptr_info.flags.alignment = actual_field_ptr_info.flags.alignment.minStrict(if (field_offset > 0) - Alignment.fromLog2Units(@ctz(field_offset)) - else - actual_field_ptr_info.flags.alignment); + const hypothetical_field_ptr_ty = try parent_ptr_ty.fieldPtrType(field_index, pt); + const casted_field_ptr = try sema.ptrCastFull( + block, + flags, + inst_src, + field_ptr, + field_ptr_src, + hypothetical_field_ptr_ty, + "@fieldParentPtr", + ); - actual_parent_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 }; - actual_field_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 }; - }, - .@"packed" => { - const byte_offset = std.math.divExact(u32, @abs(@as(i32, actual_parent_ptr_info.packed_offset.bit_offset) + - (if (zcu.typeToStruct(parent_ty)) |struct_obj| zcu.structPackedFieldBitOffset(struct_obj, field_index) else 0) - - actual_field_ptr_info.packed_offset.bit_offset), 8) catch - return sema.fail(block, inst_src, "pointer bit-offset mismatch", .{}); - actual_parent_ptr_info.flags.alignment = actual_field_ptr_info.flags.alignment.minStrict(if (byte_offset > 0) - Alignment.fromLog2Units(@ctz(byte_offset)) - else - actual_field_ptr_info.flags.alignment); - }, - } + const unaligned_parent_ptr_ty = try pt.ptrType(info: { + var info = parent_ptr_ty.ptrInfo(zcu); + info.flags.alignment = hypothetical_field_ptr_ty.ptrAlignment(zcu); + break :info info; + }); - const actual_field_ptr_ty = try pt.ptrType(actual_field_ptr_info); - const casted_field_ptr = try sema.coerce(block, actual_field_ptr_ty, field_ptr, field_ptr_src); - const actual_parent_ptr_ty = try pt.ptrType(actual_parent_ptr_info); - - const result = if (try sema.resolveDefinedValue(block, field_ptr_src, casted_field_ptr)) |field_ptr_val| result: { - switch (parent_ty.zigTypeTag(zcu)) { - .@"struct" => switch (parent_ty.containerLayout(zcu)) { - .auto => {}, - .@"extern" => { - const byte_offset = parent_ty.structFieldOffset(field_index, zcu); - const parent_ptr_val = try sema.ptrSubtract(block, field_ptr_src, field_ptr_val, byte_offset, actual_parent_ptr_ty); - break :result Air.internedToRef(parent_ptr_val.toIntern()); - }, - .@"packed" => { - // Logic lifted from type computation above - I'm just assuming it's correct. - // `catch unreachable` since error case handled above. - const byte_offset = std.math.divExact(u32, @abs(@as(i32, actual_parent_ptr_info.packed_offset.bit_offset) + - zcu.structPackedFieldBitOffset(zcu.typeToStruct(parent_ty).?, field_index) - - actual_field_ptr_info.packed_offset.bit_offset), 8) catch unreachable; - const parent_ptr_val = try sema.ptrSubtract(block, field_ptr_src, field_ptr_val, byte_offset, actual_parent_ptr_ty); - break :result Air.internedToRef(parent_ptr_val.toIntern()); - }, - }, - .@"union" => switch (parent_ty.containerLayout(zcu)) { - .auto => {}, - .@"extern", .@"packed" => { - // For an extern or packed union, just coerce the pointer. - const parent_ptr_val = try pt.getCoerced(field_ptr_val, actual_parent_ptr_ty); - break :result Air.internedToRef(parent_ptr_val.toIntern()); - }, - }, + const unaligned_parent_ptr: Air.Inst.Ref = if (try sema.resolveDefinedValue( + block, + field_ptr_src, + casted_field_ptr, + )) |field_ptr_val| switch (parent_ty.containerLayout(zcu)) { + .@"packed" => .fromValue(try pt.getCoerced(field_ptr_val, unaligned_parent_ptr_ty)), + .@"extern" => switch (parent_ty.zigTypeTag(zcu)) { + .@"struct" => .fromValue(try sema.ptrSubtract( + block, + field_ptr_src, + field_ptr_val, + parent_ty.structFieldOffset(field_index, zcu), + unaligned_parent_ptr_ty, + )), + .@"union" => .fromValue(try pt.getCoerced(field_ptr_val, unaligned_parent_ptr_ty)), else => unreachable, - } - - const opt_field: ?InternPool.Key.Ptr.BaseAddr.BaseIndex = opt_field: { - const ptr = switch (ip.indexToKey(field_ptr_val.toIntern())) { - .ptr => |ptr| ptr, - else => break :opt_field null, - }; - if (ptr.byte_offset != 0) break :opt_field null; - break :opt_field switch (ptr.base_addr) { - .field => |field| field, - else => null, + }, + .auto => result: { + const opt_field: ?InternPool.Key.Ptr.BaseAddr.BaseIndex = opt_field: { + const ptr = switch (ip.indexToKey(field_ptr_val.toIntern())) { + .ptr => |ptr| ptr, + else => break :opt_field null, + }; + if (ptr.byte_offset != 0) break :opt_field null; + break :opt_field switch (ptr.base_addr) { + .field => |field| field, + else => null, + }; }; - }; - const field = opt_field orelse { - return sema.fail(block, field_ptr_src, "pointer value not based on parent struct", .{}); - }; + const field = opt_field orelse { + return sema.fail(block, field_ptr_src, "pointer value not based on parent struct", .{}); + }; - if (Value.fromInterned(field.base).typeOf(zcu).childType(zcu).toIntern() != parent_ty.toIntern()) { - return sema.fail(block, field_ptr_src, "pointer value not based on parent struct", .{}); - } + if (Value.fromInterned(field.base).typeOf(zcu).childType(zcu).toIntern() != parent_ty.toIntern()) { + return sema.fail(block, field_ptr_src, "pointer value not based on parent struct", .{}); + } - if (field.index != field_index) { - return sema.fail(block, inst_src, "field '{f}' has index '{d}' but pointer value is index '{d}' of struct '{f}'", .{ - field_name.fmt(ip), field_index, field.index, parent_ty.fmt(pt), - }); - } - break :result try sema.coerce(block, actual_parent_ptr_ty, Air.internedToRef(field.base), inst_src); + if (field.index != field_index) { + return sema.fail(block, inst_src, "field '{f}' has index '{d}' but pointer value is index '{d}' of struct '{f}'", .{ + field_name.fmt(ip), field_index, field.index, parent_ty.fmt(pt), + }); + } + break :result .fromValue(try pt.getCoerced(.fromInterned(field.base), unaligned_parent_ptr_ty)); + }, } else result: { - try sema.requireRuntimeBlock(block, inst_src, field_ptr_src); break :result try block.addInst(.{ .tag = .field_parent_ptr, .data = .{ .ty_pl = .{ - .ty = Air.internedToRef(actual_parent_ptr_ty.toIntern()), + .ty = .fromType(unaligned_parent_ptr_ty), .payload = try block.sema.addExtra(Air.FieldParentPtr{ .field_ptr = casted_field_ptr, .field_index = @intCast(field_index), @@ -23527,14 +23428,61 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins } }, }); }; - return sema.ptrCastFull(block, flags, inst_src, result, inst_src, parent_ptr_ty, "@fieldParentPtr"); + + // There's one more error condition: if the hypothetical field pointer type has a lower + // alignment than the parent pointer type, then we need an `@alignCast`. Note that the earlier + // `ptrCastFull` may *also* have "used" the `@alignCast`; that would be a case where the field + // is naturally less aligned than the rest of the struct, *and* the field pointer is itself + // underaligned compared to the field alignment. For example, `struct { a: u32, b: u16 }` with + // a field pointer of type `*align(1) u16`. + switch (hypothetical_field_ptr_ty.ptrAlignment(zcu).order(parent_ptr_ty.ptrAlignment(zcu))) { + .gt => unreachable, // getting a field pointer can never increase alignment + .eq => return unaligned_parent_ptr, + .lt => if (flags.align_cast) { + // Go through `ptrCastFull` for the safety check. + return sema.ptrCastFull( + block, + flags, + inst_src, + unaligned_parent_ptr, + inst_src, + parent_ptr_ty, + "@fieldParentPtr", + ); + } else return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(inst_src, "@fieldParentPtr increases pointer alignment", .{}); + errdefer msg.destroy(sema.gpa); + try sema.errNote(inst_src, msg, "parent pointer type '{f}' has alignment '{d}'", .{ + parent_ptr_ty.fmt(pt), + parent_ptr_ty.abiAlignment(zcu), + }); + if (parent_ty.isTuple(zcu)) { + try sema.errNote(field_ptr_src, msg, "tuple field '{d}' limits alignment to '{d}'", .{ + field_index, + field_ptr_ty.ptrAlignment(zcu), + }); + } else { + try sema.errNote(parent_ty.srcLoc(zcu), msg, "{t} field '{f}' limits alignment to '{d}'", .{ + parent_ty.zigTypeTag(zcu), + switch (parent_ty.zigTypeTag(zcu)) { + .@"struct" => parent_ty.structFieldName(field_index, zcu).unwrap().?.fmt(ip), + .@"union" => parent_ty.unionTagTypeHypothetical(zcu).enumFieldName(field_index, zcu).fmt(ip), + else => unreachable, + }, + field_ptr_ty.ptrAlignment(zcu), + }); + } + try sema.errNote(inst_src, msg, "use @alignCast to assert pointer alignment", .{}); + break :msg msg; + }), + } } fn ptrSubtract(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, byte_subtract: u64, new_ty: Type) !Value { const pt = sema.pt; const zcu = pt.zcu; if (byte_subtract == 0) return pt.getCoerced(ptr_val, new_ty); - var ptr = switch (zcu.intern_pool.indexToKey(ptr_val.toIntern())) { + const ptr = switch (zcu.intern_pool.indexToKey(ptr_val.toIntern())) { .undef => return sema.failWithUseOfUndef(block, src, null), .ptr => |ptr| ptr, else => unreachable, @@ -23547,9 +23495,11 @@ fn ptrSubtract(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, byte break :msg msg; }); } - ptr.byte_offset -= byte_subtract; - ptr.ty = new_ty.toIntern(); - return Value.fromInterned(try pt.intern(.{ .ptr = ptr })); + return Value.fromInterned(try pt.intern(.{ .ptr = .{ + .ty = new_ty.toIntern(), + .base_addr = ptr.base_addr, + .byte_offset = ptr.byte_offset - byte_subtract, + } })); } fn zirMinMax( @@ -24186,8 +24136,8 @@ fn zirMemcpy( // ok1: dest >= src + len // ok2: src >= dest + len - const src_plus_len = try sema.analyzePtrArithmetic(block, src, raw_src_ptr, len, .ptr_add, src_src, src); - const dest_plus_len = try sema.analyzePtrArithmetic(block, src, raw_dest_ptr, len, .ptr_add, dest_src, src); + const src_plus_len = try sema.analyzePtrArithmetic(block, src, raw_src_ptr, len, .ptr_add, src); + const dest_plus_len = try sema.analyzePtrArithmetic(block, src, raw_dest_ptr, len, .ptr_add, src); const ok1 = try block.addBinOp(.cmp_gte, raw_dest_ptr, src_plus_len); const ok2 = try block.addBinOp(.cmp_gte, new_src_ptr, dest_plus_len); const ok = try block.addBinOp(.bool_or, ok1, ok2); @@ -25402,21 +25352,36 @@ fn addSafetyCheckSentinelMismatch( const expected_sentinel = Air.internedToRef(expected_sentinel_val.toIntern()); const ptr_ty = sema.typeOf(ptr); - const actual_sentinel = if (ptr_ty.isSlice(zcu)) - try parent_block.addBinOp(.slice_elem_val, ptr, sentinel_index) - else blk: { - const elem_ptr_ty = try ptr_ty.elemPtrType(null, pt); - const sentinel_ptr = try parent_block.addPtrElemPtr(ptr, sentinel_index, elem_ptr_ty); - break :blk try parent_block.addTyOp(.load, sentinel_ty, sentinel_ptr); - }; - - const ok = if (sentinel_ty.zigTypeTag(zcu) == .vector) ok: { - const eql = try parent_block.addCmpVector(expected_sentinel, actual_sentinel, .eq); - break :ok try parent_block.addReduce(eql, .And); - } else ok: { - assert(sentinel_ty.isSelfComparable(zcu, true)); - break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel); + const ptr_info = ptr_ty.ptrInfo(zcu); + const actual_sentinel: Air.Inst.Ref = switch (ptr_ty.ptrSize(zcu)) { + .slice => try parent_block.addBinOp(.slice_elem_val, ptr, sentinel_index), + .one => s: { + const array_ty: Type = .fromInterned(ptr_info.child); + assert(array_ty.zigTypeTag(zcu) == .array); + assert(array_ty.childType(zcu).toIntern() == sentinel_ty.toIntern()); + const many_ptr_ty = try pt.ptrType(.{ + .child = sentinel_ty.toIntern(), + .flags = .{ + .size = .many, + .is_const = ptr_info.flags.is_const, + .is_volatile = ptr_info.flags.is_volatile, + .is_allowzero = ptr_info.flags.is_allowzero, + .alignment = switch (ptr_info.flags.alignment) { + .none => .none, + else => |ptr_align| .minStrict(ptr_align, sentinel_ty.abiAlignment(zcu)), + }, + .address_space = ptr_info.flags.address_space, + }, + }); + const many_ptr = try parent_block.addBitCast(many_ptr_ty, ptr); + break :s try parent_block.addBinOp(.ptr_elem_val, many_ptr, sentinel_index); + }, + .many => unreachable, + .c => unreachable, }; + assert(sema.typeOf(actual_sentinel).toIntern() == sentinel_ty.toIntern()); + assert(sentinel_ty.isSelfComparable(zcu, true)); + const ok = try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel); return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.sentinelMismatch", &.{ expected_sentinel, actual_sentinel, @@ -25676,7 +25641,7 @@ fn fieldVal( .@"struct" => if (is_pointer_to) { // Avoid loading the entire struct by fetching a pointer and loading that try sema.ensureLayoutResolved(inner_ty, src); - const field_ptr = try sema.structFieldPtr(block, src, object, field_name, field_name_src, inner_ty, false); + const field_ptr = try sema.structFieldPtr(block, src, object, field_name, field_name_src, inner_ty); return sema.analyzeLoad(block, src, field_ptr, object_src); } else { return sema.structFieldVal(block, object, field_name, field_name_src, inner_ty); @@ -25730,7 +25695,7 @@ fn fieldPtr( .array => { if (field_name.eqlSlice("len", ip)) { const int_val = try pt.intValue(.usize, inner_ty.arrayLen(zcu)); - return uavRef(sema, int_val.toIntern()); + return uavRef(sema, int_val); } else if (field_name.eqlSlice("ptr", ip) and is_pointer_to) { const ptr_info = object_ty.ptrInfo(zcu); const new_ptr_ty = try pt.ptrType(.{ @@ -25752,6 +25717,7 @@ fn fieldPtr( .child = new_ptr_ty.toIntern(), .sentinel = if (object_ptr_ty.sentinel(zcu)) |s| s.toIntern() else .none, .flags = .{ + .size = .one, .alignment = ptr_ptr_info.flags.alignment, .is_const = ptr_ptr_info.flags.is_const, .is_volatile = ptr_ptr_info.flags.is_volatile, @@ -25857,10 +25823,10 @@ fn fieldPtr( }, else => unreachable, }; - return uavRef(sema, try pt.intern(.{ .err = .{ + return uavRef(sema, .fromInterned(try pt.intern(.{ .err = .{ .ty = err_set_ty.toIntern(), .name = field_name, - } })); + } }))); }, .@"union" => { if (try sema.namespaceLookupRef(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { @@ -25871,7 +25837,7 @@ fn fieldPtr( if (enum_ty.enumFieldIndex(field_name, zcu)) |field_index| { const field_index_u32: u32 = @intCast(field_index); const idx_val = try pt.enumValueFieldIndex(enum_ty, field_index_u32); - return uavRef(sema, idx_val.toIntern()); + return uavRef(sema, idx_val); } } return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name); @@ -25886,7 +25852,7 @@ fn fieldPtr( }; const field_index_u32: u32 = @intCast(field_index); const idx_val = try pt.enumValueFieldIndex(child_type, field_index_u32); - return uavRef(sema, idx_val.toIntern()); + return uavRef(sema, idx_val); }, .@"struct", .@"opaque" => { if (try sema.namespaceLookupRef(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { @@ -25903,7 +25869,7 @@ fn fieldPtr( else object_ptr; try sema.ensureLayoutResolved(inner_ty, src); - const field_ptr = try sema.structFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty, initializing); + const field_ptr = try sema.structFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty); try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr); return field_ptr; }, @@ -26190,7 +26156,6 @@ fn structFieldPtr( field_name: InternPool.NullTerminatedString, field_name_src: LazySrcLoc, struct_ty: Type, - initializing: bool, ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; @@ -26199,23 +26164,24 @@ fn structFieldPtr( assert(struct_ty.zigTypeTag(zcu) == .@"struct"); struct_ty.assertHasLayout(zcu); - if (struct_ty.isTuple(zcu)) { + const field_index: u32 = if (struct_ty.isTuple(zcu)) field_index: { if (field_name.eqlSlice("len", ip)) { const len_inst = try pt.intRef(.usize, struct_ty.structFieldCount(zcu)); return sema.analyzeRef(block, src, len_inst); } - const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src); - return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing); - } - - const struct_type = zcu.typeToStruct(struct_ty).?; - - const field_index = struct_type.nameIndex(ip, field_name) orelse - return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_name_src, field_name); + break :field_index try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src); + } else field_index: { + const struct_type = zcu.typeToStruct(struct_ty).?; + break :field_index struct_type.nameIndex(ip, field_name) orelse { + return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_name_src, field_name); + }; + }; return sema.structFieldPtrByIndex(block, src, struct_ptr, field_index, struct_ty); } +/// Supports both structs and unions. +/// /// Asserts that the layout of `struct_ty` is already resolved. fn structFieldPtrByIndex( sema: *Sema, @@ -26227,82 +26193,23 @@ fn structFieldPtrByIndex( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - const ip = &zcu.intern_pool; struct_ty.assertHasLayout(zcu); - - const struct_type = zcu.typeToStruct(struct_ty).?; - const field_is_comptime = struct_type.field_is_comptime_bits.get(ip, field_index); - - // Comptime fields are handled later - if (!field_is_comptime) { - if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| { - const val = try struct_ptr_val.ptrField(field_index, pt); - return Air.internedToRef(val.toIntern()); - } - } - - const field_ty = struct_type.field_types.get(ip)[field_index]; const struct_ptr_ty = sema.typeOf(struct_ptr); - const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(zcu); - assert(struct_ptr_ty_info.child == struct_ty.toIntern()); - var ptr_ty_data: InternPool.Key.PtrType = .{ - .child = field_ty, - .flags = .{ - .is_const = struct_ptr_ty_info.flags.is_const, - .is_volatile = struct_ptr_ty_info.flags.is_volatile, - .address_space = struct_ptr_ty_info.flags.address_space, - }, - }; - - const parent_align = if (struct_ptr_ty_info.flags.alignment != .none) - struct_ptr_ty_info.flags.alignment - else - struct_ty.abiAlignment(zcu); - - if (struct_type.layout == .@"packed") { - assert(!field_is_comptime); - const packed_offset = struct_ty.packedStructFieldPtrInfo(struct_ptr_ty, field_index, pt); - ptr_ty_data.flags.alignment = parent_align; - ptr_ty_data.packed_offset = packed_offset; - } else if (struct_type.layout == .@"extern") { - assert(!field_is_comptime); - // For extern structs, field alignment might be bigger than type's - // natural alignment. Eg, in `extern struct { x: u32, y: u16 }` the - // second field is aligned as u32. - ptr_ty_data.flags.alignment = a: { - const field_off = struct_ty.structFieldOffset(field_index, zcu); - if (field_off == 0) break :a struct_ptr_ty_info.flags.alignment; - const true_field_align: Alignment = .fromLog2Units(@ctz(field_off)); - if (struct_ptr_ty_info.flags.alignment == .none and - true_field_align == Type.fromInterned(field_ty).abiAlignment(zcu)) - { - break :a .none; - } - break :a .minStrict(true_field_align, parent_align); - }; - } else { - // Our alignment is capped at the field alignment. - ptr_ty_data.flags.alignment = if (struct_ptr_ty_info.flags.alignment == .none) - struct_ty.explicitFieldAlignment(field_index, zcu) - else - struct_ty.resolvedFieldAlignment(field_index, zcu).min(parent_align); - } - - const ptr_field_ty = try pt.ptrType(ptr_ty_data); - - if (field_is_comptime) { - assert(struct_type.field_defaults.get(ip)[field_index] != .none); - const val = try pt.intern(.{ .ptr = .{ - .ty = ptr_field_ty.toIntern(), - .base_addr = .{ .comptime_field = struct_type.field_defaults.get(ip)[field_index] }, + if (struct_ty.structFieldIsComptime(field_index, zcu)) { + const field_ptr_ty = try struct_ptr_ty.fieldPtrType(field_index, pt); + return .fromIntern(try pt.intern(.{ .ptr = .{ + .ty = field_ptr_ty.toIntern(), + .base_addr = .{ .comptime_field = struct_ty.structFieldDefaultValue(field_index, zcu).?.toIntern() }, .byte_offset = 0, - } }); - return Air.internedToRef(val); + } })); + } else if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| { + return .fromValue(try struct_ptr_val.ptrField(field_index, pt)); + } else { + const field_ptr_ty = try struct_ptr_ty.fieldPtrType(field_index, pt); + return block.addStructFieldPtr(struct_ptr, field_index, field_ptr_ty); } - - return block.addStructFieldPtr(struct_ptr, field_index, ptr_field_ty); } fn structFieldVal( @@ -26438,29 +26345,11 @@ fn unionFieldPtr( assert(union_ty.zigTypeTag(zcu) == .@"union"); union_ty.assertHasLayout(zcu); - const union_ptr_ty = sema.typeOf(union_ptr); - const union_ptr_info = union_ptr_ty.ptrInfo(zcu); const union_obj = zcu.typeToUnion(union_ty).?; + const tag_ty: Type = .fromInterned(union_obj.enum_tag_type); + const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src); const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); - const ptr_field_ty = try pt.ptrType(.{ - .child = field_ty.toIntern(), - .flags = .{ - .is_const = union_ptr_info.flags.is_const, - .is_volatile = union_ptr_info.flags.is_volatile, - .address_space = union_ptr_info.flags.address_space, - .alignment = a: { - if (union_obj.layout != .auto) break :a union_ptr_info.flags.alignment; - if (union_ptr_info.flags.alignment == .none) { - break :a union_ty.explicitFieldAlignment(field_index, zcu); - } - const field_align = union_ty.resolvedFieldAlignment(field_index, zcu); - break :a union_ptr_info.flags.alignment.min(field_align); - }, - }, - .packed_offset = union_ptr_info.packed_offset, - }); - const enum_field_index: u32 = @intCast(Type.fromInterned(union_obj.enum_tag_type).enumFieldIndex(field_name, zcu).?); if (initializing and field_ty.classify(zcu) == .no_possible_value) { const msg = msg: { @@ -26484,23 +26373,17 @@ fn unionFieldPtr( break :ct; } // Store to the union to initialize the tag. - const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_type), enum_field_index); - const payload_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); - const new_union_val = try pt.unionValue(union_ty, field_tag, try payload_ty.onePossibleValue(pt) orelse try pt.undefValue(payload_ty)); + const field_tag = try pt.enumValueFieldIndex(tag_ty, field_index); + const payload_val = try field_ty.onePossibleValue(pt) orelse try pt.undefValue(field_ty); + const new_union_val = try pt.unionValue(union_ty, field_tag, payload_val); try sema.storePtrVal(block, src, union_ptr_val, new_union_val, union_ty); } else { - const union_val = (try sema.pointerDeref(block, src, union_ptr_val, union_ptr_ty)) orelse - break :ct; - if (union_val.isUndef(zcu)) { - return sema.failWithUseOfUndef(block, src, null); - } - const un = ip.indexToKey(union_val.toIntern()).un; - const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_type), enum_field_index); - const tag_matches = un.tag == field_tag.toIntern(); - if (!tag_matches) { + const union_val = try sema.pointerDeref(block, src, union_ptr_val, union_ptr_val.typeOf(zcu)) orelse break :ct; + if (union_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, src, null); + const active_index = tag_ty.enumTagFieldIndex(union_val.unionTag(zcu).?, zcu).?; + if (active_index != field_index) { const msg = msg: { - const active_index = Type.fromInterned(union_obj.enum_tag_type).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?; - const active_field_name = Type.fromInterned(union_obj.enum_tag_type).enumFieldName(active_index, zcu); + const active_field_name = tag_ty.enumFieldName(active_index, zcu); const msg = try sema.errMsg(src, "access of union field '{f}' while field '{f}' is active", .{ field_name.fmt(ip), active_field_name.fmt(ip), @@ -26520,11 +26403,10 @@ fn unionFieldPtr( // If the union has a tag, we must either set or or safety check it depending on `initializing`. tag: { if (union_ty.containerLayout(zcu) != .auto) break :tag; - const tag_ty: Type = .fromInterned(union_obj.enum_tag_type); if (tag_ty.classify(zcu) == .one_possible_value) break :tag; // There is a hypothetical non-trivial tag. We must set it even if not there at runtime, but // only emit a safety check if it's available at runtime (i.e. it's safety-tagged). - const want_tag = try pt.enumValueFieldIndex(tag_ty, enum_field_index); + const want_tag = try pt.enumValueFieldIndex(tag_ty, field_index); if (initializing) { const set_tag_inst = try block.addBinOp(.set_union_tag, union_ptr, .fromValue(want_tag)); try sema.checkComptimeKnownStore(block, set_tag_inst, .unneeded); // `unneeded` since this isn't a "proper" store @@ -26540,7 +26422,9 @@ fn unionFieldPtr( _ = try block.addNoOp(.unreach); return .unreachable_value; } - return block.addStructFieldPtr(union_ptr, field_index, ptr_field_ty); + + const field_ptr_ty = try sema.typeOf(union_ptr).fieldPtrType(field_index, pt); + return block.addStructFieldPtr(union_ptr, field_index, field_ptr_ty); } fn unionFieldVal( @@ -26628,13 +26512,9 @@ fn elemPtr( try sema.ensureLayoutResolved(indexable_ty, src); const elem_ptr = switch (indexable_ty.zigTypeTag(zcu)) { - .array, .vector => try sema.elemPtrArray(block, src, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init, oob_safety), - .@"struct" => blk: { - // Tuple field access. - const index_val = try sema.resolveConstDefinedValue(block, elem_index_src, elem_index, .{ .simple = .tuple_field_index }); - const index: u32 = @intCast(index_val.toUnsignedInt(zcu)); - break :blk try sema.tupleFieldPtr(block, src, indexable_ptr, elem_index_src, index, init); - }, + .vector => try sema.elemPtrVector(block, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init), + .array => try sema.elemPtrArray(block, src, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init, oob_safety), + .@"struct" => try sema.tupleElemPtr(block, src, indexable_ptr, elem_index, elem_index_src), else => { const indexable = try sema.analyzeLoad(block, indexable_ptr_src, indexable_ptr, indexable_ptr_src); try sema.ensureLayoutResolved(sema.typeOf(indexable).childType(zcu), src); @@ -26672,21 +26552,21 @@ fn elemPtrOneLayerOnly( .many, .c => { const maybe_ptr_val = try sema.resolveDefinedValue(block, indexable_src, indexable); const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); + const maybe_index: ?u64 = if (maybe_index_val) |val| val.toUnsignedInt(zcu) else null; ct: { const ptr_val = maybe_ptr_val orelse break :ct; - const index_val = maybe_index_val orelse break :ct; - const index: usize = @intCast(index_val.toUnsignedInt(zcu)); - const elem_ptr = try ptr_val.ptrElem(index, pt); - return Air.internedToRef(elem_ptr.toIntern()); + const index: usize = @intCast(maybe_index orelse break :ct); + return .fromValue(try ptr_val.ptrElem(index, pt)); } try sema.checkLogicalPtrOperation(block, src, indexable_ty); - const result_ty = try indexable_ty.elemPtrType(null, pt); + + const result_ty = try indexable_ty.elemPtrType(maybe_index, pt); try sema.validateRuntimeElemAccess(block, elem_index_src, result_ty, indexable_ty, indexable_src); try sema.validateRuntimeValue(block, indexable_src, indexable); - if (result_ty.childType(zcu).abiSize(zcu) == 0) { + if (child_ty.abiSize(zcu) == 0) { // zero-bit child type; just bitcast the pointer return block.addBitCast(result_ty, indexable); } @@ -26695,13 +26575,9 @@ fn elemPtrOneLayerOnly( }, .one => { const elem_ptr = switch (child_ty.zigTypeTag(zcu)) { - .array, .vector => try sema.elemPtrArray(block, src, indexable_src, indexable, elem_index_src, elem_index, init, oob_safety), - .@"struct" => blk: { - assert(child_ty.isTuple(zcu)); - const index_val = try sema.resolveConstDefinedValue(block, elem_index_src, elem_index, .{ .simple = .tuple_field_index }); - const index: u32 = @intCast(index_val.toUnsignedInt(zcu)); - break :blk try sema.tupleFieldPtr(block, indexable_src, indexable, elem_index_src, index, false); - }, + .vector => try sema.elemPtrVector(block, indexable_src, indexable, elem_index_src, elem_index, init), + .array => try sema.elemPtrArray(block, src, indexable_src, indexable, elem_index_src, elem_index, init, oob_safety), + .@"struct" => try sema.tupleElemPtr(block, indexable_src, indexable, elem_index, elem_index_src), else => unreachable, // Guaranteed by checkIndexable }; try sema.checkKnownAllocPtr(block, indexable, elem_ptr); @@ -26746,10 +26622,8 @@ fn elemVal( const index: usize = @intCast(index_val.toUnsignedInt(zcu)); const many_ptr_ty = try pt.manyConstPtrType(child_ty); const many_ptr_val = try pt.getCoerced(indexable_val, many_ptr_ty); - const elem_ptr_ty = try pt.singleConstPtrType(child_ty); const elem_ptr_val = try many_ptr_val.ptrElem(index, pt); - const elem_val = try sema.pointerDeref(block, indexable_src, elem_ptr_val, elem_ptr_ty) orelse break :ct; - return Air.internedToRef((try pt.getCoerced(elem_val, child_ty)).toIntern()); + return sema.analyzeLoad(block, src, .fromValue(elem_ptr_val), indexable_src); } if (try child_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); @@ -26824,70 +26698,38 @@ fn validateRuntimeElemAccess( } } -/// Asserts that the layout of the tuple type is already resolved. -fn tupleFieldPtr( +/// Validates `elem_index`, and returns a pointer to that field using `structFieldPtrByIndex`. +/// +/// Asserts that the type of `tuple_ptr` is a single-item pointer whose child type is a tuple. +fn tupleElemPtr( sema: *Sema, block: *Block, - tuple_ptr_src: LazySrcLoc, + src: LazySrcLoc, tuple_ptr: Air.Inst.Ref, - field_index_src: LazySrcLoc, - field_index: u32, - init: bool, + elem_index: Air.Inst.Ref, + elem_index_src: LazySrcLoc, ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; const tuple_ptr_ty = sema.typeOf(tuple_ptr); - const tuple_ptr_info = tuple_ptr_ty.ptrInfo(zcu); - const tuple_ty: Type = .fromInterned(tuple_ptr_info.child); + assert(tuple_ptr_ty.isSinglePointer(zcu)); + const tuple_ty = tuple_ptr_ty.childType(zcu); + assert(tuple_ty.isTuple(zcu)); + const field_count = tuple_ty.structFieldCount(zcu); - - tuple_ty.assertHasLayout(zcu); - if (field_count == 0) { - return sema.fail(block, tuple_ptr_src, "indexing into empty tuple is not allowed", .{}); + return sema.fail(block, src, "indexing into empty tuple is not allowed", .{}); } - if (field_index >= field_count) { - return sema.fail(block, field_index_src, "index {d} outside tuple of length {d}", .{ - field_index, field_count, + const elem_index_val = try sema.resolveConstDefinedValue(block, elem_index_src, elem_index, .{ .simple = .tuple_field_index }); + const index = elem_index_val.getUnsignedInt(zcu); + if (index == null or index.? >= field_count) { + return sema.fail(block, elem_index_src, "index '{f}' out of bounds of tuple '{f}'", .{ + elem_index_val.fmtValueSema(pt, sema), tuple_ty.fmt(pt), }); } - const field_ty = tuple_ty.fieldType(field_index, zcu); - const ptr_field_ty = try pt.ptrType(.{ - .child = field_ty.toIntern(), - .flags = .{ - .is_const = tuple_ptr_info.flags.is_const, - .is_volatile = tuple_ptr_info.flags.is_volatile, - .address_space = tuple_ptr_info.flags.address_space, - .alignment = a: { - if (tuple_ptr_info.flags.alignment == .none) break :a .none; - // The tuple pointer isn't naturally aligned, so the field pointer might be underaligned. - const tuple_align = tuple_ptr_info.flags.alignment; - const field_align = field_ty.abiAlignment(zcu); - break :a tuple_align.min(field_align); - }, - }, - }); - - if (try tuple_ty.structFieldValueComptime(pt, field_index)) |default_val| { - return Air.internedToRef((try pt.intern(.{ .ptr = .{ - .ty = ptr_field_ty.toIntern(), - .base_addr = .{ .comptime_field = default_val.toIntern() }, - .byte_offset = 0, - } }))); - } - - if (sema.resolveValue(tuple_ptr)) |tuple_ptr_val| { - const field_ptr_val = try tuple_ptr_val.ptrField(field_index, pt); - return Air.internedToRef(field_ptr_val.toIntern()); - } - - if (!init) { - try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_ptr_src); - } - - return block.addStructFieldPtr(tuple_ptr, field_index, ptr_field_ty); + return sema.structFieldPtrByIndex(block, src, tuple_ptr, @intCast(index.?), tuple_ty); } fn tupleField( @@ -26994,7 +26836,102 @@ fn elemValArray( return block.addBinOp(.array_elem_val, array, elem_index); } -/// Asserts that the layout of the array or vector is already resolved. +fn elemPtrVector( + sema: *Sema, + block: *Block, + vector_ptr_src: LazySrcLoc, + vector_ptr: Air.Inst.Ref, + elem_index_src: LazySrcLoc, + elem_index: Air.Inst.Ref, + init: bool, +) CompileError!Air.Inst.Ref { + const pt = sema.pt; + const zcu = pt.zcu; + const vector_ptr_ty = sema.typeOf(vector_ptr); + const vector_ty = vector_ptr_ty.childType(zcu); + assert(vector_ty.zigTypeTag(zcu) == .vector); + const vector_len = vector_ty.vectorLen(zcu); + + if (vector_len == 0) { + return sema.fail(block, vector_ptr_src, "cannot index into empty vector", .{}); + } + + const maybe_vector_ptr_val = sema.resolveValue(vector_ptr); + // The index must not be undefined since it can be out of bounds. + const index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index) orelse { + return sema.fail(block, elem_index_src, "vector index not comptime known", .{}); + }; + const index = index_val.toUnsignedInt(zcu); + if (index >= vector_len) { + return sema.fail(block, elem_index_src, "index {d} outside vector of length {d}", .{ index, vector_len }); + } + + const elem_ty = vector_ty.childType(zcu); + const elem_bits = elem_ty.bitSize(zcu); + // Exiting this block means the operation is a runtime one. + const elem_ptr_ty: Type = if (elem_bits < 8 or !std.math.isPowerOfTwo(elem_bits)) elem_ptr_ty: { + // Use a packed pointer (i.e. vector_index != 0) + const vector_ptr_info = vector_ptr_ty.ptrInfo(zcu); + const elem_ptr_ty = try pt.ptrType(.{ + .child = elem_ty.toIntern(), + .flags = .{ + .size = .one, + .alignment = vector_ptr_info.flags.alignment, + .is_const = vector_ptr_info.flags.is_const, + .is_volatile = vector_ptr_info.flags.is_volatile, + .is_allowzero = vector_ptr_info.flags.is_allowzero, + .address_space = vector_ptr_info.flags.address_space, + .vector_index = @enumFromInt(index), + }, + .packed_offset = .{ + .host_size = @intCast(vector_len), + .bit_offset = 0, + }, + }); + if (maybe_vector_ptr_val) |ptr_val| { + if (ptr_val.isUndef(zcu)) return pt.undefRef(elem_ptr_ty); + return .fromValue(try pt.getCoerced(ptr_val, elem_ptr_ty)); + } + break :elem_ptr_ty elem_ptr_ty; + } else elem_ptr_ty: { + // Use a normal pointer (i.e. vector_index == 0) + const vector_ptr_info = vector_ptr_ty.ptrInfo(zcu); + const elem_ptr_ty = try pt.ptrType(.{ + .child = elem_ty.toIntern(), + .flags = .{ + .size = .one, + // TODO: this logic was ported from old code, but it's bogus. This entire block will + // go away when https://github.com/ziglang/zig/issues/24061 is implemented anyway. + .alignment = switch (vector_ptr_info.flags.alignment) { + .none => .none, + else => |vec_align| switch (index * elem_ty.abiSize(zcu)) { + 0 => vec_align, + else => |byte_offset| .minStrict(vec_align, .fromLog2Units(@ctz(byte_offset))), + }, + }, + .is_const = vector_ptr_info.flags.is_const, + .is_volatile = vector_ptr_info.flags.is_volatile, + .is_allowzero = vector_ptr_info.flags.is_allowzero, + .address_space = vector_ptr_info.flags.address_space, + }, + }); + if (maybe_vector_ptr_val) |ptr_val| { + if (ptr_val.isUndef(zcu)) return pt.undefRef(elem_ptr_ty); + const bit_offset = index * @divExact(elem_ty.bitSize(zcu), 8); + return .fromValue(try ptr_val.getOffsetPtr(bit_offset, elem_ptr_ty, pt)); + } + break :elem_ptr_ty elem_ptr_ty; + }; + + if (!init) { + try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, vector_ty, vector_ptr_src); + try sema.validateRuntimeValue(block, vector_ptr_src, vector_ptr); + } + + return block.addPtrElemPtr(vector_ptr, elem_index, elem_ptr_ty); +} + +/// Asserts that the layout of the array is already resolved. fn elemPtrArray( sema: *Sema, block: *Block, @@ -27009,19 +26946,21 @@ fn elemPtrArray( const pt = sema.pt; const zcu = pt.zcu; const array_ptr_ty = sema.typeOf(array_ptr); + assert(array_ptr_ty.ptrSize(zcu) == .one); const array_ty = array_ptr_ty.childType(zcu); + assert(array_ty.zigTypeTag(zcu) == .array); const array_sent = array_ty.sentinel(zcu) != null; const array_len = array_ty.arrayLen(zcu); const array_len_s = array_len + @intFromBool(array_sent); if (array_len_s == 0) { - return sema.fail(block, array_ptr_src, "indexing into empty array is not allowed", .{}); + return sema.fail(block, array_ptr_src, "cannot index into empty array", .{}); } const maybe_undef_array_ptr_val = sema.resolveValue(array_ptr); // The index must not be undefined since it can be out of bounds. - const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: { - const index = try sema.usizeCast(block, elem_index_src, index_val.toUnsignedInt(zcu)); + const maybe_index: ?u64 = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: { + const index = index_val.toUnsignedInt(zcu); if (index >= array_len_s) { const sentinel_label: []const u8 = if (array_sent) " +1 (sentinel)" else ""; return sema.fail(block, elem_index_src, "index {d} outside array of length {d}{s}", .{ index, array_len, sentinel_label }); @@ -27029,20 +26968,15 @@ fn elemPtrArray( break :o index; } else null; - if (offset == null and array_ty.zigTypeTag(zcu) == .vector) { - return sema.fail(block, elem_index_src, "vector index not comptime known", .{}); - } - array_ty.assertHasLayout(zcu); - const elem_ptr_ty = try array_ptr_ty.elemPtrType(offset, pt); + const elem_ptr_ty = try array_ptr_ty.elemPtrType(maybe_index, pt); if (maybe_undef_array_ptr_val) |array_ptr_val| { if (array_ptr_val.isUndef(zcu)) { return pt.undefRef(elem_ptr_ty); } - if (offset) |index| { - const elem_ptr = try array_ptr_val.ptrElem(index, pt); - return Air.internedToRef(elem_ptr.toIntern()); + if (maybe_index) |index| { + return .fromValue(try array_ptr_val.ptrElem(index, pt)); } } @@ -27052,7 +26986,7 @@ fn elemPtrArray( } // Runtime check is only needed if unable to comptime check. - if (oob_safety and block.wantSafety() and offset == null) { + if (oob_safety and block.wantSafety() and maybe_index == null) { const len_inst = try pt.intRef(.usize, array_len); const cmp_op: Air.Inst.Tag = if (array_sent) .cmp_lte else .cmp_lt; try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op); @@ -27075,9 +27009,9 @@ fn elemValSlice( const pt = sema.pt; const zcu = pt.zcu; const slice_ty = sema.typeOf(slice); + assert(slice_ty.isSlice(zcu)); const slice_sent = slice_ty.sentinel(zcu) != null; const elem_ty = slice_ty.childType(zcu); - var runtime_src = slice_src; elem_ty.assertHasLayout(zcu); @@ -27087,7 +27021,6 @@ fn elemValSlice( const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); if (maybe_slice_val) |slice_val| { - runtime_src = elem_index_src; const slice_len = slice_val.sliceLen(zcu); const slice_len_s = slice_len + @intFromBool(slice_sent); if (slice_len_s == 0) { @@ -27099,12 +27032,8 @@ fn elemValSlice( const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else ""; return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label }); } - const elem_ptr_ty = try slice_ty.elemPtrType(index, pt); const elem_ptr_val = try slice_val.ptrElem(index, pt); - if (try sema.pointerDeref(block, slice_src, elem_ptr_val, elem_ptr_ty)) |elem_val| { - return Air.internedToRef(elem_val.toIntern()); - } - runtime_src = slice_src; + return sema.analyzeLoad(block, src, .fromValue(elem_ptr_val), slice_src); } } @@ -27138,17 +27067,19 @@ fn elemPtrSlice( const pt = sema.pt; const zcu = pt.zcu; const slice_ty = sema.typeOf(slice); + assert(slice_ty.isSlice(zcu)); const slice_sent = slice_ty.sentinel(zcu) != null; - - slice_ty.childType(zcu).assertHasLayout(zcu); + const elem_ty = slice_ty.childType(zcu); + elem_ty.assertHasLayout(zcu); const maybe_undef_slice_val = sema.resolveValue(slice); // The index must not be undefined since it can be out of bounds. - const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: { - break :o try sema.usizeCast(block, elem_index_src, index_val.toUnsignedInt(zcu)); + const offset: ?u64 = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: { + break :o index_val.toUnsignedInt(zcu); } else null; const elem_ptr_ty = try slice_ty.elemPtrType(offset, pt); + assert(elem_ptr_ty.childType(zcu).toIntern() == elem_ty.toIntern()); if (maybe_undef_slice_val) |slice_val| { if (slice_val.isUndef(zcu)) { @@ -27157,15 +27088,14 @@ fn elemPtrSlice( const slice_len = slice_val.sliceLen(zcu); const slice_len_s = slice_len + @intFromBool(slice_sent); if (slice_len_s == 0) { - return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{}); + return sema.fail(block, slice_src, "cannot index into empty slice", .{}); } if (offset) |index| { if (index >= slice_len_s) { const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else ""; return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label }); } - const elem_ptr_val = try slice_val.ptrElem(index, pt); - return Air.internedToRef(elem_ptr_val.toIntern()); + return .fromValue(try slice_val.ptrElem(index, pt)); } } @@ -27182,7 +27112,7 @@ fn elemPtrSlice( const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt; try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op); } - if (slice_ty.childType(zcu).abiSize(zcu) == 0) { + if (elem_ty.abiSize(zcu) == 0) { // zero-bit child type; just extract the pointer and bitcast it const slice_ptr = try block.addTyOp(.slice_ptr, slice_ty.slicePtrFieldType(zcu), slice); return block.addBitCast(elem_ptr_ty, slice_ptr); @@ -27546,7 +27476,7 @@ fn coerceExtra( .sentinel = dest_info.sentinel, }); const empty_array_val = try pt.aggregateValue(empty_array_ty, &.{}); - const empty_array_ptr = try sema.uavRef(empty_array_val.toIntern()); + const empty_array_ptr = try sema.uavRef(empty_array_val); return sema.coerceArrayPtrToSlice(block, dest_ty, empty_array_ptr, inst_src); } @@ -28499,7 +28429,6 @@ pub fn coerceInMemoryAllowed( const field_count = dest_ty.structFieldCount(zcu); for (0..field_count) |field_idx| { if (dest_ty.structFieldIsComptime(field_idx, zcu) != src_ty.structFieldIsComptime(field_idx, zcu)) break :tuple; - if (dest_ty.resolvedFieldAlignment(field_idx, zcu) != src_ty.resolvedFieldAlignment(field_idx, zcu)) break :tuple; const dest_field_ty = dest_ty.fieldType(field_idx, zcu); const src_field_ty = src_ty.fieldType(field_idx, zcu); const field = try sema.coerceInMemoryAllowed(block, dest_field_ty, src_field_ty, dest_is_mut, target, dest_src, src_src, null); @@ -29953,12 +29882,14 @@ pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: fn optRefValue(sema: *Sema, opt_val: ?Value) !Value { const pt = sema.pt; const ptr_anyopaque_ty = try pt.singleConstPtrType(.anyopaque); - return Value.fromInterned(try pt.intern(.{ .opt = .{ - .ty = (try pt.optionalType(ptr_anyopaque_ty.toIntern())).toIntern(), - .val = if (opt_val) |val| (try pt.getCoerced( - Value.fromInterned(try pt.refValue(val.toIntern())), - ptr_anyopaque_ty, - )).toIntern() else .none, + const opt_ptr_anyopaque_ty = try pt.optionalType(ptr_anyopaque_ty.toIntern()); + return .fromInterned(try pt.intern(.{ .opt = .{ + .ty = opt_ptr_anyopaque_ty.toIntern(), + .val = payload: { + const val = opt_val orelse break :payload .none; + const ptr_val = try pt.getCoerced(try pt.uavValue(val), ptr_anyopaque_ty); + break :payload ptr_val.toIntern(); + }, } })); } @@ -30078,7 +30009,7 @@ fn analyzeRef( switch (zcu.intern_pool.indexToKey(val.toIntern())) { .@"extern" => |e| return sema.analyzeNavRef(block, src, e.owner_nav), .func => |f| return sema.analyzeNavRef(block, src, f.owner_nav), - else => return uavRef(sema, val.toIntern()), + else => return uavRef(sema, val), } } @@ -30528,7 +30459,7 @@ fn analyzeSlice( } else ptr_or_slice; const start = try sema.coerce(block, .usize, uncasted_start, start_src); - const new_ptr = try sema.analyzePtrArithmetic(block, src, ptr, start, .ptr_add, ptr_src, start_src); + const new_ptr = try sema.analyzePtrArithmetic(block, src, ptr, start, .ptr_add, start_src); const new_ptr_ty = sema.typeOf(new_ptr); // true if and only if the end index of the slice, implicitly or explicitly, equals @@ -30666,7 +30597,7 @@ fn analyzeSlice( break :msg msg; }); } - return sema.analyzePtrArithmetic(block, src, ptr, start, .ptr_add, ptr_src, start_src); + return sema.analyzePtrArithmetic(block, src, ptr, start, .ptr_add, start_src); }; const sentinel = s: { @@ -32118,12 +32049,12 @@ fn resolvePeerTypesInner( ptr_info.flags.alignment = a: { // If both alignments are implicit, the result alignment is implicit. - // e.g. '[*c]u32' + '[*c]c_uint' -> '[*c]u32' + // e.g. '*u32' + '*c_uint' -> '*u32' if (ptr_info.flags.alignment == .none and peer_info.flags.alignment == .none) { break :a .none; } // Otherwise (if either alignment is explicit), the result alignment is explicit. - // e.g. '[*c]u32' + '[*c]align(4) c_uint' -> '[*c]align(4) u32' + // e.g. '*u32' + '*align(4) c_uint' -> '*align(4) u32' const cur_align = switch (ptr_info.flags.alignment) { .none => Type.fromInterned(ptr_info.child).abiAlignment(zcu), else => ptr_info.flags.alignment, @@ -33583,7 +33514,7 @@ fn notePathToComptimeAllocPtr( else => {}, // there will be another stage } - const derivation = try comptime_ptr.pointerDerivationAdvanced(arena, pt, false, sema); + const derivation = try comptime_ptr.pointerDerivation(arena, pt, sema); var second_path_aw: std.Io.Writer.Allocating = .init(arena); defer second_path_aw.deinit(); diff --git a/src/Type.zig b/src/Type.zig index 8b1c71cc9631a8085c4b8908ce09d1c9d69a057b..81ee1e560e6505eb6721b13b6fbdd2338e1694e0 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -2337,35 +2337,11 @@ pub fn fieldType(ty: Type, index: usize, zcu: *const Zcu) Type { return .fromInterned(types.get(ip)[index]); } -// TODO MLUGG: clean up doc comments and usages of `{resolved,explicit}FieldAlignment` - -/// Returns the alignment of the given struct, tuple, or union field. -/// Asserts that the layout of `ty` is resolved. Asserts that `ty` is not packed. -/// Never returns `.none`, even if the field's alignment was not specified. -pub fn resolvedFieldAlignment(ty: Type, index: usize, zcu: *const Zcu) Alignment { - switch (ty.explicitFieldAlignment(index, zcu)) { - .none => {}, - else => |explicit| return explicit, - } - const ip = &zcu.intern_pool; - return switch (ip.indexToKey(ty.toIntern())) { - .tuple_type => |tuple| Type.fromInterned(tuple.types.get(ip)[index]).abiAlignment(zcu), - .struct_type => { - assertHasLayout(ty, zcu); - const struct_obj = ip.loadStructType(ty.toIntern()); - const field_ty: Type = .fromInterned(struct_obj.field_types.get(ip)[index]); - return field_ty.defaultStructFieldAlignment(struct_obj.layout, zcu); - }, - .union_type => { - assertHasLayout(ty, zcu); - const union_obj = ip.loadUnionType(ty.toIntern()); - const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[index]); - return field_ty.abiAlignment(zcu); - }, - else => unreachable, - }; -} - +/// If an alignment was explicitly specified for the given field of the struct or union type `ty`, +/// returns that. Otherwise, returns `.none`. This function also supports tuples, for which it +/// always returns `.none`. +/// +/// Asserts that the layout of `ty` is resolved, unless `ty` is a tuple. pub fn explicitFieldAlignment(ty: Type, index: usize, zcu: *const Zcu) Alignment { const ip = &zcu.intern_pool; return switch (ip.indexToKey(ty.toIntern())) { @@ -2388,7 +2364,10 @@ pub fn explicitFieldAlignment(ty: Type, index: usize, zcu: *const Zcu) Alignment }; } -/// Returns the alignment a struct field will have if not explicitly specified. +/// Returns the alignment a struct field of type `field_ty` will be given if no alignment is +/// explicitly specified. However, in an `extern struct`, a higher alignment may be available due +/// to the struct's full layout (i.e. a field might coincidentally be more aligned). +/// /// Asserts that the layout of `field_ty` is resolved. Asserts that `layout` is not `.@"packed"`. pub fn defaultStructFieldAlignment( field_ty: Type, @@ -2664,45 +2643,6 @@ pub fn arrayBase(ty: Type, zcu: *const Zcu) struct { Type, u64 } { return .{ cur_ty, cur_len }; } -/// Returns a bit-pointer with the same value and a new packed offset. -pub fn packedStructFieldPtrInfo( - struct_ty: Type, - parent_ptr_ty: Type, - field_idx: u32, - pt: Zcu.PerThread, -) InternPool.Key.PtrType.PackedOffset { - comptime assert(Type.packed_struct_layout_version == 2); - - const zcu = pt.zcu; - const parent_ptr_info = parent_ptr_ty.ptrInfo(zcu); - - var bit_offset: u16 = 0; - var running_bits: u16 = 0; - for (0..struct_ty.structFieldCount(zcu)) |i| { - const f_ty = struct_ty.fieldType(i, zcu); - if (i == field_idx) { - bit_offset = running_bits; - } - running_bits += @intCast(f_ty.bitSize(zcu)); - } - - const res_host_size: u16, const res_bit_offset: u16 = if (parent_ptr_info.packed_offset.host_size != 0) .{ - parent_ptr_info.packed_offset.host_size, - parent_ptr_info.packed_offset.bit_offset + bit_offset, - } else .{ - switch (zcu.comp.getZigBackend()) { - else => (running_bits + 7) / 8, - .stage2_x86_64, .stage2_c => @intCast(struct_ty.abiSize(zcu)), - }, - bit_offset, - }; - - return .{ - .host_size = res_host_size, - .bit_offset = res_bit_offset, - }; -} - pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) Zcu.UnionLayout { const ip = &zcu.intern_pool; var most_aligned_field: u32 = 0; @@ -2770,88 +2710,225 @@ pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) }; } -/// Returns the type of a pointer to an element. -/// Asserts that the type is a pointer, and that the element type is indexable. -/// If the element index is comptime-known, it must be passed in `offset`. -/// For *@Vector(n, T), return *align(a:b:h:v) T -/// For *[N]T, return *T -/// For [*]T, returns *T -/// For []T, returns *T -/// Handles const-ness and address spaces in particular. -/// This code is duplicated in `Sema.analyzePtrArithmetic`. -/// May perform type resolution and return a transitive `error.AnalysisFail`. -/// MLUGG TODO audit this shit -pub fn elemPtrType(ptr_ty: Type, offset: ?usize, pt: Zcu.PerThread) !Type { +/// Asserts that `ptr_ty` is either a many-item pointer, a slice, a C pointer, or a single pointer +/// to array (in other words, a pointer which is indexed by pointer arithmetic), and returns the +/// type of the element pointer at the given index. +/// +/// Asserts that the layout of the pointer element type is resolved. +/// +/// If `index` is `null`, the index is an arbitrary runtime-known value. +pub fn elemPtrType(ptr_ty: Type, index: ?u64, pt: Zcu.PerThread) Allocator.Error!Type { const zcu = pt.zcu; - const ptr_info = ptr_ty.ptrInfo(zcu); + const ip = &zcu.intern_pool; + const ptr_info = ip.indexToKey(ptr_ty.toIntern()).ptr_type; const elem_ty: Type = switch (ptr_info.flags.size) { - .one => switch (Type.fromInterned(ptr_info.child).zigTypeTag(zcu)) { - .array, .vector => Type.fromInterned(ptr_info.child).childType(zcu), - else => .fromInterned(ptr_info.child), + .slice, .many, .c => .fromInterned(ptr_info.child), + .one => switch (ip.indexToKey(ptr_info.child)) { + .array_type => |array_type| .fromInterned(array_type.child), + else => unreachable, }, - .many, .c, .slice => .fromInterned(ptr_info.child), }; - const is_allowzero = ptr_info.flags.is_allowzero and (offset orelse 0) == 0; - const parent_ty = ptr_ty.childType(zcu); + elem_ty.assertHasLayout(zcu); + const elem_align: Alignment = switch (elem_ty.classify(zcu)) { + .no_possible_value, + .one_possible_value, + => ptr_info.flags.alignment, - const VI = InternPool.Key.PtrType.VectorIndex; + .partially_comptime, + .fully_comptime, + => switch (ptr_info.flags.alignment) { + .none => .none, + else => |array_align| .minStrict(array_align, elem_ty.abiAlignment(zcu)), + }, - const vector_info: struct { - host_size: u16 = 0, - alignment: Alignment = .none, - vector_index: VI = .none, - } = if (parent_ty.isVector(zcu) and ptr_info.flags.size == .one) blk: { - const elem_bits = elem_ty.bitSize(zcu); - if (elem_bits == 0) break :blk .{}; - const is_packed = elem_bits < 8 or !std.math.isPowerOfTwo(elem_bits); - if (!is_packed) break :blk .{}; - - break :blk .{ - .host_size = @intCast(parent_ty.arrayLen(zcu)), - .alignment = parent_ty.abiAlignment(zcu), - .vector_index = @enumFromInt(offset.?), - }; - } else .{}; - - const alignment: Alignment = a: { - // Calculate the new pointer alignment. - if (ptr_info.flags.alignment == .none) { - // In case of an ABI-aligned pointer, any pointer arithmetic - // maintains the same ABI-alignedness. - break :a vector_info.alignment; - } - // If the addend is not a comptime-known value we can still count on - // it being a multiple of the type size. - const elem_size = elem_ty.abiSize(zcu); - const addend = if (offset) |off| elem_size * off else elem_size; - - // The resulting pointer is aligned to the lcd between the offset (an - // arbitrary number) and the alignment factor (always a power of two, - // non zero). - const new_align: Alignment = @enumFromInt(@min( - @ctz(addend), - ptr_info.flags.alignment.toLog2Units(), - )); - assert(new_align != .none); - break :a new_align; + .runtime => switch (ptr_info.flags.alignment) { + .none => .none, + else => |array_align| elem_align: { + // If the index is runtime-known, use 1 as it gives the minimum possible alignment. + const effective_index = index orelse 1; + if (effective_index == 0) break :elem_align array_align; + const byte_offset = effective_index * elem_ty.abiSize(zcu); + break :elem_align .minStrict(array_align, .fromLog2Units(@ctz(byte_offset))); + }, + }, }; return pt.ptrType(.{ .child = elem_ty.toIntern(), .flags = .{ - .alignment = alignment, + .size = .one, .is_const = ptr_info.flags.is_const, .is_volatile = ptr_info.flags.is_volatile, - .is_allowzero = is_allowzero, + .is_allowzero = ptr_info.flags.is_allowzero and (index == null or index == 0), .address_space = ptr_info.flags.address_space, - .vector_index = vector_info.vector_index, - }, - .packed_offset = .{ - .host_size = vector_info.host_size, - .bit_offset = 0, + .alignment = elem_align, }, }); } +/// Asserts that `ptr_ty` is a pointer (single-item or C) to a struct, union, tuple, or slice, and +/// returns the type of a pointer to the field at `field_index`. +/// +/// Asserts that the layout of the pointer child type is resolved. +/// +/// For slices, `Value.slice_ptr_index` and `Value.slice_len_index` are used for the field index. +pub fn fieldPtrType(ptr_ty: Type, field_index: u32, pt: Zcu.PerThread) Allocator.Error!Type { + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + const ptr_info = ip.indexToKey(ptr_ty.toIntern()).ptr_type; + assert(ptr_info.flags.size == .one or ptr_info.flags.size == .c); + const aggregate_ty: Type = .fromInterned(ptr_info.child); + aggregate_ty.assertHasLayout(zcu); + // We only exit this `switch` for default-layout aggregates, where the field pointer alignment + // is a simple minimum of the aggregate pointer alignment and the field alignment. + // `field_align` is `.none` if there is no explicit alignment annotation. + const field_ty: Type, const field_align: Alignment = switch (aggregate_ty.zigTypeTag(zcu)) { + .@"struct" => switch (aggregate_ty.containerLayout(zcu)) { + .auto => field: { + if (aggregate_ty.isTuple(zcu)) { + break :field .{ aggregate_ty.fieldType(field_index, zcu), .none }; + } + const struct_obj = ip.loadStructType(aggregate_ty.toIntern()); + break :field .{ + .fromInterned(struct_obj.field_types.get(ip)[field_index]), + struct_obj.field_aligns.getOrNone(ip, field_index), + }; + }, + .@"extern" => { + // Field alignment is determined based on the actual field offset. For instance, in + // `extern struct { x: u32, y: u16 }`, the `y` field is 4-byte aligned. + const field_ty = aggregate_ty.fieldType(field_index, zcu); + const field_offset = aggregate_ty.structFieldOffset(field_index, zcu); + const parent_align = switch (ptr_info.flags.alignment) { + .none => aggregate_ty.abiAlignment(zcu), + else => |a| a, + }; + const actual_field_align = switch (field_offset) { + 0 => parent_align, + else => parent_align.minStrict(.fromLog2Units(@ctz(field_offset))), + }; + const field_ptr_align: Alignment = a: { + if (parent_align == .none and + aggregate_ty.explicitFieldAlignment(field_index, zcu) == .none and + actual_field_align == field_ty.abiAlignment(zcu)) + { + // There's no user-specified 'align' in sight, and the alignment from the + // field offset matches the field type's natural alignment, so just use a + // default-aligned pointer. + break :a .none; + } + break :a actual_field_align; + }; + var field_ptr_info = ptr_info; + field_ptr_info.child = field_ty.toIntern(); + field_ptr_info.flags.alignment = field_ptr_align; + return pt.ptrType(field_ptr_info); + }, + .@"packed" => { + var field_ptr_info = ptr_info; + if (field_ptr_info.flags.alignment == .none) { + field_ptr_info.flags.alignment = aggregate_ty.abiAlignment(zcu); + } + field_ptr_info.packed_offset = packed_offset: { + comptime assert(Type.packed_struct_layout_version == 2); + const bit_offset = zcu.structPackedFieldBitOffset( + ip.loadStructType(aggregate_ty.toIntern()), + field_index, + ); + break :packed_offset if (ptr_info.packed_offset.host_size != 0) .{ + .host_size = ptr_info.packed_offset.host_size, + .bit_offset = ptr_info.packed_offset.bit_offset + bit_offset, + } else .{ + .host_size = switch (zcu.comp.getZigBackend()) { + else => @intCast((aggregate_ty.bitSize(zcu) + 7) / 8), + .stage2_x86_64, .stage2_c => @intCast(aggregate_ty.abiSize(zcu)), + }, + .bit_offset = ptr_info.packed_offset.bit_offset + bit_offset, + }; + }; + field_ptr_info.child = aggregate_ty.fieldType(field_index, zcu).toIntern(); + return pt.ptrType(field_ptr_info); + }, + }, + .@"union" => switch (aggregate_ty.containerLayout(zcu)) { + .auto => field: { + const union_obj = ip.loadUnionType(aggregate_ty.toIntern()); + break :field .{ + .fromInterned(union_obj.field_types.get(ip)[field_index]), + union_obj.field_aligns.getOrNone(ip, field_index), + }; + }, + .@"extern" => { + // The alignment always matches that of the union pointer. If the union pointer is + // default aligned (`.none`), we may need to explicitly align the result pointer. + const field_ty = aggregate_ty.fieldType(field_index, zcu); + var field_ptr_info = ptr_info; + field_ptr_info.child = field_ty.toIntern(); + if (field_ptr_info.flags.alignment == .none and + Alignment.compareStrict(field_ty.abiAlignment(zcu), .neq, aggregate_ty.abiAlignment(zcu))) + { + field_ptr_info.flags.alignment = aggregate_ty.abiAlignment(zcu); + } + return pt.ptrType(field_ptr_info); + }, + .@"packed" => { + const field_ty = aggregate_ty.fieldType(field_index, zcu); + var field_ptr_info = ptr_info; + if (field_ptr_info.flags.alignment == .none) { + const resolved_align = aggregate_ty.abiAlignment(zcu); + if (field_ty.abiAlignment(zcu) != resolved_align) { + field_ptr_info.flags.alignment = resolved_align; + } + } + field_ptr_info.child = aggregate_ty.fieldType(field_index, zcu).toIntern(); + return pt.ptrType(field_ptr_info); + }, + }, + .pointer => field: { + assert(aggregate_ty.isSlice(zcu)); + break :field switch (field_index) { + Value.slice_ptr_index => .{ aggregate_ty.slicePtrFieldType(zcu), .none }, + Value.slice_len_index => .{ .usize, .none }, + else => unreachable, + }; + }, + else => unreachable, + }; + const field_ptr_align: Alignment = a: { + if (aggregate_ty.zigTypeTag(zcu) == .@"struct" and aggregate_ty.structFieldIsComptime(field_index, zcu)) { + // For `comptime` fields, just use exactly what was specified, or ABI alignment if nothing was specified. + break :a field_align; + } + const actual_field_align = switch (field_align) { + .none => switch (ip.indexToKey(aggregate_ty.toIntern())) { + .tuple_type, .union_type => field_ty.abiAlignment(zcu), + .struct_type => field_ty.defaultStructFieldAlignment(.auto, zcu), + .ptr_type => Type.usize.abiAlignment(zcu), + else => unreachable, + }, + else => |a| a, + }; + const actual_aggregate_align = switch (ptr_info.flags.alignment) { + .none => aggregate_ty.abiAlignment(zcu), + else => |a| a, + }; + if (actual_aggregate_align.compareStrict(.lt, actual_field_align)) { + // Underaligned aggregate; use that alignment. + assert(ptr_info.flags.alignment != .none); + break :a actual_aggregate_align; + } + if (field_align == .none and actual_field_align == field_ty.abiAlignment(zcu)) { + // No explicit annotation on the field (nor an unusual default), and the aggregate + // alignment is irrelevant to us, so return an un-annotated pointer. + break :a .none; + } + break :a actual_field_align; + }; + var field_ptr_info = ptr_info; + field_ptr_info.flags.alignment = field_ptr_align; + field_ptr_info.child = field_ty.toIntern(); + return pt.ptrType(field_ptr_info); +} + pub fn containerTypeName(ty: Type, ip: *const InternPool) InternPool.NullTerminatedString { return switch (ip.indexToKey(ty.toIntern())) { .struct_type => ip.loadStructType(ty.toIntern()).name, diff --git a/src/Value.zig b/src/Value.zig index d158aa558c1c63a5cab26832774270680a61e5e7..5cc20853da7634efc3b0925d77fa01ab65c1e9a7 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -1687,9 +1687,6 @@ pub fn makeBool(x: bool) Value { /// `parent_ptr` must be a single-pointer or C pointer to some optional. /// /// Returns a pointer to the payload of the optional. -/// -/// May perform type resolution. -/// MLUGG TODO audit pub fn ptrOptPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value { const zcu = pt.zcu; const parent_ptr_ty = parent_ptr.typeOf(zcu); @@ -1715,7 +1712,7 @@ pub fn ptrOptPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value { } const base_ptr = try parent_ptr.canonicalizeBasePtr(.one, opt_ty, pt); - return Value.fromInterned(try pt.intern(.{ .ptr = .{ + return .fromInterned(try pt.intern(.{ .ptr = .{ .ty = result_ty.toIntern(), .base_addr = .{ .opt_payload = base_ptr.toIntern() }, .byte_offset = 0, @@ -1724,8 +1721,6 @@ pub fn ptrOptPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value { /// `parent_ptr` must be a single-pointer to some error union. /// Returns a pointer to the payload of the error union. -/// May perform type resolution. -/// MLUGG TODO audit pub fn ptrEuPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value { const zcu = pt.zcu; const parent_ptr_ty = parent_ptr.typeOf(zcu); @@ -1745,137 +1740,57 @@ pub fn ptrEuPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value { if (parent_ptr.isUndef(zcu)) return pt.undefValue(result_ty); const base_ptr = try parent_ptr.canonicalizeBasePtr(.one, eu_ty, pt); - return Value.fromInterned(try pt.intern(.{ .ptr = .{ + return .fromInterned(try pt.intern(.{ .ptr = .{ .ty = result_ty.toIntern(), .base_addr = .{ .eu_payload = base_ptr.toIntern() }, .byte_offset = 0, } })); } -// MLUGG TODO: audit ptrField etc in terms of resolution, and probably move them under sema - -/// `parent_ptr` must be a single-pointer or c pointer to a struct, union, or slice. +/// `parent_ptr` must be a single-item pointer or C pointer to a struct, union, or slice. /// /// Returns a pointer to the aggregate field at the specified index. /// /// For slices, uses `slice_ptr_index` and `slice_len_index`. /// -/// May perform type resolution. +/// Asserts that the layout of the aggregate type is resolved. pub fn ptrField(parent_ptr: Value, field_idx: u32, pt: Zcu.PerThread) !Value { const zcu = pt.zcu; const parent_ptr_ty = parent_ptr.typeOf(zcu); const aggregate_ty = parent_ptr_ty.childType(zcu); + aggregate_ty.assertHasLayout(zcu); const parent_ptr_info = parent_ptr_ty.ptrInfo(zcu); assert(parent_ptr_info.flags.size == .one or parent_ptr_info.flags.size == .c); - // Exiting this `switch` indicates that the `field` pointer representation should be used. - const field_ty: Type, const new_align: InternPool.Alignment = switch (aggregate_ty.zigTypeTag(zcu)) { - .@"struct" => field: { - const field_ty = aggregate_ty.fieldType(field_idx, zcu); - switch (aggregate_ty.containerLayout(zcu)) { - .auto => break :field .{ field_ty, a: { - if (parent_ptr_info.flags.alignment == .none) { - break :a aggregate_ty.explicitFieldAlignment(field_idx, zcu); - } - const field_align = aggregate_ty.resolvedFieldAlignment(field_idx, zcu); - break :a field_align.min(parent_ptr_info.flags.alignment); - } }, - .@"extern" => { - // Well-defined layout, so just offset the pointer appropriately. - const byte_off = aggregate_ty.structFieldOffset(field_idx, zcu); - const field_align: InternPool.Alignment = a: { - if (byte_off == 0) break :a parent_ptr_info.flags.alignment; - const true_field_align: InternPool.Alignment = .fromLog2Units(@ctz(byte_off)); - if (parent_ptr_info.flags.alignment == .none and - true_field_align == field_ty.abiAlignment(zcu)) - { - break :a .none; - } - const parent_align = if (parent_ptr_info.flags.alignment == .none) pa: { - break :pa aggregate_ty.abiAlignment(zcu); - } else parent_ptr_info.flags.alignment; - break :a .minStrict(true_field_align, parent_align); - }; - const result_ty = try pt.ptrType(info: { - var new = parent_ptr_info; - new.child = field_ty.toIntern(); - new.flags.alignment = field_align; - break :info new; - }); - return parent_ptr.getOffsetPtr(byte_off, result_ty, pt); - }, - .@"packed" => { - const packed_offset = aggregate_ty.packedStructFieldPtrInfo(parent_ptr_ty, field_idx, pt); - const result_ty = try pt.ptrType(info: { - var new = parent_ptr_info; - new.packed_offset = packed_offset; - new.child = field_ty.toIntern(); - if (new.flags.alignment == .none) { - new.flags.alignment = aggregate_ty.abiAlignment(zcu); - } - break :info new; - }); - return pt.getCoerced(parent_ptr, result_ty); - }, - } + const field_ptr_ty = try parent_ptr_ty.fieldPtrType(field_idx, pt); + + switch (aggregate_ty.zigTypeTag(zcu)) { + .pointer => assert(aggregate_ty.isSlice(zcu)), + .@"struct" => switch (aggregate_ty.containerLayout(zcu)) { + .auto => {}, + .@"extern" => return parent_ptr.getOffsetPtr( + aggregate_ty.structFieldOffset(field_idx, zcu), + field_ptr_ty, + pt, + ), + .@"packed" => return pt.getCoerced(parent_ptr, field_ptr_ty), }, - .@"union" => field: { - const union_obj = zcu.typeToUnion(aggregate_ty).?; - const field_ty = Type.fromInterned(union_obj.field_types.get(&zcu.intern_pool)[field_idx]); - switch (aggregate_ty.containerLayout(zcu)) { - .auto => break :field .{ field_ty, a: { - if (parent_ptr_info.flags.alignment == .none) { - break :a aggregate_ty.explicitFieldAlignment(field_idx, zcu); - } - const field_align = aggregate_ty.resolvedFieldAlignment(field_idx, zcu); - break :a field_align.min(parent_ptr_info.flags.alignment); - } }, - .@"extern" => { - // Point to the same address. - const result_ty = try pt.ptrType(info: { - var new = parent_ptr_info; - new.child = field_ty.toIntern(); - break :info new; - }); - return pt.getCoerced(parent_ptr, result_ty); - }, - .@"packed" => { - const result_ty = try pt.ptrType(info: { - var new = parent_ptr_info; - new.child = field_ty.toIntern(); - break :info new; - }); - return pt.getCoerced(parent_ptr, result_ty); - }, - } - }, - .pointer => field_ty: { - assert(aggregate_ty.isSlice(zcu)); - break :field_ty .{ switch (field_idx) { - Value.slice_ptr_index => aggregate_ty.slicePtrFieldType(zcu), - Value.slice_len_index => Type.usize, - else => unreachable, - }, switch (parent_ptr_info.flags.alignment) { - .none => .none, - else => Type.usize.abiAlignment(zcu).min(parent_ptr_info.flags.alignment), - } }; + .@"union" => switch (aggregate_ty.containerLayout(zcu)) { + .auto => {}, + .@"packed", .@"extern" => return pt.getCoerced(parent_ptr, field_ptr_ty), }, else => unreachable, - }; + } - const result_ty = try pt.ptrType(info: { - var new = parent_ptr_info; - new.child = field_ty.toIntern(); - new.flags.alignment = new_align; - break :info new; - }); + // If we get here, we need to use the `.field` comptime pointer representation, because the + // aggregate does not have a well-defined layout. - if (parent_ptr.isUndef(zcu)) return pt.undefValue(result_ty); + if (parent_ptr.isUndef(zcu)) return pt.undefValue(field_ptr_ty); const base_ptr = try parent_ptr.canonicalizeBasePtr(.one, aggregate_ty, pt); - return Value.fromInterned(try pt.intern(.{ .ptr = .{ - .ty = result_ty.toIntern(), + return .fromInterned(try pt.intern(.{ .ptr = .{ + .ty = field_ptr_ty.toIntern(), .base_addr = .{ .field = .{ .base = base_ptr.toIntern(), .index = field_idx, @@ -1884,10 +1799,9 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, pt: Zcu.PerThread) !Value { } })); } -/// `orig_parent_ptr` must be either a single-pointer to an array or vector, or a many-pointer or C-pointer or slice. +/// `orig_parent_ptr` must be either a single-pointer to an array, a slice, a many-item pointer, or a C pointer. /// Returns a pointer to the element at the specified index. -/// May perform type resolution. -/// MLUGG TODO AUDIT +/// Asserts that the layout of the pointer element type is resolved. pub fn ptrElem(orig_parent_ptr: Value, field_idx: u64, pt: Zcu.PerThread) !Value { const zcu = pt.zcu; const parent_ptr = switch (orig_parent_ptr.typeOf(zcu).ptrSize(zcu)) { @@ -1896,77 +1810,50 @@ pub fn ptrElem(orig_parent_ptr: Value, field_idx: u64, pt: Zcu.PerThread) !Value }; const parent_ptr_ty = parent_ptr.typeOf(zcu); - const elem_ty = parent_ptr_ty.childType(zcu); - const result_ty = try parent_ptr_ty.elemPtrType(@intCast(field_idx), pt); + const result_ty = try parent_ptr_ty.elemPtrType(field_idx, pt); + const elem_ty = result_ty.childType(zcu); + elem_ty.assertHasLayout(zcu); if (parent_ptr.isUndef(zcu)) return pt.undefValue(result_ty); - if (result_ty.ptrInfo(zcu).packed_offset.host_size != 0) { - // Since we have a bit-pointer, the pointer address should be unchanged. - assert(elem_ty.zigTypeTag(zcu) == .vector); + if (!elem_ty.comptimeOnly(zcu)) { + const byte_offset = field_idx * elem_ty.abiSize(zcu); + return parent_ptr.getOffsetPtr(byte_offset, result_ty, pt); + } + + // Comptime-only element type. + + if (field_idx == 0) { return pt.getCoerced(parent_ptr, result_ty); } - const PtrStrat = union(enum) { - offset: u64, - elem_ptr: Type, // many-ptr elem ty - }; - - const strat: PtrStrat = switch (parent_ptr_ty.ptrSize(zcu)) { - .one => switch (elem_ty.zigTypeTag(zcu)) { - .vector => .{ .offset = field_idx * @divExact(elem_ty.childType(zcu).bitSize(zcu), 8) }, - .array => strat: { - const arr_elem_ty = elem_ty.childType(zcu); - if (arr_elem_ty.comptimeOnly(zcu)) break :strat .{ .elem_ptr = arr_elem_ty }; - break :strat .{ .offset = field_idx * arr_elem_ty.abiSize(zcu) }; - }, - else => unreachable, - }, - - .many, .c => if (elem_ty.comptimeOnly(zcu)) - .{ .elem_ptr = elem_ty } - else - .{ .offset = field_idx * elem_ty.abiSize(zcu) }, - - .slice => unreachable, - }; - - switch (strat) { - .offset => |byte_offset| { - return parent_ptr.getOffsetPtr(byte_offset, result_ty, pt); - }, - .elem_ptr => |manyptr_elem_ty| if (field_idx == 0) { - return pt.getCoerced(parent_ptr, result_ty); - } else { - const arr_base_ty, const arr_base_len = manyptr_elem_ty.arrayBase(zcu); - const base_idx = arr_base_len * field_idx; - const parent_info = zcu.intern_pool.indexToKey(parent_ptr.toIntern()).ptr; - switch (parent_info.base_addr) { - .arr_elem => |arr_elem| { - if (Value.fromInterned(arr_elem.base).typeOf(zcu).childType(zcu).toIntern() == arr_base_ty.toIntern()) { - // We already have a pointer to an element of an array of this type. - // Just modify the index. - return Value.fromInterned(try pt.intern(.{ .ptr = ptr: { - var new = parent_info; - new.base_addr.arr_elem.index += base_idx; - new.ty = result_ty.toIntern(); - break :ptr new; - } })); - } - }, - else => {}, + const arr_base_ty, const arr_base_len = elem_ty.arrayBase(zcu); + const base_idx = arr_base_len * field_idx; + const parent_info = zcu.intern_pool.indexToKey(parent_ptr.toIntern()).ptr; + switch (parent_info.base_addr) { + .arr_elem => |arr_elem| { + if (Value.fromInterned(arr_elem.base).typeOf(zcu).childType(zcu).toIntern() == arr_base_ty.toIntern()) { + // We already have a pointer to an element of an array of this type. + // Just modify the index. + return .fromInterned(try pt.intern(.{ .ptr = ptr: { + var new = parent_info; + new.base_addr.arr_elem.index += base_idx; + new.ty = result_ty.toIntern(); + break :ptr new; + } })); } - const base_ptr = try parent_ptr.canonicalizeBasePtr(.many, arr_base_ty, pt); - return Value.fromInterned(try pt.intern(.{ .ptr = .{ - .ty = result_ty.toIntern(), - .base_addr = .{ .arr_elem = .{ - .base = base_ptr.toIntern(), - .index = base_idx, - } }, - .byte_offset = 0, - } })); }, + else => {}, } + const base_ptr = try parent_ptr.canonicalizeBasePtr(.many, arr_base_ty, pt); + return .fromInterned(try pt.intern(.{ .ptr = .{ + .ty = result_ty.toIntern(), + .base_addr = .{ .arr_elem = .{ + .base = base_ptr.toIntern(), + .index = base_idx, + } }, + .byte_offset = 0, + } })); } fn canonicalizeBasePtr(base_ptr: Value, want_size: std.builtin.Type.Pointer.Size, want_child: Type, pt: Zcu.PerThread) !Value { @@ -2062,19 +1949,11 @@ pub const PointerDeriveStep = union(enum) { } }; -pub fn pointerDerivation(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread) Allocator.Error!PointerDeriveStep { - return ptr_val.pointerDerivationAdvanced(arena, pt, false, null) catch |err| switch (err) { - error.OutOfMemory => |e| return e, - error.Canceled => @panic("TODO"), // pls remove from error set mlugg - error.AnalysisFail => unreachable, - }; -} - /// Given a pointer value, get the sequence of steps to derive it, ideally by taking /// only field and element pointers with no casts. This can be used by codegen backends /// which prefer field/elem accesses when lowering constant pointer values. /// It is also used by the Value printing logic for pointers. -pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread, comptime resolve_types: bool, opt_sema: ?*Sema) !PointerDeriveStep { +pub fn pointerDerivation(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread, opt_sema: ?*Sema) Allocator.Error!PointerDeriveStep { // MLUGG TODO: audit tf outta this code const zcu = pt.zcu; const ptr = zcu.intern_pool.indexToKey(ptr_val.toIntern()).ptr; @@ -2118,7 +1997,7 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh const base_ptr = Value.fromInterned(eu_ptr); const base_ptr_ty = base_ptr.typeOf(zcu); const parent_step = try arena.create(PointerDeriveStep); - parent_step.* = try pointerDerivationAdvanced(Value.fromInterned(eu_ptr), arena, pt, resolve_types, opt_sema); + parent_step.* = try pointerDerivation(.fromInterned(eu_ptr), arena, pt, opt_sema); break :base .{ .eu_payload_ptr = .{ .parent = parent_step, .result_ptr_ty = try pt.adjustPtrTypeChild(base_ptr_ty, base_ptr_ty.childType(zcu).errorUnionPayload(zcu)), @@ -2128,7 +2007,7 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh const base_ptr = Value.fromInterned(opt_ptr); const base_ptr_ty = base_ptr.typeOf(zcu); const parent_step = try arena.create(PointerDeriveStep); - parent_step.* = try pointerDerivationAdvanced(Value.fromInterned(opt_ptr), arena, pt, resolve_types, opt_sema); + parent_step.* = try pointerDerivation(.fromInterned(opt_ptr), arena, pt, opt_sema); break :base .{ .opt_payload_ptr = .{ .parent = parent_step, .result_ptr_ty = try pt.adjustPtrTypeChild(base_ptr_ty, base_ptr_ty.childType(zcu).optionalChild(zcu)), @@ -2137,48 +2016,27 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh .field => |field| base: { const base_ptr = Value.fromInterned(field.base); const base_ptr_ty = base_ptr.typeOf(zcu); - const agg_ty = base_ptr_ty.childType(zcu); - if (resolve_types) try opt_sema.?.ensureLayoutResolved(agg_ty, .unneeded); // MLUGG TODO: unneeded is a hack - const field_ty: Type, const field_align: InternPool.Alignment = switch (agg_ty.zigTypeTag(zcu)) { - .@"struct", .@"union" => .{ agg_ty.fieldType(@intCast(field.index), zcu), agg_ty.resolvedFieldAlignment(@intCast(field.index), pt.zcu) }, - .pointer => switch (field.index) { - Value.slice_ptr_index => .{ agg_ty.slicePtrFieldType(zcu), Type.ptrAbiAlignment(zcu.getTarget()) }, - Value.slice_len_index => .{ .usize, Type.abiAlignment(.usize, zcu) }, - else => unreachable, - }, - else => unreachable, - }; - const base_align = base_ptr_ty.ptrAlignment(zcu); - const result_align = field_align.minStrict(base_align); - const result_ty = try pt.ptrType(.{ - .child = field_ty.toIntern(), - .flags = flags: { - var flags = base_ptr_ty.ptrInfo(zcu).flags; - if (result_align == field_ty.abiAlignment(zcu)) { - flags.alignment = .none; - } else { - flags.alignment = result_align; - } - break :flags flags; - }, - }); const parent_step = try arena.create(PointerDeriveStep); - parent_step.* = try pointerDerivationAdvanced(base_ptr, arena, pt, resolve_types, opt_sema); + parent_step.* = try pointerDerivation(base_ptr, arena, pt, opt_sema); break :base .{ .field_ptr = .{ .parent = parent_step, .field_idx = @intCast(field.index), - .result_ptr_ty = result_ty, + .result_ptr_ty = try base_ptr_ty.fieldPtrType(@intCast(field.index), pt), } }; }, .arr_elem => |arr_elem| base: { const parent_step = try arena.create(PointerDeriveStep); - parent_step.* = try pointerDerivationAdvanced(Value.fromInterned(arr_elem.base), arena, pt, resolve_types, opt_sema); + parent_step.* = try pointerDerivation(.fromInterned(arr_elem.base), arena, pt, opt_sema); const parent_ptr_info = (try parent_step.ptrType(pt)).ptrInfo(zcu); const result_ptr_ty = try pt.ptrType(.{ .child = parent_ptr_info.child, .flags = flags: { var flags = parent_ptr_info.flags; flags.size = .one; + if (flags.alignment != .none) flags.alignment = .minStrict( + flags.alignment, + Type.fromInterned(parent_ptr_info.child).abiAlignment(zcu), + ); break :flags flags; }, }); @@ -2299,26 +2157,12 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh const end_off = start_off + field_ty.abiSize(zcu); if (cur_offset >= start_off and cur_offset + need_bytes <= end_off) { const old_ptr_ty = try cur_derive.ptrType(pt); - const parent_align = old_ptr_ty.ptrAlignment(zcu); - const field_align = InternPool.Alignment.fromLog2Units(@min(parent_align.toLog2Units(), @ctz(start_off))); const parent = try arena.create(PointerDeriveStep); parent.* = cur_derive; - const new_ptr_ty = try pt.ptrType(.{ - .child = field_ty.toIntern(), - .flags = flags: { - var flags = old_ptr_ty.ptrInfo(zcu).flags; - if (field_align == field_ty.abiAlignment(zcu)) { - flags.alignment = .none; - } else { - flags.alignment = field_align; - } - break :flags flags; - }, - }); cur_derive = .{ .field_ptr = .{ .parent = parent, .field_idx = @intCast(field_idx), - .result_ptr_ty = new_ptr_ty, + .result_ptr_ty = try old_ptr_ty.fieldPtrType(@intCast(field_idx), pt), } }; cur_offset -= start_off; break; diff --git a/src/Zcu.zig b/src/Zcu.zig index 9ae8e47a754aaf88121af4c800f2601b38fe0589..19702aee088915922972df9555c7a8a628529956 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -3813,9 +3813,9 @@ pub const AtomicPtrAlignmentDiagnostics = struct { max_bits: u16 = undefined, }; -/// If ABI alignment of `ty` is OK for atomic operations, returns 0. -/// Otherwise returns the alignment required on a pointer for the target -/// to perform atomic operations. +/// Returns the alignment required for the target to perform atomic operations on type `ty` (that +/// is, the required align attribute on the pointer). If the ABI alignment of `ty` is sufficient, +/// returns `.none`. // TODO this function does not take into account CPU features, which can affect // this value. Audit this! pub fn atomicPtrAlignment( diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 7de74743c3540370784ee7e26d50f052fa4a679e..703edd41152fa80601c25647114b42192408fa08 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -3943,10 +3943,7 @@ pub fn navPtrType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Allocator.Err return pt.ptrType(.{ .child = ty, .flags = .{ - .alignment = if (alignment == Type.fromInterned(ty).abiAlignment(zcu)) - .none - else - alignment, + .alignment = alignment, .address_space = @"addrspace", .is_const = is_const, }, @@ -4015,23 +4012,24 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace namespace.generation = zcu.generation; } -pub fn refValue(pt: Zcu.PerThread, val: InternPool.Index) Zcu.SemaError!InternPool.Index { - const ptr_ty = (try pt.ptrType(.{ - .child = pt.zcu.intern_pool.typeOf(val), +pub fn uavValue(pt: Zcu.PerThread, val: Value) Zcu.SemaError!Value { + const zcu = pt.zcu; + const ptr_ty = try pt.ptrType(.{ + .child = val.typeOf(zcu).toIntern(), .flags = .{ .alignment = .none, .is_const = true, .address_space = .generic, }, - })).toIntern(); - return pt.intern(.{ .ptr = .{ - .ty = ptr_ty, + }); + return .fromInterned(try pt.intern(.{ .ptr = .{ + .ty = ptr_ty.toIntern(), .base_addr = .{ .uav = .{ - .val = val, - .orig_ty = ptr_ty, + .val = val.toIntern(), + .orig_ty = ptr_ty.toIntern(), } }, .byte_offset = 0, - } }); + } })); } pub fn addDependency(pt: Zcu.PerThread, unit: AnalUnit, dependee: InternPool.Dependee) Allocator.Error!void { diff --git a/src/codegen/c.zig b/src/codegen/c.zig index f0df1aa1c0d0f072944a1f6d6dbd2bfc5f462f75..879dc0e45a649a24692c7b49d0af71de71f061c8 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1215,7 +1215,7 @@ pub const DeclGen = struct { .ptr => { var arena = std.heap.ArenaAllocator.init(zcu.gpa); defer arena.deinit(); - const derivation = try val.pointerDerivation(arena.allocator(), pt); + const derivation = try val.pointerDerivation(arena.allocator(), pt, null); try dg.renderPointer(w, derivation, location); }, .opt => |opt| switch (ctype.info(ctype_pool)) { diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig index 217581a72ce28eb36f6f0a08a78640124ad2e293..d303af6d610ded6effd8ff80e41cdab36650bd90 100644 --- a/src/codegen/spirv/CodeGen.zig +++ b/src/codegen/spirv/CodeGen.zig @@ -1038,7 +1038,7 @@ fn constantPtr(cg: *CodeGen, ptr_val: Value) !Id { var arena = std.heap.ArenaAllocator.init(gpa); defer arena.deinit(); - const derivation = try ptr_val.pointerDerivation(arena.allocator(), pt); + const derivation = try ptr_val.pointerDerivation(arena.allocator(), pt, null); return cg.derivePtr(derivation); } diff --git a/src/print_value.zig b/src/print_value.zig index d05fe09ec15416b21e5adfe7324f6375fd6d6ff5..46fbe63a6b12c2d755efffb62c2ef98a590af966 100644 --- a/src/print_value.zig +++ b/src/print_value.zig @@ -25,10 +25,7 @@ pub fn formatSema(ctx: FormatContext, writer: *Writer) Writer.Error!void { const sema = ctx.opt_sema.?; return print(ctx.val, writer, ctx.depth, ctx.pt, sema) catch |err| switch (err) { error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function - error.ComptimeBreak, error.ComptimeReturn => unreachable, - error.AnalysisFail => unreachable, // TODO: re-evaluate when we use `sema` more fully - error.Canceled => @panic("TODO"), // pls stop returning this error mlugg - else => |e| return e, + error.WriteFailed => |e| return e, }; } @@ -36,9 +33,7 @@ pub fn format(ctx: FormatContext, writer: *Writer) Writer.Error!void { std.debug.assert(ctx.opt_sema == null); return print(ctx.val, writer, ctx.depth, ctx.pt, null) catch |err| switch (err) { error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function - error.ComptimeBreak, error.ComptimeReturn, error.AnalysisFail => unreachable, - error.Canceled => @panic("TODO"), // pls stop returning this error mlugg - else => |e| return e, + error.WriteFailed => |e| return e, }; } @@ -48,7 +43,7 @@ pub fn print( level: u8, pt: Zcu.PerThread, opt_sema: ?*Sema, -) (Writer.Error || Zcu.CompileError)!void { +) (Writer.Error || Allocator.Error)!void { const zcu = pt.zcu; const ip = &zcu.intern_pool; switch (ip.indexToKey(val.toIntern())) { @@ -212,7 +207,7 @@ fn printAggregate( level: u8, pt: Zcu.PerThread, opt_sema: ?*Sema, -) (Writer.Error || Zcu.CompileError)!void { +) (Writer.Error || Allocator.Error)!void { if (level == 0) { if (is_ref) try writer.writeByte('&'); return writer.writeAll(".{ ... }"); @@ -307,7 +302,7 @@ fn printPtr( level: u8, pt: Zcu.PerThread, opt_sema: ?*Sema, -) (Writer.Error || Zcu.CompileError)!void { +) (Writer.Error || Allocator.Error)!void { const ptr = switch (pt.zcu.intern_pool.indexToKey(ptr_val.toIntern())) { .undef => return writer.writeAll("undefined"), .ptr => |ptr| ptr, @@ -332,10 +327,7 @@ fn printPtr( var arena = std.heap.ArenaAllocator.init(pt.zcu.gpa); defer arena.deinit(); - const derivation = if (opt_sema) |sema| - try ptr_val.pointerDerivationAdvanced(arena.allocator(), pt, true, sema) - else - try ptr_val.pointerDerivationAdvanced(arena.allocator(), pt, false, null); + const derivation = try ptr_val.pointerDerivation(arena.allocator(), pt, opt_sema); _ = try printPtrDerivation(derivation, writer, pt, want_kind, .{ .print_val = .{ .level = level, -- 2.54.0 From a9bfc94ee65f1dafe5c67bb8fbd58cd2372cfd28 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Mon, 2 Feb 2026 13:32:06 +0000 Subject: [PATCH 15/79] compiler: small misc cleanups --- lib/std/zig.zig | 4 +- src/Compilation.zig | 23 +++---- src/Sema.zig | 140 +++++++++++++++++++++++------------------- src/Zcu/PerThread.zig | 50 ++------------- 4 files changed, 94 insertions(+), 123 deletions(-) diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 26abf81a11a6b3707b84bd86f2b1a33a4b6b92b9..ca72dac442f36a5d4858780e0e9d61e021a553b7 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -868,7 +868,7 @@ pub const SimpleComptimeReason = enum(u32) { casted_to_comptime_enum, casted_to_comptime_int, casted_to_comptime_float, - panic_handler, + std_builtin_decl, pub fn message(r: SimpleComptimeReason) []const u8 { return switch (r) { @@ -957,7 +957,7 @@ pub const SimpleComptimeReason = enum(u32) { .casted_to_comptime_enum => "value casted to enum with 'comptime_int' tag type must be comptime-known", .casted_to_comptime_int => "value casted to 'comptime_int' must be comptime-known", .casted_to_comptime_float => "value casted to 'comptime_float' must be comptime-known", - .panic_handler => "panic handler must be comptime-known", + .std_builtin_decl => "'std.builtin' declaration values must be comptime-known", // zig fmt: on }; } diff --git a/src/Compilation.zig b/src/Compilation.zig index ba8a2907f9116e618941b6bad6e1cf2f35f76a7f..8b863c302202da3246c240f4612ec03e81f12afc 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -986,7 +986,9 @@ const Job = union(enum) { /// If the unit is a *test* function, an `analyze_func` job will also be queued. analyze_unit: InternPool.AnalUnit, /// The main source file for the module needs to be analyzed. - analyze_mod: *Package.Module, + /// For every module which is an analysis root, analyze the main struct type of the module's + /// root source file. This is how semantic analysis begins. + analyze_roots, /// The value is the index into `windows_libs`. windows_import_lib: usize, @@ -1396,7 +1398,6 @@ pub const MiscTask = enum { wasi_libc_crt_file, compiler_rt, libzigc, - analyze_mod, link_depfile, docs_copy, docs_wasm, @@ -4840,9 +4841,7 @@ fn performAllTheWork( try zcu.flushRetryableFailures(); // It's analysis time! Queue up our initial analysis. - for (zcu.analysisRoots()) |mod| { - try comp.queueJob(.{ .analyze_mod = mod }); - } + try comp.queueJob(.analyze_roots); zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); if (comp.bin_file != null) { @@ -5275,15 +5274,17 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v try pt.zcu.ensureFuncBodyAnalysisQueued(ip.getNav(nav).status.fully_resolved.val); } }, - .analyze_mod => |mod| { - const tracy_trace = traceNamed(@src(), "analyze_mod"); + .analyze_roots => { + const tracy_trace = traceNamed(@src(), "analyze_roots"); defer tracy_trace.end(); - const pt: Zcu.PerThread = .activate(comp.zcu.?, tid); + const zcu = comp.zcu.?; + const pt: Zcu.PerThread = .activate(zcu, tid); defer pt.deactivate(); - - const mod_root_file = pt.zcu.module_roots.get(mod).?.unwrap().?; - try pt.ensureFileAnalyzed(mod_root_file); + for (zcu.analysisRoots()) |analysis_root_mod| { + const analysis_root_file = zcu.module_roots.get(analysis_root_mod).?.unwrap().?; + try pt.ensureFileAnalyzed(analysis_root_file); + } }, .windows_import_lib => |index| { const tracy_trace = traceNamed(@src(), "windows_import_lib"); diff --git a/src/Sema.zig b/src/Sema.zig index fd4e067fe37d0705fb8c5722b970b777981ee7c4..799da305ed7495a8c78120dfe639b00798bb36d4 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2308,6 +2308,7 @@ pub fn resolveConstValue( /// being comptime-resolved is that the block is being comptime-evaluated. reason: ?ComptimeReason, ) CompileError!Value { + assert(reason != null or block.isComptime()); return sema.resolveValue(inst) orelse { return sema.failWithNeededComptime(block, src, reason); }; @@ -12927,6 +12928,8 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. try pt.ensureFileAnalyzed(file_index); const ty: Type = .fromInterned(zcu.fileRootType(file_index)); try sema.addTypeReferenceEntry(operand_src, ty); + // No need for `ensureNamespaceUpToDate`, because `Zcu.PerThread.updateFileNamespace` + // already made sure that all root file structs have up-to-date namespaces. return .fromType(ty); }, .zon => { @@ -16342,7 +16345,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const alignment_val = try pt.intValue(.comptime_int, bytes: { if (info.flags.alignment.toByteUnits()) |b| break :bytes b; const elem_ty: Type = .fromInterned(info.child); - // MLUGG TODO: this resolution is sus, but i doubt i'll solve it in this branch try sema.ensureLayoutResolved(elem_ty, src); break :bytes elem_ty.abiAlignment(zcu).toByteUnits().?; }); @@ -18942,12 +18944,13 @@ fn structInitAnon( .file_scope = block.getFileScopeIndex(zcu), .generation = zcu.generation, }); + errdefer pt.destroyNamespace(new_namespace_index); if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - break :ty .fromInterned(wip.finish(ip, new_namespace_index)); }, }; try sema.addTypeReferenceEntry(src, struct_ty); + // No need for `ensureNamespaceUpToDate` because this type's namespace is always empty. try sema.ensureLayoutResolved(struct_ty, src); _ = opt_runtime_index orelse { @@ -20150,6 +20153,7 @@ fn zirReifyStruct( })) { .existing => |ty| { try sema.addTypeReferenceEntry(src, .fromInterned(ty)); + // No need for `ensureNamespaceUpToDate` because this type's namespace is always empty. return .fromIntern(ty); }, .wip => |wip| { @@ -20210,9 +20214,9 @@ fn zirReifyStruct( .file_scope = block.getFileScopeIndex(zcu), .generation = zcu.generation, }); - try sema.addTypeReferenceEntry(src, .fromInterned(wip.index)); + errdefer pt.destroyNamespace(new_namespace_index); if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - + try sema.addTypeReferenceEntry(src, .fromInterned(wip.index)); return .fromIntern(wip.finish(ip, new_namespace_index)); }, } @@ -20393,6 +20397,7 @@ fn zirReifyUnion( })) { .existing => |ty| { try sema.addTypeReferenceEntry(src, .fromInterned(ty)); + // No need for `ensureNamespaceUpToDate` because this type's namespace is always empty. return .fromIntern(ty); }, .wip => |wip| { @@ -20430,9 +20435,9 @@ fn zirReifyUnion( .file_scope = block.getFileScopeIndex(zcu), .generation = zcu.generation, }); + errdefer pt.destroyNamespace(new_namespace_index); if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); try sema.addTypeReferenceEntry(src, .fromInterned(wip.index)); - return .fromIntern(wip.finish(ip, new_namespace_index)); }, } @@ -20557,6 +20562,7 @@ fn zirReifyEnum( })) { .existing => |ty| { try sema.addTypeReferenceEntry(src, .fromInterned(ty)); + // No need for `ensureNamespaceUpToDate` because this type's namespace is always empty. return .fromIntern(ty); }, .wip => |wip| { @@ -20581,10 +20587,9 @@ fn zirReifyEnum( .file_scope = block.getFileScopeIndex(zcu), .generation = zcu.generation, }); - - try sema.addTypeReferenceEntry(src, .fromInterned(wip.index)); + errdefer pt.destroyNamespace(new_namespace_index); if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - + try sema.addTypeReferenceEntry(src, .fromInterned(wip.index)); return .fromIntern(wip.finish(ip, new_namespace_index)); }, } @@ -33861,7 +33866,7 @@ pub fn resolveNavPtrModifiers( }; } -pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, builtin_namespace: InternPool.NamespaceIndex, stage: InternPool.MemoizedStateStage) CompileError!bool { +pub fn analyzeMemoizedState(sema: *Sema, stage: InternPool.MemoizedStateStage) CompileError!bool { const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; @@ -33869,53 +33874,87 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, const io = comp.io; const ip = &zcu.intern_pool; + // This `Block` acts kind of like it's evaluating a `comptime` declaration in the root source + // file of the standard library. In particular, its namespace is the root std namespace. + var block: Block = block: { + // Get the main struct type of the root source file of `std`. No need for a reference entry + // because `std` is always an analysis root. + const std_file_index = zcu.module_roots.get(zcu.std_mod).?.unwrap().?; + try pt.ensureFileAnalyzed(std_file_index); + const std_type: Type = .fromInterned(zcu.fileRootType(std_file_index)); + break :block .{ + .parent = null, + .sema = sema, + .namespace = std_type.getNamespaceIndex(zcu), + .instructions = .empty, + .inlining = null, + .comptime_reason = null, + .src_base_inst = std_type.typeDeclInst(zcu).?, + .type_name_ctx = .empty, + }; + }; + defer block.instructions.deinit(gpa); + + const std_builtin_ty: Type = ty: { + const std_src = block.nodeOffset(.zero); + const decl_name = try ip.getOrPutString(gpa, io, pt.tid, "builtin", .no_embedded_nulls); + const nav = try sema.namespaceLookup(&block, std_src, block.namespace, decl_name) orelse { + return sema.fail(&block, std_src, "'std' missing 'builtin'", .{}); + }; + const uncoerced_val = try sema.analyzeNavVal(&block, std_src, nav); + const decl_src: LazySrcLoc = .{ + .base_node_inst = ip.getNav(nav).srcInst(ip), + .offset = .nodeOffset(.zero), + }; + break :ty try sema.analyzeAsType(&block, decl_src, .std_builtin_decl, uncoerced_val); + }; + var any_changed = false; inline for (comptime std.enums.values(Zcu.BuiltinDecl)) |builtin_decl| { if (stage == comptime builtin_decl.stage()) { - const parent_ns: Zcu.Namespace.Index, const parent_name: []const u8, const name: []const u8 = switch (comptime builtin_decl.access()) { - .direct => |name| .{ builtin_namespace, "std.builtin", name }, + const parent_ns_ty: Type, const parent_name: []const u8, const name: []const u8 = switch (comptime builtin_decl.access()) { + .direct => |name| .{ std_builtin_ty, "std.builtin", name }, .nested => |nested| access: { - const parent_ty: Type = .fromInterned(zcu.builtin_decl_values.get(nested[0])); - const parent_ns = parent_ty.getNamespace(zcu).unwrap() orelse { - return sema.fail(block, simple_src, "std.builtin.{s} is not a container type", .{@tagName(nested[0])}); - }; - break :access .{ parent_ns, "std.builtin." ++ @tagName(nested[0]), nested[1] }; + const parent_decl, const name = nested; + const parent_ty: Type = .fromInterned(zcu.builtin_decl_values.get(parent_decl)); + break :access .{ parent_ty, "std.builtin." ++ @tagName(parent_decl), name }; }, }; + const parent_ns = parent_ns_ty.getNamespace(zcu).unwrap() orelse { + return sema.fail(&block, block.nodeOffset(.zero), "'{s}' is not a container type", .{parent_name}); + }; + const parent_ty_src = parent_ns_ty.srcLoc(zcu); const name_nts = try ip.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls); - const nav = try sema.namespaceLookup(block, simple_src, parent_ns, name_nts) orelse - return sema.fail(block, simple_src, "{s} missing {s}", .{ parent_name, name }); + const nav = try sema.namespaceLookup(&block, parent_ty_src, parent_ns, name_nts) orelse { + return sema.fail(&block, parent_ty_src, "'{s}' missing '{s}'", .{ parent_name, name }); + }; + const uncoerced_val = try sema.analyzeNavVal(&block, parent_ty_src, nav); - const src: LazySrcLoc = .{ + const decl_src: LazySrcLoc = .{ .base_node_inst = ip.getNav(nav).srcInst(ip), .offset = .nodeOffset(.zero), }; - const result = try sema.analyzeNavVal(block, src, nav); - - const uncoerced_val = try sema.resolveConstDefinedValue(block, src, result, null); const val: Value = switch (builtin_decl.kind()) { - .type => if (uncoerced_val.typeOf(zcu).zigTypeTag(zcu) != .type) { - return sema.fail(block, src, "{s}.{s} is not a type", .{ parent_name, name }); - } else val: { - try sema.ensureLayoutResolved(uncoerced_val.toType(), src); - break :val uncoerced_val; + .type => val: { + const ty = try sema.analyzeAsType(&block, decl_src, .std_builtin_decl, uncoerced_val); + try sema.ensureLayoutResolved(ty, decl_src); + break :val ty.toValue(); }, .func => val: { const func_ty = try sema.getExpectedBuiltinFnType(builtin_decl); - const coerced = try sema.coerce(block, func_ty, Air.internedToRef(uncoerced_val.toIntern()), src); - break :val .fromInterned(coerced.toInterned().?); + const coerced = try sema.coerce(&block, func_ty, uncoerced_val, decl_src); + break :val try sema.resolveConstDefinedValue(&block, decl_src, coerced, .{ .simple = .std_builtin_decl }); }, .string => val: { - const coerced = try sema.coerce(block, .slice_const_u8, Air.internedToRef(uncoerced_val.toIntern()), src); - break :val .fromInterned(coerced.toInterned().?); + const coerced = try sema.coerce(&block, .slice_const_u8, uncoerced_val, decl_src); + break :val try sema.resolveConstDefinedValue(&block, decl_src, coerced, .{ .simple = .std_builtin_decl }); }, }; - const prev = zcu.builtin_decl_values.get(builtin_decl); - if (val.toIntern() != prev) { + if (zcu.builtin_decl_values.get(builtin_decl) != val.toIntern()) { zcu.builtin_decl_values.set(builtin_decl, val.toIntern()); any_changed = true; } @@ -34147,21 +34186,15 @@ fn zirStructDecl( }); errdefer pt.destroyNamespace(new_namespace_index); try pt.scanNamespace(new_namespace_index, struct_decl.decls); - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - break :ty .fromInterned(wip.finish(ip, new_namespace_index)); }, }; try sema.addTypeReferenceEntry(src, ty); - - // Make sure we update the namespace if the declaration is re-analyzed, to pick - // up on e.g. changed comptime decls. - // TODO MLUGG: me no likey, maybe model namespaces less badly idk try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)); - return .fromIntern(ty.toIntern()); + return .fromType(ty); } fn zirUnionDecl( sema: *Sema, @@ -34218,7 +34251,6 @@ fn zirUnionDecl( .wip => |wip| ty: { errdefer wip.cancel(ip, pt.tid); try sema.setTypeName(block, &wip, union_decl.name_strategy, "union", inst); - const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ .parent = block.namespace.toOptional(), .owner_type = wip.index, @@ -34226,23 +34258,16 @@ fn zirUnionDecl( .generation = zcu.generation, }); errdefer pt.destroyNamespace(new_namespace_index); - try pt.scanNamespace(new_namespace_index, union_decl.decls); - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - break :ty .fromInterned(wip.finish(ip, new_namespace_index)); }, }; try sema.addTypeReferenceEntry(src, ty); - - // Make sure we update the namespace if the declaration is re-analyzed, to pick - // up on e.g. changed comptime decls. - // TODO MLUGG: me no likey, maybe model namespaces less badly idk try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)); - return .fromIntern(ty.toIntern()); + return .fromType(ty); } fn zirEnumDecl( sema: *Sema, @@ -34277,9 +34302,7 @@ fn zirEnumDecl( .existing => |ty| .fromInterned(ty), .wip => |wip| ty: { errdefer wip.cancel(ip, pt.tid); - try sema.setTypeName(block, &wip, enum_decl.name_strategy, "enum", inst); - const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{ .parent = block.namespace.toOptional(), .owner_type = wip.index, @@ -34287,23 +34310,16 @@ fn zirEnumDecl( .generation = zcu.generation, }); errdefer pt.destroyNamespace(new_namespace_index); - try pt.scanNamespace(new_namespace_index, enum_decl.decls); - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - break :ty .fromInterned(wip.finish(ip, new_namespace_index)); }, }; try sema.addTypeReferenceEntry(src, ty); - - // Make sure we update the namespace if the declaration is re-analyzed, to pick - // up on e.g. changed comptime decls. - // TODO MLUGG: me no likey, maybe model namespaces less badly idk try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)); - return .fromIntern(ty.toIntern()); + return .fromType(ty); } fn zirOpaqueDecl( sema: *Sema, @@ -34350,11 +34366,7 @@ fn zirOpaqueDecl( }; try sema.addTypeReferenceEntry(src, ty); - - // Make sure we update the namespace if the declaration is re-analyzed, to pick - // up on e.g. changed comptime decls. - // TODO MLUGG: me no likey, maybe model namespaces less badly idk try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu)); - return .fromIntern(ty.toIntern()); + return .fromType(ty); } diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 703edd41152fa80601c25647114b42192408fa08..8d6af9c3ad7c4e688be88323f3578ce571a2f500 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -688,6 +688,8 @@ pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Alloca if (zcu.fileRootType(file_index) != .none) return; // already good + if (zcu.comp.time_report) |*tr| tr.stats.n_imported_files += 1; + const file = zcu.fileByIndex(file_index); assert(file.getMode() == .zig); const struct_decl = file.zir.?.getStructDecl(.main_struct_inst); @@ -719,13 +721,8 @@ pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Alloca }); errdefer pt.destroyNamespace(new_namespace_index); try pt.scanNamespace(new_namespace_index, struct_decl.decls); - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); - - const file_root_type: Type = .fromInterned(wip.finish(ip, new_namespace_index)); - - zcu.setFileRootType(file_index, file_root_type.toIntern()); - if (zcu.comp.time_report) |*tr| tr.stats.n_imported_files += 1; + zcu.setFileRootType(file_index, wip.finish(ip, new_namespace_index)); } /// Ensures that all memoized state on `Zcu` is up-to-date, performing re-analysis if necessary. @@ -810,37 +807,14 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage) Zcu.CompileError!bool { const zcu = pt.zcu; - const ip = &zcu.intern_pool; const comp = zcu.comp; const gpa = comp.gpa; - const io = comp.io; const unit: AnalUnit = .wrap(.{ .memoized_state = stage }); try zcu.analysis_in_progress.putNoClobber(gpa, unit, {}); defer assert(zcu.analysis_in_progress.swapRemove(unit)); - // Before we begin, collect: - // * The type `std`, and its namespace - // * The type `std.builtin`, and its namespace - // * A semi-reasonable source location - const std_file_index = zcu.module_roots.get(zcu.std_mod).?.unwrap().?; - try pt.ensureFileAnalyzed(std_file_index); - const std_type: Type = .fromInterned(zcu.fileRootType(std_file_index)); - const std_namespace = std_type.getNamespaceIndex(zcu); - try pt.ensureNamespaceUpToDate(std_namespace); - const builtin_str = try ip.getOrPutString(gpa, io, pt.tid, "builtin", .no_embedded_nulls); - const builtin_nav = zcu.namespacePtr(std_namespace).pub_decls.getKeyAdapted(builtin_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse - @panic("lib/std.zig is corrupt and missing 'builtin'"); - try pt.ensureNavValUpToDate(builtin_nav); - const builtin_type: Type = .fromInterned(ip.getNav(builtin_nav).status.fully_resolved.val); - const builtin_namespace = builtin_type.getNamespaceIndex(zcu); - try pt.ensureNamespaceUpToDate(builtin_namespace); - const src: Zcu.LazySrcLoc = .{ - .base_node_inst = builtin_type.typeDeclInst(zcu).?, - .offset = .{ .byte_abs = 0 }, - }; - var analysis_arena: std.heap.ArenaAllocator = .init(gpa); defer analysis_arena.deinit(); @@ -861,22 +835,7 @@ fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage) }; defer sema.deinit(); - var block: Sema.Block = .{ - .parent = null, - .sema = &sema, - .namespace = std_namespace, - .instructions = .empty, - .inlining = null, - .comptime_reason = .{ .reason = .{ - .src = src, - .r = .{ .simple = .type }, - } }, - .src_base_inst = src.base_node_inst, - .type_name_ctx = .empty, - }; - defer block.instructions.deinit(gpa); - - return sema.analyzeMemoizedState(&block, src, builtin_namespace, stage); + return sema.analyzeMemoizedState(stage); } /// Ensures that the state of the given `ComptimeUnit` is fully up-to-date, performing re-analysis @@ -1966,7 +1925,6 @@ fn analyzeFuncBody( /// If the file's root struct type is not populated (the file is unreferenced), nothing is done. /// This is called by `updateZirRefs` for all updated files before the main work loop. /// This function does not perform any semantic analysis. -/// MLUGG TODO: mmmmm i have no idea if this makes sense... tbhwy i just want to update all *changed* namespaces at the start of an update or something lol fn updateFileNamespace(pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator.Error!void { const zcu = pt.zcu; -- 2.54.0 From 1826ba69d81e182f6bd7cf4ea9b944bd6c713a28 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Wed, 4 Feb 2026 13:59:07 +0000 Subject: [PATCH 16/79] compiler: make dependency loop errors good --- lib/std/zig/ErrorBundle.zig | 4 + src/Compilation.zig | 115 +------- src/Sema.zig | 262 ++++++++++-------- src/Sema/LowerZon.zig | 10 +- src/Sema/type_resolution.zig | 93 +++++-- src/Zcu.zig | 364 +++++++++++++++++++++++--- src/Zcu/PerThread.zig | 224 +++++++--------- test/incremental/type_dependency_loop | 55 ++++ tools/incr-check.zig | 76 +++--- 9 files changed, 763 insertions(+), 440 deletions(-) create mode 100644 test/incremental/type_dependency_loop diff --git a/lib/std/zig/ErrorBundle.zig b/lib/std/zig/ErrorBundle.zig index 64aafd110efb9a4d8247450ac85049286871e05a..ef3cd3d783509ca7de73eba085f6f411d7cc0a30 100644 --- a/lib/std/zig/ErrorBundle.zig +++ b/lib/std/zig/ErrorBundle.zig @@ -243,12 +243,14 @@ fn renderErrorMessage( } try t.setColor(.reset); if (src.data.source_line != 0 and options.include_source_line) { + try w.splatByteAll(' ', indent); const line = eb.nullTerminatedString(src.data.source_line); for (line) |b| switch (b) { '\t' => try w.writeByte(' '), else => try w.writeByte(b), }; try w.writeByte('\n'); + try w.splatByteAll(' ', indent); // TODO basic unicode code point monospace width const before_caret = src.data.span_main - src.data.span_start; // -1 since span.main includes the caret @@ -267,11 +269,13 @@ fn renderErrorMessage( if (src.data.reference_trace_len > 0 and options.include_reference_trace) { try t.setColor(.reset); try t.setColor(.dim); + try w.splatByteAll(' ', indent); try w.print("referenced by:\n", .{}); var ref_index = src.end; for (0..src.data.reference_trace_len) |_| { const ref_trace = eb.extraData(ReferenceTrace, ref_index); ref_index = ref_trace.end; + try w.splatByteAll(' ', indent); if (ref_trace.data.src_loc != .none) { const ref_src = eb.getSourceLocation(ref_trace.data.src_loc); try w.print(" {s}: {s}:{d}:{d}\n", .{ diff --git a/src/Compilation.zig b/src/Compilation.zig index 8b863c302202da3246c240f4612ec03e81f12afc..59fa186d82804de016b8f5c241976992b70c3174 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -4189,6 +4189,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { } } } + try zcu.addDependencyLoopErrors(&bundle); for (zcu.failed_codegen.values()) |error_msg| { try addModuleErrorMsg(zcu, &bundle, error_msg.*, false); } @@ -4208,7 +4209,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { .notes_len = 1, }); const notes_start = try bundle.reserveNotes(1); - bundle.extra.items[notes_start] = @intFromEnum(try bundle.addErrorMessage(.{ + bundle.extra.items[notes_start] = @intFromEnum(bundle.addErrorMessageAssumeCapacity(.{ .msg = try bundle.printString("use '--error-limit {d}' to increase limit", .{ actual_error_count, }), @@ -4230,10 +4231,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { .notes_len = 2, }); const notes_start = try bundle.reserveNotes(2); - bundle.extra.items[notes_start + 0] = @intFromEnum(try bundle.addErrorMessage(.{ + bundle.extra.items[notes_start + 0] = @intFromEnum(bundle.addErrorMessageAssumeCapacity(.{ .msg = try bundle.addString("run 'zig libc -h' to learn about libc installations"), })); - bundle.extra.items[notes_start + 1] = @intFromEnum(try bundle.addErrorMessage(.{ + bundle.extra.items[notes_start + 1] = @intFromEnum(bundle.addErrorMessageAssumeCapacity(.{ .msg = try bundle.addString("run 'zig targets' to see the targets for which zig can always provide libc"), })); } @@ -4428,7 +4429,6 @@ pub fn addModuleErrorMsg( already_added_error: bool, ) Allocator.Error!void { const gpa = eb.gpa; - const ip = &zcu.intern_pool; const err_src_loc = module_err_msg.src_loc.upgrade(zcu); const err_source = err_src_loc.file_scope.getSource(zcu) catch |err| { return unableToLoadZcuFile(zcu, eb, err_src_loc.file_scope, err); @@ -4441,66 +4441,12 @@ pub fn addModuleErrorMsg( var ref_traces: std.ArrayList(ErrorBundle.ReferenceTrace) = .empty; defer ref_traces.deinit(gpa); - rt: { - const rt_root = module_err_msg.reference_trace_root.unwrap() orelse break :rt; - const max_references = zcu.comp.reference_trace orelse refs: { - if (already_added_error) break :rt; + if (module_err_msg.reference_trace_root.unwrap()) |root| { + const frame_limit: u32 = zcu.comp.reference_trace orelse refs: { + if (already_added_error) break :refs 0; break :refs default_reference_trace_len; }; - - const all_references = try zcu.resolveReferences(); - - var seen: std.AutoHashMapUnmanaged(InternPool.AnalUnit, void) = .empty; - defer seen.deinit(gpa); - - var referenced_by = rt_root; - while (all_references.get(referenced_by)) |maybe_ref| { - const ref = maybe_ref orelse break; - const gop = try seen.getOrPut(gpa, ref.referencer); - if (gop.found_existing) break; - if (ref_traces.items.len < max_references) { - var last_call_src = ref.src; - var opt_inline_frame = ref.inline_frame; - while (opt_inline_frame.unwrap()) |inline_frame| { - const f = inline_frame.ptr(zcu).*; - const func_nav = ip.indexToKey(f.callee).func.owner_nav; - const func_name = ip.getNav(func_nav).name.toSlice(ip); - addReferenceTraceFrame(zcu, eb, &ref_traces, func_name, last_call_src, true) catch |err| switch (err) { - error.OutOfMemory => |e| return e, - error.AlreadyReported => { - // An incomplete reference trace isn't the end of the world; just cut it off. - break :rt; - }, - }; - last_call_src = f.call_src; - opt_inline_frame = f.parent; - } - const root_name: ?[]const u8 = switch (ref.referencer.unwrap()) { - .@"comptime" => "comptime", - .nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip), - .type_layout => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), - .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip), - .memoized_state => null, - }; - if (root_name) |n| { - addReferenceTraceFrame(zcu, eb, &ref_traces, n, last_call_src, false) catch |err| switch (err) { - error.OutOfMemory => |e| return e, - error.AlreadyReported => { - // An incomplete reference trace isn't the end of the world; just cut it off. - break :rt; - }, - }; - } - } - referenced_by = ref.referencer; - } - - if (seen.count() > ref_traces.items.len) { - try ref_traces.append(gpa, .{ - .decl_name = @intCast(seen.count() - ref_traces.items.len), - .src_loc = .none, - }); - } + try zcu.populateReferenceTrace(root, frame_limit, eb, &ref_traces); } const src_loc = try eb.addSourceLocation(.{ @@ -4565,43 +4511,10 @@ pub fn addModuleErrorMsg( const notes_start = try eb.reserveNotes(notes_len); for (notes_start.., notes.keys()) |i, note| { - eb.extra.items[i] = @intFromEnum(try eb.addErrorMessage(note)); + eb.extra.items[i] = @intFromEnum(eb.addErrorMessageAssumeCapacity(note)); } } -fn addReferenceTraceFrame( - zcu: *Zcu, - eb: *ErrorBundle.Wip, - ref_traces: *std.ArrayList(ErrorBundle.ReferenceTrace), - name: []const u8, - lazy_src: Zcu.LazySrcLoc, - inlined: bool, -) error{ OutOfMemory, AlreadyReported }!void { - const gpa = zcu.gpa; - const src = lazy_src.upgrade(zcu); - const source = src.file_scope.getSource(zcu) catch |err| { - try unableToLoadZcuFile(zcu, eb, src.file_scope, err); - return error.AlreadyReported; - }; - const span = src.span(zcu) catch |err| { - try unableToLoadZcuFile(zcu, eb, src.file_scope, err); - return error.AlreadyReported; - }; - const loc = std.zig.findLineColumn(source, span.main); - try ref_traces.append(gpa, .{ - .decl_name = try eb.printString("{s}{s}", .{ name, if (inlined) " [inlined]" else "" }), - .src_loc = try eb.addSourceLocation(.{ - .src_path = try eb.printString("{f}", .{src.file_scope.path.fmt(zcu.comp)}), - .span_start = span.start, - .span_main = span.main, - .span_end = span.end, - .line = @intCast(loc.line), - .column = @intCast(loc.column), - .source_line = 0, - }), - }); -} - fn addWholeFileError( zcu: *Zcu, eb: *ErrorBundle.Wip, @@ -5243,11 +5156,11 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v const maybe_err: Zcu.SemaError!void = switch (unit.unwrap()) { .@"comptime" => |cu| pt.ensureComptimeUnitUpToDate(cu), - .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav), - .nav_val => |nav| pt.ensureNavValUpToDate(nav), - .type_layout => |ty| pt.ensureTypeLayoutUpToDate(.fromInterned(ty)), - .memoized_state => |stage| pt.ensureMemoizedStateUpToDate(stage), - .func => |func| pt.ensureFuncBodyUpToDate(func), + .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav, null), + .nav_val => |nav| pt.ensureNavValUpToDate(nav, null), + .type_layout => |ty| pt.ensureTypeLayoutUpToDate(.fromInterned(ty), null), + .memoized_state => |stage| pt.ensureMemoizedStateUpToDate(stage, null), + .func => |func| pt.ensureFuncBodyUpToDate(func, null), }; maybe_err catch |err| switch (err) { error.OutOfMemory => |e| return e, diff --git a/src/Sema.zig b/src/Sema.zig index 799da305ed7495a8c78120dfe639b00798bb36d4..cbfe6421db8b7fc50a3954664eb93e3c0ff295f5 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -3260,7 +3260,7 @@ fn zirAllocExtended( } else .none; if (small.has_type) { - try sema.ensureLayoutResolved(var_ty, ty_src); + try sema.ensureLayoutResolved(var_ty, var_src, if (small.is_const) .constant else .variable); if (block.isComptime() or small.is_comptime or var_ty.comptimeOnly(zcu)) { return sema.analyzeComptimeAlloc(block, var_src, var_ty, alignment); } @@ -3324,7 +3324,7 @@ fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); const var_src = block.nodeOffset(inst_data.src_node); const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); - try sema.ensureLayoutResolved(var_ty, ty_src); + try sema.ensureLayoutResolved(var_ty, var_src, .variable); return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none); } @@ -3758,7 +3758,7 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I const var_src = block.nodeOffset(inst_data.src_node); const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); - try sema.ensureLayoutResolved(var_ty, ty_src); + try sema.ensureLayoutResolved(var_ty, var_src, .constant); if (block.isComptime() or var_ty.comptimeOnly(zcu)) { return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none); } @@ -3790,7 +3790,7 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const var_src = block.nodeOffset(inst_data.src_node); const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); - try sema.ensureLayoutResolved(var_ty, ty_src); + try sema.ensureLayoutResolved(var_ty, var_src, .variable); if (block.isComptime()) { return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none); } @@ -4148,7 +4148,7 @@ fn zirOptEuBasePtrInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compile const un_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const ptr = sema.resolveInst(un_node.operand); const src = block.nodeOffset(un_node.src_node); - try sema.ensureLayoutResolved(sema.typeOf(ptr).childType(sema.pt.zcu), src); + try sema.ensureLayoutResolved(sema.typeOf(ptr).childType(sema.pt.zcu), src, .init); return sema.optEuBasePtrInit(block, ptr, src); } @@ -4651,7 +4651,7 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr } const elem_ty = operand_ty.childType(zcu); - try sema.ensureLayoutResolved(elem_ty, src); + try sema.ensureLayoutResolved(elem_ty, src, .ptr_access); const need_comptime = switch (elem_ty.classify(zcu)) { .no_possible_value => return sema.fail(block, src, "cannot load {s} type '{f}'", .{ @@ -7037,7 +7037,7 @@ fn analyzeCall( break :ret_ty full_ty; }; - try sema.ensureLayoutResolved(resolved_ret_ty, func_ret_ty_src); + try sema.ensureLayoutResolved(resolved_ret_ty, func_ret_ty_src, .return_type); // If we've discovered after evaluating arguments that a generic function instantiation is // comptime-only, then we can mark the block as comptime *now*. @@ -7134,7 +7134,6 @@ fn analyzeCall( .generic_owner = func_val.?.toIntern(), .comptime_args = comptime_args, }); - try sema.ensureLayoutResolved(.fromInterned(ip.typeOf(func_instance)), call_src); if (zcu.comp.debugIncremental()) { const nav = ip.indexToKey(func_instance).func.owner_nav; const gop = try zcu.incremental_debug_state.navs.getOrPut(gpa, nav); @@ -7169,7 +7168,7 @@ fn analyzeCall( }; try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).@"struct".fields.len + runtime_args.len); - const maybe_opv = try block.addInst(.{ + const call_ref = try block.addInst(.{ .tag = call_tag, .data = .{ .pl_op = .{ .operand = runtime_func, @@ -7180,8 +7179,10 @@ fn analyzeCall( }); sema.appendRefsAssumeCapacity(runtime_args); + const actual_ret_ty = sema.typeOf(call_ref); + if (ensure_result_used) { - try sema.ensureResultUsed(block, sema.typeOf(maybe_opv), call_src); + try sema.ensureResultUsed(block, actual_ret_ty, call_src); } if (call_tag == .call_always_tail) { @@ -7191,28 +7192,31 @@ fn analyzeCall( .pointer => func_or_ptr_ty.childType(zcu), else => unreachable, }; - return sema.handleTailCall(block, call_src, runtime_func_ty, maybe_opv); + return sema.handleTailCall(block, call_src, runtime_func_ty, call_ref); } - if (resolved_ret_ty.isNoReturn(zcu)) { - const want_check = c: { - if (!block.wantSafety()) break :c false; - if (func_val != null) break :c false; - break :c true; - }; - if (want_check) { - try sema.safetyPanic(block, call_src, .noreturn_returned); - } else { - _ = try block.addNoOp(.unreach); - } - return .unreachable_value; - } - - try sema.ensureLayoutResolved(sema.typeOf(maybe_opv), func_ret_ty_src); - if (try sema.typeOf(maybe_opv).onePossibleValue(pt)) |opv| { - return .fromValue(opv); - } else { - return maybe_opv; + switch (actual_ret_ty.classify(zcu)) { + .no_possible_value => { + const want_check = c: { + if (!block.wantSafety()) break :c false; + if (func_val != null) break :c false; + break :c true; + }; + if (want_check) { + try sema.safetyPanic(block, call_src, .noreturn_returned); + } else { + _ = try block.addNoOp(.unreach); + } + return .unreachable_value; + }, + .one_possible_value => { + return .fromValue((try actual_ret_ty.onePossibleValue(pt)).?); + }, + .runtime => { + return call_ref; + }, + .partially_comptime => unreachable, + .fully_comptime => unreachable, } } @@ -7279,11 +7283,6 @@ fn analyzeCall( } } - // We're about to do an inline call; if the return type expression was generic, the return type - // may not be resolved yet. It's correct to resolve it because the function is going to return a - // value of this type. - try sema.ensureLayoutResolved(resolved_ret_ty, func_ret_ty_src); - // For an inline call, we depend on the source code of the whole function definition. try sema.declareDependency(.{ .src_hash = fn_nav.analysis.?.zir_index }); @@ -8051,7 +8050,7 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError if (dest_ty.zigTypeTag(zcu) != .@"enum") { return sema.fail(block, src, "expected enum, found '{f}'", .{dest_ty.fmt(pt)}); } - try sema.ensureLayoutResolved(dest_ty, src); + try sema.ensureLayoutResolved(dest_ty, src, .init); _ = try sema.checkIntType(block, operand_src, operand_ty); if (sema.resolveValue(operand)) |int_val| { @@ -8114,7 +8113,7 @@ fn zirOptionalPayloadPtr( const ptr_ty = sema.typeOf(optional_ptr); assert(ptr_ty.zigTypeTag(sema.pt.zcu) == .pointer); - try sema.ensureLayoutResolved(ptr_ty.childType(sema.pt.zcu), src); + try sema.ensureLayoutResolved(ptr_ty.childType(sema.pt.zcu), src, .ptr_access); return sema.analyzeOptionalPayloadPtr(block, src, optional_ptr, safety_check, false); } @@ -8311,7 +8310,7 @@ fn zirErrUnionPayloadPtr( const ptr_ty = sema.typeOf(operand); assert(ptr_ty.zigTypeTag(sema.pt.zcu) == .pointer); - try sema.ensureLayoutResolved(ptr_ty.childType(sema.pt.zcu), src); + try sema.ensureLayoutResolved(ptr_ty.childType(sema.pt.zcu), src, .ptr_access); return sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false); } @@ -9020,7 +9019,6 @@ fn funcCommon( const io = comp.io; const ip = &zcu.intern_pool; - const src = block.nodeOffset(src_node_offset); const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = src_node_offset }); const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset }); @@ -9090,7 +9088,7 @@ fn funcCommon( .lbrace_column = @as(u16, @truncate(src_locs.columns)), .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)), })); - try sema.ensureLayoutResolved(func_val.typeOf(zcu), src); + try sema.ensureLayoutResolved(func_val.typeOf(zcu), ret_ty_src, .return_type); return .fromValue(func_val); } @@ -9105,7 +9103,7 @@ fn funcCommon( }); if (has_body) { - try sema.ensureLayoutResolved(.fromInterned(func_ty), src); + try sema.ensureLayoutResolved(.fromInterned(func_ty), ret_ty_src, .return_type); return .fromIntern(try ip.getFuncDecl(gpa, io, pt.tid, .{ .owner_nav = sema.owner.unwrap().nav_val, .ty = func_ty, @@ -9761,7 +9759,7 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air return sema.failWithOwnedErrorMsg(block, msg); } try sema.checkIndexable(block, src, indexable_ty); - try sema.ensureLayoutResolved(indexable_ty.childType(zcu), src); + try sema.ensureLayoutResolved(indexable_ty.childType(zcu), src, .ptr_access); return sema.elemPtrOneLayerOnly(block, src, array_ptr, elem_index, src, false, false); } @@ -9975,14 +9973,15 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp const raw_operand_ty = sema.typeOf(eu_maybe_ptr); if (!non_err_case.operand_is_ref) break :err_union_ty raw_operand_ty; try sema.checkPtrOperand(block, operand_src, raw_operand_ty); - break :err_union_ty raw_operand_ty.childType(zcu); + const child_ty = raw_operand_ty.childType(zcu); + try sema.ensureLayoutResolved(child_ty, operand_src, .ptr_access); + break :err_union_ty child_ty; }; if (err_union_ty.zigTypeTag(zcu) != .error_union) { return sema.fail(block, operand_src, "expected error union type, found '{f}'", .{ err_union_ty.fmt(pt), }); } - try sema.ensureLayoutResolved(err_union_ty, operand_src); const non_err_cond = if (non_err_case.operand_is_ref) try sema.analyzePtrIsNonErr(block, operand_src, eu_maybe_ptr) @@ -11281,11 +11280,12 @@ fn validateSwitchBlock( const raw_operand_ty = sema.typeOf(raw_operand); if (operand_is_ref) { try sema.checkPtrType(block, operand_src, raw_operand_ty, false); - break :operand_ty raw_operand_ty.childType(zcu); + const child_ty = raw_operand_ty.childType(zcu); + try sema.ensureLayoutResolved(child_ty, operand_src, .ptr_access); + break :operand_ty child_ty; } break :operand_ty raw_operand_ty; }; - try sema.ensureLayoutResolved(operand_ty, operand_src); const item_ty: Type = item_ty: { switch (operand_ty.zigTypeTag(zcu)) { @@ -12844,7 +12844,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const name_src = block.builtinCallArgSrc(inst_data.src_node, 1); const ty = try sema.resolveType(block, ty_src, extra.lhs); const field_name = try sema.resolveConstStringIntern(block, name_src, extra.rhs, .{ .simple = .field_name }); - try sema.ensureLayoutResolved(ty, ty_src); + try sema.ensureLayoutResolved(ty, ty_src, .field_queried); const ip = &zcu.intern_pool; const has_field = hf: { @@ -15194,6 +15194,7 @@ fn analyzeArithmetic( }); } + try sema.ensureLayoutResolved(lhs_ty.childType(zcu), src, .ptr_offset); const elem_size = lhs_ty.childType(zcu).abiSize(zcu); if (elem_size == 0) { return sema.fail(block, src, "pointer subtraction requires element type '{f}' to have runtime bits", .{ @@ -15246,7 +15247,7 @@ fn analyzeArithmetic( else => return sema.failWithInvalidPtrArithmetic(block, src, "pointer-integer", "addition and subtraction"), }; - try sema.ensureLayoutResolved(lhs_ty.childType(zcu), src); + try sema.ensureLayoutResolved(lhs_ty.childType(zcu), src, .ptr_offset); return sema.analyzePtrArithmetic(block, src, lhs, rhs, air_tag, rhs_src); }, } @@ -15879,7 +15880,7 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const ty = try sema.resolveType(block, operand_src, inst_data.operand); - try sema.ensureLayoutResolved(ty, operand_src); + try sema.ensureLayoutResolved(ty, operand_src, .size_of); switch (ty.classify(zcu)) { .no_possible_value, => return sema.fail(block, operand_src, "no size available for uninstantiable type '{f}'", .{ty.fmt(pt)}), @@ -15934,7 +15935,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A .@"anyframe", => {}, } - try sema.ensureLayoutResolved(operand_ty, operand_src); + try sema.ensureLayoutResolved(operand_ty, operand_src, .size_of); return .fromValue(try pt.intValue(.comptime_int, operand_ty.bitSize(zcu))); } @@ -16185,7 +16186,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const type_info_ty = try sema.getBuiltinType(src, .Type); const type_info_tag_ty = type_info_ty.unionTagType(zcu).?; - try sema.ensureLayoutResolved(ty, src); + try sema.ensureLayoutResolved(ty, src, .type_info); if (ty.typeDeclInst(zcu)) |type_decl_inst| { try sema.declareDependency(.{ .namespace = type_decl_inst }); @@ -16345,7 +16346,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const alignment_val = try pt.intValue(.comptime_int, bytes: { if (info.flags.alignment.toByteUnits()) |b| break :bytes b; const elem_ty: Type = .fromInterned(info.child); - try sema.ensureLayoutResolved(elem_ty, src); + try sema.ensureLayoutResolved(elem_ty, src, .type_info); break :bytes elem_ty.abiAlignment(zcu).toByteUnits().?; }); @@ -18233,7 +18234,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air elem_ty.fmt(pt), bit_offset, bit_offset - host_size * 8, host_size, }); } - try sema.ensureLayoutResolved(elem_ty, elem_ty_src); + try sema.ensureLayoutResolved(elem_ty, elem_ty_src, .bit_ptr_child); const elem_bit_size = elem_ty.bitSize(zcu); if (elem_bit_size > host_size * 8 - bit_offset) { return sema.fail(block, bitoffset_src, "packed type '{f}' at bit offset {d} ends {d} bits after the end of a {d} byte host integer", .{ @@ -18302,7 +18303,7 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE const pt = sema.pt; const zcu = pt.zcu; - try sema.ensureLayoutResolved(obj_ty, ty_src); + try sema.ensureLayoutResolved(obj_ty, ty_src, .init); switch (obj_ty.zigTypeTag(zcu)) { .@"struct" => return sema.structInitEmpty(block, obj_ty, src, src), @@ -18367,7 +18368,7 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is }); } else ty_operand; - try sema.ensureLayoutResolved(init_ty, src); + try sema.ensureLayoutResolved(init_ty, src, .init); const obj_ty = init_ty.optEuBaseType(zcu); @@ -18486,7 +18487,7 @@ fn zirStructInit( // The type wasn't actually known, so treat this as an anon struct init. return sema.structInitAnon(block, src, inst, .typed_init, extra.data, extra.end, is_ref); }; - try sema.ensureLayoutResolved(result_ty, src); + try sema.ensureLayoutResolved(result_ty, src, .init); const resolved_ty = result_ty.optEuBaseType(zcu); if (resolved_ty.zigTypeTag(zcu) == .@"struct") { @@ -18951,7 +18952,7 @@ fn structInitAnon( }; try sema.addTypeReferenceEntry(src, struct_ty); // No need for `ensureNamespaceUpToDate` because this type's namespace is always empty. - try sema.ensureLayoutResolved(struct_ty, src); + try sema.ensureLayoutResolved(struct_ty, src, .init); _ = opt_runtime_index orelse { const struct_val = try pt.aggregateValue(struct_ty, values); @@ -19270,7 +19271,7 @@ fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro const field_src = block.builtinCallArgSrc(inst_data.src_node, 1); const aggregate_ty = try sema.resolveType(block, ty_src, extra.container_type); const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .simple = .field_name }); - try sema.ensureLayoutResolved(aggregate_ty, ty_src); + try sema.ensureLayoutResolved(aggregate_ty, ty_src, .field_queried); return sema.fieldType(block, aggregate_ty, field_name, field_src, ty_src); } @@ -19290,7 +19291,7 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp const aggregate_ty = wrapped_aggregate_ty.optEuBaseType(zcu); const zir_field_name = sema.code.nullTerminatedString(extra.name_start); const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_field_name, .no_embedded_nulls); - try sema.ensureLayoutResolved(aggregate_ty, ty_src); + try sema.ensureLayoutResolved(aggregate_ty, ty_src, .init); return sema.fieldType(block, aggregate_ty, field_name, field_name_src, ty_src); } @@ -19390,7 +19391,7 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); const ty = try sema.resolveType(block, operand_src, inst_data.operand); - try sema.ensureLayoutResolved(ty, operand_src); + try sema.ensureLayoutResolved(ty, operand_src, .align_of); if (ty.isNoReturn(zcu)) { return sema.fail(block, operand_src, "no align available for type '{f}'", .{ty.fmt(sema.pt)}); } @@ -19874,7 +19875,6 @@ fn zirReifyFn( const param_attrs_arr = try sema.derefSliceAsArray(block, param_attrs_src, param_attrs_slice, .{ .simple = .fn_param_attrs }); const ret_ty = try sema.resolveType(block, ret_ty_src, extra.ret_ty); - try sema.ensureLayoutResolved(ret_ty, ret_ty_src); const fn_attrs_uncoerced = sema.resolveInst(extra.fn_attrs); const fn_attrs_coerced = try sema.coerce(block, fn_attrs_ty, fn_attrs_uncoerced, fn_attrs_src); @@ -19899,10 +19899,6 @@ fn zirReifyFn( param_types_src, fn_attrs.@"callconv", ); - try sema.ensureLayoutResolved(param_ty, param_types_src); - if (param_ty.comptimeOnly(zcu)) { - return sema.fail(block, param_attrs_src, "cannot reify function type with comptime-only parameter type '{f}'", .{param_ty.fmt(pt)}); - } if (param_attrs.@"noalias") { if (param_idx > 31) { return sema.fail(block, param_attrs_src, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}); @@ -20811,8 +20807,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const elem_ty = ptr_ty.nullablePtrElem(zcu); - // We'll need to validate the pointer alignment. - try sema.ensureLayoutResolved(elem_ty, src); + try sema.ensureLayoutResolved(elem_ty, src, .align_check); const ptr_align = ptr_ty.ptrAlignment(zcu); if (ptr_ty.isSlice(zcu)) { @@ -21155,8 +21150,8 @@ fn ptrCastFull( const src_info = operand_ty.ptrInfo(zcu); const dest_info = dest_ty.ptrInfo(zcu); - try sema.ensureLayoutResolved(.fromInterned(src_info.child), operand_src); - try sema.ensureLayoutResolved(.fromInterned(dest_info.child), src); + try sema.ensureLayoutResolved(.fromInterned(src_info.child), operand_src, .align_check); + try sema.ensureLayoutResolved(.fromInterned(dest_info.child), src, .align_check); const DestSliceLen = union(enum) { undef, @@ -21927,7 +21922,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 const ty = try sema.resolveType(block, ty_src, extra.lhs); const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.rhs, .{ .simple = .field_name }); - try sema.ensureLayoutResolved(ty, ty_src); + try sema.ensureLayoutResolved(ty, ty_src, .field_queried); const pt = sema.pt; const zcu = pt.zcu; @@ -23010,7 +23005,7 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const ptr = try sema.checkAtomicPtrOperand(block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, true); const order = try sema.resolveAtomicOrder(block, order_src, extra.ordering, .{ .simple = .atomic_order }); - try sema.ensureLayoutResolved(elem_ty, elem_ty_src); + try sema.ensureLayoutResolved(elem_ty, elem_ty_src, .ptr_access); switch (order) { .release, .acq_rel => { @@ -23330,7 +23325,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins return sema.fail(block, inst_src, "expected single pointer type, found '{f}'", .{parent_ptr_ty.fmt(pt)}); } const parent_ty: Type = .fromInterned(parent_ptr_info.child); - try sema.ensureLayoutResolved(parent_ty, inst_src); + try sema.ensureLayoutResolved(parent_ty, inst_src, .field_used); switch (parent_ty.zigTypeTag(zcu)) { .@"struct", .@"union" => {}, else => return sema.fail(block, inst_src, "expected pointer to struct or union type, found '{f}'", .{parent_ptr_ty.fmt(pt)}), @@ -23938,8 +23933,8 @@ fn zirMemcpy( const dest_elem_ty = dest_ty.indexableElem(zcu); const src_elem_ty = src_ty.indexableElem(zcu); - try sema.ensureLayoutResolved(dest_elem_ty, dest_src); - try sema.ensureLayoutResolved(src_elem_ty, src_src); + try sema.ensureLayoutResolved(dest_elem_ty, dest_src, .ptr_access); + try sema.ensureLayoutResolved(src_elem_ty, src_src, .ptr_access); const imc = try sema.coerceInMemoryAllowed( block, @@ -25470,7 +25465,7 @@ fn fieldPtrLoad( const object_ptr_ty = sema.typeOf(object_ptr); assert(object_ptr_ty.zigTypeTag(zcu) == .pointer); const pointee_ty = object_ptr_ty.childType(zcu); - try sema.ensureLayoutResolved(pointee_ty, src); + try sema.ensureLayoutResolved(pointee_ty, src, .ptr_access); if (try pointee_ty.onePossibleValue(pt)) |opv| { const object: Air.Inst.Ref = .fromValue(opv); return fieldVal(sema, block, src, object, field_name, field_name_src); @@ -25606,7 +25601,7 @@ fn fieldVal( if (try sema.namespaceLookupVal(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { return inst; } - try sema.ensureLayoutResolved(child_type, src); + try sema.ensureLayoutResolved(child_type, src, .field_used); if (child_type.unionTagType(zcu)) |enum_ty| { if (enum_ty.enumFieldIndex(field_name, zcu)) |field_index_usize| { const field_index: u32 = @intCast(field_index_usize); @@ -25619,7 +25614,7 @@ fn fieldVal( if (try sema.namespaceLookupVal(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { return inst; } - try sema.ensureLayoutResolved(child_type, src); + try sema.ensureLayoutResolved(child_type, src, .field_used); const field_index_usize = child_type.enumFieldIndex(field_name, zcu) orelse return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name); const field_index: u32 = @intCast(field_index_usize); @@ -25645,7 +25640,7 @@ fn fieldVal( }, .@"struct" => if (is_pointer_to) { // Avoid loading the entire struct by fetching a pointer and loading that - try sema.ensureLayoutResolved(inner_ty, src); + try sema.ensureLayoutResolved(inner_ty, src, .ptr_access); const field_ptr = try sema.structFieldPtr(block, src, object, field_name, field_name_src, inner_ty); return sema.analyzeLoad(block, src, field_ptr, object_src); } else { @@ -25653,7 +25648,7 @@ fn fieldVal( }, .@"union" => if (is_pointer_to) { // Avoid loading the entire union by fetching a pointer and loading that - try sema.ensureLayoutResolved(inner_ty, src); + try sema.ensureLayoutResolved(inner_ty, src, .ptr_access); const field_ptr = try sema.unionFieldPtr(block, src, object, field_name, field_name_src, inner_ty, false); return sema.analyzeLoad(block, src, field_ptr, object_src); } else { @@ -25837,7 +25832,7 @@ fn fieldPtr( if (try sema.namespaceLookupRef(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { return inst; } - try sema.ensureLayoutResolved(child_type, src); + try sema.ensureLayoutResolved(child_type, src, .field_used); if (child_type.unionTagType(zcu)) |enum_ty| { if (enum_ty.enumFieldIndex(field_name, zcu)) |field_index| { const field_index_u32: u32 = @intCast(field_index); @@ -25851,7 +25846,7 @@ fn fieldPtr( if (try sema.namespaceLookupRef(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| { return inst; } - try sema.ensureLayoutResolved(child_type, src); + try sema.ensureLayoutResolved(child_type, src, .field_used); const field_index = child_type.enumFieldIndex(field_name, zcu) orelse { return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name); }; @@ -25873,7 +25868,7 @@ fn fieldPtr( try sema.analyzeLoad(block, src, object_ptr, object_ptr_src) else object_ptr; - try sema.ensureLayoutResolved(inner_ty, src); + try sema.ensureLayoutResolved(inner_ty, src, .ptr_access); const field_ptr = try sema.structFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty); try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr); return field_ptr; @@ -25883,7 +25878,7 @@ fn fieldPtr( try sema.analyzeLoad(block, src, object_ptr, object_ptr_src) else object_ptr; - try sema.ensureLayoutResolved(inner_ty, src); + try sema.ensureLayoutResolved(inner_ty, src, .ptr_access); const field_ptr = try sema.unionFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty, initializing); try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr); return field_ptr; @@ -25927,7 +25922,7 @@ fn fieldCallBind( // Optionally dereference a second pointer to get the concrete type. const is_double_ptr = inner_ty.zigTypeTag(zcu) == .pointer and inner_ty.ptrSize(zcu) == .one; const concrete_ty = if (is_double_ptr) inner_ty.childType(zcu) else inner_ty; - try sema.ensureLayoutResolved(concrete_ty, src); + try sema.ensureLayoutResolved(concrete_ty, src, .ptr_access); const ptr_ty = if (is_double_ptr) inner_ty else raw_ptr_ty; const object_ptr = if (is_double_ptr) try sema.analyzeLoad(block, src, raw_ptr, src) @@ -26514,7 +26509,7 @@ fn elemPtr( else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{f}'", .{indexable_ptr_ty.fmt(pt)}), }; try sema.checkIndexable(block, src, indexable_ty); - try sema.ensureLayoutResolved(indexable_ty, src); + try sema.ensureLayoutResolved(indexable_ty, src, .ptr_access); const elem_ptr = switch (indexable_ty.zigTypeTag(zcu)) { .vector => try sema.elemPtrVector(block, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init), @@ -26522,7 +26517,7 @@ fn elemPtr( .@"struct" => try sema.tupleElemPtr(block, src, indexable_ptr, elem_index, elem_index_src), else => { const indexable = try sema.analyzeLoad(block, indexable_ptr_src, indexable_ptr, indexable_ptr_src); - try sema.ensureLayoutResolved(sema.typeOf(indexable).childType(zcu), src); + try sema.ensureLayoutResolved(sema.typeOf(indexable).childType(zcu), src, .ptr_access); return elemPtrOneLayerOnly(sema, block, src, indexable, elem_index, elem_index_src, init, oob_safety); }, }; @@ -26614,7 +26609,7 @@ fn elemVal( switch (indexable_ty.zigTypeTag(zcu)) { .pointer => { const child_ty = indexable_ty.childType(zcu); - try sema.ensureLayoutResolved(child_ty, src); + try sema.ensureLayoutResolved(child_ty, src, .ptr_access); switch (indexable_ty.ptrSize(zcu)) { .slice => return sema.elemValSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety), .many, .c => { @@ -27192,7 +27187,7 @@ fn coerceExtra( const target = zcu.getTarget(); inst_ty.assertHasLayout(zcu); - try sema.ensureLayoutResolved(dest_ty, inst_src); + try sema.ensureLayoutResolved(dest_ty, inst_src, .coerce); // If the types are the same, we can return the operand. if (dest_ty.eql(inst_ty, zcu)) @@ -28552,8 +28547,8 @@ fn coerceInMemoryAllowedFns( } }; } - try sema.ensureLayoutResolved(src_ty, src_src); - try sema.ensureLayoutResolved(dest_ty, dest_src); + try sema.ensureLayoutResolved(src_ty, src_src, .coerce); + try sema.ensureLayoutResolved(dest_ty, dest_src, .coerce); const src_is_runtime = src_ty.fnHasRuntimeBits(zcu); const dest_is_runtime = dest_ty.fnHasRuntimeBits(zcu); if (src_is_runtime != dest_is_runtime) return .{ .fn_generic = !dest_is_runtime }; @@ -28607,7 +28602,6 @@ fn coerceInMemoryAllowedFns( const src_is_comptime = src_info.paramIsComptime(@intCast(param_i)); const dest_is_comptime = dest_info.paramIsComptime(@intCast(param_i)); if (src_is_comptime == dest_is_comptime) break :comptime_param; - try sema.ensureLayoutResolved(dest_param_ty, dest_src); if (!dest_is_mut and src_is_comptime and !dest_is_comptime and dest_param_ty.comptimeOnly(zcu)) { // A parameter which is marked `comptime` can drop that annotation if the type is comptime-only. // The function remains generic, and the parameter is going to be comptime-resolved either way, @@ -28835,11 +28829,11 @@ fn coerceInMemoryAllowedPtrs( dest_info.child != src_info.child) { const src_align = if (src_info.flags.alignment == .none) a: { - try sema.ensureLayoutResolved(src_child, src_src); + try sema.ensureLayoutResolved(src_child, src_src, .align_check); break :a src_child.abiAlignment(zcu); } else src_info.flags.alignment; const dest_align = if (dest_info.flags.alignment == .none) a: { - try sema.ensureLayoutResolved(dest_child, dest_src); + try sema.ensureLayoutResolved(dest_child, dest_src, .align_check); break :a dest_child.abiAlignment(zcu); } else dest_info.flags.alignment; if (dest_align.compare(if (dest_is_mut) .neq else .gt, src_align)) { @@ -29189,7 +29183,7 @@ fn bitCast( const old_ty = sema.typeOf(inst); old_ty.assertHasLayout(zcu); - try sema.ensureLayoutResolved(dest_ty, inst_src); + try sema.ensureLayoutResolved(dest_ty, inst_src, .init); const dest_bits = dest_ty.bitSize(zcu); const old_bits = old_ty.bitSize(zcu); @@ -29837,10 +29831,11 @@ fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.M try sema.addReferenceEntry(null, src, unit); try sema.declareDependency(.{ .memoized_state = stage }); + const reason: Zcu.DependencyReason = .{ .src = src, .type_layout_reason = undefined }; if (pt.zcu.analysis_in_progress.contains(unit)) { - return sema.failWithOwnedErrorMsg(null, try sema.errMsg(src, "dependency loop detected", .{})); + return sema.failWithDependencyLoop(unit, &reason); } - try pt.ensureMemoizedStateUpToDate(stage); + try pt.ensureMemoizedStateUpToDate(stage, &reason); } pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: InternPool.Nav.Index, kind: enum { type, fully }) CompileError!void { @@ -29854,11 +29849,6 @@ pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: return; } - try sema.declareDependency(switch (kind) { - .type => .{ .nav_ty = nav_index }, - .fully => .{ .nav_val = nav_index }, - }); - // Note that even if `nav.status == .resolved`, we must still trigger `ensureNavValUpToDate` // to make sure the value is up-to-date on incremental updates. @@ -29867,20 +29857,23 @@ pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: .fully => .{ .nav_val = nav_index }, }); try sema.addReferenceEntry(block, src, anal_unit); + try sema.declareDependency(switch (kind) { + .type => .{ .nav_ty = nav_index }, + .fully => .{ .nav_val = nav_index }, + }); + + const reason: Zcu.DependencyReason = .{ .src = src, .type_layout_reason = undefined }; if (zcu.analysis_in_progress.contains(anal_unit)) { - return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{ - .base_node_inst = nav.analysis.?.zir_index, - .offset = LazySrcLoc.Offset.nodeOffset(.zero), - }, "dependency loop detected", .{})); + return sema.failWithDependencyLoop(anal_unit, &reason); } switch (kind) { .type => { try zcu.ensureNavValAnalysisQueued(nav_index); - return pt.ensureNavTypeUpToDate(nav_index); + return pt.ensureNavTypeUpToDate(nav_index, &reason); }, - .fully => return pt.ensureNavValUpToDate(nav_index), + .fully => return pt.ensureNavValUpToDate(nav_index, &reason), } } @@ -30065,7 +30058,7 @@ fn analyzeLoad( return sema.fail(block, ptr_src, "cannot load opaque type '{f}'", .{elem_ty.fmt(pt)}); } - try sema.ensureLayoutResolved(elem_ty, src); + try sema.ensureLayoutResolved(elem_ty, src, .ptr_access); if (try elem_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { @@ -30249,7 +30242,7 @@ fn resolveIsNonErrFromType( // This is *our* error set; that is, we're currently analyzing the function // which owns it. Trying to resolve it now would cause a dependency loop. // Instead, accept that we don't know. - if (true) return null; + return null; }, else => |set_ty| switch (ip.indexToKey(set_ty)) { .error_set_type => |error_set_type| switch (error_set_type.names.len) { @@ -30450,7 +30443,7 @@ fn analyzeSlice( else => return sema.fail(block, src, "slice of non-array type '{f}'", .{ptr_ptr_child_ty.fmt(pt)}), } - try sema.ensureLayoutResolved(elem_ty, src); + try sema.ensureLayoutResolved(elem_ty, src, .ptr_access); const ptr = if (slice_ty.isSlice(zcu)) try sema.analyzeSlicePtr(block, ptr_src, ptr_or_slice, slice_ty) @@ -32831,11 +32824,13 @@ fn ensureFuncIesResolved( try sema.declareDependency(.{ .func_ies = func_index }); try sema.addReferenceEntry(block, src, .wrap(.{ .func = func_index })); + const reason: Zcu.DependencyReason = .{ .src = src, .type_layout_reason = undefined }; + if (zcu.analysis_in_progress.contains(.wrap(.{ .func = func_index }))) { - return sema.fail(block, src, "unable to resolve inferred error set", .{}); + return sema.failWithDependencyLoop(.wrap(.{ .func = func_index }), &reason); } - try pt.ensureFuncBodyUpToDate(func_index); + try pt.ensureFuncBodyUpToDate(func_index, &reason); } pub fn resolveInferredErrorSetPtr( @@ -33749,6 +33744,8 @@ pub fn flushExports(sema: *Sema) !void { // // So, pick up and delete any existing exports. This strategy performs // redundant work, but that's okay, because this case is exceedingly rare. + // + // MLUGG TODO: is this still possible? if not, delete this logic and combine deleteUnitExports into resetUnit if (zcu.single_exports.get(sema.owner)) |export_idx| { try sema.exports.append(gpa, export_idx.ptr(zcu).*); } else if (zcu.multi_exports.get(sema.owner)) |info| { @@ -33940,7 +33937,7 @@ pub fn analyzeMemoizedState(sema: *Sema, stage: InternPool.MemoizedStateStage) C const val: Value = switch (builtin_decl.kind()) { .type => val: { const ty = try sema.analyzeAsType(&block, decl_src, .std_builtin_decl, uncoerced_val); - try sema.ensureLayoutResolved(ty, decl_src); + try sema.ensureLayoutResolved(ty, decl_src, .builtin_type); break :val ty.toValue(); }, .func => val: { @@ -34370,3 +34367,42 @@ fn zirOpaqueDecl( return .fromType(ty); } + +/// Registers an error indicating a dependency loop: we have introduced a dependency on `want` (with +/// reason `want_reason`) but have learnt that `want` is already in `zcu.analysis_in_progress`. +pub fn failWithDependencyLoop( + sema: *Sema, + want: AnalUnit, + want_reason: *const Zcu.DependencyReason, +) SemaError { + const pt = sema.pt; + const zcu = pt.zcu; + const gpa = zcu.comp.gpa; + + const in_progress_len = zcu.analysis_in_progress.count(); + var index = zcu.analysis_in_progress.getIndex(want).? + 1; + + try zcu.dependency_loops.ensureUnusedCapacity(gpa, 1); + try zcu.dependency_loop_nodes.ensureUnusedCapacity(gpa, in_progress_len - index + 1); + + zcu.dependency_loops.putAssumeCapacityNoClobber(want, {}); + + while (index <= in_progress_len) : (index += 1) { + const parent_unit = zcu.analysis_in_progress.keys()[index - 1]; + const unit, const reason = if (index == in_progress_len) .{ + want, + want_reason, + } else .{ + zcu.analysis_in_progress.keys()[index], + zcu.analysis_in_progress.values()[index], + }; + + zcu.dependency_loop_nodes.putAssumeCapacityNoClobber(parent_unit, .{ + .unit = unit, + .reason = reason.?.*, + }); + } + + // A dependency loop error will be reported. Mark us all as transitive failures. + return error.AnalysisFail; +} diff --git a/src/Sema/LowerZon.zig b/src/Sema/LowerZon.zig index b755c5daaae8f6ed6688b2529ad563f347b445d4..cf809603c03a177c4aefe40407b3b649a1921cff 100644 --- a/src/Sema/LowerZon.zig +++ b/src/Sema/LowerZon.zig @@ -300,7 +300,7 @@ fn checkTypeInner( } else { const gop = try visited.getOrPut(sema.arena, ty.toIntern()); if (gop.found_existing) return; - try sema.ensureLayoutResolved(ty, self.import_loc); + try sema.ensureLayoutResolved(ty, self.import_loc, .init); const struct_info = zcu.typeToStruct(ty).?; for (struct_info.field_types.get(ip)) |field_type| { try self.checkTypeInner(.fromInterned(field_type), null, visited); @@ -309,7 +309,7 @@ fn checkTypeInner( .@"union" => { const gop = try visited.getOrPut(sema.arena, ty.toIntern()); if (gop.found_existing) return; - try sema.ensureLayoutResolved(ty, self.import_loc); + try sema.ensureLayoutResolved(ty, self.import_loc, .init); const union_info = zcu.typeToUnion(ty).?; for (union_info.field_types.get(ip)) |field_type| { if (field_type != .void_type) { @@ -646,7 +646,7 @@ fn lowerEnum(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.I const gpa = comp.gpa; const io = comp.io; const ip = &pt.zcu.intern_pool; - try self.sema.ensureLayoutResolved(res_ty, self.import_loc); + try self.sema.ensureLayoutResolved(res_ty, self.import_loc, .init); switch (node.get(self.file.zoir.?)) { .enum_literal => |field_name| { const field_name_interned = try ip.getOrPutString( @@ -769,7 +769,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool const io = comp.io; const ip = &pt.zcu.intern_pool; - try self.sema.ensureLayoutResolved(res_ty, self.import_loc); + try self.sema.ensureLayoutResolved(res_ty, self.import_loc, .init); const struct_info = self.sema.pt.zcu.typeToStruct(res_ty).?; const fields: @FieldType(Zoir.Node, "struct_literal") = switch (node.get(self.file.zoir.?)) { @@ -919,7 +919,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. const gpa = comp.gpa; const io = comp.io; const ip = &pt.zcu.intern_pool; - try self.sema.ensureLayoutResolved(res_ty, self.import_loc); + try self.sema.ensureLayoutResolved(res_ty, self.import_loc, .init); const union_info = pt.zcu.typeToUnion(res_ty).?; const enum_tag_info = ip.loadEnumType(union_info.enum_tag_type); diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig index a7b862289b6de72b34e2739a684effcddc6a60fc..07349457a44ee78f7435e9609833b9e588bf1248 100644 --- a/src/Sema/type_resolution.zig +++ b/src/Sema/type_resolution.zig @@ -14,12 +14,64 @@ const InternPool = @import("../InternPool.zig"); const Alignment = InternPool.Alignment; const arith = @import("arith.zig"); +pub const LayoutResolveReason = enum { + variable, + constant, + parameter, + return_type, + field, + backing_enum, + init, + coerce, + ptr_access, + ptr_offset, + field_used, + field_queried, + size_of, + align_of, + type_info, + align_check, + bit_ptr_child, + builtin_type, + + /// Written after string: "while resolving type 'T' " + /// e.g. "while resolving type 'MyStruct' for variable declared here" + pub fn msg(r: LayoutResolveReason) []const u8 { + return switch (r) { + // zig fmt: off + .variable => "for variable declared here", + .constant => "for constant declared here", + .parameter => "for function parameter declared here", + .return_type => "for function return type declared here", + .field => "for field declared here", + .backing_enum => "for backing enum type declared here", + .init => "for initialization performed here", + .coerce => "for coercion performed here", + .ptr_access => "for pointer access here", + .ptr_offset => "for pointer offset here", + .field_used => "for field usage here", + .field_queried => "for field query here", + .size_of => "for size query here", + .align_of => "for alignment query here", + .type_info => "for type information query here", + .align_check => "for alignment check here", + .bit_ptr_child => "for bit size check here", + .builtin_type => "from 'std.builtin'", + // zig fmt: on + }; + } +}; + /// Ensures that `ty` has known layout, including alignment, size, and (where relevant) field offsets. /// `ty` may be any type; its layout is resolved *recursively* if necessary. /// Adds incremental dependencies tracking any required type resolution. -/// MLUGG TODO: to make the langspec non-stupid, we need to call this from WAY fewer places (the conditions need to be less specific). -/// MLUGG TODO: to be clear, i should audit EVERY use of this before PRing -pub fn ensureLayoutResolved(sema: *Sema, ty: Type, src: LazySrcLoc) SemaError!void { +pub fn ensureLayoutResolved(sema: *Sema, ty: Type, src: LazySrcLoc, reason: LayoutResolveReason) SemaError!void { + return ensureLayoutResolvedInner(sema, ty, ty, &.{ + .src = src, + .type_layout_reason = reason, + }); +} +fn ensureLayoutResolvedInner(sema: *Sema, ty: Type, orig_ty: Type, reason: *const Zcu.DependencyReason) SemaError!void { const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; @@ -35,30 +87,25 @@ pub fn ensureLayoutResolved(sema: *Sema, ty: Type, src: LazySrcLoc) SemaError!vo .func_type => |func_type| { for (func_type.param_types.get(ip)) |param_ty| { - try ensureLayoutResolved(sema, .fromInterned(param_ty), src); + try ensureLayoutResolvedInner(sema, .fromInterned(param_ty), orig_ty, reason); } - try ensureLayoutResolved(sema, .fromInterned(func_type.return_type), src); + try ensureLayoutResolvedInner(sema, .fromInterned(func_type.return_type), orig_ty, reason); }, - .array_type => |arr| return ensureLayoutResolved(sema, .fromInterned(arr.child), src), - .vector_type => |vec| return ensureLayoutResolved(sema, .fromInterned(vec.child), src), - .opt_type => |child| return ensureLayoutResolved(sema, .fromInterned(child), src), - .error_union_type => |eu| return ensureLayoutResolved(sema, .fromInterned(eu.payload_type), src), + .array_type => |arr| return ensureLayoutResolvedInner(sema, .fromInterned(arr.child), orig_ty, reason), + .vector_type => |vec| return ensureLayoutResolvedInner(sema, .fromInterned(vec.child), orig_ty, reason), + .opt_type => |child| return ensureLayoutResolvedInner(sema, .fromInterned(child), orig_ty, reason), + .error_union_type => |eu| return ensureLayoutResolvedInner(sema, .fromInterned(eu.payload_type), orig_ty, reason), .tuple_type => |tuple| for (tuple.types.get(ip)) |field_ty| { - try ensureLayoutResolved(sema, .fromInterned(field_ty), src); + try ensureLayoutResolvedInner(sema, .fromInterned(field_ty), orig_ty, reason); }, .struct_type, .union_type, .enum_type => { try sema.declareDependency(.{ .type_layout = ty.toIntern() }); - try sema.addReferenceEntry(null, src, .wrap(.{ .type_layout = ty.toIntern() })); + try sema.addReferenceEntry(null, reason.src, .wrap(.{ .type_layout = ty.toIntern() })); if (zcu.analysis_in_progress.contains(.wrap(.{ .type_layout = ty.toIntern() }))) { - // TODO: better error message - return sema.failWithOwnedErrorMsg(null, try sema.errMsg( - ty.srcLoc(zcu), - "{s} '{f}' depends on itself", - .{ @tagName(ty.zigTypeTag(zcu)), ty.fmt(pt) }, - )); + return sema.failWithDependencyLoop(.wrap(.{ .type_layout = ty.toIntern() }), reason); } - try pt.ensureTypeLayoutUpToDate(ty); + try pt.ensureTypeLayoutUpToDate(ty, reason); }, // values, not types @@ -228,7 +275,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { const field_ty: Type = .fromInterned(field_ty_ip); assert(!field_ty.isGenericPoison()); const field_ty_src = block.src(.{ .container_field_type = @intCast(field_index) }); - try sema.ensureLayoutResolved(field_ty, field_ty_src); + try sema.ensureLayoutResolved(field_ty, field_ty_src, .field); if (field_ty.zigTypeTag(zcu) == .@"opaque") { return sema.failWithOwnedErrorMsg(&block, msg: { @@ -387,7 +434,7 @@ fn resolvePackedStructLayout( const field_ty: Type = .fromInterned(field_ty_ip); assert(!field_ty.isGenericPoison()); const field_ty_src = block.src(.{ .container_field_type = @intCast(field_index) }); - try sema.ensureLayoutResolved(field_ty, field_ty_src); + try sema.ensureLayoutResolved(field_ty, field_ty_src, .field); if (field_ty.zigTypeTag(zcu) == .@"opaque") { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in struct", .{field_ty.fmt(pt)}); @@ -557,7 +604,7 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { }, }; - try sema.ensureLayoutResolved(enum_tag_ty, block.src(.container_arg)); + try sema.ensureLayoutResolved(enum_tag_ty, block.src(.container_arg), .backing_enum); const enum_obj = ip.loadEnumType(enum_tag_ty.toIntern()); if (union_obj.is_reified) { @@ -652,7 +699,7 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { const field_ty: Type = .fromInterned(field_ty_ip); assert(!field_ty.isGenericPoison()); const field_ty_src = block.src(.{ .container_field_type = @intCast(field_index) }); - try sema.ensureLayoutResolved(field_ty, field_ty_src); + try sema.ensureLayoutResolved(field_ty, field_ty_src, .field); if (field_ty.zigTypeTag(zcu) == .@"opaque") { return sema.failWithOwnedErrorMsg(&block, msg: { const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in union", .{field_ty.fmt(pt)}); @@ -832,7 +879,7 @@ fn resolvePackedUnionLayout( const field_ty: Type = .fromInterned(field_ty_ip); assert(!field_ty.isGenericPoison()); const field_ty_src = block.src(.{ .container_field_type = @intCast(field_index) }); - try sema.ensureLayoutResolved(field_ty, field_ty_src); + try sema.ensureLayoutResolved(field_ty, field_ty_src, .field); if (field_ty.zigTypeTag(zcu) == .@"opaque") { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in union", .{field_ty.fmt(pt)}); diff --git a/src/Zcu.zig b/src/Zcu.zig index 19702aee088915922972df9555c7a8a628529956..49abdbed5607582a4a33d40642edd762baaab5bb 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -119,7 +119,7 @@ module_roots: std.AutoArrayHashMapUnmanaged(*Package.Module, File.Index.Optional /// /// Always accessed through `ImportTableAdapter`, where keys are fully resolved /// file paths in order to ensure files are properly deduplicated. This table owns -/// the keys and values. +/// the keysand values. /// /// Protected by Compilation's mutex. /// @@ -177,7 +177,9 @@ embed_table: std.ArrayHashMapUnmanaged( /// is not yet implemented. intern_pool: InternPool = .empty, -analysis_in_progress: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .empty, +/// Value explains why this `AnalUnit` is being analyzed. It is `null` for the topmost analysis +/// (index 0), and non-`null` for all others. +analysis_in_progress: std.AutoArrayHashMapUnmanaged(AnalUnit, ?*const DependencyReason) = .empty, /// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator. failed_analysis: std.AutoArrayHashMapUnmanaged(AnalUnit, *ErrorMsg) = .empty, /// This `AnalUnit` failed semantic analysis because it required analysis of another `AnalUnit` which itself failed. @@ -189,6 +191,19 @@ transitive_failed_analysis: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .emp /// codegen and linking run on a separate thread. failed_codegen: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, *ErrorMsg) = .empty, failed_types: std.AutoArrayHashMapUnmanaged(InternPool.Index, *ErrorMsg) = .empty, + +/// Key is an `AnalUnit` which is in `dependency_loop_nodes`. For each dependency loop, exactly one +/// unit in the loop is in this map, though the choice is arbitrary and not necessarily reproducible +/// between compilations. So, instead of (for instance) defining where the dependency loop "starts", +/// this map simply exists to allow easily iterating all dependency loops exactly once. +dependency_loops: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .empty, +/// Key is an `AnalUnit`, value is the `AnalUnit` which the key references and why it does so. +/// All units in here form loops. To iterate loops, see `dependency_loops`. +dependency_loop_nodes: std.AutoArrayHashMapUnmanaged(AnalUnit, struct { + unit: AnalUnit, + reason: DependencyReason, +}) = .empty, + /// Keep track of `@compileLog`s per `AnalUnit`. /// We track the source location of the first `@compileLog` call, and all logged lines as a linked list. /// The list is singly linked, but we do track its tail for fast appends (optimizing many logs in one unit). @@ -321,6 +336,12 @@ codegen_task_pool: CodegenTaskPool, generation: u32 = 0, +pub const DependencyReason = struct { + src: LazySrcLoc, + /// Only populated if this is for a `.type_layout` unit. + type_layout_reason: Sema.type_resolution.LayoutResolveReason, +}; + pub const IncrementalDebugState = struct { /// All container types in the ZCU, even dead ones. /// Value is the generation the type was created on. @@ -2778,6 +2799,8 @@ pub fn deinit(zcu: *Zcu) void { zcu.analysis_in_progress.deinit(gpa); zcu.failed_analysis.deinit(gpa); zcu.transitive_failed_analysis.deinit(gpa); + zcu.dependency_loops.deinit(gpa); + zcu.dependency_loop_nodes.deinit(gpa); zcu.failed_codegen.deinit(gpa); zcu.failed_types.deinit(gpa); @@ -3536,15 +3559,47 @@ pub fn deleteUnitExports(zcu: *Zcu, anal_unit: AnalUnit) void { } } -/// Delete all references in `reference_table` which are caused by this `AnalUnit`. +/// Prepares `unit` for re-analysis by clearing all of the following state: +/// * Compile errors associated with `unit` +/// * Compile logs associated with `unit` +/// * Dependencies from `unit` on other things +/// * References from `unit` to other units +/// Delete all references in `reference_table` which are caused by `unit`, and all dependencies it +/// has. Called in preparation for re-analysis, which will recreate references and dependencies. /// Re-analysis of the `AnalUnit` will cause appropriate references to be recreated. -pub fn deleteUnitReferences(zcu: *Zcu, anal_unit: AnalUnit) void { - const gpa = zcu.gpa; +pub fn resetUnit(zcu: *Zcu, unit: AnalUnit) void { + const gpa = zcu.comp.gpa; + // Compile errors + if (zcu.failed_analysis.fetchSwapRemove(unit)) |kv| { + kv.value.destroy(gpa); + } else if (zcu.dependency_loop_nodes.swapRemove(unit)) { + _ = zcu.dependency_loops.swapRemove(unit); + _ = zcu.transitive_failed_analysis.swapRemove(unit); + } else { + _ = zcu.transitive_failed_analysis.swapRemove(unit); + } + + // Compile logs + if (zcu.compile_logs.fetchSwapRemove(unit)) |kv| { + var opt_line_idx = kv.value.first_line.toOptional(); + while (opt_line_idx.unwrap()) |line_idx| { + zcu.free_compile_log_lines.append(gpa, line_idx) catch { + // This space will be reused eventually, so we need not propagate this error. + // Just leak it for now, and let GC reclaim it later on. + break; + }; + opt_line_idx = line_idx.get(zcu).next; + } + } + + // Dependencies + zcu.intern_pool.removeDependenciesForDepender(gpa, unit); + + // References zcu.clearCachedResolvedReferences(); - unit_refs: { - const kv = zcu.reference_table.fetchSwapRemove(anal_unit) orelse break :unit_refs; + const kv = zcu.reference_table.fetchSwapRemove(unit) orelse break :unit_refs; var idx = kv.value; while (idx != std.math.maxInt(u32)) { @@ -3572,9 +3627,8 @@ pub fn deleteUnitReferences(zcu: *Zcu, anal_unit: AnalUnit) void { } } } - type_refs: { - const kv = zcu.type_reference_table.fetchSwapRemove(anal_unit) orelse break :type_refs; + const kv = zcu.type_reference_table.fetchSwapRemove(unit) orelse break :type_refs; var idx = kv.value; while (idx != std.math.maxInt(u32)) { @@ -3588,22 +3642,6 @@ pub fn deleteUnitReferences(zcu: *Zcu, anal_unit: AnalUnit) void { } } -/// Delete all compile logs performed by this `AnalUnit`. -/// Re-analysis of the `AnalUnit` will cause logs to be rediscovered. -pub fn deleteUnitCompileLogs(zcu: *Zcu, anal_unit: AnalUnit) void { - const kv = zcu.compile_logs.fetchSwapRemove(anal_unit) orelse return; - const gpa = zcu.gpa; - var opt_line_idx = kv.value.first_line.toOptional(); - while (opt_line_idx.unwrap()) |line_idx| { - zcu.free_compile_log_lines.append(gpa, line_idx) catch { - // This space will be reused eventually, so we need not propagate this error. - // Just leak it for now, and let GC reclaim it later on. - return; - }; - opt_line_idx = line_idx.get(zcu).next; - } -} - pub fn addInlineReferenceFrame(zcu: *Zcu, frame: InlineReferenceFrame) Allocator.Error!Zcu.InlineReferenceFrame.Index { const frame_idx: InlineReferenceFrame.Index = zcu.free_inline_reference_frames.pop() orelse idx: { _ = try zcu.inline_reference_frames.addOne(zcu.gpa); @@ -4252,11 +4290,7 @@ pub fn fmtDependee(zcu: *Zcu, d: InternPool.Dependee) std.fmt.Alt(FormatDependee return .{ .data = .{ .dependee = d, .zcu = zcu } }; } -const FormatAnalUnit = struct { - unit: AnalUnit, - zcu: *Zcu, -}; - +const FormatAnalUnit = struct { unit: AnalUnit, zcu: *const Zcu }; fn formatAnalUnit(data: FormatAnalUnit, writer: *Io.Writer) Io.Writer.Error!void { const zcu = data.zcu; const ip = &zcu.intern_pool; @@ -4280,8 +4314,7 @@ fn formatAnalUnit(data: FormatAnalUnit, writer: *Io.Writer) Io.Writer.Error!void } } -const FormatDependee = struct { dependee: InternPool.Dependee, zcu: *Zcu }; - +const FormatDependee = struct { dependee: InternPool.Dependee, zcu: *const Zcu }; fn formatDependee(data: FormatDependee, writer: *Io.Writer) Io.Writer.Error!void { const zcu = data.zcu; const ip = &zcu.intern_pool; @@ -4666,6 +4699,273 @@ fn explainWhyFileIsInModule( } } +pub fn addDependencyLoopErrors(zcu: *Zcu, eb: *std.zig.ErrorBundle.Wip) Allocator.Error!void { + const gpa = zcu.comp.gpa; + + const all_references = try zcu.resolveReferences(); + + var units: std.ArrayList(AnalUnit) = .empty; + defer units.deinit(gpa); + + // TODO: sort the dependency loops somehow to make the error bundle reproducible + for (zcu.dependency_loops.keys()) |arbitrary_unit| { + units.clearRetainingCapacity(); + + var cur = arbitrary_unit; + while (true) { + try units.append(gpa, cur); + cur = zcu.dependency_loop_nodes.get(cur).?.unit; + if (cur == arbitrary_unit) break; + } + + // `units` now contains all units in the loop. We need to pick a starting point somewhere + // along that loop to begin. We will pick whichever node has the shortest reference trace, + // because the other units may well just be referenced *by* that one! This is also likely + // to match the user's intuition for where the loop "starts". + var start_index: usize = 0; + var start_depth: u32 = depth: { + var depth: u32 = 0; + var opt_ref = all_references.get(units.items[0]) orelse { + // This dependency loop is actually unreferenced, so we don't need to emit a compile + // error at all! Move onto the next dependency loop. + continue; + }; + while (opt_ref) |ref| : (opt_ref = all_references.get(ref.referencer).?) depth += 1; + break :depth depth; + }; + for (units.items[1..], 1..) |unit, index| { + var depth: u32 = 0; + var opt_ref = all_references.get(unit).?; + while (opt_ref) |ref| : (opt_ref = all_references.get(ref.referencer).?) depth += 1; + if (depth < start_depth) { + start_index = index; + start_depth = depth; + } + } + + // Collect a reference trace for the start of the loop. + var ref_trace: std.ArrayList(std.zig.ErrorBundle.ReferenceTrace) = .empty; + defer ref_trace.deinit(gpa); + const frame_limit = zcu.comp.reference_trace orelse 0; + try zcu.populateReferenceTrace(units.items[start_index], frame_limit, eb, &ref_trace); + + // Collect all notes first so we don't leave an incomplete root error message on `error.AlreadyReported`. + const note_buf = try gpa.alloc(std.zig.ErrorBundle.MessageIndex, units.items.len + 1); + defer gpa.free(note_buf); + note_buf[0] = addDependencyLoopNote(zcu, eb, units.items[start_index], ref_trace.items) catch |err| switch (err) { + error.AlreadyReported => return, // give up on the dep loop error + error.OutOfMemory => |e| return e, + }; + for (units.items[start_index + 1 ..], note_buf[1 .. units.items.len - start_index]) |unit, *note| { + note.* = addDependencyLoopNote(zcu, eb, unit, &.{}) catch |err| switch (err) { + error.AlreadyReported => return, // give up on the dep loop error + error.OutOfMemory => |e| return e, + }; + } + for (units.items[0..start_index], note_buf[units.items.len - start_index .. units.items.len]) |unit, *note| { + note.* = addDependencyLoopNote(zcu, eb, unit, &.{}) catch |err| switch (err) { + error.AlreadyReported => return, // give up on the dep loop error + error.OutOfMemory => |e| return e, + }; + } + note_buf[units.items.len] = try eb.addErrorMessage(.{ + .msg = try eb.addString("eliminate any one of these dependencies to break the loop"), + .src_loc = .none, + }); + + try eb.addRootErrorMessage(.{ + .msg = try eb.printString("dependency loop with length {d}", .{units.items.len}), + .src_loc = .none, + .notes_len = @intCast(units.items.len + 1), + }); + const notes_start = try eb.reserveNotes(@intCast(units.items.len + 1)); + const notes: []std.zig.ErrorBundle.MessageIndex = @ptrCast(eb.extra.items[notes_start..]); + @memcpy(notes, note_buf); + } +} +fn addDependencyLoopNote( + zcu: *Zcu, + eb: *std.zig.ErrorBundle.Wip, + source_unit: AnalUnit, + ref_trace: []const std.zig.ErrorBundle.ReferenceTrace, +) (Allocator.Error || error{AlreadyReported})!std.zig.ErrorBundle.MessageIndex { + const ip = &zcu.intern_pool; + const comp = zcu.comp; + + const fmt_source: std.fmt.Alt(FormatAnalUnit, formatDependencyLoopSourceUnit) = .{ .data = .{ + .unit = source_unit, + .zcu = zcu, + } }; + + const dep_node = zcu.dependency_loop_nodes.get(source_unit).?; + + const msg: std.zig.ErrorBundle.String = switch (dep_node.unit.unwrap()) { + .@"comptime" => unreachable, // cannot be involved in a dependency loop + .nav_val => |nav| try eb.printString("{f} uses value of declaration '{f}' here", .{ + fmt_source, ip.getNav(nav).fqn.fmt(ip), + }), + .nav_ty => |nav| try eb.printString("{f} uses type of declaration '{f}' here", .{ + fmt_source, ip.getNav(nav).fqn.fmt(ip), + }), + .memoized_state => |stage| switch (stage) { + .panic => try eb.printString("{f} requires panic handler for call here", .{fmt_source}), + else => try eb.printString("{f} requires 'std.builtin' declarations here", .{fmt_source}), + }, + .func => |func| try eb.printString("{f} uses inferred error set of function '{f}' here", .{ + fmt_source, ip.getNav(zcu.funcInfo(func).owner_nav).fqn.fmt(ip), + }), + .type_layout => |ty| try eb.printString("{f} depends on type '{f}' {s}", .{ + fmt_source, + Type.fromInterned(ty).containerTypeName(ip).fmt(ip), + dep_node.reason.type_layout_reason.msg(), + }), + }; + + const src_loc = dep_node.reason.src.upgrade(zcu); + const source = src_loc.file_scope.getSource(zcu) catch |err| { + try Compilation.unableToLoadZcuFile(zcu, eb, src_loc.file_scope, err); + return error.AlreadyReported; + }; + const span = src_loc.span(zcu) catch |err| { + try Compilation.unableToLoadZcuFile(zcu, eb, src_loc.file_scope, err); + return error.AlreadyReported; + }; + const loc = std.zig.findLineColumn(source, span.main); + const eb_src = try eb.addSourceLocation(.{ + .src_path = try eb.printString("{f}", .{src_loc.file_scope.path.fmt(comp)}), + .span_start = span.start, + .span_main = span.main, + .span_end = span.end, + .line = @intCast(loc.line), + .column = @intCast(loc.column), + .source_line = try eb.addString(loc.source_line), + .reference_trace_len = @intCast(ref_trace.len), + }); + for (ref_trace) |rt| try eb.addReferenceTrace(rt); + return eb.addErrorMessage(.{ + .msg = msg, + .src_loc = eb_src, + }); +} +fn formatDependencyLoopSourceUnit(data: FormatAnalUnit, w: *Io.Writer) Io.Writer.Error!void { + const zcu = data.zcu; + const ip = &zcu.intern_pool; + switch (data.unit.unwrap()) { + .@"comptime" => unreachable, // cannot be involved in a dependency loop + .nav_val => |nav| try w.print("value of declaration '{f}'", .{ip.getNav(nav).fqn.fmt(ip)}), + .nav_ty => |nav| try w.print("type of declaration '{f}'", .{ip.getNav(nav).fqn.fmt(ip)}), + .memoized_state => |stage| switch (stage) { + .panic => try w.writeAll("panic handler"), + else => try w.writeAll("'std.builtin' declarations"), + }, + .type_layout => |ty| try w.print("type '{f}'", .{ + Type.fromInterned(ty).containerTypeName(ip).fmt(ip), + }), + .func => |func| try w.print("function '{f}'", .{ + ip.getNav(zcu.funcInfo(func).owner_nav).fqn.fmt(ip), + }), + } +} + +pub fn populateReferenceTrace( + zcu: *Zcu, + root: AnalUnit, + frame_limit: u32, + eb: *std.zig.ErrorBundle.Wip, + ref_trace: *std.ArrayList(std.zig.ErrorBundle.ReferenceTrace), +) Allocator.Error!void { + const ip = &zcu.intern_pool; + const gpa = zcu.comp.gpa; + + if (frame_limit == 0) return; + + const all_references = try zcu.resolveReferences(); + + var seen: std.AutoHashMapUnmanaged(InternPool.AnalUnit, void) = .empty; + defer seen.deinit(gpa); + + var referenced_by = root; + while (all_references.get(referenced_by)) |maybe_ref| { + const ref = maybe_ref orelse break; + const gop = try seen.getOrPut(gpa, ref.referencer); + if (gop.found_existing) break; + if (ref_trace.items.len < frame_limit) { + var last_call_src = ref.src; + var opt_inline_frame = ref.inline_frame; + while (opt_inline_frame.unwrap()) |inline_frame| { + const f = inline_frame.ptr(zcu).*; + const func_nav = ip.indexToKey(f.callee).func.owner_nav; + const func_name = ip.getNav(func_nav).name.toSlice(ip); + addReferenceTraceFrame(zcu, eb, ref_trace, func_name, last_call_src, true) catch |err| switch (err) { + error.OutOfMemory => |e| return e, + error.AlreadyReported => { + // An incomplete reference trace isn't the end of the world; just cut it off. + return; + }, + }; + last_call_src = f.call_src; + opt_inline_frame = f.parent; + } + const root_name: ?[]const u8 = switch (ref.referencer.unwrap()) { + .@"comptime" => "comptime", + .nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip), + .type_layout => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), + .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip), + .memoized_state => null, + }; + if (root_name) |n| { + addReferenceTraceFrame(zcu, eb, ref_trace, n, last_call_src, false) catch |err| switch (err) { + error.OutOfMemory => |e| return e, + error.AlreadyReported => { + // An incomplete reference trace isn't the end of the world; just cut it off. + return; + }, + }; + } + } + referenced_by = ref.referencer; + } + + if (seen.count() > ref_trace.items.len) { + try ref_trace.append(gpa, .{ + .decl_name = @intCast(seen.count() - ref_trace.items.len), + .src_loc = .none, + }); + } +} +fn addReferenceTraceFrame( + zcu: *Zcu, + eb: *std.zig.ErrorBundle.Wip, + ref_trace: *std.ArrayList(std.zig.ErrorBundle.ReferenceTrace), + name: []const u8, + lazy_src: Zcu.LazySrcLoc, + inlined: bool, +) error{ OutOfMemory, AlreadyReported }!void { + const gpa = zcu.gpa; + const src = lazy_src.upgrade(zcu); + const source = src.file_scope.getSource(zcu) catch |err| { + try Compilation.unableToLoadZcuFile(zcu, eb, src.file_scope, err); + return error.AlreadyReported; + }; + const span = src.span(zcu) catch |err| { + try Compilation.unableToLoadZcuFile(zcu, eb, src.file_scope, err); + return error.AlreadyReported; + }; + const loc = std.zig.findLineColumn(source, span.main); + try ref_trace.append(gpa, .{ + .decl_name = try eb.printString("{s}{s}", .{ name, if (inlined) " [inlined]" else "" }), + .src_loc = try eb.addSourceLocation(.{ + .src_path = try eb.printString("{f}", .{src.file_scope.path.fmt(zcu.comp)}), + .span_start = span.start, + .span_main = span.main, + .span_end = span.end, + .line = @intCast(loc.line), + .column = @intCast(loc.column), + .source_line = 0, + }), + }); +} + const TrackedUnitSema = struct { /// `null` means we created the node, so should end it. old_name: ?[std.Progress.Node.max_name_len]u8, diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 8d6af9c3ad7c4e688be88323f3578ce571a2f500..954d1cd3bff44529db52325785eb7aa7d1c1f0d2 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -728,7 +728,12 @@ pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Alloca /// Ensures that all memoized state on `Zcu` is up-to-date, performing re-analysis if necessary. /// Returns `error.AnalysisFail` if an analysis error is encountered; the caller is free to ignore /// this, since the error is already registered, but it must not use the value of memoized fields. -pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage) Zcu.SemaError!void { +pub fn ensureMemoizedStateUpToDate( + pt: Zcu.PerThread, + stage: InternPool.MemoizedStateStage, + /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. + reason: ?*const Zcu.DependencyReason, +) Zcu.SemaError!void { const tracy = trace(@src()); defer tracy.end(); @@ -748,12 +753,7 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized dev.check(.incremental); _ = zcu.outdated_ready.swapRemove(unit); // No need for `deleteUnitExports` because we never export anything. - zcu.deleteUnitReferences(unit); - zcu.deleteUnitCompileLogs(unit); - if (zcu.failed_analysis.fetchSwapRemove(unit)) |kv| { - kv.value.destroy(gpa); - } - _ = zcu.transitive_failed_analysis.swapRemove(unit); + zcu.resetUnit(unit); } else { if (prev_failed) return error.AnalysisFail; // We use an arbitrary element to check if the state has been resolved yet. @@ -772,7 +772,7 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized info.deps.clearRetainingCapacity(); } - const any_changed: bool, const new_failed: bool = if (pt.analyzeMemoizedState(stage)) |any_changed| + const any_changed: bool, const new_failed: bool = if (pt.analyzeMemoizedState(stage, reason)) |any_changed| .{ any_changed or prev_failed, false } else |err| switch (err) { error.AnalysisFail => res: { @@ -805,14 +805,18 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized if (new_failed) return error.AnalysisFail; } -fn analyzeMemoizedState(pt: Zcu.PerThread, stage: InternPool.MemoizedStateStage) Zcu.CompileError!bool { +fn analyzeMemoizedState( + pt: Zcu.PerThread, + stage: InternPool.MemoizedStateStage, + reason: ?*const Zcu.DependencyReason, +) Zcu.CompileError!bool { const zcu = pt.zcu; const comp = zcu.comp; const gpa = comp.gpa; const unit: AnalUnit = .wrap(.{ .memoized_state = stage }); - try zcu.analysis_in_progress.putNoClobber(gpa, unit, {}); + try zcu.analysis_in_progress.putNoClobber(gpa, unit, reason); defer assert(zcu.analysis_in_progress.swapRemove(unit)); var analysis_arena: std.heap.ArenaAllocator = .init(gpa); @@ -871,13 +875,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU // `was_outdated` can be true in the initial update for comptime units, so this isn't a `dev.check`. if (dev.env.supports(.incremental)) { zcu.deleteUnitExports(anal_unit); - zcu.deleteUnitReferences(anal_unit); - zcu.deleteUnitCompileLogs(anal_unit); - if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| { - kv.value.destroy(gpa); - } - _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); - zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit); + zcu.resetUnit(anal_unit); } } else { // We can trust the current information about this unit. @@ -943,7 +941,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu const file = zcu.fileByIndex(inst_resolved.file); const zir = file.zir.?; - try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, {}); + try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, null); defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); var analysis_arena: std.heap.ArenaAllocator = .init(gpa); @@ -1009,7 +1007,12 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu /// re-analysis if necessary. Asserts that `ty` is a struct (not a tuple!) or union. Returns /// `error.AnalysisFail` if an analysis error is encountered during type resolution; the caller is /// free to ignore this, since the error is already registered. -pub fn ensureTypeLayoutUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void { +pub fn ensureTypeLayoutUpToDate( + pt: Zcu.PerThread, + ty: Type, + /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. + reason: ?*const Zcu.DependencyReason, +) Zcu.SemaError!void { const tracy = trace(@src()); defer tracy.end(); @@ -1031,13 +1034,7 @@ pub fn ensureTypeLayoutUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void // `was_outdated` is true in the initial update, so this isn't a `dev.check`. if (dev.env.supports(.incremental)) { zcu.deleteUnitExports(anal_unit); - zcu.deleteUnitReferences(anal_unit); - zcu.deleteUnitCompileLogs(anal_unit); - if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| { - kv.value.destroy(gpa); - } - _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); - zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit); + zcu.resetUnit(anal_unit); } // For types, we already know that we have to invalidate all dependees. // TODO: we actually *could* detect whether everything was the same. should we bother? @@ -1058,7 +1055,7 @@ pub fn ensureTypeLayoutUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void const unit_tracking = zcu.trackUnitSema(ty.containerTypeName(&zcu.intern_pool).toSlice(&zcu.intern_pool), null); defer unit_tracking.end(zcu); - try zcu.analysis_in_progress.put(gpa, anal_unit, {}); + try zcu.analysis_in_progress.put(gpa, anal_unit, reason); defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); var analysis_arena: std.heap.ArenaAllocator = .init(gpa); @@ -1114,7 +1111,12 @@ pub fn ensureTypeLayoutUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void /// Ensures that the resolved value of the given `Nav` is fully up-to-date, performing re-analysis /// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is /// free to ignore this, since the error is already registered. -pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.SemaError!void { +pub fn ensureNavValUpToDate( + pt: Zcu.PerThread, + nav_id: InternPool.Nav.Index, + /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. + reason: ?*const Zcu.DependencyReason, +) Zcu.SemaError!void { const tracy = trace(@src()); defer tracy.end(); @@ -1150,13 +1152,7 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu dev.check(.incremental); _ = zcu.outdated_ready.swapRemove(anal_unit); zcu.deleteUnitExports(anal_unit); - zcu.deleteUnitReferences(anal_unit); - zcu.deleteUnitCompileLogs(anal_unit); - if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| { - kv.value.destroy(gpa); - } - _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); - ip.removeDependenciesForDepender(gpa, anal_unit); + zcu.resetUnit(anal_unit); } else { // We can trust the current information about this unit. if (prev_failed) return error.AnalysisFail; @@ -1173,7 +1169,7 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu const unit_tracking = zcu.trackUnitSema(nav.fqn.toSlice(ip), nav.srcInst(ip)); defer unit_tracking.end(zcu); - const invalidate_value: bool, const new_failed: bool = if (pt.analyzeNavVal(nav_id)) |result| res: { + const invalidate_value: bool, const new_failed: bool = if (pt.analyzeNavVal(nav_id, reason)) |result| res: { break :res .{ // If the unit has gone from failed to success, we still need to invalidate the dependencies. result.val_changed or prev_failed, @@ -1217,39 +1213,14 @@ pub fn ensureNavValUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu } } - // If there isn't a type annotation, then we have also just resolved the type. That means the - // the type is up-to-date, so it won't have the chance to mark its own dependency on the value; - // we must do that ourselves. - type_deps_on_val: { - const inst_resolved = nav.analysis.?.zir_index.resolveFull(ip) orelse break :type_deps_on_val; - const file = zcu.fileByIndex(inst_resolved.file); - const zir_decl = file.zir.?.getDeclaration(inst_resolved.inst); - if (zir_decl.type_body != null) break :type_deps_on_val; - // The type does indeed depend on the value. We are responsible for populating all state of - // the `nav_ty`, including exports, references, errors, and dependencies. - const ty_unit: AnalUnit = .wrap(.{ .nav_ty = nav_id }); - const ty_was_outdated = zcu.outdated.swapRemove(ty_unit) or - zcu.potentially_outdated.swapRemove(ty_unit); - if (ty_was_outdated) { - _ = zcu.outdated_ready.swapRemove(ty_unit); - zcu.deleteUnitExports(ty_unit); - zcu.deleteUnitReferences(ty_unit); - zcu.deleteUnitCompileLogs(ty_unit); - if (zcu.failed_analysis.fetchSwapRemove(ty_unit)) |kv| { - kv.value.destroy(gpa); - } - _ = zcu.transitive_failed_analysis.swapRemove(ty_unit); - ip.removeDependenciesForDepender(gpa, ty_unit); - } - try pt.addDependency(ty_unit, .{ .nav_val = nav_id }); - if (new_failed) try zcu.transitive_failed_analysis.put(gpa, ty_unit, {}); - if (ty_was_outdated) try zcu.markDependeeOutdated(.marked_po, .{ .nav_ty = nav_id }); - } - if (new_failed) return error.AnalysisFail; } -fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileError!struct { val_changed: bool } { +fn analyzeNavVal( + pt: Zcu.PerThread, + nav_id: InternPool.Nav.Index, + reason: ?*const Zcu.DependencyReason, +) Zcu.CompileError!struct { val_changed: bool } { const zcu = pt.zcu; const ip = &zcu.intern_pool; const comp = zcu.comp; @@ -1266,17 +1237,9 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr const zir = file.zir.?; const zir_decl = zir.getDeclaration(inst_resolved.inst); - try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, {}); + try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, reason); errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit); - // If there's no type body, we are also resolving the type here. - if (zir_decl.type_body == null) { - try zcu.analysis_in_progress.putNoClobber(gpa, .wrap(.{ .nav_ty = nav_id }), {}); - } - errdefer if (zir_decl.type_body == null) { - _ = zcu.analysis_in_progress.swapRemove(.wrap(.{ .nav_ty = nav_id })); - }; - var analysis_arena: std.heap.ArenaAllocator = .init(gpa); defer analysis_arena.deinit(); @@ -1352,9 +1315,6 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr const nav_ty: Type = maybe_ty orelse final_val.?.typeOf(zcu); - // First, we must resolve the declaration's type. To do this, we analyze the type body if available, - // or otherwise, we analyze the value body, populating `early_val` in the process. - const is_const = is_const: switch (zir_decl.kind) { .@"comptime" => unreachable, // this is not a Nav .unnamed_test, .@"test", .decltest => { @@ -1441,7 +1401,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr // This resolves the type of the resolved value, not that value itself. If `nav_val` is a struct type, // this resolves the type `type` (which needs no resolution), not the struct itself. - try sema.ensureLayoutResolved(nav_ty, init_src); + try sema.ensureLayoutResolved(nav_ty, block.nodeOffset(.zero), if (zir_decl.kind == .@"var") .variable else .constant); const queue_linker_work, const is_owned_fn = switch (ip.indexToKey(nav_val.toIntern())) { .func => |f| .{ true, f.owner_nav == nav_id }, // note that this lets function aliases reach codegen @@ -1460,18 +1420,18 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr } } else if (nav_ty.comptimeOnly(zcu)) { // alignment, linksection, addrspace annotations are not allowed for comptime-only types. - const reason: []const u8 = switch (ip.indexToKey(nav_val.toIntern())) { + const cannot_align_reason: []const u8 = switch (ip.indexToKey(nav_val.toIntern())) { .func => "function alias", // slightly clearer message, since you *can* specify these on function *declarations* else => "comptime-only type", }; if (zir_decl.align_body != null) { - return sema.fail(&block, align_src, "cannot specify alignment of {s}", .{reason}); + return sema.fail(&block, align_src, "cannot specify alignment of {s}", .{cannot_align_reason}); } if (zir_decl.linksection_body != null) { - return sema.fail(&block, section_src, "cannot specify linksection of {s}", .{reason}); + return sema.fail(&block, section_src, "cannot specify linksection of {s}", .{cannot_align_reason}); } if (zir_decl.addrspace_body != null) { - return sema.fail(&block, addrspace_src, "cannot specify addrspace of {s}", .{reason}); + return sema.fail(&block, addrspace_src, "cannot specify addrspace of {s}", .{cannot_align_reason}); } } @@ -1484,10 +1444,8 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr }); // Mark the unit as completed before evaluating the export! + // MLUGG TODO: do we really need to do this? assert(zcu.analysis_in_progress.swapRemove(anal_unit)); - if (zir_decl.type_body == null) { - assert(zcu.analysis_in_progress.swapRemove(.wrap(.{ .nav_ty = nav_id }))); - } if (zir_decl.linkage == .@"export") { const export_src = block.src(.{ .token_offset = @enumFromInt(@intFromBool(zir_decl.is_pub)) }); @@ -1516,7 +1474,12 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr } } -pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.SemaError!void { +pub fn ensureNavTypeUpToDate( + pt: Zcu.PerThread, + nav_id: InternPool.Nav.Index, + /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. + reason: ?*const Zcu.DependencyReason, +) Zcu.SemaError!void { const tracy = trace(@src()); defer tracy.end(); @@ -1533,18 +1496,6 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc try zcu.ensureNavValAnalysisQueued(nav_id); - const type_resolved_by_value: bool = from_val: { - const analysis = nav.analysis orelse break :from_val false; - const inst_resolved = analysis.zir_index.resolveFull(ip) orelse break :from_val false; - const file = zcu.fileByIndex(inst_resolved.file); - const zir_decl = file.zir.?.getDeclaration(inst_resolved.inst); - break :from_val zir_decl.type_body == null; - }; - if (type_resolved_by_value) { - // Logic at the end of `ensureNavValUpToDate` is directly responsible for populating our state. - return pt.ensureNavValUpToDate(nav_id); - } - // Determine whether or not this `Nav`'s type is outdated. This also includes checking if the // status is `.unresolved`, which indicates that the value is outdated because it has *never* // been analyzed so far. @@ -1564,13 +1515,7 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc dev.check(.incremental); _ = zcu.outdated_ready.swapRemove(anal_unit); zcu.deleteUnitExports(anal_unit); - zcu.deleteUnitReferences(anal_unit); - zcu.deleteUnitCompileLogs(anal_unit); - if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| { - kv.value.destroy(gpa); - } - _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); - ip.removeDependenciesForDepender(gpa, anal_unit); + zcu.resetUnit(anal_unit); } else { // We can trust the current information about this unit. if (prev_failed) return error.AnalysisFail; @@ -1587,7 +1532,7 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc const unit_tracking = zcu.trackUnitSema(nav.fqn.toSlice(ip), nav.srcInst(ip)); defer unit_tracking.end(zcu); - const invalidate_type: bool, const new_failed: bool = if (pt.analyzeNavType(nav_id)) |result| res: { + const invalidate_type: bool, const new_failed: bool = if (pt.analyzeNavType(nav_id, reason)) |result| res: { break :res .{ // If the unit has gone from failed to success, we still need to invalidate the dependencies. result.type_changed or prev_failed, @@ -1634,7 +1579,11 @@ pub fn ensureNavTypeUpToDate(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zc if (new_failed) return error.AnalysisFail; } -fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileError!struct { type_changed: bool } { +fn analyzeNavType( + pt: Zcu.PerThread, + nav_id: InternPool.Nav.Index, + reason: ?*const Zcu.DependencyReason, +) Zcu.CompileError!struct { type_changed: bool } { const zcu = pt.zcu; const comp = zcu.comp; const gpa = comp.gpa; @@ -1650,11 +1599,10 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr const file = zcu.fileByIndex(inst_resolved.file); const zir = file.zir.?; - try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, {}); + try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, reason); defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); const zir_decl = zir.getDeclaration(inst_resolved.inst); - const type_body = zir_decl.type_body.?; var analysis_arena: std.heap.ArenaAllocator = .init(gpa); defer analysis_arena.deinit(); @@ -1696,6 +1644,17 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr defer block.instructions.deinit(gpa); const ty_src = block.src(.{ .node_offset_var_decl_ty = .zero }); + const init_src = block.src(.{ .node_offset_var_decl_init = .zero }); + + const type_body = zir_decl.type_body orelse { + // There is no type annotation, so we just need to use the declaration's value. + try sema.ensureNavResolved(&block, init_src, nav_id, .fully); + // We don't actually know what the type of this Nav was before it was resolved, so we just + // have to assume we were outdated. This isn't too bad, because assuming there was also no + // type annotation last update, we should only be re-analyzed if the value changes (it's our + // only dependency), or if there was a dependency loop. + return .{ .type_changed = true }; + }; block.comptime_reason = .{ .reason = .{ .src = ty_src, @@ -1708,7 +1667,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr break :ty .fromInterned(type_ref.toInterned().?); }; - try sema.ensureLayoutResolved(resolved_ty, ty_src); + try sema.ensureLayoutResolved(resolved_ty, block.nodeOffset(.zero), if (zir_decl.kind == .@"var") .variable else .constant); // In the case where the type is specified, this function is also responsible for resolving // the pointer modifiers, i.e. alignment, linksection, addrspace. @@ -1758,7 +1717,12 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr return .{ .type_changed = true }; } -pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!void { +pub fn ensureFuncBodyUpToDate( + pt: Zcu.PerThread, + func_index: InternPool.Index, + /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. + reason: ?*const Zcu.DependencyReason, +) Zcu.SemaError!void { dev.check(.sema); const tracy = trace(@src()); @@ -1788,12 +1752,7 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, func_index: InternPool.Index) Z dev.check(.incremental); _ = zcu.outdated_ready.swapRemove(anal_unit); zcu.deleteUnitExports(anal_unit); - zcu.deleteUnitReferences(anal_unit); - zcu.deleteUnitCompileLogs(anal_unit); - if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| { - kv.value.destroy(gpa); - } - _ = zcu.transitive_failed_analysis.swapRemove(anal_unit); + zcu.resetUnit(anal_unit); } else { // We can trust the current information about this function. if (prev_failed) return error.AnalysisFail; @@ -1813,7 +1772,7 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, func_index: InternPool.Index) Z ); defer unit_tracking.end(zcu); - const ies_outdated, const new_failed = if (pt.analyzeFuncBody(func_index)) |result| + const ies_outdated, const new_failed = if (pt.analyzeFuncBody(func_index, reason)) |result| .{ prev_failed or result.ies_outdated, false } else |err| switch (err) { error.AnalysisFail => res: { @@ -1854,6 +1813,7 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, func_index: InternPool.Index) Z fn analyzeFuncBody( pt: Zcu.PerThread, func_index: InternPool.Index, + reason: ?*const Zcu.DependencyReason, ) Zcu.SemaError!struct { ies_outdated: bool } { const zcu = pt.zcu; const gpa = zcu.gpa; @@ -1868,7 +1828,7 @@ fn analyzeFuncBody( if (func.generic_owner == .none) { // Among another things, this ensures that the function's `zir_body_inst` is correct. - try pt.ensureNavValUpToDate(func.owner_nav); + try pt.ensureNavValUpToDate(func.owner_nav, reason); if (ip.getNav(func.owner_nav).status.fully_resolved.val != func_index) { // This function is no longer referenced! There's no point in re-analyzing it. // Just mark a transitive failure and move on. @@ -1877,7 +1837,7 @@ fn analyzeFuncBody( } else { const go_nav = zcu.funcInfo(func.generic_owner).owner_nav; // Among another things, this ensures that the function's `zir_body_inst` is correct. - try pt.ensureNavValUpToDate(go_nav); + try pt.ensureNavValUpToDate(go_nav, reason); if (ip.getNav(go_nav).status.fully_resolved.val != func.generic_owner) { // The generic owner is no longer referenced, so this function is also unreferenced. // There's no point in re-analyzing it. Just mark a transitive failure and move on. @@ -1894,7 +1854,7 @@ fn analyzeFuncBody( log.debug("analyze and generate fn body {f}", .{zcu.fmtAnalUnit(anal_unit)}); - var air = try pt.analyzeFuncBodyInner(func_index); + var air = try pt.analyzeFuncBodyInner(func_index, reason); errdefer air.deinit(gpa); const ies_outdated = !func.analysisUnordered(ip).inferred_error_set or @@ -2842,7 +2802,11 @@ const ScanDeclIter = struct { } }; -fn analyzeFuncBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!Air { +fn analyzeFuncBodyInner( + pt: Zcu.PerThread, + func_index: InternPool.Index, + reason: ?*const Zcu.DependencyReason, +) Zcu.SemaError!Air { const tracy = trace(@src()); defer tracy.end(); @@ -2858,7 +2822,7 @@ fn analyzeFuncBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.Sem const file = zcu.fileByIndex(inst_info.file); const zir = file.zir.?; - try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, {}); + try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, reason); defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); if (func.analysisUnordered(ip).inferred_error_set) { @@ -2879,8 +2843,6 @@ fn analyzeFuncBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.Sem const func_nav = ip.getNav(func.owner_nav); - zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit); - var analysis_arena = std.heap.ArenaAllocator.init(gpa); defer analysis_arena.deinit(); @@ -2978,7 +2940,7 @@ fn analyzeFuncBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.Sem const param_ty: Type = .fromInterned(fn_ty_info.param_types.get(ip)[runtime_param_index]); runtime_param_index += 1; - try sema.ensureLayoutResolved(param_ty, inner_block.src(.{ .func_decl_param_ty = @intCast(zir_param_index) })); + try sema.ensureLayoutResolved(param_ty, inner_block.src(.{ .func_decl_param_ty = @intCast(zir_param_index) }), .parameter); if (try param_ty.onePossibleValue(pt)) |opv| { gop.value_ptr.* = .fromValue(opv); continue; @@ -2995,7 +2957,7 @@ fn analyzeFuncBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.Sem }); } - try sema.ensureLayoutResolved(sema.fn_ret_ty, inner_block.src(.{ .node_offset_fn_type_ret_ty = .zero })); + try sema.ensureLayoutResolved(sema.fn_ret_ty, inner_block.src(.{ .node_offset_fn_type_ret_ty = .zero }), .return_type); const last_arg_index = inner_block.instructions.items.len; @@ -4206,7 +4168,7 @@ pub fn resolveTypeForCodegen(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void { }, .@"struct" => switch (ip.indexToKey(ty.toIntern())) { - .struct_type => try pt.ensureTypeLayoutUpToDate(ty), + .struct_type => try pt.ensureTypeLayoutUpToDate(ty, null), .tuple_type => |tuple| for (0..tuple.types.len) |i| { const field_is_comptime = tuple.values.get(ip)[i] != .none; if (field_is_comptime) continue; @@ -4216,8 +4178,8 @@ pub fn resolveTypeForCodegen(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void { else => unreachable, }, - .@"union" => try pt.ensureTypeLayoutUpToDate(ty), - .@"enum" => try pt.ensureTypeLayoutUpToDate(ty), + .@"union" => try pt.ensureTypeLayoutUpToDate(ty, null), + .@"enum" => try pt.ensureTypeLayoutUpToDate(ty, null), } } pub fn resolveValueTypesForCodegen(pt: Zcu.PerThread, val: Value) Zcu.SemaError!void { diff --git a/test/incremental/type_dependency_loop b/test/incremental/type_dependency_loop new file mode 100644 index 0000000000000000000000000000000000000000..40f41bf19fe4bb4d7a19b5a4a40a0a10fb361ca9 --- /dev/null +++ b/test/incremental/type_dependency_loop @@ -0,0 +1,55 @@ +#target=x86_64-linux-selfhosted +#target=x86_64-windows-selfhosted +#target=x86_64-linux-cbe +#target=x86_64-windows-cbe +#target=wasm32-wasi-selfhosted +#update=initial version +#file=main.zig +pub const A = struct { b: B }; +pub const B = struct { a: A }; +pub fn main() void { + _ = @as(B, undefined); +} +#expect_error=:error: dependency loop with length 2 +#expect_error=main.zig:2:27: note: type 'main.B' depends on type 'main.A' for field declared here +#expect_error=main.zig:1:27: note: type 'main.A' depends on type 'main.B' for field declared here +#expect_error=:note: eliminate any one of these dependencies to break the loop + +#update=remove reference to dependency loop +#file=main.zig +pub const A = struct { b: B }; +pub const B = struct { a: A }; +pub fn main() void { + _ = B; +} +#expect_stdout="" + +#update=change dependency loop without fixing it +#file=main.zig +pub const A = struct { b: B }; +pub const B = struct { a: *align(@alignOf(A)) A }; +pub fn main() void { + _ = B; +} +#expect_stdout="" + +#update=reference dependency loop again +#file=main.zig +pub const A = struct { b: B }; +pub const B = struct { a: *align(@alignOf(A)) A }; +pub fn main() void { + _ = @as(B, undefined); +} +#expect_error=:error: dependency loop with length 2 +#expect_error=main.zig:2:43: note: type 'main.B' depends on type 'main.A' for alignment query here +#expect_error=main.zig:1:27: note: type 'main.A' depends on type 'main.B' for field declared here +#expect_error=:note: eliminate any one of these dependencies to break the loop + +#update=fix dependency loop +#file=main.zig +pub const A = struct { b: B }; +pub const B = struct { a: *A }; +pub fn main() void { + _ = @as(B, undefined); +} +#expect_stdout="" diff --git a/tools/incr-check.zig b/tools/incr-check.zig index 171af570361c4986b3ddd75ac909d2ba6b1a7551..87a782c2d314d7e2467fbd8e6fe35a3e27bf0489 100644 --- a/tools/incr-check.zig +++ b/tools/incr-check.zig @@ -417,29 +417,32 @@ const Eval = struct { is_note: bool, err_idx: std.zig.ErrorBundle.MessageIndex, ) Allocator.Error!void { + const io = eval.io; const err = eb.getErrorMessage(err_idx); - if (err.src_loc == .none) @panic("TODO error message with no source location"); if (err.count != 1) @panic("TODO error message with count>1"); const msg = eb.nullTerminatedString(err.msg); - const src = eb.getSourceLocation(err.src_loc); - const raw_filename = eb.nullTerminatedString(src.src_path); - - const io = eval.io; - - // We need to replace backslashes for consistency between platforms. - const filename = name: { - if (std.mem.indexOfScalar(u8, raw_filename, '\\') == null) break :name raw_filename; - const copied = try eval.arena.dupe(u8, raw_filename); - std.mem.replaceScalar(u8, copied, '\\', '/'); - break :name copied; + const matches = matches: { + if (expected.is_note != is_note) break :matches false; + if (!std.mem.eql(u8, expected.msg, msg)) break :matches false; + if (err.src_loc == .none) { + break :matches expected.src == null; + } + const expected_src = expected.src orelse break :matches false; + const src = eb.getSourceLocation(err.src_loc); + const raw_filename = eb.nullTerminatedString(src.src_path); + // We need to replace backslashes for consistency between platforms. + const filename = name: { + if (std.mem.indexOfScalar(u8, raw_filename, '\\') == null) break :name raw_filename; + const copied = try eval.arena.dupe(u8, raw_filename); + std.mem.replaceScalar(u8, copied, '\\', '/'); + break :name copied; + }; + if (!std.mem.eql(u8, expected_src.filename, filename)) break :matches false; + if (expected_src.line != src.line + 1) break :matches false; + if (expected_src.column != src.column + 1) break :matches false; + break :matches true; }; - - if (expected.is_note != is_note or - !std.mem.eql(u8, expected.filename, filename) or - expected.line != src.line + 1 or - expected.column != src.column + 1 or - !std.mem.eql(u8, expected.msg, msg)) - { + if (!matches) { eb.renderToStderr(io, .{}, .auto) catch {}; eval.fatal("compile error did not match expected error", .{}); } @@ -714,10 +717,12 @@ const Case = struct { const ExpectedError = struct { is_note: bool, - filename: []const u8, - line: u32, - column: u32, msg: []const u8, + src: ?struct { + filename: []const u8, + line: u32, + column: u32, + }, }; fn parse(arena: Allocator, io: Io, bytes: []const u8) !Case { @@ -930,16 +935,16 @@ fn parseExpectedError(str: []const u8, l: usize) Case.ExpectedError { var it = std.mem.splitScalar(u8, str, ':'); const filename = it.first(); - const line_str = it.next() orelse fatal("line {d}: incomplete error specification", .{l}); - const column_str = it.next() orelse fatal("line {d}: incomplete error specification", .{l}); + const line_str, const column_str = if (filename.len > 0) .{ + it.next() orelse fatal("line {d}: incomplete error specification", .{l}), + it.next() orelse fatal("line {d}: incomplete error specification", .{l}), + } else .{ undefined, undefined }; const error_or_note_str = std.mem.trim( u8, it.next() orelse fatal("line {d}: incomplete error specification", .{l}), " ", ); - const message = std.mem.trim(u8, it.rest(), " "); - if (filename.len == 0) fatal("line {d}: empty filename", .{l}); - if (message.len == 0) fatal("line {d}: empty error message", .{l}); + const is_note = if (std.mem.eql(u8, error_or_note_str, "error")) false else if (std.mem.eql(u8, error_or_note_str, "note")) @@ -947,18 +952,19 @@ fn parseExpectedError(str: []const u8, l: usize) Case.ExpectedError { else fatal("line {d}: expeted 'error' or 'note', found '{s}'", .{ l, error_or_note_str }); - const line = std.fmt.parseInt(u32, line_str, 10) catch - fatal("line {d}: invalid line number '{s}'", .{ l, line_str }); - - const column = std.fmt.parseInt(u32, column_str, 10) catch - fatal("line {d}: invalid column number '{s}'", .{ l, column_str }); + const message = std.mem.trim(u8, it.rest(), " "); + if (message.len == 0) fatal("line {d}: empty error message", .{l}); return .{ .is_note = is_note, - .filename = filename, - .line = line, - .column = column, .msg = message, + .src = if (filename.len == 0) null else .{ + .filename = filename, + .line = std.fmt.parseInt(u32, line_str, 10) catch + fatal("line {d}: invalid line number '{s}'", .{ l, line_str }), + .column = std.fmt.parseInt(u32, column_str, 10) catch + fatal("line {d}: invalid column number '{s}'", .{ l, column_str }), + }, }; } -- 2.54.0 From c91b06ef52f31090b3c8fda9b9a419bf1391d805 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Wed, 4 Mar 2026 19:13:59 +0000 Subject: [PATCH 17/79] incr-check: fix successful -fno-emit-bin updates --- tools/incr-check.zig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/incr-check.zig b/tools/incr-check.zig index 87a782c2d314d7e2467fbd8e6fe35a3e27bf0489..6b3351b315a3c23a443faca94c61bae0367a304e 100644 --- a/tools/incr-check.zig +++ b/tools/incr-check.zig @@ -338,7 +338,7 @@ const Eval = struct { if (eval.target.backend == .sema) { try eval.checkSuccessOutcome(update, null, prog_node); - // This message indicates the end of the update. + continue; } const digest = r.takeArray(Cache.bin_digest_len) catch unreachable; @@ -352,7 +352,6 @@ const Eval = struct { const bin_path = try Dir.path.join(arena, &.{ result_dir, bin_name }); try eval.checkSuccessOutcome(update, bin_path, prog_node); - // This message indicates the end of the update. }, else => { // Ignore other messages. -- 2.54.0 From 03e23bcbdea2e832307085e5855ca20b51ac9d9a Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sat, 7 Feb 2026 12:23:54 +0000 Subject: [PATCH 18/79] resolve some of my TODOs --- src/Sema.zig | 141 ++++++++++++++++++++---------------------- src/Sema/LowerZon.zig | 110 +++++++++++++++----------------- src/Value.zig | 1 - src/Zcu.zig | 72 ++++++++++----------- src/Zcu/PerThread.zig | 14 +---- 5 files changed, 148 insertions(+), 190 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index cbfe6421db8b7fc50a3954664eb93e3c0ff295f5..0504bb7e5e251d656e2daf1f0e016d098a80e520 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5746,91 +5746,94 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void } } + const export_ty = ptr_ty.childType(zcu); + if (!export_ty.validateExtern(.other, zcu)) { + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(src, "unable to export type '{f}'", .{export_ty.fmt(pt)}); + errdefer msg.destroy(sema.gpa); + try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other); + try sema.addDeclaredHereNote(msg, export_ty); + break :msg msg; + }); + } + const ptr_info = ip.indexToKey(ptr_val.toIntern()).ptr; - switch (ptr_info.base_addr) { + const target: Zcu.Exported = switch (ptr_info.base_addr) { .comptime_alloc, .int, .comptime_field => return sema.fail(block, ptr_src, "export target must be a global variable or a comptime-known constant", .{}), .eu_payload, .opt_payload, .field, .arr_elem => return sema.fail(block, ptr_src, "TODO: export pointer in middle of value", .{}), - .uav => |uav| { - if (ptr_info.byte_offset != 0) { - return sema.fail(block, ptr_src, "TODO: export pointer in middle of value", .{}); + .uav => |uav| .{ .uav = uav.val }, + .nav => |orig_nav| target: { + try sema.ensureNavResolved(block, src, orig_nav, .fully); + const export_nav = switch (ip.indexToKey(ip.getNav(orig_nav).status.fully_resolved.val)) { + .variable => |v| v.owner_nav, + .@"extern" => |e| e.owner_nav, + .func => |f| f.owner_nav, + else => orig_nav, + }; + if (ip.getNav(export_nav).getExtern(ip) != null) { + return sema.fail(block, src, "export target cannot be extern", .{}); } - if (zcu.llvm_object != null and options.linkage == .internal) return; - const export_ty = Value.fromInterned(uav.val).typeOf(zcu); - if (!export_ty.validateExtern(.other, zcu)) { - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(src, "unable to export type '{f}'", .{export_ty.fmt(pt)}); - errdefer msg.destroy(sema.gpa); - try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other); - try sema.addDeclaredHereNote(msg, export_ty); - break :msg msg; - }); - } - try sema.exports.append(zcu.gpa, .{ - .opts = options, - .src = src, - .exported = .{ .uav = uav.val }, - .status = .in_progress, - }); - }, - .nav => |nav| { - if (ptr_info.byte_offset != 0) { - return sema.fail(block, ptr_src, "TODO: export pointer in middle of value", .{}); - } - try sema.analyzeExport(block, src, options, nav); + try sema.maybeQueueFuncBodyAnalysis(block, src, export_nav); + break :target .{ .nav = export_nav }; }, + }; + if (ptr_info.byte_offset != 0) { + return sema.fail(block, ptr_src, "TODO: export pointer in middle of value", .{}); } + if (zcu.llvm_object != null and options.linkage == .internal) return; + try sema.exports.append(zcu.gpa, .{ + .opts = options, + .src = src, + .exported = target, + .status = .in_progress, + }); } -pub fn analyzeExport( +/// Asserts that `sema.owner` is a `.nav_val` whose value is resolved. +/// +/// Exports that `Nav` by the given name with all other options set to default. +pub fn analyzeExportSelfNav( sema: *Sema, block: *Block, src: LazySrcLoc, - options: Zcu.Export.Options, - orig_nav_index: InternPool.Nav.Index, + name: InternPool.NullTerminatedString, ) !void { const gpa = sema.gpa; const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; - if (zcu.llvm_object != null and options.linkage == .internal) - return; + const orig_nav = sema.owner.unwrap().nav_val; + const export_val: Value = .fromInterned(ip.getNav(orig_nav).status.fully_resolved.val); + const export_ty = export_val.typeOf(zcu); - try sema.ensureNavResolved(block, src, orig_nav_index, .fully); + if (!export_ty.validateExtern(.other, zcu)) { + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(src, "unable to export type '{f}'", .{export_ty.fmt(pt)}); + errdefer msg.destroy(gpa); + try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other); + try sema.addDeclaredHereNote(msg, export_ty); + break :msg msg; + }); + } - const exported_nav_index = switch (ip.indexToKey(ip.getNav(orig_nav_index).status.fully_resolved.val)) { + const export_nav = switch (ip.indexToKey(export_val.toIntern())) { .variable => |v| v.owner_nav, .@"extern" => |e| e.owner_nav, - .func => |f| f.owner_nav, - else => orig_nav_index, + .func => |f| export_nav: { + assert(export_ty.fnHasRuntimeBits(zcu)); // otherwise `validateExtern` failed above + const orig_fn_index = ip.unwrapCoercedFunc(export_val.toIntern()); + try sema.addReferenceEntry(block, src, .wrap(.{ .func = orig_fn_index })); + try zcu.ensureFuncBodyAnalysisQueued(orig_fn_index); + break :export_nav f.owner_nav; + }, + else => orig_nav, }; - const exported_nav = ip.getNav(exported_nav_index); - const export_ty: Type = .fromInterned(exported_nav.typeOf(ip)); - - if (!export_ty.validateExtern(.other, zcu)) { - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(src, "unable to export type '{f}'", .{export_ty.fmt(pt)}); - errdefer msg.destroy(gpa); - - try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other); - - try sema.addDeclaredHereNote(msg, export_ty); - break :msg msg; - }); - } - - // TODO: some backends might support re-exporting extern decls - if (exported_nav.getExtern(ip) != null) { - return sema.fail(block, src, "export target cannot be extern", .{}); - } - - try sema.maybeQueueFuncBodyAnalysis(block, src, exported_nav_index); - try sema.exports.append(gpa, .{ - .opts = options, + .opts = .{ .name = name }, .src = src, - .exported = .{ .nav = exported_nav_index }, + .exported = .{ .nav = export_nav }, .status = .in_progress, }); } @@ -33739,21 +33742,9 @@ pub fn flushExports(sema: *Sema) !void { const zcu = sema.pt.zcu; const gpa = zcu.gpa; - // There may be existing exports. For instance, a struct may export - // things during both field type resolution and field default resolution. - // - // So, pick up and delete any existing exports. This strategy performs - // redundant work, but that's okay, because this case is exceedingly rare. - // - // MLUGG TODO: is this still possible? if not, delete this logic and combine deleteUnitExports into resetUnit - if (zcu.single_exports.get(sema.owner)) |export_idx| { - try sema.exports.append(gpa, export_idx.ptr(zcu).*); - } else if (zcu.multi_exports.get(sema.owner)) |info| { - try sema.exports.appendSlice(gpa, zcu.all_exports.items[info.index..][0..info.len]); - } - zcu.deleteUnitExports(sema.owner); + assert(!zcu.single_exports.contains(sema.owner)); + assert(!zcu.multi_exports.contains(sema.owner)); - // `sema.exports` is completed; store the data into the `Zcu`. if (sema.exports.items.len == 1) { try zcu.single_exports.ensureUnusedCapacity(gpa, 1); const export_idx: Zcu.Export.Index = zcu.free_exports.pop() orelse idx: { @@ -34038,7 +34029,7 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.BuiltinDecl) CompileError!Typ }; } -fn setTypeName( +pub fn setTypeName( sema: *Sema, block: *Block, wip: *const InternPool.WipContainerType, diff --git a/src/Sema/LowerZon.zig b/src/Sema/LowerZon.zig index cf809603c03a177c4aefe40407b3b649a1921cff..06218806a44b24cf4433ed9b7738b27515a55154 100644 --- a/src/Sema/LowerZon.zig +++ b/src/Sema/LowerZon.zig @@ -125,89 +125,77 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter return (try pt.aggregateValue(.fromInterned(ty), values)).toIntern(); }, .struct_literal => |init| { - if (true) @panic("MLUGG TODO"); const elems = try self.sema.arena.alloc(InternPool.Index, init.names.len); for (0..init.names.len) |i| { elems[i] = try self.lowerExprAnonResTy(init.vals.at(@intCast(i))); } - const struct_ty = switch (try ip.getStructType( - gpa, - io, - pt.tid, - .{ - .layout = .auto, - .fields_len = @intCast(init.names.len), - .known_non_opv = false, - .requires_comptime = .no, - .any_comptime_fields = true, - .any_default_inits = true, - .inits_resolved = true, - .any_aligned_fields = false, - .key = .{ .reified = .{ - .zir_index = self.base_node_inst, - .type_hash = hash: { - var hasher: std.hash.Wyhash = .init(0); - hasher.update(std.mem.asBytes(&node)); - hasher.update(std.mem.sliceAsBytes(elems)); - hasher.update(std.mem.sliceAsBytes(init.names)); - break :hash hasher.final(); - }, - } }, + const struct_ty: Type = switch (try ip.getReifiedStructType(gpa, io, pt.tid, .{ + .zir_index = self.base_node_inst, + .type_hash = hash: { + var hasher: std.hash.Wyhash = .init(0); + hasher.update(std.mem.asBytes(&node)); + hasher.update(std.mem.sliceAsBytes(elems)); + hasher.update(std.mem.sliceAsBytes(init.names)); + break :hash hasher.final(); }, - false, - )) { + .fields_len = @intCast(init.names.len), + .layout = .auto, + .any_comptime_fields = true, + .any_field_defaults = true, + .any_field_aligns = false, + .packed_backing_int_type = .none, + })) { + .existing => |ty| .fromInterned(ty), .wip => |wip| ty: { errdefer wip.cancel(ip, pt.tid); - const type_name = try self.sema.createTypeName( - self.block, - .anon, - "struct", - self.base_node_inst.resolve(ip), - wip.index, - ); - wip.setName(ip, type_name.name, type_name.nav); + const block = self.block; + const zcu = pt.zcu; + try self.sema.setTypeName(block, &wip, .anon, "struct", self.base_node_inst.resolve(ip).?); - const struct_type = ip.loadStructType(wip.index); - - for (init.names, 0..) |name, field_idx| { - const name_interned = try ip.getOrPutString( + // Reified structs have field information populated immediately. + @memcpy(wip.field_values.get(ip), elems); + if (init.names.len > 0) { + // All fields are comptime, but unused bits remain zeroed. + const unused_bits = switch (init.names.len % 32) { + 0 => 0, + else => |n| 32 - n, + }; + const comptime_bits = wip.field_is_comptime_bits.getAll(ip); + @memset(comptime_bits[0 .. comptime_bits.len - 1], std.math.maxInt(u32)); + comptime_bits[comptime_bits.len - 1] = @as(u32, std.math.maxInt(u32)) >> @intCast(unused_bits); + } + for ( + init.names, + wip.field_names.get(ip), + wip.field_types.get(ip), + wip.field_values.get(ip), + ) |zoir_name, *field_name, *field_ty, field_val| { + field_name.* = try ip.getOrPutString( gpa, io, pt.tid, - name.get(self.file.zoir.?), + zoir_name.get(self.file.zoir.?), .no_embedded_nulls, ); - assert(struct_type.addFieldName(ip, name_interned) == null); - struct_type.setFieldComptime(ip, field_idx); - } - - @memcpy(struct_type.field_inits.get(ip), elems); - const types = struct_type.field_types.get(ip); - for (0..init.names.len) |i| { - types[i] = Value.fromInterned(elems[i]).typeOf(pt.zcu).toIntern(); + field_ty.* = ip.typeOf(field_val); } const new_namespace_index = try pt.createNamespace(.{ - .parent = self.block.namespace.toOptional(), + .parent = block.namespace.toOptional(), .owner_type = wip.index, - .file_scope = self.block.getFileScopeIndex(pt.zcu), - .generation = pt.zcu.generation, + .file_scope = block.getFileScopeIndex(zcu), + .generation = zcu.generation, }); - try pt.zcu.comp.queueJob(.{ .resolve_type_fully = wip.index }); - codegen_type: { - if (pt.zcu.comp.config.use_llvm) break :codegen_type; - if (self.block.ownerModule().strip) break :codegen_type; - pt.zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); - try pt.zcu.comp.queueJob(.{ .link_type = wip.index }); - } - break :ty wip.finish(ip, new_namespace_index); + errdefer pt.destroyNamespace(new_namespace_index); + if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index); + break :ty .fromInterned(wip.finish(ip, new_namespace_index)); }, - .existing => |ty| ty, }; - try self.sema.declareDependency(.{ .interned = struct_ty }); try self.sema.addTypeReferenceEntry(self.nodeSrc(node), struct_ty); + // No need for `ensureNamespaceUpToDate` because this type's namespace is always empty. + try self.sema.ensureLayoutResolved(struct_ty, self.nodeSrc(node), .init); - return (try pt.aggregateValue(.fromInterned(struct_ty), elems)).toIntern(); + return (try pt.aggregateValue(struct_ty, elems)).toIntern(); }, } } diff --git a/src/Value.zig b/src/Value.zig index 5cc20853da7634efc3b0925d77fa01ab65c1e9a7..cf8d0acc67377b3a871fe15cbd55cac4d0ef7221 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -1954,7 +1954,6 @@ pub const PointerDeriveStep = union(enum) { /// which prefer field/elem accesses when lowering constant pointer values. /// It is also used by the Value printing logic for pointers. pub fn pointerDerivation(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread, opt_sema: ?*Sema) Allocator.Error!PointerDeriveStep { - // MLUGG TODO: audit tf outta this code const zcu = pt.zcu; const ptr = zcu.intern_pool.indexToKey(ptr_val.toIntern()).ptr; const base_derive: PointerDeriveStep = switch (ptr.base_addr) { diff --git a/src/Zcu.zig b/src/Zcu.zig index 49abdbed5607582a4a33d40642edd762baaab5bb..ce90f2c417abc94c2b146c922f907c2b17a69e24 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -3518,50 +3518,10 @@ pub const ImportResult = struct { module: ?*Package.Module, }; -/// Delete all the Export objects that are caused by this `AnalUnit`. Re-analysis of -/// this `AnalUnit` will cause them to be re-created (or not). -pub fn deleteUnitExports(zcu: *Zcu, anal_unit: AnalUnit) void { - const gpa = zcu.gpa; - - const exports_base, const exports_len = if (zcu.single_exports.fetchSwapRemove(anal_unit)) |kv| - .{ @intFromEnum(kv.value), 1 } - else if (zcu.multi_exports.fetchSwapRemove(anal_unit)) |info| - .{ info.value.index, info.value.len } - else - return; - - const exports = zcu.all_exports.items[exports_base..][0..exports_len]; - - // In an only-c build, we're guaranteed to never use incremental compilation, so there are - // guaranteed not to be any exports in the output file that need deleting (since we only call - // `updateExports` on flush). - // This case is needed because in some rare edge cases, `Sema` wants to add and delete exports - // within a single update. - if (dev.env.supports(.incremental)) { - for (exports, exports_base..) |exp, export_index_usize| { - const export_idx: Export.Index = @enumFromInt(export_index_usize); - if (zcu.comp.bin_file) |lf| { - lf.deleteExport(exp.exported, exp.opts.name); - } - if (zcu.failed_exports.fetchSwapRemove(export_idx)) |failed_kv| { - failed_kv.value.destroy(gpa); - } - } - } - - zcu.free_exports.ensureUnusedCapacity(gpa, exports_len) catch { - // This space will be reused eventually, so we need not propagate this error. - // Just leak it for now, and let GC reclaim it later on. - return; - }; - for (exports_base..exports_base + exports_len) |export_idx| { - zcu.free_exports.appendAssumeCapacity(@enumFromInt(export_idx)); - } -} - /// Prepares `unit` for re-analysis by clearing all of the following state: /// * Compile errors associated with `unit` /// * Compile logs associated with `unit` +/// * Exports performed by `unit` /// * Dependencies from `unit` on other things /// * References from `unit` to other units /// Delete all references in `reference_table` which are caused by `unit`, and all dependencies it @@ -3593,6 +3553,36 @@ pub fn resetUnit(zcu: *Zcu, unit: AnalUnit) void { } } + // Exports + exports: { + const base: u32, const len: u32 = index: { + if (zcu.single_exports.fetchSwapRemove(unit)) |kv| { + break :index .{ @intFromEnum(kv.value), 1 }; + } + if (zcu.multi_exports.fetchSwapRemove(unit)) |kv| { + break :index .{ kv.value.index, kv.value.len }; + } + break :exports; + }; + for (zcu.all_exports.items[base..][0..len], base..) |exp, exp_index_usize| { + const exp_index: Export.Index = @enumFromInt(exp_index_usize); + if (zcu.comp.bin_file) |lf| { + lf.deleteExport(exp.exported, exp.opts.name); + } + if (zcu.failed_exports.fetchSwapRemove(exp_index)) |failed_kv| { + failed_kv.value.destroy(gpa); + } + } + zcu.free_exports.ensureUnusedCapacity(gpa, len) catch { + // This space will be reused eventually, so we need not propagate this error. + // Just leak it for now, and let GC reclaim it later on. + break :exports; + }; + for (base..base + len) |exp_index| { + zcu.free_exports.appendAssumeCapacity(@enumFromInt(exp_index)); + } + } + // Dependencies zcu.intern_pool.removeDependenciesForDepender(gpa, unit); diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 954d1cd3bff44529db52325785eb7aa7d1c1f0d2..b9ad8f3dfdd1375df0606f538d6ecdeb72abec82 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -752,7 +752,6 @@ pub fn ensureMemoizedStateUpToDate( if (was_outdated) { dev.check(.incremental); _ = zcu.outdated_ready.swapRemove(unit); - // No need for `deleteUnitExports` because we never export anything. zcu.resetUnit(unit); } else { if (prev_failed) return error.AnalysisFail; @@ -874,7 +873,6 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU _ = zcu.outdated_ready.swapRemove(anal_unit); // `was_outdated` can be true in the initial update for comptime units, so this isn't a `dev.check`. if (dev.env.supports(.incremental)) { - zcu.deleteUnitExports(anal_unit); zcu.resetUnit(anal_unit); } } else { @@ -1033,7 +1031,6 @@ pub fn ensureTypeLayoutUpToDate( _ = zcu.outdated_ready.swapRemove(anal_unit); // `was_outdated` is true in the initial update, so this isn't a `dev.check`. if (dev.env.supports(.incremental)) { - zcu.deleteUnitExports(anal_unit); zcu.resetUnit(anal_unit); } // For types, we already know that we have to invalidate all dependees. @@ -1151,7 +1148,6 @@ pub fn ensureNavValUpToDate( if (was_outdated) { dev.check(.incremental); _ = zcu.outdated_ready.swapRemove(anal_unit); - zcu.deleteUnitExports(anal_unit); zcu.resetUnit(anal_unit); } else { // We can trust the current information about this unit. @@ -1238,7 +1234,7 @@ fn analyzeNavVal( const zir_decl = zir.getDeclaration(inst_resolved.inst); try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, reason); - errdefer _ = zcu.analysis_in_progress.swapRemove(anal_unit); + defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); var analysis_arena: std.heap.ArenaAllocator = .init(gpa); defer analysis_arena.deinit(); @@ -1443,15 +1439,11 @@ fn analyzeNavVal( .@"addrspace" = modifiers.@"addrspace", }); - // Mark the unit as completed before evaluating the export! - // MLUGG TODO: do we really need to do this? - assert(zcu.analysis_in_progress.swapRemove(anal_unit)); - if (zir_decl.linkage == .@"export") { const export_src = block.src(.{ .token_offset = @enumFromInt(@intFromBool(zir_decl.is_pub)) }); const name_slice = zir.nullTerminatedString(zir_decl.name); const name_ip = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls); - try sema.analyzeExport(&block, export_src, .{ .name = name_ip }, nav_id); + try sema.analyzeExportSelfNav(&block, export_src, name_ip); } try sema.flushExports(); @@ -1514,7 +1506,6 @@ pub fn ensureNavTypeUpToDate( if (was_outdated) { dev.check(.incremental); _ = zcu.outdated_ready.swapRemove(anal_unit); - zcu.deleteUnitExports(anal_unit); zcu.resetUnit(anal_unit); } else { // We can trust the current information about this unit. @@ -1751,7 +1742,6 @@ pub fn ensureFuncBodyUpToDate( if (was_outdated) { dev.check(.incremental); _ = zcu.outdated_ready.swapRemove(anal_unit); - zcu.deleteUnitExports(anal_unit); zcu.resetUnit(anal_unit); } else { // We can trust the current information about this function. -- 2.54.0 From 4e92592fee6b414757b2e6c088e20ca9a1b21f44 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 8 Feb 2026 13:10:21 +0000 Subject: [PATCH 19/79] compiler: error set bugfixes --- src/Sema.zig | 117 ++++++++++++++++++++++++++++++++++++++------------- src/Type.zig | 63 +++++++++++++++------------ 2 files changed, 124 insertions(+), 56 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 0504bb7e5e251d656e2daf1f0e016d098a80e520..b0271ffde091e2cfe9c5b442d244e15ae76b020b 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -15629,10 +15629,10 @@ fn zirCmpEq( // comparing null with optionals if (lhs_ty_tag == .null and (rhs_ty_tag == .optional or rhs_ty.isCPtr(zcu))) { - return sema.analyzeIsNull(block, rhs, op == .neq); + return sema.analyzeIsNull(block, src, rhs, op == .neq); } if (rhs_ty_tag == .null and (lhs_ty_tag == .optional or lhs_ty.isCPtr(zcu))) { - return sema.analyzeIsNull(block, lhs, op == .neq); + return sema.analyzeIsNull(block, src, lhs, op == .neq); } if (lhs_ty_tag == .null or rhs_ty_tag == .null) { @@ -17375,7 +17375,7 @@ fn zirIsNonNull( const src = block.nodeOffset(inst_data.src_node); const operand = sema.resolveInst(inst_data.operand); try sema.checkNullableType(block, src, sema.typeOf(operand)); - return sema.analyzeIsNull(block, operand, true); + return sema.analyzeIsNull(block, src, operand, true); } fn zirIsNonNullPtr( @@ -17394,15 +17394,19 @@ fn zirIsNonNullPtr( const ptr_ty = sema.typeOf(ptr); assert(ptr_ty.zigTypeTag(zcu) == .pointer); const nullable_ty = ptr_ty.childType(zcu); + try sema.checkNullableType(block, src, nullable_ty); + + if (try sema.resolveIsNullFromType(block, src, nullable_ty)) |is_null| { + return .fromValue(.makeBool(!is_null)); + } + if (sema.resolveValue(ptr)) |ptr_val| { if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |nullable_val| { - return sema.analyzeIsNull(block, .fromValue(nullable_val), true); + return sema.analyzeIsNull(block, src, .fromValue(nullable_val), true); } } - if (nullable_ty.isNullFromType(zcu)) |is_null| { - return if (is_null) .bool_false else .bool_true; - } + return block.addUnOp(.is_non_null_ptr, ptr); } @@ -30147,25 +30151,25 @@ fn analyzeSliceLen( fn analyzeIsNull( sema: *Sema, block: *Block, + src: LazySrcLoc, operand: Air.Inst.Ref, invert_logic: bool, ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - const result_ty: Type = .bool; + + if (try sema.resolveIsNullFromType(block, src, sema.typeOf(operand))) |is_null| { + return .fromValue(.makeBool(is_null != invert_logic)); // XOR + } + if (sema.resolveValue(operand)) |opt_val| { if (opt_val.isUndef(zcu)) { - return pt.undefRef(result_ty); + return pt.undefRef(.bool); } const is_null = opt_val.isNull(zcu); - const bool_value = if (invert_logic) !is_null else is_null; - return if (bool_value) .bool_true else .bool_false; + return .fromValue(.makeBool(is_null != invert_logic)); // XOR } - if (sema.typeOf(operand).isNullFromType(zcu)) |is_null| { - const result = is_null != invert_logic; - return if (result) .bool_true else .bool_false; - } const air_tag: Air.Inst.Tag = if (invert_logic) .is_non_null else .is_null; return block.addUnOp(air_tag, operand); } @@ -30218,6 +30222,35 @@ fn resolveIsNonErrVal( return null; } +fn resolveIsNullFromType( + sema: *Sema, + block: *Block, + src: LazySrcLoc, + ty: Type, +) CompileError!?bool { + const zcu = sema.pt.zcu; + return switch (ty.zigTypeTag(zcu)) { + else => false, + .null => true, + .pointer => switch (ty.ptrSize(zcu)) { + .c => null, + else => false, + }, + .optional => { + const payload_ty = ty.optionalChild(zcu); + if (payload_ty.classify(zcu) == .no_possible_value) { + return true; // e.g. `?noreturn` + } + if (payload_ty.zigTypeTag(zcu) == .error_set and + try sema.resolveErrSetIsEmpty(block, src, payload_ty)) + { + return true; // e.g. `?error{}` + } + return null; + }, + }; +} + fn resolveIsNonErrFromType( sema: *Sema, block: *Block, @@ -30226,7 +30259,6 @@ fn resolveIsNonErrFromType( ) CompileError!?Value { const pt = sema.pt; const zcu = pt.zcu; - const ip = &zcu.intern_pool; const ot = operand_ty.zigTypeTag(zcu); if (ot != .error_set and ot != .error_union) return .true; if (ot == .error_set) return .false; @@ -30236,29 +30268,54 @@ fn resolveIsNonErrFromType( if (payload_ty.classify(zcu) == .no_possible_value) { return .false; } + if (try sema.resolveErrSetIsEmpty(block, src, operand_ty.errorUnionSet(zcu))) { + return .true; + } + return null; +} - // exception if the error union error set is known to be empty, - // we allow the comparison but always make it comptime-known. - return err_set: switch (ip.errorUnionSet(operand_ty.toIntern())) { - .anyerror_type => null, +/// Returns `true` iff the error set type `orig_err_set_ty` contains no errors. +/// +/// This is used to give comptime answers for whether `error{}!T` is an error or a payload, as well +/// as whether `?error{}` is null. The type `error{}` cannot be NPV, as it has runtime bits, but the +/// only value of that type which can exist is `undefined`; semantically it has no "legal" value. +/// TODO: this runs into some unsolved language design questions about such types. Performing a +/// coercion from `@as(E, undefined)` to `E!T` needs to semantically result in an `undefined` error +/// union if our implementation is to be legal, and likewise for coercing `@as(E, undefined)` to +/// `?E` (for an error set `E`) because our implementation uses the zero error value at runtime to +/// represent `null`. The unsolved problem is the exact rules for `undefined` propagation through +/// these types: for instance, what if `@as(u32, undfined)` is coerced to `?u32`? What about error +/// union *payloads*, i.e. `@as(u32, undefined)` to `E!u32`? That one is analagous to the optional +/// example in some ways, but right now I believe there is code which relies on that coercion giving +/// a well-defined error union with an `undefined` payload. +/// Relevant issues/discussions: +/// * https://github.com/ziglang/zig/issues/1831 +/// * https://github.com/ziglang/zig/issues/6762 +/// * https://github.com/ziglang/zig/issues/1831#issuecomment-722129239 +fn resolveErrSetIsEmpty( + sema: *Sema, + block: *Block, + src: LazySrcLoc, + orig_err_set_ty: Type, +) CompileError!bool { + const ip = &sema.pt.zcu.intern_pool; + err_set: switch (orig_err_set_ty.toIntern()) { + .anyerror_type => return false, .adhoc_inferred_error_set_type => { // This is *our* error set; that is, we're currently analyzing the function // which owns it. Trying to resolve it now would cause a dependency loop. // Instead, accept that we don't know. - return null; + return false; }, - else => |set_ty| switch (ip.indexToKey(set_ty)) { - .error_set_type => |error_set_type| switch (error_set_type.names.len) { - 0 => .true, - else => null, - }, + else => |err_set_ty| switch (ip.indexToKey(err_set_ty)) { + .error_set_type => |es| return es.names.len == 0, .inferred_error_set_type => |func_index| { if (sema.fn_ret_ty_ies) |ies| { if (ies.func == func_index) { // This is *our* error set; that is, we're currently analyzing the function // which owns it. Trying to resolve it now would cause a dependency loop. // Instead, accept that we don't know. - return null; + return false; } } try sema.ensureFuncIesResolved(block, src, func_index); @@ -30266,7 +30323,7 @@ fn resolveIsNonErrFromType( }, else => unreachable, }, - }; + } } fn analyzeIsNonErr( @@ -30732,7 +30789,7 @@ fn analyzeSlice( if (block.wantSafety()) { // requirement: slicing C ptr is non-null if (ptr_ptr_child_ty.isCPtr(zcu)) { - const is_non_null = try sema.analyzeIsNull(block, ptr, true); + const is_non_null = try block.addUnOp(.is_non_null, ptr); try sema.addSafetyCheck(block, src, is_non_null, .unwrap_null); } @@ -30792,7 +30849,7 @@ fn analyzeSlice( if (block.wantSafety()) { // requirement: slicing C ptr is non-null if (ptr_ptr_child_ty.isCPtr(zcu)) { - const is_non_null = try sema.analyzeIsNull(block, ptr, true); + const is_non_null = try block.addUnOp(.is_non_null, ptr); try sema.addSafetyCheck(block, src, is_non_null, .unwrap_null); } diff --git a/src/Type.zig b/src/Type.zig index 81ee1e560e6505eb6721b13b6fbdd2338e1694e0..3eb14f3b533c2fe9f2e30e312b473e9b4719b6f4 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -661,15 +661,28 @@ pub fn toValue(self: Type) Value { return .fromInterned(self.toIntern()); } -/// true if and only if the type takes up space in memory at runtime. -/// There are two reasons a type will return false: -/// * the type is a comptime-only type. For example, the type `type` itself. -/// - note, however, that a struct can have mixed fields and only the non-comptime-only -/// fields will count towards the ABI size. For example, `struct {T: type, x: i32}` -/// hasRuntimeBits()=true and abiSize()=4 -/// * the type has only one possible value, making its ABI size 0. -/// - an enum with an explicit tag type has the ABI size of the integer tag type, -/// making it one-possible-value only if the integer tag type has 0 bits. +/// Returns `true` if and only if the type takes up space in memory at runtime. This is also exactly +/// whether or not the backend/linker needs to be sent values of this type to emit to the binary. +/// +/// Types without runtime bits have an ABI size of 0; all other types have a non-zero ABI size. All +/// types, regardless of whether they have runtime bits, have a non-zero ABI alignment. +/// +/// Comptime-only types may still have runtime bits. For instance, `struct { a: u32, b: type }` is a +/// comptime-only type, but it nonetheless has runtime bits and a runtime memory layout (where the +/// field `b: type` is omitted). This is because a user may take a pointer to the field `a`, which +/// must then be valid to use at runtime. +/// +/// This function is a trivial wrapper around `classify`: +/// +/// * Types with one possible value, such as `void`, or no possible value, such as `noreturn`, do +/// not have runtime bits and have an ABI size of 0 because they simply contain no state. +/// +/// * Types which are fully comptime, such as `type` and `comptime_int`, do not have runtime bits +/// because they contain only comptime state. (This compiler implementation also currently makes +/// types like `struct { x: comptime_int }` fully comptime, but that could change in the future if +/// we start inserting hidden safety fields into them.) +/// +/// * All other types contain some runtime state, so have runtime bits and a non-zero ABI size. pub fn hasRuntimeBits(ty: Type, zcu: *const Zcu) bool { return switch (ty.classify(zcu)) { .no_possible_value, .one_possible_value, .fully_comptime => false, @@ -1576,6 +1589,11 @@ pub fn errorUnionSet(ty: Type, zcu: *const Zcu) Type { } /// Returns false for unresolved inferred error sets. +/// +/// TODO: this function will behave incorrectly under incremental compilation, because in that case +/// it may see an outdated resolved error set. This function must be either deleted, or its contract +/// changed to require the caller to resolve the error set beforehand. If you must introduce new +/// call sites, please make sure the error set in question is definitely resolved first! pub fn errorSetIsEmpty(ty: Type, zcu: *const Zcu) bool { const ip = &zcu.intern_pool; return switch (ty.toIntern()) { @@ -1594,6 +1612,11 @@ pub fn errorSetIsEmpty(ty: Type, zcu: *const Zcu) bool { /// Returns true if it is an error set that includes anyerror, false otherwise. /// Note that the result may be a false negative if the type did not get error set /// resolution prior to this call. +/// +/// TODO: this function will behave incorrectly under incremental compilation, because in that case +/// it may see an outdated resolved error set. This function must be either deleted, or its contract +/// changed to require the caller to resolve the error set beforehand. If you must introduce new +/// call sites, please make sure the error set in question is definitely resolved first! pub fn isAnyError(ty: Type, zcu: *const Zcu) bool { const ip = &zcu.intern_pool; return switch (ty.toIntern()) { @@ -1616,6 +1639,11 @@ pub fn isError(ty: Type, zcu: *const Zcu) bool { /// Returns whether ty, which must be an error set, includes an error `name`. /// Might return a false negative if `ty` is an inferred error set and not fully /// resolved yet. +/// +/// TODO: this function will behave incorrectly under incremental compilation, because in that case +/// it may see an outdated resolved error set. This function must be either deleted, or its contract +/// changed to require the caller to resolve the error set beforehand. If you must introduce new +/// call sites, please make sure the error set in question is definitely resolved first! pub fn errorSetHasField( ty: Type, name: InternPool.NullTerminatedString, @@ -2939,23 +2967,6 @@ pub fn containerTypeName(ty: Type, ip: *const InternPool) InternPool.NullTermina }; } -/// Returns `true` if a value of this type is always `null`. -/// Returns `false` if a value of this type is never `null`. -/// Returns `null` otherwise. -pub fn isNullFromType(ty: Type, zcu: *const Zcu) ?bool { - if (ty.zigTypeTag(zcu) != .optional and !ty.isCPtr(zcu)) return false; - const payload_ty = ty.optionalChild(zcu); - if (payload_ty.classify(zcu) == .no_possible_value) return true; // `?noreturn` etc - - // Although it has runtime bits, `?error{}` is always null. MLUGG TODO: think for a bit... - switch (zcu.intern_pool.indexToKey(payload_ty.toIntern())) { - .error_set_type => |error_set| if (error_set.names.len == 0) return true, - else => {}, - } - - return null; -} - pub const UnpackableReason = union(enum) { comptime_only, pointer, -- 2.54.0 From 96d6b22067cccd644190e9b63f8f5bc13b6e93db Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 8 Feb 2026 13:24:03 +0000 Subject: [PATCH 20/79] tests: update for accepted language change 'comptime_int' is no longer considered a valid backing type for an enum. In other words, 'enum(comptime_int)' is a compile error. This change is accepted to simplify the language. --- test/behavior/enum.zig | 16 --------- test/behavior/union.zig | 35 +++++++------------ .../enum_backed_by_comptime_int.zig | 8 +++++ ...int_must_be_casted_from_comptime_value.zig | 12 ------- ...acked_by_comptime_int_must_be_comptime.zig | 9 ----- ..._backed_by_enum_backed_by_comptime_int.zig | 9 +++++ 6 files changed, 29 insertions(+), 60 deletions(-) create mode 100644 test/cases/compile_errors/enum_backed_by_comptime_int.zig delete mode 100644 test/cases/compile_errors/enum_backed_by_comptime_int_must_be_casted_from_comptime_value.zig delete mode 100644 test/cases/compile_errors/enum_backed_by_comptime_int_must_be_comptime.zig create mode 100644 test/cases/compile_errors/union_backed_by_enum_backed_by_comptime_int.zig diff --git a/test/behavior/enum.zig b/test/behavior/enum.zig index d49b27d4d41841bc40b5b8bd61fff45ebc709942..a222bd605143b3de2ca5ca9f1c4f93d3760c3173 100644 --- a/test/behavior/enum.zig +++ b/test/behavior/enum.zig @@ -823,15 +823,6 @@ test "enum with one member and u1 tag type @intFromEnum" { try expect(@intFromEnum(Enum.Test) == 0); } -test "enum with comptime_int tag type" { - const Enum = enum(comptime_int) { - One = 3, - Two = 2, - Three = 1, - }; - comptime assert(Tag(Enum) == comptime_int); -} - test "enum with one member default to u0 tag type" { const E0 = enum { X }; comptime assert(Tag(E0) == u0); @@ -1274,13 +1265,6 @@ fn getLazyInitialized(param: enum(u8) { return @intFromEnum(param); } -test "Non-exhaustive enum backed by comptime_int" { - const E = enum(comptime_int) { a, b, c, _ }; - comptime var e: E = .a; - e = @as(E, @enumFromInt(378089457309184723749)); - try expect(@intFromEnum(e) == 378089457309184723749); -} - test "matching captures causes enum equivalence" { const S = struct { fn Nonexhaustive(comptime I: type) type { diff --git a/test/behavior/union.zig b/test/behavior/union.zig index a9e950a255cc6036e75e6d6df584756b537b0ac9..a7b7c20a361d192a034363cc64a06ecc1f2b572a 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -703,25 +703,23 @@ test "union with only 1 field casted to its enum type which has enum value speci if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const Literal = union(enum) { - Number: f64, - Bool: bool, + number: f64, + bool: bool, }; - const ExprTag = enum(comptime_int) { - Literal = 33, - }; + const ExprTag = enum(u32) { literal = 33 }; + const Expr = union(ExprTag) { literal: Literal }; - const Expr = union(ExprTag) { - Literal: Literal, - }; + comptime assert(Tag(ExprTag) == u32); + + var e: Expr = undefined; + e = .{ .literal = .{ .bool = true } }; - var e = Expr{ .Literal = Literal{ .Bool = true } }; - _ = &e; - comptime assert(Tag(ExprTag) == comptime_int); - const t = comptime @as(ExprTag, e); - try expect(t == Expr.Literal); - try expect(@intFromEnum(t) == 33); + const t: ExprTag = e; + comptime assert(t == Expr.literal); comptime assert(@intFromEnum(t) == 33); + try expect(t == Expr.literal); + try expect(@intFromEnum(t) == 33); } test "@intFromEnum works on unions" { @@ -893,15 +891,6 @@ test "union no tag with struct member" { u.foo(); } -test "union with comptime_int tag" { - const Union = union(enum(comptime_int)) { - X: u32, - Y: u16, - Z: u8, - }; - comptime assert(Tag(Tag(Union)) == comptime_int); -} - test "extern union doesn't trigger field check at comptime" { const U = extern union { x: u32, diff --git a/test/cases/compile_errors/enum_backed_by_comptime_int.zig b/test/cases/compile_errors/enum_backed_by_comptime_int.zig new file mode 100644 index 0000000000000000000000000000000000000000..069e36ecc4b6d321fd5f621e8875199b389be711 --- /dev/null +++ b/test/cases/compile_errors/enum_backed_by_comptime_int.zig @@ -0,0 +1,8 @@ +const E = enum(comptime_int) { a }; +comptime { + _ = E.a; +} + +// error +// +// :1:16: error: expected integer tag type, found 'comptime_int' diff --git a/test/cases/compile_errors/enum_backed_by_comptime_int_must_be_casted_from_comptime_value.zig b/test/cases/compile_errors/enum_backed_by_comptime_int_must_be_casted_from_comptime_value.zig deleted file mode 100644 index a4ce1680ffd32acf2e0edde87dab93378099f57a..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/enum_backed_by_comptime_int_must_be_casted_from_comptime_value.zig +++ /dev/null @@ -1,12 +0,0 @@ -export fn entry() void { - const Tag = enum(comptime_int) { a, b }; - - var v: u32 = 0; - _ = &v; - _ = @as(Tag, @enumFromInt(v)); -} - -// error -// -// :6:31: error: unable to resolve comptime value -// :6:31: note: value casted to enum with 'comptime_int' tag type must be comptime-known diff --git a/test/cases/compile_errors/enum_backed_by_comptime_int_must_be_comptime.zig b/test/cases/compile_errors/enum_backed_by_comptime_int_must_be_comptime.zig deleted file mode 100644 index 6f55e8c2779e5312647910553e4ffbadb8454c3c..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/enum_backed_by_comptime_int_must_be_comptime.zig +++ /dev/null @@ -1,9 +0,0 @@ -pub export fn entry() void { - const E = enum(comptime_int) { a, b, c, _ }; - var e: E = .a; - _ = &e; -} - -// error -// -// :3:12: error: variable of type 'tmp.entry.E' must be const or comptime diff --git a/test/cases/compile_errors/union_backed_by_enum_backed_by_comptime_int.zig b/test/cases/compile_errors/union_backed_by_enum_backed_by_comptime_int.zig new file mode 100644 index 0000000000000000000000000000000000000000..7217c65b59f2d96922705af883ccb0623aea98e0 --- /dev/null +++ b/test/cases/compile_errors/union_backed_by_enum_backed_by_comptime_int.zig @@ -0,0 +1,9 @@ +const U = union(enum(comptime_int)) { a: u32 }; +comptime { + const u: U = .{ .a = 123 }; + _ = u; +} + +// error +// +// :1:22: error: expected integer tag type, found 'comptime_int' -- 2.54.0 From 5c41b6db87702017791b824ec9d76d5da00c354b Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 8 Feb 2026 13:56:01 +0000 Subject: [PATCH 21/79] Sema: disallow empty extern/packed unions These types don't really make much sense: you can't pack together bits of a type which cannot exist, nor can you pass it over an ABI boundary. --- src/Sema/type_resolution.zig | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig index 07349457a44ee78f7435e9609833b9e588bf1248..adc787136f93d6e69cce6464926369def5de3388 100644 --- a/src/Sema/type_resolution.zig +++ b/src/Sema/type_resolution.zig @@ -347,6 +347,12 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { } }; + switch (struct_obj.layout) { + .auto => {}, + .@"extern" => assert(class != .no_possible_value), // field types are all extern, so are not NPV + .@"packed" => unreachable, + } + if (struct_obj.layout == .auto) { const runtime_order = struct_obj.field_runtime_order.get(ip); // This logic does not reorder fields; it only moves the omitted ones to the end so that logic @@ -451,7 +457,12 @@ fn resolvePackedStructLayout( try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; }); - assert(!field_ty.comptimeOnly(zcu)); // packable types are not comptime-only + switch (field_ty.classify(zcu)) { + .one_possible_value, .runtime => {}, + .no_possible_value => unreachable, // packable types are not NPV + .partially_comptime => unreachable, // packable types are not comptime-only + .fully_comptime => unreachable, // packable types are not comptime-only + } field_bits += field_ty.bitSize(zcu); } @@ -749,6 +760,13 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { } } + // Uninstantiable `extern union`s don't make sense; disallow them. + if (possible_tags == 0 and union_obj.layout != .auto) { + // Field types are all extern, so not NPV; thus zero possible tags means no tags at all. + assert(union_obj.field_types.len == 0); + return sema.fail(&block, union_ty.srcLoc(zcu), "extern union has no fields", .{}); + } + // We only need a runtime tag if there are multiple possible active fields *and* the union is // not going to be comptime-only. Even if there are still runtime bits in the payload, the tag // does not require runtime bits in a comptime-only union, because it is impossible to get a @@ -874,6 +892,11 @@ fn resolvePackedUnionLayout( const gpa = comp.gpa; const ip = &zcu.intern_pool; + // Uninstantiable `packed union`s don't make sense; disallow them. + if (union_obj.field_types.len == 0) { + return sema.fail(block, union_ty.srcLoc(zcu), "packed union has no fields", .{}); + } + // Resolve the layout of all fields, and check their types are allowed. for (union_obj.field_types.get(ip), 0..) |field_ty_ip, field_index| { const field_ty: Type = .fromInterned(field_ty_ip); @@ -937,9 +960,6 @@ fn resolvePackedUnionLayout( }); } break :ty backing_ty; - } else if (union_obj.field_types.len == 0) ty: { - // Special case: there is no first field to infer the type from. Treat the union as empty (zero-bit). - break :ty .u0; } else ty: { const field_types = union_obj.field_types.get(ip); const first_field_type: Type = .fromInterned(field_types[0]); -- 2.54.0 From ffc5242169d67840e0d1420b792696fc1b3d1722 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 8 Feb 2026 14:04:51 +0000 Subject: [PATCH 22/79] Sema: small NPV fixes --- src/Sema.zig | 12 +----------- src/Type.zig | 24 +++++++++++++++++++++--- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index b0271ffde091e2cfe9c5b442d244e15ae76b020b..140e69fe6ffe1e3e16e4cf6176a8ff48bf89000d 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -19400,7 +19400,7 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const ty = try sema.resolveType(block, operand_src, inst_data.operand); try sema.ensureLayoutResolved(ty, operand_src, .align_of); if (ty.isNoReturn(zcu)) { - return sema.fail(block, operand_src, "no align available for type '{f}'", .{ty.fmt(sema.pt)}); + return sema.fail(block, operand_src, "no align available for uninstantiable type '{f}'", .{ty.fmt(sema.pt)}); } return .fromValue(try pt.intValue(.comptime_int, ty.abiAlignment(zcu).toByteUnits().?)); } @@ -33432,16 +33432,6 @@ fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type { return pt.errorSetFromUnsortedNames(names.keys()); } -/// Avoids crashing the compiler when asking if inferred allocations are noreturn. -fn isNoReturn(sema: *Sema, ref: Air.Inst.Ref) bool { - if (ref == .unreachable_value) return true; - if (ref.toIndex()) |inst| switch (sema.air_instructions.items(.tag)[@intFromEnum(inst)]) { - .inferred_alloc, .inferred_alloc_comptime => return false, - else => {}, - }; - return sema.typeOf(ref).isNoReturn(sema.pt.zcu); -} - pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void { const pt = sema.pt; if (!pt.zcu.comp.config.incremental) return; diff --git a/src/Type.zig b/src/Type.zig index 3eb14f3b533c2fe9f2e30e312b473e9b4719b6f4..234850376558acefd34b85a0ed43285945c6f60d 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -790,11 +790,21 @@ pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool { /// function with this type can exist at runtime. /// Asserts that `ty` is a function type. pub fn fnHasRuntimeBits(fn_ty: Type, zcu: *Zcu) bool { + assertHasLayout(fn_ty, zcu); const fn_info = zcu.typeToFunc(fn_ty).?; if (fn_info.comptime_bits != 0) return false; for (fn_info.param_types.get(&zcu.intern_pool)) |param_ty| { if (param_ty == .generic_poison_type) return false; - if (Type.fromInterned(param_ty).comptimeOnly(zcu)) return false; + switch (Type.fromInterned(param_ty).classify(zcu)) { + .fully_comptime, + .partially_comptime, + .no_possible_value, + => return false, + + .one_possible_value, + .runtime, + => {}, + } } const ret_ty: Type = .fromInterned(fn_info.return_type); if (ret_ty.toIntern() == .generic_poison_type) { @@ -805,8 +815,16 @@ pub fn fnHasRuntimeBits(fn_ty: Type, zcu: *Zcu) bool { { return false; } - if (fn_info.return_type == .generic_poison_type) return false; - if (Type.fromInterned(fn_info.return_type).comptimeOnly(zcu)) return false; + switch (ret_ty.classify(zcu)) { + .fully_comptime, + .partially_comptime, + => return false, + + .no_possible_value, + .one_possible_value, + .runtime, + => {}, + } if (fn_info.cc == .@"inline") return false; return true; } -- 2.54.0 From 4f7344dec0bc61916f0c9af99bc5b5e5b7167da3 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 8 Feb 2026 14:11:09 +0000 Subject: [PATCH 23/79] tests: update for accepted language change Unions with no fields are now "uninstantiable" types, which work like `noreturn` in that values of this type cannot exist. Enums with no fields are different because they are currently considered `extern` types, though https://github.com/ziglang/zig/issues/19855 will change this in the future. --- test/behavior.zig | 1 - test/behavior/empty_union.zig | 66 --------------- test/behavior/enum.zig | 23 ++++++ .../compile_errors/empty_extern_union.zig | 8 ++ .../compile_errors/empty_packed_union.zig | 8 ++ .../compile_errors/initialize_empty_union.zig | 81 +++++++++++++++++++ .../sizeof_alignof_empty_union.zig | 75 +++++++++++++++++ 7 files changed, 195 insertions(+), 67 deletions(-) delete mode 100644 test/behavior/empty_union.zig create mode 100644 test/cases/compile_errors/empty_extern_union.zig create mode 100644 test/cases/compile_errors/empty_packed_union.zig create mode 100644 test/cases/compile_errors/initialize_empty_union.zig create mode 100644 test/cases/compile_errors/sizeof_alignof_empty_union.zig diff --git a/test/behavior.zig b/test/behavior.zig index e4153c91bbea3721f79807393053f87c22f4ac52..c9c06e934230692c95d07b96d911fb09a80d3bdf 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -24,7 +24,6 @@ test { _ = @import("behavior/duplicated_test_names.zig"); _ = @import("behavior/defer.zig"); _ = @import("behavior/destructure.zig"); - _ = @import("behavior/empty_union.zig"); _ = @import("behavior/enum.zig"); _ = @import("behavior/error.zig"); _ = @import("behavior/eval.zig"); diff --git a/test/behavior/empty_union.zig b/test/behavior/empty_union.zig deleted file mode 100644 index f05feacfafd7e429ff01aa3c65e376acaba63441..0000000000000000000000000000000000000000 --- a/test/behavior/empty_union.zig +++ /dev/null @@ -1,66 +0,0 @@ -const builtin = @import("builtin"); -const std = @import("std"); -const expect = std.testing.expect; - -test "switch on empty enum" { - const E = enum {}; - var e: E = undefined; - _ = &e; - switch (e) {} -} - -test "switch on empty enum with a specified tag type" { - const E = enum(u8) {}; - var e: E = undefined; - _ = &e; - switch (e) {} -} - -test "switch on empty auto numbered tagged union" { - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - - const U = union(enum(u8)) {}; - var u: U = undefined; - _ = &u; - switch (u) {} -} - -test "switch on empty tagged union" { - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - - const E = enum {}; - const U = union(E) {}; - var u: U = undefined; - _ = &u; - switch (u) {} -} - -test "empty union" { - const U = union {}; - try expect(@sizeOf(U) == 0); - try expect(@alignOf(U) == 1); -} - -test "empty extern union" { - const U = extern union {}; - try expect(@sizeOf(U) == 0); - try expect(@alignOf(U) == 1); -} - -test "empty union passed as argument" { - const U = union(enum) { - fn f(u: @This()) void { - switch (u) {} - } - }; - U.f(@as(U, undefined)); -} - -test "empty enum passed as argument" { - const E = enum { - fn f(e: @This()) void { - switch (e) {} - } - }; - E.f(@as(E, undefined)); -} diff --git a/test/behavior/enum.zig b/test/behavior/enum.zig index a222bd605143b3de2ca5ca9f1c4f93d3760c3173..4dd5ae08da6e0bf73f81b148ae060c99b7ca2be2 100644 --- a/test/behavior/enum.zig +++ b/test/behavior/enum.zig @@ -1331,3 +1331,26 @@ test "comptime @enumFromInt with signed arithmetic" { comptime assert(x == .bar); comptime assert(@intFromEnum(x) == 0); } + +test "switch on empty enum" { + const E = enum {}; + var e: E = undefined; + _ = &e; + switch (e) {} +} + +test "switch on empty enum with a specified tag type" { + const E = enum(u8) {}; + var e: E = undefined; + _ = &e; + switch (e) {} +} + +test "empty enum passed as argument" { + const E = enum { + fn f(e: @This()) void { + switch (e) {} + } + }; + E.f(@as(E, undefined)); +} diff --git a/test/cases/compile_errors/empty_extern_union.zig b/test/cases/compile_errors/empty_extern_union.zig new file mode 100644 index 0000000000000000000000000000000000000000..44d6269617ec06c17a97a544085070af52fa1e9d --- /dev/null +++ b/test/cases/compile_errors/empty_extern_union.zig @@ -0,0 +1,8 @@ +export fn foo() void { + const U = extern union {}; + _ = @as(U, undefined); +} + +// error +// +// :2:22: error: extern union has no fields diff --git a/test/cases/compile_errors/empty_packed_union.zig b/test/cases/compile_errors/empty_packed_union.zig new file mode 100644 index 0000000000000000000000000000000000000000..87209670974eb706dd1385ba8e427944b5209278 --- /dev/null +++ b/test/cases/compile_errors/empty_packed_union.zig @@ -0,0 +1,8 @@ +export fn foo() void { + const U = packed union {}; + _ = @as(U, undefined); +} + +// error +// +// :2:22: error: packed union has no fields diff --git a/test/cases/compile_errors/initialize_empty_union.zig b/test/cases/compile_errors/initialize_empty_union.zig new file mode 100644 index 0000000000000000000000000000000000000000..c84633da268c5f4e885ffa33a993cb0d3eeeecf5 --- /dev/null +++ b/test/cases/compile_errors/initialize_empty_union.zig @@ -0,0 +1,81 @@ +const EnumInferred = enum {}; +const EnumExplicit = enum(u8) {}; +const EnumNonexhaustive = enum(u8) { _ }; + +const U0 = union {}; +const U1 = union(enum) {}; +const U2 = union(enum(u8)) {}; +const U3 = union(EnumInferred) {}; +const U4 = union(EnumExplicit) {}; +const U5 = union(EnumNonexhaustive) {}; + +export fn init0() void { + _ = @as(U0, undefined); +} +export fn init1() void { + _ = @as(U1, undefined); +} +export fn init2() void { + _ = @as(U2, undefined); +} +export fn init3() void { + _ = @as(U3, undefined); +} +export fn init4() void { + _ = @as(U4, undefined); +} +export fn init5() void { + _ = @as(U5, undefined); +} + +export fn deref0(ptr: *const U0) void { + _ = ptr.*; +} +export fn deref1(ptr: *const U1) void { + _ = ptr.*; +} +export fn deref2(ptr: *const U2) void { + _ = ptr.*; +} +export fn deref3(ptr: *const U3) void { + _ = ptr.*; +} +export fn deref4(ptr: *const U4) void { + _ = ptr.*; +} +export fn deref5(ptr: *const U5) void { + _ = ptr.*; +} + +// error +// +// :13:17: error: expected type 'initialize_empty_union.U0', found '@TypeOf(undefined)' +// :13:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U0' +// :5:12: note: union declared here +// :16:17: error: expected type 'initialize_empty_union.U1', found '@TypeOf(undefined)' +// :16:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U1' +// :6:12: note: union declared here +// :19:17: error: expected type 'initialize_empty_union.U2', found '@TypeOf(undefined)' +// :19:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U2' +// :7:12: note: union declared here +// :22:17: error: expected type 'initialize_empty_union.U3', found '@TypeOf(undefined)' +// :22:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U3' +// :8:12: note: union declared here +// :25:17: error: expected type 'initialize_empty_union.U4', found '@TypeOf(undefined)' +// :25:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U4' +// :9:12: note: union declared here +// :28:17: error: expected type 'initialize_empty_union.U5', found '@TypeOf(undefined)' +// :28:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U5' +// :10:12: note: union declared here +// :32:12: error: cannot load uninstantiable type 'initialize_empty_union.U0' +// :5:12: note: union declared here +// :35:12: error: cannot load uninstantiable type 'initialize_empty_union.U1' +// :6:12: note: union declared here +// :38:12: error: cannot load uninstantiable type 'initialize_empty_union.U2' +// :7:12: note: union declared here +// :41:12: error: cannot load uninstantiable type 'initialize_empty_union.U3' +// :8:12: note: union declared here +// :44:12: error: cannot load uninstantiable type 'initialize_empty_union.U4' +// :9:12: note: union declared here +// :47:12: error: cannot load uninstantiable type 'initialize_empty_union.U5' +// :10:12: note: union declared here diff --git a/test/cases/compile_errors/sizeof_alignof_empty_union.zig b/test/cases/compile_errors/sizeof_alignof_empty_union.zig new file mode 100644 index 0000000000000000000000000000000000000000..920b3b5af8a6281cce83860996d8af8eca3011f4 --- /dev/null +++ b/test/cases/compile_errors/sizeof_alignof_empty_union.zig @@ -0,0 +1,75 @@ +const EnumInferred = enum {}; +const EnumExplicit = enum(u8) {}; +const EnumNonexhaustive = enum(u8) { _ }; + +const U0 = union {}; +const U1 = union(enum) {}; +const U2 = union(enum(u8)) {}; +const U3 = union(EnumInferred) {}; +const U4 = union(EnumExplicit) {}; +const U5 = union(EnumNonexhaustive) {}; + +export fn size0() void { + _ = @sizeOf(U0); +} +export fn size1() void { + _ = @sizeOf(U1); +} +export fn size2() void { + _ = @sizeOf(U2); +} +export fn size3() void { + _ = @sizeOf(U3); +} +export fn size4() void { + _ = @sizeOf(U4); +} +export fn size5() void { + _ = @sizeOf(U5); +} + +export fn align0() void { + _ = @alignOf(U0); +} +export fn align1() void { + _ = @alignOf(U1); +} +export fn align2() void { + _ = @alignOf(U2); +} +export fn align3() void { + _ = @alignOf(U3); +} +export fn align4() void { + _ = @alignOf(U4); +} +export fn align5() void { + _ = @alignOf(U5); +} + +// error +// +// :13:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U0' +// :5:12: note: union declared here +// :16:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U1' +// :6:12: note: union declared here +// :19:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U2' +// :7:12: note: union declared here +// :22:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U3' +// :8:12: note: union declared here +// :25:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U4' +// :9:12: note: union declared here +// :28:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U5' +// :10:12: note: union declared here +// :32:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U0' +// :5:12: note: union declared here +// :35:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U1' +// :6:12: note: union declared here +// :38:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U2' +// :7:12: note: union declared here +// :41:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U3' +// :8:12: note: union declared here +// :44:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U4' +// :9:12: note: union declared here +// :47:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U5' +// :10:12: note: union declared here -- 2.54.0 From da2006a38c63ac84aa9a075193bd72cf2d1716a2 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 8 Feb 2026 14:21:08 +0000 Subject: [PATCH 24/79] tests: unions without fields need not store their tag at runtime ...because the union semantically has no possible value so cannot be stored to or loaded from memory anyway. --- test/behavior/union.zig | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/test/behavior/union.zig b/test/behavior/union.zig index a7b7c20a361d192a034363cc64a06ecc1f2b572a..1760f02c2299cf774153c64f24b76151249830e9 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -1020,7 +1020,7 @@ test "containers with single-field enums" { try comptime S.doTheTest(); } -test "@unionInit on union with tag but no fields" { +test "@unionInit on union with u8 tag but no fields" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO @@ -1036,10 +1036,6 @@ test "@unionInit on union with tag but no fields" { } }; - comptime { - assert(@sizeOf(Data) == 1); - } - fn doTheTest() !void { var data: Data = .{ .no_op = {} }; _ = &data; -- 2.54.0 From 031d109310fe1f7e68314069ddf5d0d1dd342098 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 8 Feb 2026 14:39:43 +0000 Subject: [PATCH 25/79] Sema: small error message fix --- src/Sema/type_resolution.zig | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig index adc787136f93d6e69cce6464926369def5de3388..089ad64e254f28fc638980bf7c4533f95a8d9ec0 100644 --- a/src/Sema/type_resolution.zig +++ b/src/Sema/type_resolution.zig @@ -454,7 +454,6 @@ fn resolvePackedStructLayout( const msg = try sema.errMsg(field_ty_src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); errdefer msg.destroy(gpa); try sema.explainWhyTypeIsUnpackable(msg, field_ty_src, reason); - try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; }); switch (field_ty.classify(zcu)) { -- 2.54.0 From f9183edf08214d3ff014cfe26a5f218385ef5ccc Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 8 Feb 2026 14:40:18 +0000 Subject: [PATCH 26/79] tests: update for accepted language change `packed struct`s and `packed union`s can no longer contain pointer fields. There are a few reasons for this, but in particular, binary formats do not typically support the relocation types we would need to lower such values into static memory. See the proposal at https://github.com/ziglang/zig/issues/24657 for details. --- test/behavior/bitcast.zig | 29 ------ test/behavior/packed-struct.zig | 98 ------------------- test/behavior/packed-union.zig | 12 --- test/behavior/union.zig | 30 +----- ...truct_with_fields_of_not_allowed_types.zig | 8 ++ ...cked_union_with_automatic_layout_field.zig | 18 ---- ...union_with_fields_of_not_allowed_types.zig | 20 ++++ 7 files changed, 33 insertions(+), 182 deletions(-) delete mode 100644 test/cases/compile_errors/packed_union_with_automatic_layout_field.zig create mode 100644 test/cases/compile_errors/packed_union_with_fields_of_not_allowed_types.zig diff --git a/test/behavior/bitcast.zig b/test/behavior/bitcast.zig index 90cf8a5c776b07b538a27b19df5a3362471319a0..90d185c63f52d6c013564f629d61ba9cdbbc202f 100644 --- a/test/behavior/bitcast.zig +++ b/test/behavior/bitcast.zig @@ -511,35 +511,6 @@ test "@bitCast of packed struct of bools all false" { try expect(@as(u8, @as(u4, @bitCast(p))) == 0); } -test "@bitCast of packed struct containing pointer" { - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // https://discourse.llvm.org/t/rfc-remove-most-constant-expressions/63179 - - const S = struct { - const A = packed struct { - ptr: *const u32, - }; - - const B = packed struct { - ptr: *const i32, - }; - - fn doTheTest() !void { - const x: u32 = 123; - var a: A = undefined; - a = .{ .ptr = &x }; - const b: B = @bitCast(a); - try expect(b.ptr.* == 123); - } - }; - - try S.doTheTest(); - try comptime S.doTheTest(); -} - test "@bitCast of extern struct containing pointer" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO diff --git a/test/behavior/packed-struct.zig b/test/behavior/packed-struct.zig index 72e97bef959debf39b1a3d22b6a13cf96bd56682..1b019acb7243acaa2ccb0896b766666fabd6e83f 100644 --- a/test/behavior/packed-struct.zig +++ b/test/behavior/packed-struct.zig @@ -438,27 +438,6 @@ test "nested packed struct field pointers" { try expectEqual(6, ptr_p1_b.*); } -test "load pointer from packed struct" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - - const A = struct { - index: u16, - }; - const B = packed struct { - x: *A, - y: u32, - }; - var a: A = .{ .index = 123 }; - const b_list: []const B = &.{.{ .x = &a, .y = 99 }}; - for (b_list) |b| { - try expect(b.x.index == 123); - } -} - test "@intFromPtr on a packed struct field" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO @@ -601,19 +580,6 @@ test "packed struct fields modification" { try expect(@as(u16, @bitCast(Small.p)) == 0x1313); } -test "optional pointer in packed struct" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - - const T = packed struct { ptr: ?*const u8 }; - var n: u8 = 0; - const x = T{ .ptr = &n }; - try expect(x.ptr.? == &n); -} - test "nested packed struct field access test" { if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO packed structs larger than 64 bits @@ -1042,48 +1008,6 @@ test "packed struct acts as a namespace" { try expect(foo == .fizz); } -test "pointer loaded correctly from packed struct" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - - if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // crashes MSVC - - const RAM = struct { - data: [0xFFFF + 1]u8, - fn new() !@This() { - return .{ .data = [_]u8{0} ** 0x10000 }; - } - fn get(self: *@This(), addr: u16) u8 { - return self.data[addr]; - } - }; - - const CPU = packed struct { - interrupts: bool, - ram: *RAM, - fn new(ram: *RAM) !@This() { - return .{ - .ram = ram, - .interrupts = false, - }; - } - fn tick(self: *@This()) !void { - const queued_interrupts = self.ram.get(0xFFFF) & self.ram.get(0xFF0F); - if (self.interrupts and queued_interrupts != 0) { - self.interrupts = false; - } - } - }; - - var ram = try RAM.new(); - var cpu = try CPU.new(&ram); - try cpu.tick(); - try std.testing.expect(cpu.interrupts == false); -} - test "assignment to non-byte-aligned field in packed struct" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO @@ -1227,13 +1151,6 @@ test "2-byte packed struct argument in C calling convention" { } } -test "packed struct contains optional pointer" { - const foo: packed struct { - a: ?*@This() = null, - } = .{}; - try expect(foo.a == null); -} - test "packed struct equality" { const Foo = packed struct { a: u4, @@ -1297,21 +1214,6 @@ test "assign packed struct initialized with RLS to packed struct literal field" try expect(outer.x == x); } -test "byte-aligned packed relocation" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - - const S = struct { - var global: u8 align(2) = 0; - var packed_value: packed struct { x: u8, y: *align(2) u8 } = .{ .x = 111, .y = &global }; - }; - try expect(S.packed_value.x == 111); - try expect(S.packed_value.y == &S.global); -} - test "packed struct store of comparison result" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; diff --git a/test/behavior/packed-union.zig b/test/behavior/packed-union.zig index bbb2f612b6788be2b1a7be647195004dd81da0c2..f625c8b0733ba6b0819feaf568ab6e4796f6cf47 100644 --- a/test/behavior/packed-union.zig +++ b/test/behavior/packed-union.zig @@ -177,15 +177,3 @@ test "assigning to non-active field at comptime" { test_bits.bits = .{}; } } - -test "comptime packed union of pointers" { - const U = packed union { - a: *const u32, - b: *const [1]u32, - }; - - const x: u32 = 123; - const u: U = .{ .a = &x }; - - comptime assert(u.b[0] == 123); -} diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 1760f02c2299cf774153c64f24b76151249830e9..9badc9dabd11bd6709c95ae32ba755f6cc3b9bd2 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -217,26 +217,6 @@ test "union with specified enum tag" { try comptime doTest(); } -test "packed union generates correctly aligned type" { - // This test will be removed after the following accepted proposal is implemented: - // https://github.com/ziglang/zig/issues/24657 - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - - const U = packed union { - f1: *const fn () error{TestUnexpectedResult}!void, - f2: usize, - }; - var foo = [_]U{ - U{ .f1 = doTest }, - U{ .f2 = 0 }, - }; - try foo[0].f1(); -} - fn doTest() error{TestUnexpectedResult}!void { try expect((try bar(Payload{ .A = 1234 })) == -10); } @@ -359,12 +339,12 @@ test "simple union(enum(u32))" { try expect(@intFromEnum(@as(Tag(MultipleChoice), x)) == 60); } -const PackedPtrOrInt = packed union { - ptr: *u8, - int: usize, -}; test "packed union size" { - comptime assert(@sizeOf(PackedPtrOrInt) == @sizeOf(usize)); + const U = packed union { + signed: isize, + unsigned: usize, + }; + comptime assert(@sizeOf(U) == @sizeOf(usize)); } const ZeroBits = union { diff --git a/test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig b/test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig index b5bf3d6f3a2b2c8d44f30e0e08ec78961f5eec59..5f4482421d65b8144ace994483cf8342aa35006b 100644 --- a/test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig +++ b/test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig @@ -76,6 +76,11 @@ export fn entry14() void { x: E, }); } +export fn entry15() void { + _ = @sizeOf(packed struct { + x: *const u32, + }); +} // error // @@ -103,3 +108,6 @@ export fn entry14() void { // :70:12: note: types are not available at runtime // :76:12: error: packed structs cannot contain fields of type 'tmp.entry14.E' // :74:15: note: enum declared here +// :81:12: error: packed structs cannot contain fields of type '*const u32' +// :81:12: note: pointers cannot be directly bitpacked +// :81:12: note: consider using 'usize' and '@intFromPtr' diff --git a/test/cases/compile_errors/packed_union_with_automatic_layout_field.zig b/test/cases/compile_errors/packed_union_with_automatic_layout_field.zig deleted file mode 100644 index c37e987c1c15399d22f8ffe5eab38bdd9ef2b4b1..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/packed_union_with_automatic_layout_field.zig +++ /dev/null @@ -1,18 +0,0 @@ -const Foo = struct { - a: u32, - b: f32, -}; -const Payload = packed union { - A: Foo, - B: bool, -}; -export fn entry() void { - const a: Payload = .{ .B = true }; - _ = a; -} - -// error -// -// :6:8: error: packed unions cannot contain fields of type 'tmp.Foo' -// :6:8: note: only packed structs layout are allowed in packed types -// :1:13: note: struct declared here diff --git a/test/cases/compile_errors/packed_union_with_fields_of_not_allowed_types.zig b/test/cases/compile_errors/packed_union_with_fields_of_not_allowed_types.zig new file mode 100644 index 0000000000000000000000000000000000000000..cfbdf4e90aeaab22aa6637066e68d1a1ce0348ac --- /dev/null +++ b/test/cases/compile_errors/packed_union_with_fields_of_not_allowed_types.zig @@ -0,0 +1,20 @@ +export fn entry0() void { + _ = @sizeOf(packed union { + foo: struct { a: u32 }, + bar: bool, + }); +} +export fn entry1() void { + _ = @sizeOf(packed union { + x: *const u32, + }); +} + +// error +// +// :3:14: error: packed unions cannot contain fields of type 'packed_union_with_fields_of_not_allowed_types.entry0__union_180__struct_182' +// :3:14: note: non-packed structs do not have a bit-packed representation +// :3:14: note: struct declared here +// :9:12: error: packed unions cannot contain fields of type '*const u32' +// :9:12: note: pointers cannot be directly bitpacked +// :9:12: note: consider using 'usize' and '@intFromPtr' -- 2.54.0 From a226008e32af8700d1aa05bcaef50cb3cf1205d0 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 8 Feb 2026 14:58:03 +0000 Subject: [PATCH 27/79] Sema: minor fix --- src/Sema.zig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 140e69fe6ffe1e3e16e4cf6176a8ff48bf89000d..40a1126c9f27bc39982cceebd2f43a91f4efb716 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -15913,12 +15913,12 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A .undefined, .null, .@"opaque", + .type, + .enum_literal, + .comptime_float, + .comptime_int, => return sema.fail(block, operand_src, "no size available for type '{f}'", .{operand_ty.fmt(pt)}), - .type, - .enum_literal, - .comptime_float, - .comptime_int, .void, => return .zero, -- 2.54.0 From 21b42af5aa6bc25dd99d2e425aa3df6bac80476e Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 8 Feb 2026 14:58:32 +0000 Subject: [PATCH 28/79] tests: update for accepted language change `@sizeOf` and `@bitSizeOf` are now more restricted: they are not allowed on comptime-only or NPV (uninstantiable) types. This is because there is no correct way to actually use the returned ABI size (e.g. you cannot copy a comptime-only type by copying all of its runtime bits), so having a non-zero return value had no benefit and was simply confusing. --- test/behavior/sizeof_and_typeof.zig | 25 ------------------- test/behavior/type.zig | 4 +-- .../cases/compile_errors/alignOf_bad_type.zig | 10 ++++++-- test/cases/compile_errors/sizeOf_bad_type.zig | 22 ++++++++++++++-- 4 files changed, 30 insertions(+), 31 deletions(-) diff --git a/test/behavior/sizeof_and_typeof.zig b/test/behavior/sizeof_and_typeof.zig index a6087787b5bfec02334554fa527d1011a8bf4a96..2fb89bc484bb9ab682c2627800debbe546531b2b 100644 --- a/test/behavior/sizeof_and_typeof.zig +++ b/test/behavior/sizeof_and_typeof.zig @@ -11,13 +11,6 @@ test "@sizeOf and @TypeOf" { const x: u16 = 13; const z: @TypeOf(x) = 19; -test "@sizeOf on compile-time types" { - try expect(@sizeOf(comptime_int) == 0); - try expect(@sizeOf(comptime_float) == 0); - try expect(@sizeOf(@TypeOf(.hi)) == 0); - try expect(@sizeOf(@TypeOf(type)) == 0); -} - test "@TypeOf() with multiple arguments" { { var var_1: u32 = undefined; @@ -265,10 +258,6 @@ test "lazy size cast to float" { } } -test "bitSizeOf comptime_int" { - try expect(@bitSizeOf(comptime_int) == 0); -} - test "runtime instructions inside typeof in comptime only scope" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO @@ -336,20 +325,6 @@ test "peer type resolution with @TypeOf doesn't trigger dependency loop check" { try std.testing.expect(t.next == null); } -test "@sizeOf reified union zero-size payload fields" { - comptime { - try std.testing.expect(0 == @sizeOf(@Union(.auto, null, &.{}, &.{}, &.{}))); - try std.testing.expect(0 == @sizeOf(@Union(.auto, null, &.{"a"}, &.{void}, &.{.{}}))); - if (builtin.mode == .Debug or builtin.mode == .ReleaseSafe) { - try std.testing.expect(1 == @sizeOf(@Union(.auto, null, &.{ "a", "b" }, &.{ void, void }, &.{ .{}, .{} }))); - try std.testing.expect(1 == @sizeOf(@Union(.auto, null, &.{ "a", "b", "c" }, &.{ void, void, void }, &.{ .{}, .{}, .{} }))); - } else { - try std.testing.expect(0 == @sizeOf(@Union(.auto, null, &.{ "a", "b" }, &.{ void, void }, &.{ .{}, .{} }))); - try std.testing.expect(0 == @sizeOf(@Union(.auto, null, &.{ "a", "b", "c" }, &.{ void, void, void }, &.{ .{}, .{}, .{} }))); - } - } -} - const FILE = extern struct { dummy_field: u8, }; diff --git a/test/behavior/type.zig b/test/behavior/type.zig index ef27522a63038a36429063607d7d48768195268f..88358db1829cdb9b51018b595d49170f7482b8bc 100644 --- a/test/behavior/type.zig +++ b/test/behavior/type.zig @@ -278,13 +278,13 @@ test "Type.Union from regular enum" { test "Type.Union from empty regular enum" { const E = enum {}; const U = @Union(.auto, E, &.{}, &.{}, &.{}); - try testing.expectEqual(@sizeOf(U), 0); + try testing.expectEqual(@typeInfo(U).@"union".fields.len, 0); } test "Type.Union from empty Type.Enum" { const E = @Enum(u0, .exhaustive, &.{}, &.{}); const U = @Union(.auto, E, &.{}, &.{}, &.{}); - try testing.expectEqual(@sizeOf(U), 0); + try testing.expectEqual(@typeInfo(U).@"union".fields.len, 0); } test "Type.Fn" { diff --git a/test/cases/compile_errors/alignOf_bad_type.zig b/test/cases/compile_errors/alignOf_bad_type.zig index 253adceb0547552ba531eb93a50f989d770a3b7c..93dcfa3b94922a74c2edb4720cd0232ddabbb795 100644 --- a/test/cases/compile_errors/alignOf_bad_type.zig +++ b/test/cases/compile_errors/alignOf_bad_type.zig @@ -1,7 +1,13 @@ -export fn entry() usize { +export fn entry0() usize { return @alignOf(noreturn); } +const S = struct { a: u32, b: noreturn }; +export fn entry1() usize { + return @alignOf(S); +} // error // -// :2:21: error: no align available for type 'noreturn' +// :2:21: error: no align available for uninstantiable type 'noreturn' +// :6:21: error: no align available for uninstantiable type 'alignOf_bad_type.S' +// :4:11: note: struct declared here diff --git a/test/cases/compile_errors/sizeOf_bad_type.zig b/test/cases/compile_errors/sizeOf_bad_type.zig index 93dec1f88eeddfaf5352b183ad54886cbfb3e39c..c81ad7450f3d34e9af7e0eabcc2917e4303027f1 100644 --- a/test/cases/compile_errors/sizeOf_bad_type.zig +++ b/test/cases/compile_errors/sizeOf_bad_type.zig @@ -1,7 +1,25 @@ -export fn entry() usize { +export fn entry0() usize { return @sizeOf(@TypeOf(null)); } +export fn entry1() usize { + return @sizeOf(comptime_int); +} +export fn entry2() usize { + return @sizeOf(noreturn); +} +const S3 = struct { a: u32, b: comptime_int }; +export fn entry3() usize { + return @sizeOf(S3); +} +const S4 = struct { a: u32, b: noreturn }; +export fn entry4() usize { + return @sizeOf(S4); +} // error // -// :2:20: error: no size available for type '@TypeOf(null)' +// :2:20: error: no size available for comptime-only type '@TypeOf(null)' +// :5:20: error: no size available for comptime-only type 'comptime_int' +// :8:20: error: no size available for uninstantiable type 'noreturn' +// :12:20: error: no size available for comptime-only type 'tmp.S3' +// :16:20: error: no size available for uninstantiable type 'tmp.S4' -- 2.54.0 From c9fc921abdfddcfed3383488dc1eaf23dcdeaa54 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 8 Feb 2026 15:14:57 +0000 Subject: [PATCH 29/79] tests: update for accepted language change Pointers to comptime-only types (e.g. `*type`) are no longer themselves comptime-only types. This means explicit `comptime` annotations are required in a few more places. However, it also introduces the ability to access pointers to (including slices of) comptime-only types at runtime, provided only runtime fields are being accessed. --- test/behavior/slice.zig | 2 +- test/behavior/struct.zig | 23 ++++++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index 4de7b26d34f735b5a11976b3c3d05734e5f39e56..b13003dc5092f4395e211d24b2fef3baad0c05a4 100644 --- a/test/behavior/slice.zig +++ b/test/behavior/slice.zig @@ -160,7 +160,7 @@ test "slice of type" { test "pass a slice of types to a function" { const S = struct { - fn checkTypesSlice(types_slice: []const type) !void { + fn checkTypesSlice(comptime types_slice: []const type) !void { try expect(types_slice.len == 2); try expect(types_slice[0] == anyerror); try expect(types_slice[1] == bool); diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 6422aef034bf3b4fbcf1e16acce3742944828a04..e6a355864629600f6294492ee11e4cf7c73f5674 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -2177,7 +2177,7 @@ test "avoid unused field function body compile error" { test "pass a pointer to a comptime-only struct field to a function" { const S = struct { - fn checkField(field_ptr: *const type) !void { + fn checkField(comptime field_ptr: *const type) !void { try expect(field_ptr.* == u42); } }; @@ -2233,3 +2233,24 @@ test "overaligned extern struct fields" { try expect(std.mem.isAligned(@intFromPtr(&e.c), @alignOf(u32))); try expect(std.mem.isAligned(@intFromPtr(&e.d), @alignOf(B))); } + +test "runtime-known slice of comptime-only struct" { + const Mixed = struct { index: u32, T: type }; + + const static = struct { + fn doTheTest(index_offset: usize, s: []const Mixed) !void { + for (s, index_offset..) |*mixed, index| { + try expect(mixed.index == index); + } + } + }; + + try static.doTheTest(10, &.{ + .{ .index = 10, .T = u8 }, + .{ .index = 11, .T = noreturn }, + .{ .index = 12, .T = *opaque {} }, + .{ .index = 13, .T = undefined }, + .{ .index = 14, .T = @TypeOf(undefined) }, + .{ .index = 15, .T = Mixed }, + }); +} -- 2.54.0 From e2669689c46630afd3adb99c496a6895c6c95a15 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 8 Feb 2026 15:22:42 +0000 Subject: [PATCH 30/79] behavior: auto structs with zero fields are not extern types --- test/behavior/sizeof_and_typeof.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/behavior/sizeof_and_typeof.zig b/test/behavior/sizeof_and_typeof.zig index 2fb89bc484bb9ab682c2627800debbe546531b2b..65deede0768638791f5da2cb4b74db82ea6c0caa 100644 --- a/test/behavior/sizeof_and_typeof.zig +++ b/test/behavior/sizeof_and_typeof.zig @@ -366,7 +366,7 @@ test "Extern function calls in @TypeOf" { extern fn s_do_thing([*c]const @This(), b: c_int) c_short; }; - const E = struct { + const E = extern struct { export fn s_do_thing(a: [*c]const @This(), b: c_int) c_short { _ = a; _ = b; -- 2.54.0 From be4c4ce2787537f860c8578eb9e497f66c2e9baf Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 8 Feb 2026 15:39:21 +0000 Subject: [PATCH 31/79] Zcu: improve dependency loop errors with only one item In this case, we can write the error much more simply. --- src/Zcu.zig | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/Zcu.zig b/src/Zcu.zig index ce90f2c417abc94c2b146c922f907c2b17a69e24..fc770ba4ea1924d34d238e8bb13fd3107332a1ec 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -4739,21 +4739,32 @@ pub fn addDependencyLoopErrors(zcu: *Zcu, eb: *std.zig.ErrorBundle.Wip) Allocato const frame_limit = zcu.comp.reference_trace orelse 0; try zcu.populateReferenceTrace(units.items[start_index], frame_limit, eb, &ref_trace); + if (units.items.len == 1) { + // Don't do a complicated message with multiple notes, just do a single error message. + assert(start_index == 0); + const root_msg = addDependencyLoopErrorLine(zcu, eb, units.items[start_index], ref_trace.items) catch |err| switch (err) { + error.AlreadyReported => return, // give up on the dep loop error + error.OutOfMemory => |e| return e, + }; + try eb.root_list.append(eb.gpa, root_msg); + continue; + } + // Collect all notes first so we don't leave an incomplete root error message on `error.AlreadyReported`. const note_buf = try gpa.alloc(std.zig.ErrorBundle.MessageIndex, units.items.len + 1); defer gpa.free(note_buf); - note_buf[0] = addDependencyLoopNote(zcu, eb, units.items[start_index], ref_trace.items) catch |err| switch (err) { + note_buf[0] = addDependencyLoopErrorLine(zcu, eb, units.items[start_index], ref_trace.items) catch |err| switch (err) { error.AlreadyReported => return, // give up on the dep loop error error.OutOfMemory => |e| return e, }; for (units.items[start_index + 1 ..], note_buf[1 .. units.items.len - start_index]) |unit, *note| { - note.* = addDependencyLoopNote(zcu, eb, unit, &.{}) catch |err| switch (err) { + note.* = addDependencyLoopErrorLine(zcu, eb, unit, &.{}) catch |err| switch (err) { error.AlreadyReported => return, // give up on the dep loop error error.OutOfMemory => |e| return e, }; } for (units.items[0..start_index], note_buf[units.items.len - start_index .. units.items.len]) |unit, *note| { - note.* = addDependencyLoopNote(zcu, eb, unit, &.{}) catch |err| switch (err) { + note.* = addDependencyLoopErrorLine(zcu, eb, unit, &.{}) catch |err| switch (err) { error.AlreadyReported => return, // give up on the dep loop error error.OutOfMemory => |e| return e, }; @@ -4773,7 +4784,7 @@ pub fn addDependencyLoopErrors(zcu: *Zcu, eb: *std.zig.ErrorBundle.Wip) Allocato @memcpy(notes, note_buf); } } -fn addDependencyLoopNote( +fn addDependencyLoopErrorLine( zcu: *Zcu, eb: *std.zig.ErrorBundle.Wip, source_unit: AnalUnit, @@ -4789,7 +4800,16 @@ fn addDependencyLoopNote( const dep_node = zcu.dependency_loop_nodes.get(source_unit).?; - const msg: std.zig.ErrorBundle.String = switch (dep_node.unit.unwrap()) { + const msg: std.zig.ErrorBundle.String = if (dep_node.unit == source_unit) switch (source_unit.unwrap()) { + .@"comptime" => unreachable, // cannot be involved in a dependency loop + .nav_ty, .nav_val => try eb.printString("{f} depends on itself here", .{fmt_source}), + .memoized_state => unreachable, // memoized_state definitely does not *directly* depend on itself + .func => try eb.printString("{f} uses its own inferred error set here", .{fmt_source}), + .type_layout => try eb.printString("{f} depends on itself {s}", .{ + fmt_source, + dep_node.reason.type_layout_reason.msg(), + }), + } else switch (dep_node.unit.unwrap()) { .@"comptime" => unreachable, // cannot be involved in a dependency loop .nav_val => |nav| try eb.printString("{f} uses value of declaration '{f}' here", .{ fmt_source, ip.getNav(nav).fqn.fmt(ip), -- 2.54.0 From 1364cba90d41cb2f33380b23d534aaddbd6ceff2 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 8 Feb 2026 15:52:12 +0000 Subject: [PATCH 32/79] behavior: update for type resolution changes --- test/behavior/array.zig | 22 ------------------- test/behavior/sizeof_and_typeof.zig | 15 ------------- .../struct_contains_slice_of_itself.zig | 2 +- 3 files changed, 1 insertion(+), 38 deletions(-) diff --git a/test/behavior/array.zig b/test/behavior/array.zig index b28ee267c2e03a1a1b758ea6256b7f3fc23ebb09..2bd85555297beed2d7b33de499e272ddc639a175 100644 --- a/test/behavior/array.zig +++ b/test/behavior/array.zig @@ -539,28 +539,6 @@ test "sentinel element count towards the ABI size calculation" { try comptime S.doTheTest(); } -test "zero-sized array with recursive type definition" { - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - - const U = struct { - fn foo(comptime T: type, comptime n: usize) type { - return struct { - s: [n]T, - x: usize = n, - }; - } - }; - - const S = struct { - list: U.foo(@This(), 0), - }; - - var t: S = .{ .list = .{ .s = undefined } }; - _ = &t; - try expect(@as(usize, 0) == t.list.x); -} - test "type coercion of anon struct literal to array" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; diff --git a/test/behavior/sizeof_and_typeof.zig b/test/behavior/sizeof_and_typeof.zig index 65deede0768638791f5da2cb4b74db82ea6c0caa..cb6c334cb7448bdd403c419baaad2eb9d92443d9 100644 --- a/test/behavior/sizeof_and_typeof.zig +++ b/test/behavior/sizeof_and_typeof.zig @@ -120,21 +120,6 @@ test "@bitOffsetOf" { try expect(@offsetOf(A, "g") * 8 == @bitOffsetOf(A, "g")); } -test "@sizeOf(T) == 0 doesn't force resolving struct size" { - const S = struct { - const Foo = struct { - y: if (@sizeOf(Foo) == 0) u64 else u32, - }; - const Bar = struct { - x: i32, - y: if (0 == @sizeOf(Bar)) u64 else u32, - }; - }; - - try expect(@sizeOf(S.Foo) == 4); - try expect(@sizeOf(S.Bar) == 8); -} - test "@TypeOf() has no runtime side effects" { const S = struct { fn foo(comptime T: type, ptr: *T) T { diff --git a/test/behavior/struct_contains_slice_of_itself.zig b/test/behavior/struct_contains_slice_of_itself.zig index 5cf8d8134a1cc91abbc392c0acf7c1765f3e50bc..541babee6bb62d10cf05f141545eafe9766aefd7 100644 --- a/test/behavior/struct_contains_slice_of_itself.zig +++ b/test/behavior/struct_contains_slice_of_itself.zig @@ -8,7 +8,7 @@ const Node = struct { const NodeAligned = struct { payload: i32, - children: []align(@alignOf(NodeAligned)) NodeAligned, + children: []align(1) NodeAligned, }; test "struct contains slice of itself" { -- 2.54.0 From 12ddd5a698577e22a0bb5ed788ea4b9729a45b5d Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 8 Feb 2026 15:58:51 +0000 Subject: [PATCH 33/79] behavior: update for changes to struct field default value resolution This is separate from the previous commit so that these changes can be easily reverted in the event that we decide to allow more granularity in default value resolution in exchange for increased language complexity. --- test/behavior/eval.zig | 114 --------------------------------------- test/behavior/struct.zig | 58 ++------------------ test/behavior/union.zig | 49 ----------------- 3 files changed, 3 insertions(+), 218 deletions(-) diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig index 8f45405e94838c9c7768616a9f1f1dd24c2baa7f..9e3cd732f0e3b41152fbbb51732283bbe9c07192 100644 --- a/test/behavior/eval.zig +++ b/test/behavior/eval.zig @@ -1081,120 +1081,6 @@ test "comptime break operand passing through runtime switch converted to runtime try comptime S.doTheTest('b'); } -test "no dependency loop for alignment of self struct" { - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - - const S = struct { - fn doTheTest() !void { - var a: namespace.A = undefined; - a.d = .{ .g = &buf }; - a.d.g[3] = 42; - a.d.g[3] += 1; - try expect(a.d.g[3] == 43); - } - - var buf: [10]u8 align(@alignOf([*]u8)) = undefined; - - const namespace = struct { - const B = struct { a: A }; - const A = C(B); - }; - - pub fn C(comptime B: type) type { - return struct { - d: D(F) = .{}, - - const F = struct { b: B }; - }; - } - - pub fn D(comptime F: type) type { - return struct { - g: [*]align(@alignOf(F)) u8 = undefined, - }; - } - }; - try S.doTheTest(); -} - -test "no dependency loop for alignment of self bare union" { - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - - const S = struct { - fn doTheTest() !void { - var a: namespace.A = undefined; - a.d = .{ .g = &buf }; - a.d.g[3] = 42; - a.d.g[3] += 1; - try expect(a.d.g[3] == 43); - } - - var buf: [10]u8 align(@alignOf([*]u8)) = undefined; - - const namespace = struct { - const B = union { a: A, b: void }; - const A = C(B); - }; - - pub fn C(comptime B: type) type { - return struct { - d: D(F) = .{}, - - const F = struct { b: B }; - }; - } - - pub fn D(comptime F: type) type { - return struct { - g: [*]align(@alignOf(F)) u8 = undefined, - }; - } - }; - try S.doTheTest(); -} - -test "no dependency loop for alignment of self tagged union" { - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - - const S = struct { - fn doTheTest() !void { - var a: namespace.A = undefined; - a.d = .{ .g = &buf }; - a.d.g[3] = 42; - a.d.g[3] += 1; - try expect(a.d.g[3] == 43); - } - - var buf: [10]u8 align(@alignOf([*]u8)) = undefined; - - const namespace = struct { - const B = union(enum) { a: A, b: void }; - const A = C(B); - }; - - pub fn C(comptime B: type) type { - return struct { - d: D(F) = .{}, - - const F = struct { b: B }; - }; - } - - pub fn D(comptime F: type) type { - return struct { - g: [*]align(@alignOf(F)) u8 = undefined, - }; - } - }; - try S.doTheTest(); -} - test "equality of pointers to comptime const" { const a: i32 = undefined; comptime assert(&a == &a); diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index e6a355864629600f6294492ee11e4cf7c73f5674..37dc873d60385608367b1841362aaadb21254e5c 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -1249,20 +1249,6 @@ test "store to comptime field" { } } -test "struct field init value is size of the struct" { - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - - const namespace = struct { - const S = extern struct { - size: u8 = @sizeOf(S), - blah: u16, - }; - }; - var s: namespace.S = .{ .blah = 1234 }; - _ = &s; - try expect(s.size == 4); -} - test "under-aligned struct field" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO @@ -1710,41 +1696,19 @@ test "comptimeness of optional and error union payload is analyzed properly" { try std.testing.expectEqual(3, x); } -test "initializer uses own alignment" { - const S = struct { - x: u32 = @alignOf(@This()) + 1, - }; - - var s: S = .{}; - _ = &s; - try expectEqual(4, @alignOf(S)); - try expectEqual(@as(usize, 5), s.x); -} - -test "initializer uses own size" { - const S = struct { - x: u32 = @sizeOf(@This()) + 1, - }; - - var s: S = .{}; - _ = &s; - try expectEqual(4, @sizeOf(S)); - try expectEqual(@as(usize, 5), s.x); -} - test "initializer takes a pointer to a variable inside its struct" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const namespace = struct { const S = struct { - s: *S = &S.instance, - var instance: S = undefined; + x: *u32 = &S.int, + var int: u32 = undefined; }; fn doTheTest() !void { var foo: S = .{}; _ = &foo; - try expectEqual(&S.instance, foo.s); + try expectEqual(&S.int, foo.x); } }; @@ -1775,22 +1739,6 @@ test "circular dependency through pointer field of a struct" { try expect(outer.middle.inner == null); } -test "field calls do not force struct field init resolution" { - const S = struct { - x: u32 = blk: { - _ = @TypeOf(make().dummyFn()); // runtime field call - S not fully resolved - dummyFn call should not force field init resolution - break :blk 123; - }, - dummyFn: *const fn () void = undefined, - fn make() @This() { - return .{}; - } - }; - var s: S = .{}; - _ = &s; - try expect(s.x == 123); -} - test "tuple with comptime-only field" { const S = struct { fn getTuple() struct { comptime_int } { diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 9badc9dabd11bd6709c95ae32ba755f6cc3b9bd2..b081d9b33a06e41df101c7f55f2d716821be30fe 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -1796,55 +1796,6 @@ test "reinterpret packed union inside packed struct" { try S.doTheTest(); } -test "inner struct initializer uses union layout" { - const namespace = struct { - const U = union { - a: struct { - x: u32 = @alignOf(U) + 1, - }, - b: struct { - y: u16 = @sizeOf(U) + 2, - }, - }; - }; - - { - const u: namespace.U = .{ .a = .{} }; - try expectEqual(4, @alignOf(namespace.U)); - try expectEqual(@as(usize, 5), u.a.x); - } - - { - const u: namespace.U = .{ .b = .{} }; - try expectEqual(@as(usize, @sizeOf(namespace.U) + 2), u.b.y); - } -} - -test "inner struct initializer uses packed union layout" { - const namespace = struct { - const U = packed union { - a: packed struct { - x: u32 = @alignOf(U) + 1, - }, - b: packed struct(u32) { - y: u16 = @sizeOf(U) + 2, - padding: u16 = 0, - }, - }; - }; - - { - const u: namespace.U = .{ .a = .{} }; - try expectEqual(4, @alignOf(namespace.U)); - try expectEqual(@as(usize, 5), u.a.x); - } - - { - const u: namespace.U = .{ .b = .{} }; - try expectEqual(@as(usize, @sizeOf(namespace.U) + 2), u.b.y); - } -} - test "extern union initialized via reintepreted struct field initializer" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; -- 2.54.0 From 5865abf7f5ea2d4500cb8387252d9efee26ecae1 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Mon, 9 Feb 2026 10:20:58 +0000 Subject: [PATCH 34/79] Sema: defer extern function type validation to declaration or call Because of packed structs, checking whether a type is extern-compatible requires that its layout be resolved. For functions to do this validation as soon as the function type is created would lead to dependency loops in cases like '*const fn (*@This()) void callconv(.c)`. Therefore, when creating a function *type*, we no longer perform this check immediately, instead waiting until the function is called. --- src/Sema.zig | 258 +++++++++++++++++++++-------------- src/Sema/type_resolution.zig | 4 +- src/Type.zig | 3 +- 3 files changed, 156 insertions(+), 109 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 40a1126c9f27bc39982cceebd2f43a91f4efb716..d5aef143392ca4cceefec718c4c9acb1bbf3c7a2 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5747,6 +5747,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void } const export_ty = ptr_ty.childType(zcu); + try sema.ensureLayoutResolved(export_ty, src, .@"export"); if (!export_ty.validateExtern(.other, zcu)) { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(src, "unable to export type '{f}'", .{export_ty.fmt(pt)}); @@ -6749,6 +6750,37 @@ fn analyzeCall( } else func_src; const func_ty_info = zcu.typeToFunc(func_ty).?; + + for (func_ty_info.param_types.get(ip), 0..) |param_ty_ip, param_index| { + const arg_src = args_info.argSrc(block, param_index); + try sema.ensureLayoutResolved(.fromInterned(param_ty_ip), arg_src, .init); + } + try sema.ensureLayoutResolved(.fromInterned(func_ty_info.return_type), func_ret_ty_src, .return_type); + try sema.validateResolvedFuncType( + block, + func_ty_info.cc, + func_ty_info.param_types.get(ip), + .fromInterned(func_ty_info.return_type), + func_src, + maybe_func_inst, + ); + + if (!callConvIsCallable(func_ty_info.cc)) { + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg( + func_src, + "unable to call function with calling convention '{s}'", + .{@tagName(func_ty_info.cc)}, + ); + errdefer msg.destroy(gpa); + if (maybe_func_inst) |func_inst| try sema.errNote(.{ + .base_node_inst = func_inst, + .offset = .nodeOffset(.zero), + }, msg, "function declared here", .{}); + break :msg msg; + }); + } + const any_comptime_params = func_ty_info.comptime_bits != 0 or ct: { for (func_ty_info.param_types.get(ip)) |param_ty| { if (Type.fromInterned(param_ty).comptimeOnly(zcu)) break :ct true; @@ -6771,22 +6803,6 @@ fn analyzeCall( break :generic false; }; - if (!callConvIsCallable(func_ty_info.cc)) { - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg( - func_src, - "unable to call function with calling convention '{s}'", - .{@tagName(func_ty_info.cc)}, - ); - errdefer msg.destroy(gpa); - if (maybe_func_inst) |func_inst| try sema.errNote(.{ - .base_node_inst = func_inst, - .offset = .nodeOffset(.zero), - }, msg, "function declared here", .{}); - break :msg msg; - }); - } - // We need this value in a few code paths. const callee_val = try sema.resolveDefinedValue(block, call_src, callee); // If the callee is a comptime-known *non-extern* function, `func_val` is populated. @@ -8755,11 +8771,12 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: } } -fn checkParamTypeCommon( +fn checkParamType( sema: *Sema, block: *Block, param_idx: u32, param_ty: Type, + param_is_comptime: bool, param_is_noalias: bool, param_src: LazySrcLoc, cc: std.builtin.CallingConvention, @@ -8774,29 +8791,22 @@ fn checkParamTypeCommon( opaque_str, param_ty.fmt(pt), }); } - if (!param_ty.isGenericPoison() and - !target_util.fnCallConvAllowsZigTypes(cc) and - !param_ty.validateExtern(.param_ty, zcu)) - { - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(param_src, "parameter of type '{f}' not allowed in function with calling convention '{s}'", .{ - param_ty.fmt(pt), @tagName(cc), - }); - errdefer msg.destroy(sema.gpa); - - try sema.explainWhyTypeIsNotExtern(msg, param_src, param_ty, .param_ty); - - try sema.addDeclaredHereNote(msg, param_ty); - break :msg msg; - }); + if (!target_util.fnCallConvAllowsZigTypes(cc)) { + if (param_is_comptime) { + return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{t}'", .{cc}); + } + if (param_ty.isGenericPoison()) { + return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{t}'", .{cc}); + } + // The `validateExtern` check happens later, in `validateResolvedFuncType`. } switch (cc) { .x86_64_interrupt, .x86_interrupt => { const err_code_size = target.ptrBitWidth(); switch (param_idx) { - 0 => if (param_ty.zigTypeTag(zcu) != .pointer) return sema.fail(block, param_src, "first parameter of function with '{s}' calling convention must be a pointer type", .{@tagName(cc)}), - 1 => if (param_ty.bitSize(zcu) != err_code_size) return sema.fail(block, param_src, "second parameter of function with '{s}' calling convention must be a {d}-bit integer", .{ @tagName(cc), err_code_size }), - else => return sema.fail(block, param_src, "'{s}' calling convention supports up to 2 parameters, found {d}", .{ @tagName(cc), param_idx + 1 }), + 0 => if (param_ty.zigTypeTag(zcu) != .pointer) return sema.fail(block, param_src, "first parameter of function with '{t}' calling convention must be a pointer type", .{cc}), + 1 => if (param_ty.bitSize(zcu) != err_code_size) return sema.fail(block, param_src, "second parameter of function with '{t}' calling convention must be a {d}-bit integer", .{ cc, err_code_size }), + else => return sema.fail(block, param_src, "'{t}' calling convention supports up to 2 parameters, found {d}", .{ cc, param_idx + 1 }), } }, .arc_interrupt, @@ -8812,7 +8822,7 @@ fn checkParamTypeCommon( .m68k_interrupt, .msp430_interrupt, .avr_signal, - => return sema.fail(block, param_src, "parameters are not allowed with '{s}' calling convention", .{@tagName(cc)}), + => return sema.fail(block, param_src, "parameters are not allowed with '{t}' calling convention", .{cc}), else => {}, } if (param_is_noalias and !param_ty.isGenericPoison() and !param_ty.isPtrAtRuntime(zcu) and !param_ty.isSliceAtRuntime(zcu)) { @@ -8820,7 +8830,7 @@ fn checkParamTypeCommon( } } -fn checkReturnTypeAndCallConvCommon( +fn checkReturnTypeAndCallConv( sema: *Sema, block: *Block, bare_ret_ty: Type, @@ -8834,7 +8844,6 @@ fn checkReturnTypeAndCallConvCommon( ) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; - const gpa = zcu.gpa; if (opt_varargs_src) |varargs_src| { try sema.checkCallConvSupportsVarArgs(block, varargs_src, @"callconv"); } @@ -8848,21 +8857,14 @@ fn checkReturnTypeAndCallConvCommon( opaque_str, ies_ret_ty_prefix, bare_ret_ty.fmt(pt), }); } - if (!bare_ret_ty.isGenericPoison() and - !target_util.fnCallConvAllowsZigTypes(@"callconv") and - (inferred_error_set or !bare_ret_ty.validateExtern(.ret_ty, zcu))) - { - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(ret_ty_src, "return type '{s}{f}' not allowed in function with calling convention '{s}'", .{ - ies_ret_ty_prefix, bare_ret_ty.fmt(pt), @tagName(@"callconv"), - }); - errdefer msg.destroy(gpa); - if (!inferred_error_set) { - try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src, bare_ret_ty, .ret_ty); - try sema.addDeclaredHereNote(msg, bare_ret_ty); - } - break :msg msg; - }); + if (!target_util.fnCallConvAllowsZigTypes(@"callconv")) { + if (inferred_error_set) { + return sema.fail(block, ret_ty_src, "return type '!{f}' not allowed in function with calling convention '{t}'", .{ bare_ret_ty.fmt(pt), @"callconv" }); + } + if (bare_ret_ty.isGenericPoison()) { + return sema.fail(block, ret_ty_src, "generic return type not allowed in function with calling convention '{t}'", .{@"callconv"}); + } + // The `validateExtern` check happens later, in `validateResolvedFuncType`. } validate_incoming_stack_align: { const a: u64 = switch (@"callconv") { @@ -8897,7 +8899,7 @@ fn checkReturnTypeAndCallConvCommon( else => false, }; if (!ret_ok) { - return sema.fail(block, ret_ty_src, "function with calling convention '{s}' must return 'void' or 'noreturn'", .{@tagName(@"callconv")}); + return sema.fail(block, ret_ty_src, "function with calling convention '{t}' must return 'void' or 'noreturn'", .{@"callconv"}); } }, .@"inline" => if (is_noinline) { @@ -8918,18 +8920,76 @@ fn checkReturnTypeAndCallConvCommon( } } }; - return sema.fail(block, callconv_src, "calling convention '{s}' only available on architectures {f}", .{ - @tagName(@"callconv"), - ArchListFormatter{ .archs = allowed_archs }, + return sema.fail(block, callconv_src, "calling convention '{t}' only available on architectures {f}", .{ + @"callconv", ArchListFormatter{ .archs = allowed_archs }, }); }, - .bad_backend => |bad_backend| return sema.fail(block, callconv_src, "calling convention '{s}' not supported by compiler backend '{s}'", .{ - @tagName(@"callconv"), - @tagName(bad_backend), + .bad_backend => |bad_backend| return sema.fail(block, callconv_src, "calling convention '{t}' not supported by compiler backend '{t}'", .{ + @"callconv", bad_backend, }), } } +/// To avoid forcing type layout resolution too quickly, some validation of function types cannot be +/// performed when the type is first constructed, and instead must happen when either (a) a function +/// with that type is declared, or (b) a function with that type is called. That validation is +/// handled here. +/// +/// Asserts that all parameter types and return types have their layout fully resolved. +fn validateResolvedFuncType( + sema: *Sema, + block: *Block, + @"callconv": std.builtin.CallingConvention, + param_types: []const InternPool.Index, + ret_ty: Type, + src: LazySrcLoc, + maybe_func_decl_inst: ?InternPool.TrackedInst.Index, +) SemaError!void { + const pt = sema.pt; + const zcu = pt.zcu; + const gpa = zcu.comp.gpa; + if (!target_util.fnCallConvAllowsZigTypes(@"callconv")) { + // Check that all parameter types are extern-compatible. + for (param_types, 0..) |param_ty_ip, param_index| { + const param_ty: Type = .fromInterned(param_ty_ip); + if (!param_ty.validateExtern(.param_ty, zcu)) { + const param_src: LazySrcLoc = if (maybe_func_decl_inst) |inst| .{ + .base_node_inst = inst, + .offset = .{ .fn_proto_param = .{ + .fn_proto_node_offset = .zero, + .param_index = @intCast(param_index), + } }, + } else src; + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(param_src, "parameter of type '{f}' not allowed in function with calling convention '{t}'", .{ + param_ty.fmt(pt), @"callconv", + }); + errdefer msg.destroy(gpa); + try sema.explainWhyTypeIsNotExtern(msg, param_src, param_ty, .param_ty); + try sema.addDeclaredHereNote(msg, param_ty); + break :msg msg; + }); + } + } + // Check that the return type is extern-compatible. + if (!ret_ty.validateExtern(.ret_ty, zcu)) { + const ret_ty_src: LazySrcLoc = if (maybe_func_decl_inst) |inst| .{ + .base_node_inst = inst, + .offset = .{ .node_offset_fn_type_ret_ty = .zero }, + } else src; + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(ret_ty_src, "return type '{f}' not allowed in function with calling convention '{t}'", .{ + ret_ty.fmt(pt), @"callconv", + }); + errdefer msg.destroy(gpa); + try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src, ret_ty, .ret_ty); + try sema.addDeclaredHereNote(msg, ret_ty); + break :msg msg; + }); + } + } +} + fn callConvIsCallable(cc: std.builtin.CallingConvention.Tag) bool { return switch (cc) { .naked, @@ -9022,6 +9082,7 @@ fn funcCommon( const io = comp.io; const ip = &zcu.intern_pool; + const src = block.nodeOffset(src_node_offset); const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = src_node_offset }); const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset }); @@ -9036,27 +9097,21 @@ fn funcCommon( .fn_proto_node_offset = src_node_offset, .param_index = @intCast(i), } }); - const param_ty_generic = param_ty.isGenericPoison(); if (param_is_comptime) { comptime_bits |= @as(u32, 1) << @intCast(i); // TODO: handle cast error } - if (param_is_comptime and !target_util.fnCallConvAllowsZigTypes(cc)) { - return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)}); - } - if (param_ty_generic and !target_util.fnCallConvAllowsZigTypes(cc)) { - return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)}); - } - try sema.checkParamTypeCommon( + try sema.checkParamType( block, @intCast(i), param_ty, + param_is_comptime, is_noalias, param_src, cc, ); } - try sema.checkReturnTypeAndCallConvCommon( + try sema.checkReturnTypeAndCallConv( block, bare_return_type, ret_ty_src, @@ -9072,9 +9127,29 @@ fn funcCommon( const param_types = block.params.items(.ty); + if (has_body) { + for (param_types, 0..) |param_ty_ip, param_index| { + const param_ty: Type = .fromInterned(param_ty_ip); + const param_src = block.src(.{ .fn_proto_param = .{ + .fn_proto_node_offset = src_node_offset, + .param_index = @intCast(param_index), + } }); + try sema.ensureLayoutResolved(param_ty, param_src, .parameter); + } + try sema.ensureLayoutResolved(bare_return_type, ret_ty_src, .return_type); + try sema.validateResolvedFuncType( + block, + cc, + param_types, + bare_return_type, + src, + ip.getNav(sema.owner.unwrap().nav_val).srcInst(ip), + ); + } + if (inferred_error_set) { assert(has_body); - const func_val: Value = .fromInterned(try ip.getFuncDeclIes(gpa, io, pt.tid, .{ + return .fromIntern(try ip.getFuncDeclIes(gpa, io, pt.tid, .{ .owner_nav = sema.owner.unwrap().nav_val, .param_types = param_types, @@ -9091,8 +9166,6 @@ fn funcCommon( .lbrace_column = @as(u16, @truncate(src_locs.columns)), .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)), })); - try sema.ensureLayoutResolved(func_val.typeOf(zcu), ret_ty_src, .return_type); - return .fromValue(func_val); } const func_ty = try ip.getFuncType(gpa, io, pt.tid, .{ @@ -9106,7 +9179,6 @@ fn funcCommon( }); if (has_body) { - try sema.ensureLayoutResolved(.fromInterned(func_ty), ret_ty_src, .return_type); return .fromIntern(try ip.getFuncDecl(gpa, io, pt.tid, .{ .owner_nav = sema.owner.unwrap().nav_val, .ty = func_ty, @@ -18256,19 +18328,6 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air } } else if (inst_data.size != .one and elem_ty.zigTypeTag(zcu) == .@"opaque") { return sema.fail(block, elem_ty_src, "indexable pointer to opaque type '{f}' not allowed", .{elem_ty.fmt(pt)}); - } else if (inst_data.size == .c) { - if (!elem_ty.validateExtern(.other, zcu)) { - const msg = msg: { - const msg = try sema.errMsg(elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{f}'", .{elem_ty.fmt(pt)}); - errdefer msg.destroy(sema.gpa); - - try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src, elem_ty, .other); - - try sema.addDeclaredHereNote(msg, elem_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); - } } if (host_size != 0) { @@ -19800,16 +19859,6 @@ fn zirReifyPointer( else => {}, } - if (size == .c and !elem_ty.validateExtern(.other, zcu)) { - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(src, "C pointers cannot point to non-C-ABI-compatible type '{f}'", .{elem_ty.fmt(pt)}); - errdefer msg.destroy(gpa); - try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src, elem_ty, .other); - try sema.addDeclaredHereNote(msg, elem_ty); - break :msg msg; - }); - } - const sentinel_ty = try pt.optionalType(elem_ty.toIntern()); const sentinel_uncoerced = sema.resolveInst(extra.sentinel); const sentinel_coerced = try sema.coerce(block, sentinel_ty, sentinel_uncoerced, sentinel_src); @@ -19898,10 +19947,11 @@ fn zirReifyFn( try param_attrs_arr.elemValue(pt, param_idx), std.builtin.Type.Fn.Param.Attributes, ); - try sema.checkParamTypeCommon( + try sema.checkParamType( block, @intCast(param_idx), param_ty, + false, param_attrs.@"noalias", param_types_src, fn_attrs.@"callconv", @@ -19919,7 +19969,7 @@ fn zirReifyFn( try sema.checkCallConvSupportsVarArgs(block, fn_attrs_src, fn_attrs.@"callconv"); } - try sema.checkReturnTypeAndCallConvCommon( + try sema.checkReturnTypeAndCallConv( block, ret_ty, ret_ty_src, @@ -19929,9 +19979,6 @@ fn zirReifyFn( false, false, ); - if (ret_ty.comptimeOnly(zcu)) { - return sema.fail(block, param_attrs_src, "cannot reify function type with comptime-only return type '{f}'", .{ret_ty.fmt(pt)}); - } return .fromIntern(try ip.getFuncType(gpa, io, pt.tid, .{ .param_types = param_types_ip, @@ -20615,7 +20662,7 @@ fn zirCVaArg(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C const va_list_ref = try sema.resolveVaListRef(block, va_list_src, extra.lhs); const arg_ty = try sema.resolveType(block, ty_src, extra.rhs); - + try sema.ensureLayoutResolved(arg_ty, ty_src, .parameter); if (!arg_ty.validateExtern(.param_ty, sema.pt.zcu)) { const msg = msg: { const msg = try sema.errMsg(ty_src, "cannot get '{f}' from variadic argument", .{arg_ty.fmt(sema.pt)}); @@ -24639,13 +24686,12 @@ fn zirBuiltinExtern( return sema.fail(block, ty_src, "expected (optional) pointer", .{}); } if (!ty.validateExtern(.other, zcu)) { - const msg = msg: { + return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(ty_src, "extern symbol cannot have type '{f}'", .{ty.fmt(pt)}); errdefer msg.destroy(sema.gpa); try sema.explainWhyTypeIsNotExtern(msg, ty_src, ty, .other); break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + }); } const options = try sema.resolveExternOptions(block, options_src, extra.rhs); @@ -25034,7 +25080,7 @@ pub fn explainWhyTypeIsNotExtern( src_loc: LazySrcLoc, ty: Type, position: Type.ExternPosition, -) CompileError!void { +) SemaError!void { const pt = sema.pt; const zcu = pt.zcu; switch (ty.zigTypeTag(zcu)) { diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig index 089ad64e254f28fc638980bf7c4533f95a8d9ec0..b3413ade051c6d1672117644e61ebf9397e7ee94 100644 --- a/src/Sema/type_resolution.zig +++ b/src/Sema/type_resolution.zig @@ -32,6 +32,7 @@ pub const LayoutResolveReason = enum { type_info, align_check, bit_ptr_child, + @"export", builtin_type, /// Written after string: "while resolving type 'T' " @@ -56,6 +57,7 @@ pub const LayoutResolveReason = enum { .type_info => "for type information query here", .align_check => "for alignment check here", .bit_ptr_child => "for bit size check here", + .@"export" => "for export here", .builtin_type => "from 'std.builtin'", // zig fmt: on }; @@ -276,7 +278,6 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { assert(!field_ty.isGenericPoison()); const field_ty_src = block.src(.{ .container_field_type = @intCast(field_index) }); try sema.ensureLayoutResolved(field_ty, field_ty_src, .field); - if (field_ty.zigTypeTag(zcu) == .@"opaque") { return sema.failWithOwnedErrorMsg(&block, msg: { const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in struct", .{field_ty.fmt(pt)}); @@ -286,7 +287,6 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { break :msg msg; }); } - if (struct_obj.layout == .@"extern" and !field_ty.validateExtern(.struct_field, zcu)) { return sema.failWithOwnedErrorMsg(&block, msg: { const msg = try sema.errMsg(field_ty_src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); diff --git a/src/Type.zig b/src/Type.zig index 234850376558acefd34b85a0ed43285945c6f60d..8c67ea975958712554e1711e3e9e409f745e91f5 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -3055,9 +3055,10 @@ pub const ExternPosition = enum { }; /// Returns true if `ty` is allowed in extern types. -/// Does not require `ty` to be resolved in any way. +/// Asserts that `ty` is fully resolved. /// Keep in sync with `Sema.explainWhyTypeIsNotExtern`. pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool { + ty.assertHasLayout(zcu); return switch (ty.zigTypeTag(zcu)) { .type, .comptime_float, -- 2.54.0 From 8d8140349fe2ea3197f8eea71cc120a0e8fa08d8 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Mon, 9 Feb 2026 10:39:31 +0000 Subject: [PATCH 35/79] simple little no-objection src/Type.zig correction --- src/Type.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Type.zig b/src/Type.zig index 8c67ea975958712554e1711e3e9e409f745e91f5..d7fffdf45a79df551d0ff9581e9de2646e90cc9e 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -2853,7 +2853,7 @@ pub fn fieldPtrType(ptr_ty: Type, field_index: u32, pt: Zcu.PerThread) Allocator else => parent_align.minStrict(.fromLog2Units(@ctz(field_offset))), }; const field_ptr_align: Alignment = a: { - if (parent_align == .none and + if (ptr_info.flags.alignment == .none and aggregate_ty.explicitFieldAlignment(field_index, zcu) == .none and actual_field_align == field_ty.abiAlignment(zcu)) { -- 2.54.0 From 09d0b1f87a740e968ef739e75729204ff470c98a Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Mon, 9 Feb 2026 10:41:56 +0000 Subject: [PATCH 36/79] behavior: misc fixes They compile now! They don't *pass*, but they *compile*! --- test/behavior/align.zig | 22 +++++++++++++++------- test/behavior/bitcast.zig | 3 --- test/behavior/call.zig | 11 +++++------ test/behavior/eval.zig | 7 ------- test/behavior/packed-struct.zig | 2 +- test/behavior/switch.zig | 11 +++++------ 6 files changed, 26 insertions(+), 30 deletions(-) diff --git a/test/behavior/align.zig b/test/behavior/align.zig index b971c78596d2ef0811c8041fa199d9d387492ed3..2cbde2d56c7a72f770b6dc6d9915df05bb81f1d1 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -307,11 +307,15 @@ test "runtime-known array index has best alignment possible" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // take full advantage of over-alignment - var array align(4) = [_]u8{ 1, 2, 3, 4 }; + var array align(4) = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 }; comptime assert(@TypeOf(&array[0]) == *align(4) u8); - comptime assert(@TypeOf(&array[1]) == *u8); + comptime assert(@TypeOf(&array[1]) == *align(1) u8); comptime assert(@TypeOf(&array[2]) == *align(2) u8); - comptime assert(@TypeOf(&array[3]) == *u8); + comptime assert(@TypeOf(&array[3]) == *align(1) u8); + comptime assert(@TypeOf(&array[4]) == *align(4) u8); + comptime assert(@TypeOf(&array[5]) == *align(1) u8); + comptime assert(@TypeOf(&array[6]) == *align(2) u8); + comptime assert(@TypeOf(&array[7]) == *align(1) u8); // because align is too small but we still figure out to use 2 var bigger align(2) = [_]u64{ 1, 2, 3, 4 }; @@ -332,10 +336,14 @@ test "runtime-known array index has best alignment possible" { try testIndex(smaller[runtime_zero..].ptr, 3, *align(2) u32); // has to use ABI alignment because index known at runtime only - try testIndex2(&array, 0, *u8); - try testIndex2(&array, 1, *u8); - try testIndex2(&array, 2, *u8); - try testIndex2(&array, 3, *u8); + try testIndex2(&array, 0, *align(1) u8); + try testIndex2(&array, 1, *align(1) u8); + try testIndex2(&array, 2, *align(1) u8); + try testIndex2(&array, 3, *align(1) u8); + try testIndex2(&array, 4, *align(1) u8); + try testIndex2(&array, 5, *align(1) u8); + try testIndex2(&array, 6, *align(1) u8); + try testIndex2(&array, 7, *align(1) u8); } fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) !void { comptime assert(@TypeOf(&smaller[index]) == T); diff --git a/test/behavior/bitcast.zig b/test/behavior/bitcast.zig index 90d185c63f52d6c013564f629d61ba9cdbbc202f..910356e3608f50f60873d7e565f027c5dce041ed 100644 --- a/test/behavior/bitcast.zig +++ b/test/behavior/bitcast.zig @@ -350,9 +350,6 @@ test "comptime @bitCast packed struct to int and back" { iint_neg2: i3 = -2, float: f32 = 3.14, @"enum": enum(u2) { A, B = 1, C, D } = .B, - vectorb: @Vector(3, bool) = .{ true, false, true }, - vectori: @Vector(2, u8) = .{ 127, 42 }, - vectorf: @Vector(2, f16) = .{ 3.14, 2.71 }, }; const Int = @typeInfo(S).@"struct".backing_integer.?; diff --git a/test/behavior/call.zig b/test/behavior/call.zig index 3433cc59712750f434f33f9112c68846126020e0..fd134499439cc8fd647aac316e5f2e6f3e2de910 100644 --- a/test/behavior/call.zig +++ b/test/behavior/call.zig @@ -551,19 +551,18 @@ test "generic function pointer can be called" { test "value returned from comptime function is comptime known" { const S = struct { - fn fields(comptime T: type) switch (@typeInfo(T)) { - .@"struct" => []const std.builtin.Type.StructField, + fn fieldCount(comptime T: type) switch (@typeInfo(T)) { + .@"struct" => comptime_int, else => unreachable, } { return switch (@typeInfo(T)) { - .@"struct" => |info| info.fields, + .@"struct" => |info| info.fields.len, else => unreachable, }; } }; - const fields_list = S.fields(@TypeOf(.{})); - if (fields_list.len != 0) - @compileError("Argument count mismatch"); + const fields_len = S.fieldCount(@TypeOf(.{})); + comptime assert(fields_len == 0); } test "registers get overwritten when ignoring return" { diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig index 9e3cd732f0e3b41152fbbb51732283bbe9c07192..03550fef70d73da7b334842a25ed383d8867cc8b 100644 --- a/test/behavior/eval.zig +++ b/test/behavior/eval.zig @@ -719,13 +719,6 @@ fn testVarInsideInlineLoop(args: anytype) !void { } } -test "*align(1) u16 is the same as *align(1:0:2) u16" { - comptime { - try expect(*align(1:0:2) u16 == *align(1) u16); - try expect(*align(2:0:2) u16 == *u16); - } -} - test "array concatenation of function calls" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO diff --git a/test/behavior/packed-struct.zig b/test/behavior/packed-struct.zig index 1b019acb7243acaa2ccb0896b766666fabd6e83f..d5b01f7c12f71ac5e88976a4d50587ffc460a857 100644 --- a/test/behavior/packed-struct.zig +++ b/test/behavior/packed-struct.zig @@ -820,7 +820,7 @@ test "packed struct passed to callconv(.c) function" { if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { - const Packed = packed struct { + const Packed = packed struct(u64) { a: u16, b: bool = true, c: bool = true, diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig index 316421ea3603c98f9a6313ca3c9f60a39a5302f7..784305bca786a054dd19d32fa97f58087635818f 100644 --- a/test/behavior/switch.zig +++ b/test/behavior/switch.zig @@ -645,7 +645,7 @@ test "switch prong pointer capture alignment" { } switch (u) { - .a, .c => |*p| comptime assert(@TypeOf(p) == *const u8), + .a, .c => |*p| comptime assert(@TypeOf(p) == *align(1) const u8), .b => |*p| { _ = p; return error.TestFailed; @@ -1141,24 +1141,23 @@ test "decl literals as switch cases" { try comptime E.doTheTest(.foo); } -// TODO audit after #15909 and/or #19855 are decided/implemented +// TODO audit after #15909 and/or #19855 are decided/implemented. +// When we do that, consider adding an 'error{}' case if possible. test "switch with uninstantiable union fields" { const U = union(enum) { ok: void, a: noreturn, b: noreturn, - c: error{}, fn doTheTest(u: @This()) void { switch (u) { .ok => {}, .a => comptime unreachable, .b => comptime unreachable, - .c => comptime unreachable, } switch (u) { .ok => {}, - .a, .b, .c => comptime unreachable, + .a, .b => comptime unreachable, } switch (u) { .ok => {}, @@ -1166,7 +1165,7 @@ test "switch with uninstantiable union fields" { } switch (u) { .a => comptime unreachable, - .ok, .b, .c => {}, + .ok, .b => {}, } } }; -- 2.54.0 From b00ef1aea1a456ad8b175534add8bb324cb39bba Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Mon, 9 Feb 2026 11:23:46 +0000 Subject: [PATCH 37/79] Zcu: prevent data races from `Type.assertHasLayout` --- src/Type.zig | 12 ++---- src/Zcu.zig | 87 +++++++++++++++++++++++++++++++++++++++---- src/Zcu/PerThread.zig | 34 +++++------------ 3 files changed, 91 insertions(+), 42 deletions(-) diff --git a/src/Type.zig b/src/Type.zig index d7fffdf45a79df551d0ff9581e9de2646e90cc9e..0fe87e983b065cb43124eb1b6adc5b7c0a4888cd 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -3175,21 +3175,15 @@ pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void { }, .struct_type => { assert(zcu.intern_pool.loadStructType(ty.toIntern()).want_layout); - const unit: InternPool.AnalUnit = .wrap(.{ .type_layout = ty.toIntern() }); - assert(!zcu.outdated.contains(unit)); - assert(!zcu.potentially_outdated.contains(unit)); + zcu.assertUpToDate(.wrap(.{ .type_layout = ty.toIntern() })); }, .union_type => { assert(zcu.intern_pool.loadUnionType(ty.toIntern()).want_layout); - const unit: InternPool.AnalUnit = .wrap(.{ .type_layout = ty.toIntern() }); - assert(!zcu.outdated.contains(unit)); - assert(!zcu.potentially_outdated.contains(unit)); + zcu.assertUpToDate(.wrap(.{ .type_layout = ty.toIntern() })); }, .enum_type => { assert(zcu.intern_pool.loadEnumType(ty.toIntern()).want_layout); - const unit: InternPool.AnalUnit = .wrap(.{ .type_layout = ty.toIntern() }); - assert(!zcu.outdated.contains(unit)); - assert(!zcu.potentially_outdated.contains(unit)); + zcu.assertUpToDate(.wrap(.{ .type_layout = ty.toIntern() })); }, // values, not types diff --git a/src/Zcu.zig b/src/Zcu.zig index fc770ba4ea1924d34d238e8bb13fd3107332a1ec..4e48ff694602c4fb3833e9b133279aea76aa588d 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -264,6 +264,10 @@ cimport_errors: std.AutoArrayHashMapUnmanaged(AnalUnit, std.zig.ErrorBundle) = . /// Maximum amount of distinct error values, set by --error-limit error_limit: ErrorInt, +/// In safe builds, `Type.assertHasLayout` may be called cross-thread, so this lock +/// guards accesses to `outdated` and `potentially_outdated`. In unsafe builds, the +/// lock is not needed and is compiled out. +outdated_lock: if (std.debug.runtime_safety) std.Io.RwLock else void = if (std.debug.runtime_safety) .init, /// Value is the number of PO dependencies of this AnalUnit. /// This value will decrease as we perform semantic analysis to learn what is outdated. /// If any of these PO deps is outdated, this value will be moved to `outdated`. @@ -3063,6 +3067,8 @@ pub fn markDependeeOutdated( ) !void { deps_log.debug("outdated dependee: {f}", .{zcu.fmtDependee(dependee)}); var it = zcu.intern_pool.dependencyIterator(dependee); + if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); + defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(zcu.comp.io); while (it.next()) |depender| { if (zcu.outdated.getPtr(depender)) |po_dep_count| { switch (marked_po) { @@ -3107,6 +3113,12 @@ pub fn markDependeeOutdated( } pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { + if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); + defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(zcu.comp.io); + return markPoDependeeUpToDateInner(zcu, dependee); +} +/// Assumes that `zcu.outdated_lock` is already held exclusively. +fn markPoDependeeUpToDateInner(zcu: *Zcu, dependee: InternPool.Dependee) !void { deps_log.debug("up-to-date dependee: {f}", .{zcu.fmtDependee(dependee)}); var it = zcu.intern_pool.dependencyIterator(dependee); while (it.next()) |depender| { @@ -3142,17 +3154,19 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { // as no longer PO. switch (depender.unwrap()) { .@"comptime" => {}, - .nav_val => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_val = nav }), - .nav_ty => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav }), - .type_layout => |ty| try zcu.markPoDependeeUpToDate(.{ .type_layout = ty }), - .func => |func| try zcu.markPoDependeeUpToDate(.{ .func_ies = func }), - .memoized_state => |stage| try zcu.markPoDependeeUpToDate(.{ .memoized_state = stage }), + .nav_val => |nav| try zcu.markPoDependeeUpToDateInner(.{ .nav_val = nav }), + .nav_ty => |nav| try zcu.markPoDependeeUpToDateInner(.{ .nav_ty = nav }), + .type_layout => |ty| try zcu.markPoDependeeUpToDateInner(.{ .type_layout = ty }), + .func => |func| try zcu.markPoDependeeUpToDateInner(.{ .func_ies = func }), + .memoized_state => |stage| try zcu.markPoDependeeUpToDateInner(.{ .memoized_state = stage }), } } } /// Given a AnalUnit which is newly outdated or PO, mark all AnalUnits which may /// in turn be PO, due to a dependency on the original AnalUnit's tyval or IES. +/// +/// Assumes that `zcu.outdated_lock` is already held exclusively. fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUnit) !void { const ip = &zcu.intern_pool; const dependee: InternPool.Dependee = switch (maybe_outdated.unwrap()) { @@ -3211,6 +3225,9 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { // possible situation is a cycle where everything is actually up-to-date, so we can clear out // `zcu.potentially_outdated` and we are done. + if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); + defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(zcu.comp.io); + if (zcu.outdated.count() == 0) { // Everything is up-to-date. There could be lingering entries in `zcu.potentially_outdated` // from a dependency loop on a previous update. @@ -3230,7 +3247,10 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { /// During an incremental update, before semantic analysis, call this to flush all values from /// `retryable_failures` and mark them as outdated so they get re-analyzed. pub fn flushRetryableFailures(zcu: *Zcu) !void { - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; + if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(comp.io); + defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(comp.io); for (zcu.retryable_failures.items) |depender| { if (zcu.outdated.contains(depender)) continue; if (zcu.potentially_outdated.fetchSwapRemove(depender)) |kv| { @@ -3481,8 +3501,12 @@ pub fn ensureFuncBodyAnalysisQueued(zcu: *Zcu, func: InternPool.Index) !void { if (ip.setWantRuntimeFnAnalysis(io, func)) { // This is the first reference to this function, so we must ensure it will be analyzed. const unit: AnalUnit = .wrap(.{ .func = func }); - try zcu.outdated.putNoClobber(gpa, unit, 0); - try zcu.outdated_ready.putNoClobber(gpa, unit, {}); + if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); + defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(zcu.comp.io); + try zcu.outdated.ensureUnusedCapacity(gpa, 1); + try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); + zcu.outdated.putAssumeCapacityNoClobber(unit, 0); + zcu.outdated_ready.putAssumeCapacityNoClobber(unit, {}); } } @@ -3493,6 +3517,8 @@ pub fn ensureNavValAnalysisQueued(zcu: *Zcu, nav: InternPool.Nav.Index) !void { const ip = &zcu.intern_pool; if (ip.setWantNavAnalysis(io, nav)) { // This is the first reference to this function, so we must ensure it will be analyzed. + if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); + defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(zcu.comp.io); try zcu.outdated.ensureUnusedCapacity(gpa, 2); try zcu.outdated_ready.ensureUnusedCapacity(gpa, 2); zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .nav_val = nav }), 0); @@ -3502,6 +3528,51 @@ pub fn ensureNavValAnalysisQueued(zcu: *Zcu, nav: InternPool.Nav.Index) !void { } } +/// Called when an `InternPool.ComptimeUnit` is first created to mark it as outdated so that it will +/// be semantically analyzed. +pub fn queueComptimeUnitAnalysis(zcu: *Zcu, cu: InternPool.ComptimeUnit.Id) Allocator.Error!void { + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + const unit: AnalUnit = .wrap(.{ .@"comptime" = cu }); + if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(io); + defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(io); + try zcu.outdated.ensureUnusedCapacity(gpa, 1); + try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); + zcu.outdated.putAssumeCapacityNoClobber(unit, 0); + zcu.outdated_ready.putAssumeCapacityNoClobber(unit, {}); +} + +/// If `unit` was marked as outdated or porentially outdated, clears that status and returns `true`. +/// Otherwise, returns `false`. +pub fn clearOutdatedState(zcu: *Zcu, unit: AnalUnit) bool { + const io = zcu.comp.io; + if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(io); + defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(io); + if (zcu.outdated.fetchSwapRemove(unit)) |kv| { + if (kv.value == 0) assert(zcu.outdated_ready.swapRemove(unit)); + return true; + } else if (zcu.potentially_outdated.swapRemove(unit)) { + return true; + } else { + return false; + } +} + +/// This function takes a `*const Zcu` and `@constCast`s it so that it can be called from functions +/// in `Type` which otherwise do not modify the `Zcu`. +pub fn assertUpToDate(zcu: *const Zcu, unit: AnalUnit) void { + if (!std.debug.runtime_safety) return; + + const io = zcu.comp.io; + + @constCast(zcu).outdated_lock.lockSharedUncancelable(io); + defer @constCast(zcu).outdated_lock.unlockShared(io); + + assert(!zcu.outdated.contains(unit)); + assert(!zcu.potentially_outdated.contains(unit)); +} + pub const ImportResult = struct { /// Whether `file` has been newly created; in other words, whether this is the first import of /// this file. This should only be `true` when importing files during AstGen. After that, all diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index b9ad8f3dfdd1375df0606f538d6ecdeb72abec82..194b6fd283a8f33755c3a83c4494bb9363d7b794 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -746,12 +746,11 @@ pub fn ensureMemoizedStateUpToDate( assert(!zcu.analysis_in_progress.contains(unit)); - const was_outdated = zcu.outdated.swapRemove(unit) or zcu.potentially_outdated.swapRemove(unit); + const was_outdated = zcu.clearOutdatedState(unit); const prev_failed = zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit); if (was_outdated) { dev.check(.incremental); - _ = zcu.outdated_ready.swapRemove(unit); zcu.resetUnit(unit); } else { if (prev_failed) return error.AnalysisFail; @@ -866,11 +865,9 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU // result in over-analysis if analysis occurs in a poor order; we do our best to avoid this by // carefully choosing which units to re-analyze. See `Zcu.findOutdatedToAnalyze`. - const was_outdated = zcu.outdated.swapRemove(anal_unit) or - zcu.potentially_outdated.swapRemove(anal_unit); + const was_outdated = zcu.clearOutdatedState(anal_unit); if (was_outdated) { - _ = zcu.outdated_ready.swapRemove(anal_unit); // `was_outdated` can be true in the initial update for comptime units, so this isn't a `dev.check`. if (dev.env.supports(.incremental)) { zcu.resetUnit(anal_unit); @@ -1023,12 +1020,10 @@ pub fn ensureTypeLayoutUpToDate( assert(!zcu.analysis_in_progress.contains(anal_unit)); - const was_outdated = zcu.outdated.swapRemove(anal_unit) or - zcu.potentially_outdated.swapRemove(anal_unit) or + const was_outdated = zcu.clearOutdatedState(anal_unit) or zcu.intern_pool.setWantTypeLayout(zcu.comp.io, ty.toIntern()); if (was_outdated) { - _ = zcu.outdated_ready.swapRemove(anal_unit); // `was_outdated` is true in the initial update, so this isn't a `dev.check`. if (dev.env.supports(.incremental)) { zcu.resetUnit(anal_unit); @@ -1139,15 +1134,13 @@ pub fn ensureNavValUpToDate( // result in over-analysis if analysis occurs in a poor order; we do our best to avoid this by // carefully choosing which units to re-analyze. See `Zcu.findOutdatedToAnalyze`. - const was_outdated = zcu.outdated.swapRemove(anal_unit) or - zcu.potentially_outdated.swapRemove(anal_unit); + const was_outdated = zcu.clearOutdatedState(anal_unit); const prev_failed = zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit); if (was_outdated) { dev.check(.incremental); - _ = zcu.outdated_ready.swapRemove(anal_unit); zcu.resetUnit(anal_unit); } else { // We can trust the current information about this unit. @@ -1497,15 +1490,13 @@ pub fn ensureNavTypeUpToDate( // result in over-analysis if analysis occurs in a poor order; we do our best to avoid this by // carefully choosing which units to re-analyze. See `Zcu.findOutdatedToAnalyze`. - const was_outdated = zcu.outdated.swapRemove(anal_unit) or - zcu.potentially_outdated.swapRemove(anal_unit); + const was_outdated = zcu.clearOutdatedState(anal_unit); const prev_failed = zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit); if (was_outdated) { dev.check(.incremental); - _ = zcu.outdated_ready.swapRemove(anal_unit); zcu.resetUnit(anal_unit); } else { // We can trust the current information about this unit. @@ -1733,15 +1724,13 @@ pub fn ensureFuncBodyUpToDate( assert(func.ty == func.uncoerced_ty); // analyze the body of the original function, not a coerced one - const was_outdated = zcu.outdated.swapRemove(anal_unit) or - zcu.potentially_outdated.swapRemove(anal_unit) or + const was_outdated = zcu.clearOutdatedState(anal_unit) or ip.setWantRuntimeFnAnalysis(zcu.comp.io, func_index); const prev_failed = zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit); if (was_outdated) { dev.check(.incremental); - _ = zcu.outdated_ready.swapRemove(anal_unit); zcu.resetUnit(anal_unit); } else { // We can trust the current information about this function. @@ -2712,27 +2701,22 @@ const ScanDeclIter = struct { const existing_unit = iter.existing_by_inst.get(tracked_inst); - const unit, const want_analysis = switch (decl.kind) { + const unit: AnalUnit, const want_analysis = switch (decl.kind) { .@"comptime" => unit: { const cu = if (existing_unit) |eu| eu.unwrap().@"comptime" else try ip.createComptimeUnit(gpa, io, pt.tid, tracked_inst, namespace_index); - const unit: AnalUnit = .wrap(.{ .@"comptime" = cu }); - try namespace.comptime_decls.append(gpa, cu); if (existing_unit == null) { // For a `comptime` declaration, whether to analyze is based solely on whether the unit // is outdated. So, add this fresh one to `outdated` and `outdated_ready`. - try zcu.outdated.ensureUnusedCapacity(gpa, 1); - try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); - zcu.outdated.putAssumeCapacityNoClobber(unit, 0); - zcu.outdated_ready.putAssumeCapacityNoClobber(unit, {}); + try zcu.queueComptimeUnitAnalysis(cu); } - break :unit .{ unit, true }; + break :unit .{ .wrap(.{ .@"comptime" = cu }), true }; }, else => unit: { const name = maybe_name.unwrap().?; -- 2.54.0 From 774911b4ce6c1aef44b33aee90ca341ab2fe669d Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Wed, 11 Feb 2026 14:57:23 +0000 Subject: [PATCH 38/79] behavior: small tweaks for new semantics --- test/behavior/align.zig | 34 +++++++++++++++++++++++++++++++--- test/behavior/generics.zig | 5 +---- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/test/behavior/align.zig b/test/behavior/align.zig index 2cbde2d56c7a72f770b6dc6d9915df05bb81f1d1..a59bed56ba8c4e46892b25ca834cf7f45e54ec21 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -30,13 +30,41 @@ test "slicing array of length 1 can not assume runtime index is always zero" { var runtime_index: usize = 1; _ = &runtime_index; const slice = @as(*align(4) [1]u8, &foo)[runtime_index..]; - try expect(@TypeOf(slice) == []u8); + try expect(@TypeOf(slice) == []align(1) u8); try expect(slice.len == 0); try expect(@as(u2, @truncate(@intFromPtr(slice.ptr) - 1)) == 0); } -test "default alignment allows unspecified in type syntax" { - try expect(*u32 == *align(@alignOf(u32)) u32); +test "implicitly-aligned pointer is coercible to equivalent explicitly-aligned pointer" { + const A = *u32; + const B = *align(@alignOf(u32)) u32; + + comptime assert(A != B); + + const static = struct { + fn doTheTest() !void { + var buf: u32 = 123; + + const ptr: A = &buf; + const coerced_ptr: B = ptr; + + try expect(ptr == coerced_ptr); + try expect(ptr.* == 123); + try expect(coerced_ptr.* == 123); + + const ptr_ptr: *const A = &ptr; + const coerced_ptr_ptr: *const B = ptr_ptr; + + try expect(ptr_ptr == coerced_ptr_ptr); + try expect(ptr_ptr.* == &buf); + try expect(coerced_ptr_ptr.* == &buf); + try expect(ptr_ptr.*.* == 123); + try expect(coerced_ptr_ptr.*.* == 123); + } + }; + + try static.doTheTest(); + try comptime static.doTheTest(); } test "implicitly decreasing pointer alignment" { diff --git a/test/behavior/generics.zig b/test/behavior/generics.zig index 65a5a1b0070fa81c60774de2686f0b215f95f5ca..89ff5764a88bc2428ec76312e7702b6bf558fd11 100644 --- a/test/behavior/generics.zig +++ b/test/behavior/generics.zig @@ -339,7 +339,7 @@ test "generic instantiation of tagged union with only one field" { try expect(S.foo(.{ .s = "ab" }) == 2); } -test "nested generic function" { +test "generic parameter type is function type" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = struct { @@ -349,10 +349,7 @@ test "nested generic function" { fn bar(a: u32) anyerror!void { try expect(a == 123); } - - fn g(_: *const fn (anytype) void) void {} }; - try expect(@typeInfo(@TypeOf(S.g)).@"fn".is_generic); try S.foo(u32, S.bar, 123); } -- 2.54.0 From 7170e0f02043d157cb4e10c6333e125c10395a63 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Wed, 11 Feb 2026 14:57:59 +0000 Subject: [PATCH 39/79] Sema: small fixes --- src/Sema.zig | 54 ++++++++++++++++++++++++------------ src/Sema/type_resolution.zig | 4 +-- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index d5aef143392ca4cceefec718c4c9acb1bbf3c7a2..81bce68e682a19a2d1895b5d2e7ce6af6c6ad820 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -15263,17 +15263,29 @@ fn analyzeArithmetic( if (zir_tag != .sub) { return sema.failWithInvalidPtrArithmetic(block, src, "pointer-pointer", "subtraction"); } - if (!lhs_ty.childType(zcu).eql(rhs_ty.childType(zcu), zcu)) { + + // MLUGG TODO: these semantics are insane and matching them is causing my soul to fragment into a thousand pieces + const lhs_elem_ty = ty: { + const ptr_elem_ty = lhs_ty.childType(zcu); + if (lhs_ty.ptrSize(zcu) == .one and ptr_elem_ty.isArrayOrVector(zcu)) break :ty ptr_elem_ty.childType(zcu); + break :ty ptr_elem_ty; + }; + const rhs_elem_ty = ty: { + const ptr_elem_ty = rhs_ty.childType(zcu); + if (rhs_ty.ptrSize(zcu) == .one and ptr_elem_ty.isArrayOrVector(zcu)) break :ty ptr_elem_ty.childType(zcu); + break :ty ptr_elem_ty; + }; + if (lhs_elem_ty.toIntern() != rhs_elem_ty.toIntern()) { return sema.fail(block, src, "incompatible pointer arithmetic operands '{f}' and '{f}'", .{ lhs_ty.fmt(pt), rhs_ty.fmt(pt), }); } - try sema.ensureLayoutResolved(lhs_ty.childType(zcu), src, .ptr_offset); - const elem_size = lhs_ty.childType(zcu).abiSize(zcu); + try sema.ensureLayoutResolved(lhs_elem_ty, src, .ptr_offset); + const elem_size = lhs_elem_ty.abiSize(zcu); if (elem_size == 0) { return sema.fail(block, src, "pointer subtraction requires element type '{f}' to have runtime bits", .{ - lhs_ty.childType(zcu).fmt(pt), + lhs_elem_ty.fmt(pt), }); } @@ -16293,20 +16305,24 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const func_ty_info = zcu.typeToFunc(ty).?; const param_vals = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len); var func_is_generic = false; - for (param_vals, 0..) |*param_val, i| { - const param_ty = func_ty_info.param_types.get(ip)[i]; + + for (param_vals, 0..) |*param_val, param_index| { + const param_ty = func_ty_info.param_types.get(ip)[param_index]; const is_generic = param_ty == .generic_poison_type; - if (is_generic or Type.fromInterned(param_ty).comptimeOnly(zcu)) func_is_generic = true; + const is_noalias, const is_comptime = flags: { + const i = std.math.cast(u5, param_index) orelse break :flags .{ false, false }; + break :flags .{ func_ty_info.paramIsNoalias(i), func_ty_info.paramIsComptime(i) }; + }; + + if (is_generic or is_comptime or Type.fromInterned(param_ty).comptimeOnly(zcu)) { + func_is_generic = true; + } + const param_ty_val = try pt.intern(.{ .opt = .{ .ty = try pt.intern(.{ .opt_type = .type_type }), .val = if (is_generic) .none else param_ty, } }); - const is_noalias = blk: { - const index = std.math.cast(u5, i) orelse break :blk false; - break :blk @as(u1, @truncate(func_ty_info.noalias_bits >> index)) != 0; - }; - const param_fields = .{ // is_generic: bool, Value.makeBool(is_generic).toIntern(), @@ -16348,15 +16364,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const ret_ty_is_generic = generic: { const ret_ty: Type = .fromInterned(func_ty_info.return_type); - if (ret_ty.toIntern() == .generic_poison_type) break :generic true; - if (ret_ty.zigTypeTag(zcu) == .error_union) { - if (ret_ty.errorUnionPayload(zcu).toIntern() == .generic_poison_type) { - break :generic true; - } + if (ret_ty.toIntern() == .generic_poison_type or + (ret_ty.zigTypeTag(zcu) == .error_union and + ret_ty.errorUnionPayload(zcu).toIntern() == .generic_poison_type)) + { + break :generic true; } break :generic false; }; - if (ret_ty_is_generic) func_is_generic = true; + if (ret_ty_is_generic or Type.fromInterned(func_ty_info.return_type).comptimeOnly(zcu)) { + func_is_generic = true; + } const ret_ty_opt = try pt.intern(.{ .opt = .{ .ty = try pt.intern(.{ .opt_type = .type_type }), diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig index b3413ade051c6d1672117644e61ebf9397e7ee94..5e4e8a4ccd84e8080f71162262560a934977b34f 100644 --- a/src/Sema/type_resolution.zig +++ b/src/Sema/type_resolution.zig @@ -585,8 +585,8 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { .int_tag_mode = switch (union_obj.is_reified) { true => .auto, false => switch (sema.code.getUnionDecl(zir_index).kind) { - .tagged_enum_explicit => .auto, - else => .explicit, + .tagged_enum_explicit => .explicit, + else => .auto, }, }, .fields_len = @intCast(union_obj.field_types.len), -- 2.54.0 From bcb1a6bdf3ef1f39784298deaf2adfb91ea5c5c1 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Wed, 11 Feb 2026 15:05:33 +0000 Subject: [PATCH 40/79] compiler: make Dwarf and self-hosted x86_64 happy Introduces a small abstraction, `link.DebugConstPool`, to deal with lowering type/value information into debug info when it may not be known until type resolution (which in some cases will *never* happen). It is currently only used by self-hosted DWARF logic, but it will also be of use to the LLVM backend (which is my next focus). --- src/Compilation.zig | 75 +- src/Zcu/PerThread.zig | 492 +---------- src/codegen.zig | 37 +- src/link.zig | 46 +- src/link/DebugConstPool.zig | 287 +++++++ src/link/Dwarf.zig | 1544 +++++++++++++++-------------------- src/link/Elf.zig | 3 +- src/link/Elf/ZigObject.zig | 3 +- 8 files changed, 1026 insertions(+), 1461 deletions(-) create mode 100644 src/link/DebugConstPool.zig diff --git a/src/Compilation.zig b/src/Compilation.zig index 59fa186d82804de016b8f5c241976992b70c3174..66483ebd727709e21a586c354137269303b8cd3a 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -956,8 +956,7 @@ pub const RcSourceFile = struct { const Job = union(enum) { /// Given the generated AIR for a function, put it onto the code generation queue. - /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that - /// all types are resolved before the linker task is queued. + /// MLUGG TODO: because type resolution is no longer necessary, we can remove this now /// If the backend does not support `Zcu.Feature.separate_thread`, codegen and linking happen immediately. /// Before queueing this `Job`, increase the estimated total item count for both /// `comp.zcu.?.codegen_prog_node` and `comp.link_prog_node`. @@ -967,17 +966,10 @@ const Job = union(enum) { air: Air, }, /// Queue a `link.ZcuTask` to emit this non-function `Nav` into the output binary. - /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that - /// all types are resolved before the linker task is queued. + /// MLUGG TODO: because type resolution is no longer necessary, we can remove this now /// If the backend does not support `Zcu.Feature.separate_thread`, the task is run immediately. /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`. link_nav: InternPool.Nav.Index, - /// Queue a `link.ZcuTask` to emit debug information for this container type. - /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that - /// all types are resolved before the linker task is queued. - /// If the backend does not support `Zcu.Feature.separate_thread`, the task is run immediately. - /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`. - link_type: InternPool.Index, /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`. update_line_number: InternPool.TrackedInst.Index, /// The `AnalUnit`, which is *not* a `func`, must be semantically analyzed. @@ -5058,26 +5050,6 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v var owned_air: ?Air = func.air; defer if (owned_air) |*air| air.deinit(gpa); - { - const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid)); - defer pt.deactivate(); - pt.resolveAirTypesForCodegen(&owned_air.?) catch |err| switch (err) { - error.OutOfMemory, - error.Canceled, - => |e| return e, - - error.AnalysisFail => { - // Type resolution failed, making codegen of this function impossible. This - // is a transitive failure, but it doesn't need recording, because this - // function semantically depends on the failed type, so when it is changed - // the function will be updated. - zcu.codegen_prog_node.completeOne(); - comp.link_prog_node.completeOne(); - return; - }, - }; - } - // Some linkers need to refer to the AIR. In that case, the linker is not running // concurrently, so we'll just keep ownership of the AIR for ourselves instead of // letting the codegen job destroy it. @@ -5101,51 +5073,10 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v } } assert(nav.status == .fully_resolved); - { - const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid)); - defer pt.deactivate(); - pt.resolveValueTypesForCodegen(zcu.navValue(nav_index)) catch |err| switch (err) { - error.OutOfMemory, - error.Canceled, - => |e| return e, - - error.AnalysisFail => { - // Type resolution failed, making codegen of this `Nav` impossible. This is - // a transitive failure, but it doesn't need recording, because this `Nav` - // semantically depends on the failed type, so when it is changed the value - // of the `Nav` will be updated. - comp.link_prog_node.completeOne(); - return; - }, - }; - } try comp.link_queue.enqueueZcu(comp, tid, .{ .link_nav = nav_index }); }, - .link_type => |ty| { - const zcu = comp.zcu.?; - if (zcu.failed_types.fetchSwapRemove(ty)) |*entry| entry.value.deinit(zcu.gpa); - { - const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid)); - defer pt.deactivate(); - pt.resolveTypeForCodegen(.fromInterned(ty)) catch |err| switch (err) { - error.OutOfMemory, - error.Canceled, - => |e| return e, - - error.AnalysisFail => { - // Type resolution failed, making codegen of this type impossible. This is - // a transitive failure, but it doesn't need recording, because this type - // semantically depends on the failed type, so when it is changed the type - // will be updated appropriately. - comp.link_prog_node.completeOne(); - return; - }, - }; - } - try comp.link_queue.enqueueZcu(comp, tid, .{ .link_type = ty }); - }, .update_line_number => |tracked_inst| { - try comp.link_queue.enqueueZcu(comp, tid, .{ .update_line_number = tracked_inst }); + try comp.link_queue.enqueueZcu(comp, tid, .{ .debug_update_line_number = tracked_inst }); }, .analyze_unit => |unit| { const tracy_trace = traceNamed(@src(), "analyze_unit"); diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 194b6fd283a8f33755c3a83c4494bb9363d7b794..babf66ee720fe48fbb8d8d46ab5cd85344229318 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -998,10 +998,10 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu try sema.flushExports(); } -/// Ensures that the layout of the given `struct` or `union` type is fully up-to-date, performing -/// re-analysis if necessary. Asserts that `ty` is a struct (not a tuple!) or union. Returns -/// `error.AnalysisFail` if an analysis error is encountered during type resolution; the caller is -/// free to ignore this, since the error is already registered. +/// Ensures that the layout of the given `struct`, `union`, or `enum` type is fully up-to-date, +/// performing re-analysis if necessary. Asserts that `ty` is a struct (not a tuple!), union, or +/// enum type. Returns `error.AnalysisFail` if an analysis error is encountered during type +/// resolution; the caller is free to ignore this, since the error is already registered. pub fn ensureTypeLayoutUpToDate( pt: Zcu.PerThread, ty: Type, @@ -1012,7 +1012,8 @@ pub fn ensureTypeLayoutUpToDate( defer tracy.end(); const zcu = pt.zcu; - const gpa = zcu.gpa; + const comp = zcu.comp; + const gpa = comp.gpa; const anal_unit: AnalUnit = .wrap(.{ .type_layout = ty.toIntern() }); @@ -1021,7 +1022,7 @@ pub fn ensureTypeLayoutUpToDate( assert(!zcu.analysis_in_progress.contains(anal_unit)); const was_outdated = zcu.clearOutdatedState(anal_unit) or - zcu.intern_pool.setWantTypeLayout(zcu.comp.io, ty.toIntern()); + zcu.intern_pool.setWantTypeLayout(comp.io, ty.toIntern()); if (was_outdated) { // `was_outdated` is true in the initial update, so this isn't a `dev.check`. @@ -1038,7 +1039,7 @@ pub fn ensureTypeLayoutUpToDate( return; } - if (zcu.comp.debugIncremental()) { + if (comp.debugIncremental()) { const info = try zcu.incremental_debug_state.getUnitInfo(gpa, anal_unit); info.last_update_gen = zcu.generation; info.deps.clearRetainingCapacity(); @@ -1078,15 +1079,17 @@ pub fn ensureTypeLayoutUpToDate( .@"union" => Sema.type_resolution.resolveUnionLayout(&sema, ty), else => unreachable, }; - result catch |err| switch (err) { - error.AnalysisFail => { + const new_success: bool = if (result) s: { + break :s true; + } else |err| switch (err) { + error.AnalysisFail => success: { if (!zcu.failed_analysis.contains(anal_unit)) { // If this unit caused the error, it would have an entry in `failed_analysis`. // Since it does not, this must be a transitive failure. try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)}); } - return error.AnalysisFail; + break :success false; }, error.OutOfMemory, error.Canceled, @@ -1098,6 +1101,15 @@ pub fn ensureTypeLayoutUpToDate( sema.flushExports() catch |err| switch (err) { error.OutOfMemory => |e| return e, }; + + // We don't need to `markDependeeOutdated`/`markPoDependeeUpToDate` here, because we already + // marked the layout as outdated at the top of this function. However, we do need to tell the + // debug info logic in the backend about this type. + comp.link_prog_node.increaseEstimatedTotalItems(1); + try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .debug_update_container_type = .{ + .ty = ty.toIntern(), + .success = new_success, + } }); } /// Ensures that the resolved value of the given `Nav` is fully up-to-date, performing re-analysis @@ -4102,463 +4114,3 @@ fn printVerboseAir( try air.write(w, pt, liveness); try w.print("# End Function AIR: {f}\n\n", .{fqn.fmt(ip)}); } - -// MLUGG TODO: these functions are all blatant hacks. See if I can remove them! -pub fn resolveTypeForCodegen(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void { - const zcu = pt.zcu; - const ip = &zcu.intern_pool; - if (ty.isGenericPoison()) return; - switch (ty.zigTypeTag(zcu)) { - .type, - .void, - .bool, - .noreturn, - .int, - .float, - .error_set, - .@"opaque", - .comptime_float, - .comptime_int, - .undefined, - .null, - .enum_literal, - => {}, - - .frame, .@"anyframe" => @panic("TODO resolveTypeForCodegen async frames"), - - .optional => try pt.resolveTypeForCodegen(ty.childType(zcu)), - .error_union => try pt.resolveTypeForCodegen(ty.errorUnionPayload(zcu)), - .pointer => try pt.resolveTypeForCodegen(ty.childType(zcu)), - .array => try pt.resolveTypeForCodegen(ty.childType(zcu)), - .vector => try pt.resolveTypeForCodegen(ty.childType(zcu)), - - .@"fn" => { - const info = zcu.typeToFunc(ty).?; - for (0..info.param_types.len) |i| { - const param_ty = info.param_types.get(ip)[i]; - try pt.resolveTypeForCodegen(.fromInterned(param_ty)); - } - try pt.resolveTypeForCodegen(.fromInterned(info.return_type)); - }, - - .@"struct" => switch (ip.indexToKey(ty.toIntern())) { - .struct_type => try pt.ensureTypeLayoutUpToDate(ty, null), - .tuple_type => |tuple| for (0..tuple.types.len) |i| { - const field_is_comptime = tuple.values.get(ip)[i] != .none; - if (field_is_comptime) continue; - const field_ty = tuple.types.get(ip)[i]; - try pt.resolveTypeForCodegen(.fromInterned(field_ty)); - }, - else => unreachable, - }, - - .@"union" => try pt.ensureTypeLayoutUpToDate(ty, null), - .@"enum" => try pt.ensureTypeLayoutUpToDate(ty, null), - } -} -pub fn resolveValueTypesForCodegen(pt: Zcu.PerThread, val: Value) Zcu.SemaError!void { - const zcu = pt.zcu; - const ty: Type = switch (val.typeOf(zcu).toIntern()) { - .type_type => if (val.isUndef(zcu)) { - return; - } else val.toType(), - else => |ty| .fromInterned(ty), - }; - return pt.resolveTypeForCodegen(ty); -} -pub fn resolveAirTypesForCodegen(pt: Zcu.PerThread, air: *const Air) Zcu.SemaError!void { - return pt.resolveBodyTypesForCodegen(air, air.getMainBody()); -} -fn resolveBodyTypesForCodegen(pt: Zcu.PerThread, air: *const Air, body: []const Air.Inst.Index) Zcu.SemaError!void { - const zcu = pt.zcu; - const tags = air.instructions.items(.tag); - const datas = air.instructions.items(.data); - for (body) |inst| { - const data = datas[@intFromEnum(inst)]; - switch (tags[@intFromEnum(inst)]) { - .inferred_alloc, .inferred_alloc_comptime => unreachable, - - .arg => try pt.resolveTypeForCodegen(data.arg.ty.toType()), - - .add, - .add_safe, - .add_optimized, - .add_wrap, - .add_sat, - .sub, - .sub_safe, - .sub_optimized, - .sub_wrap, - .sub_sat, - .mul, - .mul_safe, - .mul_optimized, - .mul_wrap, - .mul_sat, - .div_float, - .div_float_optimized, - .div_trunc, - .div_trunc_optimized, - .div_floor, - .div_floor_optimized, - .div_exact, - .div_exact_optimized, - .rem, - .rem_optimized, - .mod, - .mod_optimized, - .max, - .min, - .bit_and, - .bit_or, - .shr, - .shr_exact, - .shl, - .shl_exact, - .shl_sat, - .xor, - .cmp_lt, - .cmp_lt_optimized, - .cmp_lte, - .cmp_lte_optimized, - .cmp_eq, - .cmp_eq_optimized, - .cmp_gte, - .cmp_gte_optimized, - .cmp_gt, - .cmp_gt_optimized, - .cmp_neq, - .cmp_neq_optimized, - .bool_and, - .bool_or, - .store, - .store_safe, - .set_union_tag, - .array_elem_val, - .slice_elem_val, - .ptr_elem_val, - .memset, - .memset_safe, - .memcpy, - .memmove, - .atomic_store_unordered, - .atomic_store_monotonic, - .atomic_store_release, - .atomic_store_seq_cst, - .legalize_vec_elem_val, - => { - try pt.resolveRefTypesForCodegen(data.bin_op.lhs); - try pt.resolveRefTypesForCodegen(data.bin_op.rhs); - }, - - .not, - .bitcast, - .clz, - .ctz, - .popcount, - .byte_swap, - .bit_reverse, - .abs, - .load, - .fptrunc, - .fpext, - .intcast, - .intcast_safe, - .trunc, - .optional_payload, - .optional_payload_ptr, - .optional_payload_ptr_set, - .wrap_optional, - .unwrap_errunion_payload, - .unwrap_errunion_err, - .unwrap_errunion_payload_ptr, - .unwrap_errunion_err_ptr, - .errunion_payload_ptr_set, - .wrap_errunion_payload, - .wrap_errunion_err, - .struct_field_ptr_index_0, - .struct_field_ptr_index_1, - .struct_field_ptr_index_2, - .struct_field_ptr_index_3, - .get_union_tag, - .slice_len, - .slice_ptr, - .ptr_slice_len_ptr, - .ptr_slice_ptr_ptr, - .array_to_slice, - .int_from_float, - .int_from_float_optimized, - .int_from_float_safe, - .int_from_float_optimized_safe, - .float_from_int, - .splat, - .error_set_has_value, - .addrspace_cast, - .c_va_arg, - .c_va_copy, - => { - try pt.resolveTypeForCodegen(data.ty_op.ty.toType()); - try pt.resolveRefTypesForCodegen(data.ty_op.operand); - }, - - .alloc, - .ret_ptr, - .c_va_start, - => try pt.resolveTypeForCodegen(data.ty), - - .ptr_add, - .ptr_sub, - .add_with_overflow, - .sub_with_overflow, - .mul_with_overflow, - .shl_with_overflow, - .slice, - .slice_elem_ptr, - .ptr_elem_ptr, - => { - const bin = air.extraData(Air.Bin, data.ty_pl.payload).data; - try pt.resolveTypeForCodegen(data.ty_pl.ty.toType()); - try pt.resolveRefTypesForCodegen(bin.lhs); - try pt.resolveRefTypesForCodegen(bin.rhs); - }, - - .block, - .loop, - => { - const block = air.unwrapBlock(inst); - try pt.resolveTypeForCodegen(block.ty); - try pt.resolveBodyTypesForCodegen(air, block.body); - }, - - .dbg_inline_block => { - const block = air.unwrapDbgBlock(inst); - try pt.resolveTypeForCodegen(block.ty); - try pt.resolveBodyTypesForCodegen(air, block.body); - }, - - .sqrt, - .sin, - .cos, - .tan, - .exp, - .exp2, - .log, - .log2, - .log10, - .floor, - .ceil, - .round, - .trunc_float, - .neg, - .neg_optimized, - .is_null, - .is_non_null, - .is_null_ptr, - .is_non_null_ptr, - .is_err, - .is_non_err, - .is_err_ptr, - .is_non_err_ptr, - .ret, - .ret_safe, - .ret_load, - .is_named_enum_value, - .tag_name, - .error_name, - .cmp_lt_errors_len, - .c_va_end, - .set_err_return_trace, - => try pt.resolveRefTypesForCodegen(data.un_op), - - .br, .switch_dispatch => try pt.resolveRefTypesForCodegen(data.br.operand), - - .cmp_vector, - .cmp_vector_optimized, - => { - const extra = air.extraData(Air.VectorCmp, data.ty_pl.payload).data; - try pt.resolveTypeForCodegen(data.ty_pl.ty.toType()); - try pt.resolveRefTypesForCodegen(extra.lhs); - try pt.resolveRefTypesForCodegen(extra.rhs); - }, - - .reduce, - .reduce_optimized, - => try pt.resolveRefTypesForCodegen(data.reduce.operand), - - .struct_field_ptr, - .struct_field_val, - => { - const extra = air.extraData(Air.StructField, data.ty_pl.payload).data; - try pt.resolveTypeForCodegen(data.ty_pl.ty.toType()); - try pt.resolveRefTypesForCodegen(extra.struct_operand); - }, - - .shuffle_one => { - const unwrapped = air.unwrapShuffleOne(zcu, inst); - try pt.resolveTypeForCodegen(unwrapped.result_ty); - try pt.resolveRefTypesForCodegen(unwrapped.operand); - for (unwrapped.mask) |m| switch (m.unwrap()) { - .elem => {}, - .value => |val| try pt.resolveValueTypesForCodegen(.fromInterned(val)), - }; - }, - - .shuffle_two => { - const unwrapped = air.unwrapShuffleTwo(zcu, inst); - try pt.resolveTypeForCodegen(unwrapped.result_ty); - try pt.resolveRefTypesForCodegen(unwrapped.operand_a); - try pt.resolveRefTypesForCodegen(unwrapped.operand_b); - // No values to check because there are no comptime-known values other than undef - }, - - .cmpxchg_weak, - .cmpxchg_strong, - => { - const extra = air.extraData(Air.Cmpxchg, data.ty_pl.payload).data; - try pt.resolveTypeForCodegen(data.ty_pl.ty.toType()); - try pt.resolveRefTypesForCodegen(extra.ptr); - try pt.resolveRefTypesForCodegen(extra.expected_value); - try pt.resolveRefTypesForCodegen(extra.new_value); - }, - - .aggregate_init => { - const ty = data.ty_pl.ty.toType(); - const elems_len: usize = @intCast(ty.arrayLen(zcu)); - const elems: []const Air.Inst.Ref = @ptrCast(air.extra.items[data.ty_pl.payload..][0..elems_len]); - try pt.resolveTypeForCodegen(ty); - if (ty.zigTypeTag(zcu) == .@"struct") { - for (elems, 0..) |elem, elem_idx| { - if (ty.structFieldIsComptime(elem_idx, zcu)) continue; - try pt.resolveRefTypesForCodegen(elem); - } - } else { - for (elems) |elem| { - try pt.resolveRefTypesForCodegen(elem); - } - } - }, - - .union_init => { - const extra = air.extraData(Air.UnionInit, data.ty_pl.payload).data; - try pt.resolveTypeForCodegen(data.ty_pl.ty.toType()); - try pt.resolveRefTypesForCodegen(extra.init); - }, - - .field_parent_ptr => { - const extra = air.extraData(Air.FieldParentPtr, data.ty_pl.payload).data; - try pt.resolveTypeForCodegen(data.ty_pl.ty.toType()); - try pt.resolveRefTypesForCodegen(extra.field_ptr); - }, - - .atomic_load => try pt.resolveRefTypesForCodegen(data.atomic_load.ptr), - - .prefetch => try pt.resolveRefTypesForCodegen(data.prefetch.ptr), - - .runtime_nav_ptr => try pt.resolveTypeForCodegen(.fromInterned(data.ty_nav.ty)), - - .select, - .mul_add, - .legalize_vec_store_elem, - => { - const bin = air.extraData(Air.Bin, data.pl_op.payload).data; - try pt.resolveRefTypesForCodegen(data.pl_op.operand); - try pt.resolveRefTypesForCodegen(bin.lhs); - try pt.resolveRefTypesForCodegen(bin.rhs); - }, - - .atomic_rmw => { - const extra = air.extraData(Air.AtomicRmw, data.pl_op.payload).data; - try pt.resolveRefTypesForCodegen(data.pl_op.operand); - try pt.resolveRefTypesForCodegen(extra.operand); - }, - - .call, - .call_always_tail, - .call_never_tail, - .call_never_inline, - => { - const call = air.unwrapCall(inst); - try pt.resolveRefTypesForCodegen(call.callee); - for (call.args) |arg| try pt.resolveRefTypesForCodegen(arg); - }, - - .dbg_var_ptr, - .dbg_var_val, - .dbg_arg_inline, - => try pt.resolveRefTypesForCodegen(data.pl_op.operand), - - .@"try", .try_cold => { - const @"try" = air.unwrapTry(inst); - try pt.resolveRefTypesForCodegen(@"try".error_union); - try pt.resolveBodyTypesForCodegen(air, @"try".else_body); - }, - - .try_ptr, .try_ptr_cold => { - const try_ptr = air.unwrapTryPtr(inst); - try pt.resolveTypeForCodegen(try_ptr.error_union_payload_ptr_ty.toType()); - try pt.resolveRefTypesForCodegen(try_ptr.error_union_ptr); - try pt.resolveBodyTypesForCodegen(air, try_ptr.else_body); - }, - - .cond_br => { - const cond_br = air.unwrapCondBr(inst); - try pt.resolveRefTypesForCodegen(cond_br.condition); - try pt.resolveBodyTypesForCodegen(air, cond_br.then_body); - try pt.resolveBodyTypesForCodegen(air, cond_br.else_body); - }, - - .switch_br, .loop_switch_br => { - const switch_br = air.unwrapSwitch(inst); - try pt.resolveRefTypesForCodegen(switch_br.operand); - var it = switch_br.iterateCases(); - while (it.next()) |case| { - for (case.items) |item| { - try pt.resolveRefTypesForCodegen(item); - } - for (case.ranges) |range| { - try pt.resolveRefTypesForCodegen(range[0]); - try pt.resolveRefTypesForCodegen(range[1]); - } - try pt.resolveBodyTypesForCodegen(air, case.body); - } - try pt.resolveBodyTypesForCodegen(air, it.elseBody()); - }, - - .assembly => { - const @"asm" = air.unwrapAsm(inst); - try pt.resolveTypeForCodegen(data.ty_pl.ty.toType()); - for (@"asm".outputs) |output| if (output != .none) try pt.resolveRefTypesForCodegen(output); - for (@"asm".inputs) |input| if (input != .none) try pt.resolveRefTypesForCodegen(input); - }, - - .legalize_compiler_rt_call => { - const compiler_rt_call = air.unwrapCompilerRtCall(inst); - for (compiler_rt_call.args) |arg| try pt.resolveRefTypesForCodegen(arg); - }, - - .trap, - .breakpoint, - .ret_addr, - .frame_addr, - .unreach, - .wasm_memory_size, - .wasm_memory_grow, - .work_item_id, - .work_group_size, - .work_group_id, - .dbg_stmt, - .dbg_empty_stmt, - .err_return_trace, - .save_err_return_trace_index, - .repeat, - => {}, - } - } -} -fn resolveRefTypesForCodegen(pt: Zcu.PerThread, ref: Air.Inst.Ref) Zcu.SemaError!void { - const ip_index = ref.toInterned() orelse { - // `ref` refers to a prior instruction, which we already did the resolution for. - return; - }; - return pt.resolveValueTypesForCodegen(.fromInterned(ip_index)); -} diff --git a/src/codegen.zig b/src/codegen.zig index 45b70dee2ac19600117a0a08eec0087b234c7013..9608095dc61dfc3ce1c4b68a2c297bcd5439a2ac 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -700,7 +700,14 @@ fn lowerPtr( }; return lowerPtr(bin_file, pt, src_loc, field.base, w, reloc_parent, offset + field_off); }, - .arr_elem, .comptime_field, .comptime_alloc => unreachable, + .arr_elem => |arr_elem| { + const base_ptr_ty = Value.fromInterned(arr_elem.base).typeOf(zcu); + assert(base_ptr_ty.ptrSize(zcu) == .many); + const elem_size = base_ptr_ty.childType(zcu).abiSize(zcu); + return lowerPtr(bin_file, pt, src_loc, arr_elem.base, w, reloc_parent, offset + elem_size * arr_elem.index); + }, + .comptime_alloc => unreachable, + .comptime_field => unreachable, }; } @@ -781,9 +788,8 @@ fn lowerNavRef( const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); const is_obj = lf.comp.config.output_mode == .Obj; const nav_ty = Type.fromInterned(ip.getNav(nav_index).typeOf(ip)); - const is_fn_body = nav_ty.zigTypeTag(zcu) == .@"fn"; - if (!is_fn_body and !nav_ty.hasRuntimeBits(zcu)) { + if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) and ip.getNav(nav_index).getExtern(ip) == null) { try w.splatByteAll(0xaa, ptr_width_bytes); return; } @@ -795,7 +801,7 @@ fn lowerNavRef( dev.check(link.File.Tag.wasm.devFeature()); const wasm = lf.cast(.wasm).?; assert(reloc_parent == .none); - if (is_fn_body) { + if (nav_ty.zigTypeTag(zcu) == .@"fn") { const gop = try wasm.zcu_indirect_function_set.getOrPut(gpa, nav_index); if (!gop.found_existing) gop.value_ptr.* = {}; if (is_obj) { @@ -1025,23 +1031,26 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo .pointer => switch (ty.ptrSize(zcu)) { .slice => {}, .one, .many, .c => { - const elem_ty = ty.childType(zcu); const ptr = ip.indexToKey(val.toIntern()).ptr; if (ptr.base_addr == .int) return .{ .immediate = ptr.byte_offset }; if (ptr.byte_offset == 0) switch (ptr.base_addr) { .int => unreachable, // handled above - .nav => |nav| if (elem_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { - return .{ .lea_nav = nav }; - } else { - // Create the 0xaa bit pattern... - const undef_ptr_bits: u64 = @intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() + 1)) / 3); - // ...but align the pointer - const alignment = zcu.navAlignment(nav); - return .{ .immediate = alignment.forward(undef_ptr_bits) }; + .nav => |nav_index| { + const nav = ip.getNav(nav_index); + const nav_ty: Type = .fromInterned(nav.typeOf(ip)); + if (nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) or nav.getExtern(ip) != null) { + return .{ .lea_nav = nav_index }; + } else { + // Create the 0xaa bit pattern... + const undef_ptr_bits: u64 = @intCast((@as(u66, 1) << @intCast(target.ptrBitWidth() + 1)) / 3); + // ...but align the pointer + const alignment = zcu.navAlignment(nav_index); + return .{ .immediate = alignment.forward(undef_ptr_bits) }; + } }, - .uav => |uav| if (elem_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { + .uav => |uav| if (Value.fromInterned(uav.val).typeOf(zcu).isRuntimeFnOrHasRuntimeBits(zcu)) { return .{ .lea_uav = uav }; } else { // Create the 0xaa bit pattern... diff --git a/src/link.zig b/src/link.zig index 4999c8a31affc3964f8cf129f6bb50c8c5a87675..c8ae7a6bb4dbb8cd8d0e782b6e6178dd65f049a7 100644 --- a/src/link.zig +++ b/src/link.zig @@ -798,14 +798,27 @@ pub const File = struct { }; /// Never called when LLVM is codegenning the ZCU. - fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) UpdateContainerTypeError!void { + fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) UpdateContainerTypeError!void { assert(base.comp.zcu.?.llvm_object == null); switch (base.tag) { .lld => unreachable, else => {}, inline .elf => |tag| { dev.check(tag.devFeature()); - return @as(*tag.Type(), @fieldParentPtr("base", base)).updateContainerType(pt, ty); + return @as(*tag.Type(), @fieldParentPtr("base", base)).updateContainerType(pt, ty, success); + }, + } + } + + /// Never called when LLVM is codegenning the ZCU. + fn clearContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) UpdateContainerTypeError!void { + assert(base.comp.zcu.?.llvm_object == null); + switch (base.tag) { + .lld => unreachable, + else => {}, + inline .elf => |tag| { + dev.check(tag.devFeature()); + return @as(*tag.Type(), @fieldParentPtr("base", base)).clearContainerType(pt, ty); }, } } @@ -1375,8 +1388,14 @@ pub const ZcuTask = union(enum) { link_nav: InternPool.Nav.Index, /// Write the machine code for a function to the output file. link_func: Zcu.CodegenTaskPool.Index, - link_type: InternPool.Index, - update_line_number: InternPool.TrackedInst.Index, + /// This struct/union/enum type has finished type resolution (successfully or otherwise), so the + /// linker can now lower debug information for this type (and any structural types which depend + /// on it, such as `?T`, `struct { T }`, `[2]T`, etc). + debug_update_container_type: struct { + ty: InternPool.Index, + success: bool, + }, + debug_update_line_number: InternPool.TrackedInst.Index, }; pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { @@ -1563,21 +1582,24 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void } break :nav ip.indexToKey(func).func.owner_nav; }, - .link_type => |ty| nav: { - const name = Type.fromInterned(ty).containerTypeName(ip).toSlice(ip); - const nav_prog_node = comp.link_prog_node.start(name, 0); - defer nav_prog_node.end(); - if (zcu.llvm_object == null) { + .debug_update_container_type => |container_update| nav: { + const name = Type.fromInterned(container_update.ty).containerTypeName(ip).toSlice(ip); + const ty_prog_node = comp.link_prog_node.start(name, 0); + defer ty_prog_node.end(); + if (zcu.llvm_object) |llvm_object| { + _ = llvm_object; + @compileError("MLUGG TODO"); + } else { if (comp.bin_file) |lf| { - lf.updateContainerType(pt, ty) catch |err| switch (err) { + lf.updateContainerType(pt, container_update.ty, container_update.success) catch |err| switch (err) { error.OutOfMemory => diags.setAllocFailure(), - error.TypeFailureReported => assert(zcu.failed_types.contains(ty)), + error.TypeFailureReported => assert(zcu.failed_types.contains(container_update.ty)), }; } } break :nav null; }, - .update_line_number => |ti| nav: { + .debug_update_line_number => |ti| nav: { const nav_prog_node = comp.link_prog_node.start("Update line number", 0); defer nav_prog_node.end(); if (pt.zcu.llvm_object == null) { diff --git a/src/link/DebugConstPool.zig b/src/link/DebugConstPool.zig new file mode 100644 index 0000000000000000000000000000000000000000..ce7f32551b63401a94bce51d02f388398f8912e4 --- /dev/null +++ b/src/link/DebugConstPool.zig @@ -0,0 +1,287 @@ +/// Helper type for debug information implementations (such as `link.Dwarf`) to help them emit +/// information about comptime-known values (constants), including types. +/// +/// Every constant with associated debug information is assigned an `Index` by calling `get`. The +/// pool will track which container types do and do not have a resolved layout, as well as which +/// constants in the pool depend on which types, and call into the implementation to emit debug +/// information for a constant only when all information is available. +/// +/// Indices into the pool are dense, and constants are never removed from the pool, so the debug +/// info implementation can store information for each one with a simple `ArrayList`. +/// +/// To use `DebugConstPool`, the debug info implementation is required to: +/// * forward `updateContainerType` calls to its `DebugConstPool` +/// * expose some callback functions---see functions in `DebugInfo` +/// * ensure that any `get` call is eventually followed by a `flushPending` call +const DebugConstPool = @This(); + +values: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), +pending: std.ArrayList(Index), +complete_containers: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), +container_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, ContainerDepEntry.Index), +container_dep_entries: std.ArrayList(ContainerDepEntry), + +pub const empty: DebugConstPool = .{ + .values = .empty, + .pending = .empty, + .complete_containers = .empty, + .container_deps = .empty, + .container_dep_entries = .empty, +}; + +pub fn deinit(pool: *DebugConstPool, gpa: Allocator) void { + pool.values.deinit(gpa); + pool.pending.deinit(gpa); + pool.complete_containers.deinit(gpa); + pool.container_deps.deinit(gpa); + pool.container_dep_entries.deinit(gpa); +} + +pub const Index = enum(u32) { + _, + pub fn val(i: Index, pool: *const DebugConstPool) InternPool.Index { + return pool.values.keys()[@intFromEnum(i)]; + } +}; + +pub const DebugInfo = union(enum) { + dwarf: *@import("Dwarf.zig"), + llvm: @import("../codegen/llvm.zig").Object.Ptr, + + /// Inform the debug info implementation that the new constant `val` was added to the pool at + /// the given index (which equals the current pool length) due to a `get` call. It is guaranteed + /// that there will eventually be a call to either `updateConst` or `updateConstIncomplete` + /// following the `addConst` call, to actually populate the constant's debug info. + fn addConst( + di: DebugInfo, + pt: Zcu.PerThread, + index: Index, + val: InternPool.Index, + ) !void { + switch (di) { + inline else => |impl| return impl.addConst(pt, index, val), + } + } + + /// Tell the debug info implementation to emit information for the constant `val`, which is in + /// the pool at the given index. `val` is "complete", which means: + /// * If it is a type, its layout is known. + /// * Otherwise, the layout of its type is known. + fn updateConst( + di: DebugInfo, + pt: Zcu.PerThread, + index: Index, + val: InternPool.Index, + ) !void { + switch (di) { + inline else => |impl| return impl.updateConst(pt, index, val), + } + } + + /// Tell the debug info implementation to emit information for the constant `val`, which is in + /// the pool at the given index. `val` is "incomplete", meaning the implementation cannot emit + /// full information for it (for instance, perhaps it is a struct type which was never actually + /// initialized so never had its layout resolved). Instead, the implementation must emit some + /// form of placeholder entry representing an incomplete/unknown constant. + fn updateConstIncomplete( + di: DebugInfo, + pt: Zcu.PerThread, + index: Index, + val: InternPool.Index, + ) !void { + switch (di) { + inline else => |impl| return impl.updateConstIncomplete(pt, index, val), + } + } +}; + +const ContainerDepEntry = extern struct { + next: ContainerDepEntry.Index.Optional, + depender: DebugConstPool.Index, + const Index = enum(u32) { + _, + const Optional = enum(u32) { + none = std.math.maxInt(u32), + _, + fn unwrap(o: Optional) ?ContainerDepEntry.Index { + return switch (o) { + .none => null, + else => @enumFromInt(@intFromEnum(o)), + }; + } + }; + fn toOptional(i: ContainerDepEntry.Index) Optional { + return @enumFromInt(@intFromEnum(i)); + } + fn ptr(i: ContainerDepEntry.Index, pool: *DebugConstPool) *ContainerDepEntry { + return &pool.container_dep_entries.items[@intFromEnum(i)]; + } + }; +}; + +/// Calls to `link.File.updateContainerType` must be forwarded to this function so that the debug +/// constant pool has up-to-date information about the resolution status of types. +pub fn updateContainerType( + pool: *DebugConstPool, + pt: Zcu.PerThread, + di: DebugInfo, + container_ty: InternPool.Index, + success: bool, +) !void { + if (success) { + const gpa = pt.zcu.comp.gpa; + try pool.complete_containers.put(gpa, container_ty, {}); + } else { + _ = pool.complete_containers.fetchSwapRemove(container_ty); + } + var opt_dep = pool.container_deps.get(container_ty); + while (opt_dep) |dep| : (opt_dep = dep.ptr(pool).next.unwrap()) { + try pool.update(pt, di, dep.ptr(pool).depender); + } +} + +/// After this is called, there may be a constant for which debug information (complete or not) has +/// not yet been emitted, so the user must call `flushPending` at some point after this call. +pub fn get(pool: *DebugConstPool, pt: Zcu.PerThread, di: DebugInfo, val: InternPool.Index) !DebugConstPool.Index { + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + const gpa = zcu.comp.gpa; + const gop = try pool.values.getOrPut(gpa, val); + const index: DebugConstPool.Index = @enumFromInt(gop.index); + if (!gop.found_existing) { + const ty: Type = switch (ip.typeOf(val)) { + .type_type => if (ip.isUndef(val)) .type else .fromInterned(val), + else => |ty| .fromInterned(ty), + }; + try pool.registerTypeDeps(index, ty, zcu); + try pool.pending.append(gpa, index); + try di.addConst(pt, index, val); + } + return index; +} +pub fn flushPending(pool: *DebugConstPool, pt: Zcu.PerThread, di: DebugInfo) !void { + while (pool.pending.pop()) |pending_ty| { + try pool.update(pt, di, pending_ty); + } +} + +fn update(pool: *DebugConstPool, pt: Zcu.PerThread, di: DebugInfo, index: DebugConstPool.Index) !void { + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + const val = index.val(pool); + const ty: Type = switch (ip.typeOf(val)) { + .type_type => if (ip.isUndef(val)) .type else .fromInterned(val), + else => |ty| .fromInterned(ty), + }; + if (pool.checkType(ty, zcu)) { + try di.updateConst(pt, index, val); + } else { + try di.updateConstIncomplete(pt, index, val); + } +} +fn checkType(pool: *const DebugConstPool, ty: Type, zcu: *const Zcu) bool { + if (ty.isGenericPoison()) return true; + return switch (ty.zigTypeTag(zcu)) { + .type, + .void, + .bool, + .noreturn, + .int, + .float, + .pointer, + .comptime_float, + .comptime_int, + .undefined, + .null, + .error_set, + .@"opaque", + .frame, + .@"anyframe", + .enum_literal, + => true, + + .array, .vector => pool.checkType(ty.childType(zcu), zcu), + .optional => pool.checkType(ty.optionalChild(zcu), zcu), + .error_union => pool.checkType(ty.errorUnionPayload(zcu), zcu), + .@"fn" => { + const ip = &zcu.intern_pool; + const func = ip.indexToKey(ty.toIntern()).func_type; + for (func.param_types.get(ip)) |param_ty_ip| { + if (!pool.checkType(.fromInterned(param_ty_ip), zcu)) return false; + } + return pool.checkType(.fromInterned(func.return_type), zcu); + }, + .@"struct" => if (ty.isTuple(zcu)) { + for (0..ty.structFieldCount(zcu)) |field_index| { + if (!pool.checkType(ty.fieldType(field_index, zcu), zcu)) return false; + } + return true; + } else { + return pool.complete_containers.contains(ty.toIntern()); + }, + .@"union", .@"enum" => { + return pool.complete_containers.contains(ty.toIntern()); + }, + }; +} +fn registerTypeDeps(pool: *DebugConstPool, root: Index, ty: Type, zcu: *const Zcu) Allocator.Error!void { + if (ty.isGenericPoison()) return; + switch (ty.zigTypeTag(zcu)) { + .type, + .void, + .bool, + .noreturn, + .int, + .float, + .pointer, + .comptime_float, + .comptime_int, + .undefined, + .null, + .error_set, + .@"opaque", + .frame, + .@"anyframe", + .enum_literal, + => {}, + + .array, .vector => try pool.registerTypeDeps(root, ty.childType(zcu), zcu), + .optional => try pool.registerTypeDeps(root, ty.optionalChild(zcu), zcu), + .error_union => try pool.registerTypeDeps(root, ty.errorUnionPayload(zcu), zcu), + .@"fn" => { + const ip = &zcu.intern_pool; + const func = ip.indexToKey(ty.toIntern()).func_type; + for (func.param_types.get(ip)) |param_ty_ip| { + try pool.registerTypeDeps(root, .fromInterned(param_ty_ip), zcu); + } + try pool.registerTypeDeps(root, .fromInterned(func.return_type), zcu); + }, + .@"struct", .@"union", .@"enum" => if (ty.isTuple(zcu)) { + for (0..ty.structFieldCount(zcu)) |field_index| { + try pool.registerTypeDeps(root, ty.fieldType(field_index, zcu), zcu); + } + } else { + // `ty` is a container; register the dependency. + + const gpa = zcu.comp.gpa; + try pool.container_deps.ensureUnusedCapacity(gpa, 1); + try pool.container_dep_entries.ensureUnusedCapacity(gpa, 1); + errdefer comptime unreachable; + + const gop = pool.container_deps.getOrPutAssumeCapacity(ty.toIntern()); + const entry: ContainerDepEntry.Index = @enumFromInt(pool.container_dep_entries.items.len); + pool.container_dep_entries.appendAssumeCapacity(.{ + .next = if (gop.found_existing) gop.value_ptr.toOptional() else .none, + .depender = root, + }); + gop.value_ptr.* = entry; + }, + } +} + +const std = @import("std"); +const Allocator = std.mem.Allocator; + +const InternPool = @import("../InternPool.zig"); +const Type = @import("../Type.zig"); +const Zcu = @import("../Zcu.zig"); diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 1d87a42601427050245a3c1f6b2e314b515b0d0b..3094e8671e72456103a2a9f1e47df1a0816b1800 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -18,6 +18,7 @@ const codegen = @import("../codegen.zig"); const dev = @import("../dev.zig"); const link = @import("../link.zig"); const target_info = @import("../target.zig"); +const DebugConstPool = @import("DebugConstPool.zig"); gpa: Allocator, bin_file: *link.File, @@ -25,9 +26,11 @@ format: DW.Format, endian: std.builtin.Endian, address_size: AddressSize, +const_pool: DebugConstPool, + mods: std.AutoArrayHashMapUnmanaged(*Module, ModInfo), -types: std.AutoArrayHashMapUnmanaged(InternPool.Index, Entry.Index), -values: std.AutoArrayHashMapUnmanaged(InternPool.Index, Entry.Index), +/// Indices are `DebugConstPool.Index`. +values: std.ArrayList(struct { Unit.Index, Entry.Index }), navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, Entry.Index), decls: std.AutoArrayHashMapUnmanaged(InternPool.TrackedInst.Index, Entry.Index), @@ -1034,15 +1037,14 @@ const Entry = struct { }); const zcu = dwarf.bin_file.comp.zcu.?; const ip = &zcu.intern_pool; - for (dwarf.types.keys(), dwarf.types.values()) |ty, other_entry| { - const ty_unit: Unit.Index = if (Type.fromInterned(ty).typeDeclInst(zcu)) |inst_index| - dwarf.getUnit(zcu.fileByIndex(inst_index.resolveFile(ip)).mod.?) catch unreachable - else - .main; - if (sec.getUnit(ty_unit) == unit and unit.getEntry(other_entry) == entry) - log.err("missing Type({f}({d}))", .{ - Type.fromInterned(ty).fmt(.{ .tid = .main, .zcu = zcu }), - @intFromEnum(ty), + for (0.., dwarf.values.items) |raw_index, unit_and_entry| { + const index: DebugConstPool.Index = @enumFromInt(raw_index); + const val = index.val(&dwarf.const_pool); + const val_unit, const val_entry = unit_and_entry; + if (sec.getUnit(val_unit) == unit and unit.getEntry(val_entry) == entry) + log.err("missing Value({f}({d}))", .{ + Value.fromInterned(val).fmtValue(.{ .tid = .main, .zcu = zcu }), + @intFromEnum(val), }); } for (dwarf.navs.keys(), dwarf.navs.values()) |nav, other_entry| { @@ -1520,7 +1522,6 @@ pub const WipNav = struct { debug_info: Writer.Allocating, debug_line: Writer.Allocating, debug_loclists: Writer.Allocating, - pending_lazy: PendingLazy, pub fn deinit(wip_nav: *WipNav) void { const gpa = wip_nav.dwarf.gpa; @@ -1529,8 +1530,6 @@ pub const WipNav = struct { wip_nav.debug_info.deinit(); wip_nav.debug_line.deinit(); wip_nav.debug_loclists.deinit(); - wip_nav.pending_lazy.types.deinit(gpa); - wip_nav.pending_lazy.values.deinit(gpa); } pub fn genDebugFrame(wip_nav: *WipNav, loc: u32, cfa: Cfa) UpdateError!void { @@ -1945,6 +1944,12 @@ pub const WipNav = struct { try wip_nav.infoSectionOffset(.debug_str, StringSection.unit, try wip_nav.dwarf.debug_str.addString(wip_nav.dwarf, str), 0); } + fn strpFmt(wip_nav: *WipNav, comptime fmt: []const u8, args: anytype) (UpdateError || Writer.Error)!void { + const str = try std.fmt.allocPrint(wip_nav.dwarf.gpa, fmt, args); + defer wip_nav.dwarf.gpa.free(str); + return wip_nav.strp(str); + } + const ExprLocCounter = struct { dw: Writer.Discarding, section_offset_bytes: u32, @@ -2054,74 +2059,16 @@ pub const WipNav = struct { try dfw.splatByteAll(0, @intFromEnum(wip_nav.dwarf.address_size)); } - fn getNavEntry( - wip_nav: *WipNav, - nav_index: InternPool.Nav.Index, - ) UpdateError!struct { Unit.Index, Entry.Index } { - const zcu = wip_nav.pt.zcu; - const ip = &zcu.intern_pool; - const nav = ip.getNav(nav_index); - const unit = try wip_nav.dwarf.getUnit(zcu.fileByIndex(nav.srcInst(ip).resolveFile(ip)).mod.?); - const gop = try wip_nav.dwarf.navs.getOrPut(wip_nav.dwarf.gpa, nav_index); - if (gop.found_existing) return .{ unit, gop.value_ptr.* }; - const entry = try wip_nav.dwarf.addCommonEntry(unit); - gop.value_ptr.* = entry; - return .{ unit, entry }; - } - fn refNav( wip_nav: *WipNav, nav_index: InternPool.Nav.Index, ) (UpdateError || Writer.Error)!void { - const unit, const entry = try wip_nav.getNavEntry(nav_index); + const unit, const entry = try wip_nav.dwarf.getNavEntry(nav_index); try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0); } - fn getTypeEntry(wip_nav: *WipNav, ty: Type) UpdateError!struct { Unit.Index, Entry.Index } { - const zcu = wip_nav.pt.zcu; - const ip = &zcu.intern_pool; - const maybe_inst_index = ty.typeDeclInst(zcu); - const unit = if (maybe_inst_index) |inst_index| switch (switch (ip.indexToKey(ty.toIntern())) { - else => unreachable, - .struct_type => ip.loadStructType(ty.toIntern()).name_nav, - .union_type => ip.loadUnionType(ty.toIntern()).name_nav, - .enum_type => ip.loadEnumType(ty.toIntern()).name_nav, - .opaque_type => ip.loadOpaqueType(ty.toIntern()).name_nav, - }) { - .none => try wip_nav.dwarf.getUnit(zcu.fileByIndex(inst_index.resolveFile(ip)).mod.?), - else => |name_nav| return wip_nav.getNavEntry(name_nav.unwrap().?), - } else .main; - const gop = try wip_nav.dwarf.types.getOrPut(wip_nav.dwarf.gpa, ty.toIntern()); - if (gop.found_existing) return .{ unit, gop.value_ptr.* }; - const entry = try wip_nav.dwarf.addCommonEntry(unit); - gop.value_ptr.* = entry; - if (maybe_inst_index == null) try wip_nav.pending_lazy.types.append(wip_nav.dwarf.gpa, ty.toIntern()); - return .{ unit, entry }; - } - fn refType(wip_nav: *WipNav, ty: Type) (UpdateError || Writer.Error)!void { - const unit, const entry = try wip_nav.getTypeEntry(ty); - try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0); - } - - fn getValueEntry(wip_nav: *WipNav, value: Value) UpdateError!struct { Unit.Index, Entry.Index } { - const zcu = wip_nav.pt.zcu; - const ip = &zcu.intern_pool; - const ty = value.typeOf(zcu); - if (std.debug.runtime_safety) assert(ty.comptimeOnly(zcu)); - if (ty.toIntern() == .type_type) return wip_nav.getTypeEntry(value.toType()); - if (ip.isFunctionType(ty.toIntern()) and !value.isUndef(zcu)) return wip_nav.getNavEntry(switch (ip.indexToKey(value.toIntern())) { - else => unreachable, - .func => |func| func.owner_nav, - .@"extern" => |@"extern"| @"extern".owner_nav, - }); - const gop = try wip_nav.dwarf.values.getOrPut(wip_nav.dwarf.gpa, value.toIntern()); - const unit: Unit.Index = .main; - if (gop.found_existing) return .{ unit, gop.value_ptr.* }; - const entry = try wip_nav.dwarf.addCommonEntry(unit); - gop.value_ptr.* = entry; - try wip_nav.pending_lazy.values.append(wip_nav.dwarf.gpa, value.toIntern()); - return .{ unit, entry }; + return wip_nav.refValue(ty.toValue()); } fn refValue(wip_nav: *WipNav, value: Value) (UpdateError || Writer.Error)!void { @@ -2129,6 +2076,15 @@ pub const WipNav = struct { try wip_nav.infoSectionOffset(.debug_info, unit, entry, 0); } + fn getValueEntry(wip_nav: *WipNav, value: Value) UpdateError!struct { Unit.Index, Entry.Index } { + if (value.typeOf(wip_nav.pt.zcu).toIntern() != .type_type) { + assert(value.typeOf(wip_nav.pt.zcu).comptimeOnly(wip_nav.pt.zcu)); + } + const dwarf = wip_nav.dwarf; + const index = try dwarf.const_pool.get(wip_nav.pt, .{ .dwarf = dwarf }, value.toIntern()); + return dwarf.values.items[@intFromEnum(index)]; + } + fn refForward(wip_nav: *WipNav) (Allocator.Error || Writer.Error)!u32 { const dwarf = wip_nav.dwarf; const diw = &wip_nav.debug_info.writer; @@ -2156,7 +2112,7 @@ pub const WipNav = struct { ) (UpdateError || Writer.Error)!void { const ty = val.typeOf(wip_nav.pt.zcu); const diw = &wip_nav.debug_info.writer; - const size = if (ty.hasRuntimeBits(wip_nav.pt.zcu)) ty.abiSize(wip_nav.pt.zcu) else 0; + const size = ty.abiSize(wip_nav.pt.zcu); try diw.writeUleb128(size); if (size == 0) return; const old_end = wip_nav.debug_info.writer.end; @@ -2331,22 +2287,6 @@ pub const WipNav = struct { try wip_nav.refType(parent_type.?); try wip_nav.infoSectionOffset(.debug_info, wip_nav.unit, generic_decl_entry, 0); } - - const PendingLazy = struct { - types: std.ArrayList(InternPool.Index), - values: std.ArrayList(InternPool.Index), - - const empty: PendingLazy = .{ .types = .empty, .values = .empty }; - }; - - fn updateLazy(wip_nav: *WipNav, src_loc: Zcu.LazySrcLoc) (UpdateError || Writer.Error)!void { - while (true) if (wip_nav.pending_lazy.types.pop()) |pending_ty| - try wip_nav.dwarf.updateLazyType(wip_nav.pt, src_loc, pending_ty, &wip_nav.pending_lazy) - else if (wip_nav.pending_lazy.values.pop()) |pending_val| - try wip_nav.dwarf.updateLazyValue(wip_nav.pt, src_loc, pending_val, &wip_nav.pending_lazy) - else - break; - } }; /// When allocating, the ideal_capacity is calculated by @@ -2372,8 +2312,9 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf { }, .endian = target.cpu.arch.endian(), + .const_pool = .empty, + .mods = .empty, - .types = .empty, .values = .empty, .navs = .empty, .decls = .empty, @@ -2544,9 +2485,9 @@ pub fn initMetadata(dwarf: *Dwarf) UpdateError!void { pub fn deinit(dwarf: *Dwarf) void { const gpa = dwarf.gpa; + dwarf.const_pool.deinit(gpa); for (dwarf.mods.values()) |*mod_info| mod_info.deinit(gpa); dwarf.mods.deinit(gpa); - dwarf.types.deinit(gpa); dwarf.values.deinit(gpa); dwarf.navs.deinit(gpa); dwarf.decls.deinit(gpa); @@ -2562,6 +2503,21 @@ pub fn deinit(dwarf: *Dwarf) void { dwarf.* = undefined; } +fn getNavEntry( + dwarf: *Dwarf, + nav_index: InternPool.Nav.Index, +) UpdateError!struct { Unit.Index, Entry.Index } { + const zcu = dwarf.bin_file.comp.zcu.?; + const ip = &zcu.intern_pool; + const nav = ip.getNav(nav_index); + const unit = try dwarf.getUnit(zcu.fileByIndex(nav.srcInst(ip).resolveFile(ip)).mod.?); + const gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index); + if (gop.found_existing) return .{ unit, gop.value_ptr.* }; + const entry = try dwarf.addCommonEntry(unit); + gop.value_ptr.* = entry; + return .{ unit, entry }; +} + fn getUnit(dwarf: *Dwarf, mod: *Module) !Unit.Index { const mod_gop = try dwarf.mods.getOrPut(dwarf.gpa, mod); const unit: Unit.Index = @enumFromInt(mod_gop.index); @@ -2622,6 +2578,10 @@ fn getModInfo(dwarf: *Dwarf, unit: Unit.Index) *ModInfo { return &dwarf.mods.values()[@intFromEnum(unit)]; } +fn getUnitModule(dwarf: *Dwarf, unit: Unit.Index) *Module { + return dwarf.mods.keys()[@intFromEnum(unit)]; +} + pub fn initWipNav( dwarf: *Dwarf, pt: Zcu.PerThread, @@ -2683,7 +2643,6 @@ fn initWipNavInner( .debug_info = .init(dwarf.gpa), .debug_line = .init(dwarf.gpa), .debug_loclists = .init(dwarf.gpa), - .pending_lazy = .empty, }; errdefer wip_nav.deinit(); @@ -3050,7 +3009,7 @@ fn finishWipNavWriterError( } try dwarf.debug_loclists.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_loclists.written()); - try wip_nav.updateLazy(zcu.navSrcLoc(nav_index)); + try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); } pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error{ OutOfMemory, CodegenFail }!void { @@ -3087,34 +3046,12 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo return; } - var wip_nav: WipNav = .{ - .dwarf = dwarf, - .pt = pt, - .unit = try dwarf.getUnit(file.mod.?), - .entry = undefined, - .any_children = false, - .func = .none, - .func_sym_index = undefined, - .func_high_pc = undefined, - .blocks = undefined, - .cfi = undefined, - .debug_frame = .init(dwarf.gpa), - .debug_info = .init(dwarf.gpa), - .debug_line = .init(dwarf.gpa), - .debug_loclists = .init(dwarf.gpa), - .pending_lazy = .empty, - }; - defer wip_nav.deinit(); - - const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index); - errdefer _ = if (!nav_gop.found_existing) dwarf.navs.pop(); - const tag: union(enum) { - done, - decl_alias, - decl_var, - decl_const, - decl_func_alias: InternPool.Nav.Index, + alias, + @"var", + @"const", + func: Type, + func_alias: InternPool.Nav.Index, } = switch (ip.indexToKey(nav_val.toIntern())) { .int_type, .ptr_type, @@ -3128,242 +3065,49 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo .func_type, .error_set_type, .inferred_error_set_type, - => .decl_alias, + => .alias, + .struct_type => tag: { const loaded_struct = ip.loadStructType(nav_val.toIntern()); - if (loaded_struct.zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias; - - const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); - if (type_gop.found_existing) { - if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias; - assert(!nav_gop.found_existing); - nav_gop.value_ptr.* = type_gop.value_ptr.*; - } else { - if (nav_gop.found_existing) - dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() - else - nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); - type_gop.value_ptr.* = nav_gop.value_ptr.*; + if (nav_index.toOptional() == loaded_struct.name_nav) { + // This Nav's entry is populated by the type, not the actual Nav. + _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern()); + try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); + return; } - wip_nav.entry = nav_gop.value_ptr.*; - - const diw = &wip_nav.debug_info.writer; - - switch (loaded_struct.layout) { - .auto, .@"extern" => { - try wip_nav.declCommon(if (loaded_struct.field_types.len == 0) .{ - .decl = .decl_namespace_struct, - .generic_decl = .generic_decl_const, - .decl_instance = .decl_instance_namespace_struct, - } else .{ - .decl = .decl_struct, - .generic_decl = .generic_decl_const, - .decl_instance = .decl_instance_struct, - }, &nav, inst_info.file, &decl); - if (loaded_struct.field_types.len == 0) try diw.writeByte(@intFromBool(false)) else { - try diw.writeUleb128(nav_val.toType().abiSize(zcu)); - try diw.writeUleb128(nav_val.toType().abiAlignment(zcu).toByteUnits().?); - for (0..loaded_struct.field_types.len) |field_index| { - const is_comptime = loaded_struct.field_is_comptime_bits.get(ip, field_index); - const field_init = loaded_struct.field_defaults.getOrNone(ip, field_index); - assert(!(is_comptime and field_init == .none)); - const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - const has_runtime_bits, const has_comptime_state = switch (field_init) { - .none => .{ false, false }, - else => .{ - field_type.hasRuntimeBits(zcu), - field_type.comptimeOnly(zcu), - }, - }; - try wip_nav.abbrevCode(if (is_comptime) - if (has_comptime_state) - .struct_field_comptime_comptime_state - else if (has_runtime_bits) - .struct_field_comptime_runtime_bits - else - .struct_field_comptime - else if (field_init != .none) - if (has_comptime_state) - .struct_field_default_comptime_state - else if (has_runtime_bits) - .struct_field_default_runtime_bits - else - .struct_field - else - .struct_field); - try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip)); - try wip_nav.refType(field_type); - if (!is_comptime) { - try diw.writeUleb128(loaded_struct.field_offsets.get(ip)[field_index]); - try diw.writeUleb128(loaded_struct.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse - field_type.abiAlignment(zcu).toByteUnits().?); - } - if (has_comptime_state) - try wip_nav.refValue(.fromInterned(field_init)) - else if (has_runtime_bits) - try wip_nav.blockValue(nav_src_loc, .fromInterned(field_init)); - } - try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); - } - }, - .@"packed" => { - try wip_nav.declCommon(.{ - .decl = .decl_packed_struct, - .generic_decl = .generic_decl_const, - .decl_instance = .decl_instance_packed_struct, - }, &nav, inst_info.file, &decl); - try wip_nav.refType(.fromInterned(loaded_struct.packed_backing_int_type)); - var field_bit_offset: u16 = 0; - for (0..loaded_struct.field_types.len) |field_index| { - try wip_nav.abbrevCode(.packed_struct_field); - try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip)); - const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - try wip_nav.refType(field_type); - try diw.writeUleb128(field_bit_offset); - field_bit_offset += @intCast(field_type.bitSize(zcu)); - } - try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); - }, - } - break :tag .done; + break :tag .alias; }, .enum_type => tag: { const loaded_enum = ip.loadEnumType(nav_val.toIntern()); - const type_zir_index = loaded_enum.zir_index.unwrap() orelse break :tag .decl_alias; - if (type_zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias; - - const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); - if (type_gop.found_existing) { - if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias; - assert(!nav_gop.found_existing); - nav_gop.value_ptr.* = type_gop.value_ptr.*; - } else { - if (nav_gop.found_existing) - dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() - else - nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); - type_gop.value_ptr.* = nav_gop.value_ptr.*; + if (nav_index.toOptional() == loaded_enum.name_nav) { + // This Nav's entry is populated by the type, not the actual Nav. + _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern()); + try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); + return; } - wip_nav.entry = nav_gop.value_ptr.*; - const diw = &wip_nav.debug_info.writer; - try wip_nav.declCommon(if (loaded_enum.field_names.len > 0) .{ - .decl = .decl_enum, - .generic_decl = .generic_decl_const, - .decl_instance = .decl_instance_enum, - } else .{ - .decl = .decl_empty_enum, - .generic_decl = .generic_decl_const, - .decl_instance = .decl_instance_empty_enum, - }, &nav, inst_info.file, &decl); - try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type)); - for (0..loaded_enum.field_names.len) |field_index| { - try wip_nav.enumConstValue(loaded_enum, .{ - .sdata = .signed_enum_field, - .udata = .unsigned_enum_field, - .block = .big_enum_field, - }, field_index); - try wip_nav.strp(loaded_enum.field_names.get(ip)[field_index].toSlice(ip)); - } - if (loaded_enum.field_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); - break :tag .done; + break :tag .alias; }, .union_type => tag: { const loaded_union = ip.loadUnionType(nav_val.toIntern()); - if (loaded_union.zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias; - - const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); - if (type_gop.found_existing) { - if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias; - assert(!nav_gop.found_existing); - nav_gop.value_ptr.* = type_gop.value_ptr.*; - } else { - if (nav_gop.found_existing) - dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() - else - nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); - type_gop.value_ptr.* = nav_gop.value_ptr.*; + if (nav_index.toOptional() == loaded_union.name_nav) { + // This Nav's entry is populated by the type, not the actual Nav. + _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern()); + try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); + return; } - wip_nav.entry = nav_gop.value_ptr.*; - const diw = &wip_nav.debug_info.writer; - try wip_nav.declCommon(.{ - .decl = .decl_union, - .generic_decl = .generic_decl_const, - .decl_instance = .decl_instance_union, - }, &nav, inst_info.file, &decl); - const union_layout = Type.getUnionLayout(loaded_union, zcu); - try diw.writeUleb128(union_layout.abi_size); - try diw.writeUleb128(union_layout.abi_align.toByteUnits().?); - const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); - if (loaded_union.has_runtime_tag) { - try wip_nav.abbrevCode(.tagged_union); - try wip_nav.infoSectionOffset( - .debug_info, - wip_nav.unit, - wip_nav.entry, - @intCast(diw.end + dwarf.sectionOffsetBytes()), - ); - { - try wip_nav.abbrevCode(.generated_field); - try wip_nav.strp("tag"); - try wip_nav.refType(.fromInterned(loaded_union.enum_tag_type)); - try diw.writeUleb128(union_layout.tagOffset()); - - for (0..loaded_union.field_types.len) |field_index| { - try wip_nav.enumConstValue(loaded_tag, .{ - .sdata = .signed_tagged_union_field, - .udata = .unsigned_tagged_union_field, - .block = .big_tagged_union_field, - }, field_index); - { - try wip_nav.abbrevCode(.struct_field); - try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); - const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); - try wip_nav.refType(field_type); - try diw.writeUleb128(union_layout.payloadOffset()); - try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse - if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); - } - try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); - } - } - try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); - } else for (0..loaded_union.field_types.len) |field_index| { - try wip_nav.abbrevCode(.untagged_union_field); - try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); - const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); - try wip_nav.refType(field_type); - try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse - if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); - } - try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); - break :tag .done; + break :tag .alias; }, .opaque_type => tag: { const loaded_opaque = ip.loadOpaqueType(nav_val.toIntern()); - if (loaded_opaque.zir_index.resolveFile(ip) != inst_info.file) break :tag .decl_alias; - - const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern()); - if (type_gop.found_existing) { - if (dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).len > 0) break :tag .decl_alias; - assert(!nav_gop.found_existing); - nav_gop.value_ptr.* = type_gop.value_ptr.*; - } else { - if (nav_gop.found_existing) - dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() - else - nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); - type_gop.value_ptr.* = nav_gop.value_ptr.*; + if (nav_index.toOptional() == loaded_opaque.name_nav) { + // This Nav's entry is populated by the type, not the actual Nav. + _ = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, nav_val.toIntern()); + try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); + return; } - wip_nav.entry = nav_gop.value_ptr.*; - const diw = &wip_nav.debug_info.writer; - try wip_nav.declCommon(.{ - .decl = .decl_namespace_struct, - .generic_decl = .generic_decl_const, - .decl_instance = .decl_instance_namespace_struct, - }, &nav, inst_info.file, &decl); - try diw.writeByte(@intFromBool(true)); - break :tag .done; + break :tag .alias; }, + .undef, .simple_value, .int, @@ -3378,63 +3122,69 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo .aggregate, .un, .bitpack, - => .decl_const, - .variable => .decl_var, + => .@"const", + + .variable => .@"var", + .@"extern" => unreachable, + .func => |func| tag: { - if (func.owner_nav != nav_index) break :tag .{ .decl_func_alias = func.owner_nav }; - if (nav_gop.found_existing) switch (try dwarf.debug_info.declAbbrevCode(wip_nav.unit, nav_gop.value_ptr.*)) { - .null => {}, - else => unreachable, - .decl_nullary_func, .decl_func, .decl_instance_nullary_func, .decl_instance_func => return, - .decl_nullary_func_generic, - .decl_func_generic, - .decl_instance_nullary_func_generic, - .decl_instance_func_generic, - => dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear(), - } else nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); - wip_nav.entry = nav_gop.value_ptr.*; - - const func_type = ip.indexToKey(func.ty).func_type; - const is_nullary = !func_type.is_var_args and for (0..func_type.param_types.len) |param_index| { - if (!func_type.paramIsComptime(std.math.cast(u5, param_index) orelse break false)) break false; - } else true; - const diw = &wip_nav.debug_info.writer; - try wip_nav.declCommon(if (is_nullary) .{ - .decl = .decl_nullary_func_generic, - .generic_decl = .generic_decl_func, - .decl_instance = .decl_instance_nullary_func_generic, - } else .{ - .decl = .decl_func_generic, - .generic_decl = .generic_decl_func, - .decl_instance = .decl_instance_func_generic, - }, &nav, inst_info.file, &decl); - try wip_nav.refType(.fromInterned(func_type.return_type)); - if (!is_nullary) { - for (0..func_type.param_types.len) |param_index| { - if (std.math.cast(u5, param_index)) |small_param_index| - if (func_type.paramIsComptime(small_param_index)) continue; - try wip_nav.abbrevCode(.func_type_param); - try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index])); - } - if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args); - try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); - } - break :tag .done; + if (func.owner_nav != nav_index) break :tag .{ .func_alias = func.owner_nav }; + break :tag .{ .func = .fromInterned(func.ty) }; }, + // memoization, not types .memoized_call => unreachable, }; - if (tag != .done) { - if (nav_gop.found_existing) - dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear() - else - nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit); - wip_nav.entry = nav_gop.value_ptr.*; + + const unit = try dwarf.getUnit(file.mod.?); + + const nav_gop = try dwarf.navs.getOrPut(dwarf.gpa, nav_index); + errdefer _ = if (!nav_gop.found_existing) dwarf.navs.pop(); + + if (nav_gop.found_existing) { + if (tag == .func) switch (try dwarf.debug_info.declAbbrevCode(unit, nav_gop.value_ptr.*)) { + else => unreachable, + + .decl_nullary_func, + .decl_func, + .decl_instance_nullary_func, + .decl_instance_func, + => return, + + .null, + .decl_nullary_func_generic, + .decl_func_generic, + .decl_instance_nullary_func_generic, + .decl_instance_func_generic, + => {}, + }; + dwarf.debug_info.section.getUnit(unit).getEntry(nav_gop.value_ptr.*).clear(); + } else { + nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit); } + + var wip_nav: WipNav = .{ + .dwarf = dwarf, + .pt = pt, + .unit = unit, + .entry = nav_gop.value_ptr.*, + .any_children = false, + .func = .none, + .func_sym_index = undefined, + .func_high_pc = undefined, + .blocks = undefined, + .cfi = undefined, + .debug_frame = .init(dwarf.gpa), + .debug_info = .init(dwarf.gpa), + .debug_line = .init(dwarf.gpa), + .debug_loclists = .init(dwarf.gpa), + }; + defer wip_nav.deinit(); + const diw = &wip_nav.debug_info.writer; + switch (tag) { - .done => {}, - .decl_alias => { + .alias => { try wip_nav.declCommon(.{ .decl = .decl_alias, .generic_decl = .generic_decl_const, @@ -3442,8 +3192,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo }, &nav, inst_info.file, &decl); try wip_nav.refType(nav_val.toType()); }, - .decl_var => { - const diw = &wip_nav.debug_info.writer; + .@"var" => { try wip_nav.declCommon(.{ .decl = .decl_var, .generic_decl = .generic_decl_var, @@ -3460,8 +3209,7 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo nav_ty.abiAlignment(zcu).toByteUnits().?); try diw.writeByte(@intFromBool(decl.linkage != .normal)); }, - .decl_const => { - const diw = &wip_nav.debug_info.writer; + .@"const" => { const nav_ty = nav_val.typeOf(zcu); const has_runtime_bits = nav_ty.hasRuntimeBits(zcu); const has_comptime_state = nav_ty.comptimeOnly(zcu); @@ -3496,7 +3244,33 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo try wip_nav.abbrevCode(.is_const); try wip_nav.refType(nav_ty); }, - .decl_func_alias => |owner_nav| { + .func => |func_ty| { + const func_type = ip.indexToKey(func_ty.toIntern()).func_type; + const is_nullary = !func_type.is_var_args and for (0..func_type.param_types.len) |param_index| { + if (!func_type.paramIsComptime(std.math.cast(u5, param_index) orelse break false)) break false; + } else true; + try wip_nav.declCommon(if (is_nullary) .{ + .decl = .decl_nullary_func_generic, + .generic_decl = .generic_decl_func, + .decl_instance = .decl_instance_nullary_func_generic, + } else .{ + .decl = .decl_func_generic, + .generic_decl = .generic_decl_func, + .decl_instance = .decl_instance_func_generic, + }, &nav, inst_info.file, &decl); + try wip_nav.refType(.fromInterned(func_type.return_type)); + if (!is_nullary) { + for (0..func_type.param_types.len) |param_index| { + if (std.math.cast(u5, param_index)) |small_param_index| + if (func_type.paramIsComptime(small_param_index)) continue; + try wip_nav.abbrevCode(.func_type_param); + try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index])); + } + if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args); + try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); + } + }, + .func_alias => |owner_nav| { try wip_nav.declCommon(.{ .decl = .decl_alias, .generic_decl = .generic_decl_const, @@ -3505,31 +3279,81 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo try wip_nav.refNav(owner_nav); }, } - try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); - try wip_nav.updateLazy(nav_src_loc); + try dwarf.debug_info.section.replaceEntry(unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); + try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); } -fn updateLazyType( +pub fn updateContainerType( dwarf: *Dwarf, pt: Zcu.PerThread, - src_loc: Zcu.LazySrcLoc, - type_index: InternPool.Index, - pending_lazy: *WipNav.PendingLazy, -) (UpdateError || Writer.Error)!void { + ty: InternPool.Index, + success: bool, +) !void { + try dwarf.const_pool.updateContainerType(pt, .{ .dwarf = dwarf }, ty, success); +} +/// Should only be called by the `DebugConstPool` implementation. +pub fn addConst(dwarf: *Dwarf, pt: Zcu.PerThread, index: DebugConstPool.Index, val: InternPool.Index) !void { const zcu = pt.zcu; const ip = &zcu.intern_pool; - assert(ip.typeOf(type_index) == .type_type); - const ty: Type = .fromInterned(type_index); - switch (type_index) { - .generic_poison_type => log.debug("updateLazyType({s})", .{"anytype"}), - else => log.debug("updateLazyType({f})", .{ty.fmt(pt)}), + + const unit: Unit.Index, const entry: Entry.Index = switch (ip.indexToKey(val)) { + else => .{ .main, try dwarf.addCommonEntry(.main) }, + .func => |func| try dwarf.getNavEntry(func.owner_nav), + .@"extern" => |@"extern"| try dwarf.getNavEntry(@"extern".owner_nav), + .struct_type, .union_type, .enum_type, .opaque_type => |_, tag| entry: { + const name_nav = switch (tag) { + .struct_type => ip.loadStructType(val).name_nav, + .union_type => ip.loadUnionType(val).name_nav, + .enum_type => ip.loadEnumType(val).name_nav, + .opaque_type => ip.loadOpaqueType(val).name_nav, + else => unreachable, + }; + if (name_nav.unwrap()) |nav| { + break :entry try dwarf.getNavEntry(nav); + } else { + const zir_index = Type.fromInterned(val).typeDeclInstAllowGeneratedTag(zcu).?; + const unit = try dwarf.getUnit(zcu.fileByIndex(zir_index.resolveFile(ip)).mod.?); + break :entry .{ unit, try dwarf.addCommonEntry(unit) }; + } + }, + }; + + assert(@intFromEnum(index) == dwarf.values.items.len); + try dwarf.values.append(dwarf.gpa, .{ unit, entry }); +} +/// Should only be called by the `DebugConstPool` implementation. +/// +/// Emits a "dummy" DIE for the given comptime-only value (which may be a type). For types, this is +/// an opaque type. Otherwise, it is an undefined value of the value's type. +pub fn updateConstIncomplete(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: DebugConstPool.Index, value_index: InternPool.Index) !void { + const zcu = pt.zcu; + + const val: Value = .fromInterned(value_index); + + switch (value_index) { + .generic_poison_type => log.debug("updateValueIncomplete(anytype)", .{}), + else => log.debug("updateValueIncomplete(@as({f}, {f}))", .{ + val.typeOf(zcu).fmt(pt), + val.fmtValue(pt), + }), } + const unit, const entry = dwarf.values.items[@intFromEnum(debug_const_index)]; + + for ([_]*Section{ + &dwarf.debug_aranges.section, + &dwarf.debug_aranges.section, + &dwarf.debug_info.section, + &dwarf.debug_line.section, + &dwarf.debug_loclists.section, + &dwarf.debug_rnglists.section, + }) |sec| sec.getUnit(unit).getEntry(entry).clear(); + var wip_nav: WipNav = .{ .dwarf = dwarf, .pt = pt, - .unit = .main, - .entry = dwarf.types.get(type_index).?, + .unit = unit, + .entry = entry, .any_children = false, .func = .none, .func_sym_index = undefined, @@ -3540,43 +3364,119 @@ fn updateLazyType( .debug_info = .init(dwarf.gpa), .debug_line = .init(dwarf.gpa), .debug_loclists = .init(dwarf.gpa), - .pending_lazy = pending_lazy.*, }; - defer { - pending_lazy.* = wip_nav.pending_lazy; - wip_nav.pending_lazy = .empty; - wip_nav.deinit(); - } - const diw = &wip_nav.debug_info.writer; - const name = switch (type_index) { - .generic_poison_type => "", - else => try std.fmt.allocPrint(dwarf.gpa, "{f}", .{ty.fmt(pt)}), - }; - defer dwarf.gpa.free(name); - - switch (ip.indexToKey(type_index)) { - .undef => { + defer wip_nav.deinit(); + switch (val.typeOf(zcu).toIntern()) { + .type_type => { + try wip_nav.abbrevCode(.generated_empty_struct_type); + try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); + try wip_nav.debug_info.writer.writeByte(@intFromBool(true)); + }, + else => |ty| { try wip_nav.abbrevCode(.undefined_comptime_value); - try wip_nav.refType(.type); + try wip_nav.refType(.fromInterned(ty)); }, + } + try dwarf.debug_info.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_info.written()); + try dwarf.debug_loclists.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_loclists.written()); +} +/// Should only be called by the `DebugConstPool` implementation. +/// +/// Emits a DIE for the given comptime-only value (which may be a type). +pub fn updateConst(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: DebugConstPool.Index, value_index: InternPool.Index) !void { + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + + const val: Value = .fromInterned(value_index); + + if (val.typeOf(zcu).toIntern() == .type_type and !val.isUndef(zcu)) { + val.toType().assertHasLayout(zcu); + } else { + val.typeOf(zcu).assertHasLayout(zcu); + } + + const value_ip_key = ip.indexToKey(value_index); + switch (value_ip_key) { + .func => return, // populated by the Nav instead (`updateComptimeNav` or `initWipNav`) + .@"extern" => return, // populated by the Nav instead (`initWipNav`) + else => {}, + } + + switch (value_index) { + .generic_poison_type => log.debug("updateValue(anytype)", .{}), + else => log.debug("updateValue(@as({f}, {f}))", .{ + val.typeOf(zcu).fmt(pt), + val.fmtValue(pt), + }), + } + + const unit, const entry = dwarf.values.items[@intFromEnum(debug_const_index)]; + + for ([_]*Section{ + &dwarf.debug_aranges.section, + &dwarf.debug_info.section, + &dwarf.debug_line.section, + &dwarf.debug_loclists.section, + &dwarf.debug_rnglists.section, + }) |sec| sec.getUnit(unit).getEntry(entry).clear(); + + var wip_nav: WipNav = .{ + .dwarf = dwarf, + .pt = pt, + .unit = unit, + .entry = entry, + .any_children = false, + .func = .none, + .func_sym_index = undefined, + .func_high_pc = undefined, + .blocks = undefined, + .cfi = undefined, + .debug_frame = .init(dwarf.gpa), + .debug_info = .init(dwarf.gpa), + .debug_line = .init(dwarf.gpa), + .debug_loclists = .init(dwarf.gpa), + }; + defer wip_nav.deinit(); + + // TODO: we really shouldn't need source locations at this point in the pipeline: we've lost + // that information by now. If the linker fundamentally cannot lower certain values, that needs + // to be caught in the frontend; if it can only hit transient failures, they should be reported + // without trying to tie them to a bogus source location. + const src_loc: Zcu.LazySrcLoc = .{ + .base_node_inst = inst: { + const mod_root_file_index = zcu.module_roots.get(dwarf.getUnitModule(unit)).?.unwrap().?; + const mod_root_type_index = zcu.fileRootType(mod_root_file_index); + break :inst ip.loadStructType(mod_root_type_index).zir_index; + }, + .offset = .{ .byte_abs = 0 }, + }; + + const diw = &wip_nav.debug_info.writer; + var big_int_space: Value.BigIntSpace = undefined; + switch (value_ip_key) { + .func => unreachable, // handled above + .@"extern" => unreachable, // handled above + .int_type => |int_type| { try wip_nav.abbrevCode(.numeric_type); - try wip_nav.strp(name); + try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); try diw.writeByte(switch (int_type.signedness) { inline .signed, .unsigned => |signedness| @field(DW.ATE, @tagName(signedness)), }); try diw.writeUleb128(int_type.bits); - try diw.writeUleb128(ty.abiSize(zcu)); - try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); + try diw.writeUleb128(val.toType().abiSize(zcu)); + try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?); }, .ptr_type => |ptr_type| switch (ptr_type.flags.size) { .one, .many, .c => { const ptr_child_type: Type = .fromInterned(ptr_type.child); - try wip_nav.abbrevCode(if (ptr_type.sentinel == .none) .ptr_type else .ptr_sentinel_type); - try wip_nav.strp(name); + try wip_nav.abbrevCode(switch (ptr_type.flags.alignment) { + .none => if (ptr_type.sentinel == .none) .ptr_type else .ptr_sentinel_type, + else => if (ptr_type.sentinel == .none) .ptr_aligned_type else .ptr_aligned_sentinel_type, + }); + try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); if (ptr_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(ptr_type.sentinel)); - try diw.writeUleb128(ptr_type.flags.alignment.toByteUnits() orelse - ptr_child_type.abiAlignment(zcu).toByteUnits().?); + if (ptr_type.flags.alignment.toByteUnits()) |a| try diw.writeUleb128(a); try diw.writeByte(@intFromEnum(ptr_type.flags.address_space)); if (ptr_type.flags.is_const or ptr_type.flags.is_volatile) try wip_nav.infoSectionOffset( .debug_info, @@ -3600,12 +3500,12 @@ fn updateLazyType( }, .slice => { try wip_nav.abbrevCode(.generated_struct_type); - try wip_nav.strp(name); - try diw.writeUleb128(ty.abiSize(zcu)); - try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); + try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); + try diw.writeUleb128(val.toType().abiSize(zcu)); + try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?); try wip_nav.abbrevCode(.generated_field); try wip_nav.strp("ptr"); - const ptr_field_type = ty.slicePtrFieldType(zcu); + const ptr_field_type = val.toType().slicePtrFieldType(zcu); try wip_nav.refType(ptr_field_type); try diw.writeUleb128(0); try wip_nav.abbrevCode(.generated_field); @@ -3619,7 +3519,7 @@ fn updateLazyType( .array_type => |array_type| { const array_child_type: Type = .fromInterned(array_type.child); try wip_nav.abbrevCode(if (array_type.sentinel == .none) .array_type else .array_sentinel_type); - try wip_nav.strp(name); + try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); if (array_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(array_type.sentinel)); try wip_nav.refType(array_child_type); try wip_nav.abbrevCode(.array_len); @@ -3629,7 +3529,7 @@ fn updateLazyType( }, .vector_type => |vector_type| { try wip_nav.abbrevCode(.vector_type); - try wip_nav.strp(name); + try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); try wip_nav.refType(.fromInterned(vector_type.child)); try wip_nav.abbrevCode(.array_len); try wip_nav.refType(.usize); @@ -3640,9 +3540,9 @@ fn updateLazyType( const opt_child_type: Type = .fromInterned(opt_child_type_index); const opt_repr = optRepr(opt_child_type, zcu); try wip_nav.abbrevCode(.generated_union_type); - try wip_nav.strp(name); - try diw.writeUleb128(ty.abiSize(zcu)); - try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); + try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); + try diw.writeUleb128(val.toType().abiSize(zcu)); + try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?); switch (opt_repr) { .opv_null => { try wip_nav.abbrevCode(.generated_field); @@ -3720,12 +3620,12 @@ fn updateLazyType( }; try wip_nav.abbrevCode(.generated_union_type); - try wip_nav.strp(name); + try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); if (error_union_type.error_set_type != .generic_poison_type and error_union_type.payload_type != .generic_poison_type) { - try diw.writeUleb128(ty.abiSize(zcu)); - try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); + try diw.writeUleb128(val.toType().abiSize(zcu)); + try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?); } else { try diw.writeUleb128(0); try diw.writeUleb128(1); @@ -3791,20 +3691,24 @@ fn updateLazyType( .bool, => { try wip_nav.abbrevCode(.numeric_type); - try wip_nav.strp(name); - try diw.writeByte(if (type_index == .bool_type) + try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); + try diw.writeByte(if (value_index == .bool_type) DW.ATE.boolean - else if (ty.isRuntimeFloat()) + else if (val.toType().isRuntimeFloat()) DW.ATE.float - else if (ty.isSignedInt(zcu)) + else if (val.toType().isSignedInt(zcu)) DW.ATE.signed - else if (ty.isUnsignedInt(zcu)) + else if (val.toType().isUnsignedInt(zcu)) DW.ATE.unsigned else unreachable); - try diw.writeUleb128(ty.bitSize(zcu)); - try diw.writeUleb128(ty.abiSize(zcu)); - try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); + try diw.writeUleb128(val.toType().bitSize(zcu)); + try diw.writeUleb128(val.toType().abiSize(zcu)); + try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?); + }, + .generic_poison => { + try wip_nav.abbrevCode(.void_type); + try wip_nav.strp("anytype"); }, .anyopaque, .void, @@ -3815,37 +3719,29 @@ fn updateLazyType( .null, .undefined, .enum_literal, - .generic_poison, => { try wip_nav.abbrevCode(.void_type); - try wip_nav.strp(if (type_index == .generic_poison_type) "anytype" else name); + try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); }, .anyerror => return, // delay until flush .adhoc_inferred_error_set => unreachable, }, - .struct_type, - .union_type, - .opaque_type, - => unreachable, .tuple_type => |tuple_type| if (tuple_type.types.len == 0) { try wip_nav.abbrevCode(.generated_empty_struct_type); - try wip_nav.strp(name); + try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); try diw.writeByte(@intFromBool(false)); } else { try wip_nav.abbrevCode(.generated_struct_type); - try wip_nav.strp(name); - try diw.writeUleb128(ty.abiSize(zcu)); - try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); + try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); + try diw.writeUleb128(val.toType().abiSize(zcu)); + try diw.writeUleb128(val.toType().abiAlignment(zcu).toByteUnits().?); var field_byte_offset: u64 = 0; for (0..tuple_type.types.len) |field_index| { const comptime_value = tuple_type.values.get(ip)[field_index]; const field_type: Type = .fromInterned(tuple_type.types.get(ip)[field_index]); const has_runtime_bits, const has_comptime_state = switch (comptime_value) { .none => .{ false, false }, - else => .{ - field_type.hasRuntimeBits(zcu), - field_type.comptimeOnly(zcu), - }, + else => .{ field_type.hasRuntimeBits(zcu), field_type.comptimeOnly(zcu) }, }; try wip_nav.abbrevCode(if (has_comptime_state) .struct_field_comptime_comptime_state @@ -3875,25 +3771,259 @@ fn updateLazyType( } try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); }, + .struct_type => { + const loaded_struct = ip.loadStructType(value_index); + const ty = val.toType(); + const file = loaded_struct.zir_index.resolveFile(ip); + switch (loaded_struct.layout) { + .auto, .@"extern" => { + const struct_is_file: bool = if (loaded_struct.zir_index.resolve(ip)) |inst| f: { + break :f inst == .main_struct_inst; + } else false; + if (loaded_struct.name_nav.unwrap()) |nav_index| { + assert(!struct_is_file); + const nav = ip.getNav(nav_index); + const decl_inst = nav.srcInst(ip).resolve(ip).?; + const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); + try wip_nav.declCommon(if (loaded_struct.field_types.len == 0) .{ + .decl = .decl_namespace_struct, + .generic_decl = .generic_decl_const, + .decl_instance = .decl_instance_namespace_struct, + } else .{ + .decl = .decl_struct, + .generic_decl = .generic_decl_const, + .decl_instance = .decl_instance_struct, + }, &nav, file, &decl); + } else { + const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); + try wip_nav.abbrevCode(switch (loaded_struct.field_types.len) { + 0 => if (struct_is_file) .empty_file else .empty_struct_type, + else => if (struct_is_file) .file else .struct_type, + }); + try diw.writeUleb128(file_gop.index); + try wip_nav.strp(loaded_struct.name.toSlice(ip)); + } + if (loaded_struct.field_types.len == 0) { + if (!struct_is_file) try diw.writeByte(@intFromBool(false)); + } else { + try diw.writeUleb128(ty.abiSize(zcu)); + try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); + for (0..loaded_struct.field_types.len) |field_index| { + const is_comptime = loaded_struct.field_is_comptime_bits.get(ip, field_index); + const field_init = loaded_struct.field_defaults.getOrNone(ip, field_index); + assert(!(is_comptime and field_init == .none)); + const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); + const has_runtime_bits, const has_comptime_state = switch (field_init) { + .none => .{ false, false }, + else => .{ + field_type.hasRuntimeBits(zcu), + field_type.comptimeOnly(zcu), + }, + }; + try wip_nav.abbrevCode(if (is_comptime) + if (has_comptime_state) + .struct_field_comptime_comptime_state + else if (has_runtime_bits) + .struct_field_comptime_runtime_bits + else + .struct_field_comptime + else if (field_init != .none) + if (has_comptime_state) + .struct_field_default_comptime_state + else if (has_runtime_bits) + .struct_field_default_runtime_bits + else + .struct_field + else + .struct_field); + try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip)); + try wip_nav.refType(field_type); + if (!is_comptime) { + try diw.writeUleb128(loaded_struct.field_offsets.get(ip)[field_index]); + try diw.writeUleb128(loaded_struct.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse + field_type.abiAlignment(zcu).toByteUnits().?); + } + if (has_comptime_state) + try wip_nav.refValue(.fromInterned(field_init)) + else if (has_runtime_bits) + try wip_nav.blockValue(ty.srcLoc(zcu), .fromInterned(field_init)); + } + try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); + } + }, + .@"packed" => { + const need_terminator: bool = if (loaded_struct.name_nav.unwrap()) |nav_index| t: { + const nav = ip.getNav(nav_index); + const decl_inst = nav.srcInst(ip).resolve(ip).?; + const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); + try wip_nav.declCommon(.{ + .decl = .decl_packed_struct, + .generic_decl = .generic_decl_const, + .decl_instance = .decl_instance_packed_struct, + }, &nav, file, &decl); + break :t true; + } else t: { + const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); + try wip_nav.abbrevCode(if (loaded_struct.field_types.len > 0) .packed_struct_type else .empty_packed_struct_type); + try diw.writeUleb128(file_gop.index); + try wip_nav.strp(loaded_struct.name.toSlice(ip)); + break :t loaded_struct.field_types.len > 0; + }; + try wip_nav.refType(.fromInterned(loaded_struct.packed_backing_int_type)); + var field_bit_offset: u16 = 0; + for (0..loaded_struct.field_types.len) |field_index| { + try wip_nav.abbrevCode(.packed_struct_field); + try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip)); + const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); + try wip_nav.refType(field_type); + try diw.writeUleb128(field_bit_offset); + field_bit_offset += @intCast(field_type.bitSize(zcu)); + } + if (need_terminator) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); + }, + } + }, + .union_type => { + const loaded_union = ip.loadUnionType(value_index); + const file = loaded_union.zir_index.resolveFile(ip); + const need_terminator: bool = if (loaded_union.name_nav.unwrap()) |nav_index| t: { + const nav = ip.getNav(nav_index); + const decl_inst = nav.srcInst(ip).resolve(ip).?; + const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); + try wip_nav.declCommon(.{ + .decl = .decl_union, + .generic_decl = .generic_decl_const, + .decl_instance = .decl_instance_union, + }, &nav, file, &decl); + break :t true; + } else t: { + const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); + try wip_nav.abbrevCode(if (loaded_union.field_types.len > 0) .union_type else .empty_union_type); + try diw.writeUleb128(file_gop.index); + try wip_nav.strp(loaded_union.name.toSlice(ip)); + break :t loaded_union.field_types.len > 0; + }; + const union_layout = Type.getUnionLayout(loaded_union, zcu); + try diw.writeUleb128(union_layout.abi_size); + try diw.writeUleb128(union_layout.abi_align.toByteUnits().?); + const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); + if (loaded_union.has_runtime_tag) { + try wip_nav.abbrevCode(.tagged_union); + try wip_nav.infoSectionOffset( + .debug_info, + wip_nav.unit, + wip_nav.entry, + @intCast(diw.end + dwarf.sectionOffsetBytes()), + ); + { + try wip_nav.abbrevCode(.generated_field); + try wip_nav.strp("tag"); + try wip_nav.refType(.fromInterned(loaded_union.enum_tag_type)); + try diw.writeUleb128(union_layout.tagOffset()); + + for (0..loaded_union.field_types.len) |field_index| { + try wip_nav.enumConstValue(loaded_tag, .{ + .sdata = .signed_tagged_union_field, + .udata = .unsigned_tagged_union_field, + .block = .big_tagged_union_field, + }, field_index); + { + try wip_nav.abbrevCode(.struct_field); + try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); + const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); + try wip_nav.refType(field_type); + try diw.writeUleb128(union_layout.payloadOffset()); + try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse + if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); + } + try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); + } + } + try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); + } else for (0..loaded_union.field_types.len) |field_index| { + try wip_nav.abbrevCode(.untagged_union_field); + try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); + const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); + try wip_nav.refType(field_type); + try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse + if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); + } + if (need_terminator) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); + }, .enum_type => { - const loaded_enum = ip.loadEnumType(type_index); - try wip_nav.abbrevCode(if (loaded_enum.field_names.len == 0) .generated_empty_enum_type else .generated_enum_type); - try wip_nav.strp(name); - try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type)); - for (0..loaded_enum.field_names.len) |field_index| { - try wip_nav.enumConstValue(loaded_enum, .{ - .sdata = .signed_enum_field, - .udata = .unsigned_enum_field, - .block = .big_enum_field, - }, field_index); - try wip_nav.strp(loaded_enum.field_names.get(ip)[field_index].toSlice(ip)); + const loaded_enum = ip.loadEnumType(value_index); + if (loaded_enum.zir_index.unwrap()) |zir_index| { + assert(loaded_enum.owner_union == .none); + const file = zir_index.resolveFile(ip); + if (loaded_enum.name_nav.unwrap()) |nav_index| { + const nav = ip.getNav(nav_index); + const decl_inst = nav.srcInst(ip).resolve(ip).?; + const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); + try wip_nav.declCommon(if (loaded_enum.field_names.len > 0) .{ + .decl = .decl_enum, + .generic_decl = .generic_decl_const, + .decl_instance = .decl_instance_enum, + } else .{ + .decl = .decl_empty_enum, + .generic_decl = .generic_decl_const, + .decl_instance = .decl_instance_empty_enum, + }, &nav, file, &decl); + } else { + const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); + try wip_nav.abbrevCode(if (loaded_enum.field_names.len > 0) .enum_type else .empty_enum_type); + try diw.writeUleb128(file_gop.index); + try wip_nav.strp(loaded_enum.name.toSlice(ip)); + } + try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type)); + for (0..loaded_enum.field_names.len) |field_index| { + try wip_nav.enumConstValue(loaded_enum, .{ + .sdata = .signed_enum_field, + .udata = .unsigned_enum_field, + .block = .big_enum_field, + }, field_index); + try wip_nav.strp(loaded_enum.field_names.get(ip)[field_index].toSlice(ip)); + } + if (loaded_enum.field_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); + } else { + assert(loaded_enum.owner_union != .none); + try wip_nav.abbrevCode(if (loaded_enum.field_names.len == 0) .generated_empty_enum_type else .generated_enum_type); + try wip_nav.strp(loaded_enum.name.toSlice(ip)); + try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type)); + for (0..loaded_enum.field_names.len) |field_index| { + try wip_nav.enumConstValue(loaded_enum, .{ + .sdata = .signed_enum_field, + .udata = .unsigned_enum_field, + .block = .big_enum_field, + }, field_index); + try wip_nav.strp(loaded_enum.field_names.get(ip)[field_index].toSlice(ip)); + } + if (loaded_enum.field_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); } - if (loaded_enum.field_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); + }, + .opaque_type => { + const loaded_opaque = ip.loadOpaqueType(value_index); + const file = loaded_opaque.zir_index.resolveFile(ip); + if (loaded_opaque.name_nav.unwrap()) |nav_index| { + const nav = ip.getNav(nav_index); + const decl_inst = nav.srcInst(ip).resolve(ip).?; + const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); + try wip_nav.declCommon(.{ + .decl = .decl_namespace_struct, + .generic_decl = .generic_decl_const, + .decl_instance = .decl_instance_namespace_struct, + }, &nav, file, &decl); + } else { + const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); + try wip_nav.abbrevCode(.empty_struct_type); + try diw.writeUleb128(file_gop.index); + try wip_nav.strp(loaded_opaque.name.toSlice(ip)); + } + try diw.writeByte(@intFromBool(true)); }, .func_type => |func_type| { const is_nullary = func_type.param_types.len == 0 and !func_type.is_var_args; try wip_nav.abbrevCode(if (is_nullary) .nullary_func_type else .func_type); - try wip_nav.strp(name); + try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); const cc: DW.CC = cc: { if (zcu.getTarget().cCallingConvention()) |cc| { if (@as(std.builtin.CallingConvention.Tag, cc) == func_type.cc) { @@ -3975,7 +4105,7 @@ fn updateLazyType( }, .error_set_type => |error_set_type| { try wip_nav.abbrevCode(if (error_set_type.names.len == 0) .generated_empty_enum_type else .generated_enum_type); - try wip_nav.strp(name); + try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); try wip_nav.refType(.fromInterned(try pt.intern(.{ .int_type = .{ .signedness = .unsigned, .bits = zcu.errorSetBits(), @@ -3990,100 +4120,28 @@ fn updateLazyType( }, .inferred_error_set_type => |func| { try wip_nav.abbrevCode(.inferred_error_set_type); - try wip_nav.strp(name); + try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); try wip_nav.refType(.fromInterned(switch (ip.funcIesResolvedUnordered(func)) { .none => .anyerror_type, else => |ies| ies, })); }, - // values, not types - .simple_value, - .variable, - .@"extern", - .func, - .int, - .err, - .error_union, - .enum_literal, - .enum_tag, - .float, - .ptr, - .slice, - .opt, - .aggregate, - .un, - .bitpack, - // memoization, not types - .memoized_call, - => unreachable, - } - try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); -} - -fn updateLazyValue( - dwarf: *Dwarf, - pt: Zcu.PerThread, - src_loc: Zcu.LazySrcLoc, - value_index: InternPool.Index, - pending_lazy: *WipNav.PendingLazy, -) (UpdateError || Writer.Error)!void { - const zcu = pt.zcu; - const ip = &zcu.intern_pool; - assert(ip.typeOf(value_index) != .type_type); - log.debug("updateLazyValue(@as({f}, {f}))", .{ - Value.fromInterned(value_index).typeOf(zcu).fmt(pt), - Value.fromInterned(value_index).fmtValue(pt), - }); - var wip_nav: WipNav = .{ - .dwarf = dwarf, - .pt = pt, - .unit = .main, - .entry = dwarf.values.get(value_index).?, - .any_children = false, - .func = .none, - .func_sym_index = undefined, - .func_high_pc = undefined, - .blocks = undefined, - .cfi = undefined, - .debug_frame = .init(dwarf.gpa), - .debug_info = .init(dwarf.gpa), - .debug_line = .init(dwarf.gpa), - .debug_loclists = .init(dwarf.gpa), - .pending_lazy = pending_lazy.*, - }; - defer { - pending_lazy.* = wip_nav.pending_lazy; - wip_nav.pending_lazy = .empty; - wip_nav.deinit(); - } - const diw = &wip_nav.debug_info.writer; - var big_int_space: Value.BigIntSpace = undefined; - switch (ip.indexToKey(value_index)) { - .int_type, - .ptr_type, - .array_type, - .vector_type, - .opt_type, - .anyframe_type, - .error_union_type, - .simple_type, - .struct_type, - .tuple_type, - .union_type, - .opaque_type, - .enum_type, - .func_type, - .error_set_type, - .inferred_error_set_type, - => unreachable, // already handled .undef => |ty| { try wip_nav.abbrevCode(.undefined_comptime_value); try wip_nav.refType(.fromInterned(ty)); }, - .simple_value => unreachable, // opv state - .variable, .@"extern" => unreachable, // not a value - .func => unreachable, // already handled + .simple_value => |simple_value| switch (simple_value) { + .void => unreachable, // opv state + .true, .false => unreachable, // runtime bits + .@"unreachable" => unreachable, // not a value + .null => { + // TODO: proper representation for this + try wip_nav.abbrevCode(.undefined_comptime_value); + try wip_nav.refType(.null); + }, + }, + .variable => unreachable, // not a value .int => |int| { try wip_nav.bigIntConstValue(.{ .sdata = .sdata_comptime_value, @@ -4202,7 +4260,7 @@ fn updateLazyValue( var byte_offset = ptr.byte_offset; const base_unit, const base_entry = while (true) { const base_ptr, const access: Access = base_ptr_access: switch (base_addr) { - .nav => |nav_index| break try wip_nav.getNavEntry(nav_index), + .nav => |nav_index| break try dwarf.getNavEntry(nav_index), .comptime_alloc, .comptime_field => unreachable, .uav => |uav| { const uav_ty: Type = .fromInterned(ip.typeOf(uav.val)); @@ -4319,17 +4377,7 @@ fn updateLazyValue( switch (optRepr(opt_child_type, zcu)) { .opv_null => try diw.writeUleb128(0), .unpacked => try wip_nav.blockValue(src_loc, .makeBool(opt.val != .none)), - .error_set => try wip_nav.blockValue(src_loc, .fromInterned(value_index)), - .pointer => if (opt_child_type.comptimeOnly(zcu)) { - var buf: [8]u8 = undefined; - const bytes = buf[0..@divExact(zcu.getTarget().ptrBitWidth(), 8)]; - dwarf.writeInt(bytes, switch (opt.val) { - .none => 0, - else => opt_child_type.ptrAlignment(zcu).toByteUnits().?, - }); - try diw.writeUleb128(bytes.len); - try diw.writeAll(bytes); - } else try wip_nav.blockValue(src_loc, .fromInterned(value_index)), + .error_set, .pointer => try wip_nav.blockValue(src_loc, .fromInterned(value_index)), } } if (opt.val != .none) child_field: { @@ -4457,7 +4505,8 @@ fn updateLazyValue( }, .memoized_call => unreachable, // not a value } - try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); + try dwarf.debug_info.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_info.written()); + try dwarf.debug_loclists.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_loclists.written()); } fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum { unpacked, opv_null, error_set, pointer } { @@ -4472,312 +4521,6 @@ fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum { unpacked, opv_null, err }; } -pub fn updateContainerType( - dwarf: *Dwarf, - pt: Zcu.PerThread, - type_index: InternPool.Index, -) UpdateError!void { - return dwarf.updateContainerTypeWriterError(pt, type_index) catch |err| switch (err) { - error.WriteFailed => error.OutOfMemory, - else => |e| e, - }; -} -fn updateContainerTypeWriterError( - dwarf: *Dwarf, - pt: Zcu.PerThread, - type_index: InternPool.Index, -) (UpdateError || Writer.Error)!void { - const zcu = pt.zcu; - const ip = &zcu.intern_pool; - const ty: Type = .fromInterned(type_index); - const ty_src_loc = ty.srcLoc(zcu); - log.debug("updateContainerType({f})", .{ty.fmt(pt)}); - - const inst_info = ty.typeDeclInst(zcu).?.resolveFull(ip).?; - const file = zcu.fileByIndex(inst_info.file); - const unit = try dwarf.getUnit(file.mod.?); - const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, inst_info.file); - if (inst_info.inst == .main_struct_inst) { - const type_gop = try dwarf.types.getOrPut(dwarf.gpa, type_index); - if (!type_gop.found_existing) type_gop.value_ptr.* = try dwarf.addCommonEntry(unit); - var wip_nav: WipNav = .{ - .dwarf = dwarf, - .pt = pt, - .unit = unit, - .entry = type_gop.value_ptr.*, - .any_children = false, - .func = .none, - .func_sym_index = undefined, - .func_high_pc = undefined, - .blocks = undefined, - .cfi = undefined, - .debug_frame = .init(dwarf.gpa), - .debug_info = .init(dwarf.gpa), - .debug_line = .init(dwarf.gpa), - .debug_loclists = .init(dwarf.gpa), - .pending_lazy = .empty, - }; - defer wip_nav.deinit(); - - const loaded_struct = ip.loadStructType(type_index); - - const diw = &wip_nav.debug_info.writer; - try wip_nav.abbrevCode(if (loaded_struct.field_types.len == 0) .empty_file else .file); - try diw.writeUleb128(file_gop.index); - try wip_nav.strp(loaded_struct.name.toSlice(ip)); - if (loaded_struct.field_types.len > 0) { - try diw.writeUleb128(ty.abiSize(zcu)); - try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); - for (0..loaded_struct.field_types.len) |field_index| { - const is_comptime = loaded_struct.field_is_comptime_bits.get(ip, field_index); - const field_init = loaded_struct.field_defaults.getOrNone(ip, field_index); - assert(!(is_comptime and field_init == .none)); - const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - const has_runtime_bits, const has_comptime_state = switch (field_init) { - .none => .{ false, false }, - else => .{ - field_type.hasRuntimeBits(zcu), - field_type.comptimeOnly(zcu), - }, - }; - try wip_nav.abbrevCode(if (is_comptime) - if (has_comptime_state) - .struct_field_comptime_comptime_state - else if (has_runtime_bits) - .struct_field_comptime_runtime_bits - else - .struct_field_comptime - else if (field_init != .none) - if (has_comptime_state) - .struct_field_default_comptime_state - else if (has_runtime_bits) - .struct_field_default_runtime_bits - else - .struct_field - else - .struct_field); - try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip)); - try wip_nav.refType(field_type); - if (!is_comptime) { - try diw.writeUleb128(loaded_struct.field_offsets.get(ip)[field_index]); - try diw.writeUleb128(loaded_struct.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse - field_type.abiAlignment(zcu).toByteUnits().?); - } - if (has_comptime_state) - try wip_nav.refValue(.fromInterned(field_init)) - else if (has_runtime_bits) - try wip_nav.blockValue(ty_src_loc, .fromInterned(field_init)); - } - try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); - } - - try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); - try wip_nav.updateLazy(ty_src_loc); - } else { - { - // Note that changes to ZIR instruction tracking only need to update this code - // if a newly-tracked instruction can be a type's owner `zir_index`. - comptime assert(Zir.inst_tracking_version == 0); - - const decl_inst = file.zir.?.instructions.get(@intFromEnum(inst_info.inst)); - const name_strat: Zir.Inst.NameStrategy = switch (decl_inst.tag) { - .struct_init, .struct_init_ref, .struct_init_anon => .anon, - .extended => switch (decl_inst.data.extended.opcode) { - .struct_decl => file.zir.?.getStructDecl(inst_info.inst).name_strategy, - .union_decl => file.zir.?.getUnionDecl(inst_info.inst).name_strategy, - .enum_decl => file.zir.?.getEnumDecl(inst_info.inst).name_strategy, - .opaque_decl => file.zir.?.getOpaqueDecl(inst_info.inst).name_strategy, - - .reify_enum, - .reify_struct, - .reify_union, - => @enumFromInt(decl_inst.data.extended.small), - - else => unreachable, - }, - else => unreachable, - }; - if (name_strat == .parent) return; - } - - const type_gop = try dwarf.types.getOrPut(dwarf.gpa, type_index); - if (!type_gop.found_existing) type_gop.value_ptr.* = try dwarf.addCommonEntry(unit); - var wip_nav: WipNav = .{ - .dwarf = dwarf, - .pt = pt, - .unit = unit, - .entry = type_gop.value_ptr.*, - .any_children = false, - .func = .none, - .func_sym_index = undefined, - .func_high_pc = undefined, - .blocks = undefined, - .cfi = undefined, - .debug_frame = .init(dwarf.gpa), - .debug_info = .init(dwarf.gpa), - .debug_line = .init(dwarf.gpa), - .debug_loclists = .init(dwarf.gpa), - .pending_lazy = .empty, - }; - defer wip_nav.deinit(); - const diw = &wip_nav.debug_info.writer; - const name = try std.fmt.allocPrint(dwarf.gpa, "{f}", .{ty.fmt(pt)}); - defer dwarf.gpa.free(name); - - switch (ip.indexToKey(type_index)) { - .struct_type => { - const loaded_struct = ip.loadStructType(type_index); - switch (loaded_struct.layout) { - .auto, .@"extern" => { - try wip_nav.abbrevCode(if (loaded_struct.field_types.len == 0) .empty_struct_type else .struct_type); - try diw.writeUleb128(file_gop.index); - try wip_nav.strp(name); - if (loaded_struct.field_types.len == 0) try diw.writeByte(@intFromBool(false)) else { - try diw.writeUleb128(ty.abiSize(zcu)); - try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); - for (0..loaded_struct.field_types.len) |field_index| { - const is_comptime = loaded_struct.field_is_comptime_bits.get(ip, field_index); - const field_init = loaded_struct.field_defaults.getOrNone(ip, field_index); - assert(!(is_comptime and field_init == .none)); - const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - const has_runtime_bits, const has_comptime_state = switch (field_init) { - .none => .{ false, false }, - else => .{ - field_type.hasRuntimeBits(zcu), - field_type.comptimeOnly(zcu), - }, - }; - try wip_nav.abbrevCode(if (is_comptime) - if (has_comptime_state) - .struct_field_comptime_comptime_state - else if (has_runtime_bits) - .struct_field_comptime_runtime_bits - else - .struct_field_comptime - else if (field_init != .none) - if (has_comptime_state) - .struct_field_default_comptime_state - else if (has_runtime_bits) - .struct_field_default_runtime_bits - else - .struct_field - else - .struct_field); - try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip)); - try wip_nav.refType(field_type); - if (!is_comptime) { - try diw.writeUleb128(loaded_struct.field_offsets.get(ip)[field_index]); - try diw.writeUleb128(loaded_struct.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse - field_type.abiAlignment(zcu).toByteUnits().?); - } - if (has_comptime_state) - try wip_nav.refValue(.fromInterned(field_init)) - else if (has_runtime_bits) - try wip_nav.blockValue(ty_src_loc, .fromInterned(field_init)); - } - try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); - } - }, - .@"packed" => { - try wip_nav.abbrevCode(if (loaded_struct.field_types.len > 0) .packed_struct_type else .empty_packed_struct_type); - try diw.writeUleb128(file_gop.index); - try wip_nav.strp(name); - try wip_nav.refType(.fromInterned(loaded_struct.packed_backing_int_type)); - var field_bit_offset: u16 = 0; - for (0..loaded_struct.field_types.len) |field_index| { - try wip_nav.abbrevCode(.packed_struct_field); - try wip_nav.strp(loaded_struct.field_names.get(ip)[field_index].toSlice(ip)); - const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - try wip_nav.refType(field_type); - try diw.writeUleb128(field_bit_offset); - field_bit_offset += @intCast(field_type.bitSize(zcu)); - } - if (loaded_struct.field_types.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); - }, - } - }, - .enum_type => { - const loaded_enum = ip.loadEnumType(type_index); - try wip_nav.abbrevCode(if (loaded_enum.field_names.len > 0) .enum_type else .empty_enum_type); - try diw.writeUleb128(file_gop.index); - try wip_nav.strp(name); - try wip_nav.refType(.fromInterned(loaded_enum.int_tag_type)); - for (0..loaded_enum.field_names.len) |field_index| { - try wip_nav.enumConstValue(loaded_enum, .{ - .sdata = .signed_enum_field, - .udata = .unsigned_enum_field, - .block = .big_enum_field, - }, field_index); - try wip_nav.strp(loaded_enum.field_names.get(ip)[field_index].toSlice(ip)); - } - if (loaded_enum.field_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); - }, - .union_type => { - const loaded_union = ip.loadUnionType(type_index); - try wip_nav.abbrevCode(if (loaded_union.field_types.len > 0) .union_type else .empty_union_type); - try diw.writeUleb128(file_gop.index); - try wip_nav.strp(name); - const union_layout = Type.getUnionLayout(loaded_union, zcu); - try diw.writeUleb128(union_layout.abi_size); - try diw.writeUleb128(union_layout.abi_align.toByteUnits().?); - const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); - if (loaded_union.has_runtime_tag) { - try wip_nav.abbrevCode(.tagged_union); - try wip_nav.infoSectionOffset( - .debug_info, - wip_nav.unit, - wip_nav.entry, - @intCast(diw.end + dwarf.sectionOffsetBytes()), - ); - { - try wip_nav.abbrevCode(.generated_field); - try wip_nav.strp("tag"); - try wip_nav.refType(.fromInterned(loaded_union.enum_tag_type)); - try diw.writeUleb128(union_layout.tagOffset()); - - for (0..loaded_union.field_types.len) |field_index| { - try wip_nav.enumConstValue(loaded_tag, .{ - .sdata = .signed_tagged_union_field, - .udata = .unsigned_tagged_union_field, - .block = .big_tagged_union_field, - }, field_index); - { - try wip_nav.abbrevCode(.struct_field); - try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); - const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); - try wip_nav.refType(field_type); - try diw.writeUleb128(union_layout.payloadOffset()); - try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse - if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); - } - try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); - } - } - try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); - } else for (0..loaded_union.field_types.len) |field_index| { - try wip_nav.abbrevCode(.untagged_union_field); - try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); - const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); - try wip_nav.refType(field_type); - try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse - if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); - } - if (loaded_union.field_types.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); - }, - .opaque_type => { - try wip_nav.abbrevCode(.empty_struct_type); - try diw.writeUleb128(file_gop.index); - try wip_nav.strp(name); - try diw.writeByte(@intFromBool(true)); - }, - else => unreachable, - } - try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); - try dwarf.debug_loclists.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_loclists.written()); - try wip_nav.updateLazy(ty_src_loc); - } -} - pub fn updateLineNumber(dwarf: *Dwarf, zcu: *Zcu, zir_index: InternPool.TrackedInst.Index) UpdateError!void { const comp = dwarf.bin_file.comp; const io = comp.io; @@ -4840,14 +4583,15 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Erro const comp = dwarf.bin_file.comp; const io = comp.io; + // Update `anyerror` based on the finished global error set. { - const type_gop = try dwarf.types.getOrPut(dwarf.gpa, .anyerror_type); - if (!type_gop.found_existing) type_gop.value_ptr.* = try dwarf.addCommonEntry(.main); + const index = try dwarf.const_pool.get(pt, .{ .dwarf = dwarf }, .anyerror_type); + const unit, const entry = dwarf.values.items[@intFromEnum(index)]; var wip_nav: WipNav = .{ .dwarf = dwarf, .pt = pt, - .unit = .main, - .entry = type_gop.value_ptr.*, + .unit = unit, + .entry = entry, .any_children = false, .func = .none, .func_sym_index = undefined, @@ -4858,7 +4602,6 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Erro .debug_info = .init(dwarf.gpa), .debug_line = .init(dwarf.gpa), .debug_loclists = .init(dwarf.gpa), - .pending_lazy = .empty, }; defer wip_nav.deinit(); const diw = &wip_nav.debug_info.writer; @@ -4876,7 +4619,7 @@ fn flushWriterError(dwarf: *Dwarf, pt: Zcu.PerThread) (FlushError || Writer.Erro } if (global_error_set_names.len > 0) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written()); - try wip_nav.updateLazy(.unneeded); + try dwarf.const_pool.flushPending(pt, .{ .dwarf = dwarf }); } for (dwarf.mods.keys(), dwarf.mods.values()) |mod, *mod_info| { @@ -5324,6 +5067,8 @@ const AbbrevCode = enum { inferred_error_set_type, ptr_type, ptr_sentinel_type, + ptr_aligned_type, + ptr_aligned_sentinel_type, is_const, is_volatile, array_type, @@ -5960,12 +5705,29 @@ const AbbrevCode = enum { .tag = .pointer_type, .attrs = &.{ .{ .name, .strp }, - .{ .alignment, .udata }, .{ .address_class, .data1 }, .{ .type, .ref_addr }, }, }, .ptr_sentinel_type = .{ + .tag = .pointer_type, + .attrs = &.{ + .{ .name, .strp }, + .{ .ZIG_sentinel, .block }, + .{ .address_class, .data1 }, + .{ .type, .ref_addr }, + }, + }, + .ptr_aligned_type = .{ + .tag = .pointer_type, + .attrs = &.{ + .{ .name, .strp }, + .{ .alignment, .udata }, + .{ .address_class, .data1 }, + .{ .type, .ref_addr }, + }, + }, + .ptr_aligned_sentinel_type = .{ .tag = .pointer_type, .attrs = &.{ .{ .name, .strp }, diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 85f37f88ce8b55c984f6d1e5c97c689b80659d4b..dd4c2abd248eafea4b6705a79a5c15eaf3b409d2 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1711,13 +1711,14 @@ pub fn updateContainerType( self: *Elf, pt: Zcu.PerThread, ty: InternPool.Index, + success: bool, ) link.File.UpdateContainerTypeError!void { if (build_options.skip_non_native and builtin.object_format != .elf) { @panic("Attempted to compile for object format that was disabled by build configuration"); } const zcu = pt.zcu; const gpa = zcu.gpa; - return self.zigObjectPtr().?.updateContainerType(pt, ty) catch |err| switch (err) { + return self.zigObjectPtr().?.updateContainerType(pt, ty, success) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, else => |e| { try zcu.failed_types.putNoClobber(gpa, ty, try Zcu.ErrorMsg.create( diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 9bf352c1b10bbf2ee85215dcba1f4225c5e843b9..91133412e8fc85f75e02070f546deb174a0c128a 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -1719,11 +1719,12 @@ pub fn updateContainerType( self: *ZigObject, pt: Zcu.PerThread, ty: InternPool.Index, + success: bool, ) !void { const tracy = trace(@src()); defer tracy.end(); - if (self.dwarf) |*dwarf| try dwarf.updateContainerType(pt, ty); + if (self.dwarf) |*dwarf| try dwarf.updateContainerType(pt, ty, success); } fn updateLazySymbol( -- 2.54.0 From 0a7387c41004b8378c75e476c8a4bd058b15030d Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Wed, 11 Feb 2026 15:22:52 +0000 Subject: [PATCH 41/79] jacob broke the law --- src/Sema.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sema.zig b/src/Sema.zig index 81bce68e682a19a2d1895b5d2e7ce6af6c6ad820..686bb62bb3a777b19e19679c9368ff667f69961e 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -22236,7 +22236,7 @@ fn checkAtomicPtrOperand( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - try elem_ty.resolveLayout(pt); + try sema.ensureLayoutResolved(elem_ty, elem_ty_src, .ptr_access); var diag: Zcu.AtomicPtrAlignmentDiagnostics = .{}; const alignment = zcu.atomicPtrAlignment(elem_ty, &diag) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, -- 2.54.0 From f7a1ccfc56ed2d5605aa6ee25ac8d609f4c0d2a5 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Thu, 12 Feb 2026 11:10:52 +0000 Subject: [PATCH 42/79] compiler: fix up LLVM backend, and improve its debug info The LLVM backend can now run the behavior tests and standard library tests, like the x86_64 backend can. This commit required me to make a lot of changes to how the LLVM backend lowers debug information, and while I was doing that, I improved a few things: * `anyerror` is now an enum type (and other error sets just wrap it), so error values appear by name in debuggers * Fixed broken lowering for tagged unions with zero-width payloads * Associate container types with source locations in all cases * Avoid depending on the order of type resolution (using the new `DebugConstPool` abstraction), so debug information will contain all available type information rather than just the subset which happens to be resolved when the backend lowers that debug type --- lib/std/zig/llvm/BitcodeReader.zig | 10 +- lib/std/zig/llvm/Builder.zig | 101 +- src/Sema.zig | 29 +- src/Zcu/PerThread.zig | 8 +- src/codegen/aarch64/abi.zig | 2 +- src/codegen/arm/abi.zig | 24 +- src/codegen/llvm.zig | 1637 +++++++++++++--------------- src/codegen/mips/abi.zig | 2 +- src/codegen/riscv64/abi.zig | 4 +- src/codegen/wasm/abi.zig | 6 +- src/link.zig | 6 +- src/link/DebugConstPool.zig | 3 + src/link/Dwarf.zig | 2 +- 13 files changed, 859 insertions(+), 975 deletions(-) diff --git a/lib/std/zig/llvm/BitcodeReader.zig b/lib/std/zig/llvm/BitcodeReader.zig index d7b923c3c83c3625c80c57756d27f52323975786..e32e8afc033e0dc233bb7f37aea493f6bbcb1c9e 100644 --- a/lib/std/zig/llvm/BitcodeReader.zig +++ b/lib/std/zig/llvm/BitcodeReader.zig @@ -34,8 +34,8 @@ pub const Block = struct { const default: Info = .{ .block_name = &.{}, - .record_names = .{}, - .abbrevs = .{ .abbrevs = .{} }, + .record_names = .empty, + .abbrevs = .{ .abbrevs = .empty }, }; const set_bid_id: u32 = 1; @@ -109,8 +109,8 @@ pub fn init(allocator: std.mem.Allocator, options: InitOptions) BitcodeReader { .keep_names = options.keep_names, .bit_buffer = 0, .bit_offset = 0, - .stack = .{}, - .block_info = .{}, + .stack = .empty, + .block_info = .empty, }; } @@ -278,7 +278,7 @@ fn startBlock(bc: *BitcodeReader, block_id: ?u32, new_abbrev_len: u6) !void { state.* = .{ .block_id = block_id, .abbrev_id_width = new_abbrev_len, - .abbrevs = .{ .abbrevs = .{} }, + .abbrevs = .{ .abbrevs = .empty }, }; try state.abbrevs.abbrevs.ensureTotalCapacity( bc.allocator, diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index 66d20df34810c62e2741ed066906a519032af6ef..81b99c25725a20f0bbb7ed61ac611974e98d6dac 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -1627,7 +1627,7 @@ pub const FunctionAttributes = enum(u32) { const params_index = 2; pub const Wip = struct { - maps: Maps = .{}, + maps: Maps = .empty, const Map = std.AutoArrayHashMapUnmanaged(Attribute.Kind, Attribute.Index); const Maps = std.ArrayList(Map); @@ -4048,7 +4048,7 @@ pub const Function = struct { section: String = .none, alignment: Alignment = .default, blocks: []const Block = &.{}, - instructions: std.MultiArrayList(Instruction) = .{}, + instructions: std.MultiArrayList(Instruction) = .empty, names: [*]const String = &[0]String{}, value_indices: [*]const u32 = &[0]u32{}, strip: bool, @@ -5222,13 +5222,13 @@ pub const WipFunction = struct { .prev_debug_location = .no_location, .debug_location = .no_location, .cursor = undefined, - .blocks = .{}, - .instructions = .{}, - .names = .{}, + .blocks = .empty, + .instructions = .empty, + .names = .empty, .strip = options.strip, - .debug_locations = .{}, - .debug_values = .{}, - .extra = .{}, + .debug_locations = .empty, + .debug_values = .empty, + .extra = .empty, }; errdefer self.deinit(); @@ -5265,7 +5265,7 @@ pub const WipFunction = struct { self.blocks.appendAssumeCapacity(.{ .name = final_name, .incoming = incoming, - .instructions = .{}, + .instructions = .empty, }); return index; } @@ -6325,7 +6325,7 @@ pub const WipFunction = struct { function.blocks = &.{}; gpa.free(function.names[0..function.instructions.len]); function.debug_locations.deinit(gpa); - function.debug_locations = .{}; + function.debug_locations = .empty; gpa.free(function.debug_values); function.debug_values = &.{}; gpa.free(function.extra); @@ -8391,7 +8391,7 @@ pub const Metadata = packed struct(u32) { map: std.AutoArrayHashMapUnmanaged(union(enum) { metadata: Metadata, debug_location: DebugLocation.Location, - }, void) = .{}, + }, void) = .empty, const FormatData = struct { formatter: *Formatter, @@ -8649,52 +8649,52 @@ pub fn init(options: Options) Allocator.Error!Builder { .source_filename = .none, .data_layout = .none, .target_triple = .none, - .module_asm = .{}, + .module_asm = .empty, - .string_map = .{}, - .string_indices = .{}, - .string_bytes = .{}, + .string_map = .empty, + .string_indices = .empty, + .string_bytes = .empty, - .types = .{}, + .types = .empty, .next_unnamed_type = @enumFromInt(0), - .next_unique_type_id = .{}, - .type_map = .{}, - .type_items = .{}, - .type_extra = .{}, + .next_unique_type_id = .empty, + .type_map = .empty, + .type_items = .empty, + .type_extra = .empty, - .attributes = .{}, - .attributes_map = .{}, - .attributes_indices = .{}, - .attributes_extra = .{}, + .attributes = .empty, + .attributes_map = .empty, + .attributes_indices = .empty, + .attributes_extra = .empty, - .function_attributes_set = .{}, + .function_attributes_set = .empty, - .globals = .{}, + .globals = .empty, .next_unnamed_global = @enumFromInt(0), .next_replaced_global = .none, - .next_unique_global_id = .{}, - .aliases = .{}, - .variables = .{}, - .functions = .{}, + .next_unique_global_id = .empty, + .aliases = .empty, + .variables = .empty, + .functions = .empty, - .strtab_string_map = .{}, - .strtab_string_indices = .{}, - .strtab_string_bytes = .{}, + .strtab_string_map = .empty, + .strtab_string_indices = .empty, + .strtab_string_bytes = .empty, - .constant_map = .{}, - .constant_items = .{}, - .constant_extra = .{}, - .constant_limbs = .{}, + .constant_map = .empty, + .constant_items = .empty, + .constant_extra = .empty, + .constant_limbs = .empty, - .metadata_map = .{}, - .metadata_items = .{}, - .metadata_extra = .{}, - .metadata_limbs = .{}, - .metadata_forward_references = .{}, - .metadata_named = .{}, - .metadata_string_map = .{}, - .metadata_string_indices = .{}, - .metadata_string_bytes = .{}, + .metadata_map = .empty, + .metadata_items = .empty, + .metadata_extra = .empty, + .metadata_limbs = .empty, + .metadata_forward_references = .empty, + .metadata_named = .empty, + .metadata_string_map = .empty, + .metadata_string_indices = .empty, + .metadata_string_bytes = .empty, }; errdefer self.deinit(); @@ -12069,7 +12069,7 @@ pub fn trailingMetadataStringAssumeCapacity(self: *Builder) Metadata.String { const start = self.metadata_string_indices.getLast(); const bytes: []const u8 = self.metadata_string_bytes.items[start..]; assert(bytes.len > 0); - const gop = self.metadata_string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self }); + const gop = self.metadata_string_map.getOrPutAssumeCapacityAdapted(bytes, Metadata.String.Adapter{ .builder = self }); if (gop.found_existing) { self.metadata_string_bytes.shrinkRetainingCapacity(start); } else { @@ -12467,11 +12467,12 @@ pub fn metadataConstant(self: *Builder, value: Constant) Allocator.Error!Metadat return self.metadataConstantAssumeCapacity(value); } +/// Resolves the given forward reference to the given value (which is not itself a forward +/// reference). If the forward reference is already resolved, its target is replaced. pub fn resolveDebugForwardReference(self: *Builder, fwd_ref: Metadata, value: Metadata) void { assert(fwd_ref.kind == .forward); - const resolved = &self.metadata_forward_references.items[fwd_ref.index]; - assert(resolved.is_none); - resolved.* = value.toOptional(); + assert(value.kind != .forward); + self.metadata_forward_references.items[fwd_ref.index] = value.toOptional(); } fn metadataSimpleAssumeCapacity(self: *Builder, tag: Metadata.Tag, value: anytype) Metadata { diff --git a/src/Sema.zig b/src/Sema.zig index 686bb62bb3a777b19e19679c9368ff667f69961e..f1f2d895165a9408b06b2672dadfb52000d81ff1 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -7096,7 +7096,13 @@ fn analyzeCall( } } for (args, 0..) |arg, arg_idx| { - try sema.validateRuntimeValue(block, args_info.argSrc(block, arg_idx), arg); + const arg_src = args_info.argSrc(block, arg_idx); + const arg_ty = sema.typeOf(arg); + try sema.validateRuntimeValue(block, arg_src, arg); + if (arg_ty.isPtrAtRuntime(zcu) or arg_ty.isSliceAtRuntime(zcu)) { + // LLVM wants this information for an "align" attribute on the argument. + try sema.ensureLayoutResolved(arg_ty.nullablePtrElem(zcu), arg_src, .init); + } } const runtime_func: Air.Inst.Ref, const runtime_args: []const Air.Inst.Ref = func: { if (!any_generic_types and !any_comptime_params) break :func .{ callee, args }; @@ -24270,6 +24276,13 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void const elem = try sema.coerce(block, dest_elem_ty, uncoerced_elem, value_src); + const comptime_only_elem = switch (dest_elem_ty.classify(zcu)) { + .no_possible_value => unreachable, // `elem` is a value of this type + .one_possible_value => return, // no work to do + .runtime => false, + .partially_comptime, .fully_comptime => true, + }; + const runtime_src = rs: { const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls), dest_src); const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse break :rs dest_src; @@ -24299,6 +24312,15 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void return sema.storePtrVal(block, src, array_ptr_val, array_val, array_ty); }; + if (comptime_only_elem) { + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(src, "cannot store comptime-only element '{f}' at runtime", .{dest_elem_ty.fmt(pt)}); + errdefer msg.destroy(sema.gpa); + try sema.errNote(dest_src, msg, "operation is runtime due to destination pointer", .{}); + break :msg msg; + }); + } + try sema.requireRuntimeBlock(block, src, runtime_src); try sema.validateRuntimeValue(block, dest_src, dest_ptr); try sema.validateRuntimeValue(block, value_src, elem); @@ -27063,6 +27085,11 @@ fn elemPtrArray( try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op); } + if (array_ty.childType(zcu).abiSize(zcu) == 0) { + // zero-bit child type; just bitcast the pointer + return block.addBitCast(elem_ptr_ty, array_ptr); + } + return block.addPtrElemPtr(array_ptr, elem_index, elem_ptr_ty); } diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index babf66ee720fe48fbb8d8d46ab5cd85344229318..73cb527f79791881e05d28cdb18f0bb63ec43737 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -2926,7 +2926,13 @@ fn analyzeFuncBodyInner( const param_ty: Type = .fromInterned(fn_ty_info.param_types.get(ip)[runtime_param_index]); runtime_param_index += 1; - try sema.ensureLayoutResolved(param_ty, inner_block.src(.{ .func_decl_param_ty = @intCast(zir_param_index) }), .parameter); + const param_ty_src = inner_block.src(.{ .func_decl_param_ty = @intCast(zir_param_index) }); + + try sema.ensureLayoutResolved(param_ty, param_ty_src, .parameter); + if (param_ty.isPtrAtRuntime(zcu) or param_ty.isSliceAtRuntime(zcu)) { + // LLVM wants this information for an "align" attribute on the parameter. + try sema.ensureLayoutResolved(param_ty.nullablePtrElem(zcu), param_ty_src, .parameter); + } if (try param_ty.onePossibleValue(pt)) |opv| { gop.value_ptr.* = .fromValue(opv); continue; diff --git a/src/codegen/aarch64/abi.zig b/src/codegen/aarch64/abi.zig index 9587415287d52becdb1f4d2e33d8e522134f3cd3..5b32aded166799de4851622e9235ae1f2914fa5c 100644 --- a/src/codegen/aarch64/abi.zig +++ b/src/codegen/aarch64/abi.zig @@ -13,7 +13,7 @@ pub const Class = union(enum) { /// For `float_array` the second element will be the amount of floats. pub fn classifyType(ty: Type, zcu: *Zcu) Class { - assert(ty.hasRuntimeBitsIgnoreComptime(zcu)); + assert(ty.hasRuntimeBits(zcu)); var maybe_float_bits: ?u16 = null; switch (ty.zigTypeTag(zcu)) { diff --git a/src/codegen/arm/abi.zig b/src/codegen/arm/abi.zig index 23606d6145c45d80f1dde0d1405337fb2b1958bd..22bd34274f49e24d5538302a1a9c285414085c01 100644 --- a/src/codegen/arm/abi.zig +++ b/src/codegen/arm/abi.zig @@ -23,7 +23,7 @@ pub const Class = union(enum) { pub const Context = enum { ret, arg }; pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { - assert(ty.hasRuntimeBitsIgnoreComptime(zcu)); + assert(ty.hasRuntimeBits(zcu)); var maybe_float_bits: ?u16 = null; const max_byval_size = 512; @@ -39,22 +39,22 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { const float_count = countFloats(ty, zcu, &maybe_float_bits); if (float_count <= byval_float_count) return .byval; + if (ty.abiAlignment(zcu).compare(.gt, .@"32")) { + return Class.arrSize(bit_size, 64); + } + const fields = ty.structFieldCount(zcu); var i: u32 = 0; while (i < fields) : (i += 1) { const field_ty = ty.fieldType(i, zcu); - const field_alignment = ty.fieldAlignment(i, zcu); - const field_size = field_ty.bitSize(zcu); - if (field_size > 32 or field_alignment.compare(.gt, .@"32")) { - return Class.arrSize(bit_size, 64); - } + if (field_ty.bitSize(zcu) > 32) return Class.arrSize(bit_size, 64); } return Class.arrSize(bit_size, 32); }, .@"union" => { const bit_size = ty.bitSize(zcu); const union_obj = zcu.typeToUnion(ty).?; - if (union_obj.flagsUnordered(ip).layout == .@"packed") { + if (union_obj.layout == .@"packed") { if (bit_size > 64) return .memory; return .byval; } @@ -62,10 +62,12 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { const float_count = countFloats(ty, zcu, &maybe_float_bits); if (float_count <= byval_float_count) return .byval; - for (union_obj.field_types.get(ip), 0..) |field_ty, field_index| { - if (Type.fromInterned(field_ty).bitSize(zcu) > 32 or - ty.fieldAlignment(field_index, zcu).compare(.gt, .@"32")) - { + if (union_obj.alignment.compareStrict(.gt, .@"32")) { + return Class.arrSize(bit_size, 64); + } + + for (union_obj.field_types.get(ip)) |field_ty| { + if (Type.fromInterned(field_ty).bitSize(zcu) > 32) { return Class.arrSize(bit_size, 64); } } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index b952f8c22567527c10c76afcd7c8970481418263..185dcb0fe1702e632661b49b8c1d80250c5a7b4a 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -23,6 +23,7 @@ const Package = @import("../Package.zig"); const Air = @import("../Air.zig"); const Value = @import("../Value.zig"); const Type = @import("../Type.zig"); +const DebugConstPool = link.DebugConstPool; const codegen = @import("../codegen.zig"); const x86_64_abi = @import("x86_64/abi.zig"); const wasm_c_abi = @import("wasm/abi.zig"); @@ -529,9 +530,15 @@ pub const Object = struct { debug_globals: std.ArrayList(Builder.Metadata), debug_file_map: std.AutoHashMapUnmanaged(Zcu.File.Index, Builder.Metadata), - debug_type_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Metadata), - debug_unresolved_namespace_scopes: std.AutoArrayHashMapUnmanaged(InternPool.NamespaceIndex, Builder.Metadata), + /// This pool *only* contains types (and does not contain `@as(type, undefined)`). + debug_type_pool: DebugConstPool, + /// Keyed on `DebugConstPool.Index`. + debug_types: std.ArrayList(Builder.Metadata), + /// Initially `.none`, set if the type `anyerror` is lowered to a debug type. The type will not + /// actually be created until `emit`, which must resolve this reference with an appropriate enum + /// type from the global error set. + debug_anyerror_fwd_ref: Builder.Metadata.Optional, target: *const std.Target, /// Ideally we would use `llvm_module.getNamedFunction` to go from *Decl to LLVM function, @@ -657,21 +664,22 @@ pub const Object = struct { .debug_compile_unit = debug_compile_unit, .debug_enums_fwd_ref = debug_enums_fwd_ref, .debug_globals_fwd_ref = debug_globals_fwd_ref, - .debug_enums = .{}, - .debug_globals = .{}, - .debug_file_map = .{}, - .debug_type_map = .{}, - .debug_unresolved_namespace_scopes = .{}, + .debug_enums = .empty, + .debug_globals = .empty, + .debug_file_map = .empty, + .debug_type_pool = .empty, + .debug_types = .empty, + .debug_anyerror_fwd_ref = .none, .target = target, - .nav_map = .{}, - .uav_map = .{}, - .enum_tag_name_map = .{}, - .named_enum_map = .{}, - .type_map = .{}, + .nav_map = .empty, + .uav_map = .empty, + .enum_tag_name_map = .empty, + .named_enum_map = .empty, + .type_map = .empty, .error_name_table = .none, .null_opt_usize = .no_init, - .struct_field_map = .{}, - .used = .{}, + .struct_field_map = .empty, + .used = .empty, }; return obj; } @@ -681,8 +689,8 @@ pub const Object = struct { self.debug_enums.deinit(gpa); self.debug_globals.deinit(gpa); self.debug_file_map.deinit(gpa); - self.debug_type_map.deinit(gpa); - self.debug_unresolved_namespace_scopes.deinit(gpa); + self.debug_type_pool.deinit(gpa); + self.debug_types.deinit(gpa); self.nav_map.deinit(gpa); self.uav_map.deinit(gpa); self.enum_tag_name_map.deinit(gpa); @@ -824,19 +832,13 @@ pub const Object = struct { } if (!o.builder.strip) { - { - var i: usize = 0; - while (i < o.debug_unresolved_namespace_scopes.count()) : (i += 1) { - const namespace_index = o.debug_unresolved_namespace_scopes.keys()[i]; - const fwd_ref = o.debug_unresolved_namespace_scopes.values()[i]; - - const namespace = zcu.namespacePtr(namespace_index); - const debug_type = try o.lowerDebugType(pt, Type.fromInterned(namespace.owner_type)); - - o.builder.resolveDebugForwardReference(fwd_ref, debug_type); - } + if (o.debug_anyerror_fwd_ref.unwrap()) |fwd_ref| { + const debug_anyerror_type = try o.lowerDebugAnyerrorType(pt); + o.builder.resolveDebugForwardReference(fwd_ref, debug_anyerror_type); } + try o.flushPendingDebugTypes(pt); + o.builder.resolveDebugForwardReference( o.debug_enums_fwd_ref.unwrap().?, try o.builder.metadataTuple(o.debug_enums.items), @@ -1472,7 +1474,7 @@ pub const Object = struct { const line_number = zcu.navSrcLine(func.owner_nav) + 1; const is_internal_linkage = ip.indexToKey(nav.status.fully_resolved.val) != .@"extern"; - const debug_decl_type = try o.lowerDebugType(pt, fn_ty); + const debug_decl_type = try o.getDebugType(pt, fn_ty); const subprogram = try o.builder.debugSubprogram( file, @@ -1522,7 +1524,7 @@ pub const Object = struct { break :f .{ .counters_variable = counters_variable, - .pcs = .{}, + .pcs = .empty, }; }; @@ -1538,10 +1540,10 @@ pub const Object = struct { .args = args.items, .arg_index = 0, .arg_inline_index = 0, - .func_inst_table = .{}, - .blocks = .{}, - .loops = .{}, - .switch_dispatch_info = .{}, + .func_inst_table = .empty, + .blocks = .empty, + .loops = .empty, + .switch_dispatch_info = .empty, .sync_scope = if (owner_mod.single_threaded) .singlethread else .system, .file = file, .scope = subprogram, @@ -1599,6 +1601,7 @@ pub const Object = struct { } try fg.wip.finish(); + try o.flushPendingDebugTypes(pt); } pub fn updateNav(self: *Object, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { @@ -1615,6 +1618,14 @@ pub const Object = struct { }, else => |e| return e, }; + try self.flushPendingDebugTypes(pt); + } + + fn flushPendingDebugTypes(o: *Object, pt: Zcu.PerThread) Allocator.Error!void { + o.debug_type_pool.flushPending(pt, .{ .llvm = o }) catch |err| switch (err) { + error.OutOfMemory => |e| return e, + else => unreachable, // TODO: stop self-hosted backends from returning all of this crap! + }; } pub fn updateExports( @@ -1810,6 +1821,57 @@ pub const Object = struct { } } + pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Allocator.Error!void { + if (!o.builder.strip) { + o.debug_type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success) catch |err| switch (err) { + error.OutOfMemory => |e| return e, + else => unreachable, // TODO: stop self-hosted backends from returning all of this crap! + }; + } + } + + /// Should only be called by the `DebugConstPool` implementation. + /// + /// `val` is always a type because `o.debug_type_pool` only contains types. + pub fn addConst(o: *Object, pt: Zcu.PerThread, index: DebugConstPool.Index, val: InternPool.Index) Allocator.Error!void { + const zcu = pt.zcu; + const gpa = zcu.comp.gpa; + assert(zcu.intern_pool.typeOf(val) == .type_type); + assert(@intFromEnum(index) == o.debug_types.items.len); + try o.debug_types.ensureUnusedCapacity(gpa, 1); + const fwd_ref = try o.builder.debugForwardReference(); + o.debug_types.appendAssumeCapacity(fwd_ref); + if (val == .anyerror_type) { + assert(o.debug_anyerror_fwd_ref.is_none); + o.debug_anyerror_fwd_ref = fwd_ref.toOptional(); + } + } + /// Should only be called by the `DebugConstPool` implementation. + /// + /// `val` is always a type because `o.debug_type_pool` only contains types. + pub fn updateConstIncomplete(o: *Object, pt: Zcu.PerThread, index: DebugConstPool.Index, val: InternPool.Index) Allocator.Error!void { + assert(pt.zcu.intern_pool.typeOf(val) == .type_type); + const fwd_ref = o.debug_types.items[@intFromEnum(index)]; + assert(val != .anyerror_type); + const name_str = try o.builder.metadataStringFmt("{f}", .{Type.fromInterned(val).fmt(pt)}); + const debug_incomplete_type = try o.builder.debugSignedType(name_str, 0); + o.builder.resolveDebugForwardReference(fwd_ref, debug_incomplete_type); + } + /// Should only be called by the `DebugConstPool` implementation. + /// + /// `val` is always a type because `o.debug_type_pool` only contains types. + pub fn updateConst(o: *Object, pt: Zcu.PerThread, index: DebugConstPool.Index, val: InternPool.Index) Allocator.Error!void { + assert(pt.zcu.intern_pool.typeOf(val) == .type_type); + const fwd_ref = o.debug_types.items[@intFromEnum(index)]; + if (val == .anyerror_type) { + // Don't lower this now; it will be populated in `emit` instead. + assert(o.debug_anyerror_fwd_ref == fwd_ref.toOptional()); + return; + } + const debug_type = try o.lowerDebugType(pt, .fromInterned(val), fwd_ref); + o.builder.resolveDebugForwardReference(fwd_ref, debug_type); + } + fn getDebugFile(o: *Object, pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator.Error!Builder.Metadata { const gpa = o.gpa; const gop = try o.debug_file_map.getOrPut(gpa, file_index); @@ -1826,10 +1888,22 @@ pub const Object = struct { return gop.value_ptr.*; } - pub fn lowerDebugType( + fn getDebugType(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error!Builder.Metadata { + assert(!o.builder.strip); + const index = o.debug_type_pool.get(pt, .{ .llvm = o }, ty.toIntern()) catch |err| switch (err) { + error.OutOfMemory => |e| return e, + else => unreachable, // TODO: stop self-hosted backends from returning all of this crap! + }; + return o.debug_types.items[@intFromEnum(index)]; + } + + /// In codegen logic, instead of calling this directly, use `getDebugType` to get a forward + /// reference which will be populated only when all necessary type resolution is complete. + fn lowerDebugType( o: *Object, pt: Zcu.PerThread, ty: Type, + ty_fwd_ref: Builder.Metadata, ) Allocator.Error!Builder.Metadata { assert(!o.builder.strip); @@ -1838,267 +1912,96 @@ pub const Object = struct { const zcu = pt.zcu; const ip = &zcu.intern_pool; - if (o.debug_type_map.get(ty.toIntern())) |debug_type| return debug_type; + const name = try o.builder.metadataStringFmt("{f}", .{ty.fmt(pt)}); switch (ty.zigTypeTag(zcu)) { .void, .noreturn, - => { - const debug_void_type = try o.builder.debugSignedType( - try o.builder.metadataString("void"), - 0, - ); - try o.debug_type_map.put(gpa, ty.toIntern(), debug_void_type); - return debug_void_type; - }, + .comptime_int, + .comptime_float, + .type, + .undefined, + .null, + .enum_literal, + => return o.builder.debugSignedType(name, 0), + .int => { const info = ty.intInfo(zcu); - assert(info.bits != 0); - const name = try o.allocTypeName(pt, ty); - defer gpa.free(name); - const builder_name = try o.builder.metadataString(name); - const debug_bits = ty.abiSize(zcu) * 8; // lldb cannot handle non-byte sized types - const debug_int_type = switch (info.signedness) { - .signed => try o.builder.debugSignedType(builder_name, debug_bits), - .unsigned => try o.builder.debugUnsignedType(builder_name, debug_bits), + const bits = ty.abiSize(zcu) * 8; // lldb cannot handle non-byte sized types + return switch (info.signedness) { + .signed => try o.builder.debugSignedType(name, bits), + .unsigned => try o.builder.debugUnsignedType(name, bits), }; - try o.debug_type_map.put(gpa, ty.toIntern(), debug_int_type); - return debug_int_type; - }, - .@"enum" => { - if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) { - const debug_enum_type = try o.makeEmptyNamespaceDebugType(pt, ty); - try o.debug_type_map.put(gpa, ty.toIntern(), debug_enum_type); - return debug_enum_type; - } - - const enum_type = ip.loadEnumType(ty.toIntern()); - const enumerators = try gpa.alloc(Builder.Metadata, enum_type.names.len); - defer gpa.free(enumerators); - - const int_ty = Type.fromInterned(enum_type.tag_ty); - const int_info = ty.intInfo(zcu); - assert(int_info.bits != 0); - - for (enum_type.names.get(ip), 0..) |field_name_ip, i| { - var bigint_space: Value.BigIntSpace = undefined; - const bigint = if (enum_type.values.len != 0) - Value.fromInterned(enum_type.values.get(ip)[i]).toBigInt(&bigint_space, zcu) - else - std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst(); - - enumerators[i] = try o.builder.debugEnumerator( - try o.builder.metadataString(field_name_ip.toSlice(ip)), - int_info.signedness == .unsigned, - int_info.bits, - bigint, - ); - } - - const file = try o.getDebugFile(pt, ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip)); - const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| - try o.namespaceToDebugScope(pt, parent_namespace) - else - file; - - const name = try o.allocTypeName(pt, ty); - defer gpa.free(name); - - const debug_enum_type = try o.builder.debugEnumerationType( - try o.builder.metadataString(name), - file, - scope, - ty.typeDeclSrcLine(zcu).? + 1, // Line - try o.lowerDebugType(pt, int_ty), - ty.abiSize(zcu) * 8, - (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, - try o.builder.metadataTuple(enumerators), - ); - - try o.debug_type_map.put(gpa, ty.toIntern(), debug_enum_type); - try o.debug_enums.append(gpa, debug_enum_type); - return debug_enum_type; }, .float => { - const bits = ty.floatBits(target); - const name = try o.allocTypeName(pt, ty); - defer gpa.free(name); - const debug_float_type = try o.builder.debugFloatType( - try o.builder.metadataString(name), - bits, - ); - try o.debug_type_map.put(gpa, ty.toIntern(), debug_float_type); - return debug_float_type; + return o.builder.debugFloatType(name, ty.floatBits(target)); }, .bool => { - const debug_bool_type = try o.builder.debugBoolType( - try o.builder.metadataString("bool"), + return o.builder.debugBoolType( + name, 8, // lldb cannot handle non-byte sized types ); - try o.debug_type_map.put(gpa, ty.toIntern(), debug_bool_type); - return debug_bool_type; }, .pointer => { - // Normalize everything that the debug info does not represent. - const ptr_info = ty.ptrInfo(zcu); - - if (ptr_info.sentinel != .none or - ptr_info.flags.address_space != .generic or - ptr_info.packed_offset.bit_offset != 0 or - ptr_info.packed_offset.host_size != 0 or - ptr_info.flags.vector_index != .none or - ptr_info.flags.is_allowzero or - ptr_info.flags.is_const or - ptr_info.flags.is_volatile or - ptr_info.flags.size == .many or ptr_info.flags.size == .c or - !Type.fromInterned(ptr_info.child).hasRuntimeBitsIgnoreComptime(zcu)) - { - const bland_ptr_ty = try pt.ptrType(.{ - .child = if (!Type.fromInterned(ptr_info.child).hasRuntimeBitsIgnoreComptime(zcu)) - .anyopaque_type - else - ptr_info.child, - .flags = .{ - .alignment = ptr_info.flags.alignment, - .size = switch (ptr_info.flags.size) { - .many, .c, .one => .one, - .slice => .slice, - }, - }, - }); - const debug_ptr_type = try o.lowerDebugType(pt, bland_ptr_ty); - try o.debug_type_map.put(gpa, ty.toIntern(), debug_ptr_type); - return debug_ptr_type; - } - - const debug_fwd_ref = try o.builder.debugForwardReference(); - - // Set as forward reference while the type is lowered in case it references itself - try o.debug_type_map.put(gpa, ty.toIntern(), debug_fwd_ref); + const ptr_size = Type.ptrAbiSize(zcu.getTarget()); + const ptr_align = Type.ptrAbiAlignment(zcu.getTarget()); if (ty.isSlice(zcu)) { - const ptr_ty = ty.slicePtrFieldType(zcu); - const len_ty = Type.usize; - - const name = try o.allocTypeName(pt, ty); - defer gpa.free(name); - const line = 0; - - const ptr_size = ptr_ty.abiSize(zcu); - const ptr_align = ptr_ty.abiAlignment(zcu); - const len_size = len_ty.abiSize(zcu); - const len_align = len_ty.abiAlignment(zcu); - - const len_offset = len_align.forward(ptr_size); - const debug_ptr_type = try o.builder.debugMemberType( try o.builder.metadataString("ptr"), null, // File - debug_fwd_ref, + ty_fwd_ref, 0, // Line - try o.lowerDebugType(pt, ptr_ty), + try o.getDebugType(pt, ty.slicePtrFieldType(zcu)), ptr_size * 8, - (ptr_align.toByteUnits() orelse 0) * 8, + ptr_align.toByteUnits().? * 8, 0, // Offset ); const debug_len_type = try o.builder.debugMemberType( try o.builder.metadataString("len"), null, // File - debug_fwd_ref, + ty_fwd_ref, 0, // Line - try o.lowerDebugType(pt, len_ty), - len_size * 8, - (len_align.toByteUnits() orelse 0) * 8, - len_offset * 8, + try o.getDebugType(pt, .usize), + ptr_size * 8, + ptr_align.toByteUnits().? * 8, + ptr_size * 8, ); - const debug_slice_type = try o.builder.debugStructType( - try o.builder.metadataString(name), + return o.builder.debugStructType( + name, null, // File o.debug_compile_unit.unwrap().?, // Scope - line, + 0, // Line null, // Underlying type - ty.abiSize(zcu) * 8, - (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, + ptr_size * 2 * 8, + ptr_align.toByteUnits().? * 8, try o.builder.metadataTuple(&.{ debug_ptr_type, debug_len_type, }), ); - - o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_slice_type); - - // Set to real type now that it has been lowered fully - const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable; - map_ptr.* = debug_slice_type; - - return debug_slice_type; } - const debug_elem_ty = try o.lowerDebugType(pt, Type.fromInterned(ptr_info.child)); - - const name = try o.allocTypeName(pt, ty); - defer gpa.free(name); - - const debug_ptr_type = try o.builder.debugPointerType( - try o.builder.metadataString(name), + return o.builder.debugPointerType( + name, null, // File null, // Scope 0, // Line - debug_elem_ty, - target.ptrBitWidth(), - (ty.ptrAlignment(zcu).toByteUnits() orelse 0) * 8, + try o.getDebugType(pt, ty.childType(zcu)), + ptr_size * 8, + ptr_align.toByteUnits().? * 8, 0, // Offset ); - - o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_ptr_type); - - // Set to real type now that it has been lowered fully - const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable; - map_ptr.* = debug_ptr_type; - - return debug_ptr_type; - }, - .@"opaque" => { - if (ty.toIntern() == .anyopaque_type) { - const debug_opaque_type = try o.builder.debugSignedType( - try o.builder.metadataString("anyopaque"), - 0, - ); - try o.debug_type_map.put(gpa, ty.toIntern(), debug_opaque_type); - return debug_opaque_type; - } - - const name = try o.allocTypeName(pt, ty); - defer gpa.free(name); - - const file = try o.getDebugFile(pt, ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip)); - const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| - try o.namespaceToDebugScope(pt, parent_namespace) - else - file; - - const debug_opaque_type = try o.builder.debugStructType( - try o.builder.metadataString(name), - file, - scope, - ty.typeDeclSrcLine(zcu).? + 1, // Line - null, // Underlying type - 0, // Size - 0, // Align - null, // Fields - ); - try o.debug_type_map.put(gpa, ty.toIntern(), debug_opaque_type); - return debug_opaque_type; }, .array => { - const debug_array_type = try o.builder.debugArrayType( + return o.builder.debugArrayType( null, // Name null, // File null, // Scope 0, // Line - try o.lowerDebugType(pt, ty.childType(zcu)), + try o.getDebugType(pt, ty.childType(zcu)), ty.abiSize(zcu) * 8, (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, try o.builder.metadataTuple(&.{ @@ -2108,8 +2011,6 @@ pub const Object = struct { ), }), ); - try o.debug_type_map.put(gpa, ty.toIntern(), debug_array_type); - return debug_array_type; }, .vector => { const elem_ty = ty.childType(zcu); @@ -2120,23 +2021,17 @@ pub const Object = struct { const debug_elem_type = switch (elem_ty.zigTypeTag(zcu)) { .int => blk: { const info = elem_ty.intInfo(zcu); - assert(info.bits != 0); - const name = try o.allocTypeName(pt, ty); - defer gpa.free(name); - const builder_name = try o.builder.metadataString(name); break :blk switch (info.signedness) { - .signed => try o.builder.debugSignedType(builder_name, info.bits), - .unsigned => try o.builder.debugUnsignedType(builder_name, info.bits), + .signed => try o.builder.debugSignedType(name, info.bits), + .unsigned => try o.builder.debugUnsignedType(name, info.bits), }; }, - .bool => try o.builder.debugBoolType( - try o.builder.metadataString("bool"), - 1, - ), - else => try o.lowerDebugType(pt, ty.childType(zcu)), + .bool => try o.builder.debugBoolType(try o.builder.metadataString("bool"), 1), + .pointer, .optional, .float => try o.getDebugType(pt, elem_ty), + else => unreachable, }; - const debug_vector_type = try o.builder.debugVectorType( + return o.builder.debugVectorType( null, // Name null, // File null, // Scope @@ -2151,71 +2046,64 @@ pub const Object = struct { ), }), ); - - try o.debug_type_map.put(gpa, ty.toIntern(), debug_vector_type); - return debug_vector_type; }, .optional => { - const name = try o.allocTypeName(pt, ty); - defer gpa.free(name); - const child_ty = ty.optionalChild(zcu); - if (!child_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - const debug_bool_type = try o.builder.debugBoolType( - try o.builder.metadataString(name), - 8, - ); - try o.debug_type_map.put(gpa, ty.toIntern(), debug_bool_type); - return debug_bool_type; - } - - const debug_fwd_ref = try o.builder.debugForwardReference(); - - // Set as forward reference while the type is lowered in case it references itself - try o.debug_type_map.put(gpa, ty.toIntern(), debug_fwd_ref); - + const payload_ty = ty.optionalChild(zcu); if (ty.optionalReprIsPayload(zcu)) { - const debug_optional_type = try o.lowerDebugType(pt, child_ty); - - o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_optional_type); - - // Set to real type now that it has been lowered fully - const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable; - map_ptr.* = debug_optional_type; - - return debug_optional_type; + // MLUGG TODO: these should use DW_TAG_typedef instead, but std.zig.llvm.Builder currently lacks support for those. + const payload_member = try o.builder.debugMemberType( + try o.builder.metadataString("payload"), + null, // file + ty_fwd_ref, + 0, // line + try o.getDebugType(pt, .anyerror), + ty.abiSize(zcu) * 8, + ty.abiAlignment(zcu).toByteUnits().? * 8, + 0, // offset + ); + return o.builder.debugStructType( + name, + null, // file + o.debug_compile_unit.unwrap().?, // scope + 0, // line + null, // underlying type + ty.abiSize(zcu) * 8, + ty.abiAlignment(zcu).toByteUnits().? * 8, + try o.builder.metadataTuple(&.{payload_member}), + ); } + const payload_size = payload_ty.abiSize(zcu); + const non_null_ty = Type.u8; - const payload_size = child_ty.abiSize(zcu); - const payload_align = child_ty.abiAlignment(zcu); const non_null_size = non_null_ty.abiSize(zcu); const non_null_align = non_null_ty.abiAlignment(zcu); const non_null_offset = non_null_align.forward(payload_size); - const debug_data_type = try o.builder.debugMemberType( - try o.builder.metadataString("data"), - null, // File - debug_fwd_ref, - 0, // Line - try o.lowerDebugType(pt, child_ty), + const debug_payload_type = try o.builder.debugMemberType( + try o.builder.metadataString("payload"), + null, // file + ty_fwd_ref, + 0, // line + try o.getDebugType(pt, payload_ty), payload_size * 8, - (payload_align.toByteUnits() orelse 0) * 8, - 0, // Offset + payload_ty.abiAlignment(zcu).toByteUnits().? * 8, + 0, // offset ); const debug_some_type = try o.builder.debugMemberType( try o.builder.metadataString("some"), null, - debug_fwd_ref, + ty_fwd_ref, 0, - try o.lowerDebugType(pt, non_null_ty), + try o.getDebugType(pt, non_null_ty), non_null_size * 8, - (non_null_align.toByteUnits() orelse 0) * 8, + non_null_align.toByteUnits().? * 8, non_null_offset * 8, ); - const debug_optional_type = try o.builder.debugStructType( - try o.builder.metadataString(name), + return o.builder.debugStructType( + name, null, // File o.debug_compile_unit.unwrap().?, // Scope 0, // Line @@ -2223,494 +2111,498 @@ pub const Object = struct { ty.abiSize(zcu) * 8, (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, try o.builder.metadataTuple(&.{ - debug_data_type, + debug_payload_type, debug_some_type, }), ); - - o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_optional_type); - - // Set to real type now that it has been lowered fully - const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable; - map_ptr.* = debug_optional_type; - - return debug_optional_type; }, .error_union => { + const error_ty = ty.errorUnionSet(zcu); const payload_ty = ty.errorUnionPayload(zcu); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - // TODO: Maybe remove? - const debug_error_union_type = try o.lowerDebugType(pt, Type.anyerror); - try o.debug_type_map.put(gpa, ty.toIntern(), debug_error_union_type); - return debug_error_union_type; - } - const name = try o.allocTypeName(pt, ty); - defer gpa.free(name); - - const error_size = Type.anyerror.abiSize(zcu); - const error_align = Type.anyerror.abiAlignment(zcu); + const error_size = error_ty.abiSize(zcu); + const error_align = error_ty.abiAlignment(zcu); const payload_size = payload_ty.abiSize(zcu); const payload_align = payload_ty.abiAlignment(zcu); - var error_index: u32 = undefined; - var payload_index: u32 = undefined; - var error_offset: u64 = undefined; - var payload_offset: u64 = undefined; - if (error_align.compare(.gt, payload_align)) { - error_index = 0; - payload_index = 1; - error_offset = 0; - payload_offset = payload_align.forward(error_size); - } else { - payload_index = 0; - error_index = 1; - payload_offset = 0; - error_offset = error_align.forward(payload_size); - } - - const debug_fwd_ref = try o.builder.debugForwardReference(); + const error_index: u1, const payload_index: u1, const error_offset: u64, const payload_offset: u64 = fields: { + if (error_align.compare(.gt, payload_align)) { + break :fields .{ 0, 1, 0, payload_align.forward(error_size) }; + } else { + break :fields .{ 1, 0, error_align.forward(payload_size), 0 }; + } + }; var fields: [2]Builder.Metadata = undefined; fields[error_index] = try o.builder.debugMemberType( - try o.builder.metadataString("tag"), + try o.builder.metadataString("error"), null, // File - debug_fwd_ref, + ty_fwd_ref, 0, // Line - try o.lowerDebugType(pt, Type.anyerror), + try o.getDebugType(pt, error_ty), error_size * 8, - (error_align.toByteUnits() orelse 0) * 8, + error_align.toByteUnits().? * 8, error_offset * 8, ); fields[payload_index] = try o.builder.debugMemberType( - try o.builder.metadataString("value"), + try o.builder.metadataString("payload"), null, // File - debug_fwd_ref, + ty_fwd_ref, 0, // Line - try o.lowerDebugType(pt, payload_ty), + try o.getDebugType(pt, payload_ty), payload_size * 8, - (payload_align.toByteUnits() orelse 0) * 8, + payload_align.toByteUnits().? * 8, payload_offset * 8, ); - const debug_error_union_type = try o.builder.debugStructType( - try o.builder.metadataString(name), + return try o.builder.debugStructType( + name, null, // File - o.debug_compile_unit.unwrap().?, // Sope + o.debug_compile_unit.unwrap().?, // Scope 0, // Line null, // Underlying type ty.abiSize(zcu) * 8, - (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, + ty.abiAlignment(zcu).toByteUnits().? * 8, try o.builder.metadataTuple(&fields), ); - - o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_error_union_type); - - try o.debug_type_map.put(gpa, ty.toIntern(), debug_error_union_type); - return debug_error_union_type; }, .error_set => { - const debug_error_set = try o.builder.debugUnsignedType( - try o.builder.metadataString("anyerror"), - 16, + assert(ty.toIntern() != .anyerror_type); // handled specially in `updateConst`; will be populated by `emit` instead + // Error sets are just named wrappers around `anyerror`. + // MLUGG TODO: these should use DW_TAG_typedef instead, but std.zig.llvm.Builder currently lacks support for those. + const anyerror_member = try o.builder.debugMemberType( + try o.builder.metadataString("error"), + null, // file + ty_fwd_ref, + 0, // line + try o.getDebugType(pt, .anyerror), + ty.abiSize(zcu) * 8, + ty.abiAlignment(zcu).toByteUnits().? * 8, + 0, // offset + ); + return o.builder.debugStructType( + name, + null, // file + o.debug_compile_unit.unwrap().?, // scope + 0, // line + null, // underlying type + ty.abiSize(zcu) * 8, + ty.abiAlignment(zcu).toByteUnits().? * 8, + try o.builder.metadataTuple(&.{anyerror_member}), + ); + }, + .@"fn" => { + if (!ty.fnHasRuntimeBits(zcu)) { + return o.builder.debugSignedType(name, 0); + } + + const fn_info = zcu.typeToFunc(ty).?; + + var debug_param_types: std.ArrayList(Builder.Metadata) = try .initCapacity(gpa, 3 + fn_info.param_types.len); + defer debug_param_types.deinit(gpa); + + // Return type goes first. + const sret = firstParamSRet(fn_info, zcu, target); + const ret_ty: Type = if (sret) .void else .fromInterned(fn_info.return_type); + debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, ret_ty)); + + if (sret) { + const ptr_ty = try pt.singleMutPtrType(Type.fromInterned(fn_info.return_type)); + debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, ptr_ty)); + } + + if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) { + // Stack trace pointer. + debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, .ptr_usize)); + } + + for (fn_info.param_types.get(ip)) |param_ty_ip| { + const param_ty: Type = .fromInterned(param_ty_ip); + if (!param_ty.hasRuntimeBits(zcu)) continue; + if (isByRef(param_ty, zcu)) { + const ptr_ty = try pt.singleConstPtrType(param_ty); + debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, ptr_ty)); + } else { + debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, param_ty)); + } + } + + return o.builder.debugSubroutineType( + try o.builder.metadataTuple(debug_param_types.items), ); - try o.debug_type_map.put(gpa, ty.toIntern(), debug_error_set); - return debug_error_set; }, .@"struct" => { - const name = try o.allocTypeName(pt, ty); - defer gpa.free(name); - - if (zcu.typeToPackedStruct(ty)) |struct_type| { - const backing_int_ty = struct_type.backingIntTypeUnordered(ip); - if (backing_int_ty != .none) { - const info = Type.fromInterned(backing_int_ty).intInfo(zcu); - const builder_name = try o.builder.metadataString(name); - const debug_int_type = switch (info.signedness) { - .signed => try o.builder.debugSignedType(builder_name, ty.abiSize(zcu) * 8), - .unsigned => try o.builder.debugUnsignedType(builder_name, ty.abiSize(zcu) * 8), - }; - try o.debug_type_map.put(gpa, ty.toIntern(), debug_int_type); - return debug_int_type; + if (ty.isTuple(zcu)) { + const tuple = ip.indexToKey(ty.toIntern()).tuple_type; + var fields: std.ArrayList(Builder.Metadata) = .empty; + defer fields.deinit(gpa); + + try fields.ensureUnusedCapacity(gpa, tuple.types.len); + + comptime assert(struct_layout_version == 2); + var offset: u64 = 0; + + for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty_ip, field_val, i| { + const field_ty: Type = .fromInterned(field_ty_ip); + if (field_val != .none or !field_ty.hasRuntimeBits(zcu)) continue; + + const field_size = field_ty.abiSize(zcu); + const field_align = field_ty.abiAlignment(zcu); + const field_offset = field_align.forward(offset); + offset = field_offset + field_size; + + fields.appendAssumeCapacity(try o.builder.debugMemberType( + try o.builder.metadataStringFmt("{d}", .{i}), + null, // file + ty_fwd_ref, + 0, // line + try o.getDebugType(pt, field_ty), + field_size * 8, + field_align.toByteUnits().? * 8, + field_offset * 8, + )); } + + return o.builder.debugStructType( + name, + null, // file + o.debug_compile_unit.unwrap().?, + 0, // line + null, // underlying type + ty.abiSize(zcu) * 8, + (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, + try o.builder.metadataTuple(fields.items), + ); } - switch (ip.indexToKey(ty.toIntern())) { - .tuple_type => |tuple| { - var fields: std.ArrayList(Builder.Metadata) = .empty; - defer fields.deinit(gpa); + const struct_type = zcu.typeToStruct(ty).?; - try fields.ensureUnusedCapacity(gpa, tuple.types.len); + const file = try o.getDebugFile(pt, struct_type.zir_index.resolveFile(ip)); + const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| + try o.namespaceToDebugScope(pt, parent_namespace) + else + file; + const line = ty.typeDeclSrcLine(zcu).? + 1; + + var fields: std.ArrayList(Builder.Metadata) = .empty; + defer fields.deinit(gpa); + + switch (struct_type.layout) { + .@"packed" => { + try fields.ensureTotalCapacityPrecise(gpa, 1); + fields.appendAssumeCapacity(try o.builder.debugMemberType( + try o.builder.metadataString("bits"), + null, // file + ty_fwd_ref, + 0, // line + try o.getDebugType(pt, .fromInterned(struct_type.packed_backing_int_type)), + ty.abiSize(zcu) * 8, + ty.abiAlignment(zcu).toByteUnits().? * 8, + 0, // offset + )); + }, + .auto, .@"extern" => { comptime assert(struct_layout_version == 2); - var offset: u64 = 0; - - const debug_fwd_ref = try o.builder.debugForwardReference(); - - for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| { - if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue; - - const field_size = Type.fromInterned(field_ty).abiSize(zcu); - const field_align = Type.fromInterned(field_ty).abiAlignment(zcu); - const field_offset = field_align.forward(offset); - offset = field_offset + field_size; - - var name_buf: [32]u8 = undefined; - const field_name = std.fmt.bufPrint(&name_buf, "{d}", .{i}) catch unreachable; - + try fields.ensureTotalCapacityPrecise(gpa, struct_type.field_types.len); + var it = struct_type.iterateRuntimeOrder(ip); + while (it.next()) |field_index| { + const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); + if (!field_ty.hasRuntimeBits(zcu)) continue; + const field_size = field_ty.abiSize(zcu); + const field_align = switch (ty.explicitFieldAlignment(field_index, zcu)) { + .none => field_ty.abiAlignment(zcu), + else => |a| a, + }; + const field_offset = struct_type.field_offsets.get(ip)[field_index]; + const field_name = struct_type.field_names.get(ip)[field_index]; fields.appendAssumeCapacity(try o.builder.debugMemberType( - try o.builder.metadataString(field_name), - null, // File - debug_fwd_ref, - 0, - try o.lowerDebugType(pt, Type.fromInterned(field_ty)), + try o.builder.metadataString(field_name.toSlice(ip)), + null, // file + ty_fwd_ref, + 0, // line + try o.getDebugType(pt, field_ty), field_size * 8, - (field_align.toByteUnits() orelse 0) * 8, + field_align.toByteUnits().? * 8, field_offset * 8, )); } - - const debug_struct_type = try o.builder.debugStructType( - try o.builder.metadataString(name), - null, // File - o.debug_compile_unit.unwrap().?, // Scope - 0, // Line - null, // Underlying type - ty.abiSize(zcu) * 8, - (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, - try o.builder.metadataTuple(fields.items), - ); - - o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_struct_type); - - try o.debug_type_map.put(gpa, ty.toIntern(), debug_struct_type); - return debug_struct_type; - }, - .struct_type => { - if (!ip.loadStructType(ty.toIntern()).haveFieldTypes(ip)) { - // This can happen if a struct type makes it all the way to - // flush() without ever being instantiated or referenced (even - // via pointer). The only reason we are hearing about it now is - // that it is being used as a namespace to put other debug types - // into. Therefore we can satisfy this by making an empty namespace, - // rather than changing the frontend to unnecessarily resolve the - // struct field types. - const debug_struct_type = try o.makeEmptyNamespaceDebugType(pt, ty); - try o.debug_type_map.put(gpa, ty.toIntern(), debug_struct_type); - return debug_struct_type; - } }, - else => {}, - } - - if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) { - const debug_struct_type = try o.makeEmptyNamespaceDebugType(pt, ty); - try o.debug_type_map.put(gpa, ty.toIntern(), debug_struct_type); - return debug_struct_type; - } - - const struct_type = zcu.typeToStruct(ty).?; - - var fields: std.ArrayList(Builder.Metadata) = .empty; - defer fields.deinit(gpa); - - try fields.ensureUnusedCapacity(gpa, struct_type.field_types.len); - - const debug_fwd_ref = try o.builder.debugForwardReference(); - - // Set as forward reference while the type is lowered in case it references itself - try o.debug_type_map.put(gpa, ty.toIntern(), debug_fwd_ref); - - comptime assert(struct_layout_version == 2); - var it = struct_type.iterateRuntimeOrder(ip); - while (it.next()) |field_index| { - const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; - const field_size = field_ty.abiSize(zcu); - const field_align = ty.fieldAlignment(field_index, zcu); - const field_offset = ty.structFieldOffset(field_index, zcu); - const field_name = struct_type.fieldName(ip, field_index); - fields.appendAssumeCapacity(try o.builder.debugMemberType( - try o.builder.metadataString(field_name.toSlice(ip)), - null, // File - debug_fwd_ref, - 0, // Line - try o.lowerDebugType(pt, field_ty), - field_size * 8, - (field_align.toByteUnits() orelse 0) * 8, - field_offset * 8, - )); } - const debug_struct_type = try o.builder.debugStructType( - try o.builder.metadataString(name), - null, // File - o.debug_compile_unit.unwrap().?, // Scope - 0, // Line - null, // Underlying type + return o.builder.debugStructType( + name, + file, + scope, + line, + null, // underlying type ty.abiSize(zcu) * 8, - (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, + ty.abiAlignment(zcu).toByteUnits().? * 8, try o.builder.metadataTuple(fields.items), ); - - o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_struct_type); - - // Set to real type now that it has been lowered fully - const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable; - map_ptr.* = debug_struct_type; - - return debug_struct_type; }, .@"union" => { - const name = try o.allocTypeName(pt, ty); - defer gpa.free(name); - const union_type = ip.loadUnionType(ty.toIntern()); - if (!union_type.haveFieldTypes(ip) or - !ty.hasRuntimeBitsIgnoreComptime(zcu) or - !union_type.haveLayout(ip)) - { - const debug_union_type = try o.makeEmptyNamespaceDebugType(pt, ty); - try o.debug_type_map.put(gpa, ty.toIntern(), debug_union_type); - return debug_union_type; - } + const file = try o.getDebugFile(pt, union_type.zir_index.resolveFile(ip)); + const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| + try o.namespaceToDebugScope(pt, parent_namespace) + else + file; + + const line = ty.typeDeclSrcLine(zcu).? + 1; + + const enum_tag_ty: Type = .fromInterned(union_type.enum_tag_type); const layout = Type.getUnionLayout(union_type, zcu); - const debug_fwd_ref = try o.builder.debugForwardReference(); - - // Set as forward reference while the type is lowered in case it references itself - try o.debug_type_map.put(gpa, ty.toIntern(), debug_fwd_ref); - if (layout.payload_size == 0) { - const debug_union_type = try o.builder.debugStructType( - try o.builder.metadataString(name), - null, // File - o.debug_compile_unit.unwrap().?, // Scope - 0, // Line - null, // Underlying type + const tag_member = try o.builder.debugMemberType( + try o.builder.metadataString("tag"), + null, // file + ty_fwd_ref, + 0, // line + try o.getDebugType(pt, enum_tag_ty), + layout.tag_size * 8, + layout.tag_align.toByteUnits().? * 8, + 0, // offset + ); + return o.builder.debugStructType( + name, + file, + scope, + line, + null, // underlying type ty.abiSize(zcu) * 8, - (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, - try o.builder.metadataTuple( - &.{try o.lowerDebugType(pt, Type.fromInterned(union_type.enum_tag_ty))}, - ), + ty.abiAlignment(zcu).toByteUnits().? * 8, + try o.builder.metadataTuple(&.{tag_member}), ); - - // Set to real type now that it has been lowered fully - const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable; - map_ptr.* = debug_union_type; - - return debug_union_type; } - var fields: std.ArrayList(Builder.Metadata) = .empty; + var fields: std.ArrayList(Builder.Metadata) = try .initCapacity(gpa, union_type.field_types.len); defer fields.deinit(gpa); - try fields.ensureUnusedCapacity(gpa, union_type.loadTagType(ip).names.len); - - const debug_union_fwd_ref = if (layout.tag_size == 0) - debug_fwd_ref + const payload_fwd_ref = if (layout.tag_size == 0) + ty_fwd_ref else try o.builder.debugForwardReference(); - const tag_type = union_type.loadTagType(ip); - - for (0..tag_type.names.len) |field_index| { + for (0..union_type.field_types.len) |field_index| { const field_ty = union_type.field_types.get(ip)[field_index]; - if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(zcu)) continue; const field_size = Type.fromInterned(field_ty).abiSize(zcu); - const field_align: InternPool.Alignment = switch (union_type.flagsUnordered(ip).layout) { + const field_align: InternPool.Alignment = switch (union_type.layout) { .@"packed" => .none, - .auto, .@"extern" => ty.fieldAlignment(field_index, zcu), + .auto, .@"extern" => ty.explicitFieldAlignment(field_index, zcu), }; - const field_name = tag_type.names.get(ip)[field_index]; + const field_name = enum_tag_ty.enumFieldName(field_index, zcu); fields.appendAssumeCapacity(try o.builder.debugMemberType( try o.builder.metadataString(field_name.toSlice(ip)), - null, // File - debug_union_fwd_ref, - 0, // Line - try o.lowerDebugType(pt, Type.fromInterned(field_ty)), + null, // file + payload_fwd_ref, + 0, // line + try o.getDebugType(pt, .fromInterned(field_ty)), field_size * 8, (field_align.toByteUnits() orelse 0) * 8, - 0, // Offset + 0, // offset )); } - var union_name_buf: ?[:0]const u8 = null; - defer if (union_name_buf) |buf| gpa.free(buf); - const union_name = if (layout.tag_size == 0) name else name: { - union_name_buf = try std.fmt.allocPrintSentinel(gpa, "{s}:Payload", .{name}, 0); - break :name union_name_buf.?; - }; - - const debug_union_type = try o.builder.debugUnionType( - try o.builder.metadataString(union_name), - null, // File - o.debug_compile_unit.unwrap().?, // Scope - 0, // Line - null, // Underlying type + const debug_payload_type = try o.builder.debugUnionType( + payload_name: { + if (layout.tag_size == 0) break :payload_name name; + break :payload_name try o.builder.metadataStringFmt("{s}:Payload", .{name.slice(&o.builder)}); + }, + file, + scope, + line, + null, // underlying type layout.payload_size * 8, - (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, + ty.abiAlignment(zcu).toByteUnits().? * 8, try o.builder.metadataTuple(fields.items), ); - o.builder.resolveDebugForwardReference(debug_union_fwd_ref, debug_union_type); - if (layout.tag_size == 0) { - // Set to real type now that it has been lowered fully - const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable; - map_ptr.* = debug_union_type; - - return debug_union_type; + return debug_payload_type; } - var tag_offset: u64 = undefined; - var payload_offset: u64 = undefined; - if (layout.tag_align.compare(.gte, layout.payload_align)) { - tag_offset = 0; - payload_offset = layout.payload_align.forward(layout.tag_size); - } else { - payload_offset = 0; - tag_offset = layout.tag_align.forward(layout.payload_size); - } + o.builder.resolveDebugForwardReference(payload_fwd_ref, debug_payload_type); + + const tag_offset: u64, const payload_offset: u64 = offsets: { + if (layout.tag_align.compare(.gte, layout.payload_align)) { + break :offsets .{ 0, layout.payload_align.forward(layout.tag_size) }; + } else { + break :offsets .{ layout.tag_align.forward(layout.payload_size), 0 }; + } + }; - const debug_tag_type = try o.builder.debugMemberType( + const tag_member_type = try o.builder.debugMemberType( try o.builder.metadataString("tag"), - null, // File - debug_fwd_ref, - 0, // Line - try o.lowerDebugType(pt, Type.fromInterned(union_type.enum_tag_ty)), + null, // file + ty_fwd_ref, + 0, // line + try o.getDebugType(pt, enum_tag_ty), layout.tag_size * 8, - (layout.tag_align.toByteUnits() orelse 0) * 8, + layout.tag_align.toByteUnits().? * 8, tag_offset * 8, ); - const debug_payload_type = try o.builder.debugMemberType( + const payload_member_type = try o.builder.debugMemberType( try o.builder.metadataString("payload"), - null, // File - debug_fwd_ref, - 0, // Line - debug_union_type, + null, // file + ty_fwd_ref, + 0, // line + debug_payload_type, layout.payload_size * 8, - (layout.payload_align.toByteUnits() orelse 0) * 8, + layout.payload_align.toByteUnits().? * 8, payload_offset * 8, ); const full_fields: [2]Builder.Metadata = if (layout.tag_align.compare(.gte, layout.payload_align)) - .{ debug_tag_type, debug_payload_type } + .{ tag_member_type, payload_member_type } else - .{ debug_payload_type, debug_tag_type }; + .{ payload_member_type, tag_member_type }; - const debug_tagged_union_type = try o.builder.debugStructType( - try o.builder.metadataString(name), - null, // File - o.debug_compile_unit.unwrap().?, // Scope - 0, // Line - null, // Underlying type + return o.builder.debugStructType( + name, + file, + scope, + line, + null, // underlying type ty.abiSize(zcu) * 8, - (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, + ty.abiAlignment(zcu).toByteUnits().? * 8, try o.builder.metadataTuple(&full_fields), ); + }, + .@"enum" => { + const file = try o.getDebugFile(pt, ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip)); + const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| + try o.namespaceToDebugScope(pt, parent_namespace) + else + file; - o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_tagged_union_type); - - // Set to real type now that it has been lowered fully - const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable; - map_ptr.* = debug_tagged_union_type; + const line = ty.typeDeclSrcLine(zcu).? + 1; - return debug_tagged_union_type; - }, - .@"fn" => { - const fn_info = zcu.typeToFunc(ty).?; - - var debug_param_types = std.array_list.Managed(Builder.Metadata).init(gpa); - defer debug_param_types.deinit(); - - try debug_param_types.ensureUnusedCapacity(3 + fn_info.param_types.len); - - // Return type goes first. - if (Type.fromInterned(fn_info.return_type).hasRuntimeBitsIgnoreComptime(zcu)) { - const sret = firstParamSRet(fn_info, zcu, target); - const ret_ty = if (sret) Type.void else Type.fromInterned(fn_info.return_type); - debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, ret_ty)); - - if (sret) { - const ptr_ty = try pt.singleMutPtrType(Type.fromInterned(fn_info.return_type)); - debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, ptr_ty)); - } - } else { - debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, Type.void)); + if (!ty.hasRuntimeBits(zcu)) { + return o.builder.debugStructType( + name, + file, + scope, + line, + null, // underlying type + ty.abiSize(zcu) * 8, + ty.abiAlignment(zcu).toByteUnits().? * 8, + null, // fields + ); } - if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) { - // Stack trace pointer. - debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, .fromInterned(.ptr_usize_type))); - } + const enum_type = ip.loadEnumType(ty.toIntern()); + const enumerators = try gpa.alloc(Builder.Metadata, enum_type.field_names.len); + defer gpa.free(enumerators); - for (0..fn_info.param_types.len) |i| { - const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[i]); - if (!param_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + const int_ty: Type = .fromInterned(enum_type.int_tag_type); + const int_info = ty.intInfo(zcu); + assert(int_info.bits != 0); - if (isByRef(param_ty, zcu)) { - const ptr_ty = try pt.singleMutPtrType(param_ty); - debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, ptr_ty)); - } else { - debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, param_ty)); - } + for (enumerators, enum_type.field_names.get(ip), 0..) |*out, field_name, field_index| { + var space: Value.BigIntSpace = undefined; + const field_val: std.math.big.int.Const = switch (enum_type.field_values.len) { + 0 => std.math.big.int.Mutable.init(&space.limbs, field_index).toConst(), + else => Value.fromInterned(enum_type.field_values.get(ip)[field_index]).toBigInt(&space, zcu), + }; + out.* = try o.builder.debugEnumerator( + try o.builder.metadataString(field_name.toSlice(ip)), + int_info.signedness == .unsigned, + int_info.bits, + field_val, + ); } - const debug_function_type = try o.builder.debugSubroutineType( - try o.builder.metadataTuple(debug_param_types.items), + const debug_enum_type = try o.builder.debugEnumerationType( + name, + file, + scope, + line, + try o.getDebugType(pt, int_ty), + ty.abiSize(zcu) * 8, + ty.abiAlignment(zcu).toByteUnits().? * 8, + try o.builder.metadataTuple(enumerators), ); - - try o.debug_type_map.put(gpa, ty.toIntern(), debug_function_type); - return debug_function_type; + try o.debug_enums.append(gpa, debug_enum_type); + return debug_enum_type; }, - .comptime_int => unreachable, - .comptime_float => unreachable, - .type => unreachable, - .undefined => unreachable, - .null => unreachable, - .enum_literal => unreachable, + .@"opaque" => { + if (ty.toIntern() == .anyopaque_type) { + return o.builder.debugSignedType(name, 0); + } + + const file = try o.getDebugFile(pt, ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip)); + const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| + try o.namespaceToDebugScope(pt, parent_namespace) + else + file; + + const line = ty.typeDeclSrcLine(zcu).? + 1; + return o.builder.debugStructType( + name, + file, + scope, + line, + null, // underlying type + 0, // size + ty.abiAlignment(zcu).toByteUnits().? * 8, + null, // fields + ); + }, .frame => @panic("TODO implement lowerDebugType for Frame types"), .@"anyframe" => @panic("TODO implement lowerDebugType for AnyFrame types"), } } + /// Called in `emit` so that the global error set is fully populated. + fn lowerDebugAnyerrorType(o: *Object, pt: Zcu.PerThread) Allocator.Error!Builder.Metadata { + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + const gpa = zcu.comp.gpa; + + const error_set_bits = zcu.errorSetBits(); + const error_names = ip.global_error_set.getNamesFromMainThread(); + + const enumerators = try gpa.alloc(Builder.Metadata, error_names.len); + defer gpa.free(enumerators); + + for (enumerators, error_names, 1..) |*out, error_name, error_value| { + var space: Value.BigIntSpace = undefined; + var bigint: std.math.big.int.Mutable = .init(&space.limbs, error_value); + out.* = try o.builder.debugEnumerator( + try o.builder.metadataString(error_name.toSlice(ip)), + true, // unsigned + error_set_bits, + bigint.toConst(), + ); + } + + const debug_enum_type = try o.builder.debugEnumerationType( + try o.builder.metadataString("anyerror"), + null, // file + o.debug_compile_unit.unwrap().?, // scope + 0, // line + try o.getDebugType(pt, try pt.intType(.unsigned, error_set_bits)), + Type.anyerror.abiSize(zcu) * 8, + Type.anyerror.abiAlignment(zcu).toByteUnits().? * 8, + try o.builder.metadataTuple(enumerators), + ); + try o.debug_enums.append(gpa, debug_enum_type); + return debug_enum_type; + } + fn namespaceToDebugScope(o: *Object, pt: Zcu.PerThread, namespace_index: InternPool.NamespaceIndex) !Builder.Metadata { const zcu = pt.zcu; const namespace = zcu.namespacePtr(namespace_index); if (namespace.parent == .none) return try o.getDebugFile(pt, namespace.file_scope); - - const gop = try o.debug_unresolved_namespace_scopes.getOrPut(o.gpa, namespace_index); - - if (!gop.found_existing) gop.value_ptr.* = try o.builder.debugForwardReference(); - - return gop.value_ptr.*; - } - - fn makeEmptyNamespaceDebugType(o: *Object, pt: Zcu.PerThread, ty: Type) !Builder.Metadata { - const zcu = pt.zcu; - const ip = &zcu.intern_pool; - const file = try o.getDebugFile(pt, ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip)); - const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace| - try o.namespaceToDebugScope(pt, parent_namespace) - else - file; - return o.builder.debugStructType( - try o.builder.metadataString(ty.containerTypeName(ip).toSlice(ip)), // TODO use fully qualified name - file, - scope, - ty.typeDeclSrcLine(zcu).? + 1, - null, - 0, - 0, - null, - ); + return o.getDebugType(pt, .fromInterned(namespace.owner_type)); } fn allocTypeName(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error![:0]const u8 { @@ -2885,40 +2777,6 @@ pub const Object = struct { if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder); - // Add parameter attributes. We handle only the case of extern functions (no body) - // because functions with bodies are handled in `updateFunc`. - if (is_extern) { - var it = iterateParamTypes(o, pt, fn_info); - it.llvm_index = llvm_arg_i; - while (try it.next()) |lowering| switch (lowering) { - .byval => { - const param_index = it.zig_index - 1; - const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]); - if (!isByRef(param_ty, zcu)) { - try o.addByValParamAttrs(pt, &attributes, param_ty, param_index, fn_info, it.llvm_index - 1); - } - }, - .byref => { - const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); - const param_llvm_ty = try o.lowerType(pt, param_ty); - const alignment = param_ty.abiAlignment(zcu); - try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment.toLlvm(), it.byval_attr, param_llvm_ty); - }, - .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder), - // No attributes needed for these. - .no_bits, - .abi_sized_int, - .multiple_llvm_types, - .float_array, - .i32_array, - .i64_array, - => continue, - - .slice => unreachable, // extern functions do not support slice types. - - }; - } - function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); return function_index; } @@ -3223,7 +3081,7 @@ pub const Object = struct { ), .opt_type => |child_ty| { // Must stay in sync with `opt_payload` logic in `lowerPtr`. - if (!Type.fromInterned(child_ty).hasRuntimeBitsIgnoreComptime(zcu)) return .i8; + if (!Type.fromInterned(child_ty).hasRuntimeBits(zcu)) return .i8; const payload_ty = try o.lowerType(pt, Type.fromInterned(child_ty)); if (t.optionalReprIsPayload(zcu)) return payload_ty; @@ -3245,7 +3103,7 @@ pub const Object = struct { // Must stay in sync with `codegen.errUnionPayloadOffset`. // See logic in `lowerPtr`. const error_type = try o.errorIntType(pt); - if (!Type.fromInterned(error_union_type.payload_type).hasRuntimeBitsIgnoreComptime(zcu)) + if (!Type.fromInterned(error_union_type.payload_type).hasRuntimeBits(zcu)) return error_type; const payload_type = try o.lowerType(pt, Type.fromInterned(error_union_type.payload_type)); @@ -3287,7 +3145,7 @@ pub const Object = struct { const struct_type = ip.loadStructType(t.toIntern()); if (struct_type.layout == .@"packed") { - const int_ty = try o.lowerType(pt, Type.fromInterned(struct_type.backingIntTypeUnordered(ip))); + const int_ty = try o.lowerType(pt, .fromInterned(struct_type.packed_backing_int_type)); try o.type_map.put(o.gpa, t.toIntern(), int_ty); return int_ty; } @@ -3301,18 +3159,16 @@ pub const Object = struct { comptime assert(struct_layout_version == 2); var offset: u64 = 0; - var big_align: InternPool.Alignment = .@"1"; var struct_kind: Builder.Type.Structure.Kind = .normal; // When we encounter a zero-bit field, we place it here so we know to map it to the next non-zero-bit field (if any). var it = struct_type.iterateRuntimeOrder(ip); while (it.next()) |field_index| { const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); - const field_align = t.fieldAlignment(field_index, zcu); - const field_ty_align = field_ty.abiAlignment(zcu); - if (field_align.compare(.lt, field_ty_align)) struct_kind = .@"packed"; - big_align = big_align.max(field_align); const prev_offset = offset; - offset = field_align.forward(offset); + offset = struct_type.field_offsets.get(ip)[field_index]; + if (@ctz(offset) < field_ty.abiAlignment(zcu).toLog2Units()) { + struct_kind = .@"packed"; + } const padding_len = offset - prev_offset; if (padding_len > 0) try llvm_field_types.append( @@ -3320,11 +3176,11 @@ pub const Object = struct { try o.builder.arrayType(padding_len, .i8), ); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!field_ty.hasRuntimeBits(zcu)) { // This is a zero-bit field. If there are runtime bits after this field, // map to the next LLVM field (which we know exists): otherwise, don't // map the field, indicating it's at the end of the struct. - if (offset != struct_type.sizeUnordered(ip)) { + if (offset != struct_type.size) { try o.struct_field_map.put(o.gpa, .{ .struct_ty = t.toIntern(), .field_index = field_index, @@ -3343,7 +3199,7 @@ pub const Object = struct { } { const prev_offset = offset; - offset = big_align.forward(offset); + offset = struct_type.alignment.forward(offset); const padding_len = offset - prev_offset; if (padding_len > 0) try llvm_field_types.append( o.gpa, @@ -3391,7 +3247,7 @@ pub const Object = struct { o.gpa, try o.builder.arrayType(padding_len, .i8), ); - if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(zcu)) { + if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) { // This is a zero-bit field. If there are runtime bits after this field, // map to the next LLVM field (which we know exists): otherwise, don't // map the field, indicating it's at the end of the struct. @@ -3428,14 +3284,14 @@ pub const Object = struct { const union_obj = ip.loadUnionType(t.toIntern()); const layout = Type.getUnionLayout(union_obj, zcu); - if (union_obj.flagsUnordered(ip).layout == .@"packed") { - const int_ty = try o.builder.intType(@intCast(t.bitSize(zcu))); + if (union_obj.layout == .@"packed") { + const int_ty = try o.lowerType(pt, .fromInterned(union_obj.packed_backing_int_type)); try o.type_map.put(o.gpa, t.toIntern(), int_ty); return int_ty; } if (layout.payload_size == 0) { - const enum_tag_ty = try o.lowerType(pt, Type.fromInterned(union_obj.enum_tag_ty)); + const enum_tag_ty = try o.lowerType(pt, .fromInterned(union_obj.enum_tag_type)); try o.type_map.put(o.gpa, t.toIntern(), enum_tag_ty); return enum_tag_ty; } @@ -3467,7 +3323,7 @@ pub const Object = struct { ); return ty; } - const enum_tag_ty = try o.lowerType(pt, Type.fromInterned(union_obj.enum_tag_ty)); + const enum_tag_ty = try o.lowerType(pt, .fromInterned(union_obj.enum_tag_type)); // Put the tag before or after the payload depending on which one's // alignment is greater. @@ -3502,7 +3358,7 @@ pub const Object = struct { } return gop.value_ptr.*; }, - .enum_type => try o.lowerType(pt, Type.fromInterned(ip.loadEnumType(t.toIntern()).tag_ty)), + .enum_type => try o.lowerType(pt, t.intTagType(zcu)), .func_type => |func_type| try o.lowerTypeFn(pt, func_type), .error_set_type, .inferred_error_set_type => try o.errorIntType(pt), // values, not types @@ -3522,6 +3378,7 @@ pub const Object = struct { .opt, .aggregate, .un, + .bitpack, // memoization, not types .memoized_call, => unreachable, @@ -3529,20 +3386,6 @@ pub const Object = struct { }; } - /// Use this instead of lowerType when you want to handle correctly the case of elem_ty - /// being a zero bit type, but it should still be lowered as an i8 in such case. - /// There are other similar cases handled here as well. - fn lowerPtrElemTy(o: *Object, pt: Zcu.PerThread, elem_ty: Type) Allocator.Error!Builder.Type { - const zcu = pt.zcu; - const lower_elem_ty = switch (elem_ty.zigTypeTag(zcu)) { - .@"opaque" => true, - .@"fn" => !zcu.typeToFunc(elem_ty).?.is_generic, - .array => elem_ty.childType(zcu).hasRuntimeBitsIgnoreComptime(zcu), - else => elem_ty.hasRuntimeBitsIgnoreComptime(zcu), - }; - return if (lower_elem_ty) try o.lowerType(pt, elem_ty) else .i8; - } - fn lowerTypeFn(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type { const zcu = pt.zcu; const ip = &zcu.intern_pool; @@ -3641,7 +3484,7 @@ pub const Object = struct { if (layout.payload_size == 0) return o.lowerValue(pt, un.tag); const union_obj = zcu.typeToUnion(ty).?; - const container_layout = union_obj.flagsUnordered(ip).layout; + const container_layout = union_obj.layout; assert(container_layout == .@"packed"); @@ -3699,7 +3542,9 @@ pub const Object = struct { return o.builder.undefConst(try o.lowerType(pt, Type.fromInterned(val_key.typeOf()))); } - const ty = Type.fromInterned(val_key.typeOf()); + const ty: Type = .fromInterned(val_key.typeOf()); + ty.assertHasLayout(zcu); + return switch (val_key) { .int_type, .ptr_type, @@ -3759,7 +3604,7 @@ pub const Object = struct { }; const err_int_ty = try pt.errorIntType(); const payload_type = ty.errorUnionPayload(zcu); - if (!payload_type.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_type.hasRuntimeBits(zcu)) { // We use the error type directly as the type. return o.lowerValue(pt, err_val); } @@ -3821,7 +3666,7 @@ pub const Object = struct { const payload_ty = ty.optionalChild(zcu); const non_null_bit = try o.builder.intConst(.i8, @intFromBool(opt.val != .none)); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { return non_null_bit; } const llvm_ty = try o.lowerType(pt, ty); @@ -3857,6 +3702,7 @@ pub const Object = struct { fields[0..llvm_ty_fields.len], ), vals[0..llvm_ty_fields.len]); }, + .bitpack => |bitpack| return o.lowerValue(pt, bitpack.backing_int_val), .aggregate => |aggregate| switch (ip.indexToKey(ty.toIntern())) { .array_type => |array_type| switch (aggregate.storage) { .bytes => |bytes| try o.builder.stringConst(try o.builder.string( @@ -3988,7 +3834,7 @@ pub const Object = struct { 0.., ) |field_ty, field_val, field_index| { if (field_val != .none) continue; - if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue; const field_align = Type.fromInterned(field_ty).abiAlignment(zcu); big_align = big_align.max(field_align); @@ -4034,16 +3880,8 @@ pub const Object = struct { }, .struct_type => { const struct_type = ip.loadStructType(ty.toIntern()); - assert(struct_type.haveLayout(ip)); const struct_ty = try o.lowerType(pt, ty); - if (struct_type.layout == .@"packed") { - comptime assert(Type.packed_struct_layout_version == 2); - - const bits = ty.bitSize(zcu); - const llvm_int_ty = try o.builder.intType(@intCast(bits)); - - return o.lowerValueToInt(pt, llvm_int_ty, arg_val); - } + assert(struct_type.layout != .@"packed"); const llvm_len = struct_ty.aggregateLen(&o.builder); const ExpectedContents = extern struct { @@ -4063,15 +3901,12 @@ pub const Object = struct { comptime assert(struct_layout_version == 2); var llvm_index: usize = 0; var offset: u64 = 0; - var big_align: InternPool.Alignment = .@"1"; var need_unnamed = false; var field_it = struct_type.iterateRuntimeOrder(ip); while (field_it.next()) |field_index| { const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); - const field_align = ty.fieldAlignment(field_index, zcu); - big_align = big_align.max(field_align); const prev_offset = offset; - offset = field_align.forward(offset); + offset = struct_type.field_offsets.get(ip)[field_index]; const padding_len = offset - prev_offset; if (padding_len > 0) { @@ -4084,7 +3919,7 @@ pub const Object = struct { llvm_index += 1; } - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!field_ty.hasRuntimeBits(zcu)) { // This is a zero-bit field - we only needed it for the alignment. continue; } @@ -4102,7 +3937,7 @@ pub const Object = struct { } { const prev_offset = offset; - offset = big_align.forward(offset); + offset = struct_type.alignment.forward(offset); const padding_len = offset - prev_offset; if (padding_len > 0) { fields[llvm_index] = try o.builder.arrayType(padding_len, .i8); @@ -4126,19 +3961,13 @@ pub const Object = struct { if (layout.payload_size == 0) return o.lowerValue(pt, un.tag); const union_obj = zcu.typeToUnion(ty).?; - const container_layout = union_obj.flagsUnordered(ip).layout; + const container_layout = union_obj.layout; + assert(container_layout != .@"packed"); var need_unnamed = false; const payload = if (un.tag != .none) p: { const field_index = zcu.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?; const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); - if (container_layout == .@"packed") { - if (!field_ty.hasRuntimeBits(zcu)) return o.builder.intConst(union_ty, 0); - const bits = ty.bitSize(zcu); - const llvm_int_ty = try o.builder.intType(@intCast(bits)); - - return o.lowerValueToInt(pt, llvm_int_ty, arg_val); - } // Sometimes we must make an unnamed struct because LLVM does // not support bitcasting our payload struct to the true union payload type. @@ -4146,7 +3975,7 @@ pub const Object = struct { // must pointer cast to the expected type before accessing the union. need_unnamed = layout.most_aligned_field != field_index; - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!field_ty.hasRuntimeBits(zcu)) { const padding_len = layout.payload_size; break :p try o.builder.undefConst(try o.builder.arrayType(padding_len, .i8)); } @@ -4165,13 +3994,6 @@ pub const Object = struct { ); } else p: { assert(layout.tag_size == 0); - if (container_layout == .@"packed") { - const bits = ty.bitSize(zcu); - const llvm_int_ty = try o.builder.intType(@intCast(bits)); - - return o.lowerValueToInt(pt, llvm_int_ty, arg_val); - } - const union_val = try o.lowerValue(pt, un.val); need_unnamed = true; break :p union_val; @@ -4273,7 +4095,14 @@ pub const Object = struct { }; return o.lowerPtr(pt, field.base, offset + field_off); }, - .arr_elem, .comptime_field, .comptime_alloc => unreachable, + .arr_elem => |arr_elem| { + const base_ptr_ty = Value.fromInterned(arr_elem.base).typeOf(zcu); + assert(base_ptr_ty.ptrSize(zcu) == .many); + const elem_size = base_ptr_ty.childType(zcu).abiSize(zcu); + return o.lowerPtr(pt, arr_elem.base, offset + elem_size * arr_elem.index); + }, + .comptime_field => unreachable, + .comptime_alloc => unreachable, }; } @@ -4298,12 +4127,11 @@ pub const Object = struct { const ptr_ty = Type.fromInterned(uav.orig_ty); - const is_fn_body = uav_ty.zigTypeTag(zcu) == .@"fn"; - if ((!is_fn_body and !uav_ty.hasRuntimeBits(zcu)) or - (is_fn_body and zcu.typeToFunc(uav_ty).?.is_generic)) return o.lowerPtrToVoid(pt, ptr_ty); + if (!uav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { + return o.lowerPtrToVoid(pt, ptr_ty); + } - if (is_fn_body) - @panic("TODO"); + assert(uav_ty.zigTypeTag(zcu) != .@"fn"); // should be using a Nav ref const llvm_addr_space = toLlvmAddressSpace(ptr_ty.ptrAddressSpace(zcu), target); const alignment = ptr_ty.ptrAlignment(zcu); @@ -4326,14 +4154,11 @@ pub const Object = struct { const nav_ty = Type.fromInterned(nav.typeOf(ip)); const ptr_ty = try pt.navPtrType(nav_index); - const is_fn_body = nav_ty.zigTypeTag(zcu) == .@"fn"; - if ((!is_fn_body and !nav_ty.hasRuntimeBits(zcu)) or - (is_fn_body and zcu.typeToFunc(nav_ty).?.is_generic)) - { + if (nav.getExtern(ip) == null and !nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { return o.lowerPtrToVoid(pt, ptr_ty); } - const llvm_global = if (is_fn_body) + const llvm_global = if (nav_ty.zigTypeTag(zcu) == .@"fn") (try o.resolveLlvmFunction(pt, nav_index)).ptrConst(&o.builder).global else (try o.resolveGlobalNav(pt, nav_index)).ptrConst(&o.builder).global; @@ -4376,21 +4201,18 @@ pub const Object = struct { /// types to work around a LLVM deficiency when targeting ARM/AArch64. fn getAtomicAbiType(o: *Object, pt: Zcu.PerThread, ty: Type, is_rmw_xchg: bool) Allocator.Error!Builder.Type { const zcu = pt.zcu; - const ip = &zcu.intern_pool; - const int_ty = switch (ty.zigTypeTag(zcu)) { - .int => ty, - .@"enum" => ty.intTagType(zcu), - .@"struct" => Type.fromInterned(ip.loadStructType(ty.toIntern()).backingIntTypeUnordered(ip)), + switch (ty.zigTypeTag(zcu)) { + .int, .@"enum", .@"struct", .@"union" => {}, .float => { if (!is_rmw_xchg) return .none; return o.builder.intType(@intCast(ty.abiSize(zcu) * 8)); }, .bool => return .i8, else => return .none, - }; - const bit_count = int_ty.intInfo(zcu).bits; + } + const bit_count = ty.bitSize(zcu); if (!std.math.isPowerOfTwo(bit_count) or (bit_count % 8) != 0) { - return o.builder.intType(@intCast(int_ty.abiSize(zcu) * 8)); + return o.builder.intType(@intCast(ty.abiSize(zcu) * 8)); } else { return .none; } @@ -4498,7 +4320,7 @@ pub const Object = struct { const ret_ty = try o.lowerType(pt, Type.slice_const_u8_sentinel_0); const target = &zcu.root_mod.resolved_target.result; const function_index = try o.builder.addFunction( - try o.builder.fnType(ret_ty, &.{try o.lowerType(pt, Type.fromInterned(enum_type.tag_ty))}, .normal), + try o.builder.fnType(ret_ty, &.{try o.lowerType(pt, Type.fromInterned(enum_type.int_tag_type))}, .normal), try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_type.name.fmt(ip)}), toLlvmAddressSpace(.generic, target), ); @@ -4521,12 +4343,16 @@ pub const Object = struct { const bad_value_block = try wip.block(1, "BadValue"); const tag_int_value = wip.arg(0); - var wip_switch = - try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len), .none); + var wip_switch = try wip.@"switch"( + tag_int_value, + bad_value_block, + @intCast(enum_type.field_names.len), + .none, + ); defer wip_switch.finish(&wip); - for (0..enum_type.names.len) |field_index| { - const name = try o.builder.stringNull(enum_type.names.get(ip)[field_index].toSlice(ip)); + for (0..enum_type.field_names.len) |field_index| { + const name = try o.builder.stringNull(enum_type.field_names.get(ip)[field_index].toSlice(ip)); const name_init = try o.builder.stringConst(name); const name_variable_index = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); @@ -4597,7 +4423,41 @@ pub const NavGen = struct { const ty = Type.fromInterned(nav.typeOf(ip)); if (linkage != .internal and ip.isFunctionType(ty.toIntern())) { - _ = try o.resolveLlvmFunction(pt, owner_nav); + const function_index = try o.resolveLlvmFunction(pt, owner_nav); + // Add parameter attributes which weren't set by `resolveLlvmFunction` + const fn_info = zcu.typeToFunc(ty).?; + var attributes = try function_index.ptrConst(&o.builder).attributes.toWip(&o.builder); + defer attributes.deinit(&o.builder); + var it = iterateParamTypes(o, pt, fn_info); + if (firstParamSRet(fn_info, zcu, zcu.getTarget())) it.llvm_index += 1; + if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) it.llvm_index += 1; + while (try it.next()) |lowering| switch (lowering) { + .byval => { + const param_index = it.zig_index - 1; + const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]); + if (!isByRef(param_ty, zcu)) { + try o.addByValParamAttrs(pt, &attributes, param_ty, param_index, fn_info, it.llvm_index - 1); + } + }, + .byref => { + const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); + const param_llvm_ty = try o.lowerType(pt, param_ty); + const alignment = param_ty.abiAlignment(zcu); + try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment.toLlvm(), it.byval_attr, param_llvm_ty); + }, + .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder), + // No attributes needed for these. + .no_bits, + .abi_sized_int, + .multiple_llvm_types, + .float_array, + .i32_array, + .i64_array, + => continue, + + .slice => unreachable, // extern functions do not support slice types. + }; + function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); } else { const variable_index = try o.resolveGlobalNav(pt, nav_index); variable_index.setAlignment(zcu.navAlignment(nav_index).toLlvm(), &o.builder); @@ -4626,7 +4486,7 @@ pub const NavGen = struct { debug_file, // File debug_file, // Scope line_number, - try o.lowerDebugType(pt, ty), + try o.getDebugType(pt, ty), variable_index, .{ .local = linkage == .internal }, ); @@ -4748,7 +4608,7 @@ pub const FuncGen = struct { /// Have we seen loads or stores involving `allowzero` pointers? allowzero_access: bool = false, - pub fn maybeMarkAllowZeroAccess(self: *FuncGen, info: InternPool.Key.PtrType) void { + fn maybeMarkAllowZeroAccess(self: *FuncGen, info: InternPool.Key.PtrType) void { // LLVM already considers null pointers to be valid in non-generic address spaces, so avoid // pessimizing optimization for functions with accesses to such pointers. if (info.flags.address_space == .generic and info.flags.is_allowzero) self.allowzero_access = true; @@ -5216,7 +5076,7 @@ pub const FuncGen = struct { try o.builder.metadataString(nav.fqn.toSlice(&zcu.intern_pool)), line_number, line_number + func.lbrace_line, - try o.lowerDebugType(pt, fn_ty), + try o.getDebugType(pt, fn_ty), .{ .di_flags = .{ .StaticMember = true }, .sp_flags = .{ @@ -5514,7 +5374,7 @@ pub const FuncGen = struct { return .none; } - if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBitsIgnoreComptime(zcu)) { + if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBits(zcu)) { return .none; } @@ -5633,7 +5493,7 @@ pub const FuncGen = struct { return; } const fn_info = zcu.typeToFunc(Type.fromInterned(ip.getNav(self.ng.nav_index).typeOf(ip))).?; - if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!ret_ty.hasRuntimeBits(zcu)) { if (Type.fromInterned(fn_info.return_type).isError(zcu)) { // Functions with an empty error set are emitted with an error code // return type and return zero so they can be function pointers coerced @@ -5698,7 +5558,7 @@ pub const FuncGen = struct { const ptr_ty = self.typeOf(un_op); const ret_ty = ptr_ty.childType(zcu); const fn_info = zcu.typeToFunc(Type.fromInterned(ip.getNav(self.ng.nav_index).typeOf(ip))).?; - if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!ret_ty.hasRuntimeBits(zcu)) { if (Type.fromInterned(fn_info.return_type).isError(zcu)) { // Functions with an empty error set are emitted with an error code // return type and return zero so they can be function pointers coerced @@ -5829,14 +5689,13 @@ pub const FuncGen = struct { const o = self.ng.object; const pt = self.ng.pt; const zcu = pt.zcu; - const ip = &zcu.intern_pool; const scalar_ty = operand_ty.scalarType(zcu); const int_ty = switch (scalar_ty.zigTypeTag(zcu)) { .@"enum" => scalar_ty.intTagType(zcu), .int, .bool, .pointer, .error_set => scalar_ty, .optional => blk: { const payload_ty = operand_ty.optionalChild(zcu); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu) or + if (!payload_ty.hasRuntimeBits(zcu) or operand_ty.optionalReprIsPayload(zcu)) { break :blk operand_ty; @@ -5908,12 +5767,7 @@ pub const FuncGen = struct { return phi.toValue(); }, .float => return self.buildFloatCmp(fast, op, operand_ty, .{ lhs, rhs }), - .@"struct" => blk: { - const struct_obj = ip.loadStructType(scalar_ty.toIntern()); - assert(struct_obj.layout == .@"packed"); - const backing_index = struct_obj.backingIntTypeUnordered(ip); - break :blk Type.fromInterned(backing_index); - }, + .@"struct" => scalar_ty.bitpackBackingInt(zcu), else => unreachable, }; const is_signed = int_ty.isSignedInt(zcu); @@ -6305,7 +6159,7 @@ pub const FuncGen = struct { const pt = fg.ng.pt; const zcu = pt.zcu; const payload_ty = err_union_ty.errorUnionPayload(zcu); - const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(zcu); + const payload_has_bits = payload_ty.hasRuntimeBits(zcu); const err_union_llvm_ty = try o.lowerType(pt, err_union_ty); const error_type = try o.errorIntType(pt); @@ -6641,7 +6495,7 @@ pub const FuncGen = struct { const len = try o.builder.intValue(llvm_usize, array_ty.arrayLen(zcu)); const slice_llvm_ty = try o.lowerType(pt, self.typeOfIndex(inst)); const operand = try self.resolveInst(ty_op.operand); - if (!array_ty.hasRuntimeBitsIgnoreComptime(zcu)) + if (!array_ty.hasRuntimeBits(zcu)) return self.wip.buildAggregate(slice_llvm_ty, &.{ operand, len }, ""); const ptr = try self.wip.gep(.inbounds, try o.lowerType(pt, array_ty), operand, &.{ try o.builder.intValue(llvm_usize, 0), try o.builder.intValue(llvm_usize, 0), @@ -6824,7 +6678,7 @@ pub const FuncGen = struct { const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const slice_ptr = try self.resolveInst(ty_op.operand); const slice_ptr_ty = self.typeOf(ty_op.operand); - const slice_llvm_ty = try o.lowerPtrElemTy(pt, slice_ptr_ty.childType(zcu)); + const slice_llvm_ty = try o.lowerType(pt, slice_ptr_ty.childType(zcu)); return self.wip.gepStruct(slice_llvm_ty, slice_ptr, index, ""); } @@ -6838,7 +6692,7 @@ pub const FuncGen = struct { const slice = try self.resolveInst(bin_op.lhs); const index = try self.resolveInst(bin_op.rhs); const elem_ty = slice_ty.childType(zcu); - const llvm_elem_ty = try o.lowerPtrElemTy(pt, elem_ty); + const llvm_elem_ty = try o.lowerType(pt, elem_ty); const base_ptr = try self.wip.extractValue(slice, &.{0}, ""); const ptr = try self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{index}, ""); if (isByRef(elem_ty, zcu)) { @@ -6863,7 +6717,7 @@ pub const FuncGen = struct { const slice = try self.resolveInst(bin_op.lhs); const index = try self.resolveInst(bin_op.rhs); - const llvm_elem_ty = try o.lowerPtrElemTy(pt, slice_ty.childType(zcu)); + const llvm_elem_ty = try o.lowerType(pt, slice_ty.childType(zcu)); const base_ptr = try self.wip.extractValue(slice, &.{0}, ""); return self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{index}, ""); } @@ -6903,7 +6757,7 @@ pub const FuncGen = struct { const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ptr_ty = self.typeOf(bin_op.lhs); const elem_ty = ptr_ty.childType(zcu); - const llvm_elem_ty = try o.lowerPtrElemTy(pt, elem_ty); + const llvm_elem_ty = try o.lowerType(pt, elem_ty); const base_ptr = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); // TODO: when we go fully opaque pointers in LLVM 16 we can remove this branch @@ -6930,8 +6784,8 @@ pub const FuncGen = struct { const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const ptr_ty = self.typeOf(bin_op.lhs); - const elem_ty = ptr_ty.childType(zcu); - if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return self.resolveInst(bin_op.lhs); + const elem_ty = ptr_ty.indexableElem(zcu); + assert(elem_ty.hasRuntimeBits(zcu)); const base_ptr = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -6939,12 +6793,8 @@ pub const FuncGen = struct { const elem_ptr = ty_pl.ty.toType(); if (elem_ptr.ptrInfo(zcu).flags.vector_index != .none) return base_ptr; - const llvm_elem_ty = try o.lowerPtrElemTy(pt, elem_ty); - return self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, if (ptr_ty.isSinglePointer(zcu)) - // If this is a single-item pointer to an array, we need another index in the GEP. - &.{ try o.builder.intValue(try o.lowerType(pt, Type.usize), 0), rhs } - else - &.{rhs}, ""); + const llvm_elem_ty = try o.lowerType(pt, elem_ty); + return self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{rhs}, ""); } fn airStructFieldPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { @@ -6976,7 +6826,7 @@ pub const FuncGen = struct { const struct_llvm_val = try self.resolveInst(struct_field.struct_operand); const field_index = struct_field.field_index; const field_ty = struct_ty.fieldType(field_index, zcu); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) return .none; + if (!field_ty.hasRuntimeBits(zcu)) return .none; if (!isByRef(struct_ty, zcu)) { assert(!isByRef(field_ty, zcu)); @@ -7037,15 +6887,17 @@ pub const FuncGen = struct { const llvm_field_index = o.llvmFieldIndex(struct_ty, field_index).?; const field_ptr = try self.wip.gepStruct(struct_llvm_ty, struct_llvm_val, llvm_field_index, ""); - const alignment = struct_ty.fieldAlignment(field_index, zcu); + const explicit_alignment = struct_ty.explicitFieldAlignment(field_index, zcu); const field_ptr_ty = try pt.ptrType(.{ .child = field_ty.toIntern(), - .flags = .{ .alignment = alignment }, + .flags = .{ .alignment = explicit_alignment }, }); if (isByRef(field_ty, zcu)) { - assert(alignment != .none); - const field_alignment = alignment.toLlvm(); - return self.loadByRef(field_ptr, field_ty, field_alignment, .normal); + const alignment = switch (explicit_alignment) { + .none => field_ty.abiAlignment(zcu), + else => |a| a, + }; + return self.loadByRef(field_ptr, field_ty, alignment.toLlvm(), .normal); } else { return self.load(field_ptr, field_ptr_ty); } @@ -7146,7 +6998,7 @@ pub const FuncGen = struct { self.file, self.scope, self.prev_dbg_line, - try o.lowerDebugType(pt, ptr_ty.childType(zcu)), + try o.getDebugType(pt, ptr_ty.childType(zcu)), ); _ = try self.wip.callIntrinsic( @@ -7179,7 +7031,7 @@ pub const FuncGen = struct { self.file, self.scope, self.prev_dbg_line, - try o.lowerDebugType(pt, operand_ty), + try o.getDebugType(pt, operand_ty), arg_no: { self.arg_inline_index += 1; break :arg_no self.arg_inline_index; @@ -7189,7 +7041,7 @@ pub const FuncGen = struct { self.file, self.scope, self.prev_dbg_line, - try o.lowerDebugType(pt, operand_ty), + try o.getDebugType(pt, operand_ty), ); const zcu = pt.zcu; @@ -7280,6 +7132,7 @@ pub const FuncGen = struct { const llvm_param_attrs = try arena.alloc(Builder.Type, max_param_count); const pt = self.ng.pt; const zcu = pt.zcu; + const ip = &zcu.intern_pool; const target = zcu.getTarget(); var llvm_ret_i: usize = 0; @@ -7304,7 +7157,7 @@ pub const FuncGen = struct { const output_inst = try self.resolveInst(output.operand); const output_ty = self.typeOf(output.operand); assert(output_ty.zigTypeTag(zcu) == .pointer); - const elem_llvm_ty = try o.lowerPtrElemTy(pt, output_ty.childType(zcu)); + const elem_llvm_ty = try o.lowerType(pt, output_ty.childType(zcu)); switch (constraint[0]) { '=' => {}, @@ -7422,7 +7275,7 @@ pub const FuncGen = struct { llvm_param_attrs[llvm_param_i] = if (constraint[0] == '*') blk: { if (!is_by_ref) self.maybeMarkAllowZeroAccess(arg_ty.ptrInfo(zcu)); - break :blk try o.lowerPtrElemTy(pt, if (is_by_ref) arg_ty else arg_ty.childType(zcu)); + break :blk try o.lowerType(pt, if (is_by_ref) arg_ty else arg_ty.childType(zcu)); } else .none; llvm_param_i += 1; @@ -7436,7 +7289,7 @@ pub const FuncGen = struct { if (constraint[0] != '+') continue; const rw_ty = self.typeOf(output.operand); - const llvm_elem_ty = try o.lowerPtrElemTy(pt, rw_ty.childType(zcu)); + const llvm_elem_ty = try o.lowerType(pt, rw_ty.childType(zcu)); if (llvm_ret_indirect[output.index]) { llvm_param_values[llvm_param_i] = llvm_rw_vals[output.index]; llvm_param_types[llvm_param_i] = llvm_rw_vals[output.index].typeOfWip(&self.wip); @@ -7463,7 +7316,7 @@ pub const FuncGen = struct { total_i += 1; } - const ip = &zcu.intern_pool; + if (total_i != 0) try llvm_constraints.append(gpa, ','); const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers); const clobbers_ty = clobbers_val.typeOf(zcu); var clobbers_bigint_buf: Value.BigIntSpace = undefined; @@ -7663,7 +7516,7 @@ pub const FuncGen = struct { comptime assert(optional_layout_version == 3); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { const loaded = if (operand_is_ptr) try self.wip.load(access_kind, optional_llvm_ty, operand, .default, "") else @@ -7706,7 +7559,7 @@ pub const FuncGen = struct { if (operand_is_ptr) self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu)); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { const loaded = if (operand_is_ptr) try self.wip.load(access_kind, try o.lowerType(pt, err_union_ty), operand, .default, "") else @@ -7733,7 +7586,7 @@ pub const FuncGen = struct { const operand = try self.resolveInst(ty_op.operand); const optional_ty = self.typeOf(ty_op.operand).childType(zcu); const payload_ty = optional_ty.optionalChild(zcu); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { // We have a pointer to a zero-bit value and we need to return // a pointer to a zero-bit value. return operand; @@ -7761,7 +7614,7 @@ pub const FuncGen = struct { const access_kind: Builder.MemoryAccessKind = if (optional_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { self.maybeMarkAllowZeroAccess(optional_ptr_ty.ptrInfo(zcu)); // We have a pointer to a i8. We need to set it to 1 and then return the same pointer. @@ -7797,7 +7650,7 @@ pub const FuncGen = struct { const operand = try self.resolveInst(ty_op.operand); const optional_ty = self.typeOf(ty_op.operand); const payload_ty = self.typeOfIndex(inst); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return .none; + if (!payload_ty.hasRuntimeBits(zcu)) return .none; if (optional_ty.optionalReprIsPayload(zcu)) { // Payload value is the same as the optional value. @@ -7819,7 +7672,7 @@ pub const FuncGen = struct { const result_ty = self.typeOfIndex(inst); const payload_ty = if (operand_is_ptr) result_ty.childType(zcu) else result_ty; - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { return if (operand_is_ptr) operand else .none; } const offset = try errUnionPayloadOffset(payload_ty, pt); @@ -7863,7 +7716,7 @@ pub const FuncGen = struct { if (operand_is_ptr and operand_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; const payload_ty = err_union_ty.errorUnionPayload(zcu); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { if (!operand_is_ptr) return operand; self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu)); @@ -7899,7 +7752,7 @@ pub const FuncGen = struct { const access_kind: Builder.MemoryAccessKind = if (err_union_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { self.maybeMarkAllowZeroAccess(err_union_ptr_ty.ptrInfo(zcu)); _ = try self.wip.store(access_kind, non_error_val, operand, .default); @@ -7946,9 +7799,8 @@ pub const FuncGen = struct { const struct_llvm_ty = try o.lowerType(pt, struct_ty); const llvm_field_index = o.llvmFieldIndex(struct_ty, field_index).?; assert(self.err_ret_trace != .none); - const field_ptr = - try self.wip.gepStruct(struct_llvm_ty, self.err_ret_trace, llvm_field_index, ""); - const field_alignment = struct_ty.fieldAlignment(field_index, zcu); + const field_ptr = try self.wip.gepStruct(struct_llvm_ty, self.err_ret_trace, llvm_field_index, ""); + const field_alignment = struct_ty.explicitFieldAlignment(field_index, zcu); const field_ty = struct_ty.fieldType(field_index, zcu); const field_ptr_ty = try pt.ptrType(.{ .child = field_ty.toIntern(), @@ -7989,7 +7841,7 @@ pub const FuncGen = struct { const payload_ty = self.typeOf(ty_op.operand); const non_null_bit = try o.builder.intValue(.i8, 1); comptime assert(optional_layout_version == 3); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return non_null_bit; + assert(payload_ty.hasRuntimeBits(zcu)); const operand = try self.resolveInst(ty_op.operand); const optional_ty = self.typeOfIndex(inst); if (optional_ty.optionalReprIsPayload(zcu)) return operand; @@ -8023,9 +7875,7 @@ pub const FuncGen = struct { const err_un_ty = self.typeOfIndex(inst); const operand = try self.resolveInst(ty_op.operand); const payload_ty = self.typeOf(ty_op.operand); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - return operand; - } + assert(payload_ty.hasRuntimeBits(zcu)); const ok_err_code = try o.builder.intValue(try o.errorIntType(pt), 0); const err_un_llvm_ty = try o.lowerType(pt, err_un_ty); @@ -8065,7 +7915,7 @@ pub const FuncGen = struct { const err_un_ty = self.typeOfIndex(inst); const payload_ty = err_un_ty.errorUnionPayload(zcu); const operand = try self.resolveInst(ty_op.operand); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return operand; + if (!payload_ty.hasRuntimeBits(zcu)) return operand; const err_un_llvm_ty = try o.lowerType(pt, err_un_ty); const payload_offset = try errUnionPayloadOffset(payload_ty, pt); @@ -8517,7 +8367,7 @@ pub const FuncGen = struct { const ptr = try self.resolveInst(bin_op.lhs); const offset = try self.resolveInst(bin_op.rhs); const ptr_ty = self.typeOf(bin_op.lhs); - const llvm_elem_ty = try o.lowerPtrElemTy(pt, ptr_ty.childType(zcu)); + const llvm_elem_ty = try o.lowerType(pt, ptr_ty.childType(zcu)); switch (ptr_ty.ptrSize(zcu)) { // It's a pointer to an array, so according to LLVM we need an extra GEP index. .one => return self.wip.gep(.inbounds, llvm_elem_ty, ptr, &.{ @@ -8541,7 +8391,7 @@ pub const FuncGen = struct { const offset = try self.resolveInst(bin_op.rhs); const negative_offset = try self.wip.neg(offset, ""); const ptr_ty = self.typeOf(bin_op.lhs); - const llvm_elem_ty = try o.lowerPtrElemTy(pt, ptr_ty.childType(zcu)); + const llvm_elem_ty = try o.lowerType(pt, ptr_ty.childType(zcu)); switch (ptr_ty.ptrSize(zcu)) { // It's a pointer to an array, so according to LLVM we need an extra GEP index. .one => return self.wip.gep(.inbounds, llvm_elem_ty, ptr, &.{ @@ -9502,7 +9352,7 @@ pub const FuncGen = struct { self.file, self.scope, lbrace_line, - try o.lowerDebugType(pt, inst_ty), + try o.getDebugType(pt, inst_ty), self.arg_index, ); @@ -9836,7 +9686,7 @@ pub const FuncGen = struct { const ptr_ty = self.typeOf(atomic_load.ptr); const info = ptr_ty.ptrInfo(zcu); const elem_ty = Type.fromInterned(info.child); - if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return .none; + if (!elem_ty.hasRuntimeBits(zcu)) return .none; const ordering = toLlvmAtomicOrdering(atomic_load.order); const llvm_abi_ty = try o.getAtomicAbiType(pt, elem_ty, false); const ptr_alignment = (if (info.flags.alignment != .none) @@ -10304,7 +10154,7 @@ pub const FuncGen = struct { const target = &zcu.root_mod.resolved_target.result; const function_index = try o.builder.addFunction( - try o.builder.fnType(.i1, &.{try o.lowerType(pt, Type.fromInterned(enum_type.tag_ty))}, .normal), + try o.builder.fnType(.i1, &.{try o.lowerType(pt, Type.fromInterned(enum_type.int_tag_type))}, .normal), try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_type.name.fmt(ip)}), toLlvmAddressSpace(.generic, target), ); @@ -10325,13 +10175,13 @@ pub const FuncGen = struct { defer wip.deinit(); wip.cursor = .{ .block = try wip.block(0, "Entry") }; - const named_block = try wip.block(@intCast(enum_type.names.len), "Named"); + const named_block = try wip.block(@intCast(enum_type.field_names.len), "Named"); const unnamed_block = try wip.block(1, "Unnamed"); const tag_int_value = wip.arg(0); - var wip_switch = try wip.@"switch"(tag_int_value, unnamed_block, @intCast(enum_type.names.len), .none); + var wip_switch = try wip.@"switch"(tag_int_value, unnamed_block, @intCast(enum_type.field_names.len), .none); defer wip_switch.finish(&wip); - for (0..enum_type.names.len) |field_index| { + for (0..enum_type.field_names.len) |field_index| { const this_tag_int_value = try o.lowerValue( pt, (try pt.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(), @@ -10800,15 +10650,14 @@ pub const FuncGen = struct { }, .@"struct" => { if (zcu.typeToPackedStruct(result_ty)) |struct_type| { - const backing_int_ty = struct_type.backingIntTypeUnordered(ip); - assert(backing_int_ty != .none); - const big_bits = Type.fromInterned(backing_int_ty).bitSize(zcu); + const backing_int_ty: Type = .fromInterned(struct_type.packed_backing_int_type); + const big_bits = backing_int_ty.bitSize(zcu); const int_ty = try o.builder.intType(@intCast(big_bits)); comptime assert(Type.packed_struct_layout_version == 2); var running_int = try o.builder.intValue(int_ty, 0); var running_bits: u16 = 0; for (elements, struct_type.field_types.get(ip)) |elem, field_ty| { - if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue; const non_int_val = try self.resolveInst(elem); const ty_bit_size: u16 = @intCast(Type.fromInterned(field_ty).bitSize(zcu)); @@ -10840,12 +10689,12 @@ pub const FuncGen = struct { const llvm_elem = try self.resolveInst(elem); const llvm_i = o.llvmFieldIndex(result_ty, i).?; - const field_ptr = - try self.wip.gepStruct(llvm_result_ty, alloca_inst, llvm_i, ""); + const field_ptr = try self.wip.gepStruct(llvm_result_ty, alloca_inst, llvm_i, ""); + const field_ptr_ty = try pt.ptrType(.{ .child = self.typeOf(elem).toIntern(), .flags = .{ - .alignment = result_ty.fieldAlignment(i, zcu), + .alignment = result_ty.explicitFieldAlignment(i, zcu), }, }); try self.store(field_ptr, field_ptr_ty, llvm_elem, .none); @@ -10910,7 +10759,7 @@ pub const FuncGen = struct { const layout = union_ty.unionGetLayout(zcu); const union_obj = zcu.typeToUnion(union_ty).?; - if (union_obj.flagsUnordered(ip).layout == .@"packed") { + if (union_obj.layout == .@"packed") { const big_bits = union_ty.bitSize(zcu); const int_llvm_ty = try o.builder.intType(@intCast(big_bits)); const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]); @@ -10925,10 +10774,8 @@ pub const FuncGen = struct { const tag_int_val = blk: { const tag_ty = union_ty.unionTagTypeHypothetical(zcu); - const union_field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index]; - const enum_field_index = tag_ty.enumFieldIndex(union_field_name, zcu).?; - const tag_val = try pt.enumValueFieldIndex(tag_ty, enum_field_index); - break :blk try tag_val.intFromEnum(tag_ty, pt); + const tag_val = try pt.enumValueFieldIndex(tag_ty, extra.field_index); + break :blk tag_val.intFromEnum(zcu); }; if (layout.payload_size == 0) { if (layout.tag_size == 0) { @@ -10950,16 +10797,14 @@ pub const FuncGen = struct { const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]); const field_llvm_ty = try o.lowerType(pt, field_ty); const field_size = field_ty.abiSize(zcu); - const field_align = union_ty.fieldAlignment(extra.field_index, zcu); + const field_align = union_ty.explicitFieldAlignment(extra.field_index, zcu); const llvm_usize = try o.lowerType(pt, Type.usize); const usize_zero = try o.builder.intValue(llvm_usize, 0); + assert(field_ty.hasRuntimeBits(zcu)); + const llvm_union_ty = t: { const payload_ty = p: { - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - const padding_len = layout.payload_size; - break :p try o.builder.arrayType(padding_len, .i8); - } if (field_size == layout.payload_size) { break :p field_llvm_ty; } @@ -10969,7 +10814,7 @@ pub const FuncGen = struct { }); }; if (layout.tag_size == 0) break :t try o.builder.structType(.normal, &.{payload_ty}); - const tag_ty = try o.lowerType(pt, Type.fromInterned(union_obj.enum_tag_ty)); + const tag_ty = try o.lowerType(pt, .fromInterned(union_obj.enum_tag_type)); var fields: [3]Builder.Type = undefined; var fields_len: usize = 2; if (layout.tag_align.compare(.gte, layout.payload_align)) { @@ -11010,11 +10855,11 @@ pub const FuncGen = struct { const tag_index = @intFromBool(layout.tag_align.compare(.lt, layout.payload_align)); const indices: [2]Builder.Value = .{ usize_zero, try o.builder.intValue(.i32, tag_index) }; const field_ptr = try self.wip.gep(.inbounds, llvm_union_ty, result_ptr, &indices, ""); - const tag_ty = try o.lowerType(pt, Type.fromInterned(union_obj.enum_tag_ty)); + const tag_ty = try o.lowerType(pt, .fromInterned(union_obj.enum_tag_type)); var big_int_space: Value.BigIntSpace = undefined; const tag_big_int = tag_int_val.toBigInt(&big_int_space, zcu); const llvm_tag = try o.builder.bigIntValue(tag_ty, tag_big_int); - const tag_alignment = Type.fromInterned(union_obj.enum_tag_ty).abiAlignment(zcu).toLlvm(); + const tag_alignment = Type.fromInterned(union_obj.enum_tag_type).abiAlignment(zcu).toLlvm(); _ = try self.wip.store(.normal, llvm_tag, field_ptr, tag_alignment); } @@ -11295,8 +11140,10 @@ pub const FuncGen = struct { return self.wip.gep(.inbounds, .i8, struct_ptr, &.{llvm_index}, ""); }, else => { - const struct_llvm_ty = try o.lowerPtrElemTy(pt, struct_ty); - + if (!struct_ty.hasRuntimeBits(zcu)) { + return struct_ptr; + } + const struct_llvm_ty = try o.lowerType(pt, struct_ty); if (o.llvmFieldIndex(struct_ty, field_index)) |llvm_field_index| { return self.wip.gepStruct(struct_llvm_ty, struct_ptr, llvm_field_index, ""); } else { @@ -11306,7 +11153,7 @@ pub const FuncGen = struct { // the struct. const llvm_index = try o.builder.intValue( try o.lowerType(pt, Type.usize), - @intFromBool(struct_ty.hasRuntimeBitsIgnoreComptime(zcu)), + @intFromBool(struct_ty.hasRuntimeBits(zcu)), ); return self.wip.gep(.inbounds, struct_llvm_ty, struct_ptr, &.{llvm_index}, ""); } @@ -11393,7 +11240,7 @@ pub const FuncGen = struct { const zcu = pt.zcu; const info = ptr_ty.ptrInfo(zcu); const elem_ty = Type.fromInterned(info.child); - if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return .none; + if (!elem_ty.hasRuntimeBits(zcu)) return .none; const ptr_alignment = (if (info.flags.alignment != .none) @as(InternPool.Alignment, info.flags.alignment) @@ -12048,7 +11895,7 @@ fn returnTypeByRef(zcu: *Zcu, target: *const std.Target, ty: Type) bool { fn firstParamSRet(fn_info: InternPool.Key.FuncType, zcu: *Zcu, target: *const std.Target) bool { const return_type = Type.fromInterned(fn_info.return_type); - if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) return false; + if (!return_type.hasRuntimeBits(zcu)) return false; return switch (fn_info.cc) { .auto => returnTypeByRef(zcu, target, return_type), @@ -12088,11 +11935,9 @@ fn firstParamSRetSystemV(ty: Type, zcu: *Zcu, target: *const std.Target) bool { fn lowerFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type { const zcu = pt.zcu; const return_type = Type.fromInterned(fn_info.return_type); - if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) { - // If the return type is an error set or an error union, then we make this - // anyerror return type instead, so that it can be coerced into a function - // pointer type which has anyerror as the return type. - return if (return_type.isError(zcu)) try o.errorIntType(pt) else .void; + if (!return_type.hasRuntimeBits(zcu)) { + assert(!return_type.isError(zcu)); + return .void; } const target = zcu.getTarget(); switch (fn_info.cc) { @@ -12136,7 +11981,7 @@ fn lowerFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) var types: [8]Builder.Type = undefined; for (0..return_type.structFieldCount(zcu)) |field_index| { const field_ty = return_type.fieldType(field_index, zcu); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; types[types_len] = try o.lowerType(pt, field_ty); types_len += 1; } @@ -12174,6 +12019,7 @@ fn lowerSystemVFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.Fu const zcu = pt.zcu; const ip = &zcu.intern_pool; const return_type = Type.fromInterned(fn_info.return_type); + return_type.assertHasLayout(zcu); if (isScalar(zcu, return_type)) { return o.lowerType(pt, return_type); } @@ -12222,9 +12068,7 @@ fn lowerSystemVFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.Fu assert(first_non_integer orelse classes.len == types_index); switch (ip.indexToKey(return_type.toIntern())) { .struct_type => { - const struct_type = ip.loadStructType(return_type.toIntern()); - assert(struct_type.haveLayout(ip)); - const size: u64 = struct_type.sizeUnordered(ip); + const size = return_type.abiSize(zcu); assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index); if (size % 8 > 0) { types_buffer[types_index - 1] = try o.builder.intType(@intCast(size % 8 * 8)); @@ -12260,7 +12104,7 @@ const ParamTypeIterator = struct { i64_array: u8, }; - pub fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering { + fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering { if (it.zig_index >= it.fn_info.param_types.len) return null; const ip = &it.pt.zcu.intern_pool; const ty = it.fn_info.param_types.get(ip)[it.zig_index]; @@ -12269,7 +12113,7 @@ const ParamTypeIterator = struct { } /// `airCall` uses this instead of `next` so that it can take into account variadic functions. - pub fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) Allocator.Error!?Lowering { + fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) Allocator.Error!?Lowering { assert(std.meta.eql(it.pt, fg.ng.pt)); const ip = &it.pt.zcu.intern_pool; if (it.zig_index >= it.fn_info.param_types.len) { @@ -12288,7 +12132,7 @@ const ParamTypeIterator = struct { const zcu = pt.zcu; const target = zcu.getTarget(); - if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!ty.hasRuntimeBits(zcu)) { it.zig_index += 1; return .no_bits; } @@ -12383,7 +12227,7 @@ const ParamTypeIterator = struct { it.types_len = 0; for (0..ty.structFieldCount(zcu)) |field_index| { const field_ty = ty.fieldType(field_index, zcu); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; it.types_buffer[it.types_len] = try it.object.lowerType(pt, field_ty); it.types_len += 1; } @@ -12460,6 +12304,7 @@ const ParamTypeIterator = struct { fn nextSystemV(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering { const zcu = it.pt.zcu; const ip = &zcu.intern_pool; + ty.assertHasLayout(zcu); const classes = x86_64_abi.classifySystemV(ty, zcu, zcu.getTarget(), .arg); if (classes[0] == .memory) { it.zig_index += 1; @@ -12531,9 +12376,7 @@ const ParamTypeIterator = struct { } switch (ip.indexToKey(ty.toIntern())) { .struct_type => { - const struct_type = ip.loadStructType(ty.toIntern()); - assert(struct_type.haveLayout(ip)); - const size: u64 = struct_type.sizeUnordered(ip); + const size = ty.abiSize(zcu); assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index); if (size % 8 > 0) { types_buffer[types_index - 1] = @@ -12707,14 +12550,14 @@ fn isByRef(ty: Type, zcu: *Zcu) bool { }, .error_union => { const payload_ty = ty.errorUnionPayload(zcu); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { return false; } return true; }, .optional => { const payload_ty = ty.optionalChild(zcu); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { return false; } if (ty.optionalReprIsPayload(zcu)) { diff --git a/src/codegen/mips/abi.zig b/src/codegen/mips/abi.zig index 6678b74ebc32dceed774331667cdf9d498855947..a27adb7ace40ff937a820a2e8bdfacea12f85d31 100644 --- a/src/codegen/mips/abi.zig +++ b/src/codegen/mips/abi.zig @@ -13,7 +13,7 @@ pub const Context = enum { ret, arg }; pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { const target = zcu.getTarget(); - std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(zcu)); + std.debug.assert(ty.hasRuntimeBits(zcu)); const max_direct_size = target.ptrBitWidth() * 2; switch (ty.zigTypeTag(zcu)) { diff --git a/src/codegen/riscv64/abi.zig b/src/codegen/riscv64/abi.zig index 1a380eab905708b866f18a29762e1653cd0a521b..05164530df958129231fd514f8e4c17dff8e8590 100644 --- a/src/codegen/riscv64/abi.zig +++ b/src/codegen/riscv64/abi.zig @@ -11,7 +11,7 @@ pub const Class = enum { memory, byval, integer, double_integer, fields }; pub fn classifyType(ty: Type, zcu: *Zcu) Class { const target = zcu.getTarget(); - std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(zcu)); + std.debug.assert(ty.hasRuntimeBits(zcu)); const max_byval_size = target.ptrBitWidth() * 2; switch (ty.zigTypeTag(zcu)) { @@ -27,7 +27,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class { var field_count: usize = 0; for (0..ty.structFieldCount(zcu)) |field_index| { const field_ty = ty.fieldType(field_index, zcu); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; if (field_ty.isRuntimeFloat()) any_fp = true else if (!field_ty.isAbiInt(zcu)) diff --git a/src/codegen/wasm/abi.zig b/src/codegen/wasm/abi.zig index a1fa8126491def2d9e2717faa0ccedcd2ee24805..d59047044b302fc86485237e03300efb89d7c151 100644 --- a/src/codegen/wasm/abi.zig +++ b/src/codegen/wasm/abi.zig @@ -22,7 +22,7 @@ pub const Class = union(enum) { /// or returned as value within a wasm function. pub fn classifyType(ty: Type, zcu: *const Zcu) Class { const ip = &zcu.intern_pool; - assert(ty.hasRuntimeBitsIgnoreComptime(zcu)); + assert(ty.hasRuntimeBits(zcu)); switch (ty.zigTypeTag(zcu)) { .int, .@"enum", .error_set => return .{ .direct = ty }, .float => return .{ .direct = ty }, @@ -47,7 +47,7 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class { return .indirect; } const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[0]); - const explicit_align = struct_type.fieldAlign(ip, 0); + const explicit_align = struct_type.field_aligns.getOrNone(ip, 0); if (explicit_align != .none) { if (explicit_align.compareStrict(.gt, field_ty.abiAlignment(zcu))) return .indirect; @@ -56,7 +56,7 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class { }, .@"union" => { const union_obj = zcu.typeToUnion(ty).?; - if (union_obj.flagsUnordered(ip).layout == .@"packed") { + if (union_obj.layout == .@"packed") { return .{ .direct = ty }; } const layout = ty.unionGetLayout(zcu); diff --git a/src/link.zig b/src/link.zig index c8ae7a6bb4dbb8cd8d0e782b6e6178dd65f049a7..c81737484e6da4a0b437b2ab1ad93d76ab9ac02a 100644 --- a/src/link.zig +++ b/src/link.zig @@ -29,6 +29,7 @@ const codegen = @import("codegen.zig"); pub const aarch64 = @import("link/aarch64.zig"); pub const LdScript = @import("link/LdScript.zig"); pub const Queue = @import("link/Queue.zig"); +pub const DebugConstPool = @import("link/DebugConstPool.zig"); pub const Diags = struct { /// Stored here so that function definitions can distinguish between @@ -1587,8 +1588,9 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void const ty_prog_node = comp.link_prog_node.start(name, 0); defer ty_prog_node.end(); if (zcu.llvm_object) |llvm_object| { - _ = llvm_object; - @compileError("MLUGG TODO"); + llvm_object.updateContainerType(pt, container_update.ty, container_update.success) catch |err| switch (err) { + error.OutOfMemory => diags.setAllocFailure(), + }; } else { if (comp.bin_file) |lf| { lf.updateContainerType(pt, container_update.ty, container_update.success) catch |err| switch (err) { diff --git a/src/link/DebugConstPool.zig b/src/link/DebugConstPool.zig index ce7f32551b63401a94bce51d02f388398f8912e4..eb8c60b6f9d058d12ddcfecc39b92931f6403998 100644 --- a/src/link/DebugConstPool.zig +++ b/src/link/DebugConstPool.zig @@ -13,6 +13,9 @@ /// * forward `updateContainerType` calls to its `DebugConstPool` /// * expose some callback functions---see functions in `DebugInfo` /// * ensure that any `get` call is eventually followed by a `flushPending` call +/// +/// TODO: everything in this file should have the error set 'Allocator.Error', but right now the +/// self-hosted linkers can return all kinds of crap for some reason. This needs fixing. const DebugConstPool = @This(); values: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 3094e8671e72456103a2a9f1e47df1a0816b1800..e64346c17c52d305519b575101d70343cf2ef250 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -18,7 +18,7 @@ const codegen = @import("../codegen.zig"); const dev = @import("../dev.zig"); const link = @import("../link.zig"); const target_info = @import("../target.zig"); -const DebugConstPool = @import("DebugConstPool.zig"); +const DebugConstPool = link.DebugConstPool; gpa: Allocator, bin_file: *link.File, -- 2.54.0 From b27c56fe5087872800f6b340ec3d1fc219d0d77b Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Thu, 12 Feb 2026 12:30:21 +0000 Subject: [PATCH 43/79] compiler: get everything building Several backends are crashing right now. I'll need to fix at least the C backend before this branch is ready to PR. --- lib/std/zig/target.zig | 11 +- src/codegen/aarch64/Select.zig | 89 ++++++------- src/codegen/c.zig | 143 ++++++++------------- src/codegen/c/Type.zig | 59 ++++----- src/codegen/riscv64/CodeGen.zig | 53 ++++---- src/codegen/sparc64/CodeGen.zig | 22 ++-- src/codegen/spirv/CodeGen.zig | 115 ++++++++--------- src/codegen/wasm/CodeGen.zig | 219 +++++++++++--------------------- src/link/MachO/Atom.zig | 2 +- src/link/MachO/ZigObject.zig | 2 +- src/link/MachO/file.zig | 2 +- src/link/Wasm.zig | 4 +- src/link/Wasm/Flush.zig | 6 +- src/link/tapi/parse.zig | 2 +- 14 files changed, 300 insertions(+), 429 deletions(-) diff --git a/lib/std/zig/target.zig b/lib/std/zig/target.zig index f87b93608650fe1e99955695853b2b7aa02acaf9..dee2241667c42db870163f1dbd9579ed7440a70d 100644 --- a/lib/std/zig/target.zig +++ b/lib/std/zig/target.zig @@ -519,10 +519,13 @@ pub fn intAlignment(target: *const std.Target, bits: u16) u16 { 33...64 => 8, else => 16, }, - else => return @min( - std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))), - target.cMaxIntAlignment(), - ), + else => switch (bits) { + 0 => 1, + else => @min( + std.math.ceilPowerOfTwoPromote(u16, @intCast((@as(u17, bits) + 7) / 8)), + target.cMaxIntAlignment(), + ), + }, }; } diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig index a95faca765385b3b4b879b0cf5b0e7885adf4e49..ba136872b13f406329d0f35e961a50946076e6ef 100644 --- a/src/codegen/aarch64/Select.zig +++ b/src/codegen/aarch64/Select.zig @@ -2791,9 +2791,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, } else return isel.fail("invalid constraint: '{s}'", .{constraint}); } - const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers); + const clobbers_val: Constant = .fromInterned(unwrapped_asm.clobbers); const clobbers_ty = clobbers_val.typeOf(zcu); - var clobbers_bigint_buf: Value.BigIntSpace = undefined; + var clobbers_bigint_buf: Constant.BigIntSpace = undefined; const clobbers_bigint = clobbers_val.toBigInt(&clobbers_bigint_buf, zcu); for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { assert(clobbers_ty.fieldType(field_index, zcu).toIntern() == .bool_type); @@ -2818,7 +2818,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { const limb_bits = @bitSizeOf(std.math.big.Limb); if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false - switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> field_index % limb_bits))) { + switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { 0 => continue, // field is false 1 => {}, // field is true } @@ -2871,7 +2871,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { const limb_bits = @bitSizeOf(std.math.big.Limb); if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false - switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> field_index % limb_bits))) { + switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { 0 => continue, // field is false 1 => {}, // field is true } @@ -3283,8 +3283,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, } else if (dst_ty.isSliceAtRuntime(zcu) and src_ty.isSliceAtRuntime(zcu)) { try dst_vi.value.move(isel, ty_op.operand); } else if (dst_tag == .error_union and src_tag == .error_union) { - assert(dst_ty.errorUnionSet(zcu).hasRuntimeBitsIgnoreComptime(zcu) == - src_ty.errorUnionSet(zcu).hasRuntimeBitsIgnoreComptime(zcu)); + assert(dst_ty.errorUnionSet(zcu).hasRuntimeBits(zcu) == + src_ty.errorUnionSet(zcu).hasRuntimeBits(zcu)); if (dst_ty.errorUnionPayload(zcu).toIntern() == src_ty.errorUnionPayload(zcu).toIntern()) { try dst_vi.value.move(isel, ty_op.operand); } else return isel.fail("bad {t} {f} {f}", .{ air_tag, isel.fmtType(dst_ty), isel.fmtType(src_ty) }); @@ -4562,7 +4562,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, } if (case.ranges.len == 0 and case.items.len == 1 and Constant.fromInterned( case.items[0].toInterned().?, - ).orderAgainstZero(zcu).compare(.eq)) { + ).compareHetero(.eq, .zero_comptime_int, zcu)) { try isel.emit(.cbnz( cond_reg, @intCast((isel.instructions.items.len + 1 - next_label) << 2), @@ -6893,11 +6893,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, var field_it = loaded_struct.iterateRuntimeOrder(ip); while (field_it.next()) |field_index| { const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - field_offset = field_ty.structFieldAlignment( - loaded_struct.fieldAlign(ip, field_index), - loaded_struct.layout, - zcu, - ).forward(field_offset); + field_offset = loaded_struct.field_offsets.get(ip)[field_index]; const field_size = field_ty.abiSize(zcu); if (field_size == 0) continue; var agg_part_it = agg_vi.value.field(agg_ty, field_offset, field_size); @@ -6905,7 +6901,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, try agg_part_vi.?.move(isel, elems[field_index]); field_offset += field_size; } - assert(loaded_struct.flagsUnordered(ip).alignment.forward(field_offset) == agg_vi.value.size(isel)); + assert(loaded_struct.alignment.forward(field_offset) == agg_vi.value.size(isel)); }, .tuple_type => |tuple_type| { const elems: []const Air.Inst.Ref = @@ -6947,23 +6943,23 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, const union_layout = ZigType.getUnionLayout(loaded_union, zcu); if (union_layout.tag_size > 0) unused_tag: { - const loaded_tag = loaded_union.loadTagType(ip); + const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); var tag_it = union_vi.value.field(union_ty, union_layout.tagOffset(), union_layout.tag_size); const tag_vi = try tag_it.only(isel); const tag_ra = try tag_vi.?.defReg(isel) orelse break :unused_tag; switch (union_layout.tag_size) { 0 => unreachable, - 1...4 => try isel.movImmediate(tag_ra.w(), @as(u32, switch (loaded_tag.values.len) { + 1...4 => try isel.movImmediate(tag_ra.w(), @as(u32, switch (loaded_tag.field_values.len) { 0 => extra.field_index, - else => switch (ip.indexToKey(loaded_tag.values.get(ip)[extra.field_index]).int.storage) { + else => switch (ip.indexToKey(loaded_tag.field_values.get(ip)[extra.field_index]).int.storage) { .u64 => |imm| @intCast(imm), .i64 => |imm| @bitCast(@as(i32, @intCast(imm))), else => unreachable, }, })), - 5...8 => try isel.movImmediate(tag_ra.x(), switch (loaded_tag.values.len) { + 5...8 => try isel.movImmediate(tag_ra.x(), switch (loaded_tag.field_values.len) { 0 => extra.field_index, - else => switch (ip.indexToKey(loaded_tag.values.get(ip)[extra.field_index]).int.storage) { + else => switch (ip.indexToKey(loaded_tag.field_values.get(ip)[extra.field_index]).int.storage) { .u64 => |imm| imm, .i64 => |imm| @bitCast(imm), else => unreachable, @@ -10391,7 +10387,7 @@ pub const Value = struct { switch (loaded_struct.layout) { .auto, .@"extern" => {}, .@"packed" => continue :type_key .{ - .int_type = ip.indexToKey(loaded_struct.backingIntTypeUnordered(ip)).int_type, + .int_type = ip.indexToKey(loaded_struct.packed_backing_int_type).int_type, }, } const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0; @@ -10406,7 +10402,7 @@ pub const Value = struct { var field_it = loaded_struct.iterateRuntimeOrder(ip); while (field_it.next()) |field_index| { const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - const field_begin = switch (loaded_struct.fieldAlign(ip, field_index)) { + const field_begin = switch (loaded_struct.field_aligns.getOrNone(ip, field_index)) { .none => field_ty.abiAlignment(zcu), else => |field_align| field_align, }.forward(field_end); @@ -10504,7 +10500,7 @@ pub const Value = struct { }, .union_type => { const loaded_union = ip.loadUnionType(ty.toIntern()); - switch (loaded_union.flagsUnordered(ip).layout) { + switch (loaded_union.layout) { .auto, .@"extern" => {}, .@"packed" => continue :type_key .{ .int_type = .{ .signedness = .unsigned, @@ -10539,12 +10535,13 @@ pub const Value = struct { const field_signedness = field_signedness: switch (field) { .tag => { if (offset >= field_begin and offset + size <= field_begin + field_size) { - ty = .fromInterned(loaded_union.enum_tag_ty); + ty = .fromInterned(loaded_union.enum_tag_type); ty_size = field_size; offset -= field_begin; - continue :type_key ip.indexToKey(loaded_union.enum_tag_ty); + continue :type_key ip.indexToKey(loaded_union.enum_tag_type); } - break :field_signedness ip.indexToKey(loaded_union.loadTagType(ip).tag_ty).int_type.signedness; + const loaded_enum = ip.loadEnumType(loaded_union.enum_tag_type); + break :field_signedness ip.indexToKey(loaded_enum.int_tag_type).int_type.signedness; }, .payload => null, }; @@ -10574,7 +10571,7 @@ pub const Value = struct { } }, .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque }, - .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty), + .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).int_tag_type), .error_set_type, .inferred_error_set_type, => continue :type_key .{ .simple_type = .anyerror }, @@ -10740,7 +10737,7 @@ pub const Value = struct { .storage = .{ .u64 = 0 }, } }, }, - .int => |int| break :free storage: switch (int.storage) { + .int => |int| break :free switch (int.storage) { .u64 => |imm| try isel.movImmediate(switch (size) { else => unreachable, 1...4 => mat.ra.w(), @@ -10772,12 +10769,6 @@ pub const Value = struct { } try isel.movImmediate(mat.ra.x(), imm); }, - .lazy_align => |ty| continue :storage .{ - .u64 = ZigType.fromInterned(ty).abiAlignment(zcu).toByteUnits().?, - }, - .lazy_size => |ty| continue :storage .{ - .u64 = ZigType.fromInterned(ty).abiSize(zcu), - }, }, .err => |err| continue :constant_key .{ .int = .{ .ty = err.ty, @@ -11084,13 +11075,9 @@ pub const Value = struct { var field_offset: u64 = 0; var field_it = loaded_struct.iterateRuntimeOrder(ip); while (field_it.next()) |field_index| { - if (loaded_struct.fieldIsComptime(ip, field_index)) continue; + if (loaded_struct.field_is_comptime_bits.get(ip, field_index)) continue; const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - field_offset = field_ty.structFieldAlignment( - loaded_struct.fieldAlign(ip, field_index), - loaded_struct.layout, - zcu, - ).forward(field_offset); + field_offset = loaded_struct.field_offsets.get(ip)[field_index]; const field_size = field_ty.abiSize(zcu); if (offset >= field_offset and offset + size <= field_offset + field_size) { offset -= field_offset; @@ -11132,7 +11119,7 @@ pub const Value = struct { .un => |un| { const loaded_union = ip.loadUnionType(un.ty); const union_layout = ZigType.getUnionLayout(loaded_union, zcu); - if (loaded_union.hasTag(ip)) { + if (loaded_union.has_runtime_tag) { const tag_offset = union_layout.tagOffset(); if (offset >= tag_offset and offset + size <= tag_offset + union_layout.tag_size) { offset -= tag_offset; @@ -11477,13 +11464,9 @@ fn writeKeyToMemory(isel: *Select, constant_key: InternPool.Key, buffer: []u8) e var field_offset: u64 = 0; var field_it = loaded_struct.iterateRuntimeOrder(ip); while (field_it.next()) |field_index| { - if (loaded_struct.fieldIsComptime(ip, field_index)) continue; + if (loaded_struct.field_is_comptime_bits.get(ip, field_index)) continue; const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - field_offset = field_ty.structFieldAlignment( - loaded_struct.fieldAlign(ip, field_index), - loaded_struct.layout, - zcu, - ).forward(field_offset); + field_offset = loaded_struct.field_offsets.get(ip)[field_index]; const field_size = field_ty.abiSize(zcu); if (!try isel.writeToMemory(.fromInterned(switch (aggregate.storage) { .bytes => unreachable, @@ -12082,7 +12065,7 @@ pub const CallAbiIterator = struct { const zcu = isel.pt.zcu; const ip = &zcu.intern_pool; - if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) return null; + if (!ty.hasRuntimeBits(zcu)) return null; try isel.values.ensureUnusedCapacity(zcu.gpa, Value.max_parts); const wip_vi = isel.initValue(ty); type_key: switch (ip.indexToKey(ty.toIntern())) { @@ -12186,7 +12169,7 @@ pub const CallAbiIterator = struct { switch (loaded_struct.layout) { .auto, .@"extern" => {}, .@"packed" => continue :type_key .{ - .int_type = ip.indexToKey(loaded_struct.backingIntTypeUnordered(ip)).int_type, + .int_type = ip.indexToKey(loaded_struct.packed_backing_int_type).int_type, }, } const size = wip_vi.size(isel); @@ -12210,7 +12193,7 @@ pub const CallAbiIterator = struct { const field_end = next_field_end; const next_field_begin = if (field_it.next()) |field_index| next_field_begin: { const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - const next_field_begin = switch (loaded_struct.fieldAlign(ip, field_index)) { + const next_field_begin = switch (loaded_struct.field_aligns.getOrNone(ip, field_index)) { .none => field_ty.abiAlignment(zcu), else => |field_align| field_align, }.forward(field_end); @@ -12276,7 +12259,7 @@ pub const CallAbiIterator = struct { }, .union_type => { const loaded_union = ip.loadUnionType(ty.toIntern()); - switch (loaded_union.flagsUnordered(ip).layout) { + switch (loaded_union.layout) { .auto, .@"extern" => {}, .@"packed" => continue :type_key .{ .int_type = .{ .signedness = .unsigned, @@ -12309,7 +12292,9 @@ pub const CallAbiIterator = struct { } }, .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque }, - .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty), + .enum_type => continue :type_key .{ + .int_type = ip.indexToKey(ip.loadEnumType(ty.toIntern()).int_tag_type).int_type, + }, .error_set_type, .inferred_error_set_type, => continue :type_key .{ .simple_type = .anyerror }, @@ -12414,8 +12399,8 @@ pub const CallAbiIterator = struct { const ip = &zcu.intern_pool; var common_fdt: ?FundamentalDataType = null; for (0.., loaded_struct.field_types.get(ip)) |field_index, field_ty| { - if (loaded_struct.fieldIsComptime(ip, field_index)) continue; - if (loaded_struct.fieldAlign(ip, field_index) != .none) return null; + if (loaded_struct.field_is_comptime_bits.get(ip, field_index)) continue; + if (loaded_struct.field_aligns.getOrNone(ip, field_index) != .none) return null; if (!ZigType.fromInterned(field_ty).hasRuntimeBits(zcu)) continue; const fdt = homogeneousAggregateBaseType(zcu, field_ty); if (common_fdt == null) common_fdt = fdt else if (fdt != common_fdt) return null; diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 879dc0e45a649a24692c7b49d0af71de71f061c8..c8904405e218072fc80d8753603c1e0689022f25 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1052,17 +1052,7 @@ pub const DeclGen = struct { .func, .enum_literal, => unreachable, // non-runtime values - .int => |int| switch (int.storage) { - .u64, .i64, .big_int => try w.print("{f}", .{try dg.fmtIntLiteralDec(val, location)}), - .lazy_align, .lazy_size => { - try w.writeAll("(("); - try dg.renderCType(w, ctype); - try w.print("){f})", .{try dg.fmtIntLiteralHex( - try pt.intValue(.usize, val.toUnsignedInt(zcu)), - .Other, - )}); - }, - }, + .int => try w.print("{f}", .{try dg.fmtIntLiteralDec(val, location)}), .err => |err| try dg.renderErrorName(w, err.name), .error_union => |error_union| switch (ctype.info(ctype_pool)) { .basic => switch (error_union.val) { @@ -1338,7 +1328,7 @@ pub const DeclGen = struct { const comptime_val = tuple.values.get(ip)[field_index]; if (comptime_val != .none) continue; const field_ty: Type = .fromInterned(tuple.types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; if (!empty) try w.writeByte(','); @@ -1373,7 +1363,7 @@ pub const DeclGen = struct { var need_comma = false; while (field_it.next()) |field_index| { const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; if (need_comma) try w.writeByte(','); need_comma = true; @@ -1396,7 +1386,7 @@ pub const DeclGen = struct { const loaded_union = ip.loadUnionType(ty.toIntern()); if (un.tag == .none) { const backing_ty = try ty.externUnionBackingType(pt); - assert(loaded_union.flagsUnordered(ip).layout == .@"extern"); + assert(loaded_union.layout == .@"extern"); if (location == .StaticInitializer) { return dg.fail("TODO: C backend: implement extern union backing type rendering in static initializers", .{}); } @@ -1418,9 +1408,9 @@ pub const DeclGen = struct { const field_index = zcu.unionTagFieldIndex(loaded_union, Value.fromInterned(un.tag)).?; const field_ty: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); - const field_name = loaded_union.loadTagType(ip).names.get(ip)[field_index]; + const field_name = ip.loadEnumType(loaded_union.enum_tag_type).field_names.get(ip)[field_index]; - const has_tag = loaded_union.hasTag(ip); + const has_tag = loaded_union.has_runtime_tag; if (has_tag) try w.writeByte('{'); const aggregate = ctype.info(ctype_pool).aggregate; for (0..if (has_tag) aggregate.fields.len else 1) |outer_field_index| { @@ -1597,7 +1587,7 @@ pub const DeclGen = struct { var need_comma = false; while (field_it.next()) |field_index| { const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; if (need_comma) try w.writeByte(','); need_comma = true; @@ -1620,7 +1610,7 @@ pub const DeclGen = struct { for (0..tuple_info.types.len) |field_index| { if (tuple_info.values.get(ip)[field_index] != .none) continue; const field_ty: Type = .fromInterned(tuple_info.types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; if (need_comma) try w.writeByte(','); need_comma = true; @@ -1630,7 +1620,7 @@ pub const DeclGen = struct { }, .union_type => { const loaded_union = ip.loadUnionType(ty.toIntern()); - switch (loaded_union.flagsUnordered(ip).layout) { + switch (loaded_union.layout) { .auto, .@"extern" => { if (!location.isInitializer()) { try w.writeByte('('); @@ -1638,7 +1628,7 @@ pub const DeclGen = struct { try w.writeByte(')'); } - const has_tag = loaded_union.hasTag(ip); + const has_tag = loaded_union.has_runtime_tag; if (has_tag) try w.writeByte('{'); const aggregate = ctype.info(ctype_pool).aggregate; for (0..if (has_tag) aggregate.fields.len else 1) |outer_field_index| { @@ -1649,7 +1639,7 @@ pub const DeclGen = struct { .payload) { .tag => try dg.renderUndefValue( w, - .fromInterned(loaded_union.enum_tag_ty), + .fromInterned(loaded_union.enum_tag_type), initializer_type, ), .payload => { @@ -1760,6 +1750,7 @@ pub const DeclGen = struct { .opt, .aggregate, .un, + .bitpack, .memoized_call, => unreachable, // values, not types }, @@ -2797,7 +2788,7 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn } }); try w.print("case {f}: {{", .{ - try o.dg.fmtIntLiteralDec(try tag_val.intFromEnum(enum_ty, pt), .Other), + try o.dg.fmtIntLiteralDec(tag_val.intFromEnum(zcu), .Other), }); o.indent(); try o.newline(); @@ -3599,10 +3590,7 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { const zcu = f.object.dg.pt.zcu; const inst_ty = f.typeOfIndex(inst); const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; - if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - return .none; - } + assert(inst_ty.hasRuntimeBits(zcu)); const ptr = try f.resolveInst(bin_op.lhs); const index = try f.resolveInst(bin_op.rhs); @@ -3629,7 +3617,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { const inst_ty = f.typeOfIndex(inst); const ptr_ty = f.typeOf(bin_op.lhs); - const elem_has_bits = ptr_ty.indexableElem(zcu).hasRuntimeBitsIgnoreComptime(zcu); + assert(ptr_ty.indexableElem(zcu).hasRuntimeBits(zcu)); const ptr = try f.resolveInst(bin_op.lhs); const index = try f.resolveInst(bin_op.rhs); @@ -3643,16 +3631,14 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { try w.writeByte('('); try f.renderType(w, inst_ty); try w.writeByte(')'); - if (elem_has_bits) try w.writeByte('&'); - if (elem_has_bits and ptr_ty.ptrSize(zcu) == .one) { + try w.writeByte('&'); + if (ptr_ty.ptrSize(zcu) == .one) { // It's a pointer to an array, so we need to de-reference. try f.writeCValueDeref(w, ptr); } else try f.writeCValue(w, ptr, .Other); - if (elem_has_bits) { - try w.writeByte('['); - try f.writeCValue(w, index, .Other); - try w.writeByte(']'); - } + try w.writeByte('['); + try f.writeCValue(w, index, .Other); + try w.writeByte(']'); try a.end(f, w); return local; } @@ -3661,10 +3647,7 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { const zcu = f.object.dg.pt.zcu; const inst_ty = f.typeOfIndex(inst); const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; - if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - return .none; - } + assert(inst_ty.hasRuntimeBits(zcu)); const slice = try f.resolveInst(bin_op.lhs); const index = try f.resolveInst(bin_op.rhs); @@ -3692,7 +3675,7 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { const inst_ty = f.typeOfIndex(inst); const slice_ty = f.typeOf(bin_op.lhs); const elem_ty = slice_ty.childType(zcu); - const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(zcu); + assert(elem_ty.hasRuntimeBits(zcu)); const slice = try f.resolveInst(bin_op.lhs); const index = try f.resolveInst(bin_op.rhs); @@ -3703,13 +3686,11 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); try f.writeCValue(w, local, .Other); try a.assign(f, w); - if (elem_has_bits) try w.writeByte('&'); + try w.writeByte('&'); try f.writeCValueMember(w, slice, .{ .identifier = "ptr" }); - if (elem_has_bits) { - try w.writeByte('['); - try f.writeCValue(w, index, .Other); - try w.writeByte(']'); - } + try w.writeByte('['); + try f.writeCValue(w, index, .Other); + try w.writeByte(']'); try a.end(f, w); return local; } @@ -3718,10 +3699,7 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { const zcu = f.object.dg.pt.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const inst_ty = f.typeOfIndex(inst); - if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - return .none; - } + assert(inst_ty.hasRuntimeBits(zcu)); const array = try f.resolveInst(bin_op.lhs); const index = try f.resolveInst(bin_op.rhs); @@ -3853,10 +3831,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { // bit-pointers we see here are vector element pointers. assert(ptr_info.packed_offset.host_size == 0 or ptr_info.flags.vector_index != .none); - if (!src_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - try reap(f, inst, &.{ty_op.operand}); - return .none; - } + assert(src_ty.hasRuntimeBits(zcu)); const operand = try f.resolveInst(ty_op.operand); @@ -4456,7 +4431,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { const inst_ty = f.typeOfIndex(inst); const inst_scalar_ty = inst_ty.scalarType(zcu); const elem_ty = inst_scalar_ty.indexableElem(zcu); - if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return f.moveCValue(inst, inst_ty, lhs); + assert(elem_ty.hasRuntimeBits(zcu)); const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); const local = try f.allocLocal(inst, inst_ty); @@ -4787,7 +4762,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) const w = &f.object.code.writer; const inst_ty = f.typeOfIndex(inst); - const result = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu) and !f.liveness.isUnused(inst)) + const result = if (inst_ty.hasRuntimeBits(zcu) and !f.liveness.isUnused(inst)) try f.allocLocal(inst, inst_ty) else .none; @@ -4853,7 +4828,7 @@ fn lowerTry( const liveness_condbr = f.liveness.getCondBr(inst); const w = &f.object.code.writer; const payload_ty = err_union_ty.errorUnionPayload(zcu); - const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(zcu); + const payload_has_bits = payload_ty.hasRuntimeBits(zcu); if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) { try w.writeAll("if ("); @@ -5393,7 +5368,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { const result = result: { const w = &f.object.code.writer; const inst_ty = f.typeOfIndex(inst); - const inst_local = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) local: { + const inst_local = if (inst_ty.hasRuntimeBits(zcu)) local: { const inst_local = try f.allocLocalValue(.{ .ctype = try f.ctypeFromType(inst_ty, .complete), .alignas = CType.AlignAs.fromAbiAlignment(inst_ty.abiAlignment(zcu)), @@ -5820,12 +5795,12 @@ fn fieldLocation( .struct_type => { const loaded_struct = ip.loadStructType(container_ty.toIntern()); return switch (loaded_struct.layout) { - .auto, .@"extern" => if (!container_ty.hasRuntimeBitsIgnoreComptime(zcu)) + .auto, .@"extern" => if (!container_ty.hasRuntimeBits(zcu)) .begin - else if (!field_ptr_ty.childType(zcu).hasRuntimeBitsIgnoreComptime(zcu)) - .{ .byte_offset = loaded_struct.offsets.get(ip)[field_index] } + else if (!field_ptr_ty.childType(zcu).hasRuntimeBits(zcu)) + .{ .byte_offset = loaded_struct.field_offsets.get(ip)[field_index] } else - .{ .field = .{ .identifier = loaded_struct.fieldName(ip, field_index).toSlice(ip) } }, + .{ .field = .{ .identifier = loaded_struct.field_names.get(ip)[field_index].toSlice(ip) } }, .@"packed" => if (field_ptr_ty.ptrInfo(zcu).packed_offset.host_size == 0) .{ .byte_offset = @divExact(zcu.structPackedFieldBitOffset(loaded_struct, field_index) + container_ptr_ty.ptrInfo(zcu).packed_offset.bit_offset, 8) } @@ -5833,24 +5808,24 @@ fn fieldLocation( .begin, }; }, - .tuple_type => return if (!container_ty.hasRuntimeBitsIgnoreComptime(zcu)) + .tuple_type => return if (!container_ty.hasRuntimeBits(zcu)) .begin - else if (!field_ptr_ty.childType(zcu).hasRuntimeBitsIgnoreComptime(zcu)) + else if (!field_ptr_ty.childType(zcu).hasRuntimeBits(zcu)) .{ .byte_offset = container_ty.structFieldOffset(field_index, zcu) } else .{ .field = .{ .field = field_index } }, .union_type => { const loaded_union = ip.loadUnionType(container_ty.toIntern()); - switch (loaded_union.flagsUnordered(ip).layout) { + switch (loaded_union.layout) { .auto, .@"extern" => { const field_ty: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) + if (!field_ty.hasRuntimeBits(zcu)) return if (loaded_union.has_runtime_tag and !container_ty.unionHasAllZeroBitFieldTypes(zcu)) .{ .field = .{ .identifier = "payload" } } else .begin; - const field_name = loaded_union.loadTagType(ip).names.get(ip)[field_index]; - return .{ .field = if (loaded_union.hasTag(ip)) + const field_name = ip.loadEnumType(loaded_union.enum_tag_type).field_names.get(ip)[field_index]; + return .{ .field = if (loaded_union.has_runtime_tag) .{ .payload_identifier = field_name.toSlice(ip) } else .{ .identifier = field_name.toSlice(ip) } }; @@ -5996,10 +5971,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { const extra = f.air.extraData(Air.StructField, ty_pl.payload).data; const inst_ty = f.typeOfIndex(inst); - if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - try reap(f, inst, &.{extra.struct_operand}); - return .none; - } + assert(inst_ty.hasRuntimeBits(zcu)); const struct_byval = try f.resolveInst(extra.struct_operand); try reap(f, inst, &.{extra.struct_operand}); @@ -6014,9 +5986,9 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { .struct_type => .{ .identifier = struct_ty.structFieldName(extra.field_index, zcu).unwrap().?.toSlice(ip) }, .union_type => name: { const union_type = ip.loadUnionType(struct_ty.toIntern()); - const enum_tag_ty: Type = .fromInterned(union_type.enum_tag_ty); + const enum_tag_ty: Type = .fromInterned(union_type.enum_tag_type); const field_name_str = enum_tag_ty.enumFieldName(extra.field_index, zcu).toSlice(ip); - if (union_type.hasTag(ip)) { + if (union_type.has_runtime_tag) { break :name .{ .payload_identifier = field_name_str }; } else { break :name .{ .identifier = field_name_str }; @@ -6161,7 +6133,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { const inst_ty = f.typeOfIndex(inst); const payload_ty = inst_ty.errorUnionPayload(zcu); - const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(zcu); + const repr_is_err = !payload_ty.hasRuntimeBits(zcu); const err_ty = inst_ty.errorUnionSet(zcu); const err = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); @@ -6210,7 +6182,7 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { try reap(f, inst, &.{ty_op.operand}); // First, set the non-error value. - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { const a = try Assignment.start(f, w, try f.ctypeFromType(operand_ty, .complete)); try f.writeCValueDeref(w, operand); try a.assign(f, w); @@ -6262,13 +6234,13 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { const inst_ty = f.typeOfIndex(inst); const payload_ty = inst_ty.errorUnionPayload(zcu); const payload = try f.resolveInst(ty_op.operand); - const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(zcu); + assert(payload_ty.hasRuntimeBits(zcu)); const err_ty = inst_ty.errorUnionSet(zcu); try reap(f, inst, &.{ty_op.operand}); const w = &f.object.code.writer; const local = try f.allocLocal(inst, inst_ty); - if (!repr_is_err) { + { const a = try Assignment.start(f, w, try f.ctypeFromType(payload_ty, .complete)); try f.writeCValueMember(w, local, .{ .identifier = "payload" }); try a.assign(f, w); @@ -6277,10 +6249,7 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { } { const a = try Assignment.start(f, w, try f.ctypeFromType(err_ty, .complete)); - if (repr_is_err) - try f.writeCValue(w, local, .Other) - else - try f.writeCValueMember(w, local, .{ .identifier = "error" }); + try f.writeCValueMember(w, local, .{ .identifier = "error" }); try a.assign(f, w); try f.object.dg.renderValue(w, try pt.intValue(try pt.errorIntType(), 0), .Other); try a.end(f, w); @@ -7411,10 +7380,10 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { var field_it = loaded_struct.iterateRuntimeOrder(ip); while (field_it.next()) |field_index| { const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; const a = try Assignment.start(f, w, try f.ctypeFromType(field_ty, .complete)); - try f.writeCValueMember(w, local, .{ .identifier = loaded_struct.fieldName(ip, field_index).toSlice(ip) }); + try f.writeCValueMember(w, local, .{ .identifier = loaded_struct.field_names.get(ip)[field_index].toSlice(ip) }); try a.assign(f, w); try f.writeCValue(w, resolved_elements[field_index], .Other); try a.end(f, w); @@ -7426,7 +7395,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { .tuple_type => |tuple_info| for (0..tuple_info.types.len) |field_index| { if (tuple_info.values.get(ip)[field_index] != .none) continue; const field_ty: Type = .fromInterned(tuple_info.types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; const a = try Assignment.start(f, w, try f.ctypeFromType(field_ty, .complete)); try f.writeCValueMember(w, local, .{ .field = field_index }); @@ -7449,13 +7418,13 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { const union_ty = f.typeOfIndex(inst); const loaded_union = ip.loadUnionType(union_ty.toIntern()); - const field_name = loaded_union.loadTagType(ip).names.get(ip)[extra.field_index]; + const field_name = ip.loadEnumType(loaded_union.enum_tag_type).field_names.get(ip)[extra.field_index]; const payload_ty = f.typeOf(extra.init); const payload = try f.resolveInst(extra.init); try reap(f, inst, &.{extra.init}); const w = &f.object.code.writer; - if (loaded_union.flagsUnordered(ip).layout == .@"packed") return f.moveCValue(inst, union_ty, payload); + if (loaded_union.layout == .@"packed") return f.moveCValue(inst, union_ty, payload); const local = try f.allocLocal(inst, union_ty); @@ -7466,7 +7435,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { const a = try Assignment.start(f, w, try f.ctypeFromType(tag_ty, .complete)); try f.writeCValueMember(w, local, .{ .identifier = "tag" }); try a.assign(f, w); - try w.print("{f}", .{try f.fmtIntLiteralDec(try tag_val.intFromEnum(tag_ty, pt))}); + try w.print("{f}", .{try f.fmtIntLiteralDec(tag_val.intFromEnum(zcu))}); try a.end(f, w); break :field .{ .payload_identifier = field_name.toSlice(ip) }; } else .{ .identifier = field_name.toSlice(ip) }; diff --git a/src/codegen/c/Type.zig b/src/codegen/c/Type.zig index f28dd48a1775ad0f4deea189ba22121b0c62af10..a7442a1d49dae8c626c54e448364e6169bf0eff6 100644 --- a/src/codegen/c/Type.zig +++ b/src/codegen/c/Type.zig @@ -2558,7 +2558,7 @@ pub const Pool = struct { .tag = .@"struct", .name = .{ .index = ip_index }, }); - if (kind.isForward()) return if (ty.hasRuntimeBitsIgnoreComptime(zcu)) + if (kind.isForward()) return if (ty.hasRuntimeBits(zcu)) fwd_decl else .void; @@ -2584,9 +2584,9 @@ pub const Pool = struct { kind.noParameter(), ); if (field_ctype.index == .void) continue; - const field_name = try pool.string(allocator, loaded_struct.fieldName(ip, field_index).toSlice(ip)); + const field_name = try pool.string(allocator, loaded_struct.field_names.get(ip)[field_index].toSlice(ip)); const field_alignas = AlignAs.fromAlignment(.{ - .@"align" = loaded_struct.fieldAlign(ip, field_index), + .@"align" = loaded_struct.field_aligns.getOrNone(ip, field_index), .abi = field_type.abiAlignment(zcu), }); pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{ @@ -2613,7 +2613,7 @@ pub const Pool = struct { .@"packed" => return pool.fromType( allocator, scratch, - Type.fromInterned(loaded_struct.backingIntTypeUnordered(ip)), + .fromInterned(loaded_struct.packed_backing_int_type), pt, mod, kind, @@ -2682,17 +2682,17 @@ pub const Pool = struct { }, .union_type => { const loaded_union = ip.loadUnionType(ip_index); - switch (loaded_union.flagsUnordered(ip).layout) { + switch (loaded_union.layout) { .auto, .@"extern" => { const fwd_decl = try pool.getFwdDecl(allocator, .{ .tag = if (loaded_union.has_runtime_tag) .@"struct" else .@"union", .name = .{ .index = ip_index }, }); - if (kind.isForward()) return if (ty.hasRuntimeBitsIgnoreComptime(zcu)) + if (kind.isForward()) return if (ty.hasRuntimeBits(zcu)) fwd_decl else .void; - const loaded_tag = loaded_union.loadTagType(ip); + const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); const scratch_top = scratch.items.len; defer scratch.shrinkRetainingCapacity(scratch_top); try scratch.ensureUnusedCapacity( @@ -2718,10 +2718,10 @@ pub const Pool = struct { if (field_ctype.index == .void) continue; const field_name = try pool.string( allocator, - loaded_tag.names.get(ip)[field_index].toSlice(ip), + loaded_tag.field_names.get(ip)[field_index].toSlice(ip), ); const field_alignas = AlignAs.fromAlignment(.{ - .@"align" = loaded_union.fieldAlign(ip, field_index), + .@"align" = loaded_union.field_aligns.getOrNone(ip, field_index), .abi = field_type.abiAlignment(zcu), }); pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{ @@ -2753,24 +2753,22 @@ pub const Pool = struct { try pool.ensureUnusedCapacity(allocator, 2); var struct_fields: [2]Info.Field = undefined; var struct_fields_len: usize = 0; - if (loaded_tag.tag_ty != .comptime_int_type) { - const tag_type = Type.fromInterned(loaded_tag.tag_ty); - const tag_ctype: CType = try pool.fromType( - allocator, - scratch, - tag_type, - pt, - mod, - kind.noParameter(), - ); - if (tag_ctype.index != .void) { - struct_fields[struct_fields_len] = .{ - .name = .{ .index = .tag }, - .ctype = tag_ctype, - .alignas = AlignAs.fromAbiAlignment(tag_type.abiAlignment(zcu)), - }; - struct_fields_len += 1; - } + const tag_type = Type.fromInterned(loaded_tag.int_tag_type); + const tag_ctype: CType = try pool.fromType( + allocator, + scratch, + tag_type, + pt, + mod, + kind.noParameter(), + ); + if (tag_ctype.index != .void) { + struct_fields[struct_fields_len] = .{ + .name = .{ .index = .tag }, + .ctype = tag_ctype, + .alignas = AlignAs.fromAbiAlignment(tag_type.abiAlignment(zcu)), + }; + struct_fields_len += 1; } if (fields_len > 0) { const payload_ctype = payload_ctype: { @@ -2823,12 +2821,14 @@ pub const Pool = struct { .enum_type => return pool.fromType( allocator, scratch, - Type.fromInterned(ip.loadEnumType(ip_index).tag_ty), + .fromInterned(ip.loadEnumType(ip_index).int_tag_type), pt, mod, kind, ), - .func_type => |func_info| if (func_info.is_generic) return .void else { + .func_type => |func_info| { + if (!ty.fnHasRuntimeBits(zcu)) return .void; + const scratch_top = scratch.items.len; defer scratch.shrinkRetainingCapacity(scratch_top); try scratch.ensureUnusedCapacity(allocator, func_info.param_types.len); @@ -2894,6 +2894,7 @@ pub const Pool = struct { .opt, .aggregate, .un, + .bitpack, .memoized_call, => unreachable, // values, not types }, diff --git a/src/codegen/riscv64/CodeGen.zig b/src/codegen/riscv64/CodeGen.zig index 1f5b6224d7ef7fbe1cfe1aaa2fc55889db0676ca..3ad6faf805259154ae35f347e1dee712bea196cf 100644 --- a/src/codegen/riscv64/CodeGen.zig +++ b/src/codegen/riscv64/CodeGen.zig @@ -3257,7 +3257,7 @@ fn airOptionalPayload(func: *Func, inst: Air.Inst.Index) !void { const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = result: { const pl_ty = func.typeOfIndex(inst); - if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none; + if (!pl_ty.hasRuntimeBits(zcu)) break :result .none; const opt_mcv = try func.resolveInst(ty_op.operand); if (func.reuseOperand(inst, ty_op.operand, 0, opt_mcv)) { @@ -3331,7 +3331,7 @@ fn airUnwrapErrErr(func: *Func, inst: Air.Inst.Index) !void { break :result .{ .immediate = 0 }; } - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { break :result operand; } @@ -3384,7 +3384,7 @@ fn genUnwrapErrUnionPayloadMir( const payload_ty = err_union_ty.errorUnionPayload(zcu); const result: MCValue = result: { - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none; + if (!payload_ty.hasRuntimeBits(zcu)) break :result .none; const payload_off: u31 = @intCast(errUnionPayloadOffset(payload_ty, zcu)); switch (err_union) { @@ -3547,7 +3547,7 @@ fn airWrapErrUnionPayload(func: *Func, inst: Air.Inst.Index) !void { const operand = try func.resolveInst(ty_op.operand); const result: MCValue = result: { - if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .{ .immediate = 0 }; + if (!pl_ty.hasRuntimeBits(zcu)) break :result .{ .immediate = 0 }; const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(eu_ty, zcu)); const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu)); @@ -3571,7 +3571,7 @@ fn airWrapErrUnionErr(func: *Func, inst: Air.Inst.Index) !void { const err_ty = eu_ty.errorUnionSet(zcu); const result: MCValue = result: { - if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result try func.resolveInst(ty_op.operand); + if (!pl_ty.hasRuntimeBits(zcu)) break :result try func.resolveInst(ty_op.operand); const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(eu_ty, zcu)); const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu)); @@ -3761,7 +3761,7 @@ fn airSliceElemVal(func: *Func, inst: Air.Inst.Index) !void { const result: MCValue = result: { const elem_ty = func.typeOfIndex(inst); - if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none; + assert(elem_ty.hasRuntimeBits(zcu)); const slice_ty = func.typeOf(bin_op.lhs); const slice_ptr_field_type = slice_ty.slicePtrFieldType(zcu); @@ -3914,7 +3914,7 @@ fn airPtrElemVal(func: *Func, inst: Air.Inst.Index) !void { const result: MCValue = if (!is_volatile and func.liveness.isUnused(inst)) .unreach else result: { const elem_ty = base_ptr_ty.indexableElem(zcu); - if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none; + assert(elem_ty.hasRuntimeBits(zcu)); const base_ptr_mcv = try func.resolveInst(bin_op.lhs); const base_ptr_lock: ?RegisterLock = switch (base_ptr_mcv) { .register => |reg| func.register_manager.lockRegAssumeUnused(reg), @@ -4617,7 +4617,7 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void { const src_mcv = try func.resolveInst(operand); const struct_ty = func.typeOf(operand); const field_ty = struct_ty.fieldType(index, zcu); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none; + assert(field_ty.hasRuntimeBits(zcu)); const field_off: u32 = switch (struct_ty.containerLayout(zcu)) { .auto, .@"extern" => @intCast(struct_ty.structFieldOffset(index, zcu) * 8), @@ -5126,7 +5126,6 @@ fn airCmp(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const pt = func.pt; const zcu = pt.zcu; - const ip = &zcu.intern_pool; const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: { const lhs_ty = func.typeOf(bin_op.lhs); @@ -5140,28 +5139,23 @@ fn airCmp(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { .optional, .@"struct", => { - const int_ty = switch (lhs_ty.zigTypeTag(zcu)) { + const int_ty: Type = switch (lhs_ty.zigTypeTag(zcu)) { .@"enum" => lhs_ty.intTagType(zcu), .int => lhs_ty, - .bool => Type.u1, - .pointer => Type.u64, - .error_set => Type.anyerror, + .bool => .u1, + .pointer => .u64, + .error_set => .anyerror, .optional => blk: { const payload_ty = lhs_ty.optionalChild(zcu); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - break :blk Type.u1; + if (!payload_ty.hasRuntimeBits(zcu)) { + break :blk .u1; } else if (lhs_ty.isPtrLikeOptional(zcu)) { - break :blk Type.u64; + break :blk .u64; } else { return func.fail("TODO riscv cmp non-pointer optionals", .{}); } }, - .@"struct" => blk: { - const struct_obj = ip.loadStructType(lhs_ty.toIntern()); - assert(struct_obj.layout == .@"packed"); - const backing_index = struct_obj.backingIntTypeUnordered(ip); - break :blk Type.fromInterned(backing_index); - }, + .@"struct", .@"union" => lhs_ty.bitpackBackingInt(zcu), else => unreachable, }; @@ -5925,8 +5919,7 @@ fn airBr(func: *Func, inst: Air.Inst.Index) !void { const br = func.air.instructions.items(.data)[@intFromEnum(inst)].br; const block_ty = func.typeOfIndex(br.block_inst); - const block_unused = - !block_ty.hasRuntimeBitsIgnoreComptime(zcu) or func.liveness.isUnused(br.block_inst); + const block_unused = !block_ty.hasRuntimeBits(zcu) or func.liveness.isUnused(br.block_inst); const block_tracking = func.inst_tracking.getPtr(br.block_inst).?; const block_data = func.blocks.getPtr(br.block_inst).?; const first_br = block_data.relocs.items.len == 0; @@ -8249,7 +8242,7 @@ fn resolveCallingConventionValues( // Return values if (ret_ty.zigTypeTag(zcu) == .noreturn) { result.return_value = InstTracking.init(.unreach); - } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + } else if (!ret_ty.hasRuntimeBits(zcu)) { result.return_value = InstTracking.init(.none); } else { var ret_tracking: [2]InstTracking = undefined; @@ -8300,7 +8293,7 @@ fn resolveCallingConventionValues( var param_float_reg_i: usize = 0; for (param_types, result.args) |ty, *arg| { - if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!ty.hasRuntimeBits(zcu)) { assert(cc == .auto); arg.* = .none; continue; @@ -8415,10 +8408,10 @@ fn hasFeature(func: *Func, feature: Target.riscv.Feature) bool { } pub fn errUnionPayloadOffset(payload_ty: Type, zcu: *Zcu) u64 { - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return 0; + if (!payload_ty.hasRuntimeBits(zcu)) return 0; const payload_align = payload_ty.abiAlignment(zcu); const error_align = Type.anyerror.abiAlignment(zcu); - if (payload_align.compare(.gte, error_align) or !payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (payload_align.compare(.gte, error_align) or !payload_ty.hasRuntimeBits(zcu)) { return 0; } else { return payload_align.forward(Type.anyerror.abiSize(zcu)); @@ -8426,10 +8419,10 @@ pub fn errUnionPayloadOffset(payload_ty: Type, zcu: *Zcu) u64 { } pub fn errUnionErrorOffset(payload_ty: Type, zcu: *Zcu) u64 { - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return 0; + if (!payload_ty.hasRuntimeBits(zcu)) return 0; const payload_align = payload_ty.abiAlignment(zcu); const error_align = Type.anyerror.abiAlignment(zcu); - if (payload_align.compare(.gte, error_align) and payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (payload_align.compare(.gte, error_align) and payload_ty.hasRuntimeBits(zcu)) { return error_align.forward(payload_ty.abiSize(zcu)); } else { return 0; diff --git a/src/codegen/sparc64/CodeGen.zig b/src/codegen/sparc64/CodeGen.zig index a246df12c59f3277001ba28fd671b6c42fe769e7..3b38d6319ac325cb462b805727197121be348bfd 100644 --- a/src/codegen/sparc64/CodeGen.zig +++ b/src/codegen/sparc64/CodeGen.zig @@ -1102,7 +1102,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void { fn lowerBlock(self: *Self, inst: Air.Inst.Index, body: []const Air.Inst.Index) !void { try self.blocks.putNoClobber(self.gpa, inst, .{ // A block is a setup to be able to jump to the end. - .relocs = .{}, + .relocs = .empty, // It also acts as a receptacle for break operands. // Here we use `MCValue.none` to represent a null value so that the first // break instruction will choose a MCValue for the block result and overwrite @@ -1376,19 +1376,19 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { const rhs = try self.resolveInst(bin_op.rhs); const lhs_ty = self.typeOf(bin_op.lhs); - const int_ty = switch (lhs_ty.zigTypeTag(zcu)) { + const int_ty: Type = switch (lhs_ty.zigTypeTag(zcu)) { .vector => unreachable, // Handled by cmp_vector. .@"enum" => lhs_ty.intTagType(zcu), .int => lhs_ty, - .bool => Type.u1, - .pointer => Type.usize, - .error_set => Type.u16, + .bool => .u1, + .pointer => .usize, + .error_set => .u16, .optional => blk: { const payload_ty = lhs_ty.optionalChild(zcu); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - break :blk Type.u1; + if (!payload_ty.hasRuntimeBits(zcu)) { + break :blk .u1; } else if (lhs_ty.isPtrLikeOptional(zcu)) { - break :blk Type.usize; + break :blk .usize; } else { return self.fail("TODO SPARCv9 cmp non-pointer optionals", .{}); } @@ -3452,8 +3452,8 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) if (err_ty.errorSetIsEmpty(zcu)) { return error_union_mcv; } - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - return MCValue.none; + if (!payload_ty.hasRuntimeBits(zcu)) { + return .none; } const payload_offset: u32 = @intCast(errUnionPayloadOffset(payload_ty, zcu)); @@ -4481,7 +4481,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { const ty = self.typeOf(ref); // If the type has no codegen bits, no need to store it. - if (!ty.hasRuntimeBitsIgnoreComptime(pt.zcu)) return .none; + if (!ty.hasRuntimeBits(pt.zcu)) return .none; if (ref.toIndex()) |inst| { return self.getResolvedInstValue(inst); diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig index d303af6d610ded6effd8ff80e41cdab36650bd90..34a7f99ce4f30d39e8dd4caf710390816abf220f 100644 --- a/src/codegen/spirv/CodeGen.zig +++ b/src/codegen/spirv/CodeGen.zig @@ -208,7 +208,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { try cg.args.ensureUnusedCapacity(gpa, fn_info.param_types.len); for (fn_info.param_types.get(ip)) |param_ty_index| { const param_ty: Type = .fromInterned(param_ty_index); - if (!param_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!param_ty.hasRuntimeBits(zcu)) continue; const param_type_id = try cg.resolveType(param_ty, .direct); const arg_result_id = cg.module.allocId(); @@ -884,7 +884,7 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { return try cg.constructComposite(comp_ty_id, &constituents); }, .enum_tag => { - const int_val = try val.intFromEnum(ty, pt); + const int_val = val.intFromEnum(zcu); const int_ty = ty.intTagType(zcu); break :cache try cg.constant(int_ty, int_val, repr); }, @@ -959,18 +959,7 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { }, .struct_type => { const struct_type = zcu.typeToStruct(ty).?; - - if (struct_type.layout == .@"packed") { - // TODO: composite int - // TODO: endianness - const bits: u16 = @intCast(ty.bitSize(zcu)); - const bytes = std.mem.alignForward(u16, cg.module.backingIntBits(bits).@"0", 8) / 8; - var limbs: [8]u8 = undefined; - @memset(&limbs, 0); - val.writeToPackedMemory(pt, limbs[0..bytes], 0) catch unreachable; - const backing_ty: Type = .fromInterned(struct_type.backingIntTypeUnordered(ip)); - return try cg.constInt(backing_ty, @as(u64, @bitCast(limbs))); - } + assert(struct_type.layout != .@"packed"); // packed structs use `bitpack` var types = std.array_list.Managed(Type).init(gpa); defer types.deinit(); @@ -981,7 +970,7 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { var it = struct_type.iterateRuntimeOrder(ip); while (it.next()) |field_index| { const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!field_ty.hasRuntimeBits(zcu)) { // This is a zero-bit field - we only needed it for the alignment. continue; } @@ -1001,20 +990,24 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { else => unreachable, }, .un => |un| { + assert(ty.containerLayout(zcu) != .@"packed"); // packed unions use `bitpack` if (un.tag == .none) { - assert(ty.containerLayout(zcu) == .@"packed"); // TODO - const int_ty = try pt.intType(.unsigned, @intCast(ty.bitSize(zcu))); - return try cg.constInt(int_ty, Value.toUnsignedInt(.fromInterned(un.val), zcu)); + @panic("TODO"); } const active_field = ty.unionTagFieldIndex(.fromInterned(un.tag), zcu).?; const union_obj = zcu.typeToUnion(ty).?; const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[active_field]); - const payload = if (field_ty.hasRuntimeBitsIgnoreComptime(zcu)) + const payload = if (field_ty.hasRuntimeBits(zcu)) try cg.constant(field_ty, .fromInterned(un.val), .direct) else null; return try cg.unionInit(ty, active_field, payload); }, + .bitpack => |bitpack| { + const int_val: Value = .fromInterned(bitpack.backing_int_val); + break :cache try cg.constant(int_val.typeOf(zcu), int_val, repr); + }, + .memoized_call => unreachable, } }; @@ -1255,17 +1248,16 @@ fn resolveTypeName(cg: *CodeGen, ty: Type) ![]const u8 { fn resolveUnionType(cg: *CodeGen, ty: Type) !Id { const gpa = cg.module.gpa; const zcu = cg.module.zcu; - const ip = &zcu.intern_pool; const union_obj = zcu.typeToUnion(ty).?; - if (union_obj.flagsUnordered(ip).layout == .@"packed") { + if (union_obj.layout == .@"packed") { return try cg.module.intType(.unsigned, @intCast(ty.bitSize(zcu))); } const layout = cg.unionLayout(ty); if (!layout.has_payload) { // No payload, so represent this as just the tag type. - return try cg.resolveType(.fromInterned(union_obj.enum_tag_ty), .indirect); + return try cg.resolveType(.fromInterned(union_obj.enum_tag_type), .indirect); } var member_types: [4]Id = undefined; @@ -1274,7 +1266,7 @@ fn resolveUnionType(cg: *CodeGen, ty: Type) !Id { const u8_ty_id = try cg.resolveType(.u8, .direct); if (layout.tag_size != 0) { - const tag_ty_id = try cg.resolveType(.fromInterned(union_obj.enum_tag_ty), .indirect); + const tag_ty_id = try cg.resolveType(.fromInterned(union_obj.enum_tag_type), .indirect); member_types[layout.tag_index] = tag_ty_id; member_names[layout.tag_index] = "(tag)"; } @@ -1315,7 +1307,7 @@ fn resolveUnionType(cg: *CodeGen, ty: Type) !Id { fn resolveFnReturnType(cg: *CodeGen, ret_ty: Type) !Id { const zcu = cg.module.zcu; - if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!ret_ty.hasRuntimeBits(zcu)) { // If the return type is an error set or an error union, then we make this // anyerror return type instead, so that it can be coerced into a function // pointer type which has anyerror as the return type. @@ -1389,7 +1381,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { return cg.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel(zcu)}); }; - if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!elem_ty.hasRuntimeBits(zcu)) { assert(repr == .indirect); if (target.os.tag != .opencl) return cg.fail("cannot generate opaque type", .{}); return try cg.module.opaqueType("zero-sized-array"); @@ -1453,7 +1445,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { var param_index: usize = 0; for (fn_info.param_types.get(ip)) |param_ty_index| { const param_ty: Type = .fromInterned(param_ty_index); - if (!param_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!param_ty.hasRuntimeBits(zcu)) continue; param_ty_ids[param_index] = try cg.resolveType(param_ty, .direct); param_index += 1; @@ -1518,7 +1510,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { }; if (struct_type.layout == .@"packed") { - return try cg.resolveType(.fromInterned(struct_type.backingIntTypeUnordered(ip)), .direct); + return try cg.resolveType(.fromInterned(struct_type.packed_backing_int_type), .direct); } var member_types = std.array_list.Managed(Id).init(gpa); @@ -1533,9 +1525,9 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { var it = struct_type.iterateRuntimeOrder(ip); while (it.next()) |field_index| { const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; - const field_name = struct_type.fieldName(ip, field_index); + const field_name = struct_type.field_names.get(ip)[field_index]; try member_types.append(try cg.resolveType(field_ty, .indirect)); try member_names.append(field_name.toSlice(ip)); try member_offsets.append(@intCast(ty.structFieldOffset(field_index, zcu))); @@ -1556,7 +1548,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { }, .optional => { const payload_ty = ty.optionalChild(zcu); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { // Just use a bool. // Note: Always generate the bool with indirect format, to save on some sanity // Perform the conversion to a direct bool when the field is extracted. @@ -1653,7 +1645,7 @@ fn errorUnionLayout(cg: *CodeGen, payload_ty: Type) ErrorUnionLayout { const error_first = error_align.compare(.gt, payload_align); return .{ - .payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(zcu), + .payload_has_bits = payload_ty.hasRuntimeBits(zcu), .error_first = error_first, }; } @@ -3724,7 +3716,6 @@ fn cmp( const gpa = cg.module.gpa; const pt = cg.pt; const zcu = cg.module.zcu; - const ip = &zcu.intern_pool; const scalar_ty = lhs.ty.scalarType(zcu); const is_vector = lhs.ty.isVector(zcu); @@ -3737,7 +3728,7 @@ fn cmp( }, .@"struct" => { const struct_ty = zcu.typeToPackedStruct(scalar_ty).?; - const ty: Type = .fromInterned(struct_ty.backingIntTypeUnordered(ip)); + const ty: Type = .fromInterned(struct_ty.packed_backing_int_type); return try cg.cmp(op, lhs.pun(ty), rhs.pun(ty)); }, .error_set => { @@ -3778,7 +3769,7 @@ fn cmp( const payload_ty = ty.optionalChild(zcu); if (ty.optionalReprIsPayload(zcu)) { - assert(payload_ty.hasRuntimeBitsIgnoreComptime(zcu)); + assert(payload_ty.hasRuntimeBits(zcu)); assert(!payload_ty.isSlice(zcu)); return try cg.cmp(op, lhs.pun(payload_ty), rhs.pun(payload_ty)); @@ -3787,12 +3778,12 @@ fn cmp( const lhs_id = try lhs.materialize(cg); const rhs_id = try rhs.materialize(cg); - const lhs_valid_id = if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) + const lhs_valid_id = if (payload_ty.hasRuntimeBits(zcu)) try cg.extractField(.bool, lhs_id, 1) else try cg.convertToDirect(.bool, lhs_id); - const rhs_valid_id = if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) + const rhs_valid_id = if (payload_ty.hasRuntimeBits(zcu)) try cg.extractField(.bool, rhs_id, 1) else try cg.convertToDirect(.bool, rhs_id); @@ -3800,7 +3791,7 @@ fn cmp( const lhs_valid: Temporary = .init(.bool, lhs_valid_id); const rhs_valid: Temporary = .init(.bool, rhs_valid_id); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { return try cg.cmp(op, lhs_valid, rhs_valid); } @@ -4138,7 +4129,7 @@ fn airArrayToSlice(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const array_ptr_id = try cg.resolve(ty_op.operand); const len_id = try cg.constInt(.usize, array_ty.arrayLen(zcu)); - const elem_ptr_id = if (!array_ty.hasRuntimeBitsIgnoreComptime(zcu)) + const elem_ptr_id = if (!array_ty.hasRuntimeBits(zcu)) // Note: The pointer is something like *opaque{}, so we need to bitcast it to the element type. try cg.bitCast(elem_ptr_ty, array_ptr_ty, array_ptr_id) else @@ -4174,12 +4165,12 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) !?Id { .@"struct" => { if (zcu.typeToPackedStruct(result_ty)) |struct_type| { comptime assert(Type.packed_struct_layout_version == 2); - const backing_int_ty: Type = .fromInterned(struct_type.backingIntTypeUnordered(ip)); + const backing_int_ty: Type = .fromInterned(struct_type.packed_backing_int_type); var running_int_id = try cg.constInt(backing_int_ty, 0); var running_bits: u16 = 0; for (struct_type.field_types.get(ip), elements) |field_ty_ip, element| { const field_ty: Type = .fromInterned(field_ty_ip); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; const field_id = try cg.resolve(element); const ty_bit_size: u16 = @intCast(field_ty.bitSize(zcu)); const field_int_ty = try cg.pt.intType(.unsigned, ty_bit_size); @@ -4239,7 +4230,7 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const field_index = it.next().?; if ((try result_ty.structFieldValueComptime(pt, i)) != null) continue; const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); - assert(field_ty.hasRuntimeBitsIgnoreComptime(zcu)); + assert(field_ty.hasRuntimeBits(zcu)); const id = try cg.resolve(element); types[index] = field_ty; @@ -4399,10 +4390,7 @@ fn airPtrElemPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const elem_ty = src_ptr_ty.childType(zcu); const ptr_id = try cg.resolve(bin_op.lhs); - if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - const dst_ptr_ty = cg.typeOfIndex(inst); - return try cg.bitCast(dst_ptr_ty, src_ptr_ty, ptr_id); - } + assert(elem_ty.hasRuntimeBits(zcu)); const index_id = try cg.resolve(bin_op.rhs); return try cg.ptrElemPtr(src_ptr_ty, ptr_id, index_id); @@ -4526,13 +4514,13 @@ fn unionInit( const zcu = cg.module.zcu; const ip = &zcu.intern_pool; const union_ty = zcu.typeToUnion(ty).?; - const tag_ty: Type = .fromInterned(union_ty.enum_tag_ty); + const tag_ty: Type = .fromInterned(union_ty.enum_tag_type); const layout = cg.unionLayout(ty); const payload_ty: Type = .fromInterned(union_ty.field_types.get(ip)[active_field]); - if (union_ty.flagsUnordered(ip).layout == .@"packed") { - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (union_ty.layout == .@"packed") { + if (!payload_ty.hasRuntimeBits(zcu)) { const int_ty = try pt.intType(.unsigned, @intCast(ty.bitSize(zcu))); return cg.constInt(int_ty, 0); } @@ -4558,7 +4546,7 @@ fn unionInit( const tag_int = if (layout.tag_size != 0) blk: { const tag_val = try pt.enumValueFieldIndex(tag_ty, active_field); - const tag_int_val = try tag_val.intFromEnum(tag_ty, pt); + const tag_int_val = tag_val.intFromEnum(zcu); break :blk tag_int_val.toUnsignedInt(zcu); } else 0; @@ -4577,7 +4565,7 @@ fn unionInit( try cg.store(tag_ty, ptr_id, tag_id, .{}); } - if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (payload_ty.hasRuntimeBits(zcu)) { const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect); const pl_ptr_ty_id = try cg.module.ptrType(layout_payload_ty_id, .function); const pl_ptr_id = try cg.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index}); @@ -4613,7 +4601,7 @@ fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const union_obj = zcu.typeToUnion(ty).?; const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[extra.field_index]); - const payload = if (field_ty.hasRuntimeBitsIgnoreComptime(zcu)) + const payload = if (field_ty.hasRuntimeBits(zcu)) try cg.resolve(extra.init) else null; @@ -4631,7 +4619,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const field_index = struct_field.field_index; const field_ty = object_ty.fieldType(field_index, zcu); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) return null; + assert(field_ty.hasRuntimeBits(zcu)); switch (object_ty.zigTypeTag(zcu)) { .@"struct" => switch (object_ty.containerLayout(zcu)) { @@ -5332,7 +5320,7 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) !void { const zcu = cg.module.zcu; const operand = cg.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const ret_ty = cg.typeOf(operand); - if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!ret_ty.hasRuntimeBits(zcu)) { const fn_info = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?; if (Type.fromInterned(fn_info.return_type).isError(zcu)) { // Functions with an empty error set are emitted with an error code @@ -5356,7 +5344,7 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) !void { const ptr_ty = cg.typeOf(un_op); const ret_ty = ptr_ty.childType(zcu); - if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!ret_ty.hasRuntimeBits(zcu)) { const fn_info = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?; if (Type.fromInterned(fn_info.return_type).isError(zcu)) { // Functions with an empty error set are emitted with an error code @@ -5573,7 +5561,7 @@ fn airIsNull(cg: *CodeGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { const is_non_null_id = blk: { if (is_pointer) { - if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (payload_ty.hasRuntimeBits(zcu)) { const storage_class = cg.module.storageClass(operand_ty.ptrAddressSpace(zcu)); const bool_indirect_ty_id = try cg.resolveType(.bool, .indirect); const bool_ptr_ty_id = try cg.module.ptrType(bool_indirect_ty_id, storage_class); @@ -5584,7 +5572,7 @@ fn airIsNull(cg: *CodeGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { break :blk try cg.load(.bool, operand_id, .{}); } - break :blk if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) + break :blk if (payload_ty.hasRuntimeBits(zcu)) try cg.extractField(.bool, operand_id, 1) else // Optional representation is bool indicating whether the optional is set @@ -5653,7 +5641,7 @@ fn airUnwrapOptional(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const optional_ty = cg.typeOf(ty_op.operand); const payload_ty = cg.typeOfIndex(inst); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return null; + if (!payload_ty.hasRuntimeBits(zcu)) return null; if (optional_ty.optionalReprIsPayload(zcu)) { return operand_id; @@ -5672,7 +5660,7 @@ fn airUnwrapOptionalPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const result_ty = cg.typeOfIndex(inst); const result_ty_id = try cg.resolveType(result_ty, .direct); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { // There is no payload, but we still need to return a valid pointer. // We can just return anything here, so just return a pointer to the operand. return try cg.bitCast(result_ty, operand_ty, operand_id); @@ -5691,9 +5679,7 @@ fn airWrapOptional(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const payload_ty = cg.typeOf(ty_op.operand); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - return try cg.constBool(true, .indirect); - } + assert(payload_ty.hasRuntimeBits(zcu)); const operand_id = try cg.resolve(ty_op.operand); @@ -5789,8 +5775,7 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void { const int_val: u64 = switch (cond_ty.zigTypeTag(zcu)) { .bool, .int => if (cond_ty.isSignedInt(zcu)) @bitCast(value.toSignedInt(zcu)) else value.toUnsignedInt(zcu), .@"enum" => blk: { - // TODO: figure out of cond_ty is correct (something with enum literals) - break :blk (try value.intFromEnum(cond_ty, pt)).toUnsignedInt(zcu); // TODO: composite integer constants + break :blk value.intFromEnum(zcu).toUnsignedInt(zcu); // TODO: composite integer constants }, .error_set => value.getErrorInt(zcu), .pointer => value.toUnsignedInt(zcu), @@ -6067,7 +6052,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie // before starting to emit OpFunctionCall instructions. Hence the // temporary params buffer. const arg_ty = cg.typeOf(arg); - if (!arg_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!arg_ty.hasRuntimeBits(zcu)) continue; const arg_id = try cg.resolve(arg); params[n_params] = arg_id; @@ -6081,7 +6066,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie .id_ref_3 = params[0..n_params], }); - if (cg.liveness.isUnused(inst) or !Type.fromInterned(return_type).hasRuntimeBitsIgnoreComptime(zcu)) { + if (cg.liveness.isUnused(inst) or !Type.fromInterned(return_type).hasRuntimeBits(zcu)) { return null; } diff --git a/src/codegen/wasm/CodeGen.zig b/src/codegen/wasm/CodeGen.zig index 6b5cd3c1c556aaf63343a2fe33e4966f96203a01..a8f374772e3e042f0bd32a3eb29c5cd39141092d 100644 --- a/src/codegen/wasm/CodeGen.zig +++ b/src/codegen/wasm/CodeGen.zig @@ -759,7 +759,7 @@ fn resolveInst(cg: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue { const zcu = pt.zcu; const val = (try cg.air.value(ref, pt)).?; const ty = cg.typeOf(ref); - if (!ty.hasRuntimeBitsIgnoreComptime(zcu) and !ty.isInt(zcu) and !ty.isError(zcu)) { + if (!ty.hasRuntimeBits(zcu) and !ty.isInt(zcu) and !ty.isError(zcu)) { gop.value_ptr.* = .none; return .none; } @@ -773,7 +773,7 @@ fn resolveInst(cg: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue { const result: WValue = if (isByRef(ty, zcu, cg.target)) .{ .uav_ref = .{ .ip_index = val.toIntern() } } else - try cg.lowerConstant(val, ty); + try cg.lowerConstant(val); gop.value_ptr.* = result; return result; @@ -786,7 +786,7 @@ fn resolveValue(cg: *CodeGen, val: Value) InnerError!WValue { return if (isByRef(ty, zcu, cg.target)) .{ .uav_ref = .{ .ip_index = val.toIntern() } } else - try cg.lowerConstant(val, ty); + try cg.lowerConstant(val); } /// NOTE: if result == .stack, it will be stored in .local @@ -980,7 +980,6 @@ fn addExtraAssumeCapacity(cg: *CodeGen, extra: anytype) error{OutOfMemory}!u32 { /// For `std.builtin.CallingConvention.auto`. pub fn typeToValtype(ty: Type, zcu: *const Zcu, target: *const std.Target) std.wasm.Valtype { - const ip = &zcu.intern_pool; return switch (ty.zigTypeTag(zcu)) { .float => switch (ty.floatBits(target)) { 16 => .i32, // stored/loaded as u16 @@ -994,25 +993,13 @@ pub fn typeToValtype(ty: Type, zcu: *const Zcu, target: *const std.Target) std.w 33...64 => .i64, else => .i32, }, - .@"struct" => blk: { - if (zcu.typeToPackedStruct(ty)) |packed_struct| { - const backing_int_ty = Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)); - break :blk typeToValtype(backing_int_ty, zcu, target); - } else { - break :blk .i32; - } - }, .vector => switch (CodeGen.determineSimdStoreStrategy(ty, zcu, target)) { .direct => .v128, .unrolled => .i32, }, - .@"union" => switch (ty.containerLayout(zcu)) { - .@"packed" => switch (ty.bitSize(zcu)) { - 0...32 => .i32, - 33...64 => .i64, - else => .i32, - }, - else => .i32, + .@"union", .@"struct" => switch (ty.containerLayout(zcu)) { + .@"packed" => typeToValtype(ty.bitpackBackingInt(zcu), zcu, target), + .auto, .@"extern" => .i32, }, else => .i32, // all represented as reference/immediate }; @@ -1185,7 +1172,7 @@ pub fn generate( const fn_ty = zcu.navValue(cg.owner_nav).typeOf(zcu); const fn_info = zcu.typeToFunc(fn_ty).?; const ret_ty: Type = .fromInterned(fn_info.return_type); - const any_returns = !firstParamSRet(fn_info.cc, ret_ty, zcu, target) and ret_ty.hasRuntimeBitsIgnoreComptime(zcu); + const any_returns = !firstParamSRet(fn_info.cc, ret_ty, zcu, target) and ret_ty.hasRuntimeBits(zcu); var cc_result = try resolveCallingConventionValues(zcu, fn_ty, target); defer cc_result.deinit(gpa); @@ -1244,7 +1231,7 @@ fn generateInner(cg: *CodeGen, any_returns: bool) InnerError!Mir { if (any_returns and cg.air.instructions.len > 0) { const inst: Air.Inst.Index = @enumFromInt(cg.air.instructions.len - 1); const last_inst_ty = cg.typeOfIndex(inst); - if (!last_inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!last_inst_ty.hasRuntimeBits(zcu)) { try cg.addTag(.@"unreachable"); } } @@ -1316,7 +1303,7 @@ fn resolveCallingConventionValues( switch (cc) { .auto => { for (fn_info.param_types.get(ip)) |ty| { - if (!Type.fromInterned(ty).hasRuntimeBitsIgnoreComptime(zcu)) { + if (!Type.fromInterned(ty).hasRuntimeBits(zcu)) { continue; } @@ -1326,7 +1313,7 @@ fn resolveCallingConventionValues( }, .wasm_mvp => { for (fn_info.param_types.get(ip)) |ty| { - if (!Type.fromInterned(ty).hasRuntimeBitsIgnoreComptime(zcu)) { + if (!Type.fromInterned(ty).hasRuntimeBits(zcu)) { continue; } switch (abi.classifyType(.fromInterned(ty), zcu)) { @@ -1357,7 +1344,7 @@ pub fn firstParamSRet( zcu: *const Zcu, target: *const std.Target, ) bool { - if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) return false; + if (!return_type.hasRuntimeBits(zcu)) return false; switch (cc) { .@"inline" => unreachable, .auto => return isByRef(return_type, zcu, target), @@ -1457,7 +1444,7 @@ fn restoreStackPointer(cg: *CodeGen) !void { fn allocStack(cg: *CodeGen, ty: Type) !WValue { const pt = cg.pt; const zcu = pt.zcu; - assert(ty.hasRuntimeBitsIgnoreComptime(zcu)); + assert(ty.hasRuntimeBits(zcu)); if (cg.initial_stack_value == .none) { try cg.initializeStack(); } @@ -1491,7 +1478,7 @@ fn allocStackPtr(cg: *CodeGen, inst: Air.Inst.Index) !WValue { try cg.initializeStack(); } - if (!pointee_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!pointee_ty.hasRuntimeBits(zcu)) { return cg.allocStack(Type.usize); // create a value containing just the stack pointer. } @@ -1676,7 +1663,6 @@ fn ptrSize(cg: *const CodeGen) u16 { /// For a given `Type`, will return true when the type will be passed /// by reference, rather than by value fn isByRef(ty: Type, zcu: *const Zcu, target: *const std.Target) bool { - const ip = &zcu.intern_pool; switch (ty.zigTypeTag(zcu)) { .type, .comptime_int, @@ -1697,20 +1683,10 @@ fn isByRef(ty: Type, zcu: *const Zcu, target: *const std.Target) bool { .array, .frame, - => return ty.hasRuntimeBitsIgnoreComptime(zcu), - .@"union" => { - if (zcu.typeToUnion(ty)) |union_obj| { - if (union_obj.flagsUnordered(ip).layout == .@"packed") { - return ty.abiSize(zcu) > 8; - } - } - return ty.hasRuntimeBitsIgnoreComptime(zcu); - }, - .@"struct" => { - if (zcu.typeToPackedStruct(ty)) |packed_struct| { - return isByRef(Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)), zcu, target); - } - return ty.hasRuntimeBitsIgnoreComptime(zcu); + => return ty.hasRuntimeBits(zcu), + .@"struct", .@"union" => switch (ty.containerLayout(zcu)) { + .@"packed" => return isByRef(ty.bitpackBackingInt(zcu), zcu, target), + .@"extern", .auto => return ty.hasRuntimeBits(zcu), }, .vector => return determineSimdStoreStrategy(ty, zcu, target) == .unrolled, .int => return ty.intInfo(zcu).bits > 64, @@ -1718,7 +1694,7 @@ fn isByRef(ty: Type, zcu: *const Zcu, target: *const std.Target) bool { .float => return ty.floatBits(target) > 64, .error_union => { const pl_ty = ty.errorUnionPayload(zcu); - if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!pl_ty.hasRuntimeBits(zcu)) { return false; } return true; @@ -1727,7 +1703,7 @@ fn isByRef(ty: Type, zcu: *const Zcu, target: *const std.Target) bool { if (ty.isPtrLikeOptional(zcu)) return false; const pl_type = ty.optionalChild(zcu); if (pl_type.zigTypeTag(zcu) == .error_set) return false; - return pl_type.hasRuntimeBitsIgnoreComptime(zcu); + return pl_type.hasRuntimeBits(zcu); }, .pointer => { // Slices act like struct and will be passed by reference @@ -2069,7 +2045,7 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { // to the stack instead if (cg.return_value != .none) { try cg.store(cg.return_value, operand, ret_ty, 0); - } else if (fn_info.cc == .wasm_mvp and ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + } else if (fn_info.cc == .wasm_mvp and ret_ty.hasRuntimeBits(zcu)) { switch (abi.classifyType(ret_ty, zcu)) { .direct => |scalar_type| { assert(!abi.lowerAsDoubleI64(scalar_type, zcu)); @@ -2082,7 +2058,7 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { .indirect => unreachable, } } else { - if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu) and ret_ty.isError(zcu)) { + if (!ret_ty.hasRuntimeBits(zcu) and ret_ty.isError(zcu)) { try cg.addImm32(0); } else { try cg.emitWValue(operand); @@ -2121,7 +2097,7 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const ret_ty = cg.typeOf(un_op).childType(zcu); const fn_info = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?; - if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!ret_ty.hasRuntimeBits(zcu)) { if (ret_ty.isError(zcu)) { try cg.addImm32(0); } @@ -2177,7 +2153,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie const arg_val = try cg.resolveInst(arg); const arg_ty = cg.typeOf(arg); - if (!arg_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!arg_ty.hasRuntimeBits(zcu)) continue; try cg.lowerArg(zcu.typeToFunc(fn_ty).?.cc, arg_ty, arg_val); } @@ -2199,7 +2175,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie } const result_value = result_value: { - if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu) and !ret_ty.isError(zcu)) { + if (!ret_ty.hasRuntimeBits(zcu) and !ret_ty.isError(zcu)) { break :result_value .none; } else if (first_param_sret) { break :result_value sret; @@ -2320,12 +2296,12 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr const zcu = pt.zcu; const abi_size = ty.abiSize(zcu); - if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) return; + if (!ty.hasRuntimeBits(zcu)) return; switch (ty.zigTypeTag(zcu)) { .error_union => { const pl_ty = ty.errorUnionPayload(zcu); - if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!pl_ty.hasRuntimeBits(zcu)) { return cg.store(lhs, rhs, Type.anyerror, offset); } @@ -2338,7 +2314,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr return cg.store(lhs, rhs, Type.usize, offset); } const pl_ty = ty.optionalChild(zcu); - if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!pl_ty.hasRuntimeBits(zcu)) { return cg.store(lhs, rhs, Type.u8, offset); } if (pl_ty.zigTypeTag(zcu) == .error_set) { @@ -2438,7 +2414,7 @@ fn airLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const ptr_ty = cg.typeOf(ty_op.operand); const ptr_info = ptr_ty.ptrInfo(zcu); - if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) return cg.finishAir(inst, .none, &.{ty_op.operand}); + if (!ty.hasRuntimeBits(zcu)) return cg.finishAir(inst, .none, &.{ty_op.operand}); const result = result: { if (isByRef(ty, zcu, cg.target)) { @@ -3089,7 +3065,7 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro return switch (ptr.base_addr) { .nav => |nav| return .{ .nav_ref = .{ .nav_index = nav, .offset = @intCast(offset) } }, .uav => |uav| return .{ .uav_ref = .{ .ip_index = uav.val, .offset = @intCast(offset), .orig_ptr_ty = uav.orig_ty } }, - .int => return cg.lowerConstant(try pt.intValue(Type.usize, offset), Type.usize), + .int => return cg.lowerConstant(try pt.intValue(.usize, offset)), .eu_payload => |eu_ptr| try cg.lowerPtr( eu_ptr, offset + codegen.errUnionPayloadOffset( @@ -3126,10 +3102,11 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro }; } -/// Asserts that `isByRef` returns `false` for `ty`. -fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { +/// Asserts that `isByRef` returns `false` for `val.typeOf(zcu)`. +fn lowerConstant(cg: *CodeGen, val: Value) InnerError!WValue { const pt = cg.pt; const zcu = pt.zcu; + const ty = val.typeOf(zcu); assert(!isByRef(ty, zcu, cg.target)); const ip = &zcu.intern_pool; if (val.isUndef(zcu)) return cg.emitUndefined(ty); @@ -3191,31 +3168,22 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { }, .error_union => |error_union| { const err_int_ty = try pt.errorIntType(); - const err_ty, const err_val = switch (error_union.val) { - .err_name => |err_name| .{ - ty.errorUnionSet(zcu), - Value.fromInterned(try pt.intern(.{ .err = .{ - .ty = ty.errorUnionSet(zcu).toIntern(), - .name = err_name, - } })), - }, - .payload => .{ - err_int_ty, - try pt.intValue(err_int_ty, 0), - }, + const err_val: Value = switch (error_union.val) { + .err_name => |err_name| .fromInterned(try pt.intern(.{ .err = .{ + .ty = ty.errorUnionSet(zcu).toIntern(), + .name = err_name, + } })), + .payload => try pt.intValue(err_int_ty, 0), }; const payload_type = ty.errorUnionPayload(zcu); - if (!payload_type.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_type.hasRuntimeBits(zcu)) { // We use the error type directly as the type. - return cg.lowerConstant(err_val, err_ty); + return cg.lowerConstant(err_val); } return cg.fail("Wasm TODO: lowerConstant error union with non-zero-bit payload type", .{}); }, - .enum_tag => |enum_tag| { - const int_tag_ty = ip.typeOf(enum_tag.int); - return cg.lowerConstant(Value.fromInterned(enum_tag.int), Type.fromInterned(int_tag_ty)); - }, + .enum_tag => |enum_tag| return cg.lowerConstant(.fromInterned(enum_tag.int)), .float => |float| switch (float.storage) { .f16 => |f16_val| return .{ .imm32 = @as(u16, @bitCast(f16_val)) }, .f32 => |f32_val| return .{ .float32 = f32_val }, @@ -3225,9 +3193,8 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { .slice => unreachable, // isByRef == true .ptr => return cg.lowerPtr(val.toIntern(), 0), .opt => if (ty.optionalReprIsPayload(zcu)) { - const pl_ty = ty.optionalChild(zcu); if (val.optionalValue(zcu)) |payload| { - return cg.lowerConstant(payload, pl_ty); + return cg.lowerConstant(payload); } else { return .{ .imm32 = 0 }; } @@ -3242,33 +3209,11 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { val.writeToMemory(pt, &buf) catch unreachable; return cg.storeSimdImmd(buf); }, - .struct_type => { - const struct_type = ip.loadStructType(ty.toIntern()); - // non-packed structs are not handled in this function because they - // are by-ref types. - assert(struct_type.layout == .@"packed"); - var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer - val.writeToPackedMemory(pt, &buf, 0) catch unreachable; - const backing_int_ty = Type.fromInterned(struct_type.backingIntTypeUnordered(ip)); - const int_val = try pt.intValue( - backing_int_ty, - mem.readInt(u64, &buf, .little), - ); - return cg.lowerConstant(int_val, backing_int_ty); - }, + .struct_type => unreachable, // packed structs use `bitpack` else => unreachable, }, - .un => { - const int_type = try pt.intType(.unsigned, @intCast(ty.bitSize(zcu))); - - var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer - val.writeToPackedMemory(pt, &buf, 0) catch unreachable; - const int_val = try pt.intValue( - int_type, - mem.readInt(u64, &buf, .little), - ); - return cg.lowerConstant(int_val, int_type); - }, + .un => unreachable, // packed unions use `bitpack` + .bitpack => |bitpack| return cg.lowerConstant(.fromInterned(bitpack.backing_int_val)), .memoized_call => unreachable, } } @@ -3283,7 +3228,6 @@ fn storeSimdImmd(cg: *CodeGen, value: [16]u8) !WValue { fn emitUndefined(cg: *CodeGen, ty: Type) InnerError!WValue { const zcu = cg.pt.zcu; - const ip = &zcu.intern_pool; switch (ty.zigTypeTag(zcu)) { .bool, .error_set => return .{ .imm32 = 0xaaaaaaaa }, .int, .@"enum" => switch (ty.intInfo(zcu).bits) { @@ -3311,17 +3255,9 @@ fn emitUndefined(cg: *CodeGen, ty: Type) InnerError!WValue { .error_union => { return .{ .imm32 = 0xaaaaaaaa }; }, - .@"struct" => { - const packed_struct = zcu.typeToPackedStruct(ty).?; - return cg.emitUndefined(Type.fromInterned(packed_struct.backingIntTypeUnordered(ip))); - }, - .@"union" => switch (ty.containerLayout(zcu)) { - .@"packed" => switch (ty.bitSize(zcu)) { - 0...32 => return .{ .imm32 = 0xaaaaaaaa }, - 33...64 => return .{ .imm64 = 0xaaaaaaaaaaaaaaaa }, - else => unreachable, - }, - else => unreachable, + .@"struct", .@"union" => { + const backing_int_ty = ty.bitpackBackingInt(zcu); + return cg.emitUndefined(backing_int_ty); }, else => return cg.fail("Wasm TODO: emitUndefined for type: {t}\n", .{ty.zigTypeTag(zcu)}), } @@ -3335,7 +3271,7 @@ fn airBlock(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, block_ty: Type, body: []const Air.Inst.Index) InnerError!void { const zcu = cg.pt.zcu; // if wasm_block_ty is non-empty, we create a register to store the temporary value - const block_result: WValue = if (block_ty.hasRuntimeBitsIgnoreComptime(zcu)) + const block_result: WValue = if (block_ty.hasRuntimeBits(zcu)) try cg.allocLocal(block_ty) else .none; @@ -3449,7 +3385,7 @@ fn cmp(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareOpe const zcu = cg.pt.zcu; if (ty.zigTypeTag(zcu) == .optional and !ty.optionalReprIsPayload(zcu)) { const payload_ty = ty.optionalChild(zcu); - if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (payload_ty.hasRuntimeBits(zcu)) { // When we hit this case, we must check the value of optionals // that are not pointers. This means first checking against non-null for // both lhs and rhs, as well as checking the payload are matching of lhs and rhs @@ -3792,7 +3728,6 @@ fn structFieldPtr( fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const pt = cg.pt; const zcu = pt.zcu; - const ip = &zcu.intern_pool; const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const struct_field = cg.air.extraData(Air.StructField, ty_pl.payload).data; @@ -3800,14 +3735,14 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const operand = try cg.resolveInst(struct_field.struct_operand); const field_index = struct_field.field_index; const field_ty = struct_ty.fieldType(field_index, zcu); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) return cg.finishAir(inst, .none, &.{struct_field.struct_operand}); + if (!field_ty.hasRuntimeBits(zcu)) return cg.finishAir(inst, .none, &.{struct_field.struct_operand}); const result: WValue = switch (struct_ty.containerLayout(zcu)) { .@"packed" => switch (struct_ty.zigTypeTag(zcu)) { .@"struct" => result: { const packed_struct = zcu.typeToPackedStruct(struct_ty).?; const offset = zcu.structPackedFieldBitOffset(packed_struct, field_index); - const backing_ty = Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)); + const backing_ty = Type.fromInterned(packed_struct.packed_backing_int_type); const host_bits = backing_ty.intInfo(zcu).bits; const const_wvalue: WValue = if (33 <= host_bits and host_bits <= 64) @@ -3885,7 +3820,7 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Inner const switch_br = cg.air.unwrapSwitch(inst); const target_ty = cg.typeOf(switch_br.operand); - assert(target_ty.hasRuntimeBitsIgnoreComptime(zcu)); + assert(target_ty.hasRuntimeBits(zcu)); // swap target value with placeholder local, for dispatching const target = if (is_dispatch_loop) target: { @@ -4119,7 +4054,7 @@ fn airIsErr(cg: *CodeGen, inst: Air.Inst.Index, opcode: std.wasm.Opcode, op_kind } try cg.emitWValue(operand); - if (op_kind == .ptr or pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (op_kind == .ptr or pl_ty.hasRuntimeBits(zcu)) { try cg.addMemArg(.i32_load16_u, .{ .offset = operand.offset() + @as(u32, @intCast(errUnionErrorOffset(pl_ty, zcu))), .alignment = @intCast(Type.anyerror.abiAlignment(zcu).toByteUnits().?), @@ -4146,7 +4081,7 @@ fn airUnwrapErrUnionPayload(cg: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) const payload_ty = eu_ty.errorUnionPayload(zcu); const result: WValue = result: { - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { if (op_is_ptr) { break :result cg.reuseOperand(ty_op.operand, operand); } else { @@ -4166,7 +4101,7 @@ fn airUnwrapErrUnionPayload(cg: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) } /// E!T -> E op_is_ptr == false -/// *(E!T) -> E op_is_prt == true +/// *(E!T) -> E op_is_ptr == true /// NOTE: op_is_ptr will not change return type fn airUnwrapErrUnionError(cg: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!void { const zcu = cg.pt.zcu; @@ -4186,7 +4121,7 @@ fn airUnwrapErrUnionError(cg: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) I if (op_is_ptr or isByRef(eu_ty, zcu, cg.target)) { break :result try cg.load(operand, Type.anyerror, err_offset); } else { - assert(!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)); + assert(!payload_ty.hasRuntimeBits(zcu)); break :result cg.reuseOperand(ty_op.operand, operand); } }; @@ -4202,7 +4137,7 @@ fn airWrapErrUnionPayload(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const pl_ty = cg.typeOf(ty_op.operand); const result = result: { - if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!pl_ty.hasRuntimeBits(zcu)) { break :result cg.reuseOperand(ty_op.operand, operand); } @@ -4232,7 +4167,7 @@ fn airWrapErrUnionErr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const pl_ty = err_ty.errorUnionPayload(zcu); const result = result: { - if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!pl_ty.hasRuntimeBits(zcu)) { break :result cg.reuseOperand(ty_op.operand, operand); } @@ -4348,7 +4283,7 @@ fn isNull(cg: *CodeGen, operand: WValue, optional_ty: Type, opcode: std.wasm.Opc if (!optional_ty.optionalReprIsPayload(zcu)) { // When payload is zero-bits, we can treat operand as a value, rather than // a pointer to the stack value - if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (payload_ty.hasRuntimeBits(zcu)) { const offset = std.math.cast(u32, payload_ty.abiSize(zcu)) orelse { return cg.fail("Optional type {f} too big to fit into stack frame", .{optional_ty.fmt(pt)}); }; @@ -4373,7 +4308,7 @@ fn airOptionalPayload(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const opt_ty = cg.typeOf(ty_op.operand); const payload_ty = cg.typeOfIndex(inst); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { return cg.finishAir(inst, .none, &.{ty_op.operand}); } @@ -4398,7 +4333,7 @@ fn airOptionalPayloadPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const result = result: { const payload_ty = opt_ty.optionalChild(zcu); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu) or opt_ty.optionalReprIsPayload(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu) or opt_ty.optionalReprIsPayload(zcu)) { break :result cg.reuseOperand(ty_op.operand, operand); } @@ -4438,7 +4373,7 @@ fn airWrapOptional(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const zcu = pt.zcu; const result = result: { - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { const non_null_bit = try cg.allocStack(Type.u1); try cg.emitWValue(non_null_bit); try cg.addImm32(1); @@ -4606,7 +4541,7 @@ fn airArrayToSlice(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const slice_local = try cg.allocStack(slice_ty); // store the array ptr in the slice - if (array_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (array_ty.hasRuntimeBits(zcu)) { try cg.store(slice_local, operand, Type.usize, 0); } @@ -5105,7 +5040,7 @@ fn airShuffleOne(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { try cg.emitWValue(dest_alloc); const elem_val = switch (mask_elem.unwrap()) { .elem => |idx| try cg.load(operand, elem_ty, @intCast(elem_size * idx)), - .value => |val| try cg.lowerConstant(.fromInterned(val), elem_ty), + .value => |val| try cg.lowerConstant(.fromInterned(val)), }; try cg.store(.stack, elem_val, elem_ty, @intCast(dest_alloc.offset() + elem_size * out_idx)); } @@ -5246,7 +5181,7 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { } const packed_struct = zcu.typeToPackedStruct(result_ty).?; const field_types = packed_struct.field_types; - const backing_type = Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)); + const backing_type = Type.fromInterned(packed_struct.packed_backing_int_type); // ensure the result is zero'd const result = try cg.allocLocal(backing_type); @@ -5259,7 +5194,7 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { var current_bit: u16 = 0; for (elements, 0..) |elem, elem_index| { const field_ty = Type.fromInterned(field_types.get(ip)[elem_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; const shift_val: WValue = if (backing_type.bitSize(zcu) <= 32) .{ .imm32 = current_bit } @@ -5332,13 +5267,13 @@ fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const layout = union_ty.unionGetLayout(zcu); const union_obj = zcu.typeToUnion(union_ty).?; const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]); - const field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index]; + const field_name = ip.loadEnumType(union_obj.enum_tag_type).field_names.get(ip)[extra.field_index]; const tag_int = blk: { - const tag_ty = union_ty.unionTagTypeRuntime(zcu).?; + const tag_ty = union_ty.unionTagTypeHypothetical(zcu); const enum_field_index = tag_ty.enumFieldIndex(field_name, zcu).?; const tag_val = try pt.enumValueFieldIndex(tag_ty, enum_field_index); - break :blk try cg.lowerConstant(tag_val, tag_ty); + break :blk try cg.lowerConstant(tag_val); }; if (layout.payload_size == 0) { if (layout.tag_size == 0) { @@ -5360,7 +5295,7 @@ fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { } if (layout.tag_size > 0) { - try cg.store(result_ptr, tag_int, Type.fromInterned(union_obj.enum_tag_ty), 0); + try cg.store(result_ptr, tag_int, .fromInterned(union_obj.enum_tag_type), 0); } } else { try cg.store(result_ptr, payload, field_ty, 0); @@ -5368,7 +5303,7 @@ fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { try cg.store( result_ptr, tag_int, - Type.fromInterned(union_obj.enum_tag_ty), + .fromInterned(union_obj.enum_tag_type), @intCast(layout.payload_size), ); } @@ -5415,7 +5350,7 @@ fn airWasmMemoryGrow(cg: *CodeGen, inst: Air.Inst.Index) !void { fn cmpOptionals(cg: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue { const zcu = cg.pt.zcu; - assert(operand_ty.hasRuntimeBitsIgnoreComptime(zcu)); + assert(operand_ty.hasRuntimeBits(zcu)); assert(op == .eq or op == .neq); const payload_ty = operand_ty.optionalChild(zcu); assert(!isByRef(payload_ty, zcu, cg.target)); @@ -5669,7 +5604,7 @@ fn airErrUnionPayloadPtrSet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void ); const result = result: { - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { break :result cg.reuseOperand(ty_op.operand, operand); } @@ -6458,7 +6393,7 @@ fn lowerTry( const zcu = cg.pt.zcu; const pl_ty = err_union_ty.errorUnionPayload(zcu); - const pl_has_bits = pl_ty.hasRuntimeBitsIgnoreComptime(zcu); + const pl_has_bits = pl_ty.hasRuntimeBits(zcu); if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) { // Block we can jump out of when error is not set @@ -7096,13 +7031,13 @@ fn callIntrinsic( // Lower all arguments to the stack before we call our function for (args, 0..) |arg, arg_i| { assert(!(want_sret_param and arg == .stack)); - assert(Type.fromInterned(param_types[arg_i]).hasRuntimeBitsIgnoreComptime(zcu)); + assert(Type.fromInterned(param_types[arg_i]).hasRuntimeBits(zcu)); try cg.lowerArg(.{ .wasm_mvp = .{} }, Type.fromInterned(param_types[arg_i]), arg); } try cg.addInst(.{ .tag = .call_intrinsic, .data = .{ .intrinsic = intrinsic } }); - if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!return_type.hasRuntimeBits(zcu)) { return .none; } else if (want_sret_param) { return sret; diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index 8f0f8019493d82a4eec9718e0f95344b48bf1d48..df9dc381ab025711c7086515e71af1c3303251ca 100644 --- a/src/link/MachO/Atom.zig +++ b/src/link/MachO/Atom.zig @@ -561,7 +561,7 @@ fn reportUndefSymbol(self: Atom, rel: Relocation, macho_file: *MachO) !bool { defer macho_file.undefs_mutex.unlock(io); const gop = try macho_file.undefs.getOrPut(gpa, file.getGlobals()[rel.target]); if (!gop.found_existing) { - gop.value_ptr.* = .{ .refs = .{} }; + gop.value_ptr.* = .{ .refs = .empty }; } try gop.value_ptr.refs.append(gpa, .{ .index = self.atom_index, .file = self.file }); return true; diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index b17dc099077f15af9be3f6913419b0a4507eb7d9..5d71e46eaaf90e3d3b34c2a81db173dddc1ccdb2 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -150,7 +150,7 @@ fn newAtom(self: *ZigObject, allocator: Allocator, name: MachO.String, macho_fil atom.name = name; const relocs_index = @as(u32, @intCast(self.relocs.items.len)); - self.relocs.addOneAssumeCapacity().* = .{}; + self.relocs.addOneAssumeCapacity().* = .empty; atom.addExtra(.{ .rel_index = relocs_index, .rel_count = 0 }, macho_file); return index; diff --git a/src/link/MachO/file.zig b/src/link/MachO/file.zig index cd687a4941b2e73915a7daafe31b8d996cee37a5..4f6f70debeef007b915bfeb07d5317b87fffabc2 100644 --- a/src/link/MachO/file.zig +++ b/src/link/MachO/file.zig @@ -258,7 +258,7 @@ pub const File = union(enum) { const gop = try macho_file.dupes.getOrPut(gpa, file.getGlobals()[i]); if (!gop.found_existing) { - gop.value_ptr.* = .{}; + gop.value_ptr.* = .empty; } try gop.value_ptr.append(gpa, file.getIndex()); } diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index a9e7f35c2118d313cdcd40d99a4dd6aa1141cea5..1975ad9ba9dc15477e3510377701e5666539bec6 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -4226,7 +4226,7 @@ fn convertZcuFnType( if (CodeGen.firstParamSRet(cc, return_type, zcu, target)) { try params_buffer.append(gpa, .i32); // memory address is always a 32-bit handle - } else if (return_type.hasRuntimeBitsIgnoreComptime(zcu)) { + } else if (return_type.hasRuntimeBits(zcu)) { if (cc == .wasm_mvp) { switch (abi.classifyType(return_type, zcu)) { .direct => |scalar_ty| { @@ -4245,7 +4245,7 @@ fn convertZcuFnType( // param types for (params) |param_type_ip| { const param_type = Zcu.Type.fromInterned(param_type_ip); - if (!param_type.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!param_type.hasRuntimeBits(zcu)) continue; switch (cc) { .wasm_mvp => { diff --git a/src/link/Wasm/Flush.zig b/src/link/Wasm/Flush.zig index 8197d35b724f6278d0edf4a719319fadd3cda270..5d19f5b159badbaaab884523b875996547df76ad 100644 --- a/src/link/Wasm/Flush.zig +++ b/src/link/Wasm/Flush.zig @@ -154,7 +154,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { .type_index = try wasm.internFunctionType(.auto, &.{int_tag_ty.ip_index}, .slice_const_u8_sentinel_0, target), .table_index = @intCast(wasm.tag_name_offs.items.len), } }; - const tag_names = ip.loadEnumType(data.ip_index).names; + const tag_names = ip.loadEnumType(data.ip_index).field_names; for (tag_names.get(ip)) |tag_name| { const slice = tag_name.toSlice(ip); try wasm.tag_name_offs.append(gpa, @intCast(wasm.tag_name_bytes.items.len)); @@ -1869,7 +1869,7 @@ fn emitTagNameFunction( const zcu = comp.zcu.?; const ip = &zcu.intern_pool; const enum_type = ip.loadEnumType(enum_type_ip); - const tag_values = enum_type.values.get(ip); + const tag_values = enum_type.field_values.get(ip); const slice_abi_size = 8; const encoded_alignment = @ctz(@as(u32, 4)); @@ -1908,7 +1908,7 @@ fn emitTagNameFunction( return; } - const int_info = Zcu.Type.intInfo(.fromInterned(enum_type.tag_ty), zcu); + const int_info = Zcu.Type.intInfo(.fromInterned(enum_type.int_tag_type), zcu); const outer_block_type: std.wasm.BlockType = switch (int_info.bits) { 0...32 => .i32, 33...64 => .i64, diff --git a/src/link/tapi/parse.zig b/src/link/tapi/parse.zig index 4483d359eb002e95823a4d6e1ecd64fefddfc0ec..487b609bcab3bd93fa38a2fa25026ebfc93cff85 100644 --- a/src/link/tapi/parse.zig +++ b/src/link/tapi/parse.zig @@ -530,7 +530,7 @@ const Parser = struct { fn leaf_value(self: *Parser) ParseError!*Node { const node = try self.allocator.create(Node.Value); errdefer self.allocator.destroy(node); - node.* = .{ .string_value = .{} }; + node.* = .{ .string_value = .empty }; node.base.tree = self.tree; node.base.start = self.token_it.pos; errdefer node.string_value.deinit(self.allocator); -- 2.54.0 From 986a4f1445e3ed1a6227a24d78b2154239ccdb31 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Thu, 12 Feb 2026 20:37:28 +0000 Subject: [PATCH 44/79] Sema: fix illegal comparison to undefined --- src/Sema.zig | 52 ++++++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index f1f2d895165a9408b06b2672dadfb52000d81ff1..ccb6f31aae4872cdcc3c86d9a1641292913cc0af 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -10374,7 +10374,7 @@ fn analyzeSwitchBlock( assert(case.range_infos.len == 0); for (case.item_infos, item_refs) |item_info, item_ref| { if (item_info.bodyLen()) |body_len| extra_index += body_len; - if (sema.wantSwitchProngBodyAnalysis(block, item_ref, operand_ty, false, true, prong_info.is_comptime_unreach)) { + if (sema.wantSwitchProngBodyAnalysis(item_ref, operand_ty, false, true, prong_info.is_comptime_unreach)) { break :skip_case; } } @@ -10390,7 +10390,7 @@ fn analyzeSwitchBlock( unreachable; // malformed validated switch }; - const analyze_body = sema.wantSwitchProngBodyAnalysis(block, .fromValue(item_opv), operand_ty, union_originally, err_set, false); + const analyze_body = sema.wantSwitchProngBodyAnalysis(.fromValue(item_opv), operand_ty, union_originally, err_set, false); if (!analyze_body) return .unreachable_value; if (!(err_set and @@ -10648,7 +10648,7 @@ fn finishSwitchBr( if (item_ref == .none) is_under_prong = true; if (item_info.bodyLen()) |body_len| extra_index += body_len; - const analyze_body = sema.wantSwitchProngBodyAnalysis(block, item_ref, operand_ty, union_originally, err_set, prong_info.is_comptime_unreach); + const analyze_body = sema.wantSwitchProngBodyAnalysis(item_ref, operand_ty, union_originally, err_set, prong_info.is_comptime_unreach); if (analyze_body) any_analyze_body = true; if (prong_info.is_inline) { @@ -10708,8 +10708,8 @@ fn finishSwitchBr( any_analyze_body = true; // always an integer range, always needs analysis if (prong_info.is_inline) { - var item = sema.resolveConstDefinedValue(block, .unneeded, range_ref[0], undefined) catch unreachable; - const item_last = sema.resolveConstDefinedValue(block, .unneeded, range_ref[1], undefined) catch unreachable; + var item = sema.resolveValue(range_ref[0]).?; + const item_last = sema.resolveValue(range_ref[1]).?; if (item.getUnsignedInt(zcu)) |first_int| { if (item_last.getUnsignedInt(zcu)) |last_int| { @@ -10887,7 +10887,7 @@ fn finishSwitchBr( const item_ref: Air.Inst.Ref = .fromValue(item_val); - const analyze_body = sema.wantSwitchProngBodyAnalysis(block, item_ref, operand_ty, union_originally, err_set, false); + const analyze_body = sema.wantSwitchProngBodyAnalysis(item_ref, operand_ty, union_originally, err_set, false); if (emit_bb) try sema.emitBackwardBranch(block, else_prong_src); emit_bb = true; @@ -11820,7 +11820,7 @@ fn resolveSwitchBlock( }; continue; } - const item_val = sema.resolveConstDefinedValue(child_block, .unneeded, item_ref, undefined) catch unreachable; + const item_val = sema.resolveValue(item_ref).?; if (cond_val.eql(item_val, item_ty, zcu)) { if (err_set) try sema.maybeErrorUnwrapComptime(child_block, prong_body, cond_ref); if (union_originally and operand_ty.unionFieldType(item_val, zcu).?.isNoReturn(zcu)) { @@ -11853,8 +11853,8 @@ fn resolveSwitchBlock( } } for (range_refs) |range_ref| { - const first_val = sema.resolveConstDefinedValue(child_block, .unneeded, range_ref[0], undefined) catch unreachable; - const last_val = sema.resolveConstDefinedValue(child_block, .unneeded, range_ref[1], undefined) catch unreachable; + const first_val = sema.resolveValue(range_ref[0]).?; + const last_val = sema.resolveValue(range_ref[1]).?; if ((try sema.compareAll(cond_val, .gte, first_val, item_ty)) and (try sema.compareAll(cond_val, .lte, last_val, item_ty))) { @@ -12063,7 +12063,6 @@ fn resolveSwitchProng( fn wantSwitchProngBodyAnalysis( sema: *Sema, - block: *Block, item_ref: Air.Inst.Ref, operand_ty: Type, union_originally: bool, @@ -12072,12 +12071,12 @@ fn wantSwitchProngBodyAnalysis( ) bool { const zcu = sema.pt.zcu; if (union_originally) { - const item_val = sema.resolveConstDefinedValue(block, .unneeded, item_ref, undefined) catch unreachable; + const item_val = sema.resolveValue(item_ref).?; const field_ty = operand_ty.unionFieldType(item_val, zcu).?; if (field_ty.isNoReturn(zcu)) return false; } if (err_set and prong_is_comptime_unreach) { - const item_val = sema.resolveConstDefinedValue(block, .unneeded, item_ref, undefined) catch unreachable; + const item_val = sema.resolveValue(item_ref).?; const err_name = item_val.getErrorName(zcu).unwrap().?; if (!operand_ty.errorSetHasField(err_name, zcu)) return false; } @@ -12252,7 +12251,7 @@ fn analyzeSwitchPayloadCapture( const switch_node_offset = operand_src.offset.node_offset_switch_operand; if (kind == .inline_ref) { - const item_val = sema.resolveConstDefinedValue(case_block, .unneeded, kind.inline_ref, undefined) catch unreachable; + const item_val = sema.resolveValue(kind.inline_ref).?; if (operand_ty.zigTypeTag(zcu) == .@"union") { const field_index: u32 = @intCast(operand_ty.unionTagFieldIndex(item_val, zcu).?); const union_obj = zcu.typeToUnion(operand_ty).?; @@ -12303,14 +12302,14 @@ fn analyzeSwitchPayloadCapture( const case_vals = kind.item_refs; const union_obj = zcu.typeToUnion(operand_ty).?; - const first_item_val = sema.resolveConstDefinedValue(case_block, .unneeded, case_vals[0], undefined) catch unreachable; + const first_item_val = sema.resolveValue(case_vals[0]).?; const first_field_index: u32 = zcu.unionTagFieldIndex(union_obj, first_item_val).?; const first_field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[first_field_index]); const field_indices = try sema.arena.alloc(u32, case_vals.len); for (case_vals, field_indices) |item, *field_idx| { - const item_val = sema.resolveConstDefinedValue(case_block, .unneeded, item, undefined) catch unreachable; + const item_val = sema.resolveValue(item).?; field_idx.* = zcu.unionTagFieldIndex(union_obj, item_val).?; } @@ -12592,7 +12591,7 @@ fn analyzeSwitchPayloadCapture( const case_vals = kind.item_refs; if (case_vals.len == 1) { - const item_val = sema.resolveConstDefinedValue(case_block, .unneeded, case_vals[0], undefined) catch unreachable; + const item_val = sema.resolveValue(case_vals[0]).?; const item_ty = try pt.singleErrorSetType(item_val.getErrorName(zcu).unwrap().?); return sema.bitCast(case_block, item_ty, .fromValue(item_val), operand_src, null); } @@ -12600,7 +12599,7 @@ fn analyzeSwitchPayloadCapture( var names: InferredErrorSet.NameMap = .{}; try names.ensureUnusedCapacity(sema.arena, case_vals.len); for (case_vals) |err| { - const err_val = sema.resolveConstDefinedValue(case_block, .unneeded, err, undefined) catch unreachable; + const err_val = sema.resolveValue(err).?; names.putAssumeCapacityNoClobber(err_val.getErrorName(zcu).unwrap().?, {}); } const error_ty = try pt.errorSetFromUnsortedNames(names.keys()); @@ -13731,26 +13730,24 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const lhs_elem_i = elem_i; const elem_default_val: ?Value = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, zcu) else null; const elem_val = elem_default_val orelse try lhs_sub_val.elemValue(pt, lhs_elem_i); - const elem_val_inst = Air.internedToRef(elem_val.toIntern()); const operand_src = block.src(.{ .array_cat_lhs = .{ .array_cat_offset = inst_data.src_node, .elem_index = elem_i, } }); - const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, operand_src); - const coerced_elem_val = try sema.resolveConstValue(block, operand_src, coerced_elem_val_inst, undefined); + const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, .fromValue(elem_val), operand_src); + const coerced_elem_val = sema.resolveValue(coerced_elem_val_inst).?; element_vals[elem_i] = coerced_elem_val.toIntern(); } while (elem_i < result_len) : (elem_i += 1) { const rhs_elem_i = elem_i - lhs_len; const elem_default_val: ?Value = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, zcu) else null; const elem_val = elem_default_val orelse try rhs_sub_val.elemValue(pt, rhs_elem_i); - const elem_val_inst = Air.internedToRef(elem_val.toIntern()); const operand_src = block.src(.{ .array_cat_rhs = .{ .array_cat_offset = inst_data.src_node, .elem_index = @intCast(rhs_elem_i), } }); - const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, operand_src); - const coerced_elem_val = try sema.resolveConstValue(block, operand_src, coerced_elem_val_inst, undefined); + const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, .fromValue(elem_val), operand_src); + const coerced_elem_val = sema.resolveValue(coerced_elem_val_inst).?; element_vals[elem_i] = coerced_elem_val.toIntern(); } return sema.addConstantMaybeRef( @@ -25886,7 +25883,6 @@ fn fieldPtr( } }, .type => { - _ = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, object_ptr, undefined); const result = try sema.analyzeLoad(block, src, object_ptr, object_ptr_src); const inner = if (is_pointer_to) try sema.analyzeLoad(block, src, result, object_ptr_src) @@ -27361,7 +27357,7 @@ fn coerceExtra( // Function body to function pointer. if (inst_ty.zigTypeTag(zcu) == .@"fn") { - const fn_val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined); + const fn_val = sema.resolveValue(inst).?; const fn_nav = switch (zcu.intern_pool.indexToKey(fn_val.toIntern())) { .func => |f| f.owner_nav, .@"extern" => |e| e.owner_nav, @@ -27667,7 +27663,7 @@ fn coerceExtra( }, .float, .comptime_float => switch (inst_ty.zigTypeTag(zcu)) { .comptime_float => { - const val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined); + const val = sema.resolveValue(inst).?; const result_val = try val.floatCast(dest_ty, pt); return Air.internedToRef(result_val.toIntern()); }, @@ -27753,7 +27749,7 @@ fn coerceExtra( .@"enum" => switch (inst_ty.zigTypeTag(zcu)) { .enum_literal => { // enum literal to enum - const val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined); + const val = sema.resolveValue(inst).?; const string = zcu.intern_pool.indexToKey(val.toIntern()).enum_literal; const field_index = dest_ty.enumFieldIndex(string, zcu) orelse { return sema.fail(block, inst_src, "no field named '{f}' in enum '{f}'", .{ @@ -28965,7 +28961,7 @@ fn coerceVarArgParam( .{}, ), .@"fn" => fn_ptr: { - const fn_val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined); + const fn_val = sema.resolveValue(inst).?; const fn_nav = zcu.funcInfo(fn_val.toIntern()).owner_nav; break :fn_ptr try sema.analyzeNavRef(block, inst_src, fn_nav); }, -- 2.54.0 From 7ca061f3d68ff936dd77a58402c817b0aa1044e6 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Thu, 12 Feb 2026 23:33:04 +0000 Subject: [PATCH 45/79] compiler: rework and simplify main loop --- src/Compilation.zig | 511 ++----------------------------------- src/Sema.zig | 6 +- src/Zcu.zig | 2 + src/Zcu/PerThread.zig | 580 +++++++++++++++++++++++++++++++++--------- 4 files changed, 484 insertions(+), 615 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 66483ebd727709e21a586c354137269303b8cd3a..45d0aa6e97fbb735127efa5f1d399731d6bde4a6 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -21,7 +21,6 @@ const introspect = @import("introspect.zig"); const link = @import("link.zig"); const tracy = @import("tracy.zig"); const trace = tracy.trace; -const traceNamed = tracy.traceNamed; const build_options = @import("build_options"); const LibCInstallation = std.zig.LibCInstallation; const glibc = @import("libs/glibc.zig"); @@ -89,6 +88,9 @@ framework_dirs: []const []const u8, /// These are only for DLLs dependencies fulfilled by the `.def` files shipped /// with Zig. Static libraries are provided as `link.Input` values. windows_libs: std.StringArrayHashMapUnmanaged(void), +/// The number of items in `windows_libs` which we have already built. All items at or after this +/// index will be built in `performAllTheWork`. +windows_libs_num_done: u32, version: ?std.SemanticVersion, libc_installation: ?*const LibCInstallation, skip_linker_dependencies: bool, @@ -126,8 +128,6 @@ oneshot_prelink_tasks: std.ArrayList(link.PrelinkTask), /// work is queued or not. queued_jobs: QueuedJobs, -work_queues: [2]std.Deque(Job), - /// These jobs are to invoke the Clang compiler to create an object file, which /// gets linked with the Compilation. c_object_work_queue: std.Deque(*CObject), @@ -954,51 +954,6 @@ pub const RcSourceFile = struct { extra_flags: []const []const u8 = &.{}, }; -const Job = union(enum) { - /// Given the generated AIR for a function, put it onto the code generation queue. - /// MLUGG TODO: because type resolution is no longer necessary, we can remove this now - /// If the backend does not support `Zcu.Feature.separate_thread`, codegen and linking happen immediately. - /// Before queueing this `Job`, increase the estimated total item count for both - /// `comp.zcu.?.codegen_prog_node` and `comp.link_prog_node`. - codegen_func: struct { - func: InternPool.Index, - /// The AIR emitted from analyzing `func`; owned by this `Job` in `gpa`. - air: Air, - }, - /// Queue a `link.ZcuTask` to emit this non-function `Nav` into the output binary. - /// MLUGG TODO: because type resolution is no longer necessary, we can remove this now - /// If the backend does not support `Zcu.Feature.separate_thread`, the task is run immediately. - /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`. - link_nav: InternPool.Nav.Index, - /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`. - update_line_number: InternPool.TrackedInst.Index, - /// The `AnalUnit`, which is *not* a `func`, must be semantically analyzed. - /// This may be its first time being analyzed, or it may be outdated. - /// If the unit is a function, a `codegen_func` job will be queued after analysis completes. - /// If the unit is a *test* function, an `analyze_func` job will also be queued. - analyze_unit: InternPool.AnalUnit, - /// The main source file for the module needs to be analyzed. - /// For every module which is an analysis root, analyze the main struct type of the module's - /// root source file. This is how semantic analysis begins. - analyze_roots, - - /// The value is the index into `windows_libs`. - windows_import_lib: usize, - - fn stage(job: *const Job) usize { - // Prioritize functions so that codegen can get to work on them on a - // separate thread, while Sema goes back to its own work. - return switch (job.*) { - .codegen_func => 0, - .analyze_unit => |unit| switch (unit.unwrap()) { - .func => 0, - else => 1, - }, - else => 1, - }; - } -}; - pub const CObject = struct { /// Relative to cwd. Owned by arena. src: CSourceFile, @@ -2274,7 +2229,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, .root_mod = options.root_mod, .config = options.config, .dirs = options.dirs, - .work_queues = @splat(.empty), .c_object_work_queue = .empty, .win32_resource_work_queue = .empty, .c_source_files = options.c_source_files, @@ -2308,6 +2262,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, .root_name = root_name, .sysroot = sysroot, .windows_libs = .empty, + .windows_libs_num_done = 0, .version = options.version, .libc_installation = libc_dirs.libc_installation, .compiler_rt_strat = compiler_rt_strat, @@ -2670,16 +2625,6 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, } } - // Generate Windows import libs. - if (target.os.tag == .windows) { - const count = comp.windows_libs.count(); - for (0..count) |i| { - try comp.queueJob(.{ .windows_import_lib = i }); - } - // when integrating coff linker with prelink, the above `queueJob` will need to move - // to something in `dispatchPrelinkWork`, which must queue all prelink link tasks - // *before* we begin working on the main job queue. - } if (comp.wantBuildLibUnwindFromSource()) { comp.queued_jobs.libunwind = true; } @@ -2763,7 +2708,6 @@ pub fn destroy(comp: *Compilation) void { if (comp.zcu) |zcu| zcu.deinit(); comp.cache_use.deinit(io); - for (&comp.work_queues) |*work_queue| work_queue.deinit(gpa); comp.c_object_work_queue.deinit(gpa); comp.win32_resource_work_queue.deinit(gpa); @@ -4563,13 +4507,7 @@ fn performAllTheWork( comp: *Compilation, main_progress_node: std.Progress.Node, update_arena: Allocator, -) JobError!void { - defer if (comp.zcu) |zcu| { - zcu.codegen_task_pool.cancel(zcu); - // Regardless of errors, `comp.zcu` needs to update its generation number. - zcu.generation += 1; - }; - +) (Allocator.Error || Io.Cancelable)!void { const io = comp.io; // This is awkward: we don't want to start the timer until later, but we won't want to stop it @@ -4602,207 +4540,33 @@ fn performAllTheWork( misc_group.async(io, workerDocsWasm, .{ comp, main_progress_node }); } - if (comp.zcu) |zcu| { - const tracy_trace = traceNamed(@src(), "astgen"); - defer tracy_trace.end(); - - const zir_prog_node = main_progress_node.start("AST Lowering", 0); - defer zir_prog_node.end(); - - var timer = comp.startTimer(); - defer if (timer.finish(io)) |ns| { - comp.mutex.lockUncancelable(io); - defer comp.mutex.unlock(io); - comp.time_report.?.stats.real_ns_files = ns; - }; - - const gpa = comp.gpa; - - var astgen_group: Io.Group = .init; - defer astgen_group.cancel(io); - - // We cannot reference `zcu.import_table` after we spawn any `workerUpdateFile` jobs, - // because on single-threaded targets the worker will be run eagerly, meaning the - // `import_table` could be mutated, and not even holding `comp.mutex` will save us. So, - // build up a list of the files to update *before* we spawn any jobs. - var astgen_work_items: std.MultiArrayList(struct { - file_index: Zcu.File.Index, - file: *Zcu.File, - }) = .empty; - defer astgen_work_items.deinit(gpa); - // Not every item in `import_table` will need updating, because some are builtin.zig - // files. However, most will, so let's just reserve sufficient capacity upfront. - try astgen_work_items.ensureTotalCapacity(gpa, zcu.import_table.count()); - for (zcu.import_table.keys()) |file_index| { - const file = zcu.fileByIndex(file_index); - if (file.is_builtin) { - // This is a `builtin.zig`, so updating is redundant. However, we want to make - // sure the file contents are still correct on disk, since it can improve the - // debugging experience better. That job only needs `file`, so we can kick it - // off right now. - astgen_group.async(io, workerUpdateBuiltinFile, .{ comp, file }); - continue; - } - astgen_work_items.appendAssumeCapacity(.{ - .file_index = file_index, - .file = file, - }); - } - - // Now that we're not going to touch `zcu.import_table` again, we can spawn `workerUpdateFile` jobs. - for (astgen_work_items.items(.file_index), astgen_work_items.items(.file)) |file_index, file| { - astgen_group.async(io, workerUpdateFile, .{ - comp, file, file_index, zir_prog_node, &astgen_group, - }); - } - - // On the other hand, it's fine to directly iterate `zcu.embed_table.keys()` here - // because `workerUpdateEmbedFile` can't invalidate it. The different here is that one - // `@embedFile` can't trigger analysis of a new `@embedFile`! - for (0.., zcu.embed_table.keys()) |ef_index_usize, ef| { - const ef_index: Zcu.EmbedFile.Index = @enumFromInt(ef_index_usize); - astgen_group.async(io, workerUpdateEmbedFile, .{ - comp, ef_index, ef, - }); - } - - try astgen_group.await(io); - } - + defer if (comp.zcu) |zcu| zcu.codegen_task_pool.cancel(zcu); if (comp.zcu) |zcu| { const pt: Zcu.PerThread = .activate(zcu, .main); - defer pt.deactivate(); - - const gpa = zcu.gpa; - - // On an incremental update, a source file might become "dead", in that all imports of - // the file were removed. This could even change what module the file belongs to! As such, - // we do a traversal over the files, to figure out which ones are alive and the modules - // they belong to. - const any_fatal_files = try pt.computeAliveFiles(); - - // If the cache mode is `whole`, add every alive source file to the manifest. - switch (comp.cache_use) { - .whole => |whole| if (whole.cache_manifest) |man| { - for (zcu.alive_files.keys()) |file_index| { - const file = zcu.fileByIndex(file_index); - - switch (file.status) { - .never_loaded => unreachable, // AstGen tried to load it - .retryable_failure => continue, // the file cannot be read; this is a guaranteed error - .astgen_failure, .success => {}, // the file was read successfully - } - - const path = try file.path.toAbsolute(comp.dirs, gpa); - defer gpa.free(path); - - const result = res: { - try whole.cache_manifest_mutex.lock(io); - defer whole.cache_manifest_mutex.unlock(io); - if (file.source) |source| { - break :res man.addFilePostContents(path, source, file.stat); - } else { - break :res man.addFilePost(path); - } - }; - result catch |err| switch (err) { - error.OutOfMemory => |e| return e, - else => { - try pt.reportRetryableFileError(file_index, "unable to update cache: {s}", .{@errorName(err)}); - continue; - }, - }; - } - }, - .none, .incremental => {}, + defer { + pt.deactivate(); + // Regardless of errors, `comp.zcu` needs to update its generation number. + zcu.generation += 1; } - - if (any_fatal_files or - zcu.multi_module_err != null or - zcu.failed_imports.items.len > 0 or - comp.alloc_failure_occurred) - { - // We give up right now! No updating of ZIR refs, no nothing. The idea is that this prevents - // us from invalidating lots of incremental dependencies due to files with e.g. parse errors. - // However, this means our analysis data is invalid, so we want to omit all analysis errors. - zcu.skip_analysis_this_update = true; - // Since we're skipping analysis, there are no ZCU link tasks. - comp.link_queue.finishZcuQueue(comp); - // Let other compilation work finish to collect as many errors as possible. - try misc_group.await(io); - comp.link_queue.wait(io); - return; - } - - if (comp.time_report) |*tr| { - tr.stats.n_reachable_files = @intCast(zcu.alive_files.count()); - } - - if (comp.config.incremental) { - const update_zir_refs_node = main_progress_node.start("Update ZIR References", 0); - defer update_zir_refs_node.end(); - try pt.updateZirRefs(); - } - try zcu.flushRetryableFailures(); - - // It's analysis time! Queue up our initial analysis. - try comp.queueJob(.analyze_roots); - - zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); - if (comp.bin_file != null) { - zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0); - } - // We increment `pending_codegen_jobs` so that it doesn't reach 0 until after analysis finishes. - // That prevents the "Code Generation" node from constantly disappearing and reappearing when - // we're probably going to analyze more functions at some point. - assert(zcu.pending_codegen_jobs.swap(1, .monotonic) == 0); // don't let this become 0 until analysis finishes - } - // When analysis ends, delete the progress nodes for "Semantic Analysis" and possibly "Code Generation". - defer if (comp.zcu) |zcu| { - zcu.sema_prog_node.end(); - zcu.sema_prog_node = .none; - if (zcu.pending_codegen_jobs.fetchSub(1, .monotonic) == 1) { - // Decremented to 0, so all done. - zcu.codegen_prog_node.end(); - zcu.codegen_prog_node = .none; - } - }; - - if (comp.zcu) |zcu| { - if (!zcu.backendSupportsFeature(.separate_thread)) { - // Close the ZCU task queue. Prelink may still be running, but the closed - // queue will cause the linker task to exit once prelink finishes. The - // closed queue also communicates to `enqueueZcu` that it should wait for - // the linker task to finish and then run ZCU tasks serially. - comp.link_queue.finishZcuQueue(comp); - } - } - - if (comp.zcu != null) { - // Start the timer for the "decls" part of the pipeline (Sema, CodeGen, link). - decl_work_timer = comp.startTimer(); - } - - work: while (true) { - for (&comp.work_queues) |*work_queue| if (work_queue.popFront()) |job| { - try processOneJob(.main, comp, job); - continue :work; - }; - if (comp.zcu) |zcu| { - // If there's no work queued, check if there's anything outdated - // which we need to work on, and queue it if so. - if (try zcu.findOutdatedToAnalyze()) |outdated| { - try comp.queueJob(.{ .analyze_unit = outdated }); - continue; - } - zcu.sema_prog_node.end(); - zcu.sema_prog_node = .none; - } - break; + try pt.update(main_progress_node, &decl_work_timer); } comp.link_queue.finishZcuQueue(comp); + // This has to happen after the main semantic analysis loop because it is possible for Sema to + // call `addLinkLib` and hence add more items to `comp.windows_libs`. + for (comp.windows_libs.keys()[comp.windows_libs_num_done..]) |link_lib| { + mingw.buildImportLib(comp, link_lib) catch |err| { + // TODO Surface more error details. + comp.lockAndSetMiscFailure( + .windows_import_lib, + "unable to generate DLL import .lib file for {s}: {t}", + .{ link_lib, err }, + ); + }; + } + comp.windows_libs_num_done = @intCast(comp.windows_libs.count()); + // Main thread work is all done, now just wait for all async work. try misc_group.await(io); comp.link_queue.wait(io); @@ -5032,121 +4796,6 @@ fn dispatchPrelinkWork(comp: *Compilation, main_progress_node: std.Progress.Node }; } -const JobError = Allocator.Error || Io.Cancelable; - -pub fn queueJob(comp: *Compilation, job: Job) !void { - try comp.work_queues[job.stage()].pushBack(comp.gpa, job); -} - -pub fn queueJobs(comp: *Compilation, jobs: []const Job) !void { - for (jobs) |job| try comp.queueJob(job); -} - -fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!void { - switch (job) { - .codegen_func => |func| { - const zcu = comp.zcu.?; - const gpa = zcu.gpa; - var owned_air: ?Air = func.air; - defer if (owned_air) |*air| air.deinit(gpa); - - // Some linkers need to refer to the AIR. In that case, the linker is not running - // concurrently, so we'll just keep ownership of the AIR for ourselves instead of - // letting the codegen job destroy it. - const disown_air = zcu.backendSupportsFeature(.separate_thread); - - // Begin the codegen task. If the codegen/link queue is backed up, this might - // block until the linker is able to process some tasks. - const codegen_task = try zcu.codegen_task_pool.start(zcu, func.func, &owned_air.?, disown_air); - if (disown_air) owned_air = null; - - try comp.link_queue.enqueueZcu(comp, tid, .{ .link_func = codegen_task }); - }, - .link_nav => |nav_index| { - const zcu = comp.zcu.?; - const nav = zcu.intern_pool.getNav(nav_index); - if (nav.analysis != null) { - const unit: InternPool.AnalUnit = .wrap(.{ .nav_val = nav_index }); - if (zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit)) { - comp.link_prog_node.completeOne(); - return; - } - } - assert(nav.status == .fully_resolved); - try comp.link_queue.enqueueZcu(comp, tid, .{ .link_nav = nav_index }); - }, - .update_line_number => |tracked_inst| { - try comp.link_queue.enqueueZcu(comp, tid, .{ .debug_update_line_number = tracked_inst }); - }, - .analyze_unit => |unit| { - const tracy_trace = traceNamed(@src(), "analyze_unit"); - defer tracy_trace.end(); - - const pt: Zcu.PerThread = .activate(comp.zcu.?, tid); - defer pt.deactivate(); - - const maybe_err: Zcu.SemaError!void = switch (unit.unwrap()) { - .@"comptime" => |cu| pt.ensureComptimeUnitUpToDate(cu), - .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav, null), - .nav_val => |nav| pt.ensureNavValUpToDate(nav, null), - .type_layout => |ty| pt.ensureTypeLayoutUpToDate(.fromInterned(ty), null), - .memoized_state => |stage| pt.ensureMemoizedStateUpToDate(stage, null), - .func => |func| pt.ensureFuncBodyUpToDate(func, null), - }; - maybe_err catch |err| switch (err) { - error.OutOfMemory => |e| return e, - error.Canceled => |e| return e, - error.AnalysisFail => return, - }; - - queue_test_analysis: { - if (!comp.config.is_test) break :queue_test_analysis; - const nav = switch (unit.unwrap()) { - .nav_val => |nav| nav, - else => break :queue_test_analysis, - }; - - // Check if this is a test function. - const ip = &pt.zcu.intern_pool; - if (!pt.zcu.test_functions.contains(nav)) { - break :queue_test_analysis; - } - - // Tests are always emitted in test binaries. The decl_refs are created by - // Zcu.populateTestFunctions, but this will not queue body analysis, so do - // that now. - try pt.zcu.ensureFuncBodyAnalysisQueued(ip.getNav(nav).status.fully_resolved.val); - } - }, - .analyze_roots => { - const tracy_trace = traceNamed(@src(), "analyze_roots"); - defer tracy_trace.end(); - - const zcu = comp.zcu.?; - const pt: Zcu.PerThread = .activate(zcu, tid); - defer pt.deactivate(); - for (zcu.analysisRoots()) |analysis_root_mod| { - const analysis_root_file = zcu.module_roots.get(analysis_root_mod).?.unwrap().?; - try pt.ensureFileAnalyzed(analysis_root_file); - } - }, - .windows_import_lib => |index| { - const tracy_trace = traceNamed(@src(), "windows_import_lib"); - defer tracy_trace.end(); - - const link_lib = comp.windows_libs.keys()[index]; - mingw.buildImportLib(comp, link_lib) catch |err| { - // TODO Surface more error details. - comp.lockAndSetMiscFailure( - .windows_import_lib, - "unable to generate DLL import .lib file for {s}: {t}", - .{ link_lib, err }, - ); - }; - }, - } -} - fn createDepFile(comp: *Compilation, dep_file: []const u8, bin_file: Cache.Path) anyerror!void { const io = comp.io; @@ -5474,112 +5123,6 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU }; } -fn workerUpdateFile( - comp: *Compilation, - file: *Zcu.File, - file_index: Zcu.File.Index, - prog_node: std.Progress.Node, - group: *Io.Group, -) void { - const io = comp.io; - const tid: Zcu.PerThread.Id = .acquire(io); - defer tid.release(io); - - const child_prog_node = prog_node.start(fs.path.basename(file.path.sub_path), 0); - defer child_prog_node.end(); - - const pt: Zcu.PerThread = .activate(comp.zcu.?, tid); - defer pt.deactivate(); - pt.updateFile(file_index, file) catch |err| { - pt.reportRetryableFileError(file_index, "unable to load '{s}': {s}", .{ fs.path.basename(file.path.sub_path), @errorName(err) }) catch |oom| switch (oom) { - error.OutOfMemory => { - comp.mutex.lockUncancelable(io); - defer comp.mutex.unlock(io); - comp.setAllocFailure(); - }, - }; - return; - }; - - switch (file.getMode()) { - .zig => {}, // continue to logic below - .zon => return, // ZON can't import anything so we're done - } - - // Discover all imports in the file. Imports of modules we ignore for now since we don't - // know which module we're in, but imports of file paths might need us to queue up other - // AstGen jobs. - const imports_index = file.zir.?.extra[@intFromEnum(Zir.ExtraIndex.imports)]; - if (imports_index != 0) { - const extra = file.zir.?.extraData(Zir.Inst.Imports, imports_index); - var import_i: u32 = 0; - var extra_index = extra.end; - - while (import_i < extra.data.imports_len) : (import_i += 1) { - const item = file.zir.?.extraData(Zir.Inst.Imports.Item, extra_index); - extra_index = item.end; - - const import_path = file.zir.?.nullTerminatedString(item.data.name); - - if (pt.discoverImport(file.path, import_path)) |res| switch (res) { - .module, .existing_file => {}, - .new_file => |new| { - group.async(io, workerUpdateFile, .{ - comp, new.file, new.index, prog_node, group, - }); - }, - } else |err| switch (err) { - error.OutOfMemory => { - comp.mutex.lockUncancelable(io); - defer comp.mutex.unlock(io); - comp.setAllocFailure(); - }, - } - } - } -} - -fn workerUpdateBuiltinFile(comp: *Compilation, file: *Zcu.File) void { - Builtin.updateFileOnDisk(file, comp) catch |err| comp.lockAndSetMiscFailure( - .write_builtin_zig, - "unable to write '{f}': {s}", - .{ file.path.fmt(comp), @errorName(err) }, - ); -} - -fn workerUpdateEmbedFile(comp: *Compilation, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) void { - const io = comp.io; - const tid: Zcu.PerThread.Id = .acquire(io); - defer tid.release(io); - comp.detectEmbedFileUpdate(tid, ef_index, ef) catch |err| switch (err) { - error.OutOfMemory => { - comp.mutex.lockUncancelable(io); - defer comp.mutex.unlock(io); - comp.setAllocFailure(); - }, - }; -} - -fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) !void { - const io = comp.io; - const zcu = comp.zcu.?; - const pt: Zcu.PerThread = .activate(zcu, tid); - defer pt.deactivate(); - - const old_val = ef.val; - const old_err = ef.err; - - try pt.updateEmbedFile(ef, null); - - if (ef.val != .none and ef.val == old_val) return; // success, value unchanged - if (ef.val == .none and old_val == .none and ef.err == old_err) return; // failure, error unchanged - - comp.mutex.lockUncancelable(io); - defer comp.mutex.unlock(io); - - try zcu.markDependeeOutdated(.not_marked_po, .{ .embed_file = ef_index }); -} - pub fn obtainCObjectCacheManifest( comp: *const Compilation, owner_mod: *Package.Module, @@ -8208,12 +7751,10 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void { // If we haven't seen this library yet and we're targeting Windows, we need // to queue up a work item to produce the DLL import library for this. const gop = try comp.windows_libs.getOrPut(comp.gpa, lib_name); - if (gop.found_existing) return; - { + if (!gop.found_existing) { errdefer _ = comp.windows_libs.pop(); gop.key_ptr.* = try comp.gpa.dupe(u8, lib_name); } - try comp.queueJob(.{ .windows_import_lib = gop.index }); } /// This decides the optimization mode for all zig-provided libraries, including diff --git a/src/Sema.zig b/src/Sema.zig index ccb6f31aae4872cdcc3c86d9a1641292913cc0af..79a97a3e379615f3787072565454acdc501d1fba 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5362,7 +5362,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr pt.updateFile(new_file_index, zcu.fileByIndex(new_file_index)) catch |err| return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); - try pt.ensureFileAnalyzed(new_file_index); + try pt.ensureFilePopulated(new_file_index); const ty: Type = .fromInterned(zcu.fileRootType(new_file_index)); try sema.addTypeReferenceEntry(src, ty); return .fromType(ty); @@ -13005,7 +13005,7 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. const file = zcu.fileByIndex(file_index); switch (file.getMode()) { .zig => { - try pt.ensureFileAnalyzed(file_index); + try pt.ensureFilePopulated(file_index); const ty: Type = .fromInterned(zcu.fileRootType(file_index)); try sema.addTypeReferenceEntry(operand_src, ty); // No need for `ensureNamespaceUpToDate`, because `Zcu.PerThread.updateFileNamespace` @@ -34002,7 +34002,7 @@ pub fn analyzeMemoizedState(sema: *Sema, stage: InternPool.MemoizedStateStage) C // Get the main struct type of the root source file of `std`. No need for a reference entry // because `std` is always an analysis root. const std_file_index = zcu.module_roots.get(zcu.std_mod).?.unwrap().?; - try pt.ensureFileAnalyzed(std_file_index); + try pt.ensureFilePopulated(std_file_index); const std_type: Type = .fromInterned(zcu.fileRootType(std_file_index)); break :block .{ .parent = null, diff --git a/src/Zcu.zig b/src/Zcu.zig index 4e48ff694602c4fb3833e9b133279aea76aa588d..658a6513a84d4236095ccc5e5b46b5392d9748cb 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -3208,6 +3208,8 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni /// recursive analysis (all of its previously-marked dependencies are already up-to-date), because /// recursive analysis can cause over-analysis on incremental updates. pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { + // MLUGG TODO: priorize `func` units, just like we used to do in the Compilation job queue. + if (zcu.outdated_ready.count() > 0) { const unit = zcu.outdated_ready.keys()[0]; log.debug("findOutdatedToAnalyze: {f}", .{zcu.fmtAnalUnit(unit)}); diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 73cb527f79791881e05d28cdb18f0bb63ec43737..ef22213c9a9b143c2a3ce47ca46b99e362c51765 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -27,7 +27,9 @@ const introspect = @import("../introspect.zig"); const Module = @import("../Package.zig").Module; const Sema = @import("../Sema.zig"); const target_util = @import("../target.zig"); -const trace = @import("../tracy.zig").trace; +const tracy = @import("../tracy.zig"); +const trace = tracy.trace; +const traceNamed = tracy.traceNamed; const Type = @import("../Type.zig"); const Value = @import("../Value.zig"); const Zcu = @import("../Zcu.zig"); @@ -125,6 +127,318 @@ pub fn deactivate(pt: Zcu.PerThread) void { pt.zcu.intern_pool.deactivate(); } +/// Called from `Compilation.performAllTheWork`. Performs one incremental update of the ZCU: detects +/// changes to files, runs AstGen, and then enters the main semantic analysis loop, where we build +/// up a graph of declarations, functions, etc, while also sending declarations and functions to +/// codegen as they are analyzed. +pub fn update( + pt: Zcu.PerThread, + main_progress_node: std.Progress.Node, + decl_work_timer: *?Compilation.Timer, +) (Allocator.Error || Io.Cancelable)!void { + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const io = comp.io; + + { + const tracy_trace = traceNamed(@src(), "astgen"); + defer tracy_trace.end(); + + const zir_prog_node = main_progress_node.start("AST Lowering", 0); + defer zir_prog_node.end(); + + var timer = comp.startTimer(); + defer if (timer.finish(io)) |ns| { + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); + comp.time_report.?.stats.real_ns_files = ns; + }; + + var astgen_group: Io.Group = .init; + defer astgen_group.cancel(io); + + // We cannot reference `zcu.import_table` after we spawn any `workerUpdateFile` jobs, + // because on single-threaded targets the worker will be run eagerly, meaning the + // `import_table` could be mutated, and not even holding `comp.mutex` will save us. So, + // build up a list of the files to update *before* we spawn any jobs. + var astgen_work_items: std.MultiArrayList(struct { + file_index: Zcu.File.Index, + file: *Zcu.File, + }) = .empty; + defer astgen_work_items.deinit(gpa); + // Not every item in `import_table` will need updating, because some are builtin.zig + // files. However, most will, so let's just reserve sufficient capacity upfront. + try astgen_work_items.ensureTotalCapacity(gpa, zcu.import_table.count()); + for (zcu.import_table.keys()) |file_index| { + const file = zcu.fileByIndex(file_index); + if (file.is_builtin) { + // This is a `builtin.zig`, so updating is redundant. However, we want to make + // sure the file contents are still correct on disk, since it can improve the + // debugging experience better. That job only needs `file`, so we can kick it + // off right now. + astgen_group.async(io, workerUpdateBuiltinFile, .{ comp, file }); + continue; + } + astgen_work_items.appendAssumeCapacity(.{ + .file_index = file_index, + .file = file, + }); + } + + // Now that we're not going to touch `zcu.import_table` again, we can spawn `workerUpdateFile` jobs. + for (astgen_work_items.items(.file_index), astgen_work_items.items(.file)) |file_index, file| { + astgen_group.async(io, workerUpdateFile, .{ + comp, file, file_index, zir_prog_node, &astgen_group, + }); + } + + // On the other hand, it's fine to directly iterate `zcu.embed_table.keys()` here + // because `workerUpdateEmbedFile` can't invalidate it. The different here is that one + // `@embedFile` can't trigger analysis of a new `@embedFile`! + for (0.., zcu.embed_table.keys()) |ef_index_usize, ef| { + const ef_index: Zcu.EmbedFile.Index = @enumFromInt(ef_index_usize); + astgen_group.async(io, workerUpdateEmbedFile, .{ + comp, ef_index, ef, + }); + } + + try astgen_group.await(io); + } + + // On an incremental update, a source file might become "dead", in that all imports of + // the file were removed. This could even change what module the file belongs to! As such, + // we do a traversal over the files, to figure out which ones are alive and the modules + // they belong to. + const any_fatal_files = try pt.computeAliveFiles(); + + // If the cache mode is `whole`, add every alive source file to the manifest. + switch (comp.cache_use) { + .whole => |whole| if (whole.cache_manifest) |man| { + for (zcu.alive_files.keys()) |file_index| { + const file = zcu.fileByIndex(file_index); + + switch (file.status) { + .never_loaded => unreachable, // AstGen tried to load it + .retryable_failure => continue, // the file cannot be read; this is a guaranteed error + .astgen_failure, .success => {}, // the file was read successfully + } + + const path = try file.path.toAbsolute(comp.dirs, gpa); + defer gpa.free(path); + + const result = res: { + try whole.cache_manifest_mutex.lock(io); + defer whole.cache_manifest_mutex.unlock(io); + if (file.source) |source| { + break :res man.addFilePostContents(path, source, file.stat); + } else { + break :res man.addFilePost(path); + } + }; + result catch |err| switch (err) { + error.OutOfMemory => |e| return e, + else => { + try pt.reportRetryableFileError(file_index, "unable to update cache: {s}", .{@errorName(err)}); + continue; + }, + }; + } + }, + .none, .incremental => {}, + } + + if (comp.time_report) |*tr| { + tr.stats.n_reachable_files = @intCast(zcu.alive_files.count()); + } + + if (any_fatal_files or + zcu.multi_module_err != null or + zcu.failed_imports.items.len > 0 or + comp.alloc_failure_occurred) + { + // We give up right now! No updating of ZIR refs, no nothing. The idea is that this prevents + // us from invalidating lots of incremental dependencies due to files with e.g. parse errors. + // However, this means our analysis data is invalid, so we want to omit all analysis errors. + zcu.skip_analysis_this_update = true; + return; + } + + if (comp.config.incremental) { + const update_zir_refs_node = main_progress_node.start("Update ZIR References", 0); + defer update_zir_refs_node.end(); + try pt.updateZirRefs(); + } + + try zcu.flushRetryableFailures(); + + if (!zcu.backendSupportsFeature(.separate_thread)) { + // Close the ZCU task queue. Prelink may still be running, but the closed + // queue will cause the linker task to exit once prelink finishes. The + // closed queue also communicates to `enqueueZcu` that it should wait for + // the linker task to finish and then run ZCU tasks serially. + comp.link_queue.finishZcuQueue(comp); + } + + zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0); + if (comp.bin_file != null) { + zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0); + } + // We increment `pending_codegen_jobs` so that it doesn't reach 0 until after analysis finishes. + // That prevents the "Code Generation" node from constantly disappearing and reappearing when + // we're probably going to analyze more functions at some point. + assert(zcu.pending_codegen_jobs.swap(1, .monotonic) == 0); // don't let this become 0 until analysis finishes + + defer { + zcu.sema_prog_node.end(); + zcu.sema_prog_node = .none; + if (zcu.pending_codegen_jobs.fetchSub(1, .monotonic) == 1) { + // Decremented to 0, so all done. + zcu.codegen_prog_node.end(); + zcu.codegen_prog_node = .none; + } + } + + // Start the timer for the "decls" part of the pipeline (Sema, CodeGen, link). + decl_work_timer.* = comp.startTimer(); + + // To kick off semantic analysis, populate the root source file of any module we have marked + // as an analysis root. Declarations in these files which want eager analysis---those being + // `comptime` declarations, any declarations marked `export`, and `test` declarations in the + // main module if this is a test compilation---become referenced, and so will be picked up + // up by the main semantic analysis loop below. + for (zcu.analysisRoots()) |analysis_root_mod| { + const analysis_root_file = zcu.module_roots.get(analysis_root_mod).?.unwrap().?; + try pt.ensureFilePopulated(analysis_root_file); + } + + // This is the main semantic analysis loop, which is essentially the main loop of the whole + // Zig compilation pipeline. It selects some `AnalUnit` which we know needs to be analyzed, + // and analyzes it, which may in turn discover more `AnalUnit`s which we need to analyze. + while (try zcu.findOutdatedToAnalyze()) |unit| { + const tracy_trace = traceNamed(@src(), "analyze_outdated"); + defer tracy_trace.end(); + + const maybe_err: Zcu.SemaError!void = switch (unit.unwrap()) { + .@"comptime" => |cu| pt.ensureComptimeUnitUpToDate(cu), + .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav, null), + .nav_val => |nav| pt.ensureNavValUpToDate(nav, null), + .type_layout => |ty| pt.ensureTypeLayoutUpToDate(.fromInterned(ty), null), + .memoized_state => |stage| pt.ensureMemoizedStateUpToDate(stage, null), + .func => |func| pt.ensureFuncBodyUpToDate(func, null), + }; + maybe_err catch |err| switch (err) { + error.OutOfMemory, + error.Canceled, + => |e| return e, + + error.AnalysisFail => {}, // already reported + }; + } +} +fn workerUpdateBuiltinFile(comp: *Compilation, file: *Zcu.File) void { + Builtin.updateFileOnDisk(file, comp) catch |err| comp.lockAndSetMiscFailure( + .write_builtin_zig, + "unable to write '{f}': {s}", + .{ file.path.fmt(comp), @errorName(err) }, + ); +} +fn workerUpdateFile( + comp: *Compilation, + file: *Zcu.File, + file_index: Zcu.File.Index, + prog_node: std.Progress.Node, + group: *Io.Group, +) void { + const io = comp.io; + const tid: Zcu.PerThread.Id = .acquire(io); + defer tid.release(io); + + const child_prog_node = prog_node.start(std.fs.path.basename(file.path.sub_path), 0); + defer child_prog_node.end(); + + const pt: Zcu.PerThread = .activate(comp.zcu.?, tid); + defer pt.deactivate(); + pt.updateFile(file_index, file) catch |err| { + pt.reportRetryableFileError(file_index, "unable to load '{s}': {s}", .{ std.fs.path.basename(file.path.sub_path), @errorName(err) }) catch |oom| switch (oom) { + error.OutOfMemory => { + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); + comp.setAllocFailure(); + }, + }; + return; + }; + + switch (file.getMode()) { + .zig => {}, // continue to logic below + .zon => return, // ZON can't import anything so we're done + } + + // Discover all imports in the file. Imports of modules we ignore for now since we don't + // know which module we're in, but imports of file paths might need us to queue up other + // AstGen jobs. + const imports_index = file.zir.?.extra[@intFromEnum(Zir.ExtraIndex.imports)]; + if (imports_index != 0) { + const extra = file.zir.?.extraData(Zir.Inst.Imports, imports_index); + var import_i: u32 = 0; + var extra_index = extra.end; + + while (import_i < extra.data.imports_len) : (import_i += 1) { + const item = file.zir.?.extraData(Zir.Inst.Imports.Item, extra_index); + extra_index = item.end; + + const import_path = file.zir.?.nullTerminatedString(item.data.name); + + if (pt.discoverImport(file.path, import_path)) |res| switch (res) { + .module, .existing_file => {}, + .new_file => |new| { + group.async(io, workerUpdateFile, .{ + comp, new.file, new.index, prog_node, group, + }); + }, + } else |err| switch (err) { + error.OutOfMemory => { + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); + comp.setAllocFailure(); + }, + } + } + } +} +fn workerUpdateEmbedFile(comp: *Compilation, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) void { + const io = comp.io; + const tid: Zcu.PerThread.Id = .acquire(io); + defer tid.release(io); + detectEmbedFileUpdate(comp, tid, ef_index, ef) catch |err| switch (err) { + error.OutOfMemory => { + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); + comp.setAllocFailure(); + }, + }; +} +fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zcu.EmbedFile.Index, ef: *Zcu.EmbedFile) !void { + const io = comp.io; + const zcu = comp.zcu.?; + const pt: Zcu.PerThread = .activate(zcu, tid); + defer pt.deactivate(); + + const old_val = ef.val; + const old_err = ef.err; + + try pt.updateEmbedFile(ef, null); + + if (ef.val != .none and ef.val == old_val) return; // success, value unchanged + if (ef.val == .none and old_val == .none and ef.err == old_err) return; // failure, error unchanged + + comp.mutex.lockUncancelable(io); + defer comp.mutex.unlock(io); + + try zcu.markDependeeOutdated(.not_marked_po, .{ .embed_file = ef_index }); +} + fn deinitFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) void { const zcu = pt.zcu; const gpa = zcu.gpa; @@ -156,8 +470,8 @@ pub fn updateFile( ) !void { dev.check(.ast_gen); - const tracy = trace(@src()); - defer tracy.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); const zcu = pt.zcu; const comp = zcu.comp; @@ -484,7 +798,7 @@ fn cleanupUpdatedFiles(gpa: Allocator, updated_files: *std.AutoArrayHashMapUnman updated_files.deinit(gpa); } -pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { +fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void { assert(pt.tid == .main); const zcu = pt.zcu; const comp = zcu.comp; @@ -566,7 +880,7 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { const old_line = old_zir.getDeclaration(old_inst).src_line; const new_line = new_zir.getDeclaration(new_inst).src_line; if (old_line != new_line) { - try comp.queueJob(.{ .update_line_number = tracked_inst_index }); + try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .debug_update_line_number = tracked_inst_index }); } }, else => {}, @@ -674,11 +988,11 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void { /// Typical Zig compilations begin by claling this function on the root source file of the standard /// library, `lib/std/std.zig`. The resulting namespace scan discovers a `comptime` declaration in /// that file, which is queued for analysis, and everything goes from there. -pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Allocator.Error || Io.Cancelable)!void { +pub fn ensureFilePopulated(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Allocator.Error || Io.Cancelable)!void { dev.check(.sema); - const tracy = trace(@src()); - defer tracy.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); const zcu = pt.zcu; const comp = zcu.comp; @@ -734,8 +1048,8 @@ pub fn ensureMemoizedStateUpToDate( /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. reason: ?*const Zcu.DependencyReason, ) Zcu.SemaError!void { - const tracy = trace(@src()); - defer tracy.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); const zcu = pt.zcu; const gpa = zcu.gpa; @@ -844,8 +1158,8 @@ fn analyzeMemoizedState( /// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is /// free to ignore this, since the error is already registered. pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.SemaError!void { - const tracy = trace(@src()); - defer tracy.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); const zcu = pt.zcu; const gpa = zcu.gpa; @@ -1008,8 +1322,8 @@ pub fn ensureTypeLayoutUpToDate( /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. reason: ?*const Zcu.DependencyReason, ) Zcu.SemaError!void { - const tracy = trace(@src()); - defer tracy.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); const zcu = pt.zcu; const comp = zcu.comp; @@ -1121,8 +1435,8 @@ pub fn ensureNavValUpToDate( /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. reason: ?*const Zcu.DependencyReason, ) Zcu.SemaError!void { - const tracy = trace(@src()); - defer tracy.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); const zcu = pt.zcu; const gpa = zcu.gpa; @@ -1457,12 +1771,20 @@ fn analyzeNavVal( if (!queue_linker_work) break :queue_codegen; if (!nav_ty.hasRuntimeBits(zcu)) { - if (zcu.comp.config.use_llvm) break :queue_codegen; + if (comp.config.use_llvm) break :queue_codegen; if (file.mod.?.strip) break :queue_codegen; } - zcu.comp.link_prog_node.increaseEstimatedTotalItems(1); - try zcu.comp.queueJob(.{ .link_nav = nav_id }); + comp.link_prog_node.increaseEstimatedTotalItems(1); + try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .link_nav = nav_id }); + } + + if (comp.config.is_test and zcu.test_functions.contains(nav_id)) { + // We just analyzed a test function's "value" (essentially its signature); now we need to + // implicitly reference the function *body*. `Zcu.resolveReferences` knows about this rule, + // so we don't need to mark an explicit reference, but we do need to make sure that the test + // body will actually get analyzed! + try zcu.ensureFuncBodyAnalysisQueued(nav_val.toIntern()); } switch (old_nav.status) { @@ -1477,8 +1799,8 @@ pub fn ensureNavTypeUpToDate( /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. reason: ?*const Zcu.DependencyReason, ) Zcu.SemaError!void { - const tracy = trace(@src()); - defer tracy.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); const zcu = pt.zcu; const gpa = zcu.gpa; @@ -1719,8 +2041,8 @@ pub fn ensureFuncBodyUpToDate( ) Zcu.SemaError!void { dev.check(.sema); - const tracy = trace(@src()); - defer tracy.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); const zcu = pt.zcu; const gpa = zcu.gpa; @@ -1846,7 +2168,8 @@ fn analyzeFuncBody( log.debug("analyze and generate fn body {f}", .{zcu.fmtAnalUnit(anal_unit)}); var air = try pt.analyzeFuncBodyInner(func_index, reason); - errdefer air.deinit(gpa); + var air_owned = true; + errdefer if (air_owned) air.deinit(gpa); const ies_outdated = !func.analysisUnordered(ip).inferred_error_set or func.resolvedErrorSetUnordered(ip) != old_resolved_ies; @@ -1856,18 +2179,23 @@ fn analyzeFuncBody( const dump_air = build_options.enable_debug_extensions and comp.verbose_air; const dump_llvm_ir = build_options.enable_debug_extensions and (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null); - if (comp.bin_file == null and zcu.llvm_object == null and !dump_air and !dump_llvm_ir) { - air.deinit(gpa); - return .{ .ies_outdated = ies_outdated }; + if (comp.bin_file != null or zcu.llvm_object != null or dump_air or dump_llvm_ir) { + zcu.codegen_prog_node.increaseEstimatedTotalItems(1); + comp.link_prog_node.increaseEstimatedTotalItems(1); + + // Some linkers need to refer to the AIR. In that case, the linker is not running + // concurrently, so we'll just keep ownership of the AIR for ourselves instead of + // letting the codegen job destroy it. + const disown_air = zcu.backendSupportsFeature(.separate_thread); + + // Begin the codegen task. If the codegen/link queue is backed up, this might + // block until the linker is able to process some tasks. + const codegen_task = try zcu.codegen_task_pool.start(zcu, func_index, &air, disown_air); + if (disown_air) air_owned = false; + + try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .link_func = codegen_task }); } - zcu.codegen_prog_node.increaseEstimatedTotalItems(1); - comp.link_prog_node.increaseEstimatedTotalItems(1); - try comp.queueJob(.{ .codegen_func = .{ - .func = func_index, - .air = air, - } }); - return .{ .ies_outdated = ies_outdated }; } @@ -2121,7 +2449,7 @@ pub fn populateModuleRootTable(pt: Zcu.PerThread) error{ /// modify `pt.zcu.skip_analysis_this_update`. /// /// If an error is returned, `pt.zcu.alive_files` might contain undefined values. -pub fn computeAliveFiles(pt: Zcu.PerThread) Allocator.Error!bool { +fn computeAliveFiles(pt: Zcu.PerThread) Allocator.Error!bool { const zcu = pt.zcu; const comp = zcu.comp; const gpa = zcu.gpa; @@ -2562,8 +2890,8 @@ pub fn scanNamespace( namespace_index: Zcu.Namespace.Index, decls: []const Zir.Inst.Index, ) Allocator.Error!void { - const tracy = trace(@src()); - defer tracy.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); const zcu = pt.zcu; const ip = &zcu.intern_pool; @@ -2659,8 +2987,8 @@ const ScanDeclIter = struct { } fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void { - const tracy = trace(@src()); - defer tracy.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); const pt = iter.pt; const zcu = pt.zcu; @@ -2713,77 +3041,65 @@ const ScanDeclIter = struct { const existing_unit = iter.existing_by_inst.get(tracked_inst); - const unit: AnalUnit, const want_analysis = switch (decl.kind) { - .@"comptime" => unit: { - const cu = if (existing_unit) |eu| - eu.unwrap().@"comptime" - else - try ip.createComptimeUnit(gpa, io, pt.tid, tracked_inst, namespace_index); - + const name = maybe_name.unwrap() orelse { + // Only `comptime` declarations are unnamed. + assert(decl.kind == .@"comptime"); + if (existing_unit) |unit| { + try namespace.comptime_decls.append(gpa, unit.unwrap().@"comptime"); + } else { + const cu = try ip.createComptimeUnit(gpa, io, pt.tid, tracked_inst, namespace_index); + try zcu.queueComptimeUnitAnalysis(cu); try namespace.comptime_decls.append(gpa, cu); + } + return; + }; - if (existing_unit == null) { - // For a `comptime` declaration, whether to analyze is based solely on whether the unit - // is outdated. So, add this fresh one to `outdated` and `outdated_ready`. - try zcu.queueComptimeUnitAnalysis(cu); - } - - break :unit .{ .wrap(.{ .@"comptime" = cu }), true }; - }, - else => unit: { - const name = maybe_name.unwrap().?; - const fqn = try namespace.internFullyQualifiedName(ip, gpa, io, pt.tid, name); - const nav = if (existing_unit) |eu| eu.unwrap().nav_val else nav: { - const nav = try ip.createDeclNav(gpa, io, pt.tid, name, fqn, tracked_inst, namespace_index); - if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newNav(zcu, nav); - break :nav nav; - }; - - const unit: AnalUnit = .wrap(.{ .nav_val = nav }); + const fqn = try namespace.internFullyQualifiedName(ip, gpa, io, pt.tid, name); - assert(ip.getNav(nav).name == name); - assert(ip.getNav(nav).fqn == fqn); + const nav = if (existing_unit) |unit| nav: { + const nav = unit.unwrap().nav_val; + assert(ip.getNav(nav).name == name); + assert(ip.getNav(nav).fqn == fqn); + break :nav nav; + } else nav: { + const nav = try ip.createDeclNav(gpa, io, pt.tid, name, fqn, tracked_inst, namespace_index); + if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newNav(zcu, nav); + break :nav nav; + }; - const want_analysis = switch (decl.kind) { - .@"comptime" => unreachable, - .unnamed_test, .@"test", .decltest => a: { - const is_named = decl.kind != .unnamed_test; - try namespace.test_decls.append(gpa, nav); - // TODO: incremental compilation! - // * remove from `test_functions` if no longer matching filter - // * add to `test_functions` if newly passing filter - // This logic is unaware of incremental: we'll end up with duplicates. - // Perhaps we should add all test indiscriminately and filter at the end of the update. - if (!comp.config.is_test) break :a false; - if (file.mod != zcu.main_mod) break :a false; - if (is_named and comp.test_filters.len > 0) { - const fqn_slice = fqn.toSlice(ip); - for (comp.test_filters) |test_filter| { - if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break; - } else break :a false; - } - try zcu.test_functions.put(gpa, nav, {}); - break :a true; - }, - .@"const", .@"var" => a: { - if (decl.is_pub) { - try namespace.pub_decls.putContext(gpa, nav, {}, .{ .zcu = zcu }); - } else { - try namespace.priv_decls.putContext(gpa, nav, {}, .{ .zcu = zcu }); - } - break :a false; - }, - }; - break :unit .{ unit, want_analysis }; + const want_analysis: bool = switch (decl.kind) { + .@"comptime" => unreachable, + .unnamed_test, .@"test", .decltest => a: { + const is_named = decl.kind != .unnamed_test; + try namespace.test_decls.append(gpa, nav); + // TODO: incremental compilation! + // * remove from `test_functions` if no longer matching filter + // * add to `test_functions` if newly passing filter + // This logic is unaware of incremental: we'll end up with duplicates. + // Perhaps we should add all test indiscriminately and filter at the end of the update. + if (!comp.config.is_test) break :a false; + if (file.mod != zcu.main_mod) break :a false; + if (is_named and comp.test_filters.len > 0) { + const fqn_slice = fqn.toSlice(ip); + for (comp.test_filters) |test_filter| { + if (std.mem.indexOf(u8, fqn_slice, test_filter) != null) break; + } else break :a false; + } + try zcu.test_functions.put(gpa, nav, {}); + break :a true; + }, + .@"const", .@"var" => a: { + if (decl.is_pub) { + try namespace.pub_decls.putContext(gpa, nav, {}, .{ .zcu = zcu }); + } else { + try namespace.priv_decls.putContext(gpa, nav, {}, .{ .zcu = zcu }); + } + break :a false; }, }; - if (existing_unit == null and (want_analysis or decl.linkage == .@"export")) { - log.debug( - "scanDecl queue analyze_unit file='{s}' unit={f}", - .{ namespace.fileScope(zcu).sub_file_path, zcu.fmtAnalUnit(unit) }, - ); - try comp.queueJob(.{ .analyze_unit = unit }); + if (want_analysis or decl.linkage == .@"export") { + try zcu.ensureNavValAnalysisQueued(nav); } } }; @@ -2793,8 +3109,8 @@ fn analyzeFuncBodyInner( func_index: InternPool.Index, reason: ?*const Zcu.DependencyReason, ) Zcu.SemaError!Air { - const tracy = trace(@src()); - defer tracy.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); const zcu = pt.zcu; const comp = zcu.comp; @@ -3437,36 +3753,45 @@ pub fn intern(pt: Zcu.PerThread, key: InternPool.Key) Allocator.Error!InternPool /// Essentially a shortcut for calling `intern_pool.getCoerced`. /// However, this function also allows coercing `extern`s. The `InternPool` function can't do -/// this because it requires potentially pushing to the job queue. +/// this because it requires potentially queueing a link task. pub fn getCoerced(pt: Zcu.PerThread, val: Value, new_ty: Type) Allocator.Error!Value { const ip = &pt.zcu.intern_pool; const comp = pt.zcu.comp; const gpa = comp.gpa; const io = comp.io; switch (ip.indexToKey(val.toIntern())) { - .@"extern" => |e| { - const coerced = try pt.getExtern(.{ - .name = e.name, + .@"extern" => |@"extern"| { + // TODO: it's awkward to make this function cancelable. The problem is really that + // `getCoerced` is a bad API: it should be replaced with smaller, more specialized + // functions, so that this cancel point is only possible in the rare case that you + // may actually need to coerce an extern! + const old_prot = io.swapCancelProtection(.blocked); + defer _ = io.swapCancelProtection(old_prot); + const coerced = pt.getExtern(.{ + .name = @"extern".name, .ty = new_ty.toIntern(), - .lib_name = e.lib_name, - .is_const = e.is_const, - .is_threadlocal = e.is_threadlocal, - .linkage = e.linkage, - .visibility = e.visibility, - .is_dll_import = e.is_dll_import, - .relocation = e.relocation, - .decoration = e.decoration, - .alignment = e.alignment, - .@"addrspace" = e.@"addrspace", - .zir_index = e.zir_index, + .lib_name = @"extern".lib_name, + .is_const = @"extern".is_const, + .is_threadlocal = @"extern".is_threadlocal, + .linkage = @"extern".linkage, + .visibility = @"extern".visibility, + .is_dll_import = @"extern".is_dll_import, + .relocation = @"extern".relocation, + .decoration = @"extern".decoration, + .alignment = @"extern".alignment, + .@"addrspace" = @"extern".@"addrspace", + .zir_index = @"extern".zir_index, .owner_nav = undefined, // ignored by `getExtern`. - .source = e.source, - }); - return Value.fromInterned(coerced); + .source = @"extern".source, + }) catch |err| switch (err) { + error.Canceled => unreachable, // blocked above + error.OutOfMemory => |e| return e, + }; + return .fromInterned(coerced); }, else => {}, } - return Value.fromInterned(try ip.getCoerced(gpa, io, pt.tid, val.toIntern(), new_ty.toIntern())); + return .fromInterned(try ip.getCoerced(gpa, io, pt.tid, val.toIntern(), new_ty.toIntern())); } pub fn intType(pt: Zcu.PerThread, signedness: std.builtin.Signedness, bits: u16) Allocator.Error!Type { @@ -3865,14 +4190,15 @@ pub fn navPtrType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Allocator.Err /// Intern an `.@"extern"`, creating a corresponding owner `Nav` if necessary. /// If necessary, the new `Nav` is queued for codegen. /// `key.owner_nav` is ignored and may be `undefined`. -pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) Allocator.Error!InternPool.Index { +pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) (Io.Cancelable || Allocator.Error)!InternPool.Index { const zcu = pt.zcu; const comp = zcu.comp; + Type.fromInterned(key.ty).assertHasLayout(zcu); const result = try zcu.intern_pool.getExtern(comp.gpa, comp.io, pt.tid, key); if (result.new_nav.unwrap()) |nav| { - comp.link_prog_node.increaseEstimatedTotalItems(1); - try comp.queueJob(.{ .link_nav = nav }); if (comp.debugIncremental()) try zcu.incremental_debug_state.newNav(zcu, nav); + comp.link_prog_node.increaseEstimatedTotalItems(1); + try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .link_nav = nav }); } return result.index; } -- 2.54.0 From 6402e119e8d21403cbafc4a6c8ca353b894592ba Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Fri, 13 Feb 2026 09:31:36 +0000 Subject: [PATCH 46/79] Zcu: prioritize analyzing function bodies ...so that they can be sent to the codegen backend and linker ASAP. --- src/Zcu.zig | 88 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 25 deletions(-) diff --git a/src/Zcu.zig b/src/Zcu.zig index 658a6513a84d4236095ccc5e5b46b5392d9748cb..481ea0d62ad312d3a0e9ce5f6d84f8ea13635841 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -275,10 +275,16 @@ potentially_outdated: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .empty, /// Value is the number of PO dependencies of this AnalUnit. /// Once this value drops to 0, the AnalUnit is a candidate for re-analysis. outdated: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .empty, -/// This contains all `AnalUnit`s in `outdated` whose PO dependency count is 0. +/// This is the set of all `AnalUnit`s in `outdated` whose PO dependency count is 0. /// Such `AnalUnit`s are ready for immediate re-analysis. /// See `findOutdatedToAnalyze` for details. -outdated_ready: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .empty, +outdated_ready: struct { + /// These are separate from other units because it allows `findOutdatedToAnalyze` to prioritize + /// functions, which is useful because it means they will be sent to codegen more quickly. + funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), + /// Does not contain `.func` units. + other: std.AutoArrayHashMapUnmanaged(AnalUnit, void), +} = .{ .funcs = .empty, .other = .empty }, /// This contains a list of AnalUnit whose analysis or codegen failed, but the /// failure was something like running out of disk space, and trying again may /// succeed. On the next update, we will flush this list, marking all members of @@ -2835,7 +2841,8 @@ pub fn deinit(zcu: *Zcu) void { zcu.potentially_outdated.deinit(gpa); zcu.outdated.deinit(gpa); - zcu.outdated_ready.deinit(gpa); + zcu.outdated_ready.funcs.deinit(gpa); + zcu.outdated_ready.other.deinit(gpa); zcu.retryable_failures.deinit(gpa); zcu.test_functions.deinit(gpa); @@ -3065,6 +3072,7 @@ pub fn markDependeeOutdated( marked_po: enum { not_marked_po, marked_po }, dependee: InternPool.Dependee, ) !void { + const gpa = zcu.comp.gpa; deps_log.debug("outdated dependee: {f}", .{zcu.fmtDependee(dependee)}); var it = zcu.intern_pool.dependencyIterator(dependee); if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); @@ -3078,7 +3086,10 @@ pub fn markDependeeOutdated( deps_log.debug("outdated {f} => already outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* }); if (po_dep_count.* == 0) { deps_log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); - try zcu.outdated_ready.put(zcu.gpa, depender, {}); + switch (depender.unwrap()) { + .func => |func| try zcu.outdated_ready.funcs.put(gpa, func, {}), + else => try zcu.outdated_ready.other.put(gpa, depender, {}), + } } }, } @@ -3094,14 +3105,17 @@ pub fn markDependeeOutdated( }, }; try zcu.outdated.putNoClobber( - zcu.gpa, + gpa, depender, new_po_dep_count, ); deps_log.debug("outdated {f} => new outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), new_po_dep_count }); if (new_po_dep_count == 0) { deps_log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); - try zcu.outdated_ready.put(zcu.gpa, depender, {}); + switch (depender.unwrap()) { + .func => |func| try zcu.outdated_ready.funcs.put(gpa, func, {}), + else => try zcu.outdated_ready.other.put(gpa, depender, {}), + } } // If this is a Decl and was not previously PO, we must recursively // mark dependencies on its tyval as PO. @@ -3119,6 +3133,7 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { } /// Assumes that `zcu.outdated_lock` is already held exclusively. fn markPoDependeeUpToDateInner(zcu: *Zcu, dependee: InternPool.Dependee) !void { + const gpa = zcu.comp.gpa; deps_log.debug("up-to-date dependee: {f}", .{zcu.fmtDependee(dependee)}); var it = zcu.intern_pool.dependencyIterator(dependee); while (it.next()) |depender| { @@ -3129,7 +3144,10 @@ fn markPoDependeeUpToDateInner(zcu: *Zcu, dependee: InternPool.Dependee) !void { deps_log.debug("up-to-date {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* }); if (po_dep_count.* == 0) { deps_log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)}); - try zcu.outdated_ready.put(zcu.gpa, depender, {}); + switch (depender.unwrap()) { + .func => |func| try zcu.outdated_ready.funcs.put(gpa, func, {}), + else => try zcu.outdated_ready.other.put(gpa, depender, {}), + } } continue; } @@ -3167,7 +3185,8 @@ fn markPoDependeeUpToDateInner(zcu: *Zcu, dependee: InternPool.Dependee) !void { /// in turn be PO, due to a dependency on the original AnalUnit's tyval or IES. /// /// Assumes that `zcu.outdated_lock` is already held exclusively. -fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUnit) !void { +fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUnit) Allocator.Error!void { + const gpa = zcu.comp.gpa; const ip = &zcu.intern_pool; const dependee: InternPool.Dependee = switch (maybe_outdated.unwrap()) { .@"comptime" => return, // analysis of a comptime decl can't outdate any dependencies @@ -3181,10 +3200,12 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni var it = ip.dependencyIterator(dependee); while (it.next()) |po| { if (zcu.outdated.getPtr(po)) |po_dep_count| { - // This dependency is already outdated, but it now has one more PO - // dependency. + // This dependency is already outdated, but it now has one more PO dependency. if (po_dep_count.* == 0) { - _ = zcu.outdated_ready.swapRemove(po); + switch (po.unwrap()) { + .func => |func| _ = zcu.outdated_ready.funcs.swapRemove(func), + else => _ = zcu.outdated_ready.other.swapRemove(po), + } } po_dep_count.* += 1; deps_log.debug("po {f} => {f} [outdated] po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), po_dep_count.* }); @@ -3196,7 +3217,7 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni deps_log.debug("po {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), n.* }); continue; } - try zcu.potentially_outdated.putNoClobber(zcu.gpa, po, 1); + try zcu.potentially_outdated.putNoClobber(gpa, po, 1); deps_log.debug("po {f} => {f} po_deps=1", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po) }); // This AnalUnit was not already PO, so we must recursively mark its dependers as also PO. try zcu.markTransitiveDependersPotentiallyOutdated(po); @@ -3208,10 +3229,20 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni /// recursive analysis (all of its previously-marked dependencies are already up-to-date), because /// recursive analysis can cause over-analysis on incremental updates. pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { - // MLUGG TODO: priorize `func` units, just like we used to do in the Compilation job queue. + // We prioritize functions, because the sooner they get analyzed, the sooner they can be send to + // the codegen backend and linker, which are usually running in parallel (so this can increase + // parallelism). + // TODO: perhaps we should also experiment with *avoiding* functions if the codegen/link queue + // is backed up (for instance due to a very large function). That could help minimize blocking + // on the main thread in `CodegenTaskPool.start` waiting for the linker to catch up. + if (zcu.outdated_ready.funcs.count() > 0) { + const unit: AnalUnit = .wrap(.{ .func = zcu.outdated_ready.funcs.keys()[0] }); + log.debug("findOutdatedToAnalyze: {f}", .{zcu.fmtAnalUnit(unit)}); + return unit; + } - if (zcu.outdated_ready.count() > 0) { - const unit = zcu.outdated_ready.keys()[0]; + if (zcu.outdated_ready.other.count() > 0) { + const unit = zcu.outdated_ready.other.keys()[0]; log.debug("findOutdatedToAnalyze: {f}", .{zcu.fmtAnalUnit(unit)}); return unit; } @@ -3502,13 +3533,12 @@ pub fn ensureFuncBodyAnalysisQueued(zcu: *Zcu, func: InternPool.Index) !void { assert(func == ip.unwrapCoercedFunc(func)); // analyze the body of the original function, not a coerced one if (ip.setWantRuntimeFnAnalysis(io, func)) { // This is the first reference to this function, so we must ensure it will be analyzed. - const unit: AnalUnit = .wrap(.{ .func = func }); if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(zcu.comp.io); try zcu.outdated.ensureUnusedCapacity(gpa, 1); - try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); - zcu.outdated.putAssumeCapacityNoClobber(unit, 0); - zcu.outdated_ready.putAssumeCapacityNoClobber(unit, {}); + try zcu.outdated_ready.funcs.ensureUnusedCapacity(gpa, 1); + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .func = func }), 0); + zcu.outdated_ready.funcs.putAssumeCapacityNoClobber(func, {}); } } @@ -3522,11 +3552,11 @@ pub fn ensureNavValAnalysisQueued(zcu: *Zcu, nav: InternPool.Nav.Index) !void { if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(zcu.comp.io); try zcu.outdated.ensureUnusedCapacity(gpa, 2); - try zcu.outdated_ready.ensureUnusedCapacity(gpa, 2); + try zcu.outdated_ready.other.ensureUnusedCapacity(gpa, 2); zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .nav_val = nav }), 0); zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .nav_ty = nav }), 0); - zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .nav_val = nav }), {}); - zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .nav_ty = nav }), {}); + zcu.outdated_ready.other.putAssumeCapacityNoClobber(.wrap(.{ .nav_val = nav }), {}); + zcu.outdated_ready.other.putAssumeCapacityNoClobber(.wrap(.{ .nav_ty = nav }), {}); } } @@ -3540,9 +3570,9 @@ pub fn queueComptimeUnitAnalysis(zcu: *Zcu, cu: InternPool.ComptimeUnit.Id) Allo if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(io); defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(io); try zcu.outdated.ensureUnusedCapacity(gpa, 1); - try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1); + try zcu.outdated_ready.other.ensureUnusedCapacity(gpa, 1); zcu.outdated.putAssumeCapacityNoClobber(unit, 0); - zcu.outdated_ready.putAssumeCapacityNoClobber(unit, {}); + zcu.outdated_ready.other.putAssumeCapacityNoClobber(unit, {}); } /// If `unit` was marked as outdated or porentially outdated, clears that status and returns `true`. @@ -3552,7 +3582,15 @@ pub fn clearOutdatedState(zcu: *Zcu, unit: AnalUnit) bool { if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(io); defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(io); if (zcu.outdated.fetchSwapRemove(unit)) |kv| { - if (kv.value == 0) assert(zcu.outdated_ready.swapRemove(unit)); + const was_ready = switch (unit.unwrap()) { + .func => |func| zcu.outdated_ready.funcs.swapRemove(func), + else => zcu.outdated_ready.other.swapRemove(unit), + }; + if (kv.value == 0) { + assert(was_ready); + } else { + assert(!was_ready); + } return true; } else if (zcu.potentially_outdated.swapRemove(unit)) { return true; -- 2.54.0 From 2b8feabb8f2b3a3c96d2d8e74393e0c8dfa17390 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Fri, 13 Feb 2026 11:48:56 +0000 Subject: [PATCH 47/79] llvm: some more improvements to debug info Most importantly, adds support for `DW_TAG_typedef` to `llvm.Builder`, and uses it to define error sets and optional pointers/errors. Also deletes some random dead code I found. --- lib/std/zig/llvm/Builder.zig | 58 ++++++++ src/codegen/llvm.zig | 257 ++++++++++++----------------------- 2 files changed, 142 insertions(+), 173 deletions(-) diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index 81b99c25725a20f0bbb7ed61ac611974e98d6dac..f40b63c85fdb0536b7b75cc9915de558d0f105fb 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -8021,6 +8021,7 @@ pub const Metadata = packed struct(u32) { composite_vector_type, derived_pointer_type, derived_member_type, + derived_typedef_type, subroutine_type, enumerator_unsigned, enumerator_signed_positive, @@ -8064,6 +8065,7 @@ pub const Metadata = packed struct(u32) { .composite_vector_type, .derived_pointer_type, .derived_member_type, + .derived_typedef_type, .subroutine_type, .enumerator_unsigned, .enumerator_signed_positive, @@ -10463,15 +10465,18 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void }, .derived_pointer_type, .derived_member_type, + .derived_typedef_type, => |kind| { const extra = self.metadataExtraData(Metadata.DerivedType, metadata_item.data); try metadata_formatter.specialized(.@"!", .DIDerivedType, .{ .tag = @as(enum { DW_TAG_pointer_type, DW_TAG_member, + DW_TAG_typedef, }, switch (kind) { .derived_pointer_type => .DW_TAG_pointer_type, .derived_member_type => .DW_TAG_member, + .derived_typedef_type => .DW_TAG_typedef, else => unreachable, }), .name = extra.name, @@ -12360,6 +12365,30 @@ pub fn debugMemberType( ); } +pub fn debugTypedefType( + self: *Builder, + name: ?Metadata.String, + file: ?Metadata, + scope: ?Metadata, + line: u32, + underlying_type: ?Metadata, + size_in_bits: u64, + align_in_bits: u64, + offset_in_bits: u64, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.DerivedType, 0); + return self.debugTypedefTypeAssumeCapacity( + name, + file, + scope, + line, + underlying_type, + size_in_bits, + align_in_bits, + offset_in_bits, + ); +} + pub fn debugSubroutineType(self: *Builder, types_tuple: ?Metadata) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.SubroutineType, 0); return self.debugSubroutineTypeAssumeCapacity(types_tuple); @@ -12875,6 +12904,33 @@ fn debugMemberTypeAssumeCapacity( }); } +fn debugTypedefTypeAssumeCapacity( + self: *Builder, + name: ?Metadata.String, + file: ?Metadata, + scope: ?Metadata, + line: u32, + underlying_type: ?Metadata, + size_in_bits: u64, + align_in_bits: u64, + offset_in_bits: u64, +) Metadata { + assert(!self.strip); + return self.metadataSimpleAssumeCapacity(.derived_typedef_type, Metadata.DerivedType{ + .name = .wrap(name), + .file = .wrap(file), + .scope = .wrap(scope), + .line = line, + .underlying_type = .wrap(underlying_type), + .size_in_bits_lo = @truncate(size_in_bits), + .size_in_bits_hi = @truncate(size_in_bits >> 32), + .align_in_bits_lo = @truncate(align_in_bits), + .align_in_bits_hi = @truncate(align_in_bits >> 32), + .offset_in_bits_lo = @truncate(offset_in_bits), + .offset_in_bits_hi = @truncate(offset_in_bits >> 32), + }); +} + fn debugSubroutineTypeAssumeCapacity(self: *Builder, types_tuple: ?Metadata) Metadata { assert(!self.strip); return self.metadataSimpleAssumeCapacity(.subroutine_type, Metadata.SubroutineType{ @@ -14223,12 +14279,14 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco }, .derived_pointer_type, .derived_member_type, + .derived_typedef_type, => |kind| { const extra = self.metadataExtraData(Metadata.DerivedType, data); try metadata_block.writeAbbrevAdapted(MetadataBlock.DerivedType{ .tag = switch (kind) { .derived_pointer_type => DW.TAG.pointer_type, .derived_member_type => DW.TAG.member, + .derived_typedef_type => DW.TAG.typedef, else => unreachable, }, .name = extra.name, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 185dcb0fe1702e632661b49b8c1d80250c5a7b4a..5735fe5e51a665a46e965cd3f01a26bdb57ac094 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1914,6 +1914,15 @@ pub const Object = struct { const name = try o.builder.metadataStringFmt("{f}", .{ty.fmt(pt)}); + // lldb cannot handle non-byte-sized types, so in the logic below, bit sizes are padded up. + // For instance, `bool` is considered to be 8 bits, and `u60` is considered to be 64 bits. + + // I tried using variants (DW_TAG_variant_part + DW_TAG_variant) to encode error unions, + // tagged unions, etc; this would have told debuggers which field was active, which could + // improve UX significantly. GDB handles this perfectly fine, but unfortunately, LLDB has no + // handling for variants at all, and will never print fields in them, so I opted not to use + // them for now. + switch (ty.zigTypeTag(zcu)) { .void, .noreturn, @@ -1925,23 +1934,19 @@ pub const Object = struct { .enum_literal, => return o.builder.debugSignedType(name, 0), + .float => return o.builder.debugFloatType(name, ty.floatBits(target)), + + .bool => return o.builder.debugBoolType(name, 8), + .int => { const info = ty.intInfo(zcu); - const bits = ty.abiSize(zcu) * 8; // lldb cannot handle non-byte sized types + const bits = ty.abiSize(zcu) * 8; return switch (info.signedness) { .signed => try o.builder.debugSignedType(name, bits), .unsigned => try o.builder.debugUnsignedType(name, bits), }; }, - .float => { - return o.builder.debugFloatType(name, ty.floatBits(target)); - }, - .bool => { - return o.builder.debugBoolType( - name, - 8, // lldb cannot handle non-byte sized types - ); - }, + .pointer => { const ptr_size = Type.ptrAbiSize(zcu.getTarget()); const ptr_align = Type.ptrAbiAlignment(zcu.getTarget()); @@ -1949,20 +1954,20 @@ pub const Object = struct { if (ty.isSlice(zcu)) { const debug_ptr_type = try o.builder.debugMemberType( try o.builder.metadataString("ptr"), - null, // File + null, // file ty_fwd_ref, - 0, // Line + 0, // line try o.getDebugType(pt, ty.slicePtrFieldType(zcu)), ptr_size * 8, ptr_align.toByteUnits().? * 8, - 0, // Offset + 0, // offset ); const debug_len_type = try o.builder.debugMemberType( try o.builder.metadataString("len"), - null, // File + null, // file ty_fwd_ref, - 0, // Line + 0, // line try o.getDebugType(pt, .usize), ptr_size * 8, ptr_align.toByteUnits().? * 8, @@ -1971,10 +1976,10 @@ pub const Object = struct { return o.builder.debugStructType( name, - null, // File - o.debug_compile_unit.unwrap().?, // Scope - 0, // Line - null, // Underlying type + null, // file + o.debug_compile_unit.unwrap().?, // scope + 0, // line + null, // underlying type ptr_size * 2 * 8, ptr_align.toByteUnits().? * 8, try o.builder.metadataTuple(&.{ @@ -1986,36 +1991,34 @@ pub const Object = struct { return o.builder.debugPointerType( name, - null, // File - null, // Scope - 0, // Line + null, // file + o.debug_compile_unit.unwrap().?, // scope + 0, // line try o.getDebugType(pt, ty.childType(zcu)), ptr_size * 8, ptr_align.toByteUnits().? * 8, - 0, // Offset - ); - }, - .array => { - return o.builder.debugArrayType( - null, // Name - null, // File - null, // Scope - 0, // Line - try o.getDebugType(pt, ty.childType(zcu)), - ty.abiSize(zcu) * 8, - (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, - try o.builder.metadataTuple(&.{ - try o.builder.debugSubrange( - try o.builder.metadataConstant(try o.builder.intConst(.i64, 0)), - try o.builder.metadataConstant(try o.builder.intConst(.i64, ty.arrayLen(zcu))), - ), - }), + 0, // offset ); }, + .array => return o.builder.debugArrayType( + name, + null, // file + o.debug_compile_unit.unwrap().?, // scope + 0, // line + try o.getDebugType(pt, ty.childType(zcu)), + ty.abiSize(zcu) * 8, + ty.abiAlignment(zcu).toByteUnits().? * 8, + try o.builder.metadataTuple(&.{ + try o.builder.debugSubrange( + try o.builder.metadataConstant(try o.builder.intConst(.i64, 0)), + try o.builder.metadataConstant(try o.builder.intConst(.i64, ty.arrayLen(zcu))), + ), + }), + ), .vector => { const elem_ty = ty.childType(zcu); // Vector elements cannot be padded since that would make - // @bitSizOf(elem) * len > @bitSizOf(vec). + // @bitSizeOf(elem) * len > @bitSizOf(vec). // Neither gdb nor lldb seem to be able to display non-byte sized // vectors properly. const debug_elem_type = switch (elem_ty.zigTypeTag(zcu)) { @@ -2027,18 +2030,19 @@ pub const Object = struct { }; }, .bool => try o.builder.debugBoolType(try o.builder.metadataString("bool"), 1), + // We don't pad pointers or floats, so we can lower those normally. .pointer, .optional, .float => try o.getDebugType(pt, elem_ty), else => unreachable, }; return o.builder.debugVectorType( - null, // Name - null, // File - null, // Scope - 0, // Line + name, + null, // file + o.debug_compile_unit.unwrap().?, // scope + 0, // line debug_elem_type, ty.abiSize(zcu) * 8, - (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, + ty.abiAlignment(zcu).toByteUnits().? * 8, try o.builder.metadataTuple(&.{ try o.builder.debugSubrange( try o.builder.metadataConstant(try o.builder.intConst(.i64, 0)), @@ -2050,26 +2054,15 @@ pub const Object = struct { .optional => { const payload_ty = ty.optionalChild(zcu); if (ty.optionalReprIsPayload(zcu)) { - // MLUGG TODO: these should use DW_TAG_typedef instead, but std.zig.llvm.Builder currently lacks support for those. - const payload_member = try o.builder.debugMemberType( - try o.builder.metadataString("payload"), - null, // file - ty_fwd_ref, - 0, // line - try o.getDebugType(pt, .anyerror), - ty.abiSize(zcu) * 8, - ty.abiAlignment(zcu).toByteUnits().? * 8, - 0, // offset - ); - return o.builder.debugStructType( + return o.builder.debugTypedefType( name, null, // file o.debug_compile_unit.unwrap().?, // scope 0, // line - null, // underlying type + try o.getDebugType(pt, payload_ty), ty.abiSize(zcu) * 8, ty.abiAlignment(zcu).toByteUnits().? * 8, - try o.builder.metadataTuple(&.{payload_member}), + 0, // offset ); } @@ -2083,7 +2076,7 @@ pub const Object = struct { const debug_payload_type = try o.builder.debugMemberType( try o.builder.metadataString("payload"), null, // file - ty_fwd_ref, + ty_fwd_ref, // scope 0, // line try o.getDebugType(pt, payload_ty), payload_size * 8, @@ -2104,12 +2097,12 @@ pub const Object = struct { return o.builder.debugStructType( name, - null, // File - o.debug_compile_unit.unwrap().?, // Scope - 0, // Line - null, // Underlying type + null, // file + o.debug_compile_unit.unwrap().?, // scope + 0, // line + null, // underlying type ty.abiSize(zcu) * 8, - (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8, + ty.abiAlignment(zcu).toByteUnits().? * 8, try o.builder.metadataTuple(&.{ debug_payload_type, debug_some_type, @@ -2125,30 +2118,29 @@ pub const Object = struct { const payload_size = payload_ty.abiSize(zcu); const payload_align = payload_ty.abiAlignment(zcu); - const error_index: u1, const payload_index: u1, const error_offset: u64, const payload_offset: u64 = fields: { + const error_offset: u64, const payload_offset: u64 = offsets: { if (error_align.compare(.gt, payload_align)) { - break :fields .{ 0, 1, 0, payload_align.forward(error_size) }; + break :offsets .{ 0, payload_align.forward(error_size) }; } else { - break :fields .{ 1, 0, error_align.forward(payload_size), 0 }; + break :offsets .{ error_align.forward(payload_size), 0 }; } }; - var fields: [2]Builder.Metadata = undefined; - fields[error_index] = try o.builder.debugMemberType( + const error_field = try o.builder.debugMemberType( try o.builder.metadataString("error"), - null, // File + null, // file ty_fwd_ref, - 0, // Line + 0, // line try o.getDebugType(pt, error_ty), error_size * 8, error_align.toByteUnits().? * 8, error_offset * 8, ); - fields[payload_index] = try o.builder.debugMemberType( + const payload_field = try o.builder.debugMemberType( try o.builder.metadataString("payload"), - null, // File - ty_fwd_ref, - 0, // Line + null, // file + ty_fwd_ref, // scope + 0, // line try o.getDebugType(pt, payload_ty), payload_size * 8, payload_align.toByteUnits().? * 8, @@ -2163,33 +2155,22 @@ pub const Object = struct { null, // Underlying type ty.abiSize(zcu) * 8, ty.abiAlignment(zcu).toByteUnits().? * 8, - try o.builder.metadataTuple(&fields), + try o.builder.metadataTuple(&.{ error_field, payload_field }), ); }, .error_set => { assert(ty.toIntern() != .anyerror_type); // handled specially in `updateConst`; will be populated by `emit` instead // Error sets are just named wrappers around `anyerror`. - // MLUGG TODO: these should use DW_TAG_typedef instead, but std.zig.llvm.Builder currently lacks support for those. - const anyerror_member = try o.builder.debugMemberType( - try o.builder.metadataString("error"), + return o.builder.debugTypedefType( + name, null, // file - ty_fwd_ref, + o.debug_compile_unit.unwrap().?, // scope 0, // line try o.getDebugType(pt, .anyerror), ty.abiSize(zcu) * 8, ty.abiAlignment(zcu).toByteUnits().? * 8, 0, // offset ); - return o.builder.debugStructType( - name, - null, // file - o.debug_compile_unit.unwrap().?, // scope - 0, // line - null, // underlying type - ty.abiSize(zcu) * 8, - ty.abiAlignment(zcu).toByteUnits().? * 8, - try o.builder.metadataTuple(&.{anyerror_member}), - ); }, .@"fn" => { if (!ty.fnHasRuntimeBits(zcu)) { @@ -2570,14 +2551,22 @@ pub const Object = struct { const error_set_bits = zcu.errorSetBits(); const error_names = ip.global_error_set.getNamesFromMainThread(); - const enumerators = try gpa.alloc(Builder.Metadata, error_names.len); + const enumerators = try gpa.alloc(Builder.Metadata, error_names.len + 1); defer gpa.free(enumerators); - for (enumerators, error_names, 1..) |*out, error_name, error_value| { + // The value 0 means "no error" in optionals and error unions. + enumerators[0] = try o.builder.debugEnumerator( + try o.builder.metadataString("null"), + true, // unsigned, + error_set_bits, + .{ .limbs = &.{0}, .positive = true }, // zero + ); + + for (enumerators[1..], error_names, 1..) |*out, error_name, error_value| { var space: Value.BigIntSpace = undefined; var bigint: std.math.big.int.Mutable = .init(&space.limbs, error_value); out.* = try o.builder.debugEnumerator( - try o.builder.metadataString(error_name.toSlice(ip)), + try o.builder.metadataStringFmt("error.{f}", .{error_name.fmtId(ip)}), true, // unsigned error_set_bits, bigint.toConst(), @@ -3452,84 +3441,6 @@ pub const Object = struct { ); } - fn lowerValueToInt(o: *Object, pt: Zcu.PerThread, llvm_int_ty: Builder.Type, arg_val: InternPool.Index) Error!Builder.Constant { - const zcu = pt.zcu; - const ip = &zcu.intern_pool; - const target = zcu.getTarget(); - - const val = Value.fromInterned(arg_val); - const val_key = ip.indexToKey(val.toIntern()); - - if (val.isUndef(zcu)) return o.builder.undefConst(llvm_int_ty); - - const ty = Type.fromInterned(val_key.typeOf()); - switch (val_key) { - .@"extern" => |@"extern"| { - const function_index = try o.resolveLlvmFunction(pt, @"extern".owner_nav); - const ptr = function_index.ptrConst(&o.builder).global.toConst(); - return o.builder.convConst(ptr, llvm_int_ty); - }, - .func => |func| { - const function_index = try o.resolveLlvmFunction(pt, func.owner_nav); - const ptr = function_index.ptrConst(&o.builder).global.toConst(); - return o.builder.convConst(ptr, llvm_int_ty); - }, - .ptr => return o.builder.convConst(try o.lowerPtr(pt, arg_val, 0), llvm_int_ty), - .aggregate => switch (ip.indexToKey(ty.toIntern())) { - .struct_type, .vector_type => {}, - else => unreachable, - }, - .un => |un| { - const layout = ty.unionGetLayout(zcu); - if (layout.payload_size == 0) return o.lowerValue(pt, un.tag); - - const union_obj = zcu.typeToUnion(ty).?; - const container_layout = union_obj.layout; - - assert(container_layout == .@"packed"); - - var need_unnamed = false; - if (un.tag == .none) { - assert(layout.tag_size == 0); - const union_val = try o.lowerValueToInt(pt, llvm_int_ty, un.val); - - need_unnamed = true; - return union_val; - } - const field_index = zcu.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?; - const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBits(zcu)) return o.builder.intConst(llvm_int_ty, 0); - return o.lowerValueToInt(pt, llvm_int_ty, un.val); - }, - .simple_value => |simple_value| switch (simple_value) { - .false, .true => {}, - else => unreachable, - }, - .int, - .float, - .enum_tag, - => {}, - .opt => {}, // pointer like optional expected - else => unreachable, - } - var stack = std.heap.stackFallback(32, o.gpa); - const allocator = stack.get(); - - const bits: usize = @intCast(ty.bitSize(zcu)); - - const buffer = try allocator.alloc(u8, (bits + 7) / 8); - defer allocator.free(buffer); - const limbs = try allocator.alloc(std.math.big.Limb, std.math.big.int.calcTwosCompLimbCount(bits)); - defer allocator.free(limbs); - - val.writeToPackedMemory(pt, buffer, 0) catch unreachable; - - var big: std.math.big.int.Mutable = .init(limbs, 0); - big.readTwosComplement(buffer, bits, target.cpu.arch.endian(), .unsigned); - - return o.builder.bigIntConst(llvm_int_ty, big.toConst()); - } - fn lowerValue(o: *Object, pt: Zcu.PerThread, arg_val: InternPool.Index) Error!Builder.Constant { const zcu = pt.zcu; const ip = &zcu.intern_pool; -- 2.54.0 From 5cc12da1c0b9e516e356d4d13c48ae671d2e17ff Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Thu, 19 Feb 2026 13:05:25 +0000 Subject: [PATCH 48/79] cbe: rework CType and other major refactors The goal of these changes is to allow the C backend to support the new lazier type resolution system implemented by the frontend. This required a full rewrite of the `CType` abstraction, and major changes to the C backend "linker". The `DebugConstPool` abstraction introduced in a previous commit turns out to be useful for the C backend to codegen types. Because this use case is not debug information but rather general linking (albeit when targeting an unusual object format), I have renamed the abstraction to `ConstPool`. With it, the C linker is told when a type's layout becomes known, and can at that point generate the corresponding C definitions, rather than deferring this work until `flush`. The work done in `flush` is now more-or-less *solely* focused on collecting all of the buffers into a big array for a vectored write. This does unfortunately involve a non-trivial graph traversal to emit type definitions in an appropriate order, but it's still quite fast in practice, and it operates on fairly compact dependency data. We don't generate the actual type *definitions* in `flush`; that happens during compilation using `ConstPool` as discussed above. (We do generate the typedefs for underaligned types in `flush`, but that's a trivial amount of work in most cases.) `CType` is now an ephemeral type: it is created only when we render a type (the logic for which has been pushed into just 2 or 3 functions in `codegen.c`---most of the backend now operates on unmolested Zig `Type`s instead). C types are no longer stored in a "pool", although the type "dependencies" of generated C code (that is, the struct, unions, and typedefs which the generated code references) are tracked (in some simple hash sets) and given to the linker so it can codegen the types. --- lib/zig.h | 2 +- src/Compilation.zig | 3 - src/InternPool.zig | 2 +- src/Type.zig | 4 +- src/Value.zig | 8 +- src/Zcu.zig | 4 +- src/codegen/c.zig | 5289 +++++++---------- src/codegen/c/Type.zig | 3471 ----------- src/codegen/c/type.zig | 1013 ++++ src/codegen/c/type/render_defs.zig | 651 ++ src/codegen/llvm.zig | 32 +- src/link.zig | 4 +- src/link/C.zig | 1891 ++++-- .../{DebugConstPool.zig => ConstPool.zig} | 70 +- src/link/Dwarf.zig | 37 +- src/link/Elf.zig | 11 - 16 files changed, 5299 insertions(+), 7193 deletions(-) delete mode 100644 src/codegen/c/Type.zig create mode 100644 src/codegen/c/type.zig create mode 100644 src/codegen/c/type/render_defs.zig rename src/link/{DebugConstPool.zig => ConstPool.zig} (83%) diff --git a/lib/zig.h b/lib/zig.h index 81a815ab5568b57f5d48c8da91a04b761d4f9a2a..f8744966c68276a8e160e77eb186d08f54caa8cb 100644 --- a/lib/zig.h +++ b/lib/zig.h @@ -259,7 +259,7 @@ #endif #if zig_has_attribute(packed) || defined(zig_tinyc) -#define zig_packed(definition) __attribute__((packed)) definition +#define zig_packed(definition) definition __attribute__((packed)) #elif defined(zig_msvc) #define zig_packed(definition) __pragma(pack(1)) definition __pragma(pack()) #else diff --git a/src/Compilation.zig b/src/Compilation.zig index 45d0aa6e97fbb735127efa5f1d399731d6bde4a6..a4e712826d4a04f3ca0e6f15475def928a3562ad 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -3382,9 +3382,6 @@ fn flush(comp: *Compilation, arena: Allocator, tid: Zcu.PerThread.Id) (Io.Cancel error.OutOfMemory, error.Canceled => |e| return e, }; } - if (comp.zcu) |zcu| { - try link.File.C.flushEmitH(zcu); - } } /// This function is called by the frontend before flush(). It communicates that diff --git a/src/InternPool.zig b/src/InternPool.zig index 388d0a04f74fd88f6b479395044c84a90d351469..ffabc7371b0c9d7221475b966fa059eccf275a48 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -3403,7 +3403,7 @@ pub const LoadedStructType = struct { /// Iterates over non-comptime fields in the order they are laid out in memory at runtime. /// May or may not include zero-bit fields. /// Asserts the struct is not packed. - pub fn iterateRuntimeOrder(s: *const LoadedStructType, ip: *InternPool) RuntimeOrderIterator { + pub fn iterateRuntimeOrder(s: *const LoadedStructType, ip: *const InternPool) RuntimeOrderIterator { switch (s.layout) { .auto => { const ro = std.mem.sliceTo(s.field_runtime_order.get(ip), .omitted); diff --git a/src/Type.zig b/src/Type.zig index 0fe87e983b065cb43124eb1b6adc5b7c0a4888cd..1eab734882f8d25b246e4bc754004d4ca2397e39 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -789,7 +789,7 @@ pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool { /// Determines whether a function type has runtime bits, i.e. whether a /// function with this type can exist at runtime. /// Asserts that `ty` is a function type. -pub fn fnHasRuntimeBits(fn_ty: Type, zcu: *Zcu) bool { +pub fn fnHasRuntimeBits(fn_ty: Type, zcu: *const Zcu) bool { assertHasLayout(fn_ty, zcu); const fn_info = zcu.typeToFunc(fn_ty).?; if (fn_info.comptime_bits != 0) return false; @@ -830,7 +830,7 @@ pub fn fnHasRuntimeBits(fn_ty: Type, zcu: *Zcu) bool { } /// Like `hasRuntimeBits`, but also returns `true` for runtime functions. -pub fn isRuntimeFnOrHasRuntimeBits(ty: Type, zcu: *Zcu) bool { +pub fn isRuntimeFnOrHasRuntimeBits(ty: Type, zcu: *const Zcu) bool { switch (ty.zigTypeTag(zcu)) { .@"fn" => return ty.fnHasRuntimeBits(zcu), else => return ty.hasRuntimeBits(zcu), diff --git a/src/Value.zig b/src/Value.zig index cf8d0acc67377b3a871fe15cbd55cac4d0ef7221..6a474c282133e10e15cfdd423b309df986bbf034 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -151,7 +151,7 @@ pub fn intFromEnum(val: Value, zcu: *const Zcu) Value { } /// Asserts that `val` is an integer. -pub fn toBigInt(val: Value, space: *BigIntSpace, zcu: *Zcu) BigIntConst { +pub fn toBigInt(val: Value, space: *BigIntSpace, zcu: *const Zcu) BigIntConst { if (val.getUnsignedInt(zcu)) |x| { return BigIntMutable.init(&space.limbs, x).toConst(); } @@ -669,7 +669,7 @@ pub fn floatCast(val: Value, dest_ty: Type, pt: Zcu.PerThread) !Value { } /// Asserts the value is comparable. Supports comparisons between heterogeneous types. -pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value, zcu: *Zcu) bool { +pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value, zcu: *const Zcu) bool { if (lhs.pointerNav(zcu)) |lhs_nav| { if (rhs.pointerNav(zcu)) |rhs_nav| { switch (op) { @@ -695,7 +695,7 @@ pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value, zcu: return order(lhs, rhs, zcu).compare(op); } -pub fn order(lhs: Value, rhs: Value, zcu: *Zcu) std.math.Order { +pub fn order(lhs: Value, rhs: Value, zcu: *const Zcu) std.math.Order { if (lhs.isFloat(zcu) or rhs.isFloat(zcu)) { const lhs_f128 = lhs.toFloat(f128, zcu); const rhs_f128 = rhs.toFloat(f128, zcu); @@ -805,7 +805,7 @@ pub fn canMutateComptimeVarState(val: Value, zcu: *Zcu) bool { /// Gets the `Nav` referenced by this pointer. If the pointer does not point /// to a `Nav`, or if it points to some part of one (like a field or element), /// returns null. -pub fn pointerNav(val: Value, zcu: *Zcu) ?InternPool.Nav.Index { +pub fn pointerNav(val: Value, zcu: *const Zcu) ?InternPool.Nav.Index { return switch (zcu.intern_pool.indexToKey(val.toIntern())) { // TODO: these 3 cases are weird; these aren't pointer values! .variable => |v| v.owner_nav, diff --git a/src/Zcu.zig b/src/Zcu.zig index 481ea0d62ad312d3a0e9ce5f6d84f8ea13635841..faa535da5d6e12ae12c1ba6aaed1341fde2147d6 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -4113,13 +4113,13 @@ pub const ResolvedReference = struct { /// If an `AnalUnit` is not in the returned map, it is unreferenced. /// The returned hashmap is owned by the `Zcu`, so should not be freed by the caller. /// This hashmap is cached, so repeated calls to this function are cheap. -pub fn resolveReferences(zcu: *Zcu) !*const std.AutoArrayHashMapUnmanaged(AnalUnit, ?ResolvedReference) { +pub fn resolveReferences(zcu: *Zcu) Allocator.Error!*const std.AutoArrayHashMapUnmanaged(AnalUnit, ?ResolvedReference) { if (zcu.resolved_references == null) { zcu.resolved_references = try zcu.resolveReferencesInner(); } return &zcu.resolved_references.?; } -fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?ResolvedReference) { +fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.AutoArrayHashMapUnmanaged(AnalUnit, ?ResolvedReference) { const gpa = zcu.gpa; const comp = zcu.comp; const ip = &zcu.intern_pool; diff --git a/src/codegen/c.zig b/src/codegen/c.zig index c8904405e218072fc80d8753603c1e0689022f25..b31b0a40da9a5c9663bf7d3392bef966e6eed1a9 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -50,32 +50,39 @@ pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features { /// * The types used, so declarations can be emitted in `flush` /// * The lazy functions used, so definitions can be emitted in `flush` pub const Mir = struct { - /// This map contains all the UAVs we saw generating this function. - /// `link.C` will merge them into its `uavs`/`aligned_uavs` fields. - /// Key is the value of the UAV; value is the UAV's alignment, or - /// `.none` for natural alignment. The specified alignment is never - /// less than the natural alignment. - uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), // These remaining fields are essentially just an owned version of `link.C.AvBlock`. + fwd_decl: []u8, code_header: []u8, code: []u8, - fwd_decl: []u8, - ctype_pool: CType.Pool, - lazy_fns: LazyFnMap, + /// This map contains all the UAVs we saw generating this function. + /// `link.C` will merge them into its `uavs`/`aligned_uavs` fields. + /// Key is the value of the UAV; value is the UAV's alignment, or + /// `.none` for natural alignment. The specified alignment is never + /// less than the natural alignment. + need_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), + ctype_deps: CType.Dependencies, + /// Key is an enum type for which we need a generated `@tagName` function. + need_tag_name_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), + /// Key is a function Nav for which we need a generated `zig_never_tail` wrapper. + need_never_tail_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void), + /// Key is a function Nav for which we need a generated `zig_never_inline` wrapper. + need_never_inline_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void), pub fn deinit(mir: *Mir, gpa: Allocator) void { - mir.uavs.deinit(gpa); + gpa.free(mir.fwd_decl); gpa.free(mir.code_header); gpa.free(mir.code); - gpa.free(mir.fwd_decl); - mir.ctype_pool.deinit(gpa); - mir.lazy_fns.deinit(gpa); + mir.need_uavs.deinit(gpa); + mir.ctype_deps.deinit(gpa); + mir.need_tag_name_funcs.deinit(gpa); + mir.need_never_tail_funcs.deinit(gpa); + mir.need_never_inline_funcs.deinit(gpa); } }; -pub const Error = Writer.Error || std.mem.Allocator.Error || error{AnalysisFail}; +pub const Error = Writer.Error || Allocator.Error || error{AnalysisFail}; -pub const CType = @import("c/Type.zig"); +pub const CType = @import("c/type.zig").CType; pub const CValue = union(enum) { none: void, @@ -87,8 +94,6 @@ pub const CValue = union(enum) { constant: Value, /// Index into the parameters arg: usize, - /// The array field of a parameter - arg_array: usize, /// Index into a tuple's fields field: usize, /// By-value @@ -100,8 +105,6 @@ pub const CValue = union(enum) { identifier: []const u8, /// Rendered as "payload." followed by as identifier (using fmtIdent) payload_identifier: []const u8, - /// Rendered with fmtCTypePoolString - ctype_pool_string: CType.Pool.String, fn eql(lhs: CValue, rhs: CValue) bool { return switch (lhs) { @@ -122,10 +125,6 @@ pub const CValue = union(enum) { .arg => |rhs_arg_index| lhs_arg_index == rhs_arg_index, else => false, }, - .arg_array => |lhs_arg_index| switch (rhs) { - .arg_array => |rhs_arg_index| lhs_arg_index == rhs_arg_index, - else => false, - }, .field => |lhs_field_index| switch (rhs) { .field => |rhs_field_index| lhs_field_index == rhs_field_index, else => false, @@ -150,10 +149,6 @@ pub const CValue = union(enum) { .payload_identifier => |rhs_id| std.mem.eql(u8, lhs_id, rhs_id), else => false, }, - .ctype_pool_string => |lhs_str| switch (rhs) { - .ctype_pool_string => |rhs_str| lhs_str.index == rhs_str.index, - else => false, - }, }; } }; @@ -163,53 +158,24 @@ const BlockData = struct { result: CValue, }; -pub const CValueMap = std.AutoHashMap(Air.Inst.Ref, CValue); - -pub const LazyFnKey = union(enum) { - tag_name: InternPool.Index, - never_tail: InternPool.Nav.Index, - never_inline: InternPool.Nav.Index, -}; -pub const LazyFnValue = struct { - fn_name: CType.Pool.String, -}; -pub const LazyFnMap = std.AutoArrayHashMapUnmanaged(LazyFnKey, LazyFnValue); - -const Local = struct { - ctype: CType, - flags: packed struct(u32) { - alignas: CType.AlignAs, - _: u20 = undefined, - }, - - fn getType(local: Local) LocalType { - return .{ .ctype = local.ctype, .alignas = local.flags.alignas }; - } +const LocalType = struct { + type: Type, + alignment: Alignment, }; const LocalIndex = u16; -const LocalType = struct { ctype: CType, alignas: CType.AlignAs }; const LocalsList = std.AutoArrayHashMapUnmanaged(LocalIndex, void); const LocalsMap = std.AutoArrayHashMapUnmanaged(LocalType, LocalsList); const ValueRenderLocation = enum { - FunctionArgument, - Initializer, - StaticInitializer, - Other, + initializer, + static_initializer, + other, fn isInitializer(loc: ValueRenderLocation) bool { return switch (loc) { - .Initializer, .StaticInitializer => true, - else => false, - }; - } - - fn toCTypeKind(loc: ValueRenderLocation) CType.Kind { - return switch (loc) { - .FunctionArgument => .parameter, - .Initializer, .Other => .complete, - .StaticInitializer => .global, + .initializer, .static_initializer => true, + .other => false, }; } }; @@ -334,16 +300,31 @@ const reserved_idents = std.StaticStringMap(void).initComptime(.{ }); fn isReservedIdent(ident: []const u8) bool { - if (ident.len >= 2 and ident[0] == '_') { // C language + // C language + if (ident.len >= 2 and ident[0] == '_') { switch (ident[1]) { 'A'...'Z', '_' => return true, - else => return false, + else => {}, } - } else if (mem.startsWith(u8, ident, "DUMMYSTRUCTNAME") or + } + + // windows.h + if (mem.startsWith(u8, ident, "DUMMYSTRUCTNAME") or mem.startsWith(u8, ident, "DUMMYUNIONNAME")) - { // windows.h + { return true; - } else return reserved_idents.has(ident); + } + + // CType + if (mem.startsWith(u8, ident, "enum__") or + mem.startsWith(u8, ident, "bitpack__") or + mem.startsWith(u8, ident, "aligned__") or + mem.startsWith(u8, ident, "fn__")) + { + return true; + } + + return reserved_idents.has(ident); } fn formatIdentSolo(ident: []const u8, w: *Writer) Writer.Error!void { @@ -361,7 +342,7 @@ fn formatIdentOptions(ident: []const u8, w: *Writer, solo: bool) Writer.Error!vo for (ident, 0..) |c, i| { switch (c) { 'a'...'z', 'A'...'Z', '_' => try w.writeByte(c), - '.' => try w.writeByte('_'), + '.', ' ' => try w.writeByte('_'), '0'...'9' => if (i == 0) { try w.print("_{x:2}", .{c}); } else { @@ -380,29 +361,6 @@ pub fn fmtIdentUnsolo(ident: []const u8) std.fmt.Alt([]const u8, formatIdentUnso return .{ .data = ident }; } -const CTypePoolStringFormatData = struct { - ctype_pool_string: CType.Pool.String, - ctype_pool: *const CType.Pool, - solo: bool, -}; -fn formatCTypePoolString(data: CTypePoolStringFormatData, w: *Writer) Writer.Error!void { - if (data.ctype_pool_string.toSlice(data.ctype_pool)) |slice| - try formatIdentOptions(slice, w, data.solo) - else - try w.print("{f}", .{data.ctype_pool_string.fmt(data.ctype_pool)}); -} -pub fn fmtCTypePoolString( - ctype_pool_string: CType.Pool.String, - ctype_pool: *const CType.Pool, - solo: bool, -) std.fmt.Alt(CTypePoolStringFormatData, formatCTypePoolString) { - return .{ .data = .{ - .ctype_pool_string = ctype_pool_string, - .ctype_pool = ctype_pool, - .solo = solo, - } }; -} - // Returns true if `formatIdent` would make any edits to ident. // This must be kept in sync with `formatIdent`. pub fn isMangledIdent(ident: []const u8, solo: bool) bool { @@ -417,21 +375,26 @@ pub fn isMangledIdent(ident: []const u8, solo: bool) bool { return false; } -/// This data is available when outputting .c code for a `InternPool.Index` -/// that corresponds to `func`. -/// It is not available when generating .h file. +/// This data is available when rendering C source code for an interned function. pub const Function = struct { air: Air, liveness: Air.Liveness, - value_map: CValueMap, + value_map: std.AutoHashMap(Air.Inst.Ref, CValue), blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, BlockData) = .empty, next_arg_index: u32 = 0, next_block_index: u32 = 0, - object: Object, - lazy_fns: LazyFnMap, + dg: DeclGen, + code: Writer.Allocating, + indent_counter: usize, + /// Key is an enum type for which we need a generated `@tagName` function. + need_tag_name_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), + /// Key is a function Nav for which we need a generated `zig_never_tail` wrapper. + need_never_tail_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void), + /// Key is a function Nav for which we need a generated `zig_never_inline` wrapper. + need_never_inline_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void), func_index: InternPool.Index, /// All the locals, to be emitted at the top of the function. - locals: std.ArrayList(Local) = .empty, + locals: std.ArrayList(LocalType) = .empty, /// Which locals are available for reuse, based on Type. free_locals_map: LocalsMap = .{}, /// Locals which will not be freed by Liveness. This is used after a @@ -445,37 +408,41 @@ pub const Function = struct { /// for the switch cond. Dispatches should set this local to the new cond. loop_switch_conds: std.AutoHashMapUnmanaged(Air.Inst.Index, LocalIndex) = .empty, + const indent_width = 1; + const indent_char = ' '; + + fn newline(f: *Function) !void { + const w = &f.code.writer; + try w.writeByte('\n'); + try w.splatByteAll(indent_char, f.indent_counter); + } + fn indent(f: *Function) void { + f.indent_counter += indent_width; + } + fn outdent(f: *Function) !void { + f.indent_counter -= indent_width; + const written = f.code.written(); + switch (written[written.len - 1]) { + indent_char => f.code.shrinkRetainingCapacity(written.len - indent_width), + '\n' => try f.code.writer.splatByteAll(indent_char, f.indent_counter), + else => { + std.debug.print("\"{f}\"\n", .{std.zig.fmtString(written[written.len -| 100..])}); + unreachable; + }, + } + } + fn resolveInst(f: *Function, ref: Air.Inst.Ref) !CValue { const gop = try f.value_map.getOrPut(ref); - if (gop.found_existing) return gop.value_ptr.*; - - const pt = f.object.dg.pt; - const zcu = pt.zcu; - const val = (try f.air.value(ref, pt)).?; - const ty = f.typeOf(ref); - - const result: CValue = if (lowersToArray(ty, zcu)) result: { - const ch = &f.object.code_header.writer; - const decl_c_value = try f.allocLocalValue(.{ - .ctype = try f.ctypeFromType(ty, .complete), - .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(zcu)), - }); - const gpa = f.object.dg.gpa; - try f.allocs.put(gpa, decl_c_value.new_local, false); - try ch.writeAll("static "); - try f.object.dg.renderTypeAndName(ch, ty, decl_c_value, Const, .none, .complete); - try ch.writeAll(" = "); - try f.object.dg.renderValue(ch, val, .StaticInitializer); - try ch.writeAll(";\n "); - break :result .{ .local = decl_c_value.new_local }; - } else .{ .constant = val }; - - gop.value_ptr.* = result; - return result; + if (!gop.found_existing) { + const val = try f.air.value(ref, f.dg.pt); + gop.value_ptr.* = .{ .constant = val.? }; + } + return gop.value_ptr.*; } fn wantSafety(f: *Function) bool { - return switch (f.object.dg.pt.zcu.optimizeMode()) { + return switch (f.dg.pt.zcu.optimizeMode()) { .Debug, .ReleaseSafe => true, .ReleaseFast, .ReleaseSmall => false, }; @@ -485,18 +452,16 @@ pub const Function = struct { /// those which go into `allocs`. This function does not add the resulting local into `allocs`; /// that responsibility lies with the caller. fn allocLocalValue(f: *Function, local_type: LocalType) !CValue { - try f.locals.ensureUnusedCapacity(f.object.dg.gpa, 1); - defer f.locals.appendAssumeCapacity(.{ - .ctype = local_type.ctype, - .flags = .{ .alignas = local_type.alignas }, - }); - return .{ .new_local = @intCast(f.locals.items.len) }; + try f.locals.ensureUnusedCapacity(f.dg.gpa, 1); + const index = f.locals.items.len; + f.locals.appendAssumeCapacity(local_type); + return .{ .new_local = @intCast(index) }; } fn allocLocal(f: *Function, inst: ?Air.Inst.Index, ty: Type) !CValue { return f.allocAlignedLocal(inst, .{ - .ctype = try f.ctypeFromType(ty, .complete), - .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(f.object.dg.pt.zcu)), + .type = ty, + .alignment = .none, }); } @@ -524,11 +489,10 @@ pub const Function = struct { .none => unreachable, .new_local, .local => |i| try w.print("t{d}", .{i}), .local_ref => |i| try w.print("&t{d}", .{i}), - .constant => |val| try f.object.dg.renderValue(w, val, location), + .constant => |val| try f.dg.renderValue(w, val, location), .arg => |i| try w.print("a{d}", .{i}), - .arg_array => |i| try f.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }), - .undef => |ty| try f.object.dg.renderUndefValue(w, ty, location), - else => try f.object.dg.writeCValue(w, c_value), + .undef => |ty| try f.dg.renderUndefValue(w, ty, location), + else => try f.dg.writeCValue(w, c_value), } } @@ -537,17 +501,12 @@ pub const Function = struct { .none => unreachable, .new_local, .local, .constant => { try w.writeAll("(*"); - try f.writeCValue(w, c_value, .Other); + try f.writeCValue(w, c_value, .other); try w.writeByte(')'); }, .local_ref => |i| try w.print("t{d}", .{i}), .arg => |i| try w.print("(*a{d})", .{i}), - .arg_array => |i| { - try w.writeAll("(*"); - try f.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }); - try w.writeByte(')'); - }, - else => try f.object.dg.writeCValueDeref(w, c_value), + else => try f.dg.writeCValueDeref(w, c_value), } } @@ -558,119 +517,77 @@ pub const Function = struct { member: CValue, ) Error!void { switch (c_value) { - .new_local, .local, .local_ref, .constant, .arg, .arg_array => { - try f.writeCValue(w, c_value, .Other); + .new_local, .local, .local_ref, .constant, .arg => { + try f.writeCValue(w, c_value, .other); try w.writeByte('.'); - try f.writeCValue(w, member, .Other); + try f.writeCValue(w, member, .other); }, - else => return f.object.dg.writeCValueMember(w, c_value, member), + else => return f.dg.writeCValueMember(w, c_value, member), } } fn writeCValueDerefMember(f: *Function, w: *Writer, c_value: CValue, member: CValue) !void { switch (c_value) { - .new_local, .local, .arg, .arg_array => { - try f.writeCValue(w, c_value, .Other); + .new_local, .local, .arg => { + try f.writeCValue(w, c_value, .other); try w.writeAll("->"); }, .constant => { try w.writeByte('('); - try f.writeCValue(w, c_value, .Other); + try f.writeCValue(w, c_value, .other); try w.writeAll(")->"); }, .local_ref => { try f.writeCValueDeref(w, c_value); try w.writeByte('.'); }, - else => return f.object.dg.writeCValueDerefMember(w, c_value, member), + else => return f.dg.writeCValueDerefMember(w, c_value, member), } - try f.writeCValue(w, member, .Other); + try f.writeCValue(w, member, .other); } fn fail(f: *Function, comptime format: []const u8, args: anytype) Error { - return f.object.dg.fail(format, args); + return f.dg.fail(format, args); } - fn ctypeFromType(f: *Function, ty: Type, kind: CType.Kind) !CType { - return f.object.dg.ctypeFromType(ty, kind); - } - - fn byteSize(f: *Function, ctype: CType) u64 { - return f.object.dg.byteSize(ctype); - } - - fn renderType(f: *Function, w: *Writer, ctype: Type) !void { - return f.object.dg.renderType(w, ctype); - } - - fn renderCType(f: *Function, w: *Writer, ctype: CType) !void { - return f.object.dg.renderCType(w, ctype); + fn renderType(f: *Function, w: *Writer, ty: Type) !void { + return f.dg.renderType(w, ty); } fn renderIntCast(f: *Function, w: *Writer, dest_ty: Type, src: CValue, v: Vectorize, src_ty: Type, location: ValueRenderLocation) !void { - return f.object.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location); + return f.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location); } fn fmtIntLiteralDec(f: *Function, val: Value) !std.fmt.Alt(FormatIntLiteralContext, formatIntLiteral) { - return f.object.dg.fmtIntLiteralDec(val, .Other); + return f.dg.fmtIntLiteralDec(val, .other); } fn fmtIntLiteralHex(f: *Function, val: Value) !std.fmt.Alt(FormatIntLiteralContext, formatIntLiteral) { - return f.object.dg.fmtIntLiteralHex(val, .Other); - } - - fn getLazyFnName(f: *Function, key: LazyFnKey) ![]const u8 { - const gpa = f.object.dg.gpa; - const pt = f.object.dg.pt; - const zcu = pt.zcu; - const ip = &zcu.intern_pool; - const ctype_pool = &f.object.dg.ctype_pool; - - const gop = try f.lazy_fns.getOrPut(gpa, key); - if (!gop.found_existing) { - errdefer _ = f.lazy_fns.pop(); - - gop.value_ptr.* = .{ - .fn_name = switch (key) { - .tag_name, - => |enum_ty| try ctype_pool.fmt(gpa, "zig_{s}_{f}__{d}", .{ - @tagName(key), - fmtIdentUnsolo(ip.loadEnumType(enum_ty).name.toSlice(ip)), - @intFromEnum(enum_ty), - }), - .never_tail, - .never_inline, - => |owner_nav| try ctype_pool.fmt(gpa, "zig_{s}_{f}__{d}", .{ - @tagName(key), - fmtIdentUnsolo(ip.getNav(owner_nav).name.toSlice(ip)), - @intFromEnum(owner_nav), - }), - }, - }; - } - return gop.value_ptr.fn_name.toSlice(ctype_pool).?; + return f.dg.fmtIntLiteralHex(val, .other); } pub fn deinit(f: *Function) void { - const gpa = f.object.dg.gpa; + const gpa = f.dg.gpa; f.allocs.deinit(gpa); f.locals.deinit(gpa); deinitFreeLocalsMap(gpa, &f.free_locals_map); f.blocks.deinit(gpa); f.value_map.deinit(); - f.lazy_fns.deinit(gpa); + f.need_tag_name_funcs.deinit(gpa); + f.need_never_tail_funcs.deinit(gpa); + f.need_never_inline_funcs.deinit(gpa); f.loop_switch_conds.deinit(gpa); } fn typeOf(f: *Function, inst: Air.Inst.Ref) Type { - return f.air.typeOf(inst, &f.object.dg.pt.zcu.intern_pool); + return f.air.typeOf(inst, &f.dg.pt.zcu.intern_pool); } fn typeOfIndex(f: *Function, inst: Air.Inst.Index) Type { - return f.air.typeOfIndex(inst, &f.object.dg.pt.zcu.intern_pool); + return f.air.typeOfIndex(inst, &f.dg.pt.zcu.intern_pool); } - fn copyCValue(f: *Function, ctype: CType, dst: CValue, src: CValue) !void { + fn copyCValue(f: *Function, dst: CValue, src: CValue) !void { switch (dst) { .new_local, .local => |dst_local_index| switch (src) { .new_local, .local => |src_local_index| if (dst_local_index == src_local_index) return, @@ -678,12 +595,12 @@ pub const Function = struct { }, else => {}, } - const w = &f.object.code.writer; - const a = try Assignment.start(f, w, ctype); - try f.writeCValue(w, dst, .Other); - try a.assign(f, w); - try f.writeCValue(w, src, .Other); - try a.end(f, w); + const w = &f.code.writer; + try f.writeCValue(w, dst, .other); + try w.writeAll(" = "); + try f.writeCValue(w, src, .other); + try w.writeByte(';'); + try f.newline(); } fn moveCValue(f: *Function, inst: Air.Inst.Index, ty: Type, src: CValue) !CValue { @@ -694,7 +611,7 @@ pub const Function = struct { else => { try freeCValue(f, inst, src); const dst = try f.allocLocal(inst, ty); - try f.copyCValue(try f.ctypeFromType(ty, .complete), dst, src); + try f.copyCValue(dst, src); return dst; }, } @@ -708,51 +625,17 @@ pub const Function = struct { } }; -/// This data is available when outputting .c code for a `Zcu`. -/// It is not available when generating .h file. -pub const Object = struct { - dg: DeclGen, - code_header: Writer.Allocating, - code: Writer.Allocating, - indent_counter: usize, - - const indent_width = 1; - const indent_char = ' '; - - fn newline(o: *Object) !void { - const w = &o.code.writer; - try w.writeByte('\n'); - try w.splatByteAll(indent_char, o.indent_counter); - } - fn indent(o: *Object) void { - o.indent_counter += indent_width; - } - fn outdent(o: *Object) !void { - o.indent_counter -= indent_width; - const written = o.code.written(); - switch (written[written.len - 1]) { - indent_char => o.code.shrinkRetainingCapacity(written.len - indent_width), - '\n' => try o.code.writer.splatByteAll(indent_char, o.indent_counter), - else => { - std.debug.print("\"{f}\"\n", .{std.zig.fmtString(written[written.len -| 100..])}); - unreachable; - }, - } - } -}; - -/// This data is available both when outputting .c code and when outputting an .h file. +/// This data is available when rendering *any* C source code (function or otherwise). pub const DeclGen = struct { gpa: Allocator, + arena: Allocator, pt: Zcu.PerThread, mod: *Module, - pass: Pass, + owner_nav: InternPool.Nav.Index.Optional, is_naked_fn: bool, expected_block: ?u32, - fwd_decl: Writer.Allocating, error_msg: ?*Zcu.ErrorMsg, - ctype_pool: CType.Pool, - scratch: std.ArrayList(u32), + ctype_deps: CType.Dependencies, /// This map contains all the UAVs we saw generating this function. /// `link.C` will merge them into its `uavs`/`aligned_uavs` fields. /// Key is the value of the UAV; value is the UAV's alignment, or @@ -760,16 +643,10 @@ pub const DeclGen = struct { /// less than the natural alignment. uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), - pub const Pass = union(enum) { - nav: InternPool.Nav.Index, - uav: InternPool.Index, - flush, - }; - fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) Error { @branchHint(.cold); const zcu = dg.pt.zcu; - const src_loc = zcu.navSrcLoc(dg.pass.nav); + const src_loc = zcu.navSrcLoc(dg.owner_nav.unwrap().?); dg.error_msg = try Zcu.ErrorMsg.create(dg.gpa, src_loc, format, args); return error.AnalysisFail; } @@ -783,14 +660,13 @@ pub const DeclGen = struct { const pt = dg.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; - const ctype_pool = &dg.ctype_pool; const uav_val = Value.fromInterned(uav.val); const uav_ty = uav_val.typeOf(zcu); // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. const ptr_ty: Type = .fromInterned(uav.orig_ty); if (ptr_ty.isPtrAtRuntime(zcu) and !uav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { - return dg.writeCValue(w, .{ .undef = ptr_ty }); + return dg.renderUndefValue(w, ptr_ty, location); } // Chase function values in order to be able to reference the original function. @@ -805,14 +681,12 @@ pub const DeclGen = struct { // them). The analysis until now should ensure that the C function // pointers are compatible. If they are not, then there is a bug // somewhere and we should let the C compiler tell us about it. - const ptr_ctype = try dg.ctypeFromType(ptr_ty, .complete); - const elem_ctype = ptr_ctype.info(ctype_pool).pointer.elem_ctype; - const uav_ctype = try dg.ctypeFromType(uav_ty, .complete); - const need_cast = !elem_ctype.eql(uav_ctype) and - (elem_ctype.info(ctype_pool) != .function or uav_ctype.info(ctype_pool) != .function); + const elem_ty = ptr_ty.childType(zcu); + const need_cast = elem_ty.toIntern() != uav_ty.toIntern() and + elem_ty.zigTypeTag(zcu) != .@"fn" or uav_ty.zigTypeTag(zcu) != .@"fn"; if (need_cast) { try w.writeAll("(("); - try dg.renderCType(w, ptr_ctype); + try dg.renderType(w, ptr_ty); try w.writeByte(')'); } try w.writeByte('&'); @@ -842,11 +716,9 @@ pub const DeclGen = struct { nav_index: InternPool.Nav.Index, location: ValueRenderLocation, ) Error!void { - _ = location; const pt = dg.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; - const ctype_pool = &dg.ctype_pool; // Chase function values in order to be able to reference the original function. const owner_nav = switch (ip.getNav(nav_index).status) { @@ -863,25 +735,23 @@ pub const DeclGen = struct { const nav_ty: Type = .fromInterned(ip.getNav(owner_nav).typeOf(ip)); const ptr_ty = try pt.navPtrType(owner_nav); if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { - return dg.writeCValue(w, .{ .undef = ptr_ty }); + return dg.renderUndefValue(w, ptr_ty, location); } // We shouldn't cast C function pointers as this is UB (when you call // them). The analysis until now should ensure that the C function // pointers are compatible. If they are not, then there is a bug // somewhere and we should let the C compiler tell us about it. - const ctype = try dg.ctypeFromType(ptr_ty, .complete); - const elem_ctype = ctype.info(ctype_pool).pointer.elem_ctype; - const nav_ctype = try dg.ctypeFromType(nav_ty, .complete); - const need_cast = !elem_ctype.eql(nav_ctype) and - (elem_ctype.info(ctype_pool) != .function or nav_ctype.info(ctype_pool) != .function); + const elem_ty = ptr_ty.childType(zcu); + const need_cast = elem_ty.toIntern() != nav_ty.toIntern() and + elem_ty.zigTypeTag(zcu) != .@"fn" or nav_ty.zigTypeTag(zcu) != .@"fn"; if (need_cast) { try w.writeAll("(("); - try dg.renderCType(w, ctype); + try dg.renderType(w, ptr_ty); try w.writeByte(')'); } try w.writeByte('&'); - try dg.renderNavName(w, owner_nav); + try renderNavName(w, owner_nav, ip); if (need_cast) try w.writeByte(')'); } @@ -896,11 +766,10 @@ pub const DeclGen = struct { switch (derivation) { .comptime_alloc_ptr, .comptime_field_ptr => unreachable, .int => |int| { - const ptr_ctype = try dg.ctypeFromType(int.ptr_ty, .complete); const addr_val = try pt.intValue(.usize, int.addr); try w.writeByte('('); - try dg.renderCType(w, ptr_ctype); - try w.print("){f}", .{try dg.fmtIntLiteralHex(addr_val, .Other)}); + try dg.renderType(w, int.ptr_ty); + try w.print("){f}", .{try dg.fmtIntLiteralHex(addr_val, .other)}); }, .nav_ptr => |nav| try dg.renderNav(w, nav, location), @@ -915,14 +784,10 @@ pub const DeclGen = struct { .field_ptr => |field| { const parent_ptr_ty = try field.parent.ptrType(pt); - // Ensure complete type definition is available before accessing fields. - _ = try dg.ctypeFromType(parent_ptr_ty.childType(zcu), .complete); - switch (fieldLocation(parent_ptr_ty, field.result_ptr_ty, field.field_idx, zcu)) { .begin => { - const ptr_ctype = try dg.ctypeFromType(field.result_ptr_ty, .complete); try w.writeByte('('); - try dg.renderCType(w, ptr_ctype); + try dg.renderType(w, field.result_ptr_ty); try w.writeByte(')'); try dg.renderPointer(w, field.parent.*, location); }, @@ -933,51 +798,40 @@ pub const DeclGen = struct { try dg.writeCValue(w, name); }, .byte_offset => |byte_offset| { - const ptr_ctype = try dg.ctypeFromType(field.result_ptr_ty, .complete); try w.writeByte('('); - try dg.renderCType(w, ptr_ctype); + try dg.renderType(w, field.result_ptr_ty); try w.writeByte(')'); const offset_val = try pt.intValue(.usize, byte_offset); try w.writeAll("((char *)"); try dg.renderPointer(w, field.parent.*, location); - try w.print(" + {f})", .{try dg.fmtIntLiteralDec(offset_val, .Other)}); + try w.print(" + {f})", .{try dg.fmtIntLiteralDec(offset_val, .other)}); }, } }, .elem_ptr => |elem| if (!(try elem.parent.ptrType(pt)).childType(zcu).hasRuntimeBits(zcu)) { // Element type is zero-bit, so lowers to `void`. The index is irrelevant; just cast the pointer. - const ptr_ctype = try dg.ctypeFromType(elem.result_ptr_ty, .complete); try w.writeByte('('); - try dg.renderCType(w, ptr_ctype); + try dg.renderType(w, elem.result_ptr_ty); try w.writeByte(')'); try dg.renderPointer(w, elem.parent.*, location); } else { const index_val = try pt.intValue(.usize, elem.elem_idx); - // We want to do pointer arithmetic on a pointer to the element type. - // We might have a pointer-to-array. In this case, we must cast first. - const result_ctype = try dg.ctypeFromType(elem.result_ptr_ty, .complete); - const parent_ctype = try dg.ctypeFromType(try elem.parent.ptrType(pt), .complete); - if (result_ctype.eql(parent_ctype)) { - // The pointer already has an appropriate type - just do the arithmetic. + try w.writeByte('('); + // We want to do pointer arithmetic on a pointer to the element type, but the parent + // might be a pointer-to-array, in which case we must cast it. + if (elem.result_ptr_ty.toIntern() != (try elem.parent.ptrType(pt)).toIntern()) { try w.writeByte('('); - try dg.renderPointer(w, elem.parent.*, location); - try w.print(" + {f})", .{try dg.fmtIntLiteralDec(index_val, .Other)}); - } else { - // We probably have an array pointer `T (*)[n]`. Cast to an element pointer, - // and *then* apply the index. - try w.writeAll("(("); - try dg.renderCType(w, result_ctype); + try dg.renderType(w, elem.result_ptr_ty); try w.writeByte(')'); - try dg.renderPointer(w, elem.parent.*, location); - try w.print(" + {f})", .{try dg.fmtIntLiteralDec(index_val, .Other)}); } + try dg.renderPointer(w, elem.parent.*, location); + try w.print(" + {f})", .{try dg.fmtIntLiteralDec(index_val, .other)}); }, .offset_and_cast => |oac| { - const ptr_ctype = try dg.ctypeFromType(oac.new_ptr_ty, .complete); try w.writeByte('('); - try dg.renderCType(w, ptr_ctype); + try dg.renderType(w, oac.new_ptr_ty); try w.writeByte(')'); if (oac.byte_offset == 0) { try dg.renderPointer(w, oac.parent.*, location); @@ -985,14 +839,40 @@ pub const DeclGen = struct { const offset_val = try pt.intValue(.usize, oac.byte_offset); try w.writeAll("((char *)"); try dg.renderPointer(w, oac.parent.*, location); - try w.print(" + {f})", .{try dg.fmtIntLiteralDec(offset_val, .Other)}); + try w.print(" + {f})", .{try dg.fmtIntLiteralDec(offset_val, .other)}); } }, } } - fn renderErrorName(dg: *DeclGen, w: *Writer, err_name: InternPool.NullTerminatedString) !void { - try w.print("zig_error_{f}", .{fmtIdentUnsolo(err_name.toSlice(&dg.pt.zcu.intern_pool))}); + fn renderValueAsLvalue( + dg: *DeclGen, + w: *Writer, + val: Value, + ) Error!void { + const zcu = dg.pt.zcu; + + // If the type of `val` lowers to a C struct or union type, then `renderValue` will render + // it as a compound literal, and compound literals are already lvalues. + const ty = val.typeOf(zcu); + const is_aggregate: bool = switch (ty.zigTypeTag(zcu)) { + .@"struct", .@"union" => switch (ty.containerLayout(zcu)) { + .auto, .@"extern" => true, + .@"packed" => false, + }, + .array, + .vector, + .error_union, + .optional, + => true, + else => false, + }; + if (is_aggregate) return renderValue(dg, w, val, .other); + + // Otherwise, use a UAV. + const gop = try dg.uavs.getOrPut(dg.gpa, val.toIntern()); + if (!gop.found_existing) gop.value_ptr.* = .none; + try renderUavName(w, val); } fn renderValue( @@ -1005,16 +885,13 @@ pub const DeclGen = struct { const zcu = pt.zcu; const ip = &zcu.intern_pool; const target = &dg.mod.resolved_target.result; - const ctype_pool = &dg.ctype_pool; const initializer_type: ValueRenderLocation = switch (location) { - .StaticInitializer => .StaticInitializer, - else => .Initializer, + .static_initializer => .static_initializer, + else => .initializer, }; const ty = val.typeOf(zcu); - if (val.isUndef(zcu)) return dg.renderUndefValue(w, ty, location); - const ctype = try dg.ctypeFromType(ty, location.toCTypeKind()); switch (ip.indexToKey(val.toIntern())) { // types, not values .int_type, @@ -1037,7 +914,7 @@ pub const DeclGen = struct { .memoized_call, => unreachable, - .undef => unreachable, // handled above + .undef => try dg.renderUndefValue(w, ty, location), .simple_value => |simple_value| switch (simple_value) { // non-runtime values .void => unreachable, @@ -1053,46 +930,28 @@ pub const DeclGen = struct { .enum_literal, => unreachable, // non-runtime values .int => try w.print("{f}", .{try dg.fmtIntLiteralDec(val, location)}), - .err => |err| try dg.renderErrorName(w, err.name), - .error_union => |error_union| switch (ctype.info(ctype_pool)) { - .basic => switch (error_union.val) { - .err_name => |err_name| try dg.renderErrorName(w, err_name), + .err => |err| try renderErrorName(w, err.name.toSlice(ip)), + .error_union => |error_union| { + if (!location.isInitializer()) { + try w.writeByte('('); + try dg.renderType(w, ty); + try w.writeByte(')'); + } + try w.writeAll("{ .error = "); + switch (error_union.val) { + .err_name => |err_name| try renderErrorName(w, err_name.toSlice(ip)), .payload => try w.writeByte('0'), - }, - .pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable, - .aggregate => |aggregate| { - if (!location.isInitializer()) { - try w.writeByte('('); - try dg.renderCType(w, ctype); - try w.writeByte(')'); + } + if (ty.errorUnionPayload(zcu).hasRuntimeBits(zcu)) { + try w.writeAll(", .payload = "); + switch (error_union.val) { + .err_name => try dg.renderUndefValue(w, ty.errorUnionPayload(zcu), initializer_type), + .payload => |payload| try dg.renderValue(w, .fromInterned(payload), initializer_type), } - try w.writeByte('{'); - for (0..aggregate.fields.len) |field_index| { - if (field_index > 0) try w.writeByte(','); - switch (aggregate.fields.at(field_index, ctype_pool).name.index) { - .@"error" => switch (error_union.val) { - .err_name => |err_name| try dg.renderErrorName(w, err_name), - .payload => try w.writeByte('0'), - }, - .payload => switch (error_union.val) { - .err_name => try dg.renderUndefValue( - w, - ty.errorUnionPayload(zcu), - initializer_type, - ), - .payload => |payload| try dg.renderValue( - w, - Value.fromInterned(payload), - initializer_type, - ), - }, - else => unreachable, - } - } - try w.writeByte('}'); - }, + } + try w.writeAll(" }"); }, - .enum_tag => |enum_tag| try dg.renderValue(w, Value.fromInterned(enum_tag.int), location), + .enum_tag => |enum_tag| try dg.renderValue(w, .fromInterned(enum_tag.int), location), .float => { const bits = ty.floatBits(target); const f128_val = val.toFloat(f128, zcu); @@ -1143,7 +1002,7 @@ pub const DeclGen = struct { else unreachable; - if (location == .StaticInitializer) { + if (location == .static_initializer) { if (!std.math.isNan(f128_val) and std.math.isSignalNan(f128_val)) return dg.fail("TODO: C backend: implement nans rendering in static initializers", .{}); @@ -1154,9 +1013,11 @@ pub const DeclGen = struct { // return dg.fail("Only quiet nans are supported in global variable initializers", .{}); } - try w.writeAll("zig_"); - try w.writeAll(if (location == .StaticInitializer) "init" else "make"); - try w.writeAll("_special_"); + if (location == .static_initializer) { + try w.writeAll("zig_init_special_"); + } else { + try w.writeAll("zig_make_special_"); + } try dg.renderTypeForBuiltinFnName(w, ty); try w.writeByte('('); if (std.math.signbit(f128_val)) try w.writeByte('-'); @@ -1183,105 +1044,85 @@ pub const DeclGen = struct { if (!empty) try w.writeByte(')'); }, .slice => |slice| { - const aggregate = ctype.info(ctype_pool).aggregate; if (!location.isInitializer()) { try w.writeByte('('); - try dg.renderCType(w, ctype); + try dg.renderType(w, ty); try w.writeByte(')'); } try w.writeByte('{'); - for (0..aggregate.fields.len) |field_index| { - if (field_index > 0) try w.writeByte(','); - try dg.renderValue(w, Value.fromInterned( - switch (aggregate.fields.at(field_index, ctype_pool).name.index) { - .ptr => slice.ptr, - .len => slice.len, - else => unreachable, - }, - ), initializer_type); - } + try dg.renderValue(w, .fromInterned(slice.ptr), initializer_type); + try w.writeByte(','); + try dg.renderValue(w, .fromInterned(slice.len), initializer_type); try w.writeByte('}'); }, .ptr => { - var arena = std.heap.ArenaAllocator.init(zcu.gpa); - defer arena.deinit(); - const derivation = try val.pointerDerivation(arena.allocator(), pt, null); + const derivation = try val.pointerDerivation(dg.arena, pt, null); + try w.writeByte('('); try dg.renderPointer(w, derivation, location); + try w.writeByte(')'); }, - .opt => |opt| switch (ctype.info(ctype_pool)) { - .basic => if (ctype.isBool()) try w.writeAll(switch (opt.val) { - .none => "true", - else => "false", - }) else switch (opt.val) { + .opt => |opt| switch (CType.classifyOptional(ty, zcu)) { + .npv_payload => unreachable, // opv optional + .opv_payload => { + if (!location.isInitializer()) { + try w.writeByte('('); + try dg.renderType(w, ty); + try w.writeByte(')'); + } + try w.writeAll(switch (opt.val) { + .none => "{.is_null = true}", + else => "{.is_null = false}", + }); + }, + .error_set => switch (opt.val) { .none => try w.writeByte('0'), - else => |payload| switch (ip.indexToKey(payload)) { - .undef => |err_ty| try dg.renderUndefValue( - w, - .fromInterned(err_ty), - location, - ), - .err => |err| try dg.renderErrorName(w, err.name), - else => unreachable, - }, + else => |payload_val| try dg.renderValue(w, .fromInterned(payload_val), location), }, - .pointer => switch (opt.val) { + .ptr_like => switch (opt.val) { .none => try w.writeAll("NULL"), - else => |payload| try dg.renderValue(w, Value.fromInterned(payload), location), + else => |payload_val| try dg.renderValue(w, .fromInterned(payload_val), location), }, - .aligned, .array, .vector, .fwd_decl, .function => unreachable, - .aggregate => |aggregate| { + .slice_like => switch (opt.val) { + .none => { + if (!location.isInitializer()) { + try w.writeByte('('); + try dg.renderType(w, ty); + try w.writeByte(')'); + } + try w.writeAll("{NULL,"); + try dg.renderUndefValue(w, .usize, initializer_type); + try w.writeByte('}'); + }, + else => |payload_val| try dg.renderValue(w, .fromInterned(payload_val), location), + }, + .@"struct" => { + if (!location.isInitializer()) { + try w.writeByte('('); + try dg.renderType(w, ty); + try w.writeByte(')'); + } switch (opt.val) { - .none => {}, - else => |payload| switch (aggregate.fields.at(0, ctype_pool).name.index) { - .is_null, .payload => {}, - .ptr, .len => return dg.renderValue( - w, - Value.fromInterned(payload), - location, - ), - else => unreachable, + .none => { + try w.writeAll("{ .is_null = true, .payload = "); + try dg.renderUndefValue(w, ty.optionalChild(zcu), initializer_type); + try w.writeAll(" }"); + }, + else => |payload_val| { + try w.writeAll("{ .is_null = false, .payload = "); + try dg.renderValue(w, .fromInterned(payload_val), initializer_type); + try w.writeAll(" }"); }, } - if (!location.isInitializer()) { - try w.writeByte('('); - try dg.renderCType(w, ctype); - try w.writeByte(')'); - } - try w.writeByte('{'); - for (0..aggregate.fields.len) |field_index| { - if (field_index > 0) try w.writeByte(','); - switch (aggregate.fields.at(field_index, ctype_pool).name.index) { - .is_null => try w.writeAll(switch (opt.val) { - .none => "true", - else => "false", - }), - .payload => switch (opt.val) { - .none => try dg.renderUndefValue( - w, - ty.optionalChild(zcu), - initializer_type, - ), - else => |payload| try dg.renderValue( - w, - Value.fromInterned(payload), - initializer_type, - ), - }, - .ptr => try w.writeAll("NULL"), - .len => try dg.renderUndefValue(w, .usize, initializer_type), - else => unreachable, - } - } - try w.writeByte('}'); }, }, .aggregate => switch (ip.indexToKey(ty.toIntern())) { .array_type, .vector_type => { - if (location == .FunctionArgument) { + if (!location.isInitializer()) { try w.writeByte('('); - try dg.renderCType(w, ctype); + try dg.renderType(w, ty); try w.writeByte(')'); } + try w.writeByte('{'); const ai = ty.arrayInfo(zcu); if (ai.elem_type.eql(.u8, zcu)) { var literal: StringLiteral = .init(w, @intCast(ty.arrayLenIncludingSentinel(zcu))); @@ -1314,11 +1155,12 @@ pub const DeclGen = struct { } try w.writeByte('}'); } + try w.writeByte('}'); }, .tuple_type => |tuple| { if (!location.isInitializer()) { try w.writeByte('('); - try dg.renderCType(w, ctype); + try dg.renderType(w, ty); try w.writeByte(')'); } @@ -1354,7 +1196,7 @@ pub const DeclGen = struct { if (!location.isInitializer()) { try w.writeByte('('); - try dg.renderCType(w, ctype); + try dg.renderType(w, ty); try w.writeByte(')'); } @@ -1385,69 +1227,60 @@ pub const DeclGen = struct { .un => |un| { const loaded_union = ip.loadUnionType(ty.toIntern()); if (un.tag == .none) { - const backing_ty = try ty.externUnionBackingType(pt); assert(loaded_union.layout == .@"extern"); - if (location == .StaticInitializer) { + if (location == .static_initializer) { return dg.fail("TODO: C backend: implement extern union backing type rendering in static initializers", .{}); } const ptr_ty = try pt.singleConstPtrType(ty); - try w.writeAll("*(("); + try w.writeAll("*("); try dg.renderType(w, ptr_ty); - try w.writeAll(")("); - try dg.renderType(w, backing_ty); - try w.writeAll("){"); - try dg.renderValue(w, Value.fromInterned(un.val), location); - try w.writeAll("})"); + try w.writeAll(")&"); + // We need an lvalue for '&'. + try dg.renderValueAsLvalue(w, .fromInterned(un.val)); } else { if (!location.isInitializer()) { try w.writeByte('('); - try dg.renderCType(w, ctype); + try dg.renderType(w, ty); try w.writeByte(')'); } + if (ty.unionHasAllZeroBitFieldTypes(zcu)) { + assert(loaded_union.has_runtime_tag); // otherwise it does not have runtime bits + try w.writeAll("{ .tag = "); + try dg.renderValue(w, .fromInterned(un.tag), initializer_type); + try w.writeAll(" }"); + return; + } + + if (loaded_union.layout == .auto) try w.writeByte('{'); - const field_index = zcu.unionTagFieldIndex(loaded_union, Value.fromInterned(un.tag)).?; - const field_ty: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); - const field_name = ip.loadEnumType(loaded_union.enum_tag_type).field_names.get(ip)[field_index]; + if (loaded_union.has_runtime_tag) { + try w.writeAll(" .tag = "); + try dg.renderValue(w, .fromInterned(un.tag), initializer_type); + try w.writeAll(", .payload = "); + } - const has_tag = loaded_union.has_runtime_tag; - if (has_tag) try w.writeByte('{'); - const aggregate = ctype.info(ctype_pool).aggregate; - for (0..if (has_tag) aggregate.fields.len else 1) |outer_field_index| { - if (outer_field_index > 0) try w.writeByte(','); - switch (if (has_tag) - aggregate.fields.at(outer_field_index, ctype_pool).name.index - else - .payload) { - .tag => try dg.renderValue( - w, - Value.fromInterned(un.tag), - initializer_type, - ), - .payload => { - try w.writeByte('{'); - if (field_ty.hasRuntimeBits(zcu)) { - try w.print(" .{f} = ", .{fmtIdentSolo(field_name.toSlice(ip))}); - try dg.renderValue( - w, - Value.fromInterned(un.val), - initializer_type, - ); - try w.writeByte(' '); - } else for (0..loaded_union.field_types.len) |inner_field_index| { - const inner_field_ty: Type = .fromInterned( - loaded_union.field_types.get(ip)[inner_field_index], - ); - if (!inner_field_ty.hasRuntimeBits(zcu)) continue; - try dg.renderUndefValue(w, inner_field_ty, initializer_type); - break; - } - try w.writeByte('}'); - }, - else => unreachable, - } + const enum_tag_ty: Type = .fromInterned(loaded_union.enum_tag_type); + const active_field_index = enum_tag_ty.enumTagFieldIndex(.fromInterned(un.tag), zcu).?; + const active_field_ty: Type = .fromInterned(loaded_union.field_types.get(ip)[active_field_index]); + if (active_field_ty.hasRuntimeBits(zcu)) { + const active_field_name = enum_tag_ty.enumFieldName(active_field_index, zcu); + try w.print("{{ .{f} = ", .{fmtIdentSolo(active_field_name.toSlice(ip))}); + try dg.renderValue(w, .fromInterned(un.val), initializer_type); + try w.writeAll(" }"); + } else { + const first_field_ty: Type = for (loaded_union.field_types.get(ip)) |field_ty_ip| { + const field_ty: Type = .fromInterned(field_ty_ip); + if (!field_ty.hasRuntimeBits(pt.zcu)) continue; + break field_ty; + } else unreachable; + try w.writeByte('{'); + try dg.renderUndefValue(w, first_field_ty, initializer_type); + try w.writeByte('}'); } - if (has_tag) try w.writeByte('}'); + + if (loaded_union.has_runtime_tag) try w.writeByte(' '); + if (loaded_union.layout == .auto) try w.writeByte('}'); } }, } @@ -1463,11 +1296,10 @@ pub const DeclGen = struct { const zcu = pt.zcu; const ip = &zcu.intern_pool; const target = &dg.mod.resolved_target.result; - const ctype_pool = &dg.ctype_pool; const initializer_type: ValueRenderLocation = switch (location) { - .StaticInitializer => .StaticInitializer, - else => .Initializer, + .static_initializer => .static_initializer, + else => .initializer, }; const safety_on = switch (zcu.optimizeMode()) { @@ -1475,7 +1307,6 @@ pub const DeclGen = struct { .ReleaseFast, .ReleaseSmall => false, }; - const ctype = try dg.ctypeFromType(ty, location.toCTypeKind()); switch (ty.toIntern()) { .c_longdouble_type, .f16_type, @@ -1500,88 +1331,120 @@ pub const DeclGen = struct { else => unreachable, } try w.writeAll(", "); - try dg.renderUndefValue(w, repr_ty, .FunctionArgument); + try dg.renderUndefValue(w, repr_ty, .other); return w.writeByte(')'); }, .bool_type => try w.writeAll(if (safety_on) "0xaa" else "false"), else => switch (ip.indexToKey(ty.toIntern())) { - .simple_type, + .simple_type, // anyerror, c_char (etc), usize, isize .int_type, .enum_type, .error_set_type, .inferred_error_set_type, - => return w.print("{f}", .{ - try dg.fmtIntLiteralHex(try pt.undefValue(ty), location), - }), + => switch (CType.classifyInt(ty, zcu)) { + .void => unreachable, // opv + .small => |s| { + const int = ty.intInfo(zcu); + var buf: [std.math.big.int.calcTwosCompLimbCount(128)]std.math.big.Limb = undefined; + var bigint: std.math.big.int.Mutable = .init(&buf, undefPattern(u128)); + bigint.truncate(bigint.toConst(), int.signedness, int.bits); + const fmt_undef: FormatInt128 = .{ + .target = zcu.getTarget(), + .int_cty = s, + .val = bigint.toConst(), + .is_global = location == .static_initializer, + .base = 16, + .case = .lower, + }; + try w.print("{f}", .{fmt_undef}); + }, + .big => |big| { + var buf: [std.math.big.int.calcTwosCompLimbCount(128)]std.math.big.Limb = undefined; + var limb_bigint: std.math.big.int.Mutable = .init(&buf, undefPattern(u128)); + limb_bigint.truncate(limb_bigint.toConst(), .unsigned, big.limb_size.bits()); + const fmt_undef_limb: FormatInt128 = .{ + .target = zcu.getTarget(), + .int_cty = big.limb_size.unsigned(), + .val = limb_bigint.toConst(), + .is_global = location == .static_initializer, + .base = 16, + .case = .lower, + }; + + if (!location.isInitializer()) { + try w.writeByte('('); + try dg.renderType(w, ty); + try w.writeByte(')'); + } + try w.writeAll("{{"); + try w.print("{f}", .{fmt_undef_limb}); + for (1..big.limbs_len) |_| { + try w.print(",{f}", .{fmt_undef_limb}); + } + try w.writeAll("}}"); + }, + }, .ptr_type => |ptr_type| switch (ptr_type.flags.size) { .one, .many, .c => { try w.writeAll("(("); - try dg.renderCType(w, ctype); - return w.print("){f})", .{ - try dg.fmtIntLiteralHex(.undef_usize, .Other), - }); + try dg.renderType(w, ty); + try w.writeByte(')'); + try dg.renderUndefValue(w, .usize, location); + try w.writeByte(')'); }, .slice => { if (!location.isInitializer()) { try w.writeByte('('); - try dg.renderCType(w, ctype); + try dg.renderType(w, ty); try w.writeByte(')'); } - try w.writeAll("{("); - const ptr_ty = ty.slicePtrFieldType(zcu); - try dg.renderType(w, ptr_ty); - return w.print("){f}, {0f}}}", .{ - try dg.fmtIntLiteralHex(.undef_usize, .Other), - }); - }, - }, - .opt_type => |child_type| switch (ctype.info(ctype_pool)) { - .basic, .pointer => try dg.renderUndefValue( - w, - .fromInterned(if (ctype.isBool()) .bool_type else child_type), - location, - ), - .aligned, .array, .vector, .fwd_decl, .function => unreachable, - .aggregate => |aggregate| { - switch (aggregate.fields.at(0, ctype_pool).name.index) { - .is_null, .payload => {}, - .ptr, .len => return dg.renderUndefValue( - w, - .fromInterned(child_type), - location, - ), - else => unreachable, - } - if (!location.isInitializer()) { - try w.writeByte('('); - try dg.renderCType(w, ctype); - try w.writeByte(')'); - } try w.writeByte('{'); - for (0..aggregate.fields.len) |field_index| { - if (field_index > 0) try w.writeByte(','); - try dg.renderUndefValue(w, .fromInterned( - switch (aggregate.fields.at(field_index, ctype_pool).name.index) { - .is_null => .bool_type, - .payload => child_type, - else => unreachable, - }, - ), initializer_type); - } + try dg.renderUndefValue(w, ty.slicePtrFieldType(zcu), initializer_type); + try w.writeByte(','); + try dg.renderUndefValue(w, .usize, initializer_type); try w.writeByte('}'); }, }, + .opt_type => |child_type| switch (CType.classifyOptional(ty, zcu)) { + .npv_payload => unreachable, // opv optional + + .error_set, + .ptr_like, + .slice_like, + => try dg.renderUndefValue(w, .fromInterned(child_type), location), + + .opv_payload => { + if (!location.isInitializer()) { + try w.writeByte('('); + try dg.renderType(w, ty); + try w.writeByte(')'); + } + try w.writeAll(if (safety_on) "{.is_null=0xaa}" else "{.is_null=false}"); + }, + + .@"struct" => { + if (!location.isInitializer()) { + try w.writeByte('('); + try dg.renderType(w, ty); + try w.writeByte(')'); + } + try w.writeAll("{ .is_null = "); + try dg.renderUndefValue(w, .bool, initializer_type); + try w.writeAll(", .payload = "); + try dg.renderUndefValue(w, .fromInterned(child_type), initializer_type); + try w.writeAll(" }"); + }, + }, .struct_type => { const loaded_struct = ip.loadStructType(ty.toIntern()); switch (loaded_struct.layout) { .auto, .@"extern" => { if (!location.isInitializer()) { try w.writeByte('('); - try dg.renderCType(w, ctype); + try dg.renderType(w, ty); try w.writeByte(')'); } - try w.writeByte('{'); var field_it = loaded_struct.iterateRuntimeOrder(ip); var need_comma = false; @@ -1601,7 +1464,7 @@ pub const DeclGen = struct { .tuple_type => |tuple_info| { if (!location.isInitializer()) { try w.writeByte('('); - try dg.renderCType(w, ctype); + try dg.renderType(w, ty); try w.writeByte(')'); } @@ -1624,80 +1487,61 @@ pub const DeclGen = struct { .auto, .@"extern" => { if (!location.isInitializer()) { try w.writeByte('('); - try dg.renderCType(w, ctype); + try dg.renderType(w, ty); try w.writeByte(')'); } - const has_tag = loaded_union.has_runtime_tag; - if (has_tag) try w.writeByte('{'); - const aggregate = ctype.info(ctype_pool).aggregate; - for (0..if (has_tag) aggregate.fields.len else 1) |outer_field_index| { - if (outer_field_index > 0) try w.writeByte(','); - switch (if (has_tag) - aggregate.fields.at(outer_field_index, ctype_pool).name.index - else - .payload) { - .tag => try dg.renderUndefValue( - w, - .fromInterned(loaded_union.enum_tag_type), - initializer_type, - ), - .payload => { - try w.writeByte('{'); - for (0..loaded_union.field_types.len) |inner_field_index| { - const inner_field_ty: Type = .fromInterned( - loaded_union.field_types.get(ip)[inner_field_index], - ); - if (!inner_field_ty.hasRuntimeBits(pt.zcu)) continue; - try dg.renderUndefValue( - w, - inner_field_ty, - initializer_type, - ); - break; - } - try w.writeByte('}'); - }, - else => unreachable, - } + const first_field_ty: Type = for (loaded_union.field_types.get(ip)) |field_ty_ip| { + const field_ty: Type = .fromInterned(field_ty_ip); + if (!field_ty.hasRuntimeBits(pt.zcu)) continue; + break field_ty; + } else { + assert(loaded_union.has_runtime_tag); // otherwise it does not have runtime bits + try w.writeAll("{ .tag = "); + try dg.renderUndefValue(w, .fromInterned(loaded_union.enum_tag_type), initializer_type); + try w.writeAll(" }"); + return; + }; + + if (loaded_union.layout == .auto) try w.writeByte('{'); + + if (loaded_union.has_runtime_tag) { + try w.writeAll(" .tag = "); + try dg.renderUndefValue(w, .fromInterned(loaded_union.enum_tag_type), initializer_type); + try w.writeAll(", .payload = "); } - if (has_tag) try w.writeByte('}'); + + try w.writeByte('{'); + try dg.renderUndefValue(w, first_field_ty, initializer_type); + try w.writeByte('}'); + + if (loaded_union.has_runtime_tag) try w.writeByte(' '); + if (loaded_union.layout == .auto) try w.writeByte('}'); }, .@"packed" => return dg.renderUndefValue(w, ty.bitpackBackingInt(zcu), location), } }, - .error_union_type => |error_union_type| switch (ctype.info(ctype_pool)) { - .basic => try dg.renderUndefValue( - w, - .fromInterned(error_union_type.error_set_type), - location, - ), - .pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable, - .aggregate => |aggregate| { - if (!location.isInitializer()) { - try w.writeByte('('); - try dg.renderCType(w, ctype); - try w.writeByte(')'); - } - try w.writeByte('{'); - for (0..aggregate.fields.len) |field_index| { - if (field_index > 0) try w.writeByte(','); - try dg.renderUndefValue( - w, - .fromInterned( - switch (aggregate.fields.at(field_index, ctype_pool).name.index) { - .@"error" => error_union_type.error_set_type, - .payload => error_union_type.payload_type, - else => unreachable, - }, - ), - initializer_type, - ); - } - try w.writeByte('}'); - }, + .error_union_type => |error_union| { + if (!location.isInitializer()) { + try w.writeByte('('); + try dg.renderType(w, ty); + try w.writeByte(')'); + } + try w.writeAll("{ .error = "); + try dg.renderUndefValue(w, .fromInterned(error_union.error_set_type), initializer_type); + if (Type.fromInterned(error_union.payload_type).hasRuntimeBits(zcu)) { + try w.writeAll(", .payload = "); + try dg.renderUndefValue(w, .fromInterned(error_union.payload_type), initializer_type); + } + try w.writeAll(" }"); }, .array_type, .vector_type => { + if (!location.isInitializer()) { + try w.writeByte('('); + try dg.renderType(w, ty); + try w.writeByte(')'); + } + try w.writeByte('{'); const ai = ty.arrayInfo(zcu); if (ai.elem_type.eql(.u8, zcu)) { var literal: StringLiteral = .init(w, @intCast(ty.arrayLenIncludingSentinel(zcu))); @@ -1708,14 +1552,8 @@ pub const DeclGen = struct { const s_u8: u8 = @intCast(s.toUnsignedInt(zcu)); if (s_u8 != 0) try literal.writeChar(s_u8); } - return literal.end(); + try literal.end(); } else { - if (!location.isInitializer()) { - try w.writeByte('('); - try dg.renderCType(w, ctype); - try w.writeByte(')'); - } - try w.writeByte('{'); var index: u64 = 0; while (index < ai.len) : (index += 1) { @@ -1726,8 +1564,9 @@ pub const DeclGen = struct { if (index > 0) try w.writeAll(", "); try dg.renderValue(w, s, location); } - return w.writeByte('}'); + try w.writeByte('}'); } + try w.writeByte('}'); }, .anyframe_type, .opaque_type, @@ -1762,10 +1601,11 @@ pub const DeclGen = struct { w: *Writer, fn_val: Value, fn_align: InternPool.Alignment, - kind: CType.Kind, + kind: enum { forward_decl, definition }, name: union(enum) { nav: InternPool.Nav.Index, - fmt_ctype_pool_string: std.fmt.Alt(CTypePoolStringFormatData, formatCTypePoolString), + nav_never_tail: InternPool.Nav.Index, + nav_never_inline: InternPool.Nav.Index, @"export": struct { main_name: InternPool.NullTerminatedString, extern_name: InternPool.NullTerminatedString, @@ -1776,14 +1616,12 @@ pub const DeclGen = struct { const ip = &zcu.intern_pool; const fn_ty = fn_val.typeOf(zcu); - const fn_ctype = try dg.ctypeFromType(fn_ty, kind); const fn_info = zcu.typeToFunc(fn_ty).?; if (fn_info.cc == .naked) { switch (kind) { - .forward => try w.writeAll("zig_naked_decl "), - .complete => try w.writeAll("zig_naked "), - else => unreachable, + .forward_decl => try w.writeAll("zig_naked_decl "), + .definition => try w.writeAll("zig_naked "), } } @@ -1793,45 +1631,63 @@ pub const DeclGen = struct { if (func_analysis.branch_hint == .cold) try w.writeAll("zig_cold "); - if (kind == .complete and func_analysis.disable_intrinsics or dg.mod.no_builtin) + if (kind == .definition and func_analysis.disable_intrinsics or dg.mod.no_builtin) try w.writeAll("zig_no_builtin "); } if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn "); - var trailing = try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, fn_ctype, .suffix, .{}); + // While incomplete types are usually an acceptable substitute for "void", this is not true + // in function return types, where "void" is the only incomplete type permitted. + const actual_return_type: Type = .fromInterned(fn_info.return_type); + const effective_return_type: Type = switch (actual_return_type.classify(zcu)) { + .no_possible_value => .noreturn, + .one_possible_value, .fully_comptime => .void, // no runtime bits + .partially_comptime, .runtime => actual_return_type, // yes runtime bits + }; + const ret_cty: CType = try .lower(effective_return_type, &dg.ctype_deps, dg.arena, zcu); + try w.print("{f}", .{ret_cty.fmtDeclaratorPrefix(zcu)}); if (toCallingConvention(fn_info.cc, zcu)) |call_conv| { - try w.print("{f}zig_callconv({s})", .{ trailing, call_conv }); - trailing = .maybe_space; + try w.print("zig_callconv({s}) ", .{call_conv}); } - - try w.print("{f}", .{trailing}); switch (name) { - .nav => |nav| try dg.renderNavName(w, nav), - .fmt_ctype_pool_string => |fmt| try w.print("{f}", .{fmt}), + .nav => |nav| try renderNavName(w, nav, ip), + .nav_never_tail => |nav| try w.print("zig_never_tail_{f}__{d}", .{ + fmtIdentUnsolo(ip.getNav(nav).name.toSlice(ip)), @intFromEnum(nav), + }), + .nav_never_inline => |nav| try w.print("zig_never_inline_{f}__{d}", .{ + fmtIdentUnsolo(ip.getNav(nav).name.toSlice(ip)), @intFromEnum(nav), + }), .@"export" => |@"export"| try w.print("{f}", .{fmtIdentSolo(@"export".extern_name.toSlice(ip))}), } - - try renderTypeSuffix( - dg.pass, - &dg.ctype_pool, - zcu, - w, - fn_ctype, - .suffix, - CQualifiers.init(.{ .@"const" = switch (kind) { - .forward => false, - .complete => true, - else => unreachable, - } }), - ); + { + try w.writeByte('('); + var c_param_index: u32 = 0; + for (fn_info.param_types.get(ip)) |param_ty_ip| { + const param_ty: Type = .fromInterned(param_ty_ip); + if (!param_ty.hasRuntimeBits(zcu)) continue; + if (c_param_index != 0) try w.writeAll(", "); + try dg.renderTypeAndName(w, param_ty, .{ .arg = c_param_index }, .{ + .@"const" = kind == .definition, + }, .none); + c_param_index += 1; + } + if (fn_info.is_var_args) { + if (c_param_index != 0) try w.writeAll(", "); + try w.writeAll("..."); + } else if (c_param_index == 0) { + try w.writeAll("void"); + } + try w.writeByte(')'); + } + try w.print("{f}", .{ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu)}); switch (kind) { - .forward => { + .forward_decl => { if (fn_align.toByteUnits()) |a| try w.print(" zig_align_fn({})", .{a}); switch (name) { - .nav, .fmt_ctype_pool_string => {}, + .nav, .nav_never_tail, .nav_never_inline => {}, .@"export" => |@"export"| { const extern_name = @"export".extern_name.toSlice(ip); const is_mangled = isMangledIdent(extern_name, true); @@ -1855,38 +1711,16 @@ pub const DeclGen = struct { }, } }, - .complete => {}, - else => unreachable, + .definition => {}, } } - fn ctypeFromType(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType { - defer std.debug.assert(dg.scratch.items.len == 0); - return dg.ctype_pool.fromType(dg.gpa, &dg.scratch, ty, dg.pt, dg.mod, kind); - } - - fn byteSize(dg: *DeclGen, ctype: CType) u64 { - return ctype.byteSize(&dg.ctype_pool, dg.mod); - } - - /// Renders a type as a single identifier, generating intermediate typedefs - /// if necessary. - /// - /// This is guaranteed to be valid in both typedefs and declarations/definitions. - /// - /// There are three type formats in total that we support rendering: - /// | Function | Example 1 (*u8) | Example 2 ([10]*u8) | - /// |---------------------|-----------------|---------------------| - /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" | - /// | `renderType` | "uint8_t *" | "uint8_t *[10]" | - /// - fn renderType(dg: *DeclGen, w: *Writer, t: Type) Error!void { - try dg.renderCType(w, try dg.ctypeFromType(t, .complete)); - } - - fn renderCType(dg: *DeclGen, w: *Writer, ctype: CType) Error!void { - _ = try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.pt.zcu, w, ctype, .suffix, .{}); - try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.pt.zcu, w, ctype, .suffix, .{}); + /// Renders the C lowering of the given Zig type to `w`. This renders the type name---to render + /// a declarator with this type, see instead `renderTypeAndName`. + fn renderType(dg: *DeclGen, w: *Writer, ty: Type) (Writer.Error || Allocator.Error)!void { + const zcu = dg.pt.zcu; + const cty: CType = try .lower(ty, &dg.ctype_deps, dg.arena, zcu); + try w.print("{f}", .{cty.fmtTypeName(zcu)}); } const IntCastContext = union(enum) { @@ -1990,7 +1824,7 @@ pub const DeclGen = struct { try w.writeAll("zig_lo_"); try dg.renderTypeForBuiltinFnName(w, src_eff_ty); try w.writeByte('('); - try context.writeValue(dg, w, .FunctionArgument); + try context.writeValue(dg, w, .other); try w.writeByte(')'); } else if (dest_bits > 64 and src_bits <= 64) { try w.writeAll("zig_make_"); @@ -2001,7 +1835,7 @@ pub const DeclGen = struct { try dg.renderType(w, src_eff_ty); try w.writeByte(')'); } - try context.writeValue(dg, w, .FunctionArgument); + try context.writeValue(dg, w, .other); try w.writeByte(')'); } else { assert(!src_is_ptr); @@ -2010,23 +1844,16 @@ pub const DeclGen = struct { try w.writeAll("(zig_hi_"); try dg.renderTypeForBuiltinFnName(w, src_eff_ty); try w.writeByte('('); - try context.writeValue(dg, w, .FunctionArgument); + try context.writeValue(dg, w, .other); try w.writeAll("), zig_lo_"); try dg.renderTypeForBuiltinFnName(w, src_eff_ty); try w.writeByte('('); - try context.writeValue(dg, w, .FunctionArgument); + try context.writeValue(dg, w, .other); try w.writeAll("))"); } } - /// Renders a type and name in field declaration/definition format. - /// - /// There are three type formats in total that we support rendering: - /// | Function | Example 1 (*u8) | Example 2 ([10]*u8) | - /// |---------------------|-----------------|---------------------| - /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" | - /// | `renderType` | "uint8_t *" | "uint8_t *[10]" | - /// + /// Renders to `w` a C declarator whose type is the C lowering of the given Zig type. fn renderTypeAndName( dg: *DeclGen, w: *Writer, @@ -2034,73 +1861,47 @@ pub const DeclGen = struct { name: CValue, qualifiers: CQualifiers, alignment: Alignment, - kind: CType.Kind, - ) !void { - try dg.renderCTypeAndName( - w, - try dg.ctypeFromType(ty, kind), - name, - qualifiers, - CType.AlignAs.fromAlignment(.{ - .@"align" = alignment, - .abi = ty.abiAlignment(dg.pt.zcu), - }), - ); - } - - fn renderCTypeAndName( - dg: *DeclGen, - w: *Writer, - ctype: CType, - name: CValue, - qualifiers: CQualifiers, - alignas: CType.AlignAs, ) !void { const zcu = dg.pt.zcu; - switch (alignas.abiOrder()) { - .lt => try w.print("zig_under_align({}) ", .{alignas.toByteUnits()}), + const ip = &zcu.intern_pool; + const cty: CType = try .lower(ty, &dg.ctype_deps, dg.arena, zcu); + try w.print("{f}", .{cty.fmtDeclaratorPrefix(zcu)}); + if (alignment != .none) switch (alignment.order(ty.abiAlignment(zcu))) { + .lt => try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?}), .eq => {}, - .gt => try w.print("zig_align({}) ", .{alignas.toByteUnits()}), - } - - try w.print("{f}", .{ - try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, ctype, .suffix, qualifiers), - }); - try dg.writeName(w, name); - try renderTypeSuffix(dg.pass, &dg.ctype_pool, zcu, w, ctype, .suffix, .{}); - if (ctype.isNonString(&dg.ctype_pool)) try w.writeAll(" zig_nonstring"); - } - - fn writeName(dg: *DeclGen, w: *Writer, c_value: CValue) !void { - switch (c_value) { + .gt => try w.print("zig_align({d}) ", .{alignment.toByteUnits().?}), + }; + if (qualifiers.@"const") try w.writeAll("const "); + if (qualifiers.@"volatile") try w.writeAll("volatile "); + if (qualifiers.restrict) try w.writeAll("restrict "); + switch (name) { .new_local, .local => |i| try w.print("t{d}", .{i}), + .arg => |i| try w.print("a{d}", .{i}), .constant => |uav| try renderUavName(w, uav), - .nav => |nav| try dg.renderNavName(w, nav), + .nav => |nav| try renderNavName(w, nav, ip), .identifier => |ident| try w.print("{f}", .{fmtIdentSolo(ident)}), else => unreachable, } + try w.print("{f}", .{cty.fmtDeclaratorSuffix(zcu)}); } fn writeCValue(dg: *DeclGen, w: *Writer, c_value: CValue) Error!void { switch (c_value) { .none, .new_local, .local, .local_ref => unreachable, .constant => |uav| try renderUavName(w, uav), - .arg, .arg_array => unreachable, + .arg => unreachable, .field => |i| try w.print("f{d}", .{i}), - .nav => |nav| try dg.renderNavName(w, nav), + .nav => |nav| try renderNavName(w, nav, &dg.pt.zcu.intern_pool), .nav_ref => |nav| { try w.writeByte('&'); - try dg.renderNavName(w, nav); + try renderNavName(w, nav, &dg.pt.zcu.intern_pool); }, - .undef => |ty| try dg.renderUndefValue(w, ty, .Other), + .undef => |ty| try dg.renderUndefValue(w, ty, .other), .identifier => |ident| try w.print("{f}", .{fmtIdentSolo(ident)}), .payload_identifier => |ident| try w.print("{f}.{f}", .{ fmtIdentSolo("payload"), fmtIdentSolo(ident), }), - .ctype_pool_string => |string| try w.print("{f}", .{ - fmtCTypePoolString(string, &dg.ctype_pool, true), - }), } } @@ -2112,16 +1913,14 @@ pub const DeclGen = struct { .local_ref, .constant, .arg, - .arg_array, - .ctype_pool_string, => unreachable, .field => |i| try w.print("f{d}", .{i}), .nav => |nav| { try w.writeAll("(*"); - try dg.renderNavName(w, nav); + try renderNavName(w, nav, &dg.pt.zcu.intern_pool); try w.writeByte(')'); }, - .nav_ref => |nav| try dg.renderNavName(w, nav), + .nav_ref => |nav| try renderNavName(w, nav, &dg.pt.zcu.intern_pool), .undef => unreachable, .identifier => |ident| try w.print("(*{f})", .{fmtIdentSolo(ident)}), .payload_identifier => |ident| try w.print("(*{f}.{f})", .{ @@ -2157,8 +1956,6 @@ pub const DeclGen = struct { .field, .undef, .arg, - .arg_array, - .ctype_pool_string, => unreachable, .nav, .identifier, .payload_identifier => { try dg.writeCValue(w, c_value); @@ -2172,101 +1969,36 @@ pub const DeclGen = struct { try dg.writeCValue(w, member); } - fn renderFwdDecl( - dg: *DeclGen, - nav_index: InternPool.Nav.Index, - flags: packed struct { - is_const: bool, - is_threadlocal: bool, - linkage: std.builtin.GlobalLinkage, - visibility: std.builtin.SymbolVisibility, - }, - ) !void { - const zcu = dg.pt.zcu; - const ip = &zcu.intern_pool; - const nav = ip.getNav(nav_index); - const fwd = &dg.fwd_decl.writer; - try fwd.writeAll(switch (flags.linkage) { - .internal => "static ", - .strong, .weak, .link_once => "zig_extern ", - }); - switch (flags.linkage) { - .internal, .strong => {}, - .weak => try fwd.writeAll("zig_weak_linkage "), - .link_once => return dg.fail("TODO: CBE: implement linkonce linkage?", .{}), - } - switch (flags.linkage) { - .internal => {}, - .strong, .weak, .link_once => try fwd.print("zig_visibility({s}) ", .{@tagName(flags.visibility)}), - } - if (flags.is_threadlocal and !dg.mod.single_threaded) try fwd.writeAll("zig_threadlocal "); - try dg.renderTypeAndName( - fwd, - .fromInterned(nav.typeOf(ip)), - .{ .nav = nav_index }, - CQualifiers.init(.{ .@"const" = flags.is_const }), - nav.getAlignment(), - .complete, - ); - try fwd.writeAll(";\n"); - } - - fn renderNavName(dg: *DeclGen, w: *Writer, nav_index: InternPool.Nav.Index) !void { - const zcu = dg.pt.zcu; - const ip = &zcu.intern_pool; - const nav = ip.getNav(nav_index); - if (nav.getExtern(ip)) |@"extern"| { - try w.print("{f}", .{ - fmtIdentSolo(ip.getNav(@"extern".owner_nav).name.toSlice(ip)), - }); - } else { - // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case), - // expand to 3x the length of its input, but let's cut it off at a much shorter limit. - const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip); - try w.print("{f}__{d}", .{ - fmtIdentUnsolo(fqn_slice[0..@min(fqn_slice.len, 100)]), - @intFromEnum(nav_index), - }); - } - } - - fn renderUavName(w: *Writer, uav: Value) !void { - try w.print("__anon_{d}", .{@intFromEnum(uav.toIntern())}); - } - fn renderTypeForBuiltinFnName(dg: *DeclGen, w: *Writer, ty: Type) !void { - try dg.renderCTypeForBuiltinFnName(w, try dg.ctypeFromType(ty, .complete)); - } - - fn renderCTypeForBuiltinFnName(dg: *DeclGen, w: *Writer, ctype: CType) !void { - switch (ctype.info(&dg.ctype_pool)) { - else => |ctype_info| try w.print("{c}{d}", .{ - if (ctype.isBool()) - signAbbrev(.unsigned) - else if (ctype.isInteger()) - signAbbrev(ctype.signedness(dg.mod)) - else if (ctype.isFloat()) - @as(u8, 'f') - else if (ctype_info == .pointer) - @as(u8, 'p') - else - return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for {s} type", .{@tagName(ctype_info)}), - if (ctype.isFloat()) ctype.floatActiveBits(dg.mod) else dg.byteSize(ctype) * 8, + const zcu = dg.pt.zcu; + switch (ty.zigTypeTag(zcu)) { + .bool => return w.writeAll("u8"), + .float => return w.print("f{d}", .{ty.floatBits(zcu.getTarget())}), + else => {}, + } + if (ty.isPtrAtRuntime(zcu)) { + return w.print("p{d}", .{zcu.getTarget().ptrBitWidth()}); + } + switch (CType.classifyInt(ty, zcu)) { + .void => unreachable, // opv + .small => try w.print("{c}{d}", .{ + signAbbrev(ty.intInfo(zcu).signedness), + ty.abiSize(zcu) * 8, }), - .array => try w.writeAll("big"), + .big => try w.writeAll("big"), } } fn renderBuiltinInfo(dg: *DeclGen, w: *Writer, ty: Type, info: BuiltinInfo) !void { - const ctype = try dg.ctypeFromType(ty, .complete); - const is_big = ctype.info(&dg.ctype_pool) == .array; + const pt = dg.pt; + const zcu = pt.zcu; + + const is_big = lowersToBigInt(ty, zcu); switch (info) { .none => if (!is_big) return, .bits => {}, } - const pt = dg.pt; - const zcu = pt.zcu; const int_info: std.builtin.Type.Int = if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else .{ .signedness = .unsigned, .bits = @intCast(ty.bitSize(zcu)), @@ -2275,7 +2007,7 @@ pub const DeclGen = struct { if (is_big) try w.print(", {}", .{int_info.signedness == .signed}); try w.print(", {f}", .{try dg.fmtIntLiteralDec( try pt.intValue(if (is_big) .u16 else .u8, int_info.bits), - .FunctionArgument, + .other, )}); } @@ -2286,15 +2018,13 @@ pub const DeclGen = struct { base: u8, case: std.fmt.Case, ) !std.fmt.Alt(FormatIntLiteralContext, formatIntLiteral) { - const zcu = dg.pt.zcu; - const kind = loc.toCTypeKind(); - const ty = val.typeOf(zcu); + // If there's a bigint type involved, mark a dependency on it. + const cty: CType = try .lower(val.typeOf(dg.pt.zcu), &dg.ctype_deps, dg.arena, dg.pt.zcu); return .{ .data = .{ .dg = dg, - .int_info = ty.intInfo(zcu), - .kind = kind, - .ctype = try dg.ctypeFromType(ty, kind), + .loc = loc, .val = val, + .cty = cty, .base = base, .case = case, } }; @@ -2317,339 +2047,11 @@ pub const DeclGen = struct { } }; -const CTypeFix = enum { prefix, suffix }; -const CQualifiers = std.enums.EnumSet(enum { @"const", @"volatile", restrict }); -const Const = CQualifiers.init(.{ .@"const" = true }); -const RenderCTypeTrailing = enum { - no_space, - maybe_space, - - pub fn format(self: @This(), w: *Writer) Writer.Error!void { - switch (self) { - .no_space => {}, - .maybe_space => try w.writeByte(' '), - } - } +const CQualifiers = packed struct { + @"const": bool = false, + @"volatile": bool = false, + restrict: bool = false, }; -fn renderAlignedTypeName(w: *Writer, ctype: CType) !void { - try w.print("anon__aligned_{d}", .{@intFromEnum(ctype.index)}); -} -fn renderFwdDeclTypeName( - zcu: *Zcu, - w: *Writer, - ctype: CType, - fwd_decl: CType.Info.FwdDecl, - attributes: []const u8, -) !void { - const ip = &zcu.intern_pool; - try w.print("{s} {s}", .{ @tagName(fwd_decl.tag), attributes }); - switch (fwd_decl.name) { - .anon => try w.print("anon__lazy_{d}", .{@intFromEnum(ctype.index)}), - .index => |index| try w.print("{f}__{d}", .{ - fmtIdentUnsolo(Type.fromInterned(index).containerTypeName(ip).toSlice(&zcu.intern_pool)), - @intFromEnum(index), - }), - } -} -fn renderTypePrefix( - pass: DeclGen.Pass, - ctype_pool: *const CType.Pool, - zcu: *Zcu, - w: *Writer, - ctype: CType, - parent_fix: CTypeFix, - qualifiers: CQualifiers, -) Writer.Error!RenderCTypeTrailing { - var trailing = RenderCTypeTrailing.maybe_space; - switch (ctype.info(ctype_pool)) { - .basic => |basic_info| try w.writeAll(@tagName(basic_info)), - - .pointer => |pointer_info| { - try w.print("{f}*", .{try renderTypePrefix( - pass, - ctype_pool, - zcu, - w, - pointer_info.elem_ctype, - .prefix, - CQualifiers.init(.{ - .@"const" = pointer_info.@"const", - .@"volatile" = pointer_info.@"volatile", - }), - )}); - trailing = .no_space; - }, - - .aligned => switch (pass) { - .nav => |nav| try w.print("nav__{d}_{d}", .{ - @intFromEnum(nav), @intFromEnum(ctype.index), - }), - .uav => |uav| try w.print("uav__{d}_{d}", .{ - @intFromEnum(uav), @intFromEnum(ctype.index), - }), - .flush => try renderAlignedTypeName(w, ctype), - }, - - .array, .vector => |sequence_info| { - const child_trailing = try renderTypePrefix( - pass, - ctype_pool, - zcu, - w, - sequence_info.elem_ctype, - .suffix, - qualifiers, - ); - switch (parent_fix) { - .prefix => { - try w.print("{f}(", .{child_trailing}); - return .no_space; - }, - .suffix => return child_trailing, - } - }, - - .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) { - .anon => switch (pass) { - .nav => |nav| try w.print("nav__{d}_{d}", .{ - @intFromEnum(nav), @intFromEnum(ctype.index), - }), - .uav => |uav| try w.print("uav__{d}_{d}", .{ - @intFromEnum(uav), @intFromEnum(ctype.index), - }), - .flush => try renderFwdDeclTypeName(zcu, w, ctype, fwd_decl_info, ""), - }, - .index => try renderFwdDeclTypeName(zcu, w, ctype, fwd_decl_info, ""), - }, - - .aggregate => |aggregate_info| switch (aggregate_info.name) { - .anon => { - try w.print("{s} {s}", .{ - @tagName(aggregate_info.tag), - if (aggregate_info.@"packed") "zig_packed(" else "", - }); - try renderFields(zcu, w, ctype_pool, aggregate_info, 1); - if (aggregate_info.@"packed") try w.writeByte(')'); - }, - .fwd_decl => |fwd_decl| return renderTypePrefix( - pass, - ctype_pool, - zcu, - w, - fwd_decl, - parent_fix, - qualifiers, - ), - }, - - .function => |function_info| { - const child_trailing = try renderTypePrefix( - pass, - ctype_pool, - zcu, - w, - function_info.return_ctype, - .suffix, - .{}, - ); - switch (parent_fix) { - .prefix => { - try w.print("{f}(", .{child_trailing}); - return .no_space; - }, - .suffix => return child_trailing, - } - }, - } - var qualifier_it = qualifiers.iterator(); - while (qualifier_it.next()) |qualifier| { - try w.print("{f}{s}", .{ trailing, @tagName(qualifier) }); - trailing = .maybe_space; - } - return trailing; -} -fn renderTypeSuffix( - pass: DeclGen.Pass, - ctype_pool: *const CType.Pool, - zcu: *Zcu, - w: *Writer, - ctype: CType, - parent_fix: CTypeFix, - qualifiers: CQualifiers, -) Writer.Error!void { - switch (ctype.info(ctype_pool)) { - .basic, .aligned, .fwd_decl, .aggregate => {}, - .pointer => |pointer_info| try renderTypeSuffix( - pass, - ctype_pool, - zcu, - w, - pointer_info.elem_ctype, - .prefix, - .{}, - ), - .array, .vector => |sequence_info| { - switch (parent_fix) { - .prefix => try w.writeByte(')'), - .suffix => {}, - } - - try w.print("[{}]", .{sequence_info.len}); - try renderTypeSuffix(pass, ctype_pool, zcu, w, sequence_info.elem_ctype, .suffix, .{}); - }, - .function => |function_info| { - switch (parent_fix) { - .prefix => try w.writeByte(')'), - .suffix => {}, - } - - try w.writeByte('('); - var need_comma = false; - for (0..function_info.param_ctypes.len) |param_index| { - const param_type = function_info.param_ctypes.at(param_index, ctype_pool); - if (need_comma) try w.writeAll(", "); - need_comma = true; - const trailing = - try renderTypePrefix(pass, ctype_pool, zcu, w, param_type, .suffix, qualifiers); - if (qualifiers.contains(.@"const")) try w.print("{f}a{d}", .{ trailing, param_index }); - try renderTypeSuffix(pass, ctype_pool, zcu, w, param_type, .suffix, .{}); - } - if (function_info.varargs) { - if (need_comma) try w.writeAll(", "); - need_comma = true; - try w.writeAll("..."); - } - if (!need_comma) try w.writeAll("void"); - try w.writeByte(')'); - - try renderTypeSuffix(pass, ctype_pool, zcu, w, function_info.return_ctype, .suffix, .{}); - }, - } -} -fn renderFields( - zcu: *Zcu, - w: *Writer, - ctype_pool: *const CType.Pool, - aggregate_info: CType.Info.Aggregate, - indent: usize, -) !void { - try w.writeAll("{\n"); - for (0..aggregate_info.fields.len) |field_index| { - const field_info = aggregate_info.fields.at(field_index, ctype_pool); - try w.splatByteAll(' ', indent + 1); - switch (field_info.alignas.abiOrder()) { - .lt => { - std.debug.assert(aggregate_info.@"packed"); - if (field_info.alignas.@"align" != .@"1") try w.print("zig_under_align({}) ", .{ - field_info.alignas.toByteUnits(), - }); - }, - .eq => if (aggregate_info.@"packed" and field_info.alignas.@"align" != .@"1") - try w.print("zig_align({}) ", .{field_info.alignas.toByteUnits()}), - .gt => { - std.debug.assert(field_info.alignas.@"align" != .@"1"); - try w.print("zig_align({}) ", .{field_info.alignas.toByteUnits()}); - }, - } - const trailing = try renderTypePrefix( - .flush, - ctype_pool, - zcu, - w, - field_info.ctype, - .suffix, - .{}, - ); - try w.print("{f}{f}", .{ trailing, fmtCTypePoolString(field_info.name, ctype_pool, true) }); - try renderTypeSuffix(.flush, ctype_pool, zcu, w, field_info.ctype, .suffix, .{}); - if (field_info.ctype.isNonString(ctype_pool)) try w.writeAll(" zig_nonstring"); - try w.writeAll(";\n"); - } - try w.splatByteAll(' ', indent); - try w.writeByte('}'); -} - -pub fn genTypeDecl( - zcu: *Zcu, - w: *Writer, - global_ctype_pool: *const CType.Pool, - global_ctype: CType, - pass: DeclGen.Pass, - decl_ctype_pool: *const CType.Pool, - decl_ctype: CType, - found_existing: bool, -) !void { - switch (global_ctype.info(global_ctype_pool)) { - .basic, .pointer, .array, .vector, .function => {}, - .aligned => |aligned_info| { - if (!found_existing) { - std.debug.assert(aligned_info.alignas.abiOrder().compare(.lt)); - try w.print("typedef zig_under_align({d}) ", .{aligned_info.alignas.toByteUnits()}); - try w.print("{f}", .{try renderTypePrefix( - .flush, - global_ctype_pool, - zcu, - w, - aligned_info.ctype, - .suffix, - .{}, - )}); - try renderAlignedTypeName(w, global_ctype); - try renderTypeSuffix(.flush, global_ctype_pool, zcu, w, aligned_info.ctype, .suffix, .{}); - try w.writeAll(";\n"); - } - switch (pass) { - .nav, .uav => { - try w.writeAll("typedef "); - _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, w, global_ctype, .suffix, .{}); - try w.writeByte(' '); - _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, w, decl_ctype, .suffix, .{}); - try w.writeAll(";\n"); - }, - .flush => {}, - } - }, - .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) { - .anon => switch (pass) { - .nav, .uav => { - try w.writeAll("typedef "); - _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, w, global_ctype, .suffix, .{}); - try w.writeByte(' '); - _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, w, decl_ctype, .suffix, .{}); - try w.writeAll(";\n"); - }, - .flush => {}, - }, - .index => |index| if (!found_existing) { - const ip = &zcu.intern_pool; - const ty: Type = .fromInterned(index); - _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, w, global_ctype, .suffix, .{}); - try w.writeByte(';'); - const file_scope = ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip); - if (!zcu.fileByIndex(file_scope).mod.?.strip) try w.print(" /* {f} */", .{ - ty.containerTypeName(ip).fmt(ip), - }); - try w.writeByte('\n'); - }, - }, - .aggregate => |aggregate_info| switch (aggregate_info.name) { - .anon => {}, - .fwd_decl => |fwd_decl| if (!found_existing) { - try renderFwdDeclTypeName( - zcu, - w, - fwd_decl, - fwd_decl.info(global_ctype_pool).fwd_decl, - if (aggregate_info.@"packed") "zig_packed(" else "", - ); - try w.writeByte(' '); - try renderFields(zcu, w, global_ctype_pool, aggregate_info, 0); - if (aggregate_info.@"packed") try w.writeByte(')'); - try w.writeAll(";\n"); - }, - }, - } -} pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void { for (zcu.global_assembly.values()) |asm_source| { @@ -2657,200 +2059,128 @@ pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void { } } -pub fn genErrDecls(o: *Object) Error!void { - const pt = o.dg.pt; - const zcu = pt.zcu; +pub fn genErrDecls( + zcu: *const Zcu, + w: *Writer, + slice_const_u8_sentinel_0_type_name: []const u8, +) Writer.Error!void { const ip = &zcu.intern_pool; - const w = &o.code.writer; - var max_name_len: usize = 0; - // do not generate an invalid empty enum when the global error set is empty const names = ip.global_error_set.getNamesFromMainThread(); + // Don't generate an invalid empty enum if the global error set is empty! if (names.len > 0) { - try w.writeAll("enum {"); - o.indent(); - try o.newline(); + try w.writeAll("enum {\n"); for (names, 1..) |name_nts, value| { - const name = name_nts.toSlice(ip); - max_name_len = @max(name.len, max_name_len); - const err_val = try pt.intern(.{ .err = .{ - .ty = .anyerror_type, - .name = name_nts, - } }); - try o.dg.renderValue(w, Value.fromInterned(err_val), .Other); - try w.print(" = {d}u,", .{value}); - try o.newline(); + try w.writeByte(' '); + try renderErrorName(w, name_nts.toSlice(ip)); + try w.print(" = {d}u,\n", .{value}); } - try o.outdent(); - try w.writeAll("};"); - try o.newline(); + try w.writeAll("};\n"); } - const array_identifier = "zig_errorName"; - const name_prefix = array_identifier ++ "_"; - const name_buf = try o.dg.gpa.alloc(u8, name_prefix.len + max_name_len); - defer o.dg.gpa.free(name_buf); - @memcpy(name_buf[0..name_prefix.len], name_prefix); - for (names) |name| { - const name_slice = name.toSlice(ip); - @memcpy(name_buf[name_prefix.len..][0..name_slice.len], name_slice); - const identifier = name_buf[0 .. name_prefix.len + name_slice.len]; - - const name_ty = try pt.arrayType(.{ - .len = name_slice.len, - .child = .u8_type, - .sentinel = .zero_u8, - }); - const name_val = try pt.intern(.{ .aggregate = .{ - .ty = name_ty.toIntern(), - .storage = .{ .bytes = name.toString() }, - } }); - - try w.writeAll("static "); - try o.dg.renderTypeAndName( - w, - name_ty, - .{ .identifier = identifier }, - Const, - .none, - .complete, + for (names) |name_nts| { + const name = name_nts.toSlice(ip); + try w.print( + "static uint8_t const zig_errorName_{f}[] = {f};\n", + .{ fmtIdentUnsolo(name), fmtStringLiteral(name, 0) }, ); - try w.writeAll(" = "); - try o.dg.renderValue(w, Value.fromInterned(name_val), .StaticInitializer); - try w.writeByte(';'); - try o.newline(); } - const name_array_ty = try pt.arrayType(.{ - .len = 1 + names.len, - .child = .slice_const_u8_sentinel_0_type, - }); - - try w.writeAll("static "); - try o.dg.renderTypeAndName( - w, - name_array_ty, - .{ .identifier = array_identifier }, - Const, - .none, - .complete, + try w.print( + "static {s} const zig_errorName[{d}] = {{", + .{ slice_const_u8_sentinel_0_type_name, names.len }, ); - try w.writeAll(" = {"); - for (names, 1..) |name_nts, val| { + if (names.len > 0) try w.writeByte('\n'); + for (names) |name_nts| { const name = name_nts.toSlice(ip); - if (val > 1) try w.writeAll(", "); - try w.print("{{" ++ name_prefix ++ "{f}, {f}}}", .{ - fmtIdentUnsolo(name), - try o.dg.fmtIntLiteralDec(try pt.intValue(.usize, name.len), .StaticInitializer), - }); + try w.print( + " {{zig_errorName_{f},{d}}},\n", + .{ fmtIdentUnsolo(name), name.len }, + ); } - try w.writeAll("};"); - try o.newline(); + try w.writeAll("};\n"); } -pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFnMap.Entry) Error!void { - const pt = o.dg.pt; - const zcu = pt.zcu; +pub fn genTagNameFn( + zcu: *const Zcu, + w: *Writer, + slice_const_u8_sentinel_0_type_name: []const u8, + enum_ty: Type, + enum_type_name: []const u8, +) Writer.Error!void { const ip = &zcu.intern_pool; - const ctype_pool = &o.dg.ctype_pool; - const w = &o.code.writer; - const key = lazy_fn.key_ptr.*; - const val = lazy_fn.value_ptr; - switch (key) { - .tag_name => |enum_ty_ip| { - const enum_ty: Type = .fromInterned(enum_ty_ip); - const name_slice_ty: Type = .slice_const_u8_sentinel_0; + const loaded_enum = ip.loadEnumType(enum_ty.toIntern()); + assert(loaded_enum.field_names.len > 0); + if (Type.fromInterned(loaded_enum.int_tag_type).bitSize(zcu) > 64) { + @panic("TODO CBE: tagName for enum over 128 bits"); + } - try w.writeAll("static "); - try o.dg.renderType(w, name_slice_ty); - try w.print(" {f}(", .{val.fn_name.fmt(lazy_ctype_pool)}); - try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete); - try w.writeAll(") {"); - o.indent(); - try o.newline(); - try w.writeAll("switch (tag) {"); - o.indent(); - try o.newline(); - const tag_names = enum_ty.enumFields(zcu); - for (0..tag_names.len) |tag_index| { - const tag_name = tag_names.get(ip)[tag_index]; - const tag_name_len = tag_name.length(ip); - const tag_val = try pt.enumValueFieldIndex(enum_ty, @intCast(tag_index)); + try w.print("static {s} zig_tagName_{f}__{d}({s} tag) {{\n", .{ + slice_const_u8_sentinel_0_type_name, + fmtIdentUnsolo(loaded_enum.name.toSlice(ip)), + @intFromEnum(enum_ty.toIntern()), + enum_type_name, + }); + for (loaded_enum.field_names.get(ip), 0..) |field_name, field_index| { + try w.print(" static uint8_t const name{d}[] = {f};\n", .{ + field_index, fmtStringLiteral(field_name.toSlice(ip), 0), + }); + } - const name_ty = try pt.arrayType(.{ - .len = tag_name_len, - .child = .u8_type, - .sentinel = .zero_u8, - }); - const name_val = try pt.intern(.{ .aggregate = .{ - .ty = name_ty.toIntern(), - .storage = .{ .bytes = tag_name.toString() }, - } }); + try w.writeAll(" switch (tag) {\n"); + const field_values = loaded_enum.field_values.get(ip); + for (loaded_enum.field_names.get(ip), 0..) |field_name, field_index| { + const field_int: u64 = int: { + if (field_values.len == 0) break :int field_index; + const field_val: Value = .fromInterned(field_values[field_index]); + break :int field_val.toUnsignedInt(zcu); + }; + try w.print(" case {d}: return ({s}){{name{d},{d}}};\n", .{ + field_int, + slice_const_u8_sentinel_0_type_name, + field_index, + field_name.toSlice(ip).len, + }); + } + try w.writeAll( + \\ } + \\ zig_unreachable(); + \\} + \\ + ); +} - try w.print("case {f}: {{", .{ - try o.dg.fmtIntLiteralDec(tag_val.intFromEnum(zcu), .Other), - }); - o.indent(); - try o.newline(); - try w.writeAll("static "); - try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, .none, .complete); - try w.writeAll(" = "); - try o.dg.renderValue(w, Value.fromInterned(name_val), .StaticInitializer); - try w.writeByte(';'); - try o.newline(); - try w.writeAll("return ("); - try o.dg.renderType(w, name_slice_ty); - try w.print("){{{f}, {f}}};", .{ - fmtIdentUnsolo("name"), - try o.dg.fmtIntLiteralDec(try pt.intValue(.usize, tag_name_len), .Other), - }); - try o.newline(); - try o.outdent(); - try w.writeByte('}'); - try o.newline(); - } - try o.outdent(); - try w.writeByte('}'); - try o.newline(); - try airUnreach(o); - try o.outdent(); - try w.writeByte('}'); - try o.newline(); - }, - .never_tail, .never_inline => |fn_nav_index| { - const fn_val = zcu.navValue(fn_nav_index); - const fn_ctype = try o.dg.ctypeFromType(fn_val.typeOf(zcu), .complete); - const fn_info = fn_ctype.info(ctype_pool).function; - const fn_name = fmtCTypePoolString(val.fn_name, lazy_ctype_pool, true); +pub fn genLazyCallModifierFn( + dg: *DeclGen, + fn_nav: InternPool.Nav.Index, + kind: enum { never_tail, never_inline }, + w: *Writer, +) Error!void { + const zcu = dg.pt.zcu; + const ip = &zcu.intern_pool; - const fwd = &o.dg.fwd_decl.writer; - try fwd.print("static zig_{s} ", .{@tagName(key)}); - try o.dg.renderFunctionSignature(fwd, fn_val, ip.getNav(fn_nav_index).getAlignment(), .forward, .{ - .fmt_ctype_pool_string = fn_name, - }); - try fwd.writeAll(";\n"); + const fn_val = zcu.navValue(fn_nav); - try w.print("zig_{s} ", .{@tagName(key)}); - try o.dg.renderFunctionSignature(w, fn_val, .none, .complete, .{ - .fmt_ctype_pool_string = fn_name, - }); - try w.writeAll(" {"); - o.indent(); - try o.newline(); - try w.writeAll("return "); - try o.dg.renderNavName(w, fn_nav_index); - try w.writeByte('('); - for (0..fn_info.param_ctypes.len) |arg| { - if (arg > 0) try w.writeAll(", "); - try w.print("a{d}", .{arg}); - } - try w.writeAll(");"); - try o.newline(); - try o.outdent(); - try w.writeByte('}'); - try o.newline(); - }, + try w.print("static zig_{t} ", .{kind}); + try dg.renderFunctionSignature(w, fn_val, .none, .definition, switch (kind) { + .never_tail => .{ .nav_never_tail = fn_nav }, + .never_inline => .{ .nav_never_inline = fn_nav }, + }); + try w.writeAll(" {\n return "); + try renderNavName(w, fn_nav, ip); + try w.writeByte('('); + { + const func_type = ip.indexToKey(fn_val.typeOf(zcu).toIntern()).func_type; + var c_param_index: u32 = 0; + for (func_type.param_types.get(ip)) |param_ty_ip| { + const param_ty: Type = .fromInterned(param_ty_ip); + if (!param_ty.hasRuntimeBits(zcu)) continue; + if (c_param_index != 0) try w.writeAll(", "); + try w.print("a{d}", .{c_param_index}); + c_param_index += 1; + } } + try w.writeAll(");\n}\n"); } pub fn generate( @@ -2869,110 +2199,109 @@ pub fn generate( const func = zcu.funcInfo(func_index); + var arena: std.heap.ArenaAllocator = .init(gpa); + defer arena.deinit(); + var function: Function = .{ .value_map = .init(gpa), .air = air.*, .liveness = liveness.*.?, .func_index = func_index, - .object = .{ - .dg = .{ - .gpa = gpa, - .pt = pt, - .mod = zcu.navFileScope(func.owner_nav).mod.?, - .error_msg = null, - .pass = .{ .nav = func.owner_nav }, - .is_naked_fn = Type.fromInterned(func.ty).fnCallingConvention(zcu) == .naked, - .expected_block = null, - .fwd_decl = .init(gpa), - .ctype_pool = .empty, - .scratch = .empty, - .uavs = .empty, - }, - .code_header = .init(gpa), - .code = .init(gpa), - .indent_counter = 0, + .dg = .{ + .gpa = gpa, + .arena = arena.allocator(), + .pt = pt, + .mod = zcu.navFileScope(func.owner_nav).mod.?, + .error_msg = null, + .owner_nav = func.owner_nav.toOptional(), + .is_naked_fn = Type.fromInterned(func.ty).fnCallingConvention(zcu) == .naked, + .expected_block = null, + .ctype_deps = .empty, + .uavs = .empty, }, - .lazy_fns = .empty, + .code = .init(gpa), + .indent_counter = 0, + .need_tag_name_funcs = .empty, + .need_never_tail_funcs = .empty, + .need_never_inline_funcs = .empty, }; defer { - function.object.code_header.deinit(); - function.object.code.deinit(); - function.object.dg.fwd_decl.deinit(); - function.object.dg.ctype_pool.deinit(gpa); - function.object.dg.scratch.deinit(gpa); - function.object.dg.uavs.deinit(gpa); + function.code.deinit(); + function.dg.ctype_deps.deinit(gpa); + function.dg.uavs.deinit(gpa); function.deinit(); } - try function.object.dg.ctype_pool.init(gpa); - genFunc(&function) catch |err| switch (err) { - error.AnalysisFail => return zcu.codegenFailMsg(func.owner_nav, function.object.dg.error_msg.?), - error.OutOfMemory => return error.OutOfMemory, + var fwd_decl: Writer.Allocating = .init(gpa); + defer fwd_decl.deinit(); + + var code_header: Writer.Allocating = .init(gpa); + defer code_header.deinit(); + + genFunc(&function, &fwd_decl.writer, &code_header.writer) catch |err| switch (err) { + error.AnalysisFail => return zcu.codegenFailMsg(func.owner_nav, function.dg.error_msg.?), error.WriteFailed => return error.OutOfMemory, + error.OutOfMemory => |e| return e, }; var mir: Mir = .{ - .uavs = .empty, - .code = &.{}, - .code_header = &.{}, .fwd_decl = &.{}, - .ctype_pool = .empty, - .lazy_fns = .empty, + .code_header = &.{}, + .code = &.{}, + .ctype_deps = function.dg.ctype_deps.move(), + .need_uavs = function.dg.uavs.move(), + .need_tag_name_funcs = function.need_tag_name_funcs.move(), + .need_never_tail_funcs = function.need_never_tail_funcs.move(), + .need_never_inline_funcs = function.need_never_inline_funcs.move(), }; errdefer mir.deinit(gpa); - mir.uavs = function.object.dg.uavs.move(); - mir.code_header = try function.object.code_header.toOwnedSlice(); - mir.code = try function.object.code.toOwnedSlice(); - mir.fwd_decl = try function.object.dg.fwd_decl.toOwnedSlice(); - mir.ctype_pool = function.object.dg.ctype_pool.move(); - mir.lazy_fns = function.lazy_fns.move(); + mir.fwd_decl = try fwd_decl.toOwnedSlice(); + mir.code_header = try code_header.toOwnedSlice(); + mir.code = try function.code.toOwnedSlice(); return mir; } -pub fn genFunc(f: *Function) Error!void { +pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) Error!void { const tracy = trace(@src()); defer tracy.end(); - const o = &f.object; - const zcu = o.dg.pt.zcu; + const zcu = f.dg.pt.zcu; const ip = &zcu.intern_pool; - const gpa = o.dg.gpa; - const nav_index = o.dg.pass.nav; + const gpa = f.dg.gpa; + const nav_index = f.dg.owner_nav.unwrap().?; const nav_val = zcu.navValue(nav_index); const nav = ip.getNav(nav_index); - const fwd = &o.dg.fwd_decl.writer; - try fwd.writeAll("static "); - try o.dg.renderFunctionSignature( - fwd, + try fwd_decl_writer.writeAll("static "); + try f.dg.renderFunctionSignature( + fwd_decl_writer, nav_val, nav.status.fully_resolved.alignment, - .forward, + .forward_decl, .{ .nav = nav_index }, ); - try fwd.writeAll(";\n"); + try fwd_decl_writer.writeAll(";\n"); - const ch = &o.code_header.writer; if (nav.status.fully_resolved.@"linksection".toSlice(ip)) |s| - try ch.print("zig_linksection_fn({f}) ", .{fmtStringLiteral(s, null)}); - try o.dg.renderFunctionSignature( - ch, + try header_writer.print("zig_linksection_fn({f}) ", .{fmtStringLiteral(s, null)}); + try f.dg.renderFunctionSignature( + header_writer, nav_val, .none, - .complete, + .definition, .{ .nav = nav_index }, ); - try ch.writeAll(" {\n "); + try header_writer.writeAll(" {\n "); f.free_locals_map.clearRetainingCapacity(); const main_body = f.air.getMainBody(); - o.indent(); + f.indent(); try genBodyResolveState(f, undefined, &.{}, main_body, true); - try o.outdent(); - try o.code.writer.writeByte('}'); - try o.newline(); - if (o.dg.expected_block) |_| + try f.outdent(); + try f.code.writer.writeByte('}'); + try f.newline(); + if (f.dg.expected_block) |_| return f.fail("runtime code not allowed in naked function", .{}); // Take advantage of the free_locals map to bucket locals per type. All @@ -2986,155 +2315,204 @@ pub fn genFunc(f: *Function) Error!void { if (!should_emit) continue; const local = f.locals.items[local_index]; log.debug("inserting local {d} into free_locals", .{local_index}); - const gop = try free_locals.getOrPut(gpa, local.getType()); + const gop = try free_locals.getOrPut(gpa, local); if (!gop.found_existing) gop.value_ptr.* = .{}; try gop.value_ptr.putNoClobber(gpa, local_index, {}); } const SortContext = struct { + zcu: *const Zcu, keys: []const LocalType, pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool { - const lhs_ty = ctx.keys[lhs_index]; - const rhs_ty = ctx.keys[rhs_index]; - return lhs_ty.alignas.order(rhs_ty.alignas).compare(.gt); + const lhs = ctx.keys[lhs_index]; + const rhs = ctx.keys[rhs_index]; + const lhs_align = switch (lhs.alignment) { + .none => lhs.type.abiAlignment(ctx.zcu), + else => |a| a, + }; + const rhs_align = switch (rhs.alignment) { + .none => rhs.type.abiAlignment(ctx.zcu), + else => |a| a, + }; + return Alignment.compareStrict(lhs_align, .gt, rhs_align); } }; - free_locals.sort(SortContext{ .keys = free_locals.keys() }); + free_locals.sort(SortContext{ + .zcu = zcu, + .keys = free_locals.keys(), + }); for (free_locals.values()) |list| { for (list.keys()) |local_index| { const local = f.locals.items[local_index]; - try o.dg.renderCTypeAndName(ch, local.ctype, .{ .local = local_index }, .{}, local.flags.alignas); - try ch.writeAll(";\n "); + try f.dg.renderTypeAndName(header_writer, local.type, .{ .local = local_index }, .{}, local.alignment); + try header_writer.writeAll(";\n "); } } } -pub fn genDecl(o: *Object) Error!void { +pub fn genDecl(dg: *DeclGen, w: *Writer) Error!void { const tracy = trace(@src()); defer tracy.end(); - const pt = o.dg.pt; + const pt = dg.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; - const nav = ip.getNav(o.dg.pass.nav); + const nav = ip.getNav(dg.owner_nav.unwrap().?); const nav_ty: Type = .fromInterned(nav.typeOf(ip)); - if (!nav_ty.hasRuntimeBits(zcu)) return; - switch (ip.indexToKey(nav.status.fully_resolved.val)) { - .@"extern" => |@"extern"| { - if (!ip.isFunctionType(nav_ty.toIntern())) return o.dg.renderFwdDecl(o.dg.pass.nav, .{ - .is_const = @"extern".is_const, - .is_threadlocal = @"extern".is_threadlocal, - .linkage = @"extern".linkage, - .visibility = @"extern".visibility, - }); + const is_const: bool, const is_threadlocal: bool, const init_val: Value = switch (ip.indexToKey(nav.status.fully_resolved.val)) { + else => .{ true, false, .fromInterned(nav.status.fully_resolved.val) }, + .variable => |v| .{ false, v.is_threadlocal, .fromInterned(v.init) }, + .@"extern" => return, + }; - const fwd = &o.dg.fwd_decl.writer; - try fwd.writeAll("zig_extern "); - try o.dg.renderFunctionSignature( - fwd, - Value.fromInterned(nav.status.fully_resolved.val), - nav.status.fully_resolved.alignment, - .forward, - .{ .@"export" = .{ - .main_name = nav.name, - .extern_name = nav.name, - } }, - ); - try fwd.writeAll(";\n"); - }, - .variable => |variable| { - try o.dg.renderFwdDecl(o.dg.pass.nav, .{ - .is_const = false, - .is_threadlocal = variable.is_threadlocal, - .linkage = .internal, - .visibility = .default, - }); - const w = &o.code.writer; - if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal "); - if (nav.status.fully_resolved.@"linksection".toSlice(&zcu.intern_pool)) |s| - try w.print("zig_linksection({f}) ", .{fmtStringLiteral(s, null)}); - try o.dg.renderTypeAndName( - w, - nav_ty, - .{ .nav = o.dg.pass.nav }, - .{}, - nav.status.fully_resolved.alignment, - .complete, - ); - try w.writeAll(" = "); - try o.dg.renderValue(w, Value.fromInterned(variable.init), .StaticInitializer); - try w.writeByte(';'); - try o.newline(); - }, - else => try genDeclValue( - o, - Value.fromInterned(nav.status.fully_resolved.val), - .{ .nav = o.dg.pass.nav }, - nav.status.fully_resolved.alignment, - nav.status.fully_resolved.@"linksection", - ), - } -} - -pub fn genDeclValue( - o: *Object, - val: Value, - decl_c_value: CValue, - alignment: Alignment, - @"linksection": InternPool.OptionalNullTerminatedString, -) Error!void { - const zcu = o.dg.pt.zcu; - const ty = val.typeOf(zcu); - - const fwd = &o.dg.fwd_decl.writer; - try fwd.writeAll("static "); - try o.dg.renderTypeAndName(fwd, ty, decl_c_value, Const, alignment, .complete); - try fwd.writeAll(";\n"); - - const w = &o.code.writer; - if (@"linksection".toSlice(&zcu.intern_pool)) |s| + if (nav.status.fully_resolved.@"linksection".toSlice(ip)) |s| { try w.print("zig_linksection({f}) ", .{fmtStringLiteral(s, null)}); - try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete); + } + + // We don't bother underaligning---it's unnecessary and hurts compatibility. + const a = nav.status.fully_resolved.alignment; + if (a != .none and a.compareStrict(.gt, nav_ty.abiAlignment(zcu))) { + try w.print("zig_align({d}) ", .{a.toByteUnits().?}); + } + + try genDeclValue(dg, w, .{ + .name = .{ .nav = dg.owner_nav.unwrap().? }, + .@"const" = is_const, + .@"threadlocal" = is_threadlocal, + .init_val = init_val, + }); +} +pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void { + const tracy = trace(@src()); + defer tracy.end(); + + const pt = dg.pt; + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + const nav = ip.getNav(dg.owner_nav.unwrap().?); + const nav_ty: Type = .fromInterned(nav.typeOf(ip)); + + const is_const: bool, const is_threadlocal: bool, const init_val: Value = switch (ip.indexToKey(nav.status.fully_resolved.val)) { + else => .{ true, false, .fromInterned(nav.status.fully_resolved.val) }, + .variable => |v| .{ false, v.is_threadlocal, .fromInterned(v.init) }, + + .@"extern" => |@"extern"| switch (nav_ty.zigTypeTag(zcu)) { + .@"fn" => { + try w.writeAll("zig_extern "); + try dg.renderFunctionSignature( + w, + Value.fromInterned(nav.status.fully_resolved.val), + nav.status.fully_resolved.alignment, + .forward_decl, + .{ .@"export" = .{ + .main_name = nav.name, + .extern_name = nav.name, + } }, + ); + try w.writeAll(";\n"); + return; + }, + else => { + switch (@"extern".linkage) { + .internal => try w.writeAll("static "), + .strong => try w.print("zig_extern zig_visibility({t}) ", .{@"extern".visibility}), + .weak => try w.print("zig_extern zig_weak_linkage zig_visibility({t}) ", .{@"extern".visibility}), + .link_once => return dg.fail("TODO: CBE: implement linkonce linkage?", .{}), + } + if (@"extern".is_threadlocal and !dg.mod.single_threaded) { + try w.writeAll("zig_threadlocal "); + } + try dg.renderTypeAndName( + w, + .fromInterned(nav.typeOf(ip)), + .{ .nav = dg.owner_nav.unwrap().? }, + .{ .@"const" = @"extern".is_const }, + nav.getAlignment(), + ); + try w.writeAll(";\n"); + return; + }, + }, + }; + + // We don't bother underaligning---it's unnecessary and hurts compatibility. + const a = nav.status.fully_resolved.alignment; + if (a != .none and a.compareStrict(.gt, nav_ty.abiAlignment(zcu))) { + try w.print("zig_align({d}) ", .{a.toByteUnits().?}); + } + + try genDeclValueFwd(dg, w, .{ + .name = .{ .nav = dg.owner_nav.unwrap().? }, + .@"const" = is_const, + .@"threadlocal" = is_threadlocal, + .init_val = init_val, + }); +} +pub fn genDeclValue(dg: *DeclGen, w: *Writer, options: struct { + name: CValue, + @"const": bool, + @"threadlocal": bool, + init_val: Value, +}) Error!void { + const zcu = dg.pt.zcu; + const ty = options.init_val.typeOf(zcu); + if (options.@"threadlocal" and !dg.mod.single_threaded) { + try w.writeAll("zig_threadlocal "); + } + try dg.renderTypeAndName(w, ty, options.name, .{ .@"const" = options.@"const" }, .none); try w.writeAll(" = "); - try o.dg.renderValue(w, val, .StaticInitializer); - try w.writeByte(';'); - try o.newline(); + try dg.renderValue(w, options.init_val, .static_initializer); + try w.writeAll(";\n"); +} +pub fn genDeclValueFwd(dg: *DeclGen, w: *Writer, options: struct { + name: CValue, + @"const": bool, + @"threadlocal": bool, + init_val: Value, +}) Error!void { + const zcu = dg.pt.zcu; + const ty = options.init_val.typeOf(zcu); + try w.writeAll("static "); + if (options.@"threadlocal" and !dg.mod.single_threaded) { + try w.writeAll("zig_threadlocal "); + } + try dg.renderTypeAndName(w, ty, options.name, .{ .@"const" = options.@"const" }, .none); + try w.writeAll(";\n"); } -pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const Zcu.Export.Index) !void { +pub fn genExports(dg: *DeclGen, w: *Writer, exported: Zcu.Exported, export_indices: []const Zcu.Export.Index) !void { const zcu = dg.pt.zcu; const ip = &zcu.intern_pool; - const fwd = &dg.fwd_decl.writer; const main_name = export_indices[0].ptr(zcu).opts.name; - try fwd.writeAll("#define "); + try w.writeAll("#define "); switch (exported) { - .nav => |nav| try dg.renderNavName(fwd, nav), - .uav => |uav| try DeclGen.renderUavName(fwd, Value.fromInterned(uav)), + .nav => |nav| try renderNavName(w, nav, ip), + .uav => |uav| try renderUavName(w, Value.fromInterned(uav)), } - try fwd.writeByte(' '); - try fwd.print("{f}", .{fmtIdentSolo(main_name.toSlice(ip))}); - try fwd.writeByte('\n'); + try w.writeByte(' '); + try w.print("{f}", .{fmtIdentSolo(main_name.toSlice(ip))}); + try w.writeByte('\n'); const exported_val = exported.getValue(zcu); if (ip.isFunctionType(exported_val.typeOf(zcu).toIntern())) return for (export_indices) |export_index| { const @"export" = export_index.ptr(zcu); - try fwd.writeAll("zig_extern "); - if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage_fn "); + try w.writeAll("zig_extern "); + if (@"export".opts.linkage == .weak) try w.writeAll("zig_weak_linkage_fn "); try dg.renderFunctionSignature( - fwd, + w, exported.getValue(zcu), exported.getAlign(zcu), - .forward, + .forward_decl, .{ .@"export" = .{ .main_name = main_name, .extern_name = @"export".opts.name, } }, ); - try fwd.writeAll(";\n"); + try w.writeAll(";\n"); }; const is_const = switch (ip.indexToKey(exported_val.toIntern())) { .func => unreachable, @@ -3144,39 +2522,38 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const }; for (export_indices) |export_index| { const @"export" = export_index.ptr(zcu); - try fwd.writeAll("zig_extern "); - if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage "); - if (@"export".opts.section.toSlice(ip)) |s| try fwd.print("zig_linksection({f}) ", .{ + try w.writeAll("zig_extern "); + if (@"export".opts.linkage == .weak) try w.writeAll("zig_weak_linkage "); + if (@"export".opts.section.toSlice(ip)) |s| try w.print("zig_linksection({f}) ", .{ fmtStringLiteral(s, null), }); const extern_name = @"export".opts.name.toSlice(ip); const is_mangled = isMangledIdent(extern_name, true); const is_export = @"export".opts.name != main_name; try dg.renderTypeAndName( - fwd, + w, exported.getValue(zcu).typeOf(zcu), .{ .identifier = extern_name }, - CQualifiers.init(.{ .@"const" = is_const }), + .{ .@"const" = is_const }, exported.getAlign(zcu), - .complete, ); if (is_mangled and is_export) { - try fwd.print(" zig_mangled_export({f}, {f}, {f})", .{ + try w.print(" zig_mangled_export({f}, {f}, {f})", .{ fmtIdentSolo(extern_name), fmtStringLiteral(extern_name, null), fmtStringLiteral(main_name.toSlice(ip), null), }); } else if (is_mangled) { - try fwd.print(" zig_mangled({f}, {f})", .{ + try w.print(" zig_mangled({f}, {f})", .{ fmtIdentSolo(extern_name), fmtStringLiteral(extern_name, null), }); } else if (is_export) { - try fwd.print(" zig_export({f}, {f})", .{ + try w.print(" zig_export({f}, {f})", .{ fmtStringLiteral(main_name.toSlice(ip), null), fmtStringLiteral(extern_name, null), }); } - try fwd.writeAll(";\n"); + try w.writeAll(";\n"); } } @@ -3185,15 +2562,15 @@ pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const /// have been added to `free_locals_map`. For a version of this function that restores this state, /// see `genBodyResolveState`. fn genBody(f: *Function, body: []const Air.Inst.Index) Error!void { - const w = &f.object.code.writer; + const w = &f.code.writer; if (body.len == 0) { try w.writeAll("{}"); } else { try w.writeByte('{'); - f.object.indent(); - try f.object.newline(); + f.indent(); + try f.newline(); try genBodyInner(f, body); - try f.object.outdent(); + try f.outdent(); try w.writeByte('}'); } } @@ -3207,13 +2584,13 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) Error!void { fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []const Air.Inst.Index, body: []const Air.Inst.Index, inner: bool) Error!void { if (body.len == 0) { // Don't go to the expense of cloning everything! - if (!inner) try f.object.code.writer.writeAll("{}"); + if (!inner) try f.code.writer.writeAll("{}"); return; } // TODO: we can probably avoid the copies in some other common cases too. - const gpa = f.object.dg.gpa; + const gpa = f.dg.gpa; // Save the original value_map and free_locals_map so that we can restore them after the body. var old_value_map = try f.value_map.clone(); @@ -3254,13 +2631,13 @@ fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []con } fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { - const zcu = f.object.dg.pt.zcu; + const zcu = f.dg.pt.zcu; const ip = &zcu.intern_pool; const air_tags = f.air.instructions.items(.tag); const air_datas = f.air.instructions.items(.data); for (body) |inst| { - if (f.object.dg.expected_block) |_| + if (f.dg.expected_block) |_| return f.fail("runtime code not allowed in naked function", .{}); if (f.liveness.isUnused(inst) and !f.air.mustLower(inst, ip)) continue; @@ -3529,8 +2906,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { .ret => return airRet(f, inst, false), .ret_safe => return airRet(f, inst, false), // TODO .ret_load => return airRet(f, inst, true), - .trap => return airTrap(f, &f.object.code.writer), - .unreach => return airUnreach(&f.object), + .trap => return airTrap(f), + .unreach => return airUnreach(f), // Instructions which may be `noreturn`. .block => res: { @@ -3573,21 +2950,21 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [ const operand = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); - const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); - try f.writeCValue(w, local, .Other); - try a.assign(f, w); + try f.writeCValue(w, local, .other); + try w.writeAll(" = "); if (is_ptr) { try w.writeByte('&'); try f.writeCValueDerefMember(w, operand, .{ .identifier = field_name }); } else try f.writeCValueMember(w, operand, .{ .identifier = field_name }); - try a.end(f, w); + try w.writeByte(';'); + try f.newline(); return local; } fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { - const zcu = f.object.dg.pt.zcu; + const zcu = f.dg.pt.zcu; const inst_ty = f.typeOfIndex(inst); const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; assert(inst_ty.hasRuntimeBits(zcu)); @@ -3596,21 +2973,24 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { const index = try f.resolveInst(bin_op.rhs); try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); - const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); - try f.writeCValue(w, local, .Other); - try a.assign(f, w); - try f.writeCValue(w, ptr, .Other); + try f.writeCValue(w, local, .other); + try w.writeAll(" = "); + switch (f.typeOf(bin_op.lhs).ptrSize(zcu)) { + .one => try f.writeCValueDerefMember(w, ptr, .{ .identifier = "array" }), + .many, .c => try f.writeCValue(w, ptr, .other), + .slice => unreachable, + } try w.writeByte('['); - try f.writeCValue(w, index, .Other); - try w.writeByte(']'); - try a.end(f, w); + try f.writeCValue(w, index, .other); + try w.writeAll("];"); + try f.newline(); return local; } fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; @@ -3623,28 +3003,26 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { const index = try f.resolveInst(bin_op.rhs); try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); - const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); - try f.writeCValue(w, local, .Other); - try a.assign(f, w); - try w.writeByte('('); - try f.renderType(w, inst_ty); - try w.writeByte(')'); + try f.writeCValue(w, local, .other); + try w.writeAll(" = "); try w.writeByte('&'); if (ptr_ty.ptrSize(zcu) == .one) { - // It's a pointer to an array, so we need to de-reference. - try f.writeCValueDeref(w, ptr); - } else try f.writeCValue(w, ptr, .Other); + // `*[n]T` was turned into a pointer to `struct { T array[n]; }` + try f.writeCValueDerefMember(w, ptr, .{ .identifier = "array" }); + } else { + try f.writeCValue(w, ptr, .other); + } try w.writeByte('['); - try f.writeCValue(w, index, .Other); - try w.writeByte(']'); - try a.end(f, w); + try f.writeCValue(w, index, .other); + try w.writeAll("];"); + try f.newline(); return local; } fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { - const zcu = f.object.dg.pt.zcu; + const zcu = f.dg.pt.zcu; const inst_ty = f.typeOfIndex(inst); const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; assert(inst_ty.hasRuntimeBits(zcu)); @@ -3653,21 +3031,20 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { const index = try f.resolveInst(bin_op.rhs); try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); - const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); - try f.writeCValue(w, local, .Other); - try a.assign(f, w); + try f.writeCValue(w, local, .other); + try w.writeAll(" = "); try f.writeCValueMember(w, slice, .{ .identifier = "ptr" }); try w.writeByte('['); - try f.writeCValue(w, index, .Other); - try w.writeByte(']'); - try a.end(f, w); + try f.writeCValue(w, index, .other); + try w.writeAll("];"); + try f.newline(); return local; } fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; @@ -3681,22 +3058,21 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { const index = try f.resolveInst(bin_op.rhs); try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); - const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); - try f.writeCValue(w, local, .Other); - try a.assign(f, w); + try f.writeCValue(w, local, .other); + try w.writeAll(" = "); try w.writeByte('&'); try f.writeCValueMember(w, slice, .{ .identifier = "ptr" }); try w.writeByte('['); - try f.writeCValue(w, index, .Other); - try w.writeByte(']'); - try a.end(f, w); + try f.writeCValue(w, index, .other); + try w.writeAll("];"); + try f.newline(); return local; } fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { - const zcu = f.object.dg.pt.zcu; + const zcu = f.dg.pt.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const inst_ty = f.typeOfIndex(inst); assert(inst_ty.hasRuntimeBits(zcu)); @@ -3705,32 +3081,28 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { const index = try f.resolveInst(bin_op.rhs); try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); - const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); - try f.writeCValue(w, local, .Other); - try a.assign(f, w); - try f.writeCValue(w, array, .Other); + try f.writeCValue(w, local, .other); + try w.writeAll(" = "); + try f.writeCValueMember(w, array, .{ .identifier = "array" }); try w.writeByte('['); - try f.writeCValue(w, index, .Other); - try w.writeByte(']'); - try a.end(f, w); + try f.writeCValue(w, index, .other); + try w.writeAll("];"); + try f.newline(); return local; } fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const inst_ty = f.typeOfIndex(inst); const elem_ty = inst_ty.childType(zcu); if (!elem_ty.hasRuntimeBits(zcu)) return .{ .undef = inst_ty }; const local = try f.allocLocalValue(.{ - .ctype = try f.ctypeFromType(elem_ty, .complete), - .alignas = CType.AlignAs.fromAlignment(.{ - .@"align" = inst_ty.ptrInfo(zcu).flags.alignment, - .abi = elem_ty.abiAlignment(zcu), - }), + .type = elem_ty, + .alignment = inst_ty.ptrInfo(zcu).flags.alignment, }); log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); try f.allocs.put(zcu.gpa, local.new_local, true); @@ -3741,11 +3113,11 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { // For packed aggregates, we zero-initialize to try and work around a design flaw // related to how `packed`, `undefined`, and RLS interact. See comment in `airStore` // for details. - const w = &f.object.code.writer; + const w = &f.code.writer; try w.print("memset(&t{d}, 0x00, sizeof(", .{local.new_local}); try f.renderType(w, elem_ty); try w.writeAll("));"); - try f.object.newline(); + try f.newline(); }, .auto, .@"extern" => {}, }, @@ -3756,18 +3128,15 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { } fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const inst_ty = f.typeOfIndex(inst); const elem_ty = inst_ty.childType(zcu); if (!elem_ty.hasRuntimeBits(zcu)) return .{ .undef = inst_ty }; const local = try f.allocLocalValue(.{ - .ctype = try f.ctypeFromType(elem_ty, .complete), - .alignas = CType.AlignAs.fromAlignment(.{ - .@"align" = inst_ty.ptrInfo(zcu).flags.alignment, - .abi = elem_ty.abiAlignment(zcu), - }), + .type = elem_ty, + .alignment = inst_ty.ptrInfo(zcu).flags.alignment, }); log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); try f.allocs.put(zcu.gpa, local.new_local, true); @@ -3778,11 +3147,11 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { // For packed aggregates, we zero-initialize to try and work around a design flaw // related to how `packed`, `undefined`, and RLS interact. See comment in `airStore` // for details. - const w = &f.object.code.writer; + const w = &f.code.writer; try w.print("memset(&t{d}, 0x00, sizeof(", .{local.new_local}); try f.renderType(w, elem_ty); try w.writeAll("));"); - try f.object.newline(); + try f.newline(); }, .auto, .@"extern" => {}, }, @@ -3793,24 +3162,18 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { } fn airArg(f: *Function, inst: Air.Inst.Index) !CValue { - const inst_ty = f.typeOfIndex(inst); - const inst_ctype = try f.ctypeFromType(inst_ty, .parameter); - const i = f.next_arg_index; f.next_arg_index += 1; - const result: CValue = if (inst_ctype.eql(try f.ctypeFromType(inst_ty, .complete))) - .{ .arg = i } - else - .{ .arg_array = i }; + const result: CValue = .{ .arg = i }; if (f.liveness.isUnused(inst)) { - const w = &f.object.code.writer; + const w = &f.code.writer; try w.writeByte('('); try f.renderType(w, .void); try w.writeByte(')'); - try f.writeCValue(w, result, .Other); + try f.writeCValue(w, result, .other); try w.writeByte(';'); - try f.object.newline(); + try f.newline(); return .none; } @@ -3818,7 +3181,7 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue { } fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; @@ -3841,94 +3204,69 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { ptr_info.flags.alignment.order(src_ty.abiAlignment(zcu)).compare(.gte) else true; - const is_array = lowersToArray(src_ty, zcu); - const need_memcpy = !is_aligned or is_array; - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, src_ty); const v = try Vectorize.start(f, inst, w, ptr_ty); - if (need_memcpy) { - try w.writeAll("memcpy("); - if (!is_array) try w.writeByte('&'); - try f.writeCValue(w, local, .Other); + if (!is_aligned) { + try w.writeAll("memcpy(&"); + try f.writeCValue(w, local, .other); try v.elem(f, w); try w.writeAll(", (const char *)"); - try f.writeCValue(w, operand, .Other); + try f.writeCValue(w, operand, .other); try v.elem(f, w); try w.writeAll(", sizeof("); try f.renderType(w, src_ty); try w.writeAll("))"); } else { - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try v.elem(f, w); try w.writeAll(" = "); try f.writeCValueDeref(w, operand); try v.elem(f, w); } try w.writeByte(';'); - try f.object.newline(); + try f.newline(); try v.end(f, inst, w); return local; } fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; - const w = &f.object.code.writer; + const w = &f.code.writer; const op_inst = un_op.toIndex(); const op_ty = f.typeOf(un_op); const ret_ty = if (is_ptr) op_ty.childType(zcu) else op_ty; - const ret_ctype = try f.ctypeFromType(ret_ty, .parameter); if (op_inst != null and f.air.instructions.items(.tag)[@intFromEnum(op_inst.?)] == .call_always_tail) { try reap(f, inst, &.{un_op}); _ = try airCall(f, op_inst.?, .always_tail); - } else if (ret_ctype.index != .void) { + } else if (ret_ty.hasRuntimeBits(zcu)) { const operand = try f.resolveInst(un_op); try reap(f, inst, &.{un_op}); - var deref = is_ptr; - const is_array = lowersToArray(ret_ty, zcu); - const ret_val = if (is_array) ret_val: { - const array_local = try f.allocAlignedLocal(inst, .{ - .ctype = ret_ctype, - .alignas = CType.AlignAs.fromAbiAlignment(ret_ty.abiAlignment(zcu)), - }); - try w.writeAll("memcpy("); - try f.writeCValueMember(w, array_local, .{ .identifier = "array" }); - try w.writeAll(", "); - if (deref) - try f.writeCValueDeref(w, operand) - else - try f.writeCValue(w, operand, .FunctionArgument); - deref = false; - try w.writeAll(", sizeof("); - try f.renderType(w, ret_ty); - try w.writeAll("));"); - try f.object.newline(); - break :ret_val array_local; - } else operand; try w.writeAll("return "); - if (deref) - try f.writeCValueDeref(w, ret_val) - else - try f.writeCValue(w, ret_val, .Other); - try w.writeAll(";\n"); - if (is_array) { - try freeLocal(f, inst, ret_val.new_local, null); + if (is_ptr) { + try f.writeCValueDeref(w, operand); + } else switch (operand) { + // Instead of 'return &local', emit 'return undefined'. + .local_ref => try f.dg.renderUndefValue(w, ret_ty, .other), + else => try f.writeCValue(w, operand, .other), } + try w.writeAll(";\n"); } else { try reap(f, inst, &.{un_op}); // Not even allowed to return void in a naked function. - if (!f.object.dg.is_naked_fn) try w.writeAll("return;\n"); + if (!f.dg.is_naked_fn) try w.writeAll("return;\n"); } } fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; @@ -3940,23 +3278,23 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { const operand_ty = f.typeOf(ty_op.operand); const scalar_ty = operand_ty.scalarType(zcu); - if (f.object.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) return f.moveCValue(inst, inst_ty, operand); + if (f.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) return f.moveCValue(inst, inst_ty, operand); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); const v = try Vectorize.start(f, inst, w, operand_ty); - const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete)); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try v.elem(f, w); - try a.assign(f, w); - try f.renderIntCast(w, inst_scalar_ty, operand, v, scalar_ty, .Other); - try a.end(f, w); + try w.writeAll(" = "); + try f.renderIntCast(w, inst_scalar_ty, operand, v, scalar_ty, .other); + try w.writeByte(';'); + try f.newline(); try v.end(f, inst, w); return local; } fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; @@ -3978,13 +3316,12 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { const need_mask = dest_bits < 8 or !std.math.isPowerOfTwo(dest_bits); if (!need_cast and !need_lo and !need_mask) return f.moveCValue(inst, inst_ty, operand); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); const v = try Vectorize.start(f, inst, w, operand_ty); - const a = try Assignment.start(f, w, try f.ctypeFromType(inst_scalar_ty, .complete)); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try v.elem(f, w); - try a.assign(f, w); + try w.writeAll(" = "); if (need_cast) { try w.writeByte('('); try f.renderType(w, inst_scalar_ty); @@ -3992,18 +3329,18 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { } if (need_lo) { try w.writeAll("zig_lo_"); - try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); + try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); try w.writeByte('('); } if (!need_mask) { - try f.writeCValue(w, operand, .Other); + try f.writeCValue(w, operand, .other); try v.elem(f, w); } else switch (dest_int_info.signedness) { .unsigned => { try w.writeAll("zig_and_"); - try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); + try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); try w.writeByte('('); - try f.writeCValue(w, operand, .FunctionArgument); + try f.writeCValue(w, operand, .other); try v.elem(f, w); try w.print(", {f})", .{ try f.fmtIntLiteralHex(try inst_scalar_ty.maxIntScalar(pt, scalar_ty)), @@ -4015,7 +3352,7 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { const shift_val = try pt.intValue(.u8, c_bits - dest_bits); try w.writeAll("zig_shr_"); - try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); + try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); if (c_bits == 128) { try w.print("(zig_bitCast_i{d}(", .{c_bits}); } else { @@ -4027,7 +3364,7 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { } else { try w.print("(uint{d}_t)", .{c_bits}); } - try f.writeCValue(w, operand, .FunctionArgument); + try f.writeCValue(w, operand, .other); try v.elem(f, w); if (c_bits == 128) try w.writeByte(')'); try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)}); @@ -4036,13 +3373,14 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { }, } if (need_lo) try w.writeByte(')'); - try a.end(f, w); + try w.writeByte(';'); + try f.newline(); try v.end(f, inst, w); return local; } fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; // *a = b; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; @@ -4060,7 +3398,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { const val_is_undef = if (try f.air.value(bin_op.rhs, pt)) |v| v.isUndef(zcu) else false; - const w = &f.object.code.writer; + const w = &f.code.writer; if (val_is_undef) { try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); if (safety and ptr_info.packed_offset.host_size == 0) { @@ -4080,11 +3418,11 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { }, }; try w.writeAll("memset("); - try f.writeCValue(w, ptr_val, .FunctionArgument); + try f.writeCValue(w, ptr_val, .other); try w.print(", {s}, sizeof(", .{byte_str}); try f.renderType(w, .fromInterned(ptr_info.child)); try w.writeAll("));"); - try f.object.newline(); + try f.newline(); } return .none; } @@ -4093,46 +3431,29 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { ptr_info.flags.alignment.order(src_ty.abiAlignment(zcu)).compare(.gte) else true; - const is_array = lowersToArray(.fromInterned(ptr_info.child), zcu); - const need_memcpy = !is_aligned or is_array; const src_val = try f.resolveInst(bin_op.rhs); try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - const src_scalar_ctype = try f.ctypeFromType(src_ty.scalarType(zcu), .complete); - if (need_memcpy) { + if (!is_aligned) { // For this memcpy to safely work we need the rhs to have the same // underlying type as the lhs (i.e. they must both be arrays of the same underlying type). assert(src_ty.eql(.fromInterned(ptr_info.child), zcu)); - // If the source is a constant, writeCValue will emit a brace initialization - // so work around this by initializing into new local. - // TODO this should be done by manually initializing elements of the dest array - const array_src = if (src_val == .constant) blk: { - const new_local = try f.allocLocal(inst, src_ty); - try f.writeCValue(w, new_local, .Other); - try w.writeAll(" = "); - try f.writeCValue(w, src_val, .Other); - try w.writeByte(';'); - try f.object.newline(); - - break :blk new_local; - } else src_val; - const v = try Vectorize.start(f, inst, w, ptr_ty); try w.writeAll("memcpy((char *)"); - try f.writeCValue(w, ptr_val, .FunctionArgument); + try f.writeCValue(w, ptr_val, .other); try v.elem(f, w); - try w.writeAll(", "); - if (!is_array) try w.writeByte('&'); - try f.writeCValue(w, array_src, .FunctionArgument); + try w.writeAll(", &"); + switch (src_val) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, src_val, .other), + } try v.elem(f, w); try w.writeAll(", sizeof("); try f.renderType(w, src_ty); - try w.writeAll("))"); - try f.freeCValue(inst, array_src); - try w.writeByte(';'); - try f.object.newline(); + try w.writeAll("));"); + try f.newline(); try v.end(f, inst, w); } else { switch (ptr_val) { @@ -4144,20 +3465,20 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { else => {}, } const v = try Vectorize.start(f, inst, w, ptr_ty); - const a = try Assignment.start(f, w, src_scalar_ctype); try f.writeCValueDeref(w, ptr_val); try v.elem(f, w); - try a.assign(f, w); - try f.writeCValue(w, src_val, .Other); + try w.writeAll(" = "); + try f.writeCValue(w, src_val, .other); try v.elem(f, w); - try a.end(f, w); + try w.writeByte(';'); + try f.newline(); try v.end(f, inst, w); } return .none; } fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; @@ -4170,7 +3491,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: const operand_ty = f.typeOf(bin_op.lhs); const scalar_ty = operand_ty.scalarType(zcu); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); const v = try Vectorize.start(f, inst, w, operand_ty); try f.writeCValueMember(w, local, .{ .field = 1 }); @@ -4178,26 +3499,26 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: try w.writeAll(" = zig_"); try w.writeAll(operation); try w.writeAll("o_"); - try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); + try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); try w.writeAll("(&"); try f.writeCValueMember(w, local, .{ .field = 0 }); try v.elem(f, w); try w.writeAll(", "); - try f.writeCValue(w, lhs, .FunctionArgument); + try f.writeCValue(w, lhs, .other); try v.elem(f, w); try w.writeAll(", "); - try f.writeCValue(w, rhs, .FunctionArgument); + try f.writeCValue(w, rhs, .other); if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w); - try f.object.dg.renderBuiltinInfo(w, scalar_ty, info); + try f.dg.renderBuiltinInfo(w, scalar_ty, info); try w.writeAll(");"); - try f.object.newline(); + try f.newline(); try v.end(f, inst, w); return local; } fn airNot(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand_ty = f.typeOf(ty_op.operand); @@ -4209,17 +3530,17 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue { const inst_ty = f.typeOfIndex(inst); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); const v = try Vectorize.start(f, inst, w, operand_ty); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try v.elem(f, w); try w.writeAll(" = "); try w.writeByte('!'); - try f.writeCValue(w, op, .Other); + try f.writeCValue(w, op, .other); try v.elem(f, w); try w.writeByte(';'); - try f.object.newline(); + try f.newline(); try v.end(f, inst, w); return local; @@ -4232,7 +3553,7 @@ fn airBinOp( operation: []const u8, info: BuiltinInfo, ) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const operand_ty = f.typeOf(bin_op.lhs); @@ -4246,21 +3567,21 @@ fn airBinOp( const inst_ty = f.typeOfIndex(inst); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); const v = try Vectorize.start(f, inst, w, operand_ty); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try v.elem(f, w); try w.writeAll(" = "); - try f.writeCValue(w, lhs, .Other); + try f.writeCValue(w, lhs, .other); try v.elem(f, w); try w.writeByte(' '); try w.writeAll(operator); try w.writeByte(' '); - try f.writeCValue(w, rhs, .Other); + try f.writeCValue(w, rhs, .other); try v.elem(f, w); try w.writeByte(';'); - try f.object.newline(); + try f.newline(); try v.end(f, inst, w); return local; @@ -4272,7 +3593,7 @@ fn airCmpOp( data: anytype, operator: std.math.CompareOperator, ) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const lhs_ty = f.typeOf(data.lhs); const scalar_ty = lhs_ty.scalarType(zcu); @@ -4297,26 +3618,26 @@ fn airCmpOp( const rhs_ty = f.typeOf(data.rhs); const need_cast = lhs_ty.isSinglePointer(zcu) or rhs_ty.isSinglePointer(zcu); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); const v = try Vectorize.start(f, inst, w, lhs_ty); - const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete)); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try v.elem(f, w); - try a.assign(f, w); + try w.writeAll(" = "); if (lhs != .undef and lhs.eql(rhs)) try w.writeAll(switch (operator) { .lt, .neq, .gt => "false", .lte, .eq, .gte => "true", }) else { if (need_cast) try w.writeAll("(void*)"); - try f.writeCValue(w, lhs, .Other); + try f.writeCValue(w, lhs, .other); try v.elem(f, w); try w.writeAll(compareOperatorC(operator)); if (need_cast) try w.writeAll("(void*)"); - try f.writeCValue(w, rhs, .Other); + try f.writeCValue(w, rhs, .other); try v.elem(f, w); } - try a.end(f, w); + try w.writeByte(';'); + try f.newline(); try v.end(f, inst, w); return local; @@ -4327,9 +3648,8 @@ fn airEquality( inst: Air.Inst.Index, operator: std.math.CompareOperator, ) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; - const ctype_pool = &f.object.dg.ctype_pool; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const operand_ty = f.typeOf(bin_op.lhs); @@ -4350,54 +3670,64 @@ fn airEquality( const rhs = try f.resolveInst(bin_op.rhs); try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - const w = &f.object.code.writer; + if (lhs.eql(rhs)) { + // Avoid emitting a tautological comparison. + return .{ .constant = .makeBool(switch (operator) { + .eq, .lte, .gte => true, + .neq, .lt, .gt => false, + }) }; + } + + const w = &f.code.writer; const local = try f.allocLocal(inst, .bool); - const a = try Assignment.start(f, w, .bool); - try f.writeCValue(w, local, .Other); - try a.assign(f, w); + try f.writeCValue(w, local, .other); + try w.writeAll(" = "); - const operand_ctype = try f.ctypeFromType(operand_ty, .complete); - if (lhs != .undef and lhs.eql(rhs)) try w.writeAll(switch (operator) { - .lt, .lte, .gte, .gt => unreachable, - .neq => "false", - .eq => "true", - }) else switch (operand_ctype.info(ctype_pool)) { - .basic, .pointer => { - try f.writeCValue(w, lhs, .Other); - try w.writeAll(compareOperatorC(operator)); - try f.writeCValue(w, rhs, .Other); - }, - .aligned, .array, .vector, .fwd_decl, .function => unreachable, - .aggregate => |aggregate| if (aggregate.fields.len == 2 and - (aggregate.fields.at(0, ctype_pool).name.index == .is_null or - aggregate.fields.at(1, ctype_pool).name.index == .is_null)) - { - try f.writeCValueMember(w, lhs, .{ .identifier = "is_null" }); - try w.writeAll(" || "); - try f.writeCValueMember(w, rhs, .{ .identifier = "is_null" }); - try w.writeAll(" ? "); - try f.writeCValueMember(w, lhs, .{ .identifier = "is_null" }); - try w.writeAll(compareOperatorC(operator)); - try f.writeCValueMember(w, rhs, .{ .identifier = "is_null" }); - try w.writeAll(" : "); - try f.writeCValueMember(w, lhs, .{ .identifier = "payload" }); - try w.writeAll(compareOperatorC(operator)); - try f.writeCValueMember(w, rhs, .{ .identifier = "payload" }); - } else for (0..aggregate.fields.len) |field_index| { - if (field_index > 0) try w.writeAll(switch (operator) { - .lt, .lte, .gte, .gt => unreachable, - .eq => " && ", - .neq => " || ", - }); - const field_name: CValue = .{ - .ctype_pool_string = aggregate.fields.at(field_index, ctype_pool).name, - }; - try f.writeCValueMember(w, lhs, field_name); - try w.writeAll(compareOperatorC(operator)); - try f.writeCValueMember(w, rhs, field_name); + switch (operand_ty.zigTypeTag(zcu)) { + .optional => switch (CType.classifyOptional(operand_ty, zcu)) { + .npv_payload => unreachable, // opv optional + + .error_set, .ptr_like => {}, + + .slice_like => unreachable, // equality is not defined on slices + + .opv_payload => { + try f.writeCValueMember(w, lhs, .{ .identifier = "is_null" }); + try w.writeAll(compareOperatorC(operator)); + try f.writeCValueMember(w, rhs, .{ .identifier = "is_null" }); + try w.writeByte(';'); + try f.newline(); + return local; + }, + + .@"struct" => { + // `lhs.is_null || rhs.is_null ? lhs.is_null == rhs.is_null : lhs.payload == rhs.payload` + try f.writeCValueMember(w, lhs, .{ .identifier = "is_null" }); + try w.writeAll(" || "); + try f.writeCValueMember(w, rhs, .{ .identifier = "is_null" }); + try w.writeAll(" ? "); + try f.writeCValueMember(w, lhs, .{ .identifier = "is_null" }); + try w.writeAll(compareOperatorC(operator)); + try f.writeCValueMember(w, rhs, .{ .identifier = "is_null" }); + try w.writeAll(" : "); + try f.writeCValueMember(w, lhs, .{ .identifier = "payload" }); + try w.writeAll(compareOperatorC(operator)); + try f.writeCValueMember(w, rhs, .{ .identifier = "payload" }); + try w.writeByte(';'); + try f.newline(); + return local; + }, }, + .bool, .int, .pointer, .@"enum", .error_set => {}, + .@"struct", .@"union" => assert(operand_ty.containerLayout(zcu) == .@"packed"), + else => unreachable, } - try a.end(f, w); + + try f.writeCValue(w, lhs, .other); + try w.writeAll(compareOperatorC(operator)); + try f.writeCValue(w, rhs, .other); + try w.writeByte(';'); + try f.newline(); return local; } @@ -4408,18 +3738,18 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { const operand = try f.resolveInst(un_op); try reap(f, inst, &.{un_op}); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, .bool); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try w.writeAll(" = "); - try f.writeCValue(w, operand, .Other); + try f.writeCValue(w, operand, .other); try w.print(" < sizeof({f}) / sizeof(*{0f});", .{fmtIdentSolo("zig_errorName")}); - try f.object.newline(); + try f.newline(); return local; } fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; @@ -4432,38 +3762,34 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { const inst_scalar_ty = inst_ty.scalarType(zcu); const elem_ty = inst_scalar_ty.indexableElem(zcu); assert(elem_ty.hasRuntimeBits(zcu)); - const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); const local = try f.allocLocal(inst, inst_ty); - const w = &f.object.code.writer; + const w = &f.code.writer; const v = try Vectorize.start(f, inst, w, inst_ty); - const a = try Assignment.start(f, w, inst_scalar_ctype); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try v.elem(f, w); - try a.assign(f, w); + try w.writeAll(" = "); // We must convert to and from integer types to prevent UB if the operation // results in a NULL pointer, or if LHS is NULL. The operation is only UB // if the result is NULL and then dereferenced. try w.writeByte('('); - try f.renderCType(w, inst_scalar_ctype); + try f.renderType(w, inst_scalar_ty); try w.writeAll(")(((uintptr_t)"); - try f.writeCValue(w, lhs, .Other); + try f.writeCValue(w, lhs, .other); try v.elem(f, w); - try w.writeAll(") "); - try w.writeByte(operator); - try w.writeAll(" ("); - try f.writeCValue(w, rhs, .Other); + try w.print(") {c} (", .{operator}); + try f.writeCValue(w, rhs, .other); try v.elem(f, w); try w.writeAll("*sizeof("); try f.renderType(w, elem_ty); - try w.writeAll(")))"); - try a.end(f, w); + try w.writeAll(")));"); + try f.newline(); try v.end(f, inst, w); return local; } fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; @@ -4477,36 +3803,34 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons const rhs = try f.resolveInst(bin_op.rhs); try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); const v = try Vectorize.start(f, inst, w, inst_ty); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try v.elem(f, w); // (lhs <> rhs) ? lhs : rhs try w.writeAll(" = ("); - try f.writeCValue(w, lhs, .Other); + try f.writeCValue(w, lhs, .other); try v.elem(f, w); try w.writeByte(' '); try w.writeByte(operator); try w.writeByte(' '); - try f.writeCValue(w, rhs, .Other); + try f.writeCValue(w, rhs, .other); try v.elem(f, w); try w.writeAll(") ? "); - try f.writeCValue(w, lhs, .Other); + try f.writeCValue(w, lhs, .other); try v.elem(f, w); try w.writeAll(" : "); - try f.writeCValue(w, rhs, .Other); + try f.writeCValue(w, rhs, .other); try v.elem(f, w); try w.writeByte(';'); - try f.object.newline(); + try f.newline(); try v.end(f, inst, w); return local; } fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; - const zcu = pt.zcu; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; @@ -4515,24 +3839,22 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); const inst_ty = f.typeOfIndex(inst); - const ptr_ty = inst_ty.slicePtrFieldType(zcu); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); - { - const a = try Assignment.start(f, w, try f.ctypeFromType(ptr_ty, .complete)); - try f.writeCValueMember(w, local, .{ .identifier = "ptr" }); - try a.assign(f, w); - try f.writeCValue(w, ptr, .Other); - try a.end(f, w); - } - { - const a = try Assignment.start(f, w, .usize); - try f.writeCValueMember(w, local, .{ .identifier = "len" }); - try a.assign(f, w); - try f.writeCValue(w, len, .Other); - try a.end(f, w); - } + + try f.writeCValueMember(w, local, .{ .identifier = "ptr" }); + try w.writeAll(" = "); + try f.writeCValue(w, ptr, .other); + try w.writeByte(';'); + try f.newline(); + + try f.writeCValueMember(w, local, .{ .identifier = "len" }); + try w.writeAll(" = "); + try f.writeCValue(w, len, .other); + try w.writeByte(';'); + try f.newline(); + return local; } @@ -4541,14 +3863,14 @@ fn airCall( inst: Air.Inst.Index, modifier: std.builtin.CallModifier, ) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; // Not even allowed to call panic in a naked function. - if (f.object.dg.is_naked_fn) return .none; + if (f.dg.is_naked_fn) return .none; - const gpa = f.object.dg.gpa; - const w = &f.object.code.writer; + const gpa = f.dg.gpa; + const w = &f.code.writer; const call = f.air.unwrapCall(inst); const args = call.args; @@ -4557,27 +3879,11 @@ fn airCall( defer gpa.free(resolved_args); for (resolved_args, args) |*resolved_arg, arg| { const arg_ty = f.typeOf(arg); - const arg_ctype = try f.ctypeFromType(arg_ty, .parameter); - if (arg_ctype.index == .void) { + if (!arg_ty.hasRuntimeBits(zcu)) { resolved_arg.* = .none; continue; } resolved_arg.* = try f.resolveInst(arg); - if (!arg_ctype.eql(try f.ctypeFromType(arg_ty, .complete))) { - const array_local = try f.allocAlignedLocal(inst, .{ - .ctype = arg_ctype, - .alignas = CType.AlignAs.fromAbiAlignment(arg_ty.abiAlignment(zcu)), - }); - try w.writeAll("memcpy("); - try f.writeCValueMember(w, array_local, .{ .identifier = "array" }); - try w.writeAll(", "); - try f.writeCValue(w, resolved_arg.*, .FunctionArgument); - try w.writeAll(", sizeof("); - try f.renderCType(w, arg_ctype); - try w.writeAll("));"); - try f.object.newline(); - resolved_arg.* = array_local; - } } const callee = try f.resolveInst(call.callee); @@ -4596,28 +3902,22 @@ fn airCall( }; const fn_info = zcu.typeToFunc(if (callee_is_ptr) callee_ty.childType(zcu) else callee_ty).?; const ret_ty: Type = .fromInterned(fn_info.return_type); - const ret_ctype: CType = if (ret_ty.isNoReturn(zcu)) - .void - else - try f.ctypeFromType(ret_ty, .parameter); const result_local = result: { if (modifier == .always_tail) { try w.writeAll("zig_always_tail return "); break :result .none; - } else if (ret_ctype.index == .void) { + } else if (!ret_ty.hasRuntimeBits(zcu)) { break :result .none; } else if (f.liveness.isUnused(inst)) { - try w.writeByte('('); - try f.renderCType(w, .void); - try w.writeByte(')'); + try w.writeAll("(void)"); break :result .none; } else { const local = try f.allocAlignedLocal(inst, .{ - .ctype = ret_ctype, - .alignas = CType.AlignAs.fromAbiAlignment(ret_ty.abiAlignment(zcu)), + .type = ret_ty, + .alignment = .none, }); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try w.writeAll(" = "); break :result local; } @@ -4644,8 +3944,19 @@ fn airCall( if (!callee_is_ptr) try w.writeByte('&'); } switch (modifier) { - .auto, .always_tail => try f.object.dg.renderNavName(w, fn_nav), - inline .never_tail, .never_inline => |m| try w.writeAll(try f.getLazyFnName(@unionInit(LazyFnKey, @tagName(m), fn_nav))), + .auto, .always_tail => try renderNavName(w, fn_nav, ip), + .never_tail => { + try f.need_never_tail_funcs.put(gpa, fn_nav, {}); + try w.print("zig_never_tail_{f}__{d}", .{ + fmtIdentUnsolo(ip.getNav(fn_nav).name.toSlice(ip)), @intFromEnum(fn_nav), + }); + }, + .never_inline => { + try f.need_never_inline_funcs.put(gpa, fn_nav, {}); + try w.print("zig_never_inline_{f}__{d}", .{ + fmtIdentUnsolo(ip.getNav(fn_nav).name.toSlice(ip)), @intFromEnum(fn_nav), + }); + }, else => unreachable, } if (need_cast) try w.writeByte(')'); @@ -4658,7 +3969,7 @@ fn airCall( else => unreachable, } // Fall back to function pointer call. - try f.writeCValue(w, callee, .Other); + try f.writeCValue(w, callee, .other); } try w.writeByte('('); @@ -4667,38 +3978,20 @@ fn airCall( if (resolved_arg == .none) continue; if (need_comma) try w.writeAll(", "); need_comma = true; - try f.writeCValue(w, resolved_arg, .FunctionArgument); - try f.freeCValue(inst, resolved_arg); + try f.writeCValue(w, resolved_arg, .other); } try w.writeAll(");"); switch (modifier) { .always_tail => try w.writeByte('\n'), - else => try f.object.newline(), + else => try f.newline(), } - const result = result: { - if (result_local == .none or !lowersToArray(ret_ty, zcu)) - break :result result_local; - - const array_local = try f.allocLocal(inst, ret_ty); - try w.writeAll("memcpy("); - try f.writeCValue(w, array_local, .FunctionArgument); - try w.writeAll(", "); - try f.writeCValueMember(w, result_local, .{ .identifier = "array" }); - try w.writeAll(", sizeof("); - try f.renderType(w, ret_ty); - try w.writeAll("));"); - try f.object.newline(); - try freeLocal(f, inst, result_local.new_local, null); - break :result array_local; - }; - - return result; + return result_local; } fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue { const dbg_stmt = f.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt; - const w = &f.object.code.writer; + const w = &f.code.writer; // TODO re-evaluate whether to emit these or not. If we naively emit // these directives, the output file will report bogus line numbers because // every newline after the #line directive adds one to the line. @@ -4707,32 +4000,32 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue { // newlines until the next dbg_stmt occurs. // Perhaps an additional compilation option is in order? //try w.print("#line {d}", .{dbg_stmt.line + 1}); - //try f.object.newline(); + //try f.newline(); try w.print("/* file:{d}:{d} */", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 }); - try f.object.newline(); + try f.newline(); return .none; } fn airDbgEmptyStmt(f: *Function, _: Air.Inst.Index) !CValue { - try f.object.code.writer.writeAll("(void)0;"); - try f.object.newline(); + try f.code.writer.writeAll("(void)0;"); + try f.newline(); return .none; } fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; const block = f.air.unwrapDbgBlock(inst); const owner_nav = ip.getNav(zcu.funcInfo(block.func).owner_nav); - const w = &f.object.code.writer; + const w = &f.code.writer; try w.print("/* inline:{f} */", .{owner_nav.fqn.fmt(&zcu.intern_pool)}); - try f.object.newline(); + try f.newline(); return lowerBlock(f, inst, block.body); } fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const tag = f.air.instructions.items(.tag)[@intFromEnum(inst)]; const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; @@ -4741,9 +4034,9 @@ fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue { if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand); try reap(f, inst, &.{pl_op.operand}); - const w = &f.object.code.writer; + const w = &f.code.writer; try w.print("/* {s}:{s} */", .{ @tagName(tag), name.toSlice(f.air) }); - try f.object.newline(); + try f.newline(); return .none; } @@ -4753,13 +4046,13 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue { } fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const liveness_block = f.liveness.getBlock(inst); const block_id = f.next_block_index; f.next_block_index += 1; - const w = &f.object.code.writer; + const w = &f.code.writer; const inst_ty = f.typeOfIndex(inst); const result = if (inst_ty.hasRuntimeBits(zcu) and !f.liveness.isUnused(inst)) @@ -4767,7 +4060,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) else .none; - try f.blocks.putNoClobber(f.object.dg.gpa, inst, .{ + try f.blocks.putNoClobber(f.dg.gpa, inst, .{ .block_id = block_id, .result = result, }); @@ -4782,23 +4075,23 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) } // noreturn blocks have no `br` instructions reaching them, so we don't want a label - if (f.object.dg.is_naked_fn) { - if (f.object.dg.expected_block) |expected_block| { + if (f.dg.is_naked_fn) { + if (f.dg.expected_block) |expected_block| { if (block_id != expected_block) return f.fail("runtime code not allowed in naked function", .{}); - f.object.dg.expected_block = null; + f.dg.expected_block = null; } } else if (!f.typeOfIndex(inst).isNoReturn(zcu)) { // label must be followed by an expression, include an empty one. try w.print("\nzig_block_{d}:;", .{block_id}); - try f.object.newline(); + try f.newline(); } return result; } fn airTry(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const unwrapped_try = f.air.unwrapTry(inst); const body = unwrapped_try.else_body; const err_union_ty = f.air.typeOf(unwrapped_try.error_union, &pt.zcu.intern_pool); @@ -4806,7 +4099,7 @@ fn airTry(f: *Function, inst: Air.Inst.Index) !CValue { } fn airTryPtr(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const unwrapped_try = f.air.unwrapTryPtr(inst); const body = unwrapped_try.else_body; const err_union_ty = f.air.typeOf(unwrapped_try.error_union_ptr, &pt.zcu.intern_pool).childType(pt.zcu); @@ -4821,46 +4114,38 @@ fn lowerTry( err_union_ty: Type, is_ptr: bool, ) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const err_union = try f.resolveInst(operand); const inst_ty = f.typeOfIndex(inst); const liveness_condbr = f.liveness.getCondBr(inst); - const w = &f.object.code.writer; + const w = &f.code.writer; const payload_ty = err_union_ty.errorUnionPayload(zcu); - const payload_has_bits = payload_ty.hasRuntimeBits(zcu); - if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) { - try w.writeAll("if ("); - if (!payload_has_bits) { - if (is_ptr) - try f.writeCValueDeref(w, err_union) - else - try f.writeCValue(w, err_union, .Other); - } else { - // Reap the operand so that it can be reused inside genBody. - // Remember we must avoid calling reap() twice for the same operand - // in this function. - try reap(f, inst, &.{operand}); - if (is_ptr) - try f.writeCValueDerefMember(w, err_union, .{ .identifier = "error" }) - else - try f.writeCValueMember(w, err_union, .{ .identifier = "error" }); - } - try w.writeAll(") "); + try w.writeAll("if ("); - try genBodyResolveState(f, inst, liveness_condbr.else_deaths, body, false); - try f.object.newline(); - if (f.object.dg.expected_block) |_| - return f.fail("runtime code not allowed in naked function", .{}); - } + // Reap the operand so that it can be reused inside genBody. + // Remember we must avoid calling reap() twice for the same operand + // in this function. + try reap(f, inst, &.{operand}); + if (is_ptr) + try f.writeCValueDerefMember(w, err_union, .{ .identifier = "error" }) + else + try f.writeCValueMember(w, err_union, .{ .identifier = "error" }); + + try w.writeAll(") "); + + try genBodyResolveState(f, inst, liveness_condbr.else_deaths, body, false); + try f.newline(); + if (f.dg.expected_block) |_| + return f.fail("runtime code not allowed in naked function", .{}); // Now we have the "then branch" (in terms of the liveness data); process any deaths. for (liveness_condbr.then_deaths) |death| { try die(f, inst, death.toRef()); } - if (!payload_has_bits) { + if (!payload_ty.hasRuntimeBits(zcu)) { if (!is_ptr) { return .none; } else { @@ -4873,14 +4158,14 @@ fn lowerTry( if (f.liveness.isUnused(inst)) return .none; const local = try f.allocLocal(inst, inst_ty); - const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); - try f.writeCValue(w, local, .Other); - try a.assign(f, w); + try f.writeCValue(w, local, .other); + try w.writeAll(" = "); if (is_ptr) { try w.writeByte('&'); try f.writeCValueDerefMember(w, err_union, .{ .identifier = "payload" }); } else try f.writeCValueMember(w, err_union, .{ .identifier = "payload" }); - try a.end(f, w); + try w.writeByte(';'); + try f.newline(); return local; } @@ -4888,25 +4173,24 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !void { const branch = f.air.instructions.items(.data)[@intFromEnum(inst)].br; const block = f.blocks.get(branch.block_inst).?; const result = block.result; - const w = &f.object.code.writer; + const w = &f.code.writer; - if (f.object.dg.is_naked_fn) { + if (f.dg.is_naked_fn) { if (result != .none) return f.fail("runtime code not allowed in naked function", .{}); - f.object.dg.expected_block = block.block_id; + f.dg.expected_block = block.block_id; return; } // If result is .none then the value of the block is unused. if (result != .none) { - const operand_ty = f.typeOf(branch.operand); const operand = try f.resolveInst(branch.operand); try reap(f, inst, &.{branch.operand}); - const a = try Assignment.start(f, w, try f.ctypeFromType(operand_ty, .complete)); - try f.writeCValue(w, result, .Other); - try a.assign(f, w); - try f.writeCValue(w, operand, .Other); - try a.end(f, w); + try f.writeCValue(w, result, .other); + try w.writeAll(" = "); + try f.writeCValue(w, operand, .other); + try w.writeByte(';'); + try f.newline(); } try w.print("goto zig_block_{d};\n", .{block.block_id}); @@ -4914,14 +4198,14 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !void { fn airRepeat(f: *Function, inst: Air.Inst.Index) !void { const repeat = f.air.instructions.items(.data)[@intFromEnum(inst)].repeat; - try f.object.code.writer.print("goto zig_loop_{d};\n", .{@intFromEnum(repeat.loop_inst)}); + try f.code.writer.print("goto zig_loop_{d};\n", .{@intFromEnum(repeat.loop_inst)}); } fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const br = f.air.instructions.items(.data)[@intFromEnum(inst)].br; - const w = &f.object.code.writer; + const w = &f.code.writer; if (try f.air.value(br.operand, pt)) |cond_val| { // Comptime-known dispatch. Iterate the cases to find the correct @@ -4950,11 +4234,11 @@ fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void { // Runtime-known dispatch. Set the switch condition, and branch back. const cond = try f.resolveInst(br.operand); const cond_local = f.loop_switch_conds.get(br.block_inst).?; - try f.writeCValue(w, .{ .local = cond_local }, .Other); + try f.writeCValue(w, .{ .local = cond_local }, .other); try w.writeAll(" = "); - try f.writeCValue(w, cond, .Other); + try f.writeCValue(w, cond, .other); try w.writeByte(';'); - try f.object.newline(); + try f.newline(); try w.print("goto zig_switch_{d}_loop;\n", .{@intFromEnum(br.block_inst)}); } @@ -4971,11 +4255,10 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { } fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; - const target = &f.object.dg.mod.resolved_target.result; - const ctype_pool = &f.object.dg.ctype_pool; - const w = &f.object.code.writer; + const target = &f.dg.mod.resolved_target.result; + const w = &f.code.writer; if (operand_ty.isAbiInt(zcu) and dest_ty.isAbiInt(zcu)) { const src_info = dest_ty.intInfo(zcu); @@ -4986,26 +4269,16 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal if (dest_ty.isPtrAtRuntime(zcu) or operand_ty.isPtrAtRuntime(zcu)) { const local = try f.allocLocal(null, dest_ty); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try w.writeAll(" = ("); try f.renderType(w, dest_ty); try w.writeByte(')'); - try f.writeCValue(w, operand, .Other); + try f.writeCValue(w, operand, .other); try w.writeByte(';'); - try f.object.newline(); + try f.newline(); return local; } - const operand_lval = if (operand == .constant) blk: { - const operand_local = try f.allocLocal(null, operand_ty); - try f.writeCValue(w, operand_local, .Other); - try w.writeAll(" = "); - try f.writeCValue(w, operand, .Other); - try w.writeByte(';'); - try f.object.newline(); - break :blk operand_local; - } else operand; - const local = try f.allocLocal(null, dest_ty); // On big-endian targets, copying ABI integers with padding bits is awkward, because the padding bits are at the low bytes of the value. // We need to offset the source or destination pointer appropriately and copy the right number of bytes. @@ -5013,141 +4286,134 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal // e.g. [10]u8 -> u80. We need to offset the destination so that we copy to the least significant bits of the integer. const offset = dest_ty.abiSize(zcu) - operand_ty.abiSize(zcu); try w.writeAll("memcpy((char *)&"); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try w.print(" + {d}, &", .{offset}); - try f.writeCValue(w, operand_lval, .Other); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } try w.print(", {d});", .{operand_ty.abiSize(zcu)}); } else if (target.cpu.arch.endian() == .big and operand_ty.isAbiInt(zcu) and !dest_ty.isAbiInt(zcu)) { // e.g. u80 -> [10]u8. We need to offset the source so that we copy from the least significant bits of the integer. const offset = operand_ty.abiSize(zcu) - dest_ty.abiSize(zcu); try w.writeAll("memcpy(&"); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try w.writeAll(", (const char *)&"); - try f.writeCValue(w, operand_lval, .Other); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } try w.print(" + {d}, {d});", .{ offset, dest_ty.abiSize(zcu) }); } else { try w.writeAll("memcpy(&"); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try w.writeAll(", &"); - try f.writeCValue(w, operand_lval, .Other); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } try w.print(", {d});", .{@min(dest_ty.abiSize(zcu), operand_ty.abiSize(zcu))}); } - try f.object.newline(); + try f.newline(); // Ensure padding bits have the expected value. if (dest_ty.isAbiInt(zcu)) { - const dest_ctype = try f.ctypeFromType(dest_ty, .complete); - const dest_info = dest_ty.intInfo(zcu); - var bits: u16 = dest_info.bits; - var wrap_ctype: ?CType = null; - var need_bitcasts = false; - - try f.writeCValue(w, local, .Other); - switch (dest_ctype.info(ctype_pool)) { - else => {}, - .array => |array_info| { - try w.print("[{d}]", .{switch (target.cpu.arch.endian()) { - .little => array_info.len - 1, - .big => 0, - }}); - wrap_ctype = array_info.elem_ctype.toSignedness(dest_info.signedness); - need_bitcasts = wrap_ctype.?.index == .zig_i128; - bits -= 1; - bits %= @as(u16, @intCast(f.byteSize(array_info.elem_ctype) * 8)); - bits += 1; + switch (CType.classifyInt(dest_ty, zcu)) { + .void => unreachable, // opv + .small => { + try f.writeCValue(w, local, .other); + try w.writeAll(" = zig_wrap_"); + try f.dg.renderTypeForBuiltinFnName(w, dest_ty); + try w.writeByte('('); + try f.writeCValue(w, local, .other); + try f.dg.renderBuiltinInfo(w, dest_ty, .bits); + try w.writeAll(");"); + try f.newline(); }, - } - try w.writeAll(" = "); - if (need_bitcasts) { - try w.writeAll("zig_bitCast_"); - try f.object.dg.renderCTypeForBuiltinFnName(w, wrap_ctype.?.toUnsigned()); - try w.writeByte('('); - } - try w.writeAll("zig_wrap_"); - const info_ty = try pt.intType(dest_info.signedness, bits); - if (wrap_ctype) |ctype| - try f.object.dg.renderCTypeForBuiltinFnName(w, ctype) - else - try f.object.dg.renderTypeForBuiltinFnName(w, info_ty); - try w.writeByte('('); - if (need_bitcasts) { - try w.writeAll("zig_bitCast_"); - try f.object.dg.renderCTypeForBuiltinFnName(w, wrap_ctype.?); - try w.writeByte('('); - } - try f.writeCValue(w, local, .Other); - switch (dest_ctype.info(ctype_pool)) { - else => {}, - .array => |array_info| try w.print("[{d}]", .{ - switch (target.cpu.arch.endian()) { - .little => array_info.len - 1, + .big => |big| { + const dest_info = dest_ty.intInfo(zcu); + const padding_index: u16 = switch (target.cpu.arch.endian()) { + .little => big.limbs_len - 1, .big => 0, - }, - }), + }; + const wrap_bits = ((dest_info.bits - 1) % big.limb_size.bits()) + 1; + if (big.limb_size != .@"128" or dest_info.signedness == .unsigned) { + try f.writeCValueMember(w, local, .{ .identifier = "limbs" }); + try w.print("[{d}] = zig_wrap_{c}{d}(", .{ + padding_index, + signAbbrev(dest_info.signedness), + big.limb_size.bits(), + }); + try f.writeCValueMember(w, local, .{ .identifier = "limbs" }); + try w.print("[{d}], {d});", .{ padding_index, wrap_bits }); + } else { + try f.writeCValueMember(w, local, .{ .identifier = "limbs" }); + try w.print("[{d}] = zig_bitCast_u128(zig_wrap_i128(zig_bitCast_i128(", .{ + padding_index, + }); + try f.writeCValueMember(w, local, .{ .identifier = "limbs" }); + try w.print("[{d}]), {d}));", .{ padding_index, wrap_bits }); + try f.newline(); + } + }, } - if (need_bitcasts) try w.writeByte(')'); - try f.object.dg.renderBuiltinInfo(w, info_ty, .bits); - if (need_bitcasts) try w.writeByte(')'); - try w.writeAll(");"); - try f.object.newline(); } - try f.freeCValue(null, operand_lval); return local; } -fn airTrap(f: *Function, w: *Writer) !void { +fn airTrap(f: *Function) !void { // Not even allowed to call trap in a naked function. - if (f.object.dg.is_naked_fn) return; - try w.writeAll("zig_trap();\n"); + if (f.dg.is_naked_fn) return; + try f.code.writer.writeAll("zig_trap();\n"); } fn airBreakpoint(f: *Function) !CValue { - const w = &f.object.code.writer; + const w = &f.code.writer; try w.writeAll("zig_breakpoint();"); - try f.object.newline(); + try f.newline(); return .none; } fn airRetAddr(f: *Function, inst: Air.Inst.Index) !CValue { - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, .usize); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try w.writeAll(" = ("); try f.renderType(w, .usize); try w.writeAll(")zig_return_address();"); - try f.object.newline(); + try f.newline(); return local; } fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue { - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, .usize); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try w.writeAll(" = ("); try f.renderType(w, .usize); try w.writeAll(")zig_frame_address();"); - try f.object.newline(); + try f.newline(); return local; } -fn airUnreach(o: *Object) !void { +fn airUnreach(f: *Function) !void { // Not even allowed to call unreachable in a naked function. - if (o.dg.is_naked_fn) return; - try o.code.writer.writeAll("zig_unreachable();\n"); + if (f.dg.is_naked_fn) return; + try f.code.writer.writeAll("zig_unreachable();\n"); } fn airLoop(f: *Function, inst: Air.Inst.Index) !void { const block = f.air.unwrapBlock(inst); - const w = &f.object.code.writer; + const w = &f.code.writer; // `repeat` instructions matching this loop will branch to // this label. Since we need a label for arbitrary `repeat` // anyway, there's actually no need to use a "real" looping // construct at all! try w.print("zig_loop_{d}:", .{@intFromEnum(inst)}); - try f.object.newline(); + try f.newline(); try genBodyInner(f, block.body); // no need to restore state, we're noreturn } @@ -5158,15 +4424,15 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !void { const then_body = cond_br.then_body; const else_body = cond_br.else_body; const liveness_condbr = f.liveness.getCondBr(inst); - const w = &f.object.code.writer; + const w = &f.code.writer; try w.writeAll("if ("); - try f.writeCValue(w, cond, .Other); + try f.writeCValue(w, cond, .other); try w.writeAll(") "); try genBodyResolveState(f, inst, liveness_condbr.then_deaths, then_body, false); - try f.object.newline(); - if (else_body.len > 0) if (f.object.dg.expected_block) |_| + try f.newline(); + if (else_body.len > 0) if (f.dg.expected_block) |_| return f.fail("runtime code not allowed in naked function", .{}); // We don't need to use `genBodyResolveState` for the else block, because this instruction is @@ -5184,23 +4450,23 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !void { } fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; - const gpa = f.object.dg.gpa; + const gpa = f.dg.gpa; const switch_br = f.air.unwrapSwitch(inst); const init_condition = try f.resolveInst(switch_br.operand); try reap(f, inst, &.{switch_br.operand}); const condition_ty = f.typeOf(switch_br.operand); - const w = &f.object.code.writer; + const w = &f.code.writer; // For dispatches, we will create a local alloc to contain the condition value. // This may not result in optimal codegen for switch loops, but it minimizes the // amount of C code we generate, which is probably more desirable here (and is simpler). const condition = if (is_dispatch_loop) cond: { const new_local = try f.allocLocal(inst, condition_ty); - try f.copyCValue(try f.ctypeFromType(condition_ty, .complete), new_local, init_condition); + try f.copyCValue(new_local, init_condition); try w.print("zig_switch_{d}_loop:", .{@intFromEnum(inst)}); - try f.object.newline(); + try f.newline(); try f.loop_switch_conds.put(gpa, inst, new_local.new_local); break :cond new_local; } else init_condition; @@ -5222,9 +4488,9 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void try f.renderType(w, lowered_condition_ty); try w.writeByte(')'); } - try f.writeCValue(w, condition, .Other); + try f.writeCValue(w, condition, .other); try w.writeAll(") {"); - f.object.indent(); + f.indent(); const liveness = try f.liveness.getSwitchBr(gpa, inst, switch_br.cases_len + 1); defer gpa.free(liveness.deaths); @@ -5237,7 +4503,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void continue; } for (case.items) |item| { - try f.object.newline(); + try f.newline(); try w.writeAll("case "); const item_value = try f.air.value(item, pt); // If `item_value` is a pointer with a known integer address, print the address @@ -5254,28 +4520,28 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void try f.renderType(w, .usize); try w.writeByte(')'); } - try f.object.dg.renderValue(w, (try f.air.value(item, pt)).?, .Other); + try f.dg.renderValue(w, (try f.air.value(item, pt)).?, .other); } try w.writeByte(':'); } try w.writeAll(" {"); - f.object.indent(); - try f.object.newline(); + f.indent(); + try f.newline(); if (is_dispatch_loop) { try w.print("zig_switch_{d}_dispatch_{d}:;", .{ @intFromEnum(inst), case.idx }); - try f.object.newline(); + try f.newline(); } try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true); - try f.object.outdent(); + try f.outdent(); try w.writeByte('}'); - if (f.object.dg.expected_block) |_| + if (f.dg.expected_block) |_| return f.fail("runtime code not allowed in naked function", .{}); // The case body must be noreturn so we don't need to insert a break. } const else_body = it.elseBody(); - try f.object.newline(); + try f.newline(); try w.writeAll("default: "); if (any_range_cases) { @@ -5288,33 +4554,33 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void try w.writeAll("if ("); for (case.items, 0..) |item, item_i| { if (item_i != 0) try w.writeAll(" || "); - try f.writeCValue(w, condition, .Other); + try f.writeCValue(w, condition, .other); try w.writeAll(" == "); - try f.object.dg.renderValue(w, (try f.air.value(item, pt)).?, .Other); + try f.dg.renderValue(w, (try f.air.value(item, pt)).?, .other); } for (case.ranges, 0..) |range, range_i| { if (case.items.len != 0 or range_i != 0) try w.writeAll(" || "); // "(x >= lower && x <= upper)" try w.writeByte('('); - try f.writeCValue(w, condition, .Other); + try f.writeCValue(w, condition, .other); try w.writeAll(" >= "); - try f.object.dg.renderValue(w, (try f.air.value(range[0], pt)).?, .Other); + try f.dg.renderValue(w, (try f.air.value(range[0], pt)).?, .other); try w.writeAll(" && "); - try f.writeCValue(w, condition, .Other); + try f.writeCValue(w, condition, .other); try w.writeAll(" <= "); - try f.object.dg.renderValue(w, (try f.air.value(range[1], pt)).?, .Other); + try f.dg.renderValue(w, (try f.air.value(range[1], pt)).?, .other); try w.writeByte(')'); } try w.writeAll(") {"); - f.object.indent(); - try f.object.newline(); + f.indent(); + try f.newline(); if (is_dispatch_loop) { try w.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), case.idx }); } try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true); - try f.object.outdent(); + try f.outdent(); try w.writeByte('}'); - if (f.object.dg.expected_block) |_| + if (f.dg.expected_block) |_| return f.fail("runtime code not allowed in naked function", .{}); } } @@ -5328,16 +4594,16 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void try die(f, inst, death.toRef()); } try genBody(f, else_body); - if (f.object.dg.expected_block) |_| + if (f.dg.expected_block) |_| return f.fail("runtime code not allowed in naked function", .{}); - } else try airUnreach(&f.object); - try f.object.newline(); - try f.object.outdent(); + } else try airUnreach(f); + try f.newline(); + try f.outdent(); try w.writeAll("}\n"); } fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool { - const dg = f.object.dg; + const dg = f.dg; const target = &dg.mod.resolved_target.result; return switch (constraint[0]) { '{' => true, @@ -5357,28 +4623,28 @@ fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool } fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const unwrapped_asm = f.air.unwrapAsm(inst); const is_volatile = unwrapped_asm.is_volatile; - const gpa = f.object.dg.gpa; + const gpa = f.dg.gpa; const outputs = unwrapped_asm.outputs; const inputs = unwrapped_asm.inputs; const result = result: { - const w = &f.object.code.writer; + const w = &f.code.writer; const inst_ty = f.typeOfIndex(inst); const inst_local = if (inst_ty.hasRuntimeBits(zcu)) local: { const inst_local = try f.allocLocalValue(.{ - .ctype = try f.ctypeFromType(inst_ty, .complete), - .alignas = CType.AlignAs.fromAbiAlignment(inst_ty.abiAlignment(zcu)), + .type = inst_ty, + .alignment = .none, }); if (f.wantSafety()) { - try f.writeCValue(w, inst_local, .Other); + try f.writeCValue(w, inst_local, .other); try w.writeAll(" = "); - try f.writeCValue(w, .{ .undef = inst_ty }, .Other); + try f.writeCValue(w, .{ .undef = inst_ty }, .other); try w.writeByte(';'); - try f.object.newline(); + try f.newline(); } break :local inst_local; } else .none; @@ -5399,20 +4665,20 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { const output_ty = if (output.operand == .none) inst_ty else f.typeOf(output.operand).childType(zcu); try w.writeAll("register "); const output_local = try f.allocLocalValue(.{ - .ctype = try f.ctypeFromType(output_ty, .complete), - .alignas = CType.AlignAs.fromAbiAlignment(output_ty.abiAlignment(zcu)), + .type = output_ty, + .alignment = .none, }); try f.allocs.put(gpa, output_local.new_local, false); - try f.object.dg.renderTypeAndName(w, output_ty, output_local, .{}, .none, .complete); + try f.dg.renderTypeAndName(w, output_ty, output_local, .{}, .none); try w.writeAll(" __asm(\""); try w.writeAll(constraint["={".len .. constraint.len - "}".len]); try w.writeAll("\")"); if (f.wantSafety()) { try w.writeAll(" = "); - try f.writeCValue(w, .{ .undef = output_ty }, .Other); + try f.writeCValue(w, .{ .undef = output_ty }, .other); } try w.writeByte(';'); - try f.object.newline(); + try f.newline(); } } @@ -5432,29 +4698,29 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { const input_ty = f.typeOf(input.operand); if (is_reg) try w.writeAll("register "); const input_local = try f.allocLocalValue(.{ - .ctype = try f.ctypeFromType(input_ty, .complete), - .alignas = CType.AlignAs.fromAbiAlignment(input_ty.abiAlignment(zcu)), + .type = input_ty, + .alignment = .none, }); try f.allocs.put(gpa, input_local.new_local, false); // Do not render the declaration as `const` qualified if we're generating an // explicit `register` local, as GCC will ignore the constraint completely. - try f.object.dg.renderTypeAndName(w, input_ty, input_local, if (is_reg) .{} else Const, .none, .complete); + try f.dg.renderTypeAndName(w, input_ty, input_local, .{ .@"const" = is_reg }, .none); if (is_reg) { try w.writeAll(" __asm(\""); try w.writeAll(constraint["{".len .. constraint.len - "}".len]); try w.writeAll("\")"); } try w.writeAll(" = "); - try f.writeCValue(w, input_val, .Other); + try f.writeCValue(w, input_val, .other); try w.writeByte(';'); - try f.object.newline(); + try f.newline(); } } { const asm_source = unwrapped_asm.source; - var stack = std.heap.stackFallback(256, f.object.dg.gpa); + var stack = std.heap.stackFallback(256, f.dg.gpa); const allocator = stack.get(); const fixed_asm_source = try allocator.alloc(u8, asm_source.len); defer allocator.free(fixed_asm_source); @@ -5520,10 +4786,10 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { const is_reg = constraint[1] == '{'; try w.print("{f}(", .{fmtStringLiteral(if (is_reg) "=r" else constraint, null)}); if (is_reg) { - try f.writeCValue(w, .{ .local = locals_index }, .Other); + try f.writeCValue(w, .{ .local = locals_index }, .other); locals_index += 1; } else if (output.operand == .none) { - try f.writeCValue(w, inst_local, .FunctionArgument); + try f.writeCValue(w, inst_local, .other); } else { try f.writeCValueDeref(w, try f.resolveInst(output.operand)); } @@ -5547,7 +4813,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { const input_local_idx = locals_index; locals_index += 1; break :local .{ .local = input_local_idx }; - } else input_val, .Other); + } else input_val, .other); try w.writeByte(')'); } try w.writeByte(':'); @@ -5567,7 +4833,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { const field_name = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?; assert(field_name.len != 0); - const target = &f.object.dg.mod.resolved_target.result; + const target = &f.dg.mod.resolved_target.result; var c_name_buf: [16]u8 = undefined; const name = if ((target.cpu.arch.isMIPS() or target.cpu.arch == .alpha) and field_name[0] == 'r') name: { @@ -5594,7 +4860,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { } w.undo(1); // erase the last comma try w.writeAll(");"); - try f.object.newline(); + try f.newline(); locals_index = locals_begin; it = unwrapped_asm.iterateOutputs(); @@ -5608,10 +4874,10 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { else try f.resolveInst(output.operand)); try w.writeAll(" = "); - try f.writeCValue(w, .{ .local = locals_index }, .Other); + try f.writeCValue(w, .{ .local = locals_index }, .other); locals_index += 1; try w.writeByte(';'); - try f.object.newline(); + try f.newline(); } } @@ -5633,147 +4899,145 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { fn airIsNull( f: *Function, inst: Air.Inst.Index, - operator: std.math.CompareOperator, + operator: enum { eq, neq }, is_ptr: bool, ) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; - const ctype_pool = &f.object.dg.ctype_pool; const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; - const w = &f.object.code.writer; + const w = &f.code.writer; const operand = try f.resolveInst(un_op); try reap(f, inst, &.{un_op}); const local = try f.allocLocal(inst, .bool); - const a = try Assignment.start(f, w, .bool); - try f.writeCValue(w, local, .Other); - try a.assign(f, w); + try f.writeCValue(w, local, .other); + try w.writeAll(" = "); const operand_ty = f.typeOf(un_op); const optional_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty; - const opt_ctype = try f.ctypeFromType(optional_ty, .complete); - const rhs = switch (opt_ctype.info(ctype_pool)) { - .basic, .pointer => rhs: { - if (is_ptr) - try f.writeCValueDeref(w, operand) - else - try f.writeCValue(w, operand, .Other); - break :rhs if (opt_ctype.isBool()) - "true" - else if (opt_ctype.isInteger()) - "0" - else - "NULL"; + + const pre: []const u8, const maybe_field: ?[]const u8, const post: []const u8 = switch (operator) { + // zig fmt: off + .eq => switch (CType.classifyOptional(optional_ty, zcu)) { + .npv_payload => unreachable, // opv optional + .error_set => .{ "", null, " == 0" }, + .ptr_like => .{ "", null, " == NULL" }, + .slice_like => .{ "", "ptr", " == NULL" }, + .opv_payload => .{ "", "is_null", "" }, + .@"struct" => .{ "", "is_null", "" }, }, - .aligned, .array, .vector, .fwd_decl, .function => unreachable, - .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) { - .is_null, .payload => rhs: { - if (is_ptr) - try f.writeCValueDerefMember(w, operand, .{ .identifier = "is_null" }) - else - try f.writeCValueMember(w, operand, .{ .identifier = "is_null" }); - break :rhs "true"; - }, - .ptr, .len => rhs: { - if (is_ptr) - try f.writeCValueDerefMember(w, operand, .{ .identifier = "ptr" }) - else - try f.writeCValueMember(w, operand, .{ .identifier = "ptr" }); - break :rhs "NULL"; - }, - else => unreachable, + .neq => switch (CType.classifyOptional(optional_ty, zcu)) { + .npv_payload => unreachable, // opv optional + .error_set => .{ "", null, " != 0" }, + .ptr_like => .{ "", null, " != NULL" }, + .slice_like => .{ "", "ptr", " != NULL" }, + .opv_payload => .{ "!", "is_null", "" }, + .@"struct" => .{ "!", "is_null", "" }, }, + // zig fmt: on }; - try w.writeAll(compareOperatorC(operator)); - try w.writeAll(rhs); - try a.end(f, w); + + try w.writeAll(pre); + if (maybe_field) |field| { + if (is_ptr) { + try f.writeCValueDerefMember(w, operand, .{ .identifier = field }); + } else { + try f.writeCValueMember(w, operand, .{ .identifier = field }); + } + } else { + if (is_ptr) { + try f.writeCValueDeref(w, operand); + } else { + try f.writeCValue(w, operand, .other); + } + } + try w.writeAll(post); + + try w.writeByte(';'); + try f.newline(); return local; } fn airOptionalPayload(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; - const ctype_pool = &f.object.dg.ctype_pool; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const inst_ty = f.typeOfIndex(inst); const operand_ty = f.typeOf(ty_op.operand); const opt_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty; - const opt_ctype = try f.ctypeFromType(opt_ty, .complete); - if (opt_ctype.isBool()) return if (is_ptr) .{ .undef = inst_ty } else .none; const operand = try f.resolveInst(ty_op.operand); - switch (opt_ctype.info(ctype_pool)) { - .basic, .pointer => return f.moveCValue(inst, inst_ty, operand), - .aligned, .array, .vector, .fwd_decl, .function => unreachable, - .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) { - .is_null, .payload => { - const w = &f.object.code.writer; - const local = try f.allocLocal(inst, inst_ty); - const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); - try f.writeCValue(w, local, .Other); - try a.assign(f, w); - if (is_ptr) { - try w.writeByte('&'); - try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" }); - } else try f.writeCValueMember(w, operand, .{ .identifier = "payload" }); - try a.end(f, w); - return local; - }, - .ptr, .len => return f.moveCValue(inst, inst_ty, operand), - else => unreachable, + + switch (CType.classifyOptional(opt_ty, zcu)) { + .npv_payload => unreachable, // opv optional + + .opv_payload => return if (is_ptr) .{ .undef = inst_ty } else .none, + + .error_set, + .ptr_like, + .slice_like, + => return f.moveCValue(inst, inst_ty, operand), + + .@"struct" => { + const w = &f.code.writer; + const local = try f.allocLocal(inst, inst_ty); + try f.writeCValue(w, local, .other); + try w.writeAll(" = "); + if (is_ptr) { + try w.writeByte('&'); + try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" }); + } else try f.writeCValueMember(w, operand, .{ .identifier = "payload" }); + try w.writeByte(';'); + try f.newline(); + return local; }, } } fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; - const w = &f.object.code.writer; + const w = &f.code.writer; const operand = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); const operand_ty = f.typeOf(ty_op.operand); + const opt_ty = operand_ty.childType(zcu); const inst_ty = f.typeOfIndex(inst); - const opt_ctype = try f.ctypeFromType(operand_ty.childType(zcu), .complete); - switch (opt_ctype.info(&f.object.dg.ctype_pool)) { - .basic => { - const a = try Assignment.start(f, w, opt_ctype); - try f.writeCValueDeref(w, operand); - try a.assign(f, w); - try f.object.dg.renderValue(w, Value.false, .Other); - try a.end(f, w); - return .none; + + switch (CType.classifyOptional(opt_ty, zcu)) { + .npv_payload => unreachable, // opv optional + + .opv_payload => { + try f.writeCValueDerefMember(w, operand, .{ .identifier = "is_null" }); + try w.writeAll(" = "); + try f.dg.renderValue(w, .false, .other); + try w.writeByte(';'); + try f.newline(); + return .{ .undef = inst_ty }; }, - .pointer => { + + .error_set, + .ptr_like, + .slice_like, + => return f.moveCValue(inst, inst_ty, operand), + + .@"struct" => { + try f.writeCValueDerefMember(w, operand, .{ .identifier = "is_null" }); + try w.writeAll(" = "); + try f.dg.renderValue(w, .false, .other); + try w.writeByte(';'); + try f.newline(); if (f.liveness.isUnused(inst)) return .none; const local = try f.allocLocal(inst, inst_ty); - const a = try Assignment.start(f, w, opt_ctype); - try f.writeCValue(w, local, .Other); - try a.assign(f, w); - try f.writeCValue(w, operand, .Other); - try a.end(f, w); - return local; - }, - .aligned, .array, .vector, .fwd_decl, .function => unreachable, - .aggregate => { - { - const a = try Assignment.start(f, w, opt_ctype); - try f.writeCValueDerefMember(w, operand, .{ .identifier = "is_null" }); - try a.assign(f, w); - try f.object.dg.renderValue(w, Value.false, .Other); - try a.end(f, w); - } - if (f.liveness.isUnused(inst)) return .none; - const local = try f.allocLocal(inst, inst_ty); - const a = try Assignment.start(f, w, opt_ctype); - try f.writeCValue(w, local, .Other); - try a.assign(f, w); - try w.writeByte('&'); + try f.writeCValue(w, local, .other); + try w.writeAll(" = &"); try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" }); - try a.end(f, w); + try w.writeByte(';'); + try f.newline(); return local; }, } @@ -5817,18 +5081,20 @@ fn fieldLocation( .union_type => { const loaded_union = ip.loadUnionType(container_ty.toIntern()); switch (loaded_union.layout) { - .auto, .@"extern" => { + .auto => { const field_ty: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBits(zcu)) - return if (loaded_union.has_runtime_tag and !container_ty.unionHasAllZeroBitFieldTypes(zcu)) - .{ .field = .{ .identifier = "payload" } } - else - .begin; + if (!field_ty.hasRuntimeBits(zcu)) { + if (container_ty.unionHasAllZeroBitFieldTypes(zcu)) return .begin; + return .{ .field = .{ .identifier = "payload" } }; + } const field_name = ip.loadEnumType(loaded_union.enum_tag_type).field_names.get(ip)[field_index]; - return .{ .field = if (loaded_union.has_runtime_tag) - .{ .payload_identifier = field_name.toSlice(ip) } - else - .{ .identifier = field_name.toSlice(ip) } }; + return .{ .field = .{ .payload_identifier = field_name.toSlice(ip) } }; + }, + .@"extern" => { + const field_ty: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); + if (!field_ty.hasRuntimeBits(zcu)) return .begin; + const field_name = ip.loadEnumType(loaded_union.enum_tag_type).field_names.get(ip)[field_index]; + return .{ .field = .{ .identifier = field_name.toSlice(ip) } }; }, .@"packed" => return .begin, } @@ -5865,7 +5131,7 @@ fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue } fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = f.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; @@ -5877,26 +5143,26 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { const field_ptr_val = try f.resolveInst(extra.field_ptr); try reap(f, inst, &.{extra.field_ptr}); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, container_ptr_ty); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try w.writeAll(" = ("); try f.renderType(w, container_ptr_ty); try w.writeByte(')'); switch (fieldLocation(container_ptr_ty, field_ptr_ty, extra.field_index, zcu)) { - .begin => try f.writeCValue(w, field_ptr_val, .Other), + .begin => try f.writeCValue(w, field_ptr_val, .other), .field => |field| { const u8_ptr_ty = try pt.adjustPtrTypeChild(field_ptr_ty, .u8); try w.writeAll("(("); try f.renderType(w, u8_ptr_ty); try w.writeByte(')'); - try f.writeCValue(w, field_ptr_val, .Other); + try f.writeCValue(w, field_ptr_val, .other); try w.writeAll(" - offsetof("); try f.renderType(w, container_ty); try w.writeAll(", "); - try f.writeCValue(w, field, .Other); + try f.writeCValue(w, field, .other); try w.writeAll("))"); }, .byte_offset => |byte_offset| { @@ -5905,7 +5171,7 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { try w.writeAll("(("); try f.renderType(w, u8_ptr_ty); try w.writeByte(')'); - try f.writeCValue(w, field_ptr_val, .Other); + try f.writeCValue(w, field_ptr_val, .other); try w.print(" - {f})", .{ try f.fmtIntLiteralDec(try pt.intValue(.usize, byte_offset)), }); @@ -5913,7 +5179,7 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { } try w.writeByte(';'); - try f.object.newline(); + try f.newline(); return local; } @@ -5924,23 +5190,19 @@ fn fieldPtr( container_ptr_val: CValue, field_index: u32, ) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; - const container_ty = container_ptr_ty.childType(zcu); const field_ptr_ty = f.typeOfIndex(inst); - // Ensure complete type definition is visible before accessing fields. - _ = try f.ctypeFromType(container_ty, .complete); - - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, field_ptr_ty); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try w.writeAll(" = ("); try f.renderType(w, field_ptr_ty); try w.writeByte(')'); switch (fieldLocation(container_ptr_ty, field_ptr_ty, field_index, zcu)) { - .begin => try f.writeCValue(w, container_ptr_val, .Other), + .begin => try f.writeCValue(w, container_ptr_val, .other), .field => |field| { try w.writeByte('&'); try f.writeCValueDerefMember(w, container_ptr_val, field); @@ -5951,7 +5213,7 @@ fn fieldPtr( try w.writeAll("(("); try f.renderType(w, u8_ptr_ty); try w.writeByte(')'); - try f.writeCValue(w, container_ptr_val, .Other); + try f.writeCValue(w, container_ptr_val, .other); try w.print(" + {f})", .{ try f.fmtIntLiteralDec(try pt.intValue(.usize, byte_offset)), }); @@ -5959,12 +5221,12 @@ fn fieldPtr( } try w.writeByte(';'); - try f.object.newline(); + try f.newline(); return local; } fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; @@ -5976,10 +5238,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { const struct_byval = try f.resolveInst(extra.struct_operand); try reap(f, inst, &.{extra.struct_operand}); const struct_ty = f.typeOf(extra.struct_operand); - const w = &f.object.code.writer; - - // Ensure complete type definition is visible before accessing fields. - _ = try f.ctypeFromType(struct_ty, .complete); + const w = &f.code.writer; assert(struct_ty.containerLayout(zcu) != .@"packed"); // `Air.Legalize.Feature.expand_packed_struct_field_val` handles this case const field_name: CValue = switch (ip.indexToKey(struct_ty.toIntern())) { @@ -5988,29 +5247,25 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { const union_type = ip.loadUnionType(struct_ty.toIntern()); const enum_tag_ty: Type = .fromInterned(union_type.enum_tag_type); const field_name_str = enum_tag_ty.enumFieldName(extra.field_index, zcu).toSlice(ip); - if (union_type.has_runtime_tag) { - break :name .{ .payload_identifier = field_name_str }; - } else { - break :name .{ .identifier = field_name_str }; - } + break :name .{ .payload_identifier = field_name_str }; }, .tuple_type => .{ .field = extra.field_index }, else => unreachable, }; const local = try f.allocLocal(inst, inst_ty); - const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); - try f.writeCValue(w, local, .Other); - try a.assign(f, w); + try f.writeCValue(w, local, .other); + try w.writeAll(" = "); try f.writeCValueMember(w, struct_byval, field_name); - try a.end(f, w); + try w.writeByte(';'); + try f.newline(); return local; } /// *(E!T) -> E /// Note that the result is never a pointer. fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; @@ -6020,37 +5275,23 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { try reap(f, inst, &.{ty_op.operand}); const operand_is_ptr = operand_ty.zigTypeTag(zcu) == .pointer; - const error_union_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty; - const error_ty = error_union_ty.errorUnionSet(zcu); - const payload_ty = error_union_ty.errorUnionPayload(zcu); const local = try f.allocLocal(inst, inst_ty); - if (!payload_ty.hasRuntimeBits(zcu) and operand == .local and operand.local == local.new_local) { - // The store will be 'x = x'; elide it. - return local; - } - - const w = &f.object.code.writer; - try f.writeCValue(w, local, .Other); + const w = &f.code.writer; + try f.writeCValue(w, local, .other); try w.writeAll(" = "); - if (!payload_ty.hasRuntimeBits(zcu)) - try f.writeCValue(w, operand, .Other) - else if (error_ty.errorSetIsEmpty(zcu)) - try w.print("{f}", .{ - try f.fmtIntLiteralDec(try pt.intValue(try pt.errorIntType(), 0)), - }) - else if (operand_is_ptr) + if (operand_is_ptr) try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" }) else try f.writeCValueMember(w, operand, .{ .identifier = "error" }); try w.writeByte(';'); - try f.object.newline(); + try f.newline(); return local; } fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; @@ -6060,154 +5301,124 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu const operand_ty = f.typeOf(ty_op.operand); const error_union_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty; - const w = &f.object.code.writer; + const w = &f.code.writer; if (!error_union_ty.errorUnionPayload(zcu).hasRuntimeBits(zcu)) { - if (!is_ptr) return .none; - + assert(is_ptr); // opv bug in sema const local = try f.allocLocal(inst, inst_ty); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try w.writeAll(" = ("); try f.renderType(w, inst_ty); try w.writeByte(')'); - try f.writeCValue(w, operand, .Other); + try f.writeCValue(w, operand, .other); try w.writeByte(';'); - try f.object.newline(); + try f.newline(); return local; } const local = try f.allocLocal(inst, inst_ty); - const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); - try f.writeCValue(w, local, .Other); - try a.assign(f, w); + try f.writeCValue(w, local, .other); + try w.writeAll(" = "); if (is_ptr) { try w.writeByte('&'); try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" }); } else try f.writeCValueMember(w, operand, .{ .identifier = "payload" }); - try a.end(f, w); + try w.writeByte(';'); + try f.newline(); return local; } fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { - const ctype_pool = &f.object.dg.ctype_pool; + const zcu = f.dg.pt.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const inst_ty = f.typeOfIndex(inst); - const inst_ctype = try f.ctypeFromType(inst_ty, .complete); - if (inst_ctype.isBool()) return .{ .constant = Value.true }; const operand = try f.resolveInst(ty_op.operand); - switch (inst_ctype.info(ctype_pool)) { - .basic, .pointer => return f.moveCValue(inst, inst_ty, operand), - .aligned, .array, .vector, .fwd_decl, .function => unreachable, - .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) { - .is_null, .payload => { - const operand_ctype = try f.ctypeFromType(f.typeOf(ty_op.operand), .complete); - const w = &f.object.code.writer; - const local = try f.allocLocal(inst, inst_ty); - { - const a = try Assignment.start(f, w, .bool); - try f.writeCValueMember(w, local, .{ .identifier = "is_null" }); - try a.assign(f, w); - try w.writeAll("false"); - try a.end(f, w); - } - { - const a = try Assignment.start(f, w, operand_ctype); - try f.writeCValueMember(w, local, .{ .identifier = "payload" }); - try a.assign(f, w); - try f.writeCValue(w, operand, .Other); - try a.end(f, w); - } - return local; - }, - .ptr, .len => return f.moveCValue(inst, inst_ty, operand), - else => unreachable, + + switch (CType.classifyOptional(inst_ty, zcu)) { + .npv_payload => unreachable, // opv optional + + .opv_payload => unreachable, // opv bug in Sema + + .error_set, + .ptr_like, + .slice_like, + => return f.moveCValue(inst, inst_ty, operand), + + .@"struct" => { + const w = &f.code.writer; + const local = try f.allocLocal(inst, inst_ty); + + try f.writeCValueMember(w, local, .{ .identifier = "is_null" }); + try w.writeAll(" = false;"); + try f.newline(); + + try f.writeCValueMember(w, local, .{ .identifier = "payload" }); + try w.writeAll(" = "); + try f.writeCValue(w, operand, .other); + try w.writeByte(';'); + try f.newline(); + + return local; }, } } fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const inst_ty = f.typeOfIndex(inst); const payload_ty = inst_ty.errorUnionPayload(zcu); - const repr_is_err = !payload_ty.hasRuntimeBits(zcu); - const err_ty = inst_ty.errorUnionSet(zcu); const err = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); - if (repr_is_err and err == .local and err.local == local.new_local) { - // The store will be 'x = x'; elide it. - return local; - } - - if (!repr_is_err) { - const a = try Assignment.start(f, w, try f.ctypeFromType(payload_ty, .complete)); + if (payload_ty.hasRuntimeBits(zcu)) { try f.writeCValueMember(w, local, .{ .identifier = "payload" }); - try a.assign(f, w); - try f.object.dg.renderUndefValue(w, payload_ty, .Other); - try a.end(f, w); - } - { - const a = try Assignment.start(f, w, try f.ctypeFromType(err_ty, .complete)); - if (repr_is_err) - try f.writeCValue(w, local, .Other) - else - try f.writeCValueMember(w, local, .{ .identifier = "error" }); - try a.assign(f, w); - try f.writeCValue(w, err, .Other); - try a.end(f, w); + try w.writeAll(" = "); + try f.dg.renderUndefValue(w, payload_ty, .other); + try w.writeByte(';'); + try f.newline(); } + + try f.writeCValueMember(w, local, .{ .identifier = "error" }); + try w.writeAll(" = "); + try f.writeCValue(w, err, .other); + try w.writeByte(';'); + try f.newline(); + return local; } fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; - const zcu = pt.zcu; - const w = &f.object.code.writer; + const pt = f.dg.pt; + const w = &f.code.writer; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const inst_ty = f.typeOfIndex(inst); const operand = try f.resolveInst(ty_op.operand); - const operand_ty = f.typeOf(ty_op.operand); - const error_union_ty = operand_ty.childType(zcu); - const payload_ty = error_union_ty.errorUnionPayload(zcu); const err_int_ty = try pt.errorIntType(); const no_err = try pt.intValue(err_int_ty, 0); try reap(f, inst, &.{ty_op.operand}); // First, set the non-error value. - if (!payload_ty.hasRuntimeBits(zcu)) { - const a = try Assignment.start(f, w, try f.ctypeFromType(operand_ty, .complete)); - try f.writeCValueDeref(w, operand); - try a.assign(f, w); - try w.print("{f}", .{try f.fmtIntLiteralDec(no_err)}); - try a.end(f, w); - return .none; - } - { - const a = try Assignment.start(f, w, try f.ctypeFromType(err_int_ty, .complete)); - try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" }); - try a.assign(f, w); - try w.print("{f}", .{try f.fmtIntLiteralDec(no_err)}); - try a.end(f, w); - } + try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" }); + try w.print(" = {f};", .{try f.fmtIntLiteralDec(no_err)}); + try f.newline(); // Then return the payload pointer (only if it is used) if (f.liveness.isUnused(inst)) return .none; const local = try f.allocLocal(inst, inst_ty); - const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); - try f.writeCValue(w, local, .Other); - try a.assign(f, w); - try w.writeByte('&'); + try f.writeCValue(w, local, .other); + try w.writeAll(" = &"); try f.writeCValueDerefMember(w, operand, .{ .identifier = "payload" }); - try a.end(f, w); + try w.writeByte(';'); + try f.newline(); return local; } @@ -6227,7 +5438,7 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue { } fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; @@ -6235,120 +5446,88 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { const payload_ty = inst_ty.errorUnionPayload(zcu); const payload = try f.resolveInst(ty_op.operand); assert(payload_ty.hasRuntimeBits(zcu)); - const err_ty = inst_ty.errorUnionSet(zcu); try reap(f, inst, &.{ty_op.operand}); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); - { - const a = try Assignment.start(f, w, try f.ctypeFromType(payload_ty, .complete)); - try f.writeCValueMember(w, local, .{ .identifier = "payload" }); - try a.assign(f, w); - try f.writeCValue(w, payload, .Other); - try a.end(f, w); - } - { - const a = try Assignment.start(f, w, try f.ctypeFromType(err_ty, .complete)); - try f.writeCValueMember(w, local, .{ .identifier = "error" }); - try a.assign(f, w); - try f.object.dg.renderValue(w, try pt.intValue(try pt.errorIntType(), 0), .Other); - try a.end(f, w); - } + + try f.writeCValueMember(w, local, .{ .identifier = "payload" }); + try w.writeAll(" = "); + try f.writeCValue(w, payload, .other); + try w.writeByte(';'); + try f.newline(); + + try f.writeCValueMember(w, local, .{ .identifier = "error" }); + try w.writeAll(" = "); + try f.dg.renderValue(w, try pt.intValue(try pt.errorIntType(), 0), .other); + try w.writeByte(';'); + try f.newline(); + return local; } fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !CValue { - const pt = f.object.dg.pt; - const zcu = pt.zcu; + const pt = f.dg.pt; const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; - const w = &f.object.code.writer; + const w = &f.code.writer; const operand = try f.resolveInst(un_op); try reap(f, inst, &.{un_op}); - const operand_ty = f.typeOf(un_op); const local = try f.allocLocal(inst, .bool); - const err_union_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty; - const payload_ty = err_union_ty.errorUnionPayload(zcu); - const error_ty = err_union_ty.errorUnionSet(zcu); - const a = try Assignment.start(f, w, .bool); - try f.writeCValue(w, local, .Other); - try a.assign(f, w); + try f.writeCValue(w, local, .other); + try w.writeAll(" = "); const err_int_ty = try pt.errorIntType(); - if (!error_ty.errorSetIsEmpty(zcu)) - if (payload_ty.hasRuntimeBits(zcu)) - if (is_ptr) - try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" }) - else - try f.writeCValueMember(w, operand, .{ .identifier = "error" }) - else - try f.writeCValue(w, operand, .Other) + if (is_ptr) + try f.writeCValueDerefMember(w, operand, .{ .identifier = "error" }) else - try f.object.dg.renderValue(w, try pt.intValue(err_int_ty, 0), .Other); - try w.writeByte(' '); - try w.writeAll(operator); - try w.writeByte(' '); - try f.object.dg.renderValue(w, try pt.intValue(err_int_ty, 0), .Other); - try a.end(f, w); + try f.writeCValueMember(w, operand, .{ .identifier = "error" }); + try w.print(" {s} ", .{operator}); + try f.dg.renderValue(w, try pt.intValue(err_int_ty, 0), .other); + try w.writeByte(';'); + try f.newline(); return local; } fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; - const ctype_pool = &f.object.dg.ctype_pool; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); const inst_ty = f.typeOfIndex(inst); - const ptr_ty = inst_ty.slicePtrFieldType(zcu); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); const operand_ty = f.typeOf(ty_op.operand); const array_ty = operand_ty.childType(zcu); - { - const a = try Assignment.start(f, w, try f.ctypeFromType(ptr_ty, .complete)); - try f.writeCValueMember(w, local, .{ .identifier = "ptr" }); - try a.assign(f, w); - if (operand == .undef) { - try f.writeCValue(w, .{ .undef = inst_ty.slicePtrFieldType(zcu) }, .Other); - } else { - const ptr_ctype = try f.ctypeFromType(ptr_ty, .complete); - const ptr_child_ctype = ptr_ctype.info(ctype_pool).pointer.elem_ctype; - const elem_ty = array_ty.childType(zcu); - const elem_ctype = try f.ctypeFromType(elem_ty, .complete); - if (!ptr_child_ctype.eql(elem_ctype)) { - try w.writeByte('('); - try f.renderCType(w, ptr_ctype); - try w.writeByte(')'); - } - const operand_ctype = try f.ctypeFromType(operand_ty, .complete); - const operand_child_ctype = operand_ctype.info(ctype_pool).pointer.elem_ctype; - if (operand_child_ctype.info(ctype_pool) == .array) { - try w.writeByte('&'); - try f.writeCValueDeref(w, operand); - try w.print("[{f}]", .{try f.fmtIntLiteralDec(.zero_usize)}); - } else try f.writeCValue(w, operand, .Other); - } - try a.end(f, w); - } - { - const a = try Assignment.start(f, w, .usize); - try f.writeCValueMember(w, local, .{ .identifier = "len" }); - try a.assign(f, w); - try w.print("{f}", .{ - try f.fmtIntLiteralDec(try pt.intValue(.usize, array_ty.arrayLen(zcu))), - }); - try a.end(f, w); - } + // We have a `*[n]T`, which was turned into to a pointer to `struct { T array[n]; }`. + // Ideally we would want to use 'operand->array' to convert to a `T *` (we get a `T []` + // which decays to a pointer), but if the element type is zero-bit or the array length is + // zero, there will not be an `array` member (the array type lowers to `void`). We cannot + // check the type layout here because it may not be resolved, so in this instance, we must + // use a pointer cast. + try f.writeCValueMember(w, local, .{ .identifier = "ptr" }); + try w.writeAll(" = ("); + try f.dg.renderType(w, inst_ty.slicePtrFieldType(zcu)); + try w.writeByte(')'); + try f.writeCValue(w, operand, .other); + try w.writeByte(';'); + try f.newline(); + + try f.writeCValueMember(w, local, .{ .identifier = "len" }); + try w.print(" = {f}", .{ + try f.fmtIntLiteralDec(try pt.intValue(.usize, array_ty.arrayLen(zcu))), + }); + try w.writeByte(';'); + try f.newline(); return local; } fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; @@ -6358,7 +5537,7 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { try reap(f, inst, &.{ty_op.operand}); const operand_ty = f.typeOf(ty_op.operand); const scalar_ty = operand_ty.scalarType(zcu); - const target = &f.object.dg.mod.resolved_target.result; + const target = &f.dg.mod.resolved_target.result; const operation = if (inst_scalar_ty.isRuntimeFloat() and scalar_ty.isRuntimeFloat()) if (inst_scalar_ty.floatBits(target) < scalar_ty.floatBits(target)) "trunc" else "extend" else if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) @@ -6368,16 +5547,15 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { else unreachable; - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); const v = try Vectorize.start(f, inst, w, operand_ty); - const a = try Assignment.start(f, w, try f.ctypeFromType(scalar_ty, .complete)); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try v.elem(f, w); - try a.assign(f, w); + try w.writeAll(" = "); if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) { try w.writeAll("zig_wrap_"); - try f.object.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); + try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); try w.writeByte('('); } try w.writeAll("zig_"); @@ -6385,14 +5563,15 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { try w.writeAll(compilerRtAbbrev(scalar_ty, zcu, target)); try w.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target)); try w.writeByte('('); - try f.writeCValue(w, operand, .FunctionArgument); + try f.writeCValue(w, operand, .other); try v.elem(f, w); try w.writeByte(')'); if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) { - try f.object.dg.renderBuiltinInfo(w, inst_scalar_ty, .bits); + try f.dg.renderBuiltinInfo(w, inst_scalar_ty, .bits); try w.writeByte(')'); } - try a.end(f, w); + try w.writeByte(';'); + try f.newline(); try v.end(f, inst, w); return local; @@ -6405,7 +5584,7 @@ fn airUnBuiltinCall( operation: []const u8, info: BuiltinInfo, ) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const operand = try f.resolveInst(operand_ref); @@ -6415,30 +5594,32 @@ fn airUnBuiltinCall( const operand_ty = f.typeOf(operand_ref); const scalar_ty = operand_ty.scalarType(zcu); - const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); - const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array; + const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); + const ref_arg = lowersToBigInt(scalar_ty, zcu); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); const v = try Vectorize.start(f, inst, w, operand_ty); if (!ref_ret) { - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try v.elem(f, w); try w.writeAll(" = "); } try w.print("zig_{s}_", .{operation}); - try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); + try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); try w.writeByte('('); if (ref_ret) { - try f.writeCValue(w, local, .FunctionArgument); + try w.writeByte('&'); + try f.writeCValue(w, local, .other); try v.elem(f, w); try w.writeAll(", "); } - try f.writeCValue(w, operand, .FunctionArgument); + if (ref_arg) try w.writeByte('&'); + try f.writeCValue(w, operand, .other); try v.elem(f, w); - try f.object.dg.renderBuiltinInfo(w, scalar_ty, info); + try f.dg.renderBuiltinInfo(w, scalar_ty, info); try w.writeAll(");"); - try f.object.newline(); + try f.newline(); try v.end(f, inst, w); return local; @@ -6450,13 +5631,12 @@ fn airBinBuiltinCall( operation: []const u8, info: BuiltinInfo, ) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const operand_ty = f.typeOf(bin_op.lhs); - const operand_ctype = try f.ctypeFromType(operand_ty, .complete); - const is_big = operand_ctype.info(&f.object.dg.ctype_pool) == .array; + const is_big = lowersToBigInt(operand_ty, zcu); const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); @@ -6466,32 +5646,35 @@ fn airBinBuiltinCall( const inst_scalar_ty = inst_ty.scalarType(zcu); const scalar_ty = operand_ty.scalarType(zcu); - const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); - const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array; + const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); + const ref_arg = lowersToBigInt(scalar_ty, zcu); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); const v = try Vectorize.start(f, inst, w, operand_ty); if (!ref_ret) { - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try v.elem(f, w); try w.writeAll(" = "); } try w.print("zig_{s}_", .{operation}); - try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); + try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); try w.writeByte('('); if (ref_ret) { - try f.writeCValue(w, local, .FunctionArgument); + try w.writeByte('&'); + try f.writeCValue(w, local, .other); try v.elem(f, w); try w.writeAll(", "); } - try f.writeCValue(w, lhs, .FunctionArgument); + if (ref_arg) try w.writeByte('&'); + try f.writeCValue(w, lhs, .other); try v.elem(f, w); try w.writeAll(", "); - try f.writeCValue(w, rhs, .FunctionArgument); + if (ref_arg) try w.writeByte('&'); + try f.writeCValue(w, rhs, .other); if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w); - try f.object.dg.renderBuiltinInfo(w, scalar_ty, info); + try f.dg.renderBuiltinInfo(w, scalar_ty, info); try w.writeAll(");\n"); try v.end(f, inst, w); @@ -6506,7 +5689,7 @@ fn airCmpBuiltinCall( operation: enum { cmp, operator }, info: BuiltinInfo, ) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const lhs = try f.resolveInst(data.lhs); const rhs = try f.resolveInst(data.rhs); @@ -6517,14 +5700,14 @@ fn airCmpBuiltinCall( const operand_ty = f.typeOf(data.lhs); const scalar_ty = operand_ty.scalarType(zcu); - const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); - const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array; + const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); + const ref_arg = lowersToBigInt(scalar_ty, zcu); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); const v = try Vectorize.start(f, inst, w, operand_ty); if (!ref_ret) { - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try v.elem(f, w); try w.writeAll(" = "); } @@ -6532,33 +5715,36 @@ fn airCmpBuiltinCall( else => @tagName(operation), .operator => compareOperatorAbbrev(operator), }}); - try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); + try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); try w.writeByte('('); if (ref_ret) { - try f.writeCValue(w, local, .FunctionArgument); + try w.writeByte('&'); + try f.writeCValue(w, local, .other); try v.elem(f, w); try w.writeAll(", "); } - try f.writeCValue(w, lhs, .FunctionArgument); + if (ref_arg) try w.writeByte('&'); + try f.writeCValue(w, lhs, .other); try v.elem(f, w); try w.writeAll(", "); - try f.writeCValue(w, rhs, .FunctionArgument); + if (ref_arg) try w.writeByte('&'); + try f.writeCValue(w, rhs, .other); try v.elem(f, w); - try f.object.dg.renderBuiltinInfo(w, scalar_ty, info); + try f.dg.renderBuiltinInfo(w, scalar_ty, info); try w.writeByte(')'); if (!ref_ret) try w.print("{s}{f}", .{ compareOperatorC(operator), try f.fmtIntLiteralDec(try pt.intValue(.i32, 0)), }); try w.writeByte(';'); - try f.object.newline(); + try f.newline(); try v.end(f, inst, w); return local; } fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = f.air.extraData(Air.Cmpxchg, ty_pl.payload).data; @@ -6568,9 +5754,8 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue const new_value = try f.resolveInst(extra.new_value); const ptr_ty = f.typeOf(extra.ptr); const ty = ptr_ty.childType(zcu); - const ctype = try f.ctypeFromType(ty, .complete); - const w = &f.object.code.writer; + const w = &f.code.writer; const new_value_mat = try Materialize.start(f, inst, ty, new_value); try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value }); @@ -6581,13 +5766,11 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue const local = try f.allocLocal(inst, inst_ty); if (inst_ty.isPtrLikeOptional(zcu)) { - { - const a = try Assignment.start(f, w, ctype); - try f.writeCValue(w, local, .Other); - try a.assign(f, w); - try f.writeCValue(w, expected_value, .Other); - try a.end(f, w); - } + try f.writeCValue(w, local, .other); + try w.writeAll(" = "); + try f.writeCValue(w, expected_value, .other); + try w.writeByte(';'); + try f.newline(); try w.writeAll("if ("); try w.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); @@ -6595,9 +5778,9 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue try w.writeByte(')'); if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile"); try w.writeAll(" *)"); - try f.writeCValue(w, ptr, .Other); + try f.writeCValue(w, ptr, .other); try w.writeAll(", "); - try f.writeCValue(w, local, .FunctionArgument); + try f.writeCValue(w, local, .other); try w.writeAll(", "); try new_value_mat.mat(f, w); try w.writeAll(", "); @@ -6605,56 +5788,49 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue try w.writeAll(", "); try writeMemoryOrder(w, extra.failureOrder()); try w.writeAll(", "); - try f.object.dg.renderTypeForBuiltinFnName(w, ty); + try f.dg.renderTypeForBuiltinFnName(w, ty); try w.writeAll(", "); try f.renderType(w, repr_ty); try w.writeByte(')'); try w.writeAll(") {"); - f.object.indent(); - try f.object.newline(); - { - const a = try Assignment.start(f, w, ctype); - try f.writeCValue(w, local, .Other); - try a.assign(f, w); - try w.writeAll("NULL"); - try a.end(f, w); - } - try f.object.outdent(); + f.indent(); + try f.newline(); + + try f.writeCValue(w, local, .other); + try w.writeAll(" = NULL;"); + try f.newline(); + + try f.outdent(); try w.writeByte('}'); - try f.object.newline(); + try f.newline(); } else { - { - const a = try Assignment.start(f, w, ctype); - try f.writeCValueMember(w, local, .{ .identifier = "payload" }); - try a.assign(f, w); - try f.writeCValue(w, expected_value, .Other); - try a.end(f, w); - } - { - const a = try Assignment.start(f, w, .bool); - try f.writeCValueMember(w, local, .{ .identifier = "is_null" }); - try a.assign(f, w); - try w.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); - try f.renderType(w, ty); - try w.writeByte(')'); - if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile"); - try w.writeAll(" *)"); - try f.writeCValue(w, ptr, .Other); - try w.writeAll(", "); - try f.writeCValueMember(w, local, .{ .identifier = "payload" }); - try w.writeAll(", "); - try new_value_mat.mat(f, w); - try w.writeAll(", "); - try writeMemoryOrder(w, extra.successOrder()); - try w.writeAll(", "); - try writeMemoryOrder(w, extra.failureOrder()); - try w.writeAll(", "); - try f.object.dg.renderTypeForBuiltinFnName(w, ty); - try w.writeAll(", "); - try f.renderType(w, repr_ty); - try w.writeByte(')'); - try a.end(f, w); - } + try f.writeCValueMember(w, local, .{ .identifier = "payload" }); + try w.writeAll(" = "); + try f.writeCValue(w, expected_value, .other); + try w.writeByte(';'); + try f.newline(); + + try f.writeCValueMember(w, local, .{ .identifier = "is_null" }); + try w.print(" = zig_cmpxchg_{s}((zig_atomic(", .{flavor}); + try f.renderType(w, ty); + try w.writeByte(')'); + if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile"); + try w.writeAll(" *)"); + try f.writeCValue(w, ptr, .other); + try w.writeAll(", "); + try f.writeCValueMember(w, local, .{ .identifier = "payload" }); + try w.writeAll(", "); + try new_value_mat.mat(f, w); + try w.writeAll(", "); + try writeMemoryOrder(w, extra.successOrder()); + try w.writeAll(", "); + try writeMemoryOrder(w, extra.failureOrder()); + try w.writeAll(", "); + try f.dg.renderTypeForBuiltinFnName(w, ty); + try w.writeAll(", "); + try f.renderType(w, repr_ty); + try w.writeAll(");"); + try f.newline(); } try new_value_mat.end(f, inst); @@ -6667,7 +5843,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue } fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const extra = f.air.extraData(Air.AtomicRmw, pl_op.payload).data; @@ -6677,7 +5853,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { const ptr = try f.resolveInst(pl_op.operand); const operand = try f.resolveInst(extra.operand); - const w = &f.object.code.writer; + const w = &f.code.writer; const operand_mat = try Materialize.start(f, inst, ty, operand); try reap(f, inst, &.{ pl_op.operand, extra.operand }); @@ -6690,7 +5866,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { try w.print("zig_atomicrmw_{s}", .{toAtomicRmwSuffix(extra.op())}); if (is_float) try w.writeAll("_float") else if (is_128) try w.writeAll("_int128"); try w.writeByte('('); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try w.writeAll(", ("); const use_atomic = switch (extra.op()) { else => true, @@ -6702,17 +5878,17 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { if (use_atomic) try w.writeByte(')'); if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile"); try w.writeAll(" *)"); - try f.writeCValue(w, ptr, .Other); + try f.writeCValue(w, ptr, .other); try w.writeAll(", "); try operand_mat.mat(f, w); try w.writeAll(", "); try writeMemoryOrder(w, extra.ordering()); try w.writeAll(", "); - try f.object.dg.renderTypeForBuiltinFnName(w, ty); + try f.dg.renderTypeForBuiltinFnName(w, ty); try w.writeAll(", "); try f.renderType(w, repr_ty); try w.writeAll(");"); - try f.object.newline(); + try f.newline(); try operand_mat.end(f, inst); if (f.liveness.isUnused(inst)) { @@ -6724,7 +5900,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { } fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const atomic_load = f.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load; const ptr = try f.resolveInst(atomic_load.ptr); @@ -6738,31 +5914,31 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { ty; const inst_ty = f.typeOfIndex(inst); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); try w.writeAll("zig_atomic_load("); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try w.writeAll(", (zig_atomic("); try f.renderType(w, ty); try w.writeByte(')'); if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile"); try w.writeAll(" *)"); - try f.writeCValue(w, ptr, .Other); + try f.writeCValue(w, ptr, .other); try w.writeAll(", "); try writeMemoryOrder(w, atomic_load.order); try w.writeAll(", "); - try f.object.dg.renderTypeForBuiltinFnName(w, ty); + try f.dg.renderTypeForBuiltinFnName(w, ty); try w.writeAll(", "); try f.renderType(w, repr_ty); try w.writeAll(");"); - try f.object.newline(); + try f.newline(); return local; } fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ptr_ty = f.typeOf(bin_op.lhs); @@ -6770,7 +5946,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa const ptr = try f.resolveInst(bin_op.lhs); const element = try f.resolveInst(bin_op.rhs); - const w = &f.object.code.writer; + const w = &f.code.writer; const element_mat = try Materialize.start(f, inst, ty, element); try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); @@ -6784,32 +5960,22 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa try w.writeByte(')'); if (ptr_ty.isVolatilePtr(zcu)) try w.writeAll(" volatile"); try w.writeAll(" *)"); - try f.writeCValue(w, ptr, .Other); + try f.writeCValue(w, ptr, .other); try w.writeAll(", "); try element_mat.mat(f, w); try w.print(", {s}, ", .{order}); - try f.object.dg.renderTypeForBuiltinFnName(w, ty); + try f.dg.renderTypeForBuiltinFnName(w, ty); try w.writeAll(", "); try f.renderType(w, repr_ty); try w.writeAll(");"); - try f.object.newline(); + try f.newline(); try element_mat.end(f, inst); return .none; } -fn writeSliceOrPtr(f: *Function, w: *Writer, ptr: CValue, ptr_ty: Type) !void { - const pt = f.object.dg.pt; - const zcu = pt.zcu; - if (ptr_ty.isSlice(zcu)) { - try f.writeCValueMember(w, ptr, .{ .identifier = "ptr" }); - } else { - try f.writeCValue(w, ptr, .FunctionArgument); - } -} - fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const dest_ty = f.typeOf(bin_op.lhs); @@ -6818,7 +5984,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { const elem_ty = f.typeOf(bin_op.rhs); const elem_abi_size = elem_ty.abiSize(zcu); const val_is_undef = if (try f.air.value(bin_op.rhs, pt)) |val| val.isUndef(zcu) else false; - const w = &f.object.code.writer; + const w = &f.code.writer; if (val_is_undef) { if (!safety) { @@ -6832,153 +5998,128 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { try f.writeCValueMember(w, dest_slice, .{ .identifier = "ptr" }); try w.writeAll(", 0xaa, "); try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" }); - if (elem_abi_size > 1) { - try w.print(" * {d}", .{elem_abi_size}); - } - try w.writeAll(");"); - try f.object.newline(); }, .one => { - const array_ty = dest_ty.childType(zcu); - const len = array_ty.arrayLen(zcu) * elem_abi_size; - - try f.writeCValue(w, dest_slice, .FunctionArgument); - try w.print(", 0xaa, {d});", .{len}); - try f.object.newline(); + try f.writeCValue(w, dest_slice, .other); + try w.print(", 0xaa, {d}", .{dest_ty.childType(zcu).arrayLen(zcu)}); }, .many, .c => unreachable, } + if (elem_abi_size > 0) try w.print(" * {d}", .{elem_abi_size}); + try w.writeAll(");"); + try f.newline(); try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); return .none; } - if (elem_abi_size > 1 or dest_ty.isVolatilePtr(zcu)) { - // For the assignment in this loop, the array pointer needs to get - // casted to a regular pointer, otherwise an error like this occurs: - // error: array type 'uint32_t[20]' (aka 'unsigned int[20]') is not assignable - const elem_ptr_ty = try pt.ptrType(.{ - .child = elem_ty.toIntern(), - .flags = .{ - .size = .c, - }, - }); - - const index = try f.allocLocal(inst, .usize); - - try w.writeAll("for ("); - try f.writeCValue(w, index, .Other); - try w.writeAll(" = "); - try f.object.dg.renderValue(w, .zero_usize, .Other); - try w.writeAll("; "); - try f.writeCValue(w, index, .Other); - try w.writeAll(" != "); + if (elem_abi_size == 1 and !dest_ty.isVolatilePtr(zcu)) { + const bitcasted = try bitcast(f, .u8, value, elem_ty); + try w.writeAll("memset("); switch (dest_ty.ptrSize(zcu)) { .slice => { + try f.writeCValueMember(w, dest_slice, .{ .identifier = "ptr" }); + try w.writeAll(", "); + try f.writeCValue(w, bitcasted, .other); + try w.writeAll(", "); try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" }); }, .one => { - const array_ty = dest_ty.childType(zcu); - try w.print("{d}", .{array_ty.arrayLen(zcu)}); + try f.writeCValue(w, dest_slice, .other); + try w.writeAll(", "); + try f.writeCValue(w, bitcasted, .other); + try w.print(", {d}", .{dest_ty.childType(zcu).arrayLen(zcu)}); }, .many, .c => unreachable, } - try w.writeAll("; ++"); - try f.writeCValue(w, index, .Other); - try w.writeAll(") "); - - const a = try Assignment.start(f, w, try f.ctypeFromType(elem_ty, .complete)); - try w.writeAll("(("); - try f.renderType(w, elem_ptr_ty); - try w.writeByte(')'); - try writeSliceOrPtr(f, w, dest_slice, dest_ty); - try w.writeAll(")["); - try f.writeCValue(w, index, .Other); - try w.writeByte(']'); - try a.assign(f, w); - try f.writeCValue(w, value, .Other); - try a.end(f, w); - + try w.writeAll(");"); + try f.newline(); + try f.freeCValue(inst, bitcasted); try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - try freeLocal(f, inst, index.new_local, null); - return .none; } - const bitcasted = try bitcast(f, .u8, value, elem_ty); + // Fallback path: use a `for` loop. - try w.writeAll("memset("); + const index = try f.allocLocal(inst, .usize); + + try w.writeAll("for ("); + try f.writeCValue(w, index, .other); + try w.writeAll(" = "); + try f.dg.renderValue(w, .zero_usize, .other); + try w.writeAll("; "); + try f.writeCValue(w, index, .other); + try w.writeAll(" != "); switch (dest_ty.ptrSize(zcu)) { - .slice => { - try f.writeCValueMember(w, dest_slice, .{ .identifier = "ptr" }); - try w.writeAll(", "); - try f.writeCValue(w, bitcasted, .FunctionArgument); - try w.writeAll(", "); - try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" }); - try w.writeAll(");"); - try f.object.newline(); - }, - .one => { - const array_ty = dest_ty.childType(zcu); - const len = array_ty.arrayLen(zcu) * elem_abi_size; + .slice => try f.writeCValueMember(w, dest_slice, .{ .identifier = "len" }), + .one => try w.print("{d}", .{dest_ty.childType(zcu).arrayLen(zcu)}), + .many, .c => unreachable, + } + try w.writeAll("; ++"); + try f.writeCValue(w, index, .other); + try w.writeAll(") "); - try f.writeCValue(w, dest_slice, .FunctionArgument); - try w.writeAll(", "); - try f.writeCValue(w, bitcasted, .FunctionArgument); - try w.print(", {d});", .{len}); - try f.object.newline(); - }, + switch (dest_ty.ptrSize(zcu)) { + .slice => try f.writeCValueMember(w, dest_slice, .{ .identifier = "ptr" }), + .one => try f.writeCValueDerefMember(w, dest_slice, .{ .identifier = "array" }), .many, .c => unreachable, } - try f.freeCValue(inst, bitcasted); + try w.writeByte('['); + try f.writeCValue(w, index, .other); + try w.writeAll("] = "); + try f.writeCValue(w, value, .other); + try w.writeByte(';'); + try f.newline(); + try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); + try freeLocal(f, inst, index.new_local, null); + return .none; } fn airMemcpy(f: *Function, inst: Air.Inst.Index, function_paren: []const u8) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const dest_ptr = try f.resolveInst(bin_op.lhs); const src_ptr = try f.resolveInst(bin_op.rhs); const dest_ty = f.typeOf(bin_op.lhs); const src_ty = f.typeOf(bin_op.rhs); - const w = &f.object.code.writer; + const w = &f.code.writer; if (dest_ty.ptrSize(zcu) != .one) { try w.writeAll("if ("); - try writeArrayLen(f, dest_ptr, dest_ty); + try f.writeCValueMember(w, dest_ptr, .{ .identifier = "len" }); try w.writeAll(" != 0) "); } try w.writeAll(function_paren); - try writeSliceOrPtr(f, w, dest_ptr, dest_ty); + switch (dest_ty.ptrSize(zcu)) { + .slice => try f.writeCValueMember(w, dest_ptr, .{ .identifier = "ptr" }), + .one => try f.writeCValueDerefMember(w, dest_ptr, .{ .identifier = "array" }), + .many, .c => unreachable, + } try w.writeAll(", "); - try writeSliceOrPtr(f, w, src_ptr, src_ty); + switch (src_ty.ptrSize(zcu)) { + .slice => try f.writeCValueMember(w, src_ptr, .{ .identifier = "ptr" }), + .one => try f.writeCValueDerefMember(w, src_ptr, .{ .identifier = "array" }), + .many, .c => try f.writeCValue(w, src_ptr, .other), + } try w.writeAll(", "); - try writeArrayLen(f, dest_ptr, dest_ty); + switch (dest_ty.ptrSize(zcu)) { + .slice => try f.writeCValueMember(w, dest_ptr, .{ .identifier = "len" }), + .one => try w.print("{d}", .{dest_ty.childType(zcu).arrayLen(zcu)}), + .many, .c => unreachable, + } try w.writeAll(" * sizeof("); try f.renderType(w, dest_ty.indexableElem(zcu)); try w.writeAll("));"); - try f.object.newline(); + try f.newline(); try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); return .none; } -fn writeArrayLen(f: *Function, dest_ptr: CValue, dest_ty: Type) !void { - const pt = f.object.dg.pt; - const zcu = pt.zcu; - const w = &f.object.code.writer; - switch (dest_ty.ptrSize(zcu)) { - .one => try w.print("{f}", .{ - try f.fmtIntLiteralDec(try pt.intValue(.usize, dest_ty.childType(zcu).arrayLen(zcu))), - }), - .many, .c => unreachable, - .slice => try f.writeCValueMember(w, dest_ptr, .{ .identifier = "len" }), - } -} - fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const union_ptr = try f.resolveInst(bin_op.lhs); @@ -6988,19 +6129,18 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { const union_ty = f.typeOf(bin_op.lhs).childType(zcu); const layout = union_ty.unionGetLayout(zcu); if (layout.tag_size == 0) return .none; - const tag_ty = union_ty.unionTagTypeRuntime(zcu).?; - const w = &f.object.code.writer; - const a = try Assignment.start(f, w, try f.ctypeFromType(tag_ty, .complete)); + const w = &f.code.writer; try f.writeCValueDerefMember(w, union_ptr, .{ .identifier = "tag" }); - try a.assign(f, w); - try f.writeCValue(w, new_tag, .Other); - try a.end(f, w); + try w.writeAll(" = "); + try f.writeCValue(w, new_tag, .other); + try w.writeByte(';'); + try f.newline(); return .none; } fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; @@ -7012,17 +6152,20 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { if (layout.tag_size == 0) return .none; const inst_ty = f.typeOfIndex(inst); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); - const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); - try f.writeCValue(w, local, .Other); - try a.assign(f, w); + try f.writeCValue(w, local, .other); + try w.writeAll(" = "); try f.writeCValueMember(w, operand, .{ .identifier = "tag" }); - try a.end(f, w); + try w.writeByte(';'); + try f.newline(); return local; } fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { + const zcu = f.dg.pt.zcu; + const ip = &zcu.intern_pool; + const gpa = zcu.comp.gpa; const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const inst_ty = f.typeOfIndex(inst); @@ -7030,15 +6173,17 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { const operand = try f.resolveInst(un_op); try reap(f, inst, &.{un_op}); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); - try f.writeCValue(w, local, .Other); - try w.print(" = {s}(", .{ - try f.getLazyFnName(.{ .tag_name = enum_ty.toIntern() }), + try f.writeCValue(w, local, .other); + try f.need_tag_name_funcs.put(gpa, enum_ty.toIntern(), {}); + try w.print(" = zig_tagName_{f}__{d}(", .{ + fmtIdentUnsolo(enum_ty.containerTypeName(ip).toSlice(ip)), + @intFromEnum(enum_ty.toIntern()), }); - try f.writeCValue(w, operand, .Other); + try f.writeCValue(w, operand, .other); try w.writeAll(");"); - try f.object.newline(); + try f.newline(); return local; } @@ -7046,40 +6191,37 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue { const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; - const w = &f.object.code.writer; + const w = &f.code.writer; const inst_ty = f.typeOfIndex(inst); const operand = try f.resolveInst(un_op); try reap(f, inst, &.{un_op}); const local = try f.allocLocal(inst, inst_ty); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try w.writeAll(" = zig_errorName["); - try f.writeCValue(w, operand, .Other); + try f.writeCValue(w, operand, .other); try w.writeAll(" - 1];"); - try f.object.newline(); + try f.newline(); return local; } fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; - const zcu = pt.zcu; const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); const inst_ty = f.typeOfIndex(inst); - const inst_scalar_ty = inst_ty.scalarType(zcu); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); const v = try Vectorize.start(f, inst, w, inst_ty); - const a = try Assignment.start(f, w, try f.ctypeFromType(inst_scalar_ty, .complete)); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try v.elem(f, w); - try a.assign(f, w); - try f.writeCValue(w, operand, .Other); - try a.end(f, w); + try w.writeAll(" = "); + try f.writeCValue(w, operand, .other); + try w.writeByte(';'); + try f.newline(); try v.end(f, inst, w); return local; @@ -7096,29 +6238,29 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue { const inst_ty = f.typeOfIndex(inst); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); const v = try Vectorize.start(f, inst, w, inst_ty); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try v.elem(f, w); try w.writeAll(" = "); - try f.writeCValue(w, pred, .Other); + try f.writeCValue(w, pred, .other); try v.elem(f, w); try w.writeAll(" ? "); - try f.writeCValue(w, lhs, .Other); + try f.writeCValue(w, lhs, .other); try v.elem(f, w); try w.writeAll(" : "); - try f.writeCValue(w, rhs, .Other); + try f.writeCValue(w, rhs, .other); try v.elem(f, w); try w.writeByte(';'); - try f.object.newline(); + try f.newline(); try v.end(f, inst, w); return local; } fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const unwrapped = f.air.unwrapShuffleOne(zcu, inst); @@ -7126,22 +6268,22 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue { const operand = try f.resolveInst(unwrapped.operand); const inst_ty = unwrapped.result_ty; - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); try reap(f, inst, &.{unwrapped.operand}); // local cannot alias operand for (mask, 0..) |mask_elem, out_idx| { - try f.writeCValue(w, local, .Other); + try f.writeCValueMember(w, local, .{ .identifier = "array" }); try w.writeByte('['); - try f.object.dg.renderValue(w, try pt.intValue(.usize, out_idx), .Other); + try f.dg.renderValue(w, try pt.intValue(.usize, out_idx), .other); try w.writeAll("] = "); switch (mask_elem.unwrap()) { .elem => |src_idx| { - try f.writeCValue(w, operand, .Other); + try f.writeCValueMember(w, operand, .{ .identifier = "array" }); try w.writeByte('['); - try f.object.dg.renderValue(w, try pt.intValue(.usize, src_idx), .Other); + try f.dg.renderValue(w, try pt.intValue(.usize, src_idx), .other); try w.writeByte(']'); }, - .value => |val| try f.object.dg.renderValue(w, .fromInterned(val), .Other), + .value => |val| try f.dg.renderValue(w, .fromInterned(val), .other), } try w.writeAll(";\n"); } @@ -7150,7 +6292,7 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue { } fn airShuffleTwo(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const unwrapped = f.air.unwrapShuffleTwo(zcu, inst); @@ -7160,38 +6302,38 @@ fn airShuffleTwo(f: *Function, inst: Air.Inst.Index) !CValue { const inst_ty = unwrapped.result_ty; const elem_ty = inst_ty.childType(zcu); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); try reap(f, inst, &.{ unwrapped.operand_a, unwrapped.operand_b }); // local cannot alias operands for (mask, 0..) |mask_elem, out_idx| { - try f.writeCValue(w, local, .Other); + try f.writeCValueMember(w, local, .{ .identifier = "array" }); try w.writeByte('['); - try f.object.dg.renderValue(w, try pt.intValue(.usize, out_idx), .Other); + try f.dg.renderValue(w, try pt.intValue(.usize, out_idx), .other); try w.writeAll("] = "); switch (mask_elem.unwrap()) { .a_elem => |src_idx| { - try f.writeCValue(w, operand_a, .Other); + try f.writeCValueMember(w, operand_a, .{ .identifier = "array" }); try w.writeByte('['); - try f.object.dg.renderValue(w, try pt.intValue(.usize, src_idx), .Other); + try f.dg.renderValue(w, try pt.intValue(.usize, src_idx), .other); try w.writeByte(']'); }, .b_elem => |src_idx| { - try f.writeCValue(w, operand_b, .Other); + try f.writeCValueMember(w, operand_b, .{ .identifier = "array" }); try w.writeByte('['); - try f.object.dg.renderValue(w, try pt.intValue(.usize, src_idx), .Other); + try f.dg.renderValue(w, try pt.intValue(.usize, src_idx), .other); try w.writeByte(']'); }, - .undef => try f.object.dg.renderUndefValue(w, elem_ty, .Other), + .undef => try f.dg.renderUndefValue(w, elem_ty, .other), } try w.writeByte(';'); - try f.object.newline(); + try f.newline(); } return local; } fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const reduce = f.air.instructions.items(.data)[@intFromEnum(inst)].reduce; @@ -7199,7 +6341,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { const operand = try f.resolveInst(reduce.operand); try reap(f, inst, &.{reduce.operand}); const operand_ty = f.typeOf(reduce.operand); - const w = &f.object.code.writer; + const w = &f.code.writer; const use_operator = scalar_ty.bitSize(zcu) <= 64; const op: union(enum) { @@ -7246,10 +6388,10 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { // } const accum = try f.allocLocal(inst, scalar_ty); - try f.writeCValue(w, accum, .Other); + try f.writeCValue(w, accum, .other); try w.writeAll(" = "); - try f.object.dg.renderValue(w, switch (reduce.operation) { + try f.dg.renderValue(w, switch (reduce.operation) { .Or, .Xor => switch (scalar_ty.zigTypeTag(zcu)) { .bool => Value.false, .int => try pt.intValue(scalar_ty, 0), @@ -7285,58 +6427,58 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { .float => try pt.floatValue(scalar_ty, std.math.nan(f128)), else => unreachable, }, - }, .Other); + }, .other); try w.writeByte(';'); - try f.object.newline(); + try f.newline(); const v = try Vectorize.start(f, inst, w, operand_ty); - try f.writeCValue(w, accum, .Other); + try f.writeCValue(w, accum, .other); switch (op) { .builtin => |func| { try w.print(" = zig_{s}_", .{func.operation}); - try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty); + try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); try w.writeByte('('); - try f.writeCValue(w, accum, .FunctionArgument); + try f.writeCValue(w, accum, .other); try w.writeAll(", "); - try f.writeCValue(w, operand, .Other); + try f.writeCValue(w, operand, .other); try v.elem(f, w); - try f.object.dg.renderBuiltinInfo(w, scalar_ty, func.info); + try f.dg.renderBuiltinInfo(w, scalar_ty, func.info); try w.writeByte(')'); }, .infix => |ass| { try w.writeAll(ass); - try f.writeCValue(w, operand, .Other); + try f.writeCValue(w, operand, .other); try v.elem(f, w); }, .ternary => |cmp| { try w.writeAll(" = "); - try f.writeCValue(w, accum, .Other); + try f.writeCValue(w, accum, .other); try w.writeAll(cmp); - try f.writeCValue(w, operand, .Other); + try f.writeCValue(w, operand, .other); try v.elem(f, w); try w.writeAll(" ? "); - try f.writeCValue(w, accum, .Other); + try f.writeCValue(w, accum, .other); try w.writeAll(" : "); - try f.writeCValue(w, operand, .Other); + try f.writeCValue(w, operand, .other); try v.elem(f, w); }, } try w.writeByte(';'); - try f.object.newline(); + try f.newline(); try v.end(f, inst, w); return accum; } fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const inst_ty = f.typeOfIndex(inst); const len: usize = @intCast(inst_ty.arrayLen(zcu)); const elements: []const Air.Inst.Ref = @ptrCast(f.air.extra.items[ty_pl.payload..][0..len]); - const gpa = f.object.dg.gpa; + const gpa = f.dg.gpa; const resolved_elements = try gpa.alloc(CValue, elements.len); defer gpa.free(resolved_elements); for (resolved_elements, elements) |*resolved_element, element| { @@ -7349,28 +6491,23 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { } } - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); switch (ip.indexToKey(inst_ty.toIntern())) { inline .array_type, .vector_type => |info, tag| { - const a: Assignment = .{ - .ctype = try f.ctypeFromType(.fromInterned(info.child), .complete), - }; for (resolved_elements, 0..) |element, i| { - try a.restart(f, w); - try f.writeCValue(w, local, .Other); - try w.print("[{d}]", .{i}); - try a.assign(f, w); - try f.writeCValue(w, element, .Other); - try a.end(f, w); + try f.writeCValueMember(w, local, .{ .identifier = "array" }); + try w.print("[{d}] = ", .{i}); + try f.writeCValue(w, element, .other); + try w.writeByte(';'); + try f.newline(); } if (tag == .array_type and info.sentinel != .none) { - try a.restart(f, w); - try f.writeCValue(w, local, .Other); - try w.print("[{d}]", .{info.len}); - try a.assign(f, w); - try f.object.dg.renderValue(w, Value.fromInterned(info.sentinel), .Other); - try a.end(f, w); + try f.writeCValueMember(w, local, .{ .identifier = "array" }); + try w.print("[{d}] = ", .{info.len}); + try f.dg.renderValue(w, Value.fromInterned(info.sentinel), .other); + try w.writeByte(';'); + try f.newline(); } }, .struct_type => { @@ -7382,11 +6519,11 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); if (!field_ty.hasRuntimeBits(zcu)) continue; - const a = try Assignment.start(f, w, try f.ctypeFromType(field_ty, .complete)); try f.writeCValueMember(w, local, .{ .identifier = loaded_struct.field_names.get(ip)[field_index].toSlice(ip) }); - try a.assign(f, w); - try f.writeCValue(w, resolved_elements[field_index], .Other); - try a.end(f, w); + try w.writeAll(" = "); + try f.writeCValue(w, resolved_elements[field_index], .other); + try w.writeByte(';'); + try f.newline(); } }, .@"packed" => unreachable, // `Air.Legalize.Feature.expand_packed_struct_init` handles this case @@ -7397,11 +6534,11 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { const field_ty: Type = .fromInterned(tuple_info.types.get(ip)[field_index]); if (!field_ty.hasRuntimeBits(zcu)) continue; - const a = try Assignment.start(f, w, try f.ctypeFromType(field_ty, .complete)); try f.writeCValueMember(w, local, .{ .field = field_index }); - try a.assign(f, w); - try f.writeCValue(w, resolved_elements[field_index], .Other); - try a.end(f, w); + try w.writeAll(" = "); + try f.writeCValue(w, resolved_elements[field_index], .other); + try w.writeByte(';'); + try f.newline(); }, else => unreachable, } @@ -7410,46 +6547,52 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { } fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data; + const field_index = extra.field_index; const union_ty = f.typeOfIndex(inst); const loaded_union = ip.loadUnionType(union_ty.toIntern()); - const field_name = ip.loadEnumType(loaded_union.enum_tag_type).field_names.get(ip)[extra.field_index]; - const payload_ty = f.typeOf(extra.init); + const loaded_enum = ip.loadEnumType(loaded_union.enum_tag_type); + const payload = try f.resolveInst(extra.init); try reap(f, inst, &.{extra.init}); - const w = &f.object.code.writer; + const w = &f.code.writer; if (loaded_union.layout == .@"packed") return f.moveCValue(inst, union_ty, payload); const local = try f.allocLocal(inst, union_ty); - const field: CValue = if (union_ty.unionTagTypeRuntime(zcu)) |tag_ty| field: { - assert(union_ty.unionGetLayout(zcu).tag_size != 0); - const field_index = tag_ty.enumFieldIndex(field_name, zcu).?; - const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index); - const a = try Assignment.start(f, w, try f.ctypeFromType(tag_ty, .complete)); + if (loaded_union.has_runtime_tag) { try f.writeCValueMember(w, local, .{ .identifier = "tag" }); - try a.assign(f, w); - try w.print("{f}", .{try f.fmtIntLiteralDec(tag_val.intFromEnum(zcu))}); - try a.end(f, w); - break :field .{ .payload_identifier = field_name.toSlice(ip) }; - } else .{ .identifier = field_name.toSlice(ip) }; + if (loaded_enum.field_values.len == 0) { + // auto-numbered + try w.print(" = {d};", .{field_index}); + } else { + const tag_int_val: Value = .fromInterned(loaded_enum.field_values.get(ip)[field_index]); + try w.print(" = {f};", .{try f.fmtIntLiteralDec(tag_int_val)}); + } + try f.newline(); + } - const a = try Assignment.start(f, w, try f.ctypeFromType(payload_ty, .complete)); - try f.writeCValueMember(w, local, field); - try a.assign(f, w); - try f.writeCValue(w, payload, .Other); - try a.end(f, w); + const field_name_slice = loaded_enum.field_names.get(ip)[field_index].toSlice(ip); + switch (loaded_union.layout) { + .auto => try f.writeCValueMember(w, local, .{ .payload_identifier = field_name_slice }), + .@"extern" => try f.writeCValueMember(w, local, .{ .identifier = field_name_slice }), + .@"packed" => unreachable, + } + try w.writeAll(" = "); + try f.writeCValue(w, payload, .other); + try w.writeByte(';'); + try f.newline(); return local; } fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const prefetch = f.air.instructions.items(.data)[@intFromEnum(inst)].prefetch; @@ -7457,16 +6600,16 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { const ptr = try f.resolveInst(prefetch.ptr); try reap(f, inst, &.{prefetch.ptr}); - const w = &f.object.code.writer; + const w = &f.code.writer; switch (prefetch.cache) { .data => { try w.writeAll("zig_prefetch("); if (ptr_ty.isSlice(zcu)) try f.writeCValueMember(w, ptr, .{ .identifier = "ptr" }) else - try f.writeCValue(w, ptr, .FunctionArgument); + try f.writeCValue(w, ptr, .other); try w.print(", {d}, {d});", .{ @intFromEnum(prefetch.rw), prefetch.locality }); - try f.object.newline(); + try f.newline(); }, // The available prefetch intrinsics do not accept a cache argument; only // address, rw, and locality. @@ -7479,14 +6622,14 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue { const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; - const w = &f.object.code.writer; + const w = &f.code.writer; const inst_ty = f.typeOfIndex(inst); const local = try f.allocLocal(inst, inst_ty); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try w.writeAll(" = "); try w.print("zig_wasm_memory_size({d});", .{pl_op.payload}); - try f.object.newline(); + try f.newline(); return local; } @@ -7494,23 +6637,23 @@ fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue { fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; - const w = &f.object.code.writer; + const w = &f.code.writer; const inst_ty = f.typeOfIndex(inst); const operand = try f.resolveInst(pl_op.operand); try reap(f, inst, &.{pl_op.operand}); const local = try f.allocLocal(inst, inst_ty); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try w.writeAll(" = "); try w.print("zig_wasm_memory_grow({d}, ", .{pl_op.payload}); - try f.writeCValue(w, operand, .FunctionArgument); + try f.writeCValue(w, operand, .other); try w.writeAll(");"); - try f.object.newline(); + try f.newline(); return local; } fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const bin_op = f.air.extraData(Air.Bin, pl_op.payload).data; @@ -7523,24 +6666,24 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { const inst_ty = f.typeOfIndex(inst); const inst_scalar_ty = inst_ty.scalarType(zcu); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); const v = try Vectorize.start(f, inst, w, inst_ty); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try v.elem(f, w); try w.writeAll(" = zig_fma_"); - try f.object.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); + try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); try w.writeByte('('); - try f.writeCValue(w, mulend1, .FunctionArgument); + try f.writeCValue(w, mulend1, .other); try v.elem(f, w); try w.writeAll(", "); - try f.writeCValue(w, mulend2, .FunctionArgument); + try f.writeCValue(w, mulend2, .other); try v.elem(f, w); try w.writeAll(", "); - try f.writeCValue(w, addend, .FunctionArgument); + try f.writeCValue(w, addend, .other); try v.elem(f, w); try w.writeAll(");"); - try f.object.newline(); + try f.newline(); try v.end(f, inst, w); return local; @@ -7548,34 +6691,33 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { fn airRuntimeNavPtr(f: *Function, inst: Air.Inst.Index) !CValue { const ty_nav = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, .fromInterned(ty_nav.ty)); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try w.writeAll(" = "); - try f.object.dg.renderNav(w, ty_nav.nav, .Other); + try f.dg.renderNav(w, ty_nav.nav, .other); try w.writeByte(';'); - try f.object.newline(); + try f.newline(); return local; } fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; const inst_ty = f.typeOfIndex(inst); - const function_ty = zcu.navValue(f.object.dg.pass.nav).typeOf(zcu); - const function_info = (try f.ctypeFromType(function_ty, .complete)).info(&f.object.dg.ctype_pool).function; - assert(function_info.varargs); - const w = &f.object.code.writer; + assert(Value.fromInterned(f.func_index).typeOf(zcu).fnIsVarArgs(zcu)); + + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); try w.writeAll("va_start(*(va_list *)&"); - try f.writeCValue(w, local, .Other); - if (function_info.param_ctypes.len > 0) { + try f.writeCValue(w, local, .other); + if (f.next_arg_index > 0) { try w.writeAll(", "); - try f.writeCValue(w, .{ .arg = function_info.param_ctypes.len - 1 }, .FunctionArgument); + try f.writeCValue(w, .{ .arg = f.next_arg_index - 1 }, .other); } try w.writeAll(");"); - try f.object.newline(); + try f.newline(); return local; } @@ -7586,15 +6728,15 @@ fn airCVaArg(f: *Function, inst: Air.Inst.Index) !CValue { const va_list = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try w.writeAll(" = va_arg(*(va_list *)"); - try f.writeCValue(w, va_list, .Other); + try f.writeCValue(w, va_list, .other); try w.writeAll(", "); try f.renderType(w, ty_op.ty.toType()); try w.writeAll(");"); - try f.object.newline(); + try f.newline(); return local; } @@ -7604,11 +6746,11 @@ fn airCVaEnd(f: *Function, inst: Air.Inst.Index) !CValue { const va_list = try f.resolveInst(un_op); try reap(f, inst, &.{un_op}); - const w = &f.object.code.writer; + const w = &f.code.writer; try w.writeAll("va_end(*(va_list *)"); - try f.writeCValue(w, va_list, .Other); + try f.writeCValue(w, va_list, .other); try w.writeAll(");"); - try f.object.newline(); + try f.newline(); return .none; } @@ -7619,14 +6761,14 @@ fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue { const va_list = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); - const w = &f.object.code.writer; + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); try w.writeAll("va_copy(*(va_list *)&"); - try f.writeCValue(w, local, .Other); + try f.writeCValue(w, local, .other); try w.writeAll(", *(va_list *)"); - try f.writeCValue(w, va_list, .Other); + try f.writeCValue(w, va_list, .other); try w.writeAll(");"); - try f.object.newline(); + try f.newline(); return local; } @@ -7943,103 +7085,193 @@ fn undefPattern(comptime IntType: type) IntType { const FormatIntLiteralContext = struct { dg: *DeclGen, - int_info: InternPool.Key.IntType, - kind: CType.Kind, - ctype: CType, + loc: ValueRenderLocation, val: Value, + cty: CType, base: u8, case: std.fmt.Case, }; fn formatIntLiteral(data: FormatIntLiteralContext, w: *Writer) Writer.Error!void { - const pt = data.dg.pt; - const zcu = pt.zcu; - const target = &data.dg.mod.resolved_target.result; - const ctype_pool = &data.dg.ctype_pool; - - const ExpectedContents = struct { - const base = 10; - const bits = 128; - const limbs_count = BigInt.calcTwosCompLimbCount(bits); - - undef_limbs: [limbs_count]BigIntLimb, - wrap_limbs: [limbs_count]BigIntLimb, - to_string_buf: [bits]u8, - to_string_limbs: [BigInt.calcToStringLimbsBufferLen(limbs_count, base)]BigIntLimb, - }; - var stack align(@alignOf(ExpectedContents)) = - std.heap.stackFallback(@sizeOf(ExpectedContents), data.dg.gpa); - const allocator = stack.get(); - - var undef_limbs: []BigIntLimb = &.{}; - defer allocator.free(undef_limbs); - - var int_buf: Value.BigIntSpace = undefined; - const int = if (data.val.isUndef(zcu)) blk: { - undef_limbs = allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits)) catch return error.WriteFailed; - @memset(undef_limbs, undefPattern(BigIntLimb)); - - var undef_int = BigInt.Mutable{ - .limbs = undef_limbs, - .len = undef_limbs.len, - .positive = true, - }; - undef_int.truncate(undef_int.toConst(), data.int_info.signedness, data.int_info.bits); - break :blk undef_int.toConst(); - } else data.val.toBigInt(&int_buf, zcu); - assert(int.fitsInTwosComp(data.int_info.signedness, data.int_info.bits)); - - const c_bits: usize = @intCast(data.ctype.byteSize(ctype_pool, data.dg.mod) * 8); - var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined; - const one = BigInt.Mutable.init(&one_limbs, 1).toConst(); - - var wrap = BigInt.Mutable{ - .limbs = allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits)) catch return error.WriteFailed, - .len = undefined, - .positive = undefined, - }; - defer allocator.free(wrap.limbs); - - const c_limb_info: struct { - ctype: CType, - count: usize, - endian: std.builtin.Endian, - homogeneous: bool, - } = switch (data.ctype.info(ctype_pool)) { - .basic => |basic_info| switch (basic_info) { - else => .{ - .ctype = .void, - .count = 1, - .endian = .little, - .homogeneous = true, + const dg = data.dg; + const zcu = dg.pt.zcu; + const target = &dg.mod.resolved_target.result; + + const val = data.val; + const ty = val.typeOf(zcu); + + assert(!val.isUndef(zcu)); + + var space: Value.BigIntSpace = undefined; + const val_bigint = val.toBigInt(&space, zcu); + + switch (CType.classifyInt(ty, zcu)) { + .void => unreachable, // opv + .small => |int_cty| return FormatInt128.format(.{ + .target = zcu.getTarget(), + .int_cty = int_cty, + .val = val_bigint, + .is_global = data.loc == .static_initializer, + .base = data.base, + .case = data.case, + }, w), + .big => |big| { + if (!data.loc.isInitializer()) { + // Use `CType.fmtTypeName` directly to avoid the possibility of `error.OutOfMemory`. + try w.print("({f})", .{data.cty.fmtTypeName(zcu)}); + } + + try w.writeAll("{{"); + + var limb_buf: [std.math.big.int.calcTwosCompLimbCount(65535)]std.math.big.Limb = undefined; + for (0..big.limbs_len) |limb_index| { + if (limb_index != 0) try w.writeAll(", "); + const limb_bit_offset: u64 = switch (target.cpu.arch.endian()) { + .little => limb_index * big.limb_size.bits(), + .big => (big.limbs_len - limb_index - 1) * big.limb_size.bits(), + }; + var limb_bigint: std.math.big.int.Mutable = .{ + .limbs = &limb_buf, + .len = undefined, + .positive = undefined, + }; + limb_bigint.shiftRight(val_bigint, limb_bit_offset); + limb_bigint.truncate(limb_bigint.toConst(), .unsigned, big.limb_size.bits()); + try FormatInt128.format(.{ + .target = zcu.getTarget(), + .int_cty = big.limb_size.unsigned(), + .val = limb_bigint.toConst(), + .is_global = data.loc == .static_initializer, + .base = data.base, + .case = data.case, + }, w); + } + + try w.writeAll("}}"); + }, + } +} +const FormatInt128 = struct { + target: *const std.Target, + int_cty: CType.Int, + val: std.math.big.int.Const, + is_global: bool, + base: u8, + case: std.fmt.Case, + pub fn format(data: FormatInt128, w: *Writer) Writer.Error!void { + const target = data.target; + + const val = data.val; + const is_global = data.is_global; + const base = data.base; + const case = data.case; + + switch (data.int_cty) { + .uint8_t, + .uint16_t, + .uint32_t, + .uint64_t, + .@"unsigned short", + .@"unsigned int", + .@"unsigned long", + .@"unsigned long long", + .uintptr_t, + => |t| try w.print("{f}", .{ + fmtUnsignedIntLiteralSmall(target, t, val.toInt(u64) catch unreachable, is_global, base, case), + }), + + .int8_t, + .int16_t, + .int32_t, + .int64_t, + .char, + .@"signed short", + .@"signed int", + .@"signed long", + .@"signed long long", + .intptr_t, + => |t| try w.print("{f}", .{ + fmtSignedIntLiteralSmall(target, t, val.toInt(i64) catch unreachable, is_global, base, case), + }), + + .zig_u128 => { + const raw = val.toInt(u128) catch unreachable; + const lo: u64 = @truncate(raw); + const hi: u64 = @intCast(raw >> 64); + const macro_name: []const u8 = if (is_global) "zig_init_u128" else "zig_make_u128"; + try w.print("{s}({f}, {f})", .{ + macro_name, + fmtUnsignedIntLiteralSmall(target, .uint64_t, hi, is_global, base, case), + fmtUnsignedIntLiteralSmall(target, .uint64_t, lo, is_global, base, case), + }); }, - .zig_u128, .zig_i128 => .{ - .ctype = .u64, - .count = 2, - .endian = .big, - .homogeneous = false, + + .zig_i128 => { + const raw = val.toInt(i128) catch unreachable; + const lo: u64 = @truncate(@as(u128, @bitCast(raw))); + const hi: i64 = @intCast(raw >> 64); + const macro_name: []const u8 = if (is_global) "zig_init_i128" else "zig_make_i128"; + try w.print("{s}({f}, {f})", .{ + macro_name, + fmtSignedIntLiteralSmall(target, .int64_t, hi, is_global, base, case), + fmtUnsignedIntLiteralSmall(target, .uint64_t, lo, is_global, base, case), + }); }, - }, - .array => |array_info| .{ - .ctype = array_info.elem_ctype, - .count = @intCast(array_info.len), - .endian = target.cpu.arch.endian(), - .homogeneous = true, - }, - else => unreachable, + } + } +}; +fn fmtUnsignedIntLiteralSmall( + target: *const std.Target, + int_cty: CType.Int, + val: u64, + is_global: bool, + base: u8, + case: std.fmt.Case, +) FormatUnsignedIntLiteralSmall { + return .{ + .target = target, + .int_cty = int_cty, + .val = val, + .is_global = is_global, + .base = base, + .case = case, + }; +} +fn fmtSignedIntLiteralSmall( + target: *const std.Target, + int_cty: CType.Int, + val: i64, + is_global: bool, + base: u8, + case: std.fmt.Case, +) FormatSignedIntLiteralSmall { + return .{ + .target = target, + .int_cty = int_cty, + .val = val, + .is_global = is_global, + .base = base, + .case = case, }; - if (c_limb_info.count == 1) { - if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or - data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits)) - return w.print("{s}_{s}", .{ - data.ctype.getStandardDefineAbbrev() orelse return w.print("zig_{s}Int_{c}{d}", .{ - if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits, - }), - if (int.positive) "MAX" else "MIN", - }); - - if (!int.positive) try w.writeByte('-'); - try data.ctype.renderLiteralPrefix(w, data.kind, ctype_pool); +} +const FormatSignedIntLiteralSmall = struct { + target: *const std.Target, + int_cty: CType.Int, + val: i64, + is_global: bool, + base: u8, + case: std.fmt.Case, + pub fn format(data: FormatSignedIntLiteralSmall, w: *Writer) Writer.Error!void { + const bits = data.int_cty.bits(data.target); + const max_int: i64 = @bitCast((@as(u64, 1) << @intCast(bits - 1)) - 1); + const min_int: i64 = @bitCast(@as(u64, 1) << @intCast(bits - 1)); + if (data.val == max_int) { + return w.print("{s}_MAX", .{minMaxMacroPrefix(data.int_cty)}); + } else if (data.val == min_int) { + return w.print("{s}_MIN", .{minMaxMacroPrefix(data.int_cty)}); + } + if (data.val < 0) try w.writeByte('-'); + try w.writeAll(intLiteralPrefix(data.int_cty, data.is_global)); switch (data.base) { 2 => try w.writeAll("0b"), 8 => try w.writeByte('0'), @@ -8047,68 +7279,131 @@ fn formatIntLiteral(data: FormatIntLiteralContext, w: *Writer) Writer.Error!void 16 => try w.writeAll("0x"), else => unreachable, } - const string = int.abs().toStringAlloc(allocator, data.base, data.case) catch - return error.WriteFailed; - defer allocator.free(string); - try w.writeAll(string); - } else { - try data.ctype.renderLiteralPrefix(w, data.kind, ctype_pool); - wrap.truncate(int, .unsigned, c_bits); - @memset(wrap.limbs[wrap.len..], 0); - wrap.len = wrap.limbs.len; - const limbs_per_c_limb = @divExact(wrap.len, c_limb_info.count); - - var c_limb_int_info: std.builtin.Type.Int = .{ - .signedness = undefined, - .bits = @intCast(@divExact(c_bits, c_limb_info.count)), - }; - var c_limb_ctype: CType = undefined; - - var limb_offset: usize = 0; - const most_significant_limb_i = wrap.len - limbs_per_c_limb; - while (limb_offset < wrap.len) : (limb_offset += limbs_per_c_limb) { - const limb_i = switch (c_limb_info.endian) { - .little => limb_offset, - .big => most_significant_limb_i - limb_offset, - }; - var c_limb_mut = BigInt.Mutable{ - .limbs = wrap.limbs[limb_i..][0..limbs_per_c_limb], - .len = undefined, - .positive = true, - }; - c_limb_mut.normalize(limbs_per_c_limb); - - if (limb_i == most_significant_limb_i and - !c_limb_info.homogeneous and data.int_info.signedness == .signed) - { - // most significant limb is actually signed - c_limb_int_info.signedness = .signed; - c_limb_ctype = c_limb_info.ctype.toSigned(); - - c_limb_mut.truncate( - c_limb_mut.toConst(), - .signed, - data.int_info.bits - limb_i * @bitSizeOf(BigIntLimb), - ); - } else { - c_limb_int_info.signedness = .unsigned; - c_limb_ctype = c_limb_info.ctype; - } - - if (limb_offset > 0) try w.writeAll(", "); - try formatIntLiteral(.{ - .dg = data.dg, - .int_info = c_limb_int_info, - .kind = data.kind, - .ctype = c_limb_ctype, - .val = pt.intValue_big(.comptime_int, c_limb_mut.toConst()) catch - return error.WriteFailed, - .base = data.base, - .case = data.case, - }, w); + // This `@abs` is safe thanks to the `min_int` case above. + try w.printInt(@abs(data.val), data.base, data.case, .{}); + try w.writeAll(intLiteralSuffix(data.int_cty)); + } +}; +const FormatUnsignedIntLiteralSmall = struct { + target: *const std.Target, + int_cty: CType.Int, + val: u64, + is_global: bool, + base: u8, + case: std.fmt.Case, + pub fn format(data: FormatUnsignedIntLiteralSmall, w: *Writer) Writer.Error!void { + const bits = data.int_cty.bits(data.target); + const max_int: u64 = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - bits); + if (data.val == max_int) { + return w.print("{s}_MAX", .{minMaxMacroPrefix(data.int_cty)}); } + try w.writeAll(intLiteralPrefix(data.int_cty, data.is_global)); + switch (data.base) { + 2 => try w.writeAll("0b"), + 8 => try w.writeByte('0'), + 10 => {}, + 16 => try w.writeAll("0x"), + else => unreachable, + } + try w.printInt(data.val, data.base, data.case, .{}); + try w.writeAll(intLiteralSuffix(data.int_cty)); } - try data.ctype.renderLiteralSuffix(w, ctype_pool); +}; +fn minMaxMacroPrefix(int_cty: CType.Int) []const u8 { + return switch (int_cty) { + // zig fmt: off + .char => "CHAR", + + .@"unsigned short" => "USHRT", + .@"unsigned int" => "UINT", + .@"unsigned long" => "ULONG", + .@"unsigned long long" => "ULLONG", + + .@"signed short" => "SHRT", + .@"signed int" => "INT", + .@"signed long" => "LONG", + .@"signed long long" => "LLONG", + + .uint8_t => "UINT8", + .uint16_t => "UINT16", + .uint32_t => "UINT32", + .uint64_t => "UINT64", + .zig_u128 => unreachable, + + .int8_t => "INT8", + .int16_t => "INT16", + .int32_t => "INT32", + .int64_t => "INT64", + .zig_i128 => unreachable, + + .uintptr_t => "UINTPTR", + .intptr_t => "INTPTR", + // zig fmt: on + }; +} +fn intLiteralPrefix(cty: CType.Int, is_global: bool) []const u8 { + return switch (cty) { + // zig fmt: off + .char => if (is_global) "" else "(char)", + + .@"unsigned short" => if (is_global) "" else "(unsigned short)", + .@"unsigned int" => "", + .@"unsigned long" => "", + .@"unsigned long long" => "", + + .@"signed short" => if (is_global) "" else "(signed short)", + .@"signed int" => "", + .@"signed long" => "", + .@"signed long long" => "", + + .uint8_t => "UINT8_C(", + .uint16_t => "UINT16_C(", + .uint32_t => "UINT32_C(", + .uint64_t => "UINT64_C(", + .zig_u128 => unreachable, + + .int8_t => "INT8_C(", + .int16_t => "INT16_C(", + .int32_t => "INT32_C(", + .int64_t => "INT64_C(", + .zig_i128 => unreachable, + + .uintptr_t => if (is_global) "" else "(uintptr_t)", + .intptr_t => if (is_global) "" else "(intptr_t)", + // zig fmt: on + }; +} +fn intLiteralSuffix(cty: CType.Int) []const u8 { + return switch (cty) { + // zig fmt: off + .char => "", + + .@"unsigned short" => "u", + .@"unsigned int" => "u", + .@"unsigned long" => "ul", + .@"unsigned long long" => "ull", + + .@"signed short" => "", + .@"signed int" => "", + .@"signed long" => "l", + .@"signed long long" => "ll", + + .uint8_t => ")", + .uint16_t => ")", + .uint32_t => ")", + .uint64_t => ")", + .zig_u128 => unreachable, + + .int8_t => ")", + .int16_t => ")", + .int32_t => ")", + .int64_t => ")", + .zig_i128 => unreachable, + + .uintptr_t => "ul", + .intptr_t => "", + // zig fmt: on + }; } const Materialize = struct { @@ -8123,7 +7418,7 @@ const Materialize = struct { } pub fn mat(self: Materialize, f: *Function, w: *Writer) !void { - try f.writeCValue(w, self.local, .Other); + try f.writeCValue(w, self.local, .other); } pub fn end(self: Materialize, f: *Function, inst: Air.Inst.Index) !void { @@ -8131,95 +7426,52 @@ const Materialize = struct { } }; -const Assignment = struct { - ctype: CType, - - pub fn start(f: *Function, w: *Writer, ctype: CType) !Assignment { - const self: Assignment = .{ .ctype = ctype }; - try self.restart(f, w); - return self; - } - - pub fn restart(self: Assignment, f: *Function, w: *Writer) !void { - switch (self.strategy(f)) { - .assign => {}, - .memcpy => try w.writeAll("memcpy("), - } - } - - pub fn assign(self: Assignment, f: *Function, w: *Writer) !void { - switch (self.strategy(f)) { - .assign => try w.writeAll(" = "), - .memcpy => try w.writeAll(", "), - } - } - - pub fn end(self: Assignment, f: *Function, w: *Writer) !void { - switch (self.strategy(f)) { - .assign => {}, - .memcpy => { - try w.writeAll(", sizeof("); - try f.renderCType(w, self.ctype); - try w.writeAll("))"); - }, - } - try w.writeByte(';'); - try f.object.newline(); - } - - fn strategy(self: Assignment, f: *Function) enum { assign, memcpy } { - return switch (self.ctype.info(&f.object.dg.ctype_pool)) { - else => .assign, - .array, .vector => .memcpy, - }; - } -}; - const Vectorize = struct { index: CValue = .none, pub fn start(f: *Function, inst: Air.Inst.Index, w: *Writer, ty: Type) !Vectorize { - const pt = f.object.dg.pt; + const pt = f.dg.pt; const zcu = pt.zcu; - return if (ty.zigTypeTag(zcu) == .vector) index: { - const local = try f.allocLocal(inst, .usize); - - try w.writeAll("for ("); - try f.writeCValue(w, local, .Other); - try w.print(" = {f}; ", .{try f.fmtIntLiteralDec(.zero_usize)}); - try f.writeCValue(w, local, .Other); - try w.print(" < {f}; ", .{try f.fmtIntLiteralDec(try pt.intValue(.usize, ty.vectorLen(zcu)))}); - try f.writeCValue(w, local, .Other); - try w.print(" += {f}) {{\n", .{try f.fmtIntLiteralDec(.one_usize)}); - f.object.indent(); - try f.object.newline(); - - break :index .{ .index = local }; - } else .{}; + switch (ty.zigTypeTag(zcu)) { + else => return .{ .index = .none }, + .vector => { + const local = try f.allocLocal(inst, .usize); + try w.writeAll("for ("); + try f.writeCValue(w, local, .other); + try w.print(" = {f}; ", .{try f.fmtIntLiteralDec(.zero_usize)}); + try f.writeCValue(w, local, .other); + try w.print(" < {f}; ", .{try f.fmtIntLiteralDec(try pt.intValue(.usize, ty.vectorLen(zcu)))}); + try f.writeCValue(w, local, .other); + try w.print(" += {f}) {{", .{try f.fmtIntLiteralDec(.one_usize)}); + f.indent(); + try f.newline(); + return .{ .index = local }; + }, + } } pub fn elem(self: Vectorize, f: *Function, w: *Writer) !void { if (self.index != .none) { - try w.writeByte('['); - try f.writeCValue(w, self.index, .Other); + try w.writeAll(".array["); + try f.writeCValue(w, self.index, .other); try w.writeByte(']'); } } pub fn end(self: Vectorize, f: *Function, inst: Air.Inst.Index, w: *Writer) !void { if (self.index != .none) { - try f.object.outdent(); + try f.outdent(); try w.writeByte('}'); - try f.object.newline(); + try f.newline(); try freeLocal(f, inst, self.index.new_local, null); } } }; -fn lowersToArray(ty: Type, zcu: *Zcu) bool { +fn lowersToBigInt(ty: Type, zcu: *const Zcu) bool { return switch (ty.zigTypeTag(zcu)) { - .array, .vector => return true, - else => return ty.isAbiInt(zcu) and toCIntBits(@as(u32, @intCast(ty.bitSize(zcu)))) == null, + .int, .@"enum", .@"struct", .@"union" => CType.classifyInt(ty, zcu) == .big, + else => false, }; } @@ -8245,8 +7497,8 @@ fn die(f: *Function, inst: Air.Inst.Index, ref: Air.Inst.Ref) !void { } fn freeLocal(f: *Function, inst: ?Air.Inst.Index, local_index: LocalIndex, ref_inst: ?Air.Inst.Index) !void { - const gpa = f.object.dg.gpa; - const local = &f.locals.items[local_index]; + const gpa = f.dg.gpa; + const local = f.locals.items[local_index]; if (inst) |i| { if (ref_inst) |operand| { log.debug("%{d}: freeing t{d} (operand %{d})", .{ @intFromEnum(i), local_index, operand }); @@ -8260,7 +7512,7 @@ fn freeLocal(f: *Function, inst: ?Air.Inst.Index, local_index: LocalIndex, ref_i log.debug("freeing t{d}", .{local_index}); } } - const gop = try f.free_locals_map.getOrPut(gpa, local.getType()); + const gop = try f.free_locals_map.getOrPut(gpa, local); if (!gop.found_existing) gop.value_ptr.* = .{}; if (std.debug.runtime_safety) { // If this trips, an unfreeable allocation was attempted to be freed. @@ -8317,3 +7569,28 @@ fn deinitFreeLocalsMap(gpa: Allocator, map: *LocalsMap) void { } map.deinit(gpa); } + +fn renderErrorName(w: *Writer, err_name: []const u8) Writer.Error!void { + try w.print("zig_error_{f}", .{fmtIdentUnsolo(err_name)}); +} + +fn renderNavName(w: *Writer, nav_index: InternPool.Nav.Index, ip: *const InternPool) !void { + const nav = ip.getNav(nav_index); + if (nav.getExtern(ip)) |@"extern"| { + try w.print("{f}", .{ + fmtIdentSolo(ip.getNav(@"extern".owner_nav).name.toSlice(ip)), + }); + } else { + // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case), + // expand to 3x the length of its input, but let's cut it off at a much shorter limit. + const fqn_slice = ip.getNav(nav_index).fqn.toSlice(ip); + try w.print("{f}__{d}", .{ + fmtIdentUnsolo(fqn_slice[0..@min(fqn_slice.len, 100)]), + @intFromEnum(nav_index), + }); + } +} + +fn renderUavName(w: *Writer, uav: Value) !void { + try w.print("__anon_{d}", .{@intFromEnum(uav.toIntern())}); +} diff --git a/src/codegen/c/Type.zig b/src/codegen/c/Type.zig deleted file mode 100644 index a7442a1d49dae8c626c54e448364e6169bf0eff6..0000000000000000000000000000000000000000 --- a/src/codegen/c/Type.zig +++ /dev/null @@ -1,3471 +0,0 @@ -index: CType.Index, - -pub const @"void": CType = .{ .index = .void }; -pub const @"bool": CType = .{ .index = .bool }; -pub const @"i8": CType = .{ .index = .int8_t }; -pub const @"u8": CType = .{ .index = .uint8_t }; -pub const @"i16": CType = .{ .index = .int16_t }; -pub const @"u16": CType = .{ .index = .uint16_t }; -pub const @"i32": CType = .{ .index = .int32_t }; -pub const @"u32": CType = .{ .index = .uint32_t }; -pub const @"i64": CType = .{ .index = .int64_t }; -pub const @"u64": CType = .{ .index = .uint64_t }; -pub const @"i128": CType = .{ .index = .zig_i128 }; -pub const @"u128": CType = .{ .index = .zig_u128 }; -pub const @"isize": CType = .{ .index = .intptr_t }; -pub const @"usize": CType = .{ .index = .uintptr_t }; -pub const @"f16": CType = .{ .index = .zig_f16 }; -pub const @"f32": CType = .{ .index = .zig_f32 }; -pub const @"f64": CType = .{ .index = .zig_f64 }; -pub const @"f80": CType = .{ .index = .zig_f80 }; -pub const @"f128": CType = .{ .index = .zig_f128 }; - -pub fn fromPoolIndex(pool_index: usize) CType { - return .{ .index = @enumFromInt(CType.Index.first_pool_index + pool_index) }; -} - -pub fn toPoolIndex(ctype: CType) ?u32 { - const pool_index, const is_null = - @subWithOverflow(@intFromEnum(ctype.index), CType.Index.first_pool_index); - return switch (is_null) { - 0 => pool_index, - 1 => null, - }; -} - -pub fn eql(lhs: CType, rhs: CType) bool { - return lhs.index == rhs.index; -} - -pub fn isBool(ctype: CType) bool { - return switch (ctype.index) { - ._Bool, .bool => true, - else => false, - }; -} - -pub fn isInteger(ctype: CType) bool { - return switch (ctype.index) { - .char, - .@"signed char", - .short, - .int, - .long, - .@"long long", - .@"unsigned char", - .@"unsigned short", - .@"unsigned int", - .@"unsigned long", - .@"unsigned long long", - .size_t, - .ptrdiff_t, - .uint8_t, - .int8_t, - .uint16_t, - .int16_t, - .uint32_t, - .int32_t, - .uint64_t, - .int64_t, - .uintptr_t, - .intptr_t, - .zig_u128, - .zig_i128, - => true, - else => false, - }; -} - -pub fn signedness(ctype: CType, mod: *Module) std.builtin.Signedness { - return switch (ctype.index) { - .char => mod.resolved_target.result.cCharSignedness(), - .@"signed char", - .short, - .int, - .long, - .@"long long", - .ptrdiff_t, - .int8_t, - .int16_t, - .int32_t, - .int64_t, - .intptr_t, - .zig_i128, - => .signed, - .@"unsigned char", - .@"unsigned short", - .@"unsigned int", - .@"unsigned long", - .@"unsigned long long", - .size_t, - .uint8_t, - .uint16_t, - .uint32_t, - .uint64_t, - .uintptr_t, - .zig_u128, - => .unsigned, - else => unreachable, - }; -} - -pub fn isFloat(ctype: CType) bool { - return switch (ctype.index) { - .float, - .double, - .@"long double", - .zig_f16, - .zig_f32, - .zig_f64, - .zig_f80, - .zig_f128, - .zig_c_longdouble, - => true, - else => false, - }; -} - -pub fn toSigned(ctype: CType) CType { - return switch (ctype.index) { - .char, .@"signed char", .@"unsigned char" => .{ .index = .@"signed char" }, - .short, .@"unsigned short" => .{ .index = .short }, - .int, .@"unsigned int" => .{ .index = .int }, - .long, .@"unsigned long" => .{ .index = .long }, - .@"long long", .@"unsigned long long" => .{ .index = .@"long long" }, - .size_t, .ptrdiff_t => .{ .index = .ptrdiff_t }, - .uint8_t, .int8_t => .{ .index = .int8_t }, - .uint16_t, .int16_t => .{ .index = .int16_t }, - .uint32_t, .int32_t => .{ .index = .int32_t }, - .uint64_t, .int64_t => .{ .index = .int64_t }, - .uintptr_t, .intptr_t => .{ .index = .intptr_t }, - .zig_u128, .zig_i128 => .{ .index = .zig_i128 }, - .float, - .double, - .@"long double", - .zig_f16, - .zig_f32, - .zig_f80, - .zig_f128, - .zig_c_longdouble, - => ctype, - else => unreachable, - }; -} - -pub fn toUnsigned(ctype: CType) CType { - return switch (ctype.index) { - .char, .@"signed char", .@"unsigned char" => .{ .index = .@"unsigned char" }, - .short, .@"unsigned short" => .{ .index = .@"unsigned short" }, - .int, .@"unsigned int" => .{ .index = .@"unsigned int" }, - .long, .@"unsigned long" => .{ .index = .@"unsigned long" }, - .@"long long", .@"unsigned long long" => .{ .index = .@"unsigned long long" }, - .size_t, .ptrdiff_t => .{ .index = .size_t }, - .uint8_t, .int8_t => .{ .index = .uint8_t }, - .uint16_t, .int16_t => .{ .index = .uint16_t }, - .uint32_t, .int32_t => .{ .index = .uint32_t }, - .uint64_t, .int64_t => .{ .index = .uint64_t }, - .uintptr_t, .intptr_t => .{ .index = .uintptr_t }, - .zig_u128, .zig_i128 => .{ .index = .zig_u128 }, - else => unreachable, - }; -} - -pub fn toSignedness(ctype: CType, s: std.builtin.Signedness) CType { - return switch (s) { - .unsigned => ctype.toUnsigned(), - .signed => ctype.toSigned(), - }; -} - -pub fn isAnyChar(ctype: CType) bool { - return switch (ctype.index) { - else => false, - .char, .@"signed char", .@"unsigned char", .uint8_t, .int8_t => true, - }; -} - -pub fn isString(ctype: CType, pool: *const Pool) bool { - return info: switch (ctype.info(pool)) { - .basic, .fwd_decl, .aggregate, .function => false, - .pointer => |pointer_info| pointer_info.elem_ctype.isAnyChar(), - .aligned => |aligned_info| continue :info aligned_info.ctype.info(pool), - .array, .vector => |sequence_info| sequence_info.elem_type.isAnyChar(), - }; -} - -pub fn isNonString(ctype: CType, pool: *const Pool) bool { - var allow_pointer = true; - return info: switch (ctype.info(pool)) { - .basic, .fwd_decl, .aggregate, .function => false, - .pointer => |pointer_info| allow_pointer and pointer_info.nonstring, - .aligned => |aligned_info| continue :info aligned_info.ctype.info(pool), - .array, .vector => |sequence_info| sequence_info.nonstring or { - allow_pointer = false; - continue :info sequence_info.elem_ctype.info(pool); - }, - }; -} - -pub fn getStandardDefineAbbrev(ctype: CType) ?[]const u8 { - return switch (ctype.index) { - .char => "CHAR", - .@"signed char" => "SCHAR", - .short => "SHRT", - .int => "INT", - .long => "LONG", - .@"long long" => "LLONG", - .@"unsigned char" => "UCHAR", - .@"unsigned short" => "USHRT", - .@"unsigned int" => "UINT", - .@"unsigned long" => "ULONG", - .@"unsigned long long" => "ULLONG", - .float => "FLT", - .double => "DBL", - .@"long double" => "LDBL", - .size_t => "SIZE", - .ptrdiff_t => "PTRDIFF", - .uint8_t => "UINT8", - .int8_t => "INT8", - .uint16_t => "UINT16", - .int16_t => "INT16", - .uint32_t => "UINT32", - .int32_t => "INT32", - .uint64_t => "UINT64", - .int64_t => "INT64", - .uintptr_t => "UINTPTR", - .intptr_t => "INTPTR", - else => null, - }; -} - -pub fn renderLiteralPrefix(ctype: CType, w: *Writer, kind: Kind, pool: *const Pool) Writer.Error!void { - switch (ctype.info(pool)) { - .basic => |basic_info| switch (basic_info) { - .void => unreachable, - ._Bool, - .char, - .@"signed char", - .short, - .@"unsigned short", - .bool, - .size_t, - .ptrdiff_t, - .uintptr_t, - .intptr_t, - => switch (kind) { - else => try w.print("({s})", .{@tagName(basic_info)}), - .global => {}, - }, - .int, - .long, - .@"long long", - .@"unsigned char", - .@"unsigned int", - .@"unsigned long", - .@"unsigned long long", - .float, - .double, - .@"long double", - => {}, - .uint8_t, - .int8_t, - .uint16_t, - .int16_t, - .uint32_t, - .int32_t, - .uint64_t, - .int64_t, - => try w.print("{s}_C(", .{ctype.getStandardDefineAbbrev().?}), - .zig_u128, - .zig_i128, - .zig_f16, - .zig_f32, - .zig_f64, - .zig_f80, - .zig_f128, - .zig_c_longdouble, - => try w.print("zig_{s}_{s}(", .{ - switch (kind) { - else => "make", - .global => "init", - }, - @tagName(basic_info)["zig_".len..], - }), - .va_list => unreachable, - _ => unreachable, - }, - .array, .vector => try w.writeByte('{'), - else => unreachable, - } -} - -pub fn renderLiteralSuffix(ctype: CType, w: *Writer, pool: *const Pool) Writer.Error!void { - switch (ctype.info(pool)) { - .basic => |basic_info| switch (basic_info) { - .void => unreachable, - ._Bool => {}, - .char, - .@"signed char", - .short, - .int, - => {}, - .long => try w.writeByte('l'), - .@"long long" => try w.writeAll("ll"), - .@"unsigned char", - .@"unsigned short", - .@"unsigned int", - => try w.writeByte('u'), - .@"unsigned long", - .size_t, - .uintptr_t, - => try w.writeAll("ul"), - .@"unsigned long long" => try w.writeAll("ull"), - .float => try w.writeByte('f'), - .double => {}, - .@"long double" => try w.writeByte('l'), - .bool, - .ptrdiff_t, - .intptr_t, - => {}, - .uint8_t, - .int8_t, - .uint16_t, - .int16_t, - .uint32_t, - .int32_t, - .uint64_t, - .int64_t, - .zig_u128, - .zig_i128, - .zig_f16, - .zig_f32, - .zig_f64, - .zig_f80, - .zig_f128, - .zig_c_longdouble, - => try w.writeByte(')'), - .va_list => unreachable, - _ => unreachable, - }, - .array, .vector => try w.writeByte('}'), - else => unreachable, - } -} - -pub fn floatActiveBits(ctype: CType, mod: *Module) u16 { - const target = &mod.resolved_target.result; - return switch (ctype.index) { - .float => target.cTypeBitSize(.float), - .double => target.cTypeBitSize(.double), - .@"long double", .zig_c_longdouble => target.cTypeBitSize(.longdouble), - .zig_f16 => 16, - .zig_f32 => 32, - .zig_f64 => 64, - .zig_f80 => 80, - .zig_f128 => 128, - else => unreachable, - }; -} - -pub fn byteSize(ctype: CType, pool: *const Pool, mod: *Module) u64 { - const target = &mod.resolved_target.result; - return switch (ctype.info(pool)) { - .basic => |basic_info| switch (basic_info) { - .void => 0, - .char, .@"signed char", ._Bool, .@"unsigned char", .bool, .uint8_t, .int8_t => 1, - .short => target.cTypeByteSize(.short), - .int => target.cTypeByteSize(.int), - .long => target.cTypeByteSize(.long), - .@"long long" => target.cTypeByteSize(.longlong), - .@"unsigned short" => target.cTypeByteSize(.ushort), - .@"unsigned int" => target.cTypeByteSize(.uint), - .@"unsigned long" => target.cTypeByteSize(.ulong), - .@"unsigned long long" => target.cTypeByteSize(.ulonglong), - .float => target.cTypeByteSize(.float), - .double => target.cTypeByteSize(.double), - .@"long double" => target.cTypeByteSize(.longdouble), - .size_t, - .ptrdiff_t, - .uintptr_t, - .intptr_t, - => @divExact(target.ptrBitWidth(), 8), - .uint16_t, .int16_t, .zig_f16 => 2, - .uint32_t, .int32_t, .zig_f32 => 4, - .uint64_t, .int64_t, .zig_f64 => 8, - .zig_u128, .zig_i128, .zig_f128 => 16, - .zig_f80 => if (target.cTypeBitSize(.longdouble) == 80) - target.cTypeByteSize(.longdouble) - else - 16, - .zig_c_longdouble => target.cTypeByteSize(.longdouble), - .va_list => unreachable, - _ => unreachable, - }, - .pointer => @divExact(target.ptrBitWidth(), 8), - .array, .vector => |sequence_info| sequence_info.elem_ctype.byteSize(pool, mod) * sequence_info.len, - else => unreachable, - }; -} - -pub fn info(ctype: CType, pool: *const Pool) Info { - const pool_index = ctype.toPoolIndex() orelse return .{ .basic = ctype.index }; - const item = pool.items.get(pool_index); - switch (item.tag) { - .basic => unreachable, - .pointer => return .{ .pointer = .{ - .elem_ctype = .{ .index = @enumFromInt(item.data) }, - } }, - .pointer_const => return .{ .pointer = .{ - .elem_ctype = .{ .index = @enumFromInt(item.data) }, - .@"const" = true, - } }, - .pointer_volatile => return .{ .pointer = .{ - .elem_ctype = .{ .index = @enumFromInt(item.data) }, - .@"volatile" = true, - } }, - .pointer_const_volatile => return .{ .pointer = .{ - .elem_ctype = .{ .index = @enumFromInt(item.data) }, - .@"const" = true, - .@"volatile" = true, - } }, - .aligned => { - const extra = pool.getExtra(Pool.Aligned, item.data); - return .{ .aligned = .{ - .ctype = .{ .index = extra.ctype }, - .alignas = extra.flags.alignas, - } }; - }, - .array_small => { - const extra = pool.getExtra(Pool.SequenceSmall, item.data); - return .{ .array = .{ - .elem_ctype = .{ .index = extra.elem_ctype }, - .len = extra.len, - } }; - }, - .array_large => { - const extra = pool.getExtra(Pool.SequenceLarge, item.data); - return .{ .array = .{ - .elem_ctype = .{ .index = extra.elem_ctype }, - .len = extra.len(), - } }; - }, - .vector => { - const extra = pool.getExtra(Pool.SequenceSmall, item.data); - return .{ .vector = .{ - .elem_ctype = .{ .index = extra.elem_ctype }, - .len = extra.len, - } }; - }, - .nonstring => { - var child_info = info(.{ .index = @enumFromInt(item.data) }, pool); - switch (child_info) { - else => unreachable, - .pointer => |*pointer_info| pointer_info.nonstring = true, - .array, .vector => |*sequence_info| sequence_info.nonstring = true, - } - return child_info; - }, - .fwd_decl_struct_anon => { - const extra_trail = pool.getExtraTrail(Pool.FwdDeclAnon, item.data); - return .{ .fwd_decl = .{ - .tag = .@"struct", - .name = .{ .anon = .{ - .extra_index = extra_trail.trail.extra_index, - .len = extra_trail.extra.fields_len, - } }, - } }; - }, - .fwd_decl_union_anon => { - const extra_trail = pool.getExtraTrail(Pool.FwdDeclAnon, item.data); - return .{ .fwd_decl = .{ - .tag = .@"union", - .name = .{ .anon = .{ - .extra_index = extra_trail.trail.extra_index, - .len = extra_trail.extra.fields_len, - } }, - } }; - }, - .fwd_decl_struct => return .{ .fwd_decl = .{ - .tag = .@"struct", - .name = .{ .index = @enumFromInt(item.data) }, - } }, - .fwd_decl_union => return .{ .fwd_decl = .{ - .tag = .@"union", - .name = .{ .index = @enumFromInt(item.data) }, - } }, - .aggregate_struct_anon => { - const extra_trail = pool.getExtraTrail(Pool.AggregateAnon, item.data); - return .{ .aggregate = .{ - .tag = .@"struct", - .name = .{ .anon = .{ - .index = extra_trail.extra.index, - .id = extra_trail.extra.id, - } }, - .fields = .{ - .extra_index = extra_trail.trail.extra_index, - .len = extra_trail.extra.fields_len, - }, - } }; - }, - .aggregate_union_anon => { - const extra_trail = pool.getExtraTrail(Pool.AggregateAnon, item.data); - return .{ .aggregate = .{ - .tag = .@"union", - .name = .{ .anon = .{ - .index = extra_trail.extra.index, - .id = extra_trail.extra.id, - } }, - .fields = .{ - .extra_index = extra_trail.trail.extra_index, - .len = extra_trail.extra.fields_len, - }, - } }; - }, - .aggregate_struct_packed_anon => { - const extra_trail = pool.getExtraTrail(Pool.AggregateAnon, item.data); - return .{ .aggregate = .{ - .tag = .@"struct", - .@"packed" = true, - .name = .{ .anon = .{ - .index = extra_trail.extra.index, - .id = extra_trail.extra.id, - } }, - .fields = .{ - .extra_index = extra_trail.trail.extra_index, - .len = extra_trail.extra.fields_len, - }, - } }; - }, - .aggregate_union_packed_anon => { - const extra_trail = pool.getExtraTrail(Pool.AggregateAnon, item.data); - return .{ .aggregate = .{ - .tag = .@"union", - .@"packed" = true, - .name = .{ .anon = .{ - .index = extra_trail.extra.index, - .id = extra_trail.extra.id, - } }, - .fields = .{ - .extra_index = extra_trail.trail.extra_index, - .len = extra_trail.extra.fields_len, - }, - } }; - }, - .aggregate_struct => { - const extra_trail = pool.getExtraTrail(Pool.Aggregate, item.data); - return .{ .aggregate = .{ - .tag = .@"struct", - .name = .{ .fwd_decl = .{ .index = extra_trail.extra.fwd_decl } }, - .fields = .{ - .extra_index = extra_trail.trail.extra_index, - .len = extra_trail.extra.fields_len, - }, - } }; - }, - .aggregate_union => { - const extra_trail = pool.getExtraTrail(Pool.Aggregate, item.data); - return .{ .aggregate = .{ - .tag = .@"union", - .name = .{ .fwd_decl = .{ .index = extra_trail.extra.fwd_decl } }, - .fields = .{ - .extra_index = extra_trail.trail.extra_index, - .len = extra_trail.extra.fields_len, - }, - } }; - }, - .aggregate_struct_packed => { - const extra_trail = pool.getExtraTrail(Pool.Aggregate, item.data); - return .{ .aggregate = .{ - .tag = .@"struct", - .@"packed" = true, - .name = .{ .fwd_decl = .{ .index = extra_trail.extra.fwd_decl } }, - .fields = .{ - .extra_index = extra_trail.trail.extra_index, - .len = extra_trail.extra.fields_len, - }, - } }; - }, - .aggregate_union_packed => { - const extra_trail = pool.getExtraTrail(Pool.Aggregate, item.data); - return .{ .aggregate = .{ - .tag = .@"union", - .@"packed" = true, - .name = .{ .fwd_decl = .{ .index = extra_trail.extra.fwd_decl } }, - .fields = .{ - .extra_index = extra_trail.trail.extra_index, - .len = extra_trail.extra.fields_len, - }, - } }; - }, - .function => { - const extra_trail = pool.getExtraTrail(Pool.Function, item.data); - return .{ .function = .{ - .return_ctype = .{ .index = extra_trail.extra.return_ctype }, - .param_ctypes = .{ - .extra_index = extra_trail.trail.extra_index, - .len = extra_trail.extra.param_ctypes_len, - }, - .varargs = false, - } }; - }, - .function_varargs => { - const extra_trail = pool.getExtraTrail(Pool.Function, item.data); - return .{ .function = .{ - .return_ctype = .{ .index = extra_trail.extra.return_ctype }, - .param_ctypes = .{ - .extra_index = extra_trail.trail.extra_index, - .len = extra_trail.extra.param_ctypes_len, - }, - .varargs = true, - } }; - }, - } -} - -pub fn hash(ctype: CType, pool: *const Pool) Pool.Map.Hash { - return if (ctype.toPoolIndex()) |pool_index| - pool.map.entries.items(.hash)[pool_index] - else - CType.Index.basic_hashes[@intFromEnum(ctype.index)]; -} - -fn toForward(ctype: CType, pool: *Pool, allocator: std.mem.Allocator) !CType { - return switch (ctype.info(pool)) { - .basic, .pointer, .fwd_decl => ctype, - .aligned => |aligned_info| pool.getAligned(allocator, .{ - .ctype = try aligned_info.ctype.toForward(pool, allocator), - .alignas = aligned_info.alignas, - }), - .array => |array_info| pool.getArray(allocator, .{ - .elem_ctype = try array_info.elem_ctype.toForward(pool, allocator), - .len = array_info.len, - .nonstring = array_info.nonstring, - }), - .vector => |vector_info| pool.getVector(allocator, .{ - .elem_ctype = try vector_info.elem_ctype.toForward(pool, allocator), - .len = vector_info.len, - .nonstring = vector_info.nonstring, - }), - .aggregate => |aggregate_info| switch (aggregate_info.name) { - .anon => ctype, - .fwd_decl => |fwd_decl| fwd_decl, - }, - .function => unreachable, - }; -} - -const Index = enum(u32) { - void, - - // C basic types - char, - - @"signed char", - short, - int, - long, - @"long long", - - _Bool, - @"unsigned char", - @"unsigned short", - @"unsigned int", - @"unsigned long", - @"unsigned long long", - - float, - double, - @"long double", - - // C header types - // - stdbool.h - bool, - // - stddef.h - size_t, - ptrdiff_t, - // - stdint.h - uint8_t, - int8_t, - uint16_t, - int16_t, - uint32_t, - int32_t, - uint64_t, - int64_t, - uintptr_t, - intptr_t, - // - stdarg.h - va_list, - - // zig.h types - zig_u128, - zig_i128, - zig_f16, - zig_f32, - zig_f64, - zig_f80, - zig_f128, - zig_c_longdouble, - - _, - - const first_pool_index: u32 = @typeInfo(CType.Index).@"enum".fields.len; - const basic_hashes = init: { - @setEvalBranchQuota(1_600); - var basic_hashes_init: [first_pool_index]Pool.Map.Hash = undefined; - for (&basic_hashes_init, 0..) |*basic_hash, index| { - const ctype_index: CType.Index = @enumFromInt(index); - var hasher = Pool.Hasher.init; - hasher.update(@intFromEnum(ctype_index)); - basic_hash.* = hasher.final(.basic); - } - break :init basic_hashes_init; - }; -}; - -const Slice = struct { - extra_index: Pool.ExtraIndex, - len: u32, - - pub fn at(slice: CType.Slice, index: usize, pool: *const Pool) CType { - var extra: Pool.ExtraTrail = .{ .extra_index = slice.extra_index }; - return .{ .index = extra.next(slice.len, CType.Index, pool)[index] }; - } -}; - -pub const Kind = enum { - forward, - forward_parameter, - complete, - global, - parameter, - - pub fn isForward(kind: Kind) bool { - return switch (kind) { - .forward, .forward_parameter => true, - .complete, .global, .parameter => false, - }; - } - - pub fn isParameter(kind: Kind) bool { - return switch (kind) { - .forward_parameter, .parameter => true, - .forward, .complete, .global => false, - }; - } - - pub fn asParameter(kind: Kind) Kind { - return switch (kind) { - .forward, .forward_parameter => .forward_parameter, - .complete, .parameter, .global => .parameter, - }; - } - - pub fn noParameter(kind: Kind) Kind { - return switch (kind) { - .forward, .forward_parameter => .forward, - .complete, .parameter => .complete, - .global => .global, - }; - } - - pub fn asComplete(kind: Kind) Kind { - return switch (kind) { - .forward, .complete => .complete, - .forward_parameter, .parameter => .parameter, - .global => .global, - }; - } -}; - -pub const Info = union(enum) { - basic: CType.Index, - pointer: Pointer, - aligned: Aligned, - array: Sequence, - vector: Sequence, - fwd_decl: FwdDecl, - aggregate: Aggregate, - function: Function, - - const Tag = @typeInfo(Info).@"union".tag_type.?; - - pub const Pointer = struct { - elem_ctype: CType, - @"const": bool = false, - @"volatile": bool = false, - nonstring: bool = false, - - fn tag(pointer_info: Pointer) Pool.Tag { - return @enumFromInt(@intFromEnum(Pool.Tag.pointer) + - @as(u2, @bitCast(packed struct(u2) { - @"const": bool, - @"volatile": bool, - }{ - .@"const" = pointer_info.@"const", - .@"volatile" = pointer_info.@"volatile", - }))); - } - }; - - pub const Aligned = struct { - ctype: CType, - alignas: AlignAs, - }; - - pub const Sequence = struct { - elem_ctype: CType, - len: u64, - nonstring: bool = false, - }; - - pub const AggregateTag = enum { @"enum", @"struct", @"union" }; - - pub const Field = struct { - name: Pool.String, - ctype: CType, - alignas: AlignAs, - - pub const Slice = struct { - extra_index: Pool.ExtraIndex, - len: u32, - - pub fn at(slice: Field.Slice, index: usize, pool: *const Pool) Field { - assert(index < slice.len); - const extra = pool.getExtra(Pool.Field, @intCast(slice.extra_index + - index * @typeInfo(Pool.Field).@"struct".fields.len)); - return .{ - .name = .{ .index = extra.name }, - .ctype = .{ .index = extra.ctype }, - .alignas = extra.flags.alignas, - }; - } - - fn eqlAdapted( - lhs_slice: Field.Slice, - lhs_pool: *const Pool, - rhs_slice: Field.Slice, - rhs_pool: *const Pool, - pool_adapter: anytype, - ) bool { - if (lhs_slice.len != rhs_slice.len) return false; - for (0..lhs_slice.len) |index| { - if (!lhs_slice.at(index, lhs_pool).eqlAdapted( - lhs_pool, - rhs_slice.at(index, rhs_pool), - rhs_pool, - pool_adapter, - )) return false; - } - return true; - } - }; - - fn eqlAdapted( - lhs_field: Field, - lhs_pool: *const Pool, - rhs_field: Field, - rhs_pool: *const Pool, - pool_adapter: anytype, - ) bool { - if (!std.meta.eql(lhs_field.alignas, rhs_field.alignas)) return false; - if (!pool_adapter.eql(lhs_field.ctype, rhs_field.ctype)) return false; - return if (lhs_field.name.toPoolSlice(lhs_pool)) |lhs_name| - if (rhs_field.name.toPoolSlice(rhs_pool)) |rhs_name| - std.mem.eql(u8, lhs_name, rhs_name) - else - false - else - lhs_field.name.index == rhs_field.name.index; - } - }; - - pub const FwdDecl = struct { - tag: AggregateTag, - name: union(enum) { - anon: Field.Slice, - index: InternPool.Index, - }, - }; - - pub const Aggregate = struct { - tag: AggregateTag, - @"packed": bool = false, - name: union(enum) { - anon: struct { - index: InternPool.Index, - id: u32, - }, - fwd_decl: CType, - }, - fields: Field.Slice, - }; - - pub const Function = struct { - return_ctype: CType, - param_ctypes: CType.Slice, - varargs: bool = false, - }; - - pub fn eqlAdapted( - lhs_info: Info, - lhs_pool: *const Pool, - rhs_ctype: CType, - rhs_pool: *const Pool, - pool_adapter: anytype, - ) bool { - const rhs_info = rhs_ctype.info(rhs_pool); - if (@as(Info.Tag, lhs_info) != @as(Info.Tag, rhs_info)) return false; - return switch (lhs_info) { - .basic => |lhs_basic_info| lhs_basic_info == rhs_info.basic, - .pointer => |lhs_pointer_info| lhs_pointer_info.@"const" == rhs_info.pointer.@"const" and - lhs_pointer_info.@"volatile" == rhs_info.pointer.@"volatile" and - lhs_pointer_info.nonstring == rhs_info.pointer.nonstring and - pool_adapter.eql(lhs_pointer_info.elem_ctype, rhs_info.pointer.elem_ctype), - .aligned => |lhs_aligned_info| std.meta.eql(lhs_aligned_info.alignas, rhs_info.aligned.alignas) and - pool_adapter.eql(lhs_aligned_info.ctype, rhs_info.aligned.ctype), - .array => |lhs_array_info| lhs_array_info.len == rhs_info.array.len and - lhs_array_info.nonstring == rhs_info.array.nonstring and - pool_adapter.eql(lhs_array_info.elem_ctype, rhs_info.array.elem_ctype), - .vector => |lhs_vector_info| lhs_vector_info.len == rhs_info.vector.len and - lhs_vector_info.nonstring == rhs_info.vector.nonstring and - pool_adapter.eql(lhs_vector_info.elem_ctype, rhs_info.vector.elem_ctype), - .fwd_decl => |lhs_fwd_decl_info| lhs_fwd_decl_info.tag == rhs_info.fwd_decl.tag and - switch (lhs_fwd_decl_info.name) { - .anon => |lhs_anon| rhs_info.fwd_decl.name == .anon and lhs_anon.eqlAdapted( - lhs_pool, - rhs_info.fwd_decl.name.anon, - rhs_pool, - pool_adapter, - ), - .index => |lhs_index| rhs_info.fwd_decl.name == .index and - lhs_index == rhs_info.fwd_decl.name.index, - }, - .aggregate => |lhs_aggregate_info| lhs_aggregate_info.tag == rhs_info.aggregate.tag and - lhs_aggregate_info.@"packed" == rhs_info.aggregate.@"packed" and - switch (lhs_aggregate_info.name) { - .anon => |lhs_anon| rhs_info.aggregate.name == .anon and - lhs_anon.index == rhs_info.aggregate.name.anon.index and - lhs_anon.id == rhs_info.aggregate.name.anon.id, - .fwd_decl => |lhs_fwd_decl| rhs_info.aggregate.name == .fwd_decl and - pool_adapter.eql(lhs_fwd_decl, rhs_info.aggregate.name.fwd_decl), - } and lhs_aggregate_info.fields.eqlAdapted( - lhs_pool, - rhs_info.aggregate.fields, - rhs_pool, - pool_adapter, - ), - .function => |lhs_function_info| lhs_function_info.param_ctypes.len == - rhs_info.function.param_ctypes.len and - pool_adapter.eql(lhs_function_info.return_ctype, rhs_info.function.return_ctype) and - for (0..lhs_function_info.param_ctypes.len) |param_index| { - if (!pool_adapter.eql( - lhs_function_info.param_ctypes.at(param_index, lhs_pool), - rhs_info.function.param_ctypes.at(param_index, rhs_pool), - )) break false; - } else true, - }; - } -}; - -pub const Pool = struct { - map: Map, - items: std.MultiArrayList(Item), - extra: std.ArrayList(u32), - - string_map: Map, - string_indices: std.ArrayList(u32), - string_bytes: std.ArrayList(u8), - - const Map = std.AutoArrayHashMapUnmanaged(void, void); - - pub const String = struct { - index: String.Index, - - const FormatData = struct { string: String, pool: *const Pool }; - fn format(data: FormatData, writer: *Writer) Writer.Error!void { - if (data.string.toSlice(data.pool)) |slice| - try writer.writeAll(slice) - else - try writer.print("f{d}", .{@intFromEnum(data.string.index)}); - } - pub fn fmt(str: String, pool: *const Pool) std.fmt.Alt(FormatData, format) { - return .{ .data = .{ .string = str, .pool = pool } }; - } - - fn fromUnnamed(index: u31) String { - return .{ .index = @enumFromInt(index) }; - } - - fn isNamed(str: String) bool { - return @intFromEnum(str.index) >= String.Index.first_named_index; - } - - pub fn toSlice(str: String, pool: *const Pool) ?[]const u8 { - return str.toPoolSlice(pool) orelse if (str.isNamed()) @tagName(str.index) else null; - } - - fn toPoolSlice(str: String, pool: *const Pool) ?[]const u8 { - if (str.toPoolIndex()) |pool_index| { - const start = pool.string_indices.items[pool_index + 0]; - const end = pool.string_indices.items[pool_index + 1]; - return pool.string_bytes.items[start..end]; - } else return null; - } - - fn fromPoolIndex(pool_index: usize) String { - return .{ .index = @enumFromInt(String.Index.first_pool_index + pool_index) }; - } - - fn toPoolIndex(str: String) ?u32 { - const pool_index, const is_null = - @subWithOverflow(@intFromEnum(str.index), String.Index.first_pool_index); - return switch (is_null) { - 0 => pool_index, - 1 => null, - }; - } - - const Index = enum(u32) { - array = first_named_index, - @"error", - is_null, - len, - payload, - ptr, - tag, - _, - - const first_named_index: u32 = 1 << 31; - const first_pool_index: u32 = first_named_index + @typeInfo(String.Index).@"enum".fields.len; - }; - - const Adapter = struct { - pool: *const Pool, - pub fn hash(_: @This(), slice: []const u8) Map.Hash { - return @truncate(Hasher.Impl.hash(1, slice)); - } - pub fn eql(string_adapter: @This(), lhs_slice: []const u8, _: void, rhs_index: usize) bool { - const rhs_string = String.fromPoolIndex(rhs_index); - const rhs_slice = rhs_string.toPoolSlice(string_adapter.pool).?; - return std.mem.eql(u8, lhs_slice, rhs_slice); - } - }; - }; - - pub const empty: Pool = .{ - .map = .empty, - .items = .empty, - .extra = .empty, - - .string_map = .empty, - .string_indices = .empty, - .string_bytes = .empty, - }; - - pub fn init(pool: *Pool, allocator: std.mem.Allocator) !void { - if (pool.string_indices.items.len == 0) - try pool.string_indices.append(allocator, 0); - } - - pub fn deinit(pool: *Pool, allocator: std.mem.Allocator) void { - pool.map.deinit(allocator); - pool.items.deinit(allocator); - pool.extra.deinit(allocator); - - pool.string_map.deinit(allocator); - pool.string_indices.deinit(allocator); - pool.string_bytes.deinit(allocator); - - pool.* = undefined; - } - - pub fn move(pool: *Pool) Pool { - defer pool.* = empty; - return pool.*; - } - - pub fn clearRetainingCapacity(pool: *Pool) void { - pool.map.clearRetainingCapacity(); - pool.items.shrinkRetainingCapacity(0); - pool.extra.clearRetainingCapacity(); - - pool.string_map.clearRetainingCapacity(); - pool.string_indices.shrinkRetainingCapacity(1); - pool.string_bytes.clearRetainingCapacity(); - } - - pub fn freeUnusedCapacity(pool: *Pool, allocator: std.mem.Allocator) void { - pool.map.shrinkAndFree(allocator, pool.map.count()); - pool.items.shrinkAndFree(allocator, pool.items.len); - pool.extra.shrinkAndFree(allocator, pool.extra.items.len); - - pool.string_map.shrinkAndFree(allocator, pool.string_map.count()); - pool.string_indices.shrinkAndFree(allocator, pool.string_indices.items.len); - pool.string_bytes.shrinkAndFree(allocator, pool.string_bytes.items.len); - } - - pub fn getPointer(pool: *Pool, allocator: std.mem.Allocator, pointer_info: Info.Pointer) !CType { - var hasher = Hasher.init; - hasher.update(pointer_info.elem_ctype.hash(pool)); - return pool.getNonString(allocator, try pool.tagData( - allocator, - hasher, - pointer_info.tag(), - @intFromEnum(pointer_info.elem_ctype.index), - ), pointer_info.nonstring); - } - - pub fn getAligned(pool: *Pool, allocator: std.mem.Allocator, aligned_info: Info.Aligned) !CType { - return pool.tagExtra(allocator, .aligned, Aligned, .{ - .ctype = aligned_info.ctype.index, - .flags = .{ .alignas = aligned_info.alignas }, - }); - } - - pub fn getArray(pool: *Pool, allocator: std.mem.Allocator, array_info: Info.Sequence) !CType { - return pool.getNonString(allocator, if (std.math.cast(u32, array_info.len)) |small_len| - try pool.tagExtra(allocator, .array_small, SequenceSmall, .{ - .elem_ctype = array_info.elem_ctype.index, - .len = small_len, - }) - else - try pool.tagExtra(allocator, .array_large, SequenceLarge, .{ - .elem_ctype = array_info.elem_ctype.index, - .len_lo = @truncate(array_info.len >> 0), - .len_hi = @truncate(array_info.len >> 32), - }), array_info.nonstring); - } - - pub fn getVector(pool: *Pool, allocator: std.mem.Allocator, vector_info: Info.Sequence) !CType { - return pool.getNonString(allocator, try pool.tagExtra(allocator, .vector, SequenceSmall, .{ - .elem_ctype = vector_info.elem_ctype.index, - .len = @intCast(vector_info.len), - }), vector_info.nonstring); - } - - pub fn getNonString( - pool: *Pool, - allocator: std.mem.Allocator, - child_ctype: CType, - nonstring: bool, - ) !CType { - if (!nonstring) return child_ctype; - var hasher = Hasher.init; - hasher.update(child_ctype.hash(pool)); - return pool.tagData(allocator, hasher, .nonstring, @intFromEnum(child_ctype.index)); - } - - pub fn getFwdDecl( - pool: *Pool, - allocator: std.mem.Allocator, - fwd_decl_info: struct { - tag: Info.AggregateTag, - name: union(enum) { - anon: []const Info.Field, - index: InternPool.Index, - }, - }, - ) !CType { - var hasher = Hasher.init; - switch (fwd_decl_info.name) { - .anon => |fields| { - const ExpectedContents = [32]CType; - var stack align(@max( - @alignOf(std.heap.StackFallbackAllocator(0)), - @alignOf(ExpectedContents), - )) = std.heap.stackFallback(@sizeOf(ExpectedContents), allocator); - const stack_allocator = stack.get(); - const field_ctypes = try stack_allocator.alloc(CType, fields.len); - defer stack_allocator.free(field_ctypes); - for (field_ctypes, fields) |*field_ctype, field| - field_ctype.* = try field.ctype.toForward(pool, allocator); - const extra: FwdDeclAnon = .{ .fields_len = @intCast(fields.len) }; - const extra_index = try pool.addExtra( - allocator, - FwdDeclAnon, - extra, - fields.len * @typeInfo(Field).@"struct".fields.len, - ); - for (fields, field_ctypes) |field, field_ctype| pool.addHashedExtraAssumeCapacity( - &hasher, - Field, - .{ - .name = field.name.index, - .ctype = field_ctype.index, - .flags = .{ .alignas = field.alignas }, - }, - ); - hasher.updateExtra(FwdDeclAnon, extra, pool); - return pool.tagTrailingExtra(allocator, hasher, switch (fwd_decl_info.tag) { - .@"struct" => .fwd_decl_struct_anon, - .@"union" => .fwd_decl_union_anon, - .@"enum" => unreachable, - }, extra_index); - }, - .index => |index| { - hasher.update(index); - return pool.tagData(allocator, hasher, switch (fwd_decl_info.tag) { - .@"struct" => .fwd_decl_struct, - .@"union" => .fwd_decl_union, - .@"enum" => unreachable, - }, @intFromEnum(index)); - }, - } - } - - pub fn getAggregate( - pool: *Pool, - allocator: std.mem.Allocator, - aggregate_info: struct { - tag: Info.AggregateTag, - @"packed": bool = false, - name: union(enum) { - anon: struct { - index: InternPool.Index, - id: u32, - }, - fwd_decl: CType, - }, - fields: []const Info.Field, - }, - ) !CType { - var hasher = Hasher.init; - switch (aggregate_info.name) { - .anon => |anon| { - const extra: AggregateAnon = .{ - .index = anon.index, - .id = anon.id, - .fields_len = @intCast(aggregate_info.fields.len), - }; - const extra_index = try pool.addExtra( - allocator, - AggregateAnon, - extra, - aggregate_info.fields.len * @typeInfo(Field).@"struct".fields.len, - ); - for (aggregate_info.fields) |field| pool.addHashedExtraAssumeCapacity(&hasher, Field, .{ - .name = field.name.index, - .ctype = field.ctype.index, - .flags = .{ .alignas = field.alignas }, - }); - hasher.updateExtra(AggregateAnon, extra, pool); - return pool.tagTrailingExtra(allocator, hasher, switch (aggregate_info.tag) { - .@"struct" => switch (aggregate_info.@"packed") { - false => .aggregate_struct_anon, - true => .aggregate_struct_packed_anon, - }, - .@"union" => switch (aggregate_info.@"packed") { - false => .aggregate_union_anon, - true => .aggregate_union_packed_anon, - }, - .@"enum" => unreachable, - }, extra_index); - }, - .fwd_decl => |fwd_decl| { - const extra: Aggregate = .{ - .fwd_decl = fwd_decl.index, - .fields_len = @intCast(aggregate_info.fields.len), - }; - const extra_index = try pool.addExtra( - allocator, - Aggregate, - extra, - aggregate_info.fields.len * @typeInfo(Field).@"struct".fields.len, - ); - for (aggregate_info.fields) |field| pool.addHashedExtraAssumeCapacity(&hasher, Field, .{ - .name = field.name.index, - .ctype = field.ctype.index, - .flags = .{ .alignas = field.alignas }, - }); - hasher.updateExtra(Aggregate, extra, pool); - return pool.tagTrailingExtra(allocator, hasher, switch (aggregate_info.tag) { - .@"struct" => switch (aggregate_info.@"packed") { - false => .aggregate_struct, - true => .aggregate_struct_packed, - }, - .@"union" => switch (aggregate_info.@"packed") { - false => .aggregate_union, - true => .aggregate_union_packed, - }, - .@"enum" => unreachable, - }, extra_index); - }, - } - } - - pub fn getFunction( - pool: *Pool, - allocator: std.mem.Allocator, - function_info: struct { - return_ctype: CType, - param_ctypes: []const CType, - varargs: bool = false, - }, - ) !CType { - var hasher = Hasher.init; - const extra: Function = .{ - .return_ctype = function_info.return_ctype.index, - .param_ctypes_len = @intCast(function_info.param_ctypes.len), - }; - const extra_index = try pool.addExtra(allocator, Function, extra, function_info.param_ctypes.len); - for (function_info.param_ctypes) |param_ctype| { - hasher.update(param_ctype.hash(pool)); - pool.extra.appendAssumeCapacity(@intFromEnum(param_ctype.index)); - } - hasher.updateExtra(Function, extra, pool); - return pool.tagTrailingExtra(allocator, hasher, switch (function_info.varargs) { - false => .function, - true => .function_varargs, - }, extra_index); - } - - pub fn fromFields( - pool: *Pool, - allocator: std.mem.Allocator, - tag: Info.AggregateTag, - fields: []Info.Field, - kind: Kind, - ) !CType { - sortFields(fields); - const fwd_decl = try pool.getFwdDecl(allocator, .{ - .tag = tag, - .name = .{ .anon = fields }, - }); - return if (kind.isForward()) fwd_decl else pool.getAggregate(allocator, .{ - .tag = tag, - .name = .{ .fwd_decl = fwd_decl }, - .fields = fields, - }); - } - - pub fn fromIntInfo( - pool: *Pool, - allocator: std.mem.Allocator, - int_info: std.builtin.Type.Int, - mod: *Module, - kind: Kind, - ) !CType { - switch (int_info.bits) { - 0 => return .void, - 1...8 => switch (int_info.signedness) { - .signed => return .i8, - .unsigned => return .u8, - }, - 9...16 => switch (int_info.signedness) { - .signed => return .i16, - .unsigned => return .u16, - }, - 17...32 => switch (int_info.signedness) { - .signed => return .i32, - .unsigned => return .u32, - }, - 33...64 => switch (int_info.signedness) { - .signed => return .i64, - .unsigned => return .u64, - }, - 65...128 => switch (int_info.signedness) { - .signed => return .i128, - .unsigned => return .u128, - }, - else => { - const target = &mod.resolved_target.result; - const abi_align_bytes = std.zig.target.intAlignment(target, int_info.bits); - const limb_ctype = try pool.fromIntInfo(allocator, .{ - .signedness = .unsigned, - .bits = @intCast(abi_align_bytes * 8), - }, mod, kind.noParameter()); - const array_ctype = try pool.getArray(allocator, .{ - .len = @divExact(std.zig.target.intByteSize(target, int_info.bits), abi_align_bytes), - .elem_ctype = limb_ctype, - .nonstring = limb_ctype.isAnyChar(), - }); - if (!kind.isParameter()) return array_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = array_ctype, - .alignas = AlignAs.fromAbiAlignment(.fromByteUnits(abi_align_bytes)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - } - } - - pub fn fromType( - pool: *Pool, - allocator: std.mem.Allocator, - scratch: *std.ArrayList(u32), - ty: Type, - pt: Zcu.PerThread, - mod: *Module, - kind: Kind, - ) !CType { - const ip = &pt.zcu.intern_pool; - const zcu = pt.zcu; - switch (ty.toIntern()) { - .u0_type, - .i0_type, - .anyopaque_type, - .void_type, - .empty_tuple_type, - .type_type, - .comptime_int_type, - .comptime_float_type, - .null_type, - .undefined_type, - .enum_literal_type, - .optional_type_type, - .manyptr_const_type_type, - .slice_const_type_type, - => return .void, - .u1_type, .u8_type => return .u8, - .i8_type => return .i8, - .u16_type => return .u16, - .i16_type => return .i16, - .u29_type, .u32_type => return .u32, - .i32_type => return .i32, - .u64_type => return .u64, - .i64_type => return .i64, - .u80_type, .u128_type => return .u128, - .i128_type => return .i128, - .u256_type => return pool.fromIntInfo(allocator, .{ - .signedness = .unsigned, - .bits = 256, - }, mod, kind), - .usize_type => return .usize, - .isize_type => return .isize, - .c_char_type => return .{ .index = .char }, - .c_short_type => return .{ .index = .short }, - .c_ushort_type => return .{ .index = .@"unsigned short" }, - .c_int_type => return .{ .index = .int }, - .c_uint_type => return .{ .index = .@"unsigned int" }, - .c_long_type => return .{ .index = .long }, - .c_ulong_type => return .{ .index = .@"unsigned long" }, - .c_longlong_type => return .{ .index = .@"long long" }, - .c_ulonglong_type => return .{ .index = .@"unsigned long long" }, - .c_longdouble_type => return .{ .index = .@"long double" }, - .f16_type => return .f16, - .f32_type => return .f32, - .f64_type => return .f64, - .f80_type => return .f80, - .f128_type => return .f128, - .bool_type, .optional_noreturn_type => return .bool, - .noreturn_type, - .anyframe_type, - .generic_poison_type, - => unreachable, - .anyerror_type, - .anyerror_void_error_union_type, - .adhoc_inferred_error_set_type, - => return pool.fromIntInfo(allocator, .{ - .signedness = .unsigned, - .bits = pt.zcu.errorSetBits(), - }, mod, kind), - - .ptr_usize_type => return pool.getPointer(allocator, .{ - .elem_ctype = .usize, - }), - .ptr_const_comptime_int_type => return pool.getPointer(allocator, .{ - .elem_ctype = .void, - .@"const" = true, - }), - .manyptr_u8_type => return pool.getPointer(allocator, .{ - .elem_ctype = .u8, - .nonstring = true, - }), - .manyptr_const_u8_type => return pool.getPointer(allocator, .{ - .elem_ctype = .u8, - .@"const" = true, - .nonstring = true, - }), - .manyptr_const_u8_sentinel_0_type => return pool.getPointer(allocator, .{ - .elem_ctype = .u8, - .@"const" = true, - }), - .slice_const_u8_type => { - const target = &mod.resolved_target.result; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .ptr }, - .ctype = try pool.getPointer(allocator, .{ - .elem_ctype = .u8, - .@"const" = true, - .nonstring = true, - }), - .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)), - }, - .{ - .name = .{ .index = .len }, - .ctype = .usize, - .alignas = AlignAs.fromAbiAlignment( - .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())), - ), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .slice_const_u8_sentinel_0_type => { - const target = &mod.resolved_target.result; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .ptr }, - .ctype = try pool.getPointer(allocator, .{ - .elem_ctype = .u8, - .@"const" = true, - }), - .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)), - }, - .{ - .name = .{ .index = .len }, - .ctype = .usize, - .alignas = AlignAs.fromAbiAlignment( - .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())), - ), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - - .manyptr_const_slice_const_u8_type => { - const target = &mod.resolved_target.result; - var fields: [2]Info.Field = .{ - .{ - .name = .{ .index = .ptr }, - .ctype = try pool.getPointer(allocator, .{ - .elem_ctype = .u8, - .@"const" = true, - .nonstring = true, - }), - .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)), - }, - .{ - .name = .{ .index = .len }, - .ctype = .usize, - .alignas = AlignAs.fromAbiAlignment( - .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())), - ), - }, - }; - const slice_const_u8 = try pool.fromFields(allocator, .@"struct", &fields, kind); - return pool.getPointer(allocator, .{ - .elem_ctype = slice_const_u8, - .@"const" = true, - }); - }, - .slice_const_slice_const_u8_type => { - const target = &mod.resolved_target.result; - var fields: [2]Info.Field = .{ - .{ - .name = .{ .index = .ptr }, - .ctype = try pool.getPointer(allocator, .{ - .elem_ctype = .u8, - .@"const" = true, - .nonstring = true, - }), - .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)), - }, - .{ - .name = .{ .index = .len }, - .ctype = .usize, - .alignas = AlignAs.fromAbiAlignment( - .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())), - ), - }, - }; - const slice_const_u8 = try pool.fromFields(allocator, .@"struct", &fields, .forward); - fields = .{ - .{ - .name = .{ .index = .ptr }, - .ctype = try pool.getPointer(allocator, .{ - .elem_ctype = slice_const_u8, - .@"const" = true, - }), - .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)), - }, - .{ - .name = .{ .index = .len }, - .ctype = .usize, - .alignas = AlignAs.fromAbiAlignment( - .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())), - ), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - - .vector_8_i8_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .i8, - .len = 8, - .nonstring = true, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.i8.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_16_i8_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .i8, - .len = 16, - .nonstring = true, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.i8.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_32_i8_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .i8, - .len = 32, - .nonstring = true, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.i8.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_64_i8_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .i8, - .len = 64, - .nonstring = true, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.i8.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_1_u8_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .u8, - .len = 1, - .nonstring = true, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u8.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_2_u8_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .u8, - .len = 2, - .nonstring = true, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u8.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_4_u8_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .u8, - .len = 4, - .nonstring = true, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u8.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_8_u8_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .u8, - .len = 8, - .nonstring = true, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u8.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_16_u8_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .u8, - .len = 16, - .nonstring = true, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u8.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_32_u8_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .u8, - .len = 32, - .nonstring = true, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u8.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_64_u8_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .u8, - .len = 64, - .nonstring = true, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u8.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_2_i16_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .i16, - .len = 2, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.i16.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_4_i16_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .i16, - .len = 4, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.i16.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_8_i16_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .i16, - .len = 8, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.i16.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_16_i16_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .i16, - .len = 16, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.i16.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_32_i16_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .i16, - .len = 32, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.i16.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_4_u16_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .u16, - .len = 4, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u16.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_8_u16_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .u16, - .len = 8, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u16.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_16_u16_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .u16, - .len = 16, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u16.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_32_u16_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .u16, - .len = 32, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u16.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_2_i32_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .i32, - .len = 2, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.i32.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_4_i32_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .i32, - .len = 4, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.i32.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_8_i32_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .i32, - .len = 8, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.i32.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_16_i32_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .i32, - .len = 16, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.i32.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_4_u32_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .u32, - .len = 4, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u32.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_8_u32_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .u32, - .len = 8, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u32.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_16_u32_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .u32, - .len = 16, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u32.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_2_i64_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .i64, - .len = 2, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.i64.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_4_i64_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .i64, - .len = 4, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.i64.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_8_i64_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .i64, - .len = 8, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.i64.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_2_u64_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .u64, - .len = 2, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u64.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_4_u64_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .u64, - .len = 4, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u64.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_8_u64_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .u64, - .len = 8, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u64.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_1_u128_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .u128, - .len = 1, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u128.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_2_u128_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .u128, - .len = 2, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u128.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_1_u256_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = try pool.fromIntInfo(allocator, .{ - .signedness = .unsigned, - .bits = 256, - }, mod, kind), - .len = 1, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.u256.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_4_f16_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .f16, - .len = 4, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.f16.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_8_f16_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .f16, - .len = 8, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.f16.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_16_f16_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .f16, - .len = 16, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.f16.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_32_f16_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .f16, - .len = 32, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.f16.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_2_f32_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .f32, - .len = 2, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.f32.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_4_f32_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .f32, - .len = 4, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.f32.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_8_f32_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .f32, - .len = 8, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.f32.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_16_f32_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .f32, - .len = 16, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.f32.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_2_f64_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .f64, - .len = 2, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.f64.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_4_f64_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .f64, - .len = 4, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.f64.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_8_f64_type => { - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = .f64, - .len = 8, - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(Type.f64.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - - .undef, - .undef_bool, - .undef_usize, - .undef_u1, - .zero, - .zero_usize, - .zero_u1, - .zero_u8, - .one, - .one_usize, - .one_u1, - .one_u8, - .four_u8, - .negative_one, - .void_value, - .unreachable_value, - .null_value, - .bool_true, - .bool_false, - .empty_tuple, - .none, - => unreachable, // values, not types - - _ => |ip_index| switch (ip.indexToKey(ip_index)) { - .int_type => |int_info| return pool.fromIntInfo(allocator, int_info, mod, kind), - .ptr_type => |ptr_info| switch (ptr_info.flags.size) { - .one, .many, .c => { - const elem_ctype = elem_ctype: { - if (ptr_info.packed_offset.host_size > 0 and - ptr_info.flags.vector_index == .none) - break :elem_ctype try pool.fromIntInfo(allocator, .{ - .signedness = .unsigned, - .bits = ptr_info.packed_offset.host_size * 8, - }, mod, .forward); - const elem: Info.Aligned = .{ - .ctype = try pool.fromType( - allocator, - scratch, - Type.fromInterned(ptr_info.child), - pt, - mod, - .forward, - ), - .alignas = AlignAs.fromAlignment(.{ - .@"align" = ptr_info.flags.alignment, - .abi = Type.fromInterned(ptr_info.child).abiAlignment(zcu), - }), - }; - break :elem_ctype if (elem.alignas.abiOrder().compare(.gte)) - elem.ctype - else - try pool.getAligned(allocator, elem); - }; - const elem_tag: Info.Tag = switch (elem_ctype.info(pool)) { - .aligned => |aligned_info| aligned_info.ctype.info(pool), - else => |elem_tag| elem_tag, - }; - return pool.getPointer(allocator, .{ - .elem_ctype = elem_ctype, - .@"const" = switch (elem_tag) { - .basic, - .pointer, - .aligned, - .array, - .vector, - .fwd_decl, - .aggregate, - => ptr_info.flags.is_const, - .function => false, - }, - .@"volatile" = ptr_info.flags.is_volatile, - .nonstring = elem_ctype.isAnyChar() and switch (ptr_info.sentinel) { - .none => true, - .zero_u8 => false, - else => |sentinel| !Value.fromInterned(sentinel).compareAllWithZero(.eq, zcu), - }, - }); - }, - .slice => { - const target = &mod.resolved_target.result; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .ptr }, - .ctype = try pool.fromType( - allocator, - scratch, - Type.fromInterned(ip.slicePtrType(ip_index)), - pt, - mod, - kind, - ), - .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)), - }, - .{ - .name = .{ .index = .len }, - .ctype = .usize, - .alignas = AlignAs.fromAbiAlignment( - .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())), - ), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - }, - .array_type => |array_info| { - const len = array_info.lenIncludingSentinel(); - if (len == 0) return .void; - const elem_type = Type.fromInterned(array_info.child); - const elem_ctype = try pool.fromType( - allocator, - scratch, - elem_type, - pt, - mod, - kind.noParameter().asComplete(), - ); - if (elem_ctype.index == .void) return .void; - const array_ctype = try pool.getArray(allocator, .{ - .elem_ctype = elem_ctype, - .len = len, - .nonstring = elem_ctype.isAnyChar() and switch (array_info.sentinel) { - .none => true, - .zero_u8 => false, - else => |sentinel| !Value.fromInterned(sentinel).compareAllWithZero(.eq, zcu), - }, - }); - if (!kind.isParameter()) return array_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = array_ctype, - .alignas = AlignAs.fromAbiAlignment(elem_type.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .vector_type => |vector_info| { - if (vector_info.len == 0) return .void; - const elem_type = Type.fromInterned(vector_info.child); - const elem_ctype = try pool.fromType( - allocator, - scratch, - elem_type, - pt, - mod, - kind.noParameter().asComplete(), - ); - if (elem_ctype.index == .void) return .void; - const vector_ctype = try pool.getVector(allocator, .{ - .elem_ctype = elem_ctype, - .len = vector_info.len, - .nonstring = elem_ctype.isAnyChar(), - }); - if (!kind.isParameter()) return vector_ctype; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .array }, - .ctype = vector_ctype, - .alignas = AlignAs.fromAbiAlignment(elem_type.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .opt_type => |payload_type| { - if (Type.fromInterned(payload_type).isNoReturn(zcu)) return .void; - const payload_ctype = try pool.fromType( - allocator, - scratch, - Type.fromInterned(payload_type), - pt, - mod, - kind.noParameter(), - ); - if (payload_ctype.index == .void) return .bool; - switch (payload_type) { - .anyerror_type => return payload_ctype, - else => switch (ip.indexToKey(payload_type)) { - .ptr_type => |payload_ptr_info| if (payload_ptr_info.flags.size != .c and - !payload_ptr_info.flags.is_allowzero) return payload_ctype, - .error_set_type, .inferred_error_set_type => return payload_ctype, - else => {}, - }, - } - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .is_null }, - .ctype = .bool, - .alignas = AlignAs.fromAbiAlignment(.@"1"), - }, - .{ - .name = .{ .index = .payload }, - .ctype = payload_ctype, - .alignas = AlignAs.fromAbiAlignment( - Type.fromInterned(payload_type).abiAlignment(zcu), - ), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .anyframe_type => unreachable, - .error_union_type => |error_union_info| { - const error_set_bits = pt.zcu.errorSetBits(); - const error_set_ctype = try pool.fromIntInfo(allocator, .{ - .signedness = .unsigned, - .bits = error_set_bits, - }, mod, kind); - if (Type.fromInterned(error_union_info.payload_type).isNoReturn(zcu)) return error_set_ctype; - const payload_type = Type.fromInterned(error_union_info.payload_type); - const payload_ctype = try pool.fromType( - allocator, - scratch, - payload_type, - pt, - mod, - kind.noParameter(), - ); - if (payload_ctype.index == .void) return error_set_ctype; - const target = &mod.resolved_target.result; - var fields = [_]Info.Field{ - .{ - .name = .{ .index = .@"error" }, - .ctype = error_set_ctype, - .alignas = AlignAs.fromAbiAlignment( - .fromByteUnits(std.zig.target.intAlignment(target, error_set_bits)), - ), - }, - .{ - .name = .{ .index = .payload }, - .ctype = payload_ctype, - .alignas = AlignAs.fromAbiAlignment(payload_type.abiAlignment(zcu)), - }, - }; - return pool.fromFields(allocator, .@"struct", &fields, kind); - }, - .simple_type => unreachable, - .struct_type => { - const loaded_struct = ip.loadStructType(ip_index); - switch (loaded_struct.layout) { - .auto, .@"extern" => { - const fwd_decl = try pool.getFwdDecl(allocator, .{ - .tag = .@"struct", - .name = .{ .index = ip_index }, - }); - if (kind.isForward()) return if (ty.hasRuntimeBits(zcu)) - fwd_decl - else - .void; - const scratch_top = scratch.items.len; - defer scratch.shrinkRetainingCapacity(scratch_top); - try scratch.ensureUnusedCapacity( - allocator, - loaded_struct.field_types.len * @typeInfo(Field).@"struct".fields.len, - ); - var hasher = Hasher.init; - var tag: Pool.Tag = .aggregate_struct; - var field_it = loaded_struct.iterateRuntimeOrder(ip); - while (field_it.next()) |field_index| { - const field_type = Type.fromInterned( - loaded_struct.field_types.get(ip)[field_index], - ); - const field_ctype = try pool.fromType( - allocator, - scratch, - field_type, - pt, - mod, - kind.noParameter(), - ); - if (field_ctype.index == .void) continue; - const field_name = try pool.string(allocator, loaded_struct.field_names.get(ip)[field_index].toSlice(ip)); - const field_alignas = AlignAs.fromAlignment(.{ - .@"align" = loaded_struct.field_aligns.getOrNone(ip, field_index), - .abi = field_type.abiAlignment(zcu), - }); - pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{ - .name = field_name.index, - .ctype = field_ctype.index, - .flags = .{ .alignas = field_alignas }, - }); - if (field_alignas.abiOrder().compare(.lt)) - tag = .aggregate_struct_packed; - } - const fields_len: u32 = @intCast(@divExact( - scratch.items.len - scratch_top, - @typeInfo(Field).@"struct".fields.len, - )); - if (fields_len == 0) return .void; - try pool.ensureUnusedCapacity(allocator, 1); - const extra_index = try pool.addHashedExtra(allocator, &hasher, Aggregate, .{ - .fwd_decl = fwd_decl.index, - .fields_len = fields_len, - }, fields_len * @typeInfo(Field).@"struct".fields.len); - pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); - return pool.tagTrailingExtraAssumeCapacity(hasher, tag, extra_index); - }, - .@"packed" => return pool.fromType( - allocator, - scratch, - .fromInterned(loaded_struct.packed_backing_int_type), - pt, - mod, - kind, - ), - } - }, - .tuple_type => |tuple_info| { - const scratch_top = scratch.items.len; - defer scratch.shrinkRetainingCapacity(scratch_top); - try scratch.ensureUnusedCapacity(allocator, tuple_info.types.len * - @typeInfo(Field).@"struct".fields.len); - var hasher = Hasher.init; - for (0..tuple_info.types.len) |field_index| { - if (tuple_info.values.get(ip)[field_index] != .none) continue; - const field_type = Type.fromInterned( - tuple_info.types.get(ip)[field_index], - ); - const field_ctype = try pool.fromType( - allocator, - scratch, - field_type, - pt, - mod, - kind.noParameter(), - ); - if (field_ctype.index == .void) continue; - const field_name = try pool.fmt(allocator, "f{d}", .{field_index}); - pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{ - .name = field_name.index, - .ctype = field_ctype.index, - .flags = .{ .alignas = AlignAs.fromAbiAlignment( - field_type.abiAlignment(zcu), - ) }, - }); - } - const fields_len: u32 = @intCast(@divExact( - scratch.items.len - scratch_top, - @typeInfo(Field).@"struct".fields.len, - )); - if (fields_len == 0) return .void; - if (kind.isForward()) { - try pool.ensureUnusedCapacity(allocator, 1); - const extra_index = try pool.addHashedExtra( - allocator, - &hasher, - FwdDeclAnon, - .{ .fields_len = fields_len }, - fields_len * @typeInfo(Field).@"struct".fields.len, - ); - pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); - return pool.tagTrailingExtra( - allocator, - hasher, - .fwd_decl_struct_anon, - extra_index, - ); - } - const fwd_decl = try pool.fromType(allocator, scratch, ty, pt, mod, .forward); - try pool.ensureUnusedCapacity(allocator, 1); - const extra_index = try pool.addHashedExtra(allocator, &hasher, Aggregate, .{ - .fwd_decl = fwd_decl.index, - .fields_len = fields_len, - }, fields_len * @typeInfo(Field).@"struct".fields.len); - pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); - return pool.tagTrailingExtraAssumeCapacity(hasher, .aggregate_struct, extra_index); - }, - .union_type => { - const loaded_union = ip.loadUnionType(ip_index); - switch (loaded_union.layout) { - .auto, .@"extern" => { - const fwd_decl = try pool.getFwdDecl(allocator, .{ - .tag = if (loaded_union.has_runtime_tag) .@"struct" else .@"union", - .name = .{ .index = ip_index }, - }); - if (kind.isForward()) return if (ty.hasRuntimeBits(zcu)) - fwd_decl - else - .void; - const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); - const scratch_top = scratch.items.len; - defer scratch.shrinkRetainingCapacity(scratch_top); - try scratch.ensureUnusedCapacity( - allocator, - loaded_union.field_types.len * @typeInfo(Field).@"struct".fields.len, - ); - var hasher = Hasher.init; - var tag: Pool.Tag = .aggregate_union; - var payload_align: InternPool.Alignment = .@"1"; - for (0..loaded_union.field_types.len) |field_index| { - const field_type = Type.fromInterned( - loaded_union.field_types.get(ip)[field_index], - ); - if (field_type.isNoReturn(zcu)) continue; - const field_ctype = try pool.fromType( - allocator, - scratch, - field_type, - pt, - mod, - kind.noParameter(), - ); - if (field_ctype.index == .void) continue; - const field_name = try pool.string( - allocator, - loaded_tag.field_names.get(ip)[field_index].toSlice(ip), - ); - const field_alignas = AlignAs.fromAlignment(.{ - .@"align" = loaded_union.field_aligns.getOrNone(ip, field_index), - .abi = field_type.abiAlignment(zcu), - }); - pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{ - .name = field_name.index, - .ctype = field_ctype.index, - .flags = .{ .alignas = field_alignas }, - }); - if (field_alignas.abiOrder().compare(.lt)) - tag = .aggregate_union_packed; - payload_align = payload_align.maxStrict(field_alignas.@"align"); - } - const fields_len: u32 = @intCast(@divExact( - scratch.items.len - scratch_top, - @typeInfo(Field).@"struct".fields.len, - )); - if (!loaded_union.has_runtime_tag) { - if (fields_len == 0) return .void; - try pool.ensureUnusedCapacity(allocator, 1); - const extra_index = try pool.addHashedExtra( - allocator, - &hasher, - Aggregate, - .{ .fwd_decl = fwd_decl.index, .fields_len = fields_len }, - fields_len * @typeInfo(Field).@"struct".fields.len, - ); - pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); - return pool.tagTrailingExtraAssumeCapacity(hasher, tag, extra_index); - } - try pool.ensureUnusedCapacity(allocator, 2); - var struct_fields: [2]Info.Field = undefined; - var struct_fields_len: usize = 0; - const tag_type = Type.fromInterned(loaded_tag.int_tag_type); - const tag_ctype: CType = try pool.fromType( - allocator, - scratch, - tag_type, - pt, - mod, - kind.noParameter(), - ); - if (tag_ctype.index != .void) { - struct_fields[struct_fields_len] = .{ - .name = .{ .index = .tag }, - .ctype = tag_ctype, - .alignas = AlignAs.fromAbiAlignment(tag_type.abiAlignment(zcu)), - }; - struct_fields_len += 1; - } - if (fields_len > 0) { - const payload_ctype = payload_ctype: { - const extra_index = try pool.addHashedExtra( - allocator, - &hasher, - AggregateAnon, - .{ - .index = ip_index, - .id = 0, - .fields_len = fields_len, - }, - fields_len * @typeInfo(Field).@"struct".fields.len, - ); - pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); - break :payload_ctype pool.tagTrailingExtraAssumeCapacity( - hasher, - switch (tag) { - .aggregate_union => .aggregate_union_anon, - .aggregate_union_packed => .aggregate_union_packed_anon, - else => unreachable, - }, - extra_index, - ); - }; - if (payload_ctype.index != .void) { - struct_fields[struct_fields_len] = .{ - .name = .{ .index = .payload }, - .ctype = payload_ctype, - .alignas = AlignAs.fromAbiAlignment(payload_align), - }; - struct_fields_len += 1; - } - } - if (struct_fields_len == 0) return .void; - sortFields(struct_fields[0..struct_fields_len]); - return pool.getAggregate(allocator, .{ - .tag = .@"struct", - .name = .{ .fwd_decl = fwd_decl }, - .fields = struct_fields[0..struct_fields_len], - }); - }, - .@"packed" => return pool.fromIntInfo(allocator, .{ - .signedness = .unsigned, - .bits = @intCast(ty.bitSize(zcu)), - }, mod, kind), - } - }, - .opaque_type => return .void, - .enum_type => return pool.fromType( - allocator, - scratch, - .fromInterned(ip.loadEnumType(ip_index).int_tag_type), - pt, - mod, - kind, - ), - .func_type => |func_info| { - if (!ty.fnHasRuntimeBits(zcu)) return .void; - - const scratch_top = scratch.items.len; - defer scratch.shrinkRetainingCapacity(scratch_top); - try scratch.ensureUnusedCapacity(allocator, func_info.param_types.len); - var hasher = Hasher.init; - const return_type = Type.fromInterned(func_info.return_type); - const return_ctype: CType = - if (!Type.fromInterned(func_info.return_type).isNoReturn(zcu)) try pool.fromType( - allocator, - scratch, - return_type, - pt, - mod, - kind.asParameter(), - ) else .void; - for (0..func_info.param_types.len) |param_index| { - const param_type = Type.fromInterned( - func_info.param_types.get(ip)[param_index], - ); - const param_ctype = try pool.fromType( - allocator, - scratch, - param_type, - pt, - mod, - kind.asParameter(), - ); - if (param_ctype.index == .void) continue; - hasher.update(param_ctype.hash(pool)); - scratch.appendAssumeCapacity(@intFromEnum(param_ctype.index)); - } - const param_ctypes_len: u32 = @intCast(scratch.items.len - scratch_top); - try pool.ensureUnusedCapacity(allocator, 1); - const extra_index = try pool.addHashedExtra(allocator, &hasher, Function, .{ - .return_ctype = return_ctype.index, - .param_ctypes_len = param_ctypes_len, - }, param_ctypes_len); - pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); - return pool.tagTrailingExtraAssumeCapacity(hasher, switch (func_info.is_var_args) { - false => .function, - true => .function_varargs, - }, extra_index); - }, - .error_set_type, - .inferred_error_set_type, - => return pool.fromIntInfo(allocator, .{ - .signedness = .unsigned, - .bits = pt.zcu.errorSetBits(), - }, mod, kind), - - .undef, - .simple_value, - .variable, - .@"extern", - .func, - .int, - .err, - .error_union, - .enum_literal, - .enum_tag, - .float, - .ptr, - .slice, - .opt, - .aggregate, - .un, - .bitpack, - .memoized_call, - => unreachable, // values, not types - }, - } - } - - pub fn getOrPutAdapted( - pool: *Pool, - allocator: std.mem.Allocator, - source_pool: *const Pool, - source_ctype: CType, - pool_adapter: anytype, - ) !struct { CType, bool } { - const tag = source_pool.items.items(.tag)[ - source_ctype.toPoolIndex() orelse return .{ source_ctype, true } - ]; - try pool.ensureUnusedCapacity(allocator, 1); - const CTypeAdapter = struct { - pool: *const Pool, - source_pool: *const Pool, - source_info: Info, - pool_adapter: @TypeOf(pool_adapter), - pub fn hash(map_adapter: @This(), key_ctype: CType) Map.Hash { - return key_ctype.hash(map_adapter.source_pool); - } - pub fn eql(map_adapter: @This(), _: CType, _: void, pool_index: usize) bool { - return map_adapter.source_info.eqlAdapted( - map_adapter.source_pool, - .fromPoolIndex(pool_index), - map_adapter.pool, - map_adapter.pool_adapter, - ); - } - }; - const source_info = source_ctype.info(source_pool); - const gop = pool.map.getOrPutAssumeCapacityAdapted(source_ctype, CTypeAdapter{ - .pool = pool, - .source_pool = source_pool, - .source_info = source_info, - .pool_adapter = pool_adapter, - }); - errdefer _ = pool.map.pop(); - const ctype: CType = .fromPoolIndex(gop.index); - if (!gop.found_existing) switch (source_info) { - .basic => unreachable, - .pointer => |pointer_info| pool.items.appendAssumeCapacity(switch (pointer_info.nonstring) { - false => .{ - .tag = tag, - .data = @intFromEnum(pool_adapter.copy(pointer_info.elem_ctype).index), - }, - true => .{ - .tag = .nonstring, - .data = @intFromEnum(pool_adapter.copy(.{ .index = @enumFromInt( - source_pool.items.items(.data)[source_ctype.toPoolIndex().?], - ) }).index), - }, - }), - .aligned => |aligned_info| pool.items.appendAssumeCapacity(.{ - .tag = tag, - .data = try pool.addExtra(allocator, Aligned, .{ - .ctype = pool_adapter.copy(aligned_info.ctype).index, - .flags = .{ .alignas = aligned_info.alignas }, - }, 0), - }), - .array, .vector => |sequence_info| pool.items.appendAssumeCapacity(switch (sequence_info.nonstring) { - false => .{ - .tag = tag, - .data = switch (tag) { - .array_small, .vector => try pool.addExtra(allocator, SequenceSmall, .{ - .elem_ctype = pool_adapter.copy(sequence_info.elem_ctype).index, - .len = @intCast(sequence_info.len), - }, 0), - .array_large => try pool.addExtra(allocator, SequenceLarge, .{ - .elem_ctype = pool_adapter.copy(sequence_info.elem_ctype).index, - .len_lo = @truncate(sequence_info.len >> 0), - .len_hi = @truncate(sequence_info.len >> 32), - }, 0), - else => unreachable, - }, - }, - true => .{ - .tag = .nonstring, - .data = @intFromEnum(pool_adapter.copy(.{ .index = @enumFromInt( - source_pool.items.items(.data)[source_ctype.toPoolIndex().?], - ) }).index), - }, - }), - .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) { - .anon => |fields| { - pool.items.appendAssumeCapacity(.{ - .tag = tag, - .data = try pool.addExtra(allocator, FwdDeclAnon, .{ - .fields_len = fields.len, - }, fields.len * @typeInfo(Field).@"struct".fields.len), - }); - for (0..fields.len) |field_index| { - const field = fields.at(field_index, source_pool); - const field_name = if (field.name.toPoolSlice(source_pool)) |slice| - try pool.string(allocator, slice) - else - field.name; - pool.addExtraAssumeCapacity(Field, .{ - .name = field_name.index, - .ctype = pool_adapter.copy(field.ctype).index, - .flags = .{ .alignas = field.alignas }, - }); - } - }, - .index => |index| pool.items.appendAssumeCapacity(.{ - .tag = tag, - .data = @intFromEnum(index), - }), - }, - .aggregate => |aggregate_info| { - pool.items.appendAssumeCapacity(.{ - .tag = tag, - .data = switch (aggregate_info.name) { - .anon => |anon| try pool.addExtra(allocator, AggregateAnon, .{ - .index = anon.index, - .id = anon.id, - .fields_len = aggregate_info.fields.len, - }, aggregate_info.fields.len * @typeInfo(Field).@"struct".fields.len), - .fwd_decl => |fwd_decl| try pool.addExtra(allocator, Aggregate, .{ - .fwd_decl = pool_adapter.copy(fwd_decl).index, - .fields_len = aggregate_info.fields.len, - }, aggregate_info.fields.len * @typeInfo(Field).@"struct".fields.len), - }, - }); - for (0..aggregate_info.fields.len) |field_index| { - const field = aggregate_info.fields.at(field_index, source_pool); - const field_name = if (field.name.toPoolSlice(source_pool)) |slice| - try pool.string(allocator, slice) - else - field.name; - pool.addExtraAssumeCapacity(Field, .{ - .name = field_name.index, - .ctype = pool_adapter.copy(field.ctype).index, - .flags = .{ .alignas = field.alignas }, - }); - } - }, - .function => |function_info| { - pool.items.appendAssumeCapacity(.{ - .tag = tag, - .data = try pool.addExtra(allocator, Function, .{ - .return_ctype = pool_adapter.copy(function_info.return_ctype).index, - .param_ctypes_len = function_info.param_ctypes.len, - }, function_info.param_ctypes.len), - }); - for (0..function_info.param_ctypes.len) |param_index| pool.extra.appendAssumeCapacity( - @intFromEnum(pool_adapter.copy( - function_info.param_ctypes.at(param_index, source_pool), - ).index), - ); - }, - }; - assert(source_info.eqlAdapted(source_pool, ctype, pool, pool_adapter)); - assert(source_ctype.hash(source_pool) == ctype.hash(pool)); - return .{ ctype, gop.found_existing }; - } - - pub fn string(pool: *Pool, allocator: std.mem.Allocator, slice: []const u8) !String { - try pool.string_bytes.appendSlice(allocator, slice); - return pool.trailingString(allocator); - } - - pub fn fmt( - pool: *Pool, - allocator: std.mem.Allocator, - comptime fmt_str: []const u8, - fmt_args: anytype, - ) !String { - try pool.string_bytes.print(allocator, fmt_str, fmt_args); - return pool.trailingString(allocator); - } - - fn ensureUnusedCapacity(pool: *Pool, allocator: std.mem.Allocator, len: u32) !void { - try pool.map.ensureUnusedCapacity(allocator, len); - try pool.items.ensureUnusedCapacity(allocator, len); - } - - const Hasher = struct { - const Impl = std.hash.Wyhash; - impl: Impl, - - const init: Hasher = .{ .impl = Impl.init(0) }; - - fn updateExtra(hasher: *Hasher, comptime Extra: type, extra: Extra, pool: *const Pool) void { - inline for (@typeInfo(Extra).@"struct".fields) |field| { - const value = @field(extra, field.name); - switch (field.type) { - Pool.Tag, String, CType => unreachable, - CType.Index => hasher.update((CType{ .index = value }).hash(pool)), - String.Index => if ((String{ .index = value }).toPoolSlice(pool)) |slice| - hasher.update(slice) - else - hasher.update(@intFromEnum(value)), - else => hasher.update(value), - } - } - } - fn update(hasher: *Hasher, data: anytype) void { - switch (@TypeOf(data)) { - Pool.Tag => @compileError("pass tag to final"), - CType, CType.Index => @compileError("hash ctype.hash(pool) instead"), - String, String.Index => @compileError("hash string.slice(pool) instead"), - u32, InternPool.Index, Aligned.Flags => hasher.impl.update(std.mem.asBytes(&data)), - []const u8 => hasher.impl.update(data), - else => @compileError("unhandled type: " ++ @typeName(@TypeOf(data))), - } - } - - fn final(hasher: Hasher, tag: Pool.Tag) Map.Hash { - var impl = hasher.impl; - impl.update(std.mem.asBytes(&tag)); - return @truncate(impl.final()); - } - }; - - fn tagData( - pool: *Pool, - allocator: std.mem.Allocator, - hasher: Hasher, - tag: Pool.Tag, - data: u32, - ) !CType { - try pool.ensureUnusedCapacity(allocator, 1); - const Key = struct { hash: Map.Hash, tag: Pool.Tag, data: u32 }; - const CTypeAdapter = struct { - pool: *const Pool, - pub fn hash(_: @This(), key: Key) Map.Hash { - return key.hash; - } - pub fn eql(ctype_adapter: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { - const rhs_item = ctype_adapter.pool.items.get(rhs_index); - return lhs_key.tag == rhs_item.tag and lhs_key.data == rhs_item.data; - } - }; - const gop = pool.map.getOrPutAssumeCapacityAdapted( - Key{ .hash = hasher.final(tag), .tag = tag, .data = data }, - CTypeAdapter{ .pool = pool }, - ); - if (!gop.found_existing) pool.items.appendAssumeCapacity(.{ .tag = tag, .data = data }); - return .fromPoolIndex(gop.index); - } - - fn tagExtra( - pool: *Pool, - allocator: std.mem.Allocator, - tag: Pool.Tag, - comptime Extra: type, - extra: Extra, - ) !CType { - var hasher = Hasher.init; - hasher.updateExtra(Extra, extra, pool); - return pool.tagTrailingExtra( - allocator, - hasher, - tag, - try pool.addExtra(allocator, Extra, extra, 0), - ); - } - - fn tagTrailingExtra( - pool: *Pool, - allocator: std.mem.Allocator, - hasher: Hasher, - tag: Pool.Tag, - extra_index: ExtraIndex, - ) !CType { - try pool.ensureUnusedCapacity(allocator, 1); - return pool.tagTrailingExtraAssumeCapacity(hasher, tag, extra_index); - } - - fn tagTrailingExtraAssumeCapacity( - pool: *Pool, - hasher: Hasher, - tag: Pool.Tag, - extra_index: ExtraIndex, - ) CType { - const Key = struct { hash: Map.Hash, tag: Pool.Tag, extra: []const u32 }; - const CTypeAdapter = struct { - pool: *const Pool, - pub fn hash(_: @This(), key: Key) Map.Hash { - return key.hash; - } - pub fn eql(ctype_adapter: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { - const rhs_item = ctype_adapter.pool.items.get(rhs_index); - if (lhs_key.tag != rhs_item.tag) return false; - const rhs_extra = ctype_adapter.pool.extra.items[rhs_item.data..]; - return std.mem.startsWith(u32, rhs_extra, lhs_key.extra); - } - }; - const gop = pool.map.getOrPutAssumeCapacityAdapted( - Key{ .hash = hasher.final(tag), .tag = tag, .extra = pool.extra.items[extra_index..] }, - CTypeAdapter{ .pool = pool }, - ); - if (gop.found_existing) - pool.extra.shrinkRetainingCapacity(extra_index) - else - pool.items.appendAssumeCapacity(.{ .tag = tag, .data = extra_index }); - return .fromPoolIndex(gop.index); - } - - fn sortFields(fields: []Info.Field) void { - std.mem.sort(Info.Field, fields, {}, struct { - fn before(_: void, lhs_field: Info.Field, rhs_field: Info.Field) bool { - return lhs_field.alignas.order(rhs_field.alignas).compare(.gt); - } - }.before); - } - - fn trailingString(pool: *Pool, allocator: std.mem.Allocator) !String { - const start = pool.string_indices.getLast(); - const slice: []const u8 = pool.string_bytes.items[start..]; - if (slice.len >= 2 and slice[0] == 'f' and switch (slice[1]) { - '0' => slice.len == 2, - '1'...'9' => true, - else => false, - }) if (std.fmt.parseInt(u31, slice[1..], 10)) |unnamed| { - pool.string_bytes.shrinkRetainingCapacity(start); - return String.fromUnnamed(unnamed); - } else |_| {}; - if (std.meta.stringToEnum(String.Index, slice)) |index| { - pool.string_bytes.shrinkRetainingCapacity(start); - return .{ .index = index }; - } - - try pool.string_map.ensureUnusedCapacity(allocator, 1); - try pool.string_indices.ensureUnusedCapacity(allocator, 1); - - const gop = pool.string_map.getOrPutAssumeCapacityAdapted(slice, String.Adapter{ .pool = pool }); - if (gop.found_existing) - pool.string_bytes.shrinkRetainingCapacity(start) - else - pool.string_indices.appendAssumeCapacity(@intCast(pool.string_bytes.items.len)); - return String.fromPoolIndex(gop.index); - } - - const Item = struct { - tag: Pool.Tag, - data: u32, - }; - - const ExtraIndex = u32; - - const Tag = enum(u8) { - basic, - pointer, - pointer_const, - pointer_volatile, - pointer_const_volatile, - aligned, - array_small, - array_large, - vector, - nonstring, - fwd_decl_struct_anon, - fwd_decl_union_anon, - fwd_decl_struct, - fwd_decl_union, - aggregate_struct_anon, - aggregate_struct_packed_anon, - aggregate_union_anon, - aggregate_union_packed_anon, - aggregate_struct, - aggregate_struct_packed, - aggregate_union, - aggregate_union_packed, - function, - function_varargs, - }; - - const Aligned = struct { - ctype: CType.Index, - flags: Flags, - - const Flags = packed struct(u32) { - alignas: AlignAs, - _: u20 = 0, - }; - }; - - const SequenceSmall = struct { - elem_ctype: CType.Index, - len: u32, - }; - - const SequenceLarge = struct { - elem_ctype: CType.Index, - len_lo: u32, - len_hi: u32, - - fn len(extra: SequenceLarge) u64 { - return @as(u64, extra.len_lo) << 0 | - @as(u64, extra.len_hi) << 32; - } - }; - - const Field = struct { - name: String.Index, - ctype: CType.Index, - flags: Flags, - - const Flags = Aligned.Flags; - }; - - const FwdDeclAnon = struct { - fields_len: u32, - }; - - const AggregateAnon = struct { - index: InternPool.Index, - id: u32, - fields_len: u32, - }; - - const Aggregate = struct { - fwd_decl: CType.Index, - fields_len: u32, - }; - - const Function = struct { - return_ctype: CType.Index, - param_ctypes_len: u32, - }; - - fn addExtra( - pool: *Pool, - allocator: std.mem.Allocator, - comptime Extra: type, - extra: Extra, - trailing_len: usize, - ) !ExtraIndex { - try pool.extra.ensureUnusedCapacity( - allocator, - @typeInfo(Extra).@"struct".fields.len + trailing_len, - ); - defer pool.addExtraAssumeCapacity(Extra, extra); - return @intCast(pool.extra.items.len); - } - fn addExtraAssumeCapacity(pool: *Pool, comptime Extra: type, extra: Extra) void { - addExtraAssumeCapacityTo(&pool.extra, Extra, extra); - } - fn addExtraAssumeCapacityTo( - array: *std.ArrayList(u32), - comptime Extra: type, - extra: Extra, - ) void { - inline for (@typeInfo(Extra).@"struct".fields) |field| { - const value = @field(extra, field.name); - array.appendAssumeCapacity(switch (field.type) { - u32 => value, - CType.Index, String.Index, InternPool.Index => @intFromEnum(value), - Aligned.Flags => @bitCast(value), - else => @compileError("bad field type: " ++ field.name ++ ": " ++ - @typeName(field.type)), - }); - } - } - - fn addHashedExtra( - pool: *Pool, - allocator: std.mem.Allocator, - hasher: *Hasher, - comptime Extra: type, - extra: Extra, - trailing_len: usize, - ) !ExtraIndex { - hasher.updateExtra(Extra, extra, pool); - return pool.addExtra(allocator, Extra, extra, trailing_len); - } - fn addHashedExtraAssumeCapacity( - pool: *Pool, - hasher: *Hasher, - comptime Extra: type, - extra: Extra, - ) void { - hasher.updateExtra(Extra, extra, pool); - pool.addExtraAssumeCapacity(Extra, extra); - } - fn addHashedExtraAssumeCapacityTo( - pool: *Pool, - array: *std.ArrayList(u32), - hasher: *Hasher, - comptime Extra: type, - extra: Extra, - ) void { - hasher.updateExtra(Extra, extra, pool); - addExtraAssumeCapacityTo(array, Extra, extra); - } - - const ExtraTrail = struct { - extra_index: ExtraIndex, - - fn next( - extra_trail: *ExtraTrail, - len: u32, - comptime Extra: type, - pool: *const Pool, - ) []const Extra { - defer extra_trail.extra_index += @intCast(len); - return @ptrCast(pool.extra.items[extra_trail.extra_index..][0..len]); - } - }; - - fn getExtraTrail( - pool: *const Pool, - comptime Extra: type, - extra_index: ExtraIndex, - ) struct { extra: Extra, trail: ExtraTrail } { - var extra: Extra = undefined; - const fields = @typeInfo(Extra).@"struct".fields; - inline for (fields, pool.extra.items[extra_index..][0..fields.len]) |field, value| - @field(extra, field.name) = switch (field.type) { - u32 => value, - CType.Index, String.Index, InternPool.Index => @enumFromInt(value), - Aligned.Flags => @bitCast(value), - else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), - }; - return .{ - .extra = extra, - .trail = .{ .extra_index = extra_index + @as(ExtraIndex, @intCast(fields.len)) }, - }; - } - - fn getExtra(pool: *const Pool, comptime Extra: type, extra_index: ExtraIndex) Extra { - return pool.getExtraTrail(Extra, extra_index).extra; - } -}; - -pub const AlignAs = packed struct { - @"align": InternPool.Alignment, - abi: InternPool.Alignment, - - pub fn fromAlignment(alignas: AlignAs) AlignAs { - assert(alignas.abi != .none); - return .{ - .@"align" = if (alignas.@"align" != .none) alignas.@"align" else alignas.abi, - .abi = alignas.abi, - }; - } - pub fn fromAbiAlignment(abi: InternPool.Alignment) AlignAs { - assert(abi != .none); - return .{ .@"align" = abi, .abi = abi }; - } - pub fn fromByteUnits(@"align": u64, abi: u64) AlignAs { - return fromAlignment(.{ - .@"align" = InternPool.Alignment.fromByteUnits(@"align"), - .abi = InternPool.Alignment.fromNonzeroByteUnits(abi), - }); - } - - pub fn order(lhs: AlignAs, rhs: AlignAs) std.math.Order { - return lhs.@"align".order(rhs.@"align"); - } - pub fn abiOrder(alignas: AlignAs) std.math.Order { - return alignas.@"align".order(alignas.abi); - } - pub fn toByteUnits(alignas: AlignAs) u64 { - return alignas.@"align".toByteUnits().?; - } -}; - -const std = @import("std"); -const assert = std.debug.assert; -const Writer = std.Io.Writer; - -const CType = @This(); -const InternPool = @import("../../InternPool.zig"); -const Module = @import("../../Package/Module.zig"); -const Type = @import("../../Type.zig"); -const Value = @import("../../Value.zig"); -const Zcu = @import("../../Zcu.zig"); diff --git a/src/codegen/c/type.zig b/src/codegen/c/type.zig new file mode 100644 index 0000000000000000000000000000000000000000..64e63e4d6733980ea6cca735f53c82cb041e36d8 --- /dev/null +++ b/src/codegen/c/type.zig @@ -0,0 +1,1013 @@ +pub const CType = union(enum) { + pub const render_defs = @import("type/render_defs.zig"); + + // The first nodes are primitive types (or standard typedefs). + + void, + bool, + int: Int, + float: Float, + + // These next nodes are all typedefs, structs, or unions. + + @"fn": Type, + @"enum": Type, + bitpack: Type, + @"struct": Type, + union_auto: Type, + union_extern: Type, + slice: Type, + opt: Type, + arr: Type, + vec: Type, + errunion: struct { payload_ty: Type }, + aligned: struct { + ty: Type, + alignment: InternPool.Alignment, + }, + bigint: BigInt, + + // The remaining nodes have children. + + pointer: struct { + @"const": bool, + @"volatile": bool, + elem_ty: *const CType, + nonstring: bool, + }, + array: struct { + len: u64, + elem_ty: *const CType, + nonstring: bool, + }, + function: struct { + param_tys: []const CType, + ret_ty: *const CType, + varargs: bool, + }, + + /// Returns `true` if this node has a postfix operator, meaning an `[...]` or `(...)` appears + /// after the identifier in a declarator with this type. In this case, if this node is wrapped + /// in a pointer type, we will need to add parentheses due to operator precedence. + /// + /// For instance, when lowering a Zig declaration `foo: *const fn (c_int) void`, it would be a + /// bug to write the C declarator as `void *foo(int)`, because the `(int)` suffix declaring the + /// function type has higher precedence than the `*` prefix declaring the pointer type. Instead, + /// this type must be lowered as `void (*foo)(int)`. + fn kind(cty: *const CType) enum { + /// `cty` is just a C type specifier, i.e. a typedef or a named struct/union type. + specifier, + /// `cty` is a C function or array type. It will have a postfix "operator" in its suffix to + /// declare the type, either `(...)` (for a function type) or `[...]` (for an array type). + postfix_op, + /// `cty` is a C pointer type. Its prefix will end with "*". + pointer, + } { + return switch (cty.*) { + .void, + .bool, + .int, + .float, + .@"fn", + .@"enum", + .bitpack, + .@"struct", + .union_auto, + .union_extern, + .slice, + .opt, + .arr, + .vec, + .errunion, + .aligned, + .bigint, + => .specifier, + + .array, + .function, + => .postfix_op, + + .pointer => .pointer, + }; + } + + pub const Int = enum { + char, + + @"unsigned short", + @"unsigned int", + @"unsigned long", + @"unsigned long long", + + @"signed short", + @"signed int", + @"signed long", + @"signed long long", + + uint8_t, + uint16_t, + uint32_t, + uint64_t, + zig_u128, + + int8_t, + int16_t, + int32_t, + int64_t, + zig_i128, + + uintptr_t, + intptr_t, + + pub fn bits(int: Int, target: *const std.Target) u16 { + return switch (int) { + // zig fmt: off + .char => target.cTypeBitSize(.char), + + .@"unsigned short" => target.cTypeBitSize(.ushort), + .@"unsigned int" => target.cTypeBitSize(.uint), + .@"unsigned long" => target.cTypeBitSize(.ulong), + .@"unsigned long long" => target.cTypeBitSize(.ulonglong), + + .@"signed short" => target.cTypeBitSize(.short), + .@"signed int" => target.cTypeBitSize(.int), + .@"signed long" => target.cTypeBitSize(.long), + .@"signed long long" => target.cTypeBitSize(.longlong), + + .uintptr_t, .intptr_t => target.ptrBitWidth(), + + .uint8_t, .int8_t => 8, + .uint16_t, .int16_t => 16, + .uint32_t, .int32_t => 32, + .uint64_t, .int64_t => 64, + .zig_u128, .zig_i128 => 128, + // zig fmt: on + }; + } + }; + + pub const BigInt = struct { + limb_size: LimbSize, + /// Always greater than 1. + limbs_len: u16, + + pub const LimbSize = enum { + @"8", + @"16", + @"32", + @"64", + @"128", + pub fn bits(s: LimbSize) u8 { + return switch (s) { + .@"8" => 8, + .@"16" => 16, + .@"32" => 32, + .@"64" => 64, + .@"128" => 128, + }; + } + pub fn unsigned(s: LimbSize) Int { + return switch (s) { + .@"8" => .uint8_t, + .@"16" => .uint16_t, + .@"32" => .uint32_t, + .@"64" => .uint64_t, + .@"128" => .zig_u128, + }; + } + pub fn signed(s: LimbSize) Int { + return switch (s) { + .@"8" => .int8_t, + .@"16" => .int16_t, + .@"32" => .int32_t, + .@"64" => .int64_t, + .@"128" => .zig_i128, + }; + } + }; + }; + + pub const Float = enum { + @"long double", + zig_f16, + zig_f32, + zig_f64, + zig_f80, + zig_f128, + zig_u128, + zig_i128, + }; + + pub fn isStringElem(cty: CType) bool { + return switch (cty) { + .int => |int| switch (int) { + .char, .int8_t, .uint8_t => true, + else => false, + }, + else => false, + }; + } + + pub fn lower( + ty: Type, + deps: *Dependencies, + arena: Allocator, + zcu: *const Zcu, + ) Allocator.Error!CType { + return lowerInner(ty, false, deps, arena, zcu); + } + fn lowerInner( + start_ty: Type, + allow_incomplete: bool, + deps: *Dependencies, + arena: Allocator, + zcu: *const Zcu, + ) Allocator.Error!CType { + const gpa = zcu.comp.gpa; + const ip = &zcu.intern_pool; + var cur_ty = start_ty; + while (true) { + switch (cur_ty.zigTypeTag(zcu)) { + .type, + .comptime_int, + .comptime_float, + .undefined, + .null, + .enum_literal, + .@"opaque", + .noreturn, + .void, + => return .void, + + .bool => return .bool, + + .int, .error_set => switch (classifyInt(cur_ty, zcu)) { + .void => return .void, + .small => |s| return .{ .int = s }, + .big => |big| { + try deps.bigint.put(gpa, big, {}); + return .{ .bigint = big }; + }, + }, + + .float => return .{ .float = switch (cur_ty.toIntern()) { + .c_longdouble_type => .@"long double", + .f16_type => .zig_f16, + .f32_type => .zig_f32, + .f64_type => .zig_f64, + .f80_type => .zig_f80, + .f128_type => .zig_f128, + else => unreachable, + } }, + .vector => { + try deps.addType(gpa, cur_ty, allow_incomplete); + return .{ .vec = cur_ty }; + }, + .array => { + try deps.addType(gpa, cur_ty, allow_incomplete); + return .{ .arr = cur_ty }; + }, + + .pointer => { + const ptr = cur_ty.ptrInfo(zcu); + switch (ptr.flags.size) { + .slice => { + try deps.addType(gpa, cur_ty, allow_incomplete); + return .{ .slice = cur_ty }; + }, + .one, .many, .c => { + const elem_ty: Type = .fromInterned(ptr.child); + const is_fn_ptr = elem_ty.zigTypeTag(zcu) == .@"fn"; + const elem_cty: CType = elem_cty: { + if (ptr.packed_offset.host_size > 0 and ptr.flags.vector_index == .none) { + switch (classifyBitInt(.unsigned, ptr.packed_offset.host_size * 8, zcu)) { + .void => break :elem_cty .void, + .small => |s| break :elem_cty .{ .int = s }, + .big => |big| { + try deps.bigint.put(gpa, big, {}); + break :elem_cty .{ .bigint = big }; + }, + } + } + if (ptr.flags.alignment != .none and !is_fn_ptr) { + // The pointer has an explicit alignment---if it's an underalignment + // then we need to use an "aligned" typedef. + const ptr_align = ptr.flags.alignment; + if (!alwaysHasLayout(elem_ty, ip) or + ptr_align.compareStrict(.lt, elem_ty.abiAlignment(zcu))) + { + const gop = try deps.aligned_type_fwd.getOrPut(gpa, elem_ty.toIntern()); + if (!gop.found_existing) gop.value_ptr.* = 0; + gop.value_ptr.* |= @as(u64, 1) << ptr_align.toLog2Units(); + break :elem_cty .{ .aligned = .{ + .ty = elem_ty, + .alignment = ptr_align, + } }; + } + } + break :elem_cty try .lowerInner(elem_ty, true, deps, arena, zcu); + }; + const elem_cty_buf = try arena.create(CType); + elem_cty_buf.* = elem_cty; + return .{ .pointer = .{ + .@"const" = ptr.flags.is_const and !is_fn_ptr, + .@"volatile" = ptr.flags.is_volatile and !is_fn_ptr, + .elem_ty = elem_cty_buf, + .nonstring = nonstring: { + if (!elem_cty.isStringElem()) break :nonstring false; + if (ptr.sentinel == .none) break :nonstring true; + break :nonstring Value.compareHetero( + .fromInterned(ptr.sentinel), + .neq, + .zero_comptime_int, + zcu, + ); + }, + } }; + }, + } + }, + + .@"fn" => { + const func_type = ip.indexToKey(cur_ty.toIntern()).func_type; + direct: { + const ret_ty: Type = .fromInterned(func_type.return_type); + if (!alwaysHasLayout(ret_ty, ip)) break :direct; + var params_len: usize = 0; // only counts parameter types with runtime bits + for (func_type.param_types.get(ip)) |param_ty_ip| { + const param_ty: Type = .fromInterned(param_ty_ip); + if (!alwaysHasLayout(param_ty, ip)) break :direct; + if (param_ty.hasRuntimeBits(zcu)) params_len += 1; + } + // We can actually write this function type directly! + if (!cur_ty.fnHasRuntimeBits(zcu)) return .void; + const ret_cty_buf = try arena.create(CType); + if (!ret_ty.hasRuntimeBits(zcu)) { + // Incomplete function return types must always be `void`. + ret_cty_buf.* = .void; + } else { + ret_cty_buf.* = try .lowerInner(ret_ty, allow_incomplete, deps, arena, zcu); + } + const param_cty_buf = try arena.alloc(CType, params_len); + var param_index: usize = 0; + for (func_type.param_types.get(ip)) |param_ty_ip| { + const param_ty: Type = .fromInterned(param_ty_ip); + if (!param_ty.hasRuntimeBits(zcu)) continue; + param_cty_buf[param_index] = try .lowerInner(param_ty, allow_incomplete, deps, arena, zcu); + param_index += 1; + } + assert(param_index == params_len); + return .{ .function = .{ + .ret_ty = ret_cty_buf, + .param_tys = param_cty_buf, + .varargs = func_type.is_var_args, + } }; + } + try deps.addType(gpa, cur_ty, allow_incomplete); + return .{ .@"fn" = cur_ty }; + }, + + .@"struct" => { + try deps.addType(gpa, cur_ty, allow_incomplete); + switch (cur_ty.containerLayout(zcu)) { + .auto, .@"extern" => return .{ .@"struct" = cur_ty }, + .@"packed" => return .{ .bitpack = cur_ty }, + } + }, + .@"union" => { + try deps.addType(gpa, cur_ty, allow_incomplete); + switch (cur_ty.containerLayout(zcu)) { + .auto => return .{ .union_auto = cur_ty }, + .@"extern" => return .{ .union_extern = cur_ty }, + .@"packed" => return .{ .bitpack = cur_ty }, + } + }, + .@"enum" => { + try deps.addType(gpa, cur_ty, allow_incomplete); + return .{ .@"enum" = cur_ty }; + }, + + .optional => { + // This query does not require any type resolution. + if (cur_ty.optionalReprIsPayload(zcu)) { + // Either a pointer-like optional, or an optional error set. Just lower the payload. + cur_ty = cur_ty.optionalChild(zcu); + continue; + } + if (alwaysHasLayout(cur_ty, ip)) switch (classifyOptional(cur_ty, zcu)) { + .error_set, .ptr_like, .slice_like => unreachable, // handled above + .npv_payload => return .void, + .opv_payload, .@"struct" => {}, + }; + try deps.addType(gpa, cur_ty, allow_incomplete); + return .{ .opt = cur_ty }; + }, + + .error_union => { + const payload_ty = cur_ty.errorUnionPayload(zcu); + if (allow_incomplete) { + try deps.errunion_type_fwd.put(gpa, payload_ty.toIntern(), {}); + } else { + try deps.errunion_type.put(gpa, payload_ty.toIntern(), {}); + } + return .{ .errunion = .{ + .payload_ty = payload_ty, + } }; + }, + + .frame, + .@"anyframe", + => unreachable, + } + comptime unreachable; + } + } + + pub fn classifyOptional(opt_ty: Type, zcu: *const Zcu) enum { + /// The optional is something like `?noreturn`; it lowers to `void`. + npv_payload, + /// The payload type is an error set; the representation matches that of the error set, with + /// the value 0 representing `null`. + error_set, + /// The payload type is a non-optional pointer; the NULL pointer is used for `null`. + ptr_like, + /// The payload type is a non-optional slice; a NULL pointer field is used for `null`. + slice_like, + /// The optional is something like `?void`; it lowers to a struct, but one containing only + /// one field `is_null` (the payload is omitted). + opv_payload, + /// The optional uses the "default" lowering of a struct with two fields, like this: + /// struct optional_1234 { payload_ty payload; bool is_null; } + @"struct", + } { + const payload_ty = opt_ty.optionalChild(zcu); + if (opt_ty.optionalReprIsPayload(zcu)) { + return switch (payload_ty.zigTypeTag(zcu)) { + .error_set => .error_set, + .pointer => if (payload_ty.isSlice(zcu)) .slice_like else .ptr_like, + else => unreachable, + }; + } else { + return switch (payload_ty.classify(zcu)) { + .no_possible_value => .npv_payload, + .one_possible_value => .opv_payload, + else => .@"struct", + }; + } + } + + pub const IntClass = union(enum) { + /// The integer type is zero-bit, so lowers to `void`. + void, + /// The integer is under 128 bits long, so lowers to this C integer type. + small: Int, + /// The integer is over 128 bits long, so lowers to an array of limbs. + big: BigInt, + }; + + /// Asserts that `ty` is an integer, enum, bitpack, or error set. + pub fn classifyInt(ty: Type, zcu: *const Zcu) IntClass { + const int_ty: Type = switch (ty.zigTypeTag(zcu)) { + .error_set => return classifyBitInt(.unsigned, zcu.errorSetBits(), zcu), + .@"enum" => ty.intTagType(zcu), + .@"struct", .@"union" => ty.bitpackBackingInt(zcu), + .int => ty, + else => unreachable, + }; + switch (int_ty.toIntern()) { + // zig fmt: off + .usize_type => return .{ .small = .uintptr_t }, + .isize_type => return .{ .small = .intptr_t }, + + .c_char_type => return .{ .small = .char }, + + .c_short_type => return .{ .small = .@"signed short" }, + .c_int_type => return .{ .small = .@"signed int" }, + .c_long_type => return .{ .small = .@"signed long" }, + .c_longlong_type => return .{ .small = .@"signed long long" }, + + .c_ushort_type => return .{ .small = .@"unsigned short" }, + .c_uint_type => return .{ .small = .@"unsigned int" }, + .c_ulong_type => return .{ .small = .@"unsigned long" }, + .c_ulonglong_type => return .{ .small = .@"unsigned long long" }, + // zig fmt: on + + else => { + const int = ty.intInfo(zcu); + return classifyBitInt(int.signedness, int.bits, zcu); + }, + } + } + fn classifyBitInt(signedness: std.builtin.Signedness, bits: u16, zcu: *const Zcu) IntClass { + return switch (bits) { + 0 => .void, + 1...8 => switch (signedness) { + .unsigned => .{ .small = .uint8_t }, + .signed => .{ .small = .int8_t }, + }, + 9...16 => switch (signedness) { + .unsigned => .{ .small = .uint16_t }, + .signed => .{ .small = .int16_t }, + }, + 17...32 => switch (signedness) { + .unsigned => .{ .small = .uint32_t }, + .signed => .{ .small = .int32_t }, + }, + 33...64 => switch (signedness) { + .unsigned => .{ .small = .uint64_t }, + .signed => .{ .small = .int64_t }, + }, + 65...128 => switch (signedness) { + .unsigned => .{ .small = .zig_u128 }, + .signed => .{ .small = .zig_i128 }, + }, + else => { + @branchHint(.unlikely); + const target = zcu.getTarget(); + const limb_bytes = std.zig.target.intAlignment(target, bits); + return .{ .big = .{ + .limb_size = switch (limb_bytes) { + 1 => .@"8", + 2 => .@"16", + 4 => .@"32", + 8 => .@"64", + 16 => .@"128", + else => unreachable, + }, + .limbs_len = @divExact( + std.zig.target.intByteSize(target, bits), + limb_bytes, + ), + } }; + }, + }; + } + + /// Describes a set of types which must be declared or completed in the C source file before + /// some string of rendered C code (such as a function), due to said C code using these types. + pub const Dependencies = struct { + /// Key is any Zig type which corresponds to a C `struct`, `union`, or `typedef`. That C + /// type must be declared and complete. + type: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), + + /// Key is a Zig type which is the *payload* of an error union. The C `struct` type + /// corresponding to such an error union must be declared and complete. + /// + /// These are separate from `type` to avoid redundant types for every different error set + /// used with the same payload type---for instance a different C type for every `E!void`. + errunion_type: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), + + /// Like `type`, but the type does not necessarily need to be completed yet: a forward + /// declaration is sufficient. + type_fwd: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), + + /// Like `errunion_type`, but the type does not necessarily need to be completed yet: a + /// forward declaration is sufficient. + errunion_type_fwd: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), + + /// Key is a Zig type; value is a bitmask of alignments. For every bit which is set, an + /// aligned typedef is required. For instance, if bit 3 is set, the C type 'aligned__8_foo' + /// must be declared through `typedef` (but not necessarily completed yet). + aligned_type_fwd: std.AutoArrayHashMapUnmanaged(InternPool.Index, u64), + + /// Key specifies a big-int type whose C `struct` must be declared and complete. + bigint: std.AutoArrayHashMapUnmanaged(BigInt, void), + + pub const empty: Dependencies = .{ + .type = .empty, + .errunion_type = .empty, + .type_fwd = .empty, + .errunion_type_fwd = .empty, + .aligned_type_fwd = .empty, + .bigint = .empty, + }; + + pub fn deinit(deps: *Dependencies, gpa: Allocator) void { + deps.type.deinit(gpa); + deps.errunion_type.deinit(gpa); + deps.type_fwd.deinit(gpa); + deps.errunion_type_fwd.deinit(gpa); + deps.aligned_type_fwd.deinit(gpa); + deps.bigint.deinit(gpa); + } + + pub fn clearRetainingCapacity(deps: *Dependencies) void { + deps.type.clearRetainingCapacity(); + deps.errunion_type.clearRetainingCapacity(); + deps.type_fwd.clearRetainingCapacity(); + deps.errunion_type_fwd.clearRetainingCapacity(); + deps.aligned_type_fwd.clearRetainingCapacity(); + deps.bigint.clearRetainingCapacity(); + } + + pub fn move(deps: *Dependencies) Dependencies { + const moved = deps.*; + deps.* = .empty; + return moved; + } + + fn addType(deps: *Dependencies, gpa: Allocator, ty: Type, allow_incomplete: bool) Allocator.Error!void { + if (allow_incomplete) { + try deps.type_fwd.put(gpa, ty.toIntern(), {}); + } else { + try deps.type.put(gpa, ty.toIntern(), {}); + } + } + }; + + /// Formats the bytes which appear *before* the identifier in a declarator. This includes the + /// type specifier and all "prefix type operators" in the declarator. e.g: + /// * for the declarator "int foo", writes "int " + /// * for the declarator "struct thing *foo", writes "struct thing *" + /// * for the declarator "void *(*foo)(int)", writes "void *(*" + pub fn fmtDeclaratorPrefix(cty: CType, zcu: *const Zcu) Formatter { + return .{ + .cty = cty, + .zcu = zcu, + .kind = .declarator_prefix, + }; + } + /// Formats the bytes which appear *before* the identifier in a declarator. This includes the + /// type specifier and all "prefix type operators" in the declarator. e.g: + /// * for the declarator "int foo", writes "" + /// * for the declarator "struct thing *foo", writes "" + /// * for the declarator "void *(*foo)(int)", writes ")(int)" + pub fn fmtDeclaratorSuffix(cty: CType, zcu: *const Zcu) Formatter { + return .{ + .cty = cty, + .zcu = zcu, + .kind = .declarator_suffix, + }; + } + /// Like `fmtDeclaratorSuffix`, except never emits a `zig_nonstring` annotation. + pub fn fmtDeclaratorSuffixIgnoreNonstring(cty: CType, zcu: *const Zcu) Formatter { + return .{ + .cty = cty, + .zcu = zcu, + .kind = .declarator_suffix_ignore_nonstring, + }; + } + /// Formats a type's full name, e.g. "int", "struct foo *", "void *(uint32_t)". + /// + /// This is almost identical to `fmtDeclaratorPrefix` followed by `fmtDeclaratorSuffix`, but + /// that sequence of calls may emit trailing whitespace where this one does not---for instance, + /// those calls would write the type "void" as "void ". + pub fn fmtTypeName(cty: CType, zcu: *const Zcu) Formatter { + return .{ + .cty = cty, + .zcu = zcu, + .kind = .type_name, + }; + } + + const Formatter = struct { + cty: CType, + zcu: *const Zcu, + kind: enum { type_name, declarator_prefix, declarator_suffix, declarator_suffix_ignore_nonstring }, + + pub fn format(ctx: Formatter, w: *Writer) Writer.Error!void { + switch (ctx.kind) { + .type_name => { + try ctx.cty.writeTypePrefix(w, ctx.zcu); + try ctx.cty.writeTypeSuffix(w, ctx.zcu); + }, + .declarator_prefix => { + try ctx.cty.writeTypePrefix(w, ctx.zcu); + switch (ctx.cty.kind()) { + .specifier => try w.writeByte(' '), // write "int " rather than "int" + .pointer => {}, // we already have something like "foo *" + .postfix_op => {}, // we already have something like "ret_ty " + } + }, + .declarator_suffix => { + try ctx.cty.writeTypeSuffix(w, ctx.zcu); + const nonstring = switch (ctx.cty) { + .array => |arr| arr.nonstring, + .pointer => |ptr| ptr.nonstring, + else => false, + }; + if (nonstring) try w.writeAll(" zig_nonstring"); + }, + .declarator_suffix_ignore_nonstring => { + try ctx.cty.writeTypeSuffix(w, ctx.zcu); + }, + } + } + }; + + fn writeTypePrefix(cty: CType, w: *Writer, zcu: *const Zcu) Writer.Error!void { + switch (cty) { + .void => try w.writeAll("void"), + .bool => try w.writeAll("bool"), + .int => |int| try w.writeAll(@tagName(int)), + .float => |float| try w.writeAll(@tagName(float)), + .@"fn" => |ty| try w.print("{f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), + .@"enum" => |ty| try w.print("enum__{f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), + .bitpack => |ty| try w.print("bitpack__{f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), + .@"struct" => |ty| try w.print("struct {f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), + .union_auto => |ty| try w.print("struct {f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), + .union_extern => |ty| try w.print("union {f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), + .slice => |ty| try w.print("struct {f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), + .opt => |ty| try w.print("struct {f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), + .arr => |ty| try w.print("struct {f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), + .vec => |ty| try w.print("struct {f}_{d}", .{ fmtZigType(ty, zcu), ty.toIntern() }), + .errunion => |eu| try w.print("struct errunion_{f}_{d}", .{ + fmtZigType(eu.payload_ty, zcu), + eu.payload_ty.toIntern(), + }), + .aligned => |aligned| try w.print("aligned__{d}_{f}_{d}", .{ + aligned.alignment.toByteUnits().?, + fmtZigType(aligned.ty, zcu), + aligned.ty.toIntern(), + }), + .bigint => |bigint| try w.print("struct int_{d}x{d}", .{ + bigint.limb_size.bits(), + bigint.limbs_len, + }), + + .pointer => |ptr| { + try ptr.elem_ty.writeTypePrefix(w, zcu); + switch (ptr.elem_ty.kind()) { + .pointer, .postfix_op => {}, + .specifier => { + // We want "foo *" or "foo const *" rather than "foo*" or "fooconst *". + try w.writeByte(' '); + }, + } + if (ptr.@"const") try w.writeAll("const "); + if (ptr.@"volatile") try w.writeAll("volatile "); + switch (ptr.elem_ty.kind()) { + .specifier, .pointer => {}, + .postfix_op => { + // Prefix "*" is lower precedence than postfix "(x)" or "[x]" so use parens + // to disambiguate; e.g. "void (*foo)(int)" instead of "void *foo(int)". + try w.writeByte('('); + }, + } + try w.writeByte('*'); + }, + + .array => |array| { + try array.elem_ty.writeTypePrefix(w, zcu); + switch (array.elem_ty.kind()) { + .pointer, .postfix_op => {}, + .specifier => { + // We want e.g. "struct foo [5]" rather than "struct foo[5]". + try w.writeByte(' '); + }, + } + }, + + .function => |function| { + try function.ret_ty.writeTypePrefix(w, zcu); + switch (function.ret_ty.kind()) { + .pointer, .postfix_op => {}, + .specifier => { + // We want e.g. "struct foo (void)" rather than "struct foo(void)". + try w.writeByte(' '); + }, + } + }, + } + } + fn writeTypeSuffix(cty: CType, w: *Writer, zcu: *const Zcu) Writer.Error!void { + switch (cty) { + // simple type specifiers + .void, + .bool, + .int, + .float, + .@"fn", + .@"enum", + .bitpack, + .@"struct", + .union_auto, + .union_extern, + .slice, + .opt, + .arr, + .vec, + .errunion, + .aligned, + .bigint, + => {}, + + .pointer => |ptr| { + // Match opening paren "(" write `writeTypePrefix`. + switch (ptr.elem_ty.kind()) { + .specifier, .pointer => {}, + .postfix_op => try w.writeByte(')'), + } + try ptr.elem_ty.writeTypeSuffix(w, zcu); + }, + + .array => |array| { + try w.print("[{d}]", .{array.len}); + try array.elem_ty.writeTypeSuffix(w, zcu); + }, + + .function => |function| { + if (function.param_tys.len == 0 and !function.varargs) { + try w.writeAll("(void)"); + } else { + try w.writeByte('('); + for (function.param_tys, 0..) |param_ty, param_index| { + if (param_index > 0) try w.writeAll(", "); + try param_ty.writeTypePrefix(w, zcu); + try param_ty.writeTypeSuffix(w, zcu); + } + if (function.varargs) { + if (function.param_tys.len > 0) try w.writeAll(", "); + try w.writeAll("..."); + } + try w.writeByte(')'); + } + try function.ret_ty.writeTypeSuffix(w, zcu); + }, + } + } + + /// Renders Zig types using only bytes allowed in C identifiers in a somewhat-understandable + /// way. The output is *not* guaranteed to be unique. + fn fmtZigType(ty: Type, zcu: *const Zcu) FormatZigType { + return .{ .ty = ty, .zcu = zcu }; + } + const FormatZigType = struct { + ty: Type, + zcu: *const Zcu, + pub fn format(ctx: FormatZigType, w: *Writer) Writer.Error!void { + const ty = ctx.ty; + const zcu = ctx.zcu; + const ip = &zcu.intern_pool; + switch (ty.zigTypeTag(zcu)) { + .frame => unreachable, + .@"anyframe" => unreachable, + + .type => try w.writeAll("type"), + .void => try w.writeAll("void"), + .bool => try w.writeAll("bool"), + .noreturn => try w.writeAll("noreturn"), + .comptime_int => try w.writeAll("comptime_int"), + .comptime_float => try w.writeAll("comptime_float"), + .enum_literal => try w.writeAll("enum_literal"), + .undefined => try w.writeAll("undefined"), + .null => try w.writeAll("null"), + + .int => switch (ty.toIntern()) { + .usize_type => try w.writeAll("usize"), + .isize_type => try w.writeAll("isize"), + .c_char_type => try w.writeAll("c_char"), + .c_short_type => try w.writeAll("c_short"), + .c_ushort_type => try w.writeAll("c_ushort"), + .c_int_type => try w.writeAll("c_int"), + .c_uint_type => try w.writeAll("c_uint"), + .c_long_type => try w.writeAll("c_long"), + .c_ulong_type => try w.writeAll("c_ulong"), + .c_longlong_type => try w.writeAll("c_longlong"), + .c_ulonglong_type => try w.writeAll("c_ulonglong"), + else => { + const info = ty.intInfo(zcu); + switch (info.signedness) { + .unsigned => try w.print("u{d}", .{info.bits}), + .signed => try w.print("i{d}", .{info.bits}), + } + }, + }, + .float => switch (ty.toIntern()) { + .c_longdouble_type => try w.writeAll("c_longdouble"), + .f16_type => try w.writeAll("f16"), + .f32_type => try w.writeAll("f32"), + .f64_type => try w.writeAll("f64"), + .f80_type => try w.writeAll("f80"), + .f128_type => try w.writeAll("f128"), + else => unreachable, + }, + .error_set => switch (ty.toIntern()) { + .anyerror_type => try w.writeAll("anyerror"), + else => try w.print("error_{d}", .{@intFromEnum(ty.toIntern())}), + }, + .optional => try w.print("opt_{f}", .{fmtZigType(ty.optionalChild(zcu), zcu)}), + .error_union => try w.print("errunion_{f}", .{fmtZigType(ty.errorUnionPayload(zcu), zcu)}), + + .pointer => switch (ty.ptrSize(zcu)) { + .one, .many, .c => try w.print("ptr_{f}", .{fmtZigType(ty.childType(zcu), zcu)}), + .slice => try w.print("slice_{f}", .{fmtZigType(ty.childType(zcu), zcu)}), + }, + .@"fn" => { + const func_type = ip.indexToKey(ty.toIntern()).func_type; + try w.writeAll("fn_"); // intentional double underscore to start + for (func_type.param_types.get(ip)) |param_ty_ip| { + const param_ty: Type = .fromInterned(param_ty_ip); + try w.print("_P{f}", .{fmtZigType(param_ty, zcu)}); + } + if (func_type.is_var_args) { + try w.writeAll("_VA"); + } + const ret_ty: Type = .fromInterned(func_type.return_type); + try w.print("_R{f}", .{fmtZigType(ret_ty, zcu)}); + }, + + .vector => try w.print("vec_{d}_{f}", .{ + ty.arrayLen(zcu), + fmtZigType(ty.childType(zcu), zcu), + }), + + .array => if (ty.sentinel(zcu)) |s| try w.print("arr_{d}s{d}_{f}", .{ + ty.arrayLen(zcu), + @intFromEnum(s.toIntern()), + fmtZigType(ty.childType(zcu), zcu), + }) else try w.print("arr_{d}_{f}", .{ + ty.arrayLen(zcu), + fmtZigType(ty.childType(zcu), zcu), + }), + + .@"struct" => if (ty.isTuple(zcu)) { + const len = ty.structFieldCount(zcu); + try w.print("tuple_{d}", .{len}); + for (0..len) |field_index| { + const field_ty = ty.fieldType(field_index, zcu); + try w.print("_{f}", .{fmtZigType(field_ty, zcu)}); + } + } else { + const name = ty.containerTypeName(ip).toSlice(ip); + try w.print("{f}", .{@import("../c.zig").fmtIdentUnsolo(name)}); + }, + .@"opaque" => if (ty.toIntern() == .anyopaque_type) { + try w.writeAll("anyopaque"); + } else { + const name = ty.containerTypeName(ip).toSlice(ip); + try w.print("{f}", .{@import("../c.zig").fmtIdentUnsolo(name)}); + }, + .@"union", .@"enum" => { + const name = ty.containerTypeName(ip).toSlice(ip); + try w.print("{f}", .{@import("../c.zig").fmtIdentUnsolo(name)}); + }, + } + } + }; + + /// Returns `true` if the layout of `ty` is known without any type resolution required. This + /// allows some types to be lowered directly where 'typedef' would otherwise be necessary. + fn alwaysHasLayout(ty: Type, ip: *const InternPool) bool { + return switch (ip.indexToKey(ty.toIntern())) { + .int_type, + .ptr_type, + .anyframe_type, + .simple_type, + .opaque_type, + .error_set_type, + .inferred_error_set_type, + => true, + + .struct_type, + .union_type, + .enum_type, + => false, + + .array_type => |arr| alwaysHasLayout(.fromInterned(arr.child), ip), + .vector_type => |vec| alwaysHasLayout(.fromInterned(vec.child), ip), + .opt_type => |child| alwaysHasLayout(.fromInterned(child), ip), + .error_union_type => |eu| alwaysHasLayout(.fromInterned(eu.payload_type), ip), + + .tuple_type => |tuple| for (tuple.types.get(ip)) |field_ty| { + if (!alwaysHasLayout(.fromInterned(field_ty), ip)) break false; + } else true, + + .func_type => |f| for (f.param_types.get(ip)) |param_ty| { + if (!alwaysHasLayout(.fromInterned(param_ty), ip)) break false; + } else alwaysHasLayout(.fromInterned(f.return_type), ip), + + // values, not types + .undef, + .simple_value, + .variable, + .@"extern", + .func, + .int, + .err, + .error_union, + .enum_literal, + .enum_tag, + .float, + .ptr, + .slice, + .opt, + .aggregate, + .un, + .bitpack, + // memoization, not types + .memoized_call, + => unreachable, + }; + } +}; + +const Zcu = @import("../../Zcu.zig"); +const Type = @import("../../Type.zig"); +const Value = @import("../../Value.zig"); +const InternPool = @import("../../InternPool.zig"); + +const std = @import("std"); +const assert = std.debug.assert; +const Allocator = std.mem.Allocator; +const Writer = std.Io.Writer; diff --git a/src/codegen/c/type/render_defs.zig b/src/codegen/c/type/render_defs.zig new file mode 100644 index 0000000000000000000000000000000000000000..a34b0d6d3ce720663b63202e7e4260243f9bbb0f --- /dev/null +++ b/src/codegen/c/type/render_defs.zig @@ -0,0 +1,651 @@ +/// Renders the `typedef` for an aligned type. +pub fn defineAligned( + ty: Type, + alignment: Alignment, + complete: bool, + deps: *CType.Dependencies, + arena: Allocator, + w: *Writer, + pt: Zcu.PerThread, +) (Allocator.Error || Writer.Error)!void { + const zcu = pt.zcu; + + const name_cty: CType = .{ .aligned = .{ + .ty = ty, + .alignment = alignment, + } }; + + const cty: CType = try .lower(ty, deps, arena, zcu); + + try w.writeAll("typedef "); + if (complete and alignment.compareStrict(.lt, ty.abiAlignment(zcu))) { + try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?}); + } + try w.print("{f}{f}{f}; /* align({d}) {f} */\n", .{ + cty.fmtDeclaratorPrefix(zcu), + name_cty.fmtTypeName(zcu), + cty.fmtDeclaratorSuffix(zcu), + alignment.toByteUnits().?, + ty.fmt(pt), + }); +} +/// Renders the definition of a big-int `struct`. +pub fn defineBigInt(big: CType.BigInt, w: *Writer, zcu: *const Zcu) Writer.Error!void { + const name_cty: CType = .{ .bigint = .{ + .limb_size = big.limb_size, + .limbs_len = big.limbs_len, + } }; + const limb_cty: CType = .{ .int = big.limb_size.unsigned() }; + const array_cty: CType = .{ .array = .{ + .len = big.limbs_len, + .elem_ty = &limb_cty, + .nonstring = limb_cty.isStringElem(), + } }; + try w.print("{f} {{ {f}limbs{f}; }}; /* {d} bits */\n", .{ + name_cty.fmtTypeName(zcu), + array_cty.fmtDeclaratorPrefix(zcu), + array_cty.fmtDeclaratorSuffix(zcu), + big.limb_size.bits() * @as(u17, big.limbs_len), + }); +} + +/// Renders a forward declaration of the `struct` which represents an error union whose payload type +/// is `payload_ty` (the error set type is unspecified). +pub fn errunionFwdDecl(payload_ty: Type, w: *Writer, zcu: *const Zcu) Writer.Error!void { + const name_cty: CType = .{ .errunion = .{ + .payload_ty = payload_ty, + } }; + try w.print("{f};\n", .{name_cty.fmtTypeName(zcu)}); +} +/// Renders the definition of the `struct` which represents an error union whose payload type is +/// `payload_ty` (the error set type is unspecified). +/// +/// Asserts that the layout of `payload_ty` is resolved. +pub fn errunionDefineComplete( + payload_ty: Type, + deps: *CType.Dependencies, + arena: Allocator, + w: *Writer, + pt: Zcu.PerThread, +) (Allocator.Error || Writer.Error)!void { + const zcu = pt.zcu; + + payload_ty.assertHasLayout(zcu); + + const name_cty: CType = .{ .errunion = .{ + .payload_ty = payload_ty, + } }; + + const error_cty: CType = try .lower(.anyerror, deps, arena, zcu); + + if (payload_ty.hasRuntimeBits(zcu)) { + const payload_cty: CType = try .lower(payload_ty, deps, arena, zcu); + try w.print( + \\{f} {{ /* anyerror!{f} */ + \\ {f}payload{f}; + \\ {f}error{f}; + \\}}; + \\ + , .{ + name_cty.fmtTypeName(zcu), + payload_ty.fmt(pt), + payload_cty.fmtDeclaratorPrefix(zcu), + payload_cty.fmtDeclaratorSuffix(zcu), + error_cty.fmtDeclaratorPrefix(zcu), + error_cty.fmtDeclaratorSuffix(zcu), + }); + } else { + try w.print("{f} {{ {f}error{f}; }}; /* anyerror!{f} */\n", .{ + name_cty.fmtTypeName(zcu), + error_cty.fmtDeclaratorPrefix(zcu), + error_cty.fmtDeclaratorSuffix(zcu), + payload_ty.fmt(pt), + }); + } +} + +/// If the Zig type `ty` lowers to a `struct` or `union` type, renders a forward declaration of that +/// type. Does not write anything for error union types, because their forward declarations are +/// instead rendered by `errunionFwdDecl`. +pub fn fwdDecl(ty: Type, w: *Writer, zcu: *const Zcu) Writer.Error!void { + const name_cty: CType = switch (ty.zigTypeTag(zcu)) { + .@"struct" => switch (ty.containerLayout(zcu)) { + .auto, .@"extern" => .{ .@"struct" = ty }, + .@"packed" => return, + }, + .@"union" => switch (ty.containerLayout(zcu)) { + .auto => .{ .union_auto = ty }, + .@"extern" => .{ .union_extern = ty }, + .@"packed" => return, + }, + .pointer => if (ty.isSlice(zcu)) .{ .slice = ty } else return, + .optional => .{ .opt = ty }, + .array => .{ .arr = ty }, + .vector => .{ .vec = ty }, + else => return, + }; + try w.print("{f};\n", .{name_cty.fmtTypeName(zcu)}); +} + +/// If the Zig type `ty` lowers to a `typedef`, renders a typedef of that type to `void`, because +/// the type's layout is not resolved. This is only necessary for `typedef`s because a `struct` or +/// `union` which is never defined is already an incomplete type, just like `void`. +pub fn defineIncomplete(ty: Type, w: *Writer, pt: Zcu.PerThread) Writer.Error!void { + const zcu = pt.zcu; + const name_cty: CType = switch (ty.zigTypeTag(zcu)) { + .@"fn" => .{ .@"fn" = ty }, + .@"enum" => .{ .@"enum" = ty }, + .@"struct", .@"union" => switch (ty.containerLayout(zcu)) { + .auto, .@"extern" => return, + .@"packed" => .{ .bitpack = ty }, + }, + else => return, + }; + try w.print("typedef void {f}; /* {f} */\n", .{ + name_cty.fmtTypeName(zcu), + ty.fmt(pt), + }); +} + +/// If the Zig type `ty` lowers to a `struct` or `union` type, or to a `typedef`, renders the +/// definition of that type. Does not write anything for error union types, because their +/// definitions are instead rendered by `errunionDefine`. +/// +/// Asserts that the layout of `ty` is resolved. +pub fn defineComplete( + ty: Type, + deps: *CType.Dependencies, + arena: Allocator, + w: *Writer, + pt: Zcu.PerThread, +) (Allocator.Error || Writer.Error)!void { + const zcu = pt.zcu; + + ty.assertHasLayout(zcu); + + switch (ty.zigTypeTag(zcu)) { + .@"fn" => if (!ty.fnHasRuntimeBits(zcu)) { + const name_cty: CType = .{ .@"fn" = ty }; + try w.print("typedef void {f}; /* {f} */\n", .{ + name_cty.fmtTypeName(zcu), + ty.fmt(pt), + }); + } else { + const ip = &zcu.intern_pool; + const func_type = ip.indexToKey(ty.toIntern()).func_type; + + // While incomplete types are usually an acceptable substitute for "void", this is not + // true in function return types, where "void" is the only incomplete type permitted. + const actual_ret_ty: Type = .fromInterned(func_type.return_type); + const effective_ret_ty: Type = switch (actual_ret_ty.classify(zcu)) { + .no_possible_value => .noreturn, + .one_possible_value, .fully_comptime => .void, // no runtime bits + .partially_comptime, .runtime => actual_ret_ty, // yes runtime bits + }; + + const name_cty: CType = .{ .@"fn" = ty }; + const ret_cty: CType = try .lower(effective_ret_ty, deps, arena, zcu); + + try w.print("typedef {f}{f}(", .{ + ret_cty.fmtDeclaratorPrefix(zcu), + name_cty.fmtTypeName(zcu), + }); + var any_params = false; + for (func_type.param_types.get(ip)) |param_ty_ip| { + const param_ty: Type = .fromInterned(param_ty_ip); + if (!param_ty.hasRuntimeBits(zcu)) continue; + if (any_params) try w.writeAll(", "); + any_params = true; + const param_cty: CType = try .lower(param_ty, deps, arena, zcu); + try w.print("{f}", .{param_cty.fmtTypeName(zcu)}); + } + if (func_type.is_var_args) { + if (any_params) try w.writeAll(", "); + try w.writeAll("..."); + } else if (!any_params) { + try w.writeAll("void"); + } + try w.print("){f}; /* {f} */\n", .{ + ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu), + ty.fmt(pt), + }); + }, + .@"enum" => { + const name_cty: CType = .{ .@"enum" = ty }; + const cty: CType = try .lower(ty.intTagType(zcu), deps, arena, zcu); + try w.print("typedef {f}{f}{f}; /* {f} */\n", .{ + cty.fmtDeclaratorPrefix(zcu), + name_cty.fmtTypeName(zcu), + cty.fmtDeclaratorSuffix(zcu), + ty.fmt(pt), + }); + }, + .@"struct" => if (ty.isTuple(zcu)) { + try defineTuple(ty, deps, arena, w, pt); + } else switch (ty.containerLayout(zcu)) { + .auto, .@"extern" => try defineStruct(ty, deps, arena, w, pt), + .@"packed" => try defineBitpack(ty, deps, arena, w, pt), + }, + .@"union" => switch (ty.containerLayout(zcu)) { + .auto => try defineUnionAuto(ty, deps, arena, w, pt), + .@"extern" => try defineUnionExtern(ty, deps, arena, w, pt), + .@"packed" => try defineBitpack(ty, deps, arena, w, pt), + }, + .pointer => if (ty.isSlice(zcu)) { + const name_cty: CType = .{ .slice = ty }; + const ptr_cty: CType = try .lower(ty.slicePtrFieldType(zcu), deps, arena, zcu); + try w.print( + \\{f} {{ /* {f} */ + \\ {f}ptr{f}; + \\ size_t len; + \\}}; + \\ + , .{ + name_cty.fmtTypeName(zcu), + ty.fmt(pt), + ptr_cty.fmtDeclaratorPrefix(zcu), + ptr_cty.fmtDeclaratorSuffix(zcu), + }); + }, + .optional => switch (CType.classifyOptional(ty, zcu)) { + .error_set, + .ptr_like, + .slice_like, + .npv_payload, + => {}, + + .opv_payload => { + const name_cty: CType = .{ .opt = ty }; + try w.print("{f} {{ bool is_null; }}; /* {f} */\n", .{ + name_cty.fmtTypeName(zcu), + ty.fmt(pt), + }); + }, + + .@"struct" => { + const name_cty: CType = .{ .opt = ty }; + const payload_cty: CType = try .lower(ty.optionalChild(zcu), deps, arena, zcu); + try w.print( + \\{f} {{ /* {f} */ + \\ {f}payload{f}; + \\ bool is_null; + \\}}; + \\ + , .{ + name_cty.fmtTypeName(zcu), + ty.fmt(pt), + payload_cty.fmtDeclaratorPrefix(zcu), + payload_cty.fmtDeclaratorSuffix(zcu), + }); + }, + }, + .array => if (ty.hasRuntimeBits(zcu)) { + const name_cty: CType = .{ .arr = ty }; + const elem_cty: CType = try .lower(ty.childType(zcu), deps, arena, zcu); + const array_cty: CType = .{ .array = .{ + .len = ty.arrayLenIncludingSentinel(zcu), + .elem_ty = &elem_cty, + .nonstring = nonstring: { + if (!elem_cty.isStringElem()) break :nonstring false; + const s = ty.sentinel(zcu) orelse break :nonstring true; + break :nonstring Value.compareHetero(s, .neq, .zero_comptime_int, zcu); + }, + } }; + try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{ + name_cty.fmtTypeName(zcu), + array_cty.fmtDeclaratorPrefix(zcu), + array_cty.fmtDeclaratorSuffix(zcu), + ty.fmt(pt), + }); + }, + .vector => if (ty.hasRuntimeBits(zcu)) { + const name_cty: CType = .{ .vec = ty }; + const elem_cty: CType = try .lower(ty.childType(zcu), deps, arena, zcu); + const array_cty: CType = .{ .array = .{ + .len = ty.arrayLenIncludingSentinel(zcu), + .elem_ty = &elem_cty, + .nonstring = elem_cty.isStringElem(), + } }; + try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{ + name_cty.fmtTypeName(zcu), + array_cty.fmtDeclaratorPrefix(zcu), + array_cty.fmtDeclaratorSuffix(zcu), + ty.fmt(pt), + }); + }, + else => {}, + } +} +fn defineBitpack( + ty: Type, + deps: *CType.Dependencies, + arena: Allocator, + w: *Writer, + pt: Zcu.PerThread, +) (Allocator.Error || Writer.Error)!void { + const zcu = pt.zcu; + const name_cty: CType = .{ .bitpack = ty }; + const cty: CType = try .lower(ty.bitpackBackingInt(zcu), deps, arena, zcu); + try w.print("typedef {f}{f}{f}; /* {f} */\n", .{ + cty.fmtDeclaratorPrefix(zcu), + name_cty.fmtTypeName(zcu), + cty.fmtDeclaratorSuffix(zcu), + ty.fmt(pt), + }); +} +fn defineTuple( + ty: Type, + deps: *CType.Dependencies, + arena: Allocator, + w: *Writer, + pt: Zcu.PerThread, +) (Allocator.Error || Writer.Error)!void { + const zcu = pt.zcu; + if (!ty.hasRuntimeBits(zcu)) return; + const ip = &zcu.intern_pool; + const tuple = ip.indexToKey(ty.toIntern()).tuple_type; + + // Fields cannot be underaligned, because tuple fields cannot have specified alignments. + // However, overaligned fields are possible thanks to intermediate zero-bit fields. + + const tuple_align = ty.abiAlignment(zcu); + + // If the alignment of other fields would not give the tuple sufficient alignment, we + // need to align the first field (which does not affect its offset, because 0 is always + // well-aligned) to indirectly specify the tuple alignment. + const overalign: bool = for (tuple.types.get(ip)) |field_ty_ip| { + const field_ty: Type = .fromInterned(field_ty_ip); + if (!field_ty.hasRuntimeBits(zcu)) continue; + const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu); + if (natural_align.compareStrict(.gte, tuple_align)) break false; + } else true; + + const name_cty: CType = .{ .@"struct" = ty }; + try w.print("{f} {{ /* {f} */\n", .{ + name_cty.fmtTypeName(zcu), + ty.fmt(pt), + }); + var zig_offset: u64 = 0; + var c_offset: u64 = 0; + for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty_ip, field_val_ip, field_index| { + if (field_val_ip != .none) continue; // `comptime` field + const field_ty: Type = .fromInterned(field_ty_ip); + const field_align = field_ty.abiAlignment(zcu); + zig_offset = field_align.forward(zig_offset); + if (!field_ty.hasRuntimeBits(zcu)) continue; + c_offset = field_align.forward(c_offset); + if (zig_offset == 0 and overalign) { + // This is the first field; specify its alignment to align the tuple. + try w.print(" zig_align({d})", .{tuple_align.toByteUnits().?}); + } else if (zig_offset > c_offset) { + // This field needs to be overaligned compared to what its offset would otherwise be. + const need_align: Alignment = .fromLog2Units(@ctz(zig_offset)); + try w.print(" zig_align({d})", .{need_align.toByteUnits().?}); + c_offset = need_align.forward(c_offset); + assert(c_offset == zig_offset); + } + const field_cty: CType = try .lower(field_ty, deps, arena, zcu); + try w.print(" {f}f{d}{f};\n", .{ + field_cty.fmtDeclaratorPrefix(zcu), + field_index, + field_cty.fmtDeclaratorSuffix(zcu), + }); + const field_size = field_ty.abiSize(zcu); + zig_offset += field_size; + c_offset += field_size; + } + try w.writeAll("};\n"); +} +fn defineStruct( + ty: Type, + deps: *CType.Dependencies, + arena: Allocator, + w: *Writer, + pt: Zcu.PerThread, +) (Allocator.Error || Writer.Error)!void { + const zcu = pt.zcu; + if (!ty.hasRuntimeBits(zcu)) return; + const ip = &zcu.intern_pool; + + const struct_type = ip.loadStructType(ty.toIntern()); + + // If there are any underaligned fields, we need to byte-pack the struct. + const pack: bool = pack: { + var it = struct_type.iterateRuntimeOrder(ip); + var offset: u64 = 0; + while (it.next()) |field_index| { + const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); + if (!field_ty.hasRuntimeBits(zcu)) continue; + const natural_align = field_ty.defaultStructFieldAlignment(struct_type.layout, zcu); + const natural_offset = natural_align.forward(offset); + const actual_offset = struct_type.field_offsets.get(ip)[field_index]; + if (actual_offset < natural_offset) break :pack true; + offset = actual_offset + field_ty.abiSize(zcu); + } + break :pack false; + }; + + // If the alignment of other fields would not give the struct sufficient alignment, we + // need to align the first field (which does not affect its offset, because 0 is always + // well-aligned) to indirectly specify the struct alignment. + const overalign: bool = switch (pack) { + true => struct_type.alignment.compareStrict(.gt, .@"1"), + false => overalign: { + var it = struct_type.iterateRuntimeOrder(ip); + while (it.next()) |field_index| { + const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); + if (!field_ty.hasRuntimeBits(zcu)) continue; + const natural_align = field_ty.defaultStructFieldAlignment(struct_type.layout, zcu); + if (natural_align.compareStrict(.gte, struct_type.alignment)) break :overalign false; + } + break :overalign true; + }, + }; + + if (pack) try w.writeAll("zig_packed("); + const name_cty: CType = .{ .@"struct" = ty }; + try w.print("{f} {{ /* {f} */\n", .{ + name_cty.fmtTypeName(zcu), + ty.fmt(pt), + }); + var it = struct_type.iterateRuntimeOrder(ip); + var offset: u64 = 0; + while (it.next()) |field_index| { + const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); + if (!field_ty.hasRuntimeBits(zcu)) continue; + const natural_align = field_ty.defaultStructFieldAlignment(struct_type.layout, zcu); + const natural_offset = switch (pack) { + true => offset, + false => natural_align.forward(offset), + }; + const actual_offset = struct_type.field_offsets.get(ip)[field_index]; + if (actual_offset == 0 and overalign) { + // This is the first field; specify its alignment to align the struct. + try w.print(" zig_align({d})", .{struct_type.alignment.toByteUnits().?}); + } else if (actual_offset > natural_offset) { + // This field needs to be underaligned or overaligned compared to what its + // offset would otherwise be. + const need_align: Alignment = .fromLog2Units(@ctz(actual_offset)); + if (need_align.compareStrict(.lt, natural_align)) { + try w.print(" zig_under_align({d})", .{need_align.toByteUnits().?}); + } else { + try w.print(" zig_align({d})", .{need_align.toByteUnits().?}); + } + } + const field_cty: CType = try .lower(field_ty, deps, arena, zcu); + const field_name = struct_type.field_names.get(ip)[field_index].toSlice(ip); + try w.print(" {f}{f}{f};\n", .{ + field_cty.fmtDeclaratorPrefix(zcu), + fmtIdentSolo(field_name), + field_cty.fmtDeclaratorSuffix(zcu), + }); + offset = actual_offset + field_ty.abiSize(zcu); + } + assert(struct_type.alignment.forward(offset) == struct_type.size); + try w.writeByte('}'); + if (pack) try w.writeByte(')'); + try w.writeAll(";\n"); +} +fn defineUnionAuto( + ty: Type, + deps: *CType.Dependencies, + arena: Allocator, + w: *Writer, + pt: Zcu.PerThread, +) (Allocator.Error || Writer.Error)!void { + const zcu = pt.zcu; + if (!ty.hasRuntimeBits(zcu)) return; + const ip = &zcu.intern_pool; + + const union_type = ip.loadUnionType(ty.toIntern()); + const enum_tag_ty: Type = .fromInterned(union_type.enum_tag_type); + + // If there are any underaligned fields, we need to byte-pack the union. + const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| { + const field_ty: Type = .fromInterned(field_ty_ip); + if (!field_ty.hasRuntimeBits(zcu)) continue; + const natural_align = field_ty.abiAlignment(zcu); + if (natural_align.compareStrict(.gt, union_type.alignment)) break true; + } else false; + + // If the alignment of other fields would not give the union sufficient alignment, we + // need to align the first field (which does not affect its offset, because 0 is always + // well-aligned) to indirectly specify the union alignment. + const overalign: bool = switch (pack) { + true => union_type.alignment.compareStrict(.gt, .@"1"), + false => for (union_type.field_types.get(ip)) |field_ty_ip| { + const field_ty: Type = .fromInterned(field_ty_ip); + if (!field_ty.hasRuntimeBits(zcu)) continue; + const natural_align = field_ty.abiAlignment(zcu); + if (natural_align.compareStrict(.gte, union_type.alignment)) break false; + } else overalign: { + if (union_type.has_runtime_tag) { + const tag_align = enum_tag_ty.abiAlignment(zcu); + if (tag_align.compareStrict(.gte, union_type.alignment)) break :overalign false; + } + break :overalign true; + }, + }; + + const payload_has_bits = !union_type.has_runtime_tag or union_type.size > enum_tag_ty.abiSize(zcu); + + const name_cty: CType = .{ .union_auto = ty }; + try w.print("{f} {{ /* {f} */\n", .{ + name_cty.fmtTypeName(zcu), + ty.fmt(pt), + }); + if (payload_has_bits) { + try w.writeByte(' '); + if (pack) try w.writeAll("zig_packed("); + try w.writeAll("union {\n"); + for (0..enum_tag_ty.enumFieldCount(zcu)) |field_index| { + const field_ty = ty.fieldType(field_index, zcu); + if (!field_ty.hasRuntimeBits(zcu)) continue; + const field_name = enum_tag_ty.enumFieldName(field_index, zcu).toSlice(ip); + const field_cty: CType = try .lower(field_ty, deps, arena, zcu); + try w.writeAll(" "); + if (overalign and field_index == 0) { + // This is the first field; specify its alignment to align the union. + try w.print("zig_align({d}) ", .{union_type.alignment.toByteUnits().?}); + } + try w.print("{f}{f}{f};\n", .{ + field_cty.fmtDeclaratorPrefix(zcu), + fmtIdentSolo(field_name), + field_cty.fmtDeclaratorSuffix(zcu), + }); + } + try w.writeAll(" }"); + if (pack) try w.writeByte(')'); + try w.writeAll(" payload;\n"); + } + if (union_type.has_runtime_tag) { + const tag_cty: CType = try .lower(enum_tag_ty, deps, arena, zcu); + try w.print(" {f}tag{f};\n", .{ + tag_cty.fmtDeclaratorPrefix(zcu), + tag_cty.fmtDeclaratorSuffix(zcu), + }); + } + try w.writeAll("};\n"); +} +fn defineUnionExtern( + ty: Type, + deps: *CType.Dependencies, + arena: Allocator, + w: *Writer, + pt: Zcu.PerThread, +) (Allocator.Error || Writer.Error)!void { + const zcu = pt.zcu; + if (!ty.hasRuntimeBits(zcu)) return; + const ip = &zcu.intern_pool; + + const union_type = ip.loadUnionType(ty.toIntern()); + assert(!union_type.has_runtime_tag); + const enum_tag_ty: Type = .fromInterned(union_type.enum_tag_type); + + // If there are any underaligned fields, we need to byte-pack the union. + const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| { + const field_ty: Type = .fromInterned(field_ty_ip); + if (!field_ty.hasRuntimeBits(zcu)) continue; + const natural_align = field_ty.abiAlignment(zcu); + if (natural_align.compareStrict(.gt, union_type.alignment)) break true; + } else false; + + // If the alignment of other fields would not give the union sufficient alignment, we + // need to align the first field (which does not affect its offset, because 0 is always + // well-aligned) to indirectly specify the union alignment. + const overalign: bool = switch (pack) { + true => union_type.alignment.compareStrict(.gt, .@"1"), + false => for (union_type.field_types.get(ip)) |field_ty_ip| { + const field_ty: Type = .fromInterned(field_ty_ip); + if (!field_ty.hasRuntimeBits(zcu)) continue; + const natural_align = field_ty.abiAlignment(zcu); + if (natural_align.compareStrict(.gte, union_type.alignment)) break false; + } else overalign: { + if (union_type.has_runtime_tag) { + const tag_align = enum_tag_ty.abiAlignment(zcu); + if (tag_align.compareStrict(.gte, union_type.alignment)) break :overalign false; + } + break :overalign true; + }, + }; + + if (pack) try w.writeAll("zig_packed("); + + const name_cty: CType = .{ .union_extern = ty }; + try w.print("{f} {{ /* {f} */\n", .{ + name_cty.fmtTypeName(zcu), + ty.fmt(pt), + }); + + for (0..enum_tag_ty.enumFieldCount(zcu)) |field_index| { + const field_ty = ty.fieldType(field_index, zcu); + if (!field_ty.hasRuntimeBits(zcu)) continue; + const field_name = enum_tag_ty.enumFieldName(field_index, zcu).toSlice(ip); + const field_cty: CType = try .lower(field_ty, deps, arena, zcu); + if (overalign and field_index == 0) { + // This is the first field; specify its alignment to align the union. + try w.print(" zig_align({d})", .{union_type.alignment.toByteUnits().?}); + } + try w.print(" {f}{f}{f};\n", .{ + field_cty.fmtDeclaratorPrefix(zcu), + fmtIdentSolo(field_name), + field_cty.fmtDeclaratorSuffix(zcu), + }); + } + try w.writeByte('}'); + if (pack) try w.writeByte(')'); + try w.writeAll(";\n"); +} + +const std = @import("std"); +const assert = std.debug.assert; +const Writer = std.Io.Writer; +const Allocator = std.mem.Allocator; + +const Zcu = @import("../../../Zcu.zig"); +const Type = @import("../../../Type.zig"); +const Value = @import("../../../Value.zig"); +const CType = @import("../type.zig").CType; +const Alignment = @import("../../../InternPool.zig").Alignment; + +const fmtIdentSolo = @import("../../c.zig").fmtIdentSolo; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 5735fe5e51a665a46e965cd3f01a26bdb57ac094..f8d1310b1c7693c8b2f46fb03debc802d7eba69b 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -23,7 +23,6 @@ const Package = @import("../Package.zig"); const Air = @import("../Air.zig"); const Value = @import("../Value.zig"); const Type = @import("../Type.zig"); -const DebugConstPool = link.DebugConstPool; const codegen = @import("../codegen.zig"); const x86_64_abi = @import("x86_64/abi.zig"); const wasm_c_abi = @import("wasm/abi.zig"); @@ -532,8 +531,8 @@ pub const Object = struct { debug_file_map: std.AutoHashMapUnmanaged(Zcu.File.Index, Builder.Metadata), /// This pool *only* contains types (and does not contain `@as(type, undefined)`). - debug_type_pool: DebugConstPool, - /// Keyed on `DebugConstPool.Index`. + debug_type_pool: link.ConstPool, + /// Keyed on `link.ConstPool.Index`. debug_types: std.ArrayList(Builder.Metadata), /// Initially `.none`, set if the type `anyerror` is lowered to a debug type. The type will not /// actually be created until `emit`, which must resolve this reference with an appropriate enum @@ -1622,10 +1621,7 @@ pub const Object = struct { } fn flushPendingDebugTypes(o: *Object, pt: Zcu.PerThread) Allocator.Error!void { - o.debug_type_pool.flushPending(pt, .{ .llvm = o }) catch |err| switch (err) { - error.OutOfMemory => |e| return e, - else => unreachable, // TODO: stop self-hosted backends from returning all of this crap! - }; + try o.debug_type_pool.flushPending(pt, .{ .llvm = o }); } pub fn updateExports( @@ -1823,17 +1819,14 @@ pub const Object = struct { pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Allocator.Error!void { if (!o.builder.strip) { - o.debug_type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success) catch |err| switch (err) { - error.OutOfMemory => |e| return e, - else => unreachable, // TODO: stop self-hosted backends from returning all of this crap! - }; + try o.debug_type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success); } } - /// Should only be called by the `DebugConstPool` implementation. + /// Should only be called by the `link.ConstPool` implementation. /// /// `val` is always a type because `o.debug_type_pool` only contains types. - pub fn addConst(o: *Object, pt: Zcu.PerThread, index: DebugConstPool.Index, val: InternPool.Index) Allocator.Error!void { + pub fn addConst(o: *Object, pt: Zcu.PerThread, index: link.ConstPool.Index, val: InternPool.Index) Allocator.Error!void { const zcu = pt.zcu; const gpa = zcu.comp.gpa; assert(zcu.intern_pool.typeOf(val) == .type_type); @@ -1846,10 +1839,10 @@ pub const Object = struct { o.debug_anyerror_fwd_ref = fwd_ref.toOptional(); } } - /// Should only be called by the `DebugConstPool` implementation. + /// Should only be called by the `link.ConstPool` implementation. /// /// `val` is always a type because `o.debug_type_pool` only contains types. - pub fn updateConstIncomplete(o: *Object, pt: Zcu.PerThread, index: DebugConstPool.Index, val: InternPool.Index) Allocator.Error!void { + pub fn updateConstIncomplete(o: *Object, pt: Zcu.PerThread, index: link.ConstPool.Index, val: InternPool.Index) Allocator.Error!void { assert(pt.zcu.intern_pool.typeOf(val) == .type_type); const fwd_ref = o.debug_types.items[@intFromEnum(index)]; assert(val != .anyerror_type); @@ -1857,10 +1850,10 @@ pub const Object = struct { const debug_incomplete_type = try o.builder.debugSignedType(name_str, 0); o.builder.resolveDebugForwardReference(fwd_ref, debug_incomplete_type); } - /// Should only be called by the `DebugConstPool` implementation. + /// Should only be called by the `link.ConstPool` implementation. /// /// `val` is always a type because `o.debug_type_pool` only contains types. - pub fn updateConst(o: *Object, pt: Zcu.PerThread, index: DebugConstPool.Index, val: InternPool.Index) Allocator.Error!void { + pub fn updateConst(o: *Object, pt: Zcu.PerThread, index: link.ConstPool.Index, val: InternPool.Index) Allocator.Error!void { assert(pt.zcu.intern_pool.typeOf(val) == .type_type); const fwd_ref = o.debug_types.items[@intFromEnum(index)]; if (val == .anyerror_type) { @@ -1890,10 +1883,7 @@ pub const Object = struct { fn getDebugType(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error!Builder.Metadata { assert(!o.builder.strip); - const index = o.debug_type_pool.get(pt, .{ .llvm = o }, ty.toIntern()) catch |err| switch (err) { - error.OutOfMemory => |e| return e, - else => unreachable, // TODO: stop self-hosted backends from returning all of this crap! - }; + const index = try o.debug_type_pool.get(pt, .{ .llvm = o }, ty.toIntern()); return o.debug_types.items[@intFromEnum(index)]; } diff --git a/src/link.zig b/src/link.zig index c81737484e6da4a0b437b2ab1ad93d76ab9ac02a..3eb4add772149d4a5e149ecf842156cde14d0849 100644 --- a/src/link.zig +++ b/src/link.zig @@ -29,7 +29,7 @@ const codegen = @import("codegen.zig"); pub const aarch64 = @import("link/aarch64.zig"); pub const LdScript = @import("link/LdScript.zig"); pub const Queue = @import("link/Queue.zig"); -pub const DebugConstPool = @import("link/DebugConstPool.zig"); +pub const ConstPool = @import("link/ConstPool.zig"); pub const Diags = struct { /// Stored here so that function definitions can distinguish between @@ -804,7 +804,7 @@ pub const File = struct { switch (base.tag) { .lld => unreachable, else => {}, - inline .elf => |tag| { + inline .elf, .c => |tag| { dev.check(tag.devFeature()); return @as(*tag.Type(), @fieldParentPtr("base", base)).updateContainerType(pt, ty, success); }, diff --git a/src/link/C.zig b/src/link/C.zig index 93e771ebfc3d01a61f7fb5268bd84fe8b639f489..3c71206cc70db582e6d1d462cb49bcb80e51da7b 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -1,3 +1,9 @@ +/// Unlike other linker implementations, `link.C` does not attempt to incrementally link its output, +/// because C has many language rules which make that impractical. Instead, we individually generate +/// each declaration (NAV), and the output is stitched together (alongside types and UAVs) in an +/// appropriate order in `flush`. +const C = @This(); + const std = @import("std"); const mem = std.mem; const assert = std.debug.assert; @@ -5,7 +11,6 @@ const Allocator = std.mem.Allocator; const fs = std.fs; const Path = std.Build.Cache.Path; -const C = @This(); const build_options = @import("build_options"); const Zcu = @import("../Zcu.zig"); const Module = @import("../Package/Module.zig"); @@ -19,40 +24,45 @@ const Type = @import("../Type.zig"); const Value = @import("../Value.zig"); const AnyMir = @import("../codegen.zig").AnyMir; -pub const zig_h = "#include \"zig.h\"\n"; - base: link.File, -/// This linker backend does not try to incrementally link output C source code. -/// Instead, it tracks all declarations in this table, and iterates over it -/// in the flush function, stitching pre-rendered pieces of C code together. -navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, AvBlock), -/// All the string bytes of rendered C code, all squished into one array. -/// While in progress, a separate buffer is used, and then when finished, the -/// buffer is copied into this one. + +/// All the string bytes of rendered C code, all squished into one array. `String` is used to refer +/// to specific slices of this array, used for the rendered C code of an individual UAV/NAV/type. +/// +/// During code generation for functions, a separate buffer is used, and the contents of that buffer +/// are copied into `string_bytes` when the function is emitted by `updateFunc`. string_bytes: std.ArrayList(u8), -/// Tracks all the anonymous decls that are used by all the decls so they can -/// be rendered during flush(). -uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, AvBlock), -/// Sparse set of uavs that are overaligned. Underaligned anon decls are -/// lowered the same as ABI-aligned anon decls. The keys here are a subset of -/// the keys of `uavs`. -aligned_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), -exported_navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, ExportedBlock), -exported_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, ExportedBlock), +/// Like with `string_bytes`, we concatenate all type dependencies into one array, and slice into it +/// for specific groups of dependencies. These values are indices into `type_pool`, and thus also +/// into `types`. We store these instead of `InternPool.Index` because it lets us avoid some hash +/// map lookups in `flush`. +type_dependencies: std.ArrayList(link.ConstPool.Index), +/// For storing dependencies on "aligned" versions of types, we must associate each type with a +/// bitmask of required alignments. As with `type_dependencies`, we concatenate all such masks into +/// one array. +align_dependency_masks: std.ArrayList(u64), -/// Optimization, `updateDecl` reuses this buffer rather than creating a new -/// one with every call. -fwd_decl_buf: []u8, -/// Optimization, `updateDecl` reuses this buffer rather than creating a new -/// one with every call. -code_header_buf: []u8, -/// Optimization, `updateDecl` reuses this buffer rather than creating a new -/// one with every call. -code_buf: []u8, -/// Optimization, `flush` reuses this buffer rather than creating a new -/// one with every call. -scratch_buf: []u32, +/// All NAVs, regardless of whether they are functions or simple constants, are put in this map. +navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, RenderedDecl), +/// All UAVs which may be referenced are in this map. The UAV alignment is not included in the +/// rendered C code stored here, because we don't know the alignment a UAV needs until `flush`. +uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, RenderedDecl), +/// Contains all types which are needed by some other rendered code. Does not contain any constants +/// other than types. +type_pool: link.ConstPool, +/// Indices are `link.ConstPool.Index` from `type_pool`. Contains rendered C code for every type +/// which may be referenced. Logic in `flush` will perform the appropriate topological sort to emit +/// these type definitions in an order which C allows. +types: std.ArrayList(RenderedType), + +/// The set of big int types required by *any* generated code so far. These are always safe to emit, +/// so they do not participate in the dependency graph traversal in `flush`. Therefore, redundant +/// big-int types may be emitted under incremental compilation. +bigint_types: std.AutoArrayHashMapUnmanaged(codegen.CType.BigInt, void), + +exported_navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, String), +exported_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, String), /// A reference into `string_bytes`. const String = extern struct { @@ -64,50 +74,320 @@ const String = extern struct { .len = 0, }; - fn concat(lhs: String, rhs: String) String { - assert(lhs.start + lhs.len == rhs.start); + fn get(s: String, c: *C) []const u8 { + return c.string_bytes.items[s.start..][0..s.len]; + } +}; + +const CTypeDependencies = struct { + len: u32, + errunion_len: u32, + fwd_len: u32, + errunion_fwd_len: u32, + aligned_fwd_len: u32, + + /// Index into `C.type_dependencies`. Starting at this index are: + /// * `len` dependencies on complete types + /// * `errunion_len` dependencies on complete error union types + /// * `fwd_len` dependencies on forward-declared types + /// * `errunion_fwd_len` dependencies on forward-declared error union types + /// * `aligned_fwd_len` dependencies on aligned types + type_start: u32, + /// Index into `C.align_dependency_masks`. Starting at this index are `aligned_type_fwd_len` + /// items containing the bitmasks for each aligned type (in `C.type_dependencies`). + align_mask_start: u32, + + const Resolved = struct { + type: []const link.ConstPool.Index, + errunion_type: []const link.ConstPool.Index, + type_fwd: []const link.ConstPool.Index, + errunion_type_fwd: []const link.ConstPool.Index, + aligned_type_fwd: []const link.ConstPool.Index, + aligned_type_masks: []const u64, + }; + + fn get(td: *const CTypeDependencies, c: *const C) Resolved { + const types_overlong = c.type_dependencies.items[td.type_start..]; return .{ - .start = lhs.start, - .len = lhs.len + rhs.len, + .type = types_overlong[0..td.len], + .errunion_type = types_overlong[td.len..][0..td.errunion_len], + .type_fwd = types_overlong[td.len + td.errunion_len ..][0..td.fwd_len], + .errunion_type_fwd = types_overlong[td.len + td.errunion_len + td.fwd_len ..][0..td.errunion_fwd_len], + .aligned_type_fwd = types_overlong[td.len + td.errunion_len + td.fwd_len + td.errunion_fwd_len ..][0..td.aligned_fwd_len], + .aligned_type_masks = c.align_dependency_masks.items[td.align_mask_start..][0..td.aligned_fwd_len], }; } + + const empty: CTypeDependencies = .{ + .len = 0, + .errunion_len = 0, + .fwd_len = 0, + .errunion_fwd_len = 0, + .aligned_fwd_len = 0, + .type_start = 0, + .align_mask_start = 0, + }; }; -/// Per-declaration data. -pub const AvBlock = struct { - fwd_decl: String = .empty, - code: String = .empty, - /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate - /// over each `Decl` and generate the definition for each used `CType` once. - ctype_pool: codegen.CType.Pool = .empty, - /// May contain string references to ctype_pool - lazy_fns: codegen.LazyFnMap = .{}, - - fn deinit(ab: *AvBlock, gpa: Allocator) void { - ab.lazy_fns.deinit(gpa); - ab.ctype_pool.deinit(gpa); - ab.* = undefined; +const RenderedDecl = struct { + fwd_decl: String, + code: String, + ctype_deps: CTypeDependencies, + need_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), + need_tag_name_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), + need_never_tail_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void), + need_never_inline_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void), + + const init: RenderedDecl = .{ + .fwd_decl = .empty, + .code = .empty, + .ctype_deps = .empty, + .need_uavs = .empty, + .need_tag_name_funcs = .empty, + .need_never_tail_funcs = .empty, + .need_never_inline_funcs = .empty, + }; + + fn deinit(rd: *RenderedDecl, gpa: Allocator) void { + rd.need_uavs.deinit(gpa); + rd.need_tag_name_funcs.deinit(gpa); + rd.need_never_tail_funcs.deinit(gpa); + rd.need_never_inline_funcs.deinit(gpa); + rd.* = undefined; + } + + /// We are about to re-render this declaration, but we want to reuse the existing buffers, so + /// call `clearRetainCapacity` on the containers. Sets `fwd_decl` and `code` to `undefined`, + /// because we shouldn't be using the old values any longer. + fn clearRetainingCapacity(rd: *RenderedDecl) void { + rd.fwd_decl = undefined; + rd.code = undefined; + rd.need_uavs.clearRetainingCapacity(); + rd.need_tag_name_funcs.clearRetainingCapacity(); + rd.need_never_tail_funcs.clearRetainingCapacity(); + rd.need_never_inline_funcs.clearRetainingCapacity(); } }; -/// Per-exported-symbol data. -pub const ExportedBlock = struct { - fwd_decl: String = .empty, +const RenderedType = struct { + /// If this type lowers to an aggregate, this is a forward declaration of its struct/union tag. + /// Otherwise, this is `.empty`. + /// + /// Populated immediately and never changes. + fwd_decl: String, + + /// A forward declaration of an error union type with this type as its *payload*. + /// + /// Populated immediately and never changes. + errunion_fwd_decl: String, + + /// If this type lowers to an aggregate, this is the struct/union definition. + /// If this type lowers to a typedef, this is that typedef. + /// Otherwise, this is `.empty`. + definition: String, + /// The `struct` definition for an error union type with this type as its *payload*. + /// + /// This string is empty iff the payload type does not have a resolved layout. If the layout is + /// resolved, the error union struct is defined, even if the payload type lacks runtime bits. + errunion_definition: String, + + /// Dependencies which must be satisfied before emitting the name of this type. As such, they + /// must be satisfied before emitting `errunion_definition` or any aligned typedef. + /// + /// Populated immediately and never changes. + deps: CTypeDependencies, + + /// Dependencies which must be satisfied before emitting `definition`. + definition_deps: CTypeDependencies, }; -pub fn getString(this: C, s: String) []const u8 { - return this.string_bytes.items[s.start..][0..s.len]; +/// Only called by `link.ConstPool` due to `c.type_pool`, so `val` is always a type. +pub fn addConst( + c: *C, + pt: Zcu.PerThread, + pool_index: link.ConstPool.Index, + val: InternPool.Index, +) Allocator.Error!void { + const zcu = pt.zcu; + const gpa = zcu.comp.gpa; + assert(zcu.intern_pool.typeOf(val) == .type_type); + assert(@intFromEnum(pool_index) == c.types.items.len); + + const ty: Type = .fromInterned(val); + + const fwd_decl: String = fwd_decl: { + var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); + defer c.string_bytes = aw.toArrayList(); + const start = aw.written().len; + codegen.CType.render_defs.fwdDecl(ty, &aw.writer, zcu) catch |err| switch (err) { + error.WriteFailed => return error.OutOfMemory, + }; + break :fwd_decl .{ + .start = @intCast(start), + .len = @intCast(aw.written().len - start), + }; + }; + + const errunion_fwd_decl: String = errunion_fwd_decl: { + var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); + defer c.string_bytes = aw.toArrayList(); + const start = aw.written().len; + codegen.CType.render_defs.errunionFwdDecl(ty, &aw.writer, zcu) catch |err| switch (err) { + error.WriteFailed => return error.OutOfMemory, + }; + break :errunion_fwd_decl .{ + .start = @intCast(start), + .len = @intCast(aw.written().len - start), + }; + }; + + try c.types.append(gpa, .{ + .fwd_decl = fwd_decl, + .errunion_fwd_decl = errunion_fwd_decl, + // This field will be populated just below. + .deps = undefined, + // The remaining fields will be populated later by either `updateConstIncomplete` or + // `updateConstComplete` (it is guaranteed that at least one will be called). + .definition = undefined, + .errunion_definition = undefined, + .definition_deps = undefined, + }); + + { + // Find the dependencies required to just render the type `ty`. + var arena: std.heap.ArenaAllocator = .init(gpa); + defer arena.deinit(); + var deps: codegen.CType.Dependencies = .empty; + defer deps.deinit(gpa); + _ = try codegen.CType.lower(ty, &deps, arena.allocator(), zcu); + // This call may add more items to `c.types`. + const type_deps = try c.addCTypeDependencies(pt, &deps); + c.types.items[@intFromEnum(pool_index)].deps = type_deps; + } } -pub fn addString(this: *C, s: []const u8) Allocator.Error!String { - const comp = this.base.comp; - const gpa = comp.gpa; - try this.string_bytes.appendSlice(gpa, s); - return .{ - .start = @intCast(this.string_bytes.items.len - s.len), - .len = @intCast(s.len), +/// Only called by `link.ConstPool` due to `c.type_pool`, so `val` is always a type. +pub fn updateConstIncomplete( + c: *C, + pt: Zcu.PerThread, + index: link.ConstPool.Index, + val: InternPool.Index, +) Allocator.Error!void { + const zcu = pt.zcu; + const gpa = zcu.comp.gpa; + + assert(zcu.intern_pool.typeOf(val) == .type_type); + const ty: Type = .fromInterned(val); + + const rendered: *RenderedType = &c.types.items[@intFromEnum(index)]; + + rendered.errunion_definition = .empty; + rendered.definition_deps = .empty; + rendered.definition = definition: { + if (rendered.fwd_decl.len != 0) { + // This is a struct or union type. We will never complete it, but we must forward + // declare it to ensure that its first usage does not appear in a different scope. + break :definition rendered.fwd_decl; + } + // Otherwise, we might need to `typedef` to `void`. + var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); + defer c.string_bytes = aw.toArrayList(); + const start = aw.written().len; + codegen.CType.render_defs.defineIncomplete(ty, &aw.writer, pt) catch |err| switch (err) { + error.WriteFailed => return error.OutOfMemory, + }; + break :definition .{ + .start = @intCast(start), + .len = @intCast(aw.written().len - start), + }; }; } +/// Only called by `link.ConstPool` due to `c.type_pool`, so `val` is always a type. +pub fn updateConst( + c: *C, + pt: Zcu.PerThread, + index: link.ConstPool.Index, + val: InternPool.Index, +) Allocator.Error!void { + const zcu = pt.zcu; + const gpa = zcu.comp.gpa; + + assert(zcu.intern_pool.typeOf(val) == .type_type); + const ty: Type = .fromInterned(val); + + const rendered: *RenderedType = &c.types.items[@intFromEnum(index)]; + + var arena: std.heap.ArenaAllocator = .init(gpa); + defer arena.deinit(); + + var deps: codegen.CType.Dependencies = .empty; + defer deps.deinit(gpa); + + { + var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); + defer c.string_bytes = aw.toArrayList(); + const start = aw.written().len; + codegen.CType.render_defs.errunionDefineComplete( + ty, + &deps, + arena.allocator(), + &aw.writer, + pt, + ) catch |err| switch (err) { + error.WriteFailed => return error.OutOfMemory, + error.OutOfMemory => |e| return e, + }; + rendered.errunion_definition = .{ + .start = @intCast(start), + .len = @intCast(aw.written().len - start), + }; + } + + deps.clearRetainingCapacity(); + + { + var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); + defer c.string_bytes = aw.toArrayList(); + const start = aw.written().len; + codegen.CType.render_defs.defineComplete( + ty, + &deps, + arena.allocator(), + &aw.writer, + pt, + ) catch |err| switch (err) { + error.WriteFailed => return error.OutOfMemory, + error.OutOfMemory => |e| return e, + }; + // Remove dependency on a forward declaration of ourselves; we're defining this type so that + // forward declaration obviously exists! + _ = deps.type_fwd.swapRemove(ty.toIntern()); + rendered.definition = .{ + .start = @intCast(start), + .len = @intCast(aw.written().len - start), + }; + } + + { + // This call invalidates `rendered`. + const definition_deps = try c.addCTypeDependencies(pt, &deps); + c.types.items[@intFromEnum(index)].definition_deps = definition_deps; + } +} + +fn addString(c: *C, vec: []const []const u8) Allocator.Error!String { + const gpa = c.base.comp.gpa; + + var len: u32 = 0; + for (vec) |s| len += @intCast(s.len); + try c.string_bytes.ensureUnusedCapacity(gpa, len); + + const start: u32 = @intCast(c.string_bytes.items.len); + for (vec) |s| c.string_bytes.appendSliceAssumeCapacity(s); + assert(c.string_bytes.items.len == start + len); + + return .{ .start = start, .len = len }; +} pub fn open( arena: Allocator, @@ -156,267 +436,622 @@ pub fn createEmpty( .file = file, .build_id = options.build_id, }, - .navs = .empty, .string_bytes = .empty, + .type_dependencies = .empty, + .align_dependency_masks = .empty, + .navs = .empty, .uavs = .empty, - .aligned_uavs = .empty, + .type_pool = .empty, + .types = .empty, + .bigint_types = .empty, .exported_navs = .empty, .exported_uavs = .empty, - .fwd_decl_buf = &.{}, - .code_header_buf = &.{}, - .code_buf = &.{}, - .scratch_buf = &.{}, }; return c_file; } -pub fn deinit(self: *C) void { - const gpa = self.base.comp.gpa; +pub fn deinit(c: *C) void { + const gpa = c.base.comp.gpa; - for (self.navs.values()) |*db| { - db.deinit(gpa); - } - self.navs.deinit(gpa); + for (c.navs.values()) |*r| r.deinit(gpa); + for (c.uavs.values()) |*r| r.deinit(gpa); - for (self.uavs.values()) |*db| { - db.deinit(gpa); - } - self.uavs.deinit(gpa); - self.aligned_uavs.deinit(gpa); + c.string_bytes.deinit(gpa); + c.type_dependencies.deinit(gpa); + c.align_dependency_masks.deinit(gpa); + c.navs.deinit(gpa); + c.uavs.deinit(gpa); + c.type_pool.deinit(gpa); + c.types.deinit(gpa); + c.bigint_types.deinit(gpa); + c.exported_navs.deinit(gpa); + c.exported_uavs.deinit(gpa); +} - self.exported_navs.deinit(gpa); - self.exported_uavs.deinit(gpa); - - self.string_bytes.deinit(gpa); - gpa.free(self.fwd_decl_buf); - gpa.free(self.code_header_buf); - gpa.free(self.code_buf); - gpa.free(self.scratch_buf); +pub fn updateContainerType( + c: *C, + pt: Zcu.PerThread, + ty: InternPool.Index, + success: bool, +) link.File.UpdateContainerTypeError!void { + try c.type_pool.updateContainerType(pt, .{ .c = c }, ty, success); } pub fn updateFunc( - self: *C, + c: *C, pt: Zcu.PerThread, func_index: InternPool.Index, mir: *AnyMir, -) link.File.UpdateNavError!void { +) Allocator.Error!void { const zcu = pt.zcu; const gpa = zcu.gpa; - const func = zcu.funcInfo(func_index); + const nav = zcu.funcInfo(func_index).owner_nav; - const gop = try self.navs.getOrPut(gpa, func.owner_nav); - if (gop.found_existing) gop.value_ptr.deinit(gpa); - gop.value_ptr.* = .{ - .code = .empty, - .fwd_decl = .empty, - .ctype_pool = mir.c.ctype_pool.move(), - .lazy_fns = mir.c.lazy_fns.move(), + const rendered_decl: *RenderedDecl = rd: { + const gop = try c.navs.getOrPut(gpa, nav); + if (gop.found_existing) gop.value_ptr.deinit(gpa); + break :rd gop.value_ptr; }; - gop.value_ptr.fwd_decl = try self.addString(mir.c.fwd_decl); - const code_header = try self.addString(mir.c.code_header); - const code = try self.addString(mir.c.code); - gop.value_ptr.code = code_header.concat(code); - try self.addUavsFromCodegen(&mir.c.uavs); -} + c.navs.lockPointers(); + defer c.navs.unlockPointers(); -fn updateUav(self: *C, pt: Zcu.PerThread, i: usize) link.File.FlushError!void { - const gpa = self.base.comp.gpa; - const uav = self.uavs.keys()[i]; - - var object: codegen.Object = .{ - .dg = .{ - .gpa = gpa, - .pt = pt, - .mod = pt.zcu.root_mod, - .error_msg = null, - .pass = .{ .uav = uav }, - .is_naked_fn = false, - .expected_block = null, - .fwd_decl = undefined, - .ctype_pool = .empty, - .scratch = .initBuffer(self.scratch_buf), - .uavs = .empty, - }, - .code_header = undefined, - .code = undefined, - .indent_counter = 0, + rendered_decl.* = .{ + .fwd_decl = try c.addString(&.{mir.c.fwd_decl}), + .code = try c.addString(&.{ mir.c.code_header, mir.c.code }), + .ctype_deps = try c.addCTypeDependencies(pt, &mir.c.ctype_deps), + .need_uavs = mir.c.need_uavs.move(), + .need_tag_name_funcs = mir.c.need_tag_name_funcs.move(), + .need_never_tail_funcs = mir.c.need_never_tail_funcs.move(), + .need_never_inline_funcs = mir.c.need_never_inline_funcs.move(), }; - object.dg.fwd_decl = .initOwnedSlice(gpa, self.fwd_decl_buf); - object.code = .initOwnedSlice(gpa, self.code_buf); - defer { - object.dg.uavs.deinit(gpa); - object.dg.ctype_pool.deinit(object.dg.gpa); - self.fwd_decl_buf = object.dg.fwd_decl.toArrayList().allocatedSlice(); - self.code_buf = object.code.toArrayList().allocatedSlice(); - self.scratch_buf = object.dg.scratch.allocatedSlice(); + const old_uavs_len = c.uavs.count(); + try c.uavs.ensureUnusedCapacity(gpa, rendered_decl.need_uavs.count()); + for (rendered_decl.need_uavs.keys()) |val| { + const gop = c.uavs.getOrPutAssumeCapacity(val); + if (gop.found_existing) { + assert(gop.index < old_uavs_len); + } else { + assert(gop.index >= old_uavs_len); + } } - try object.dg.ctype_pool.init(gpa); + try c.updateNewUavs(pt, old_uavs_len); - const c_value: codegen.CValue = .{ .constant = Value.fromInterned(uav) }; - const alignment: Alignment = self.aligned_uavs.get(uav) orelse .none; - codegen.genDeclValue(&object, c_value.constant, c_value, alignment, .none) catch |err| switch (err) { - error.AnalysisFail => { - @panic("TODO: C backend AnalysisFail on anonymous decl"); - //try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?); - //return; - }, - error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, - }; - - try self.addUavsFromCodegen(&object.dg.uavs); - - object.dg.ctype_pool.freeUnusedCapacity(gpa); - self.uavs.values()[i] = .{ - .fwd_decl = try self.addString(object.dg.fwd_decl.written()), - .code = try self.addString(object.code.written()), - .ctype_pool = object.dg.ctype_pool.move(), - }; + try c.type_pool.flushPending(pt, .{ .c = c }); } -pub fn updateNav(self: *C, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) link.File.UpdateNavError!void { +pub fn updateNav( + c: *C, + pt: Zcu.PerThread, + nav_index: InternPool.Nav.Index, +) Allocator.Error!void { const tracy = trace(@src()); defer tracy.end(); - const gpa = self.base.comp.gpa; + const gpa = c.base.comp.gpa; const zcu = pt.zcu; const ip = &zcu.intern_pool; const nav = ip.getNav(nav_index); - const nav_init = switch (ip.indexToKey(nav.status.fully_resolved.val)) { + switch (ip.indexToKey(nav.status.fully_resolved.val)) { .func => return, - .@"extern" => .none, - .variable => |variable| variable.init, - else => nav.status.fully_resolved.val, + .@"extern" => {}, + else => { + const nav_ty: Type = .fromInterned(nav.typeOf(ip)); + if (!nav_ty.hasRuntimeBits(zcu)) { + if (c.navs.fetchSwapRemove(nav_index)) |kv| { + var old_rendered = kv.value; + old_rendered.deinit(gpa); + } + return; + } + }, + } + + const rendered_decl: *RenderedDecl = rd: { + const gop = try c.navs.getOrPut(gpa, nav_index); + if (gop.found_existing) { + gop.value_ptr.clearRetainingCapacity(); + } else { + gop.value_ptr.* = .init; + } + break :rd gop.value_ptr; }; - if (nav_init != .none and !Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) return; + c.navs.lockPointers(); + defer c.navs.unlockPointers(); - const gop = try self.navs.getOrPut(gpa, nav_index); - errdefer _ = self.navs.pop(); - if (!gop.found_existing) gop.value_ptr.* = .{}; - const ctype_pool = &gop.value_ptr.ctype_pool; - try ctype_pool.init(gpa); - ctype_pool.clearRetainingCapacity(); + { + var arena: std.heap.ArenaAllocator = .init(gpa); + defer arena.deinit(); - var object: codegen.Object = .{ - .dg = .{ + var dg: codegen.DeclGen = .{ .gpa = gpa, + .arena = arena.allocator(), .pt = pt, .mod = zcu.navFileScope(nav_index).mod.?, .error_msg = null, - .pass = .{ .nav = nav_index }, + .owner_nav = nav_index.toOptional(), .is_naked_fn = false, .expected_block = null, - .fwd_decl = undefined, - .ctype_pool = ctype_pool.*, - .scratch = .initBuffer(self.scratch_buf), - .uavs = .empty, - }, - .code_header = undefined, - .code = undefined, - .indent_counter = 0, + .ctype_deps = .empty, + .uavs = rendered_decl.need_uavs.move(), + }; + + defer { + rendered_decl.need_uavs = dg.uavs.move(); + dg.ctype_deps.deinit(gpa); + } + + rendered_decl.fwd_decl = fwd_decl: { + var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); + defer c.string_bytes = aw.toArrayList(); + const start = aw.written().len; + codegen.genDeclFwd(&dg, &aw.writer) catch |err| switch (err) { + error.AnalysisFail => switch (zcu.codegenFailMsg(nav_index, dg.error_msg.?)) { + error.CodegenFail => return, + error.OutOfMemory => |e| return e, + }, + error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, + }; + break :fwd_decl .{ + .start = @intCast(start), + .len = @intCast(aw.written().len - start), + }; + }; + + rendered_decl.code = code: { + var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); + defer c.string_bytes = aw.toArrayList(); + const start = aw.written().len; + codegen.genDecl(&dg, &aw.writer) catch |err| switch (err) { + error.AnalysisFail => switch (zcu.codegenFailMsg(nav_index, dg.error_msg.?)) { + error.CodegenFail => return, + error.OutOfMemory => |e| return e, + }, + error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, + }; + break :code .{ + .start = @intCast(start), + .len = @intCast(aw.written().len - start), + }; + }; + + rendered_decl.ctype_deps = try c.addCTypeDependencies(pt, &dg.ctype_deps); + } + + const old_uavs_len = c.uavs.count(); + try c.uavs.ensureUnusedCapacity(gpa, rendered_decl.need_uavs.count()); + for (rendered_decl.need_uavs.keys()) |val| { + const gop = c.uavs.getOrPutAssumeCapacity(val); + if (gop.found_existing) { + assert(gop.index < old_uavs_len); + } else { + assert(gop.index >= old_uavs_len); + } + } + try c.updateNewUavs(pt, old_uavs_len); + + try c.type_pool.flushPending(pt, .{ .c = c }); +} + +/// Unlike `updateNav` and `updateFunc`, this does *not* add newly-discovered UAVs to `c.uavs`. The +/// caller is instead responsible for doing that (by iterating `rendered_decl.need_uavs`). However, +/// this function *does* still add newly-discovered *types* to `c.type_pool`. +/// +/// This function does not accept an alignment for the UAV, because the alignment needed on a UAV is +/// not known until `flush` (since we need to have seen all uses of the UAV first). Instead, `flush` +/// will prefix the UAV definition with an appropriate alignment annotation if necessary. +fn updateUav( + c: *C, + pt: Zcu.PerThread, + val: Value, + rendered_decl: *RenderedDecl, +) Allocator.Error!void { + const tracy = trace(@src()); + defer tracy.end(); + + const gpa = c.base.comp.gpa; + + var arena: std.heap.ArenaAllocator = .init(gpa); + defer arena.deinit(); + + var dg: codegen.DeclGen = .{ + .gpa = gpa, + .arena = arena.allocator(), + .pt = pt, + .mod = pt.zcu.root_mod, + .error_msg = null, + .owner_nav = .none, + .is_naked_fn = false, + .expected_block = null, + .ctype_deps = .empty, + .uavs = .empty, }; - object.dg.fwd_decl = .initOwnedSlice(gpa, self.fwd_decl_buf); - object.code = .initOwnedSlice(gpa, self.code_buf); defer { - object.dg.uavs.deinit(gpa); - ctype_pool.* = object.dg.ctype_pool.move(); - ctype_pool.freeUnusedCapacity(gpa); - - self.fwd_decl_buf = object.dg.fwd_decl.toArrayList().allocatedSlice(); - self.code_buf = object.code.toArrayList().allocatedSlice(); - self.scratch_buf = object.dg.scratch.allocatedSlice(); + rendered_decl.need_uavs = dg.uavs.move(); + dg.ctype_deps.deinit(gpa); } - codegen.genDecl(&object) catch |err| switch (err) { - error.AnalysisFail => switch (zcu.codegenFailMsg(nav_index, object.dg.error_msg.?)) { - error.CodegenFail => return, - error.OutOfMemory => |e| return e, - }, - error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, + rendered_decl.fwd_decl = fwd_decl: { + var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); + defer c.string_bytes = aw.toArrayList(); + const start = aw.written().len; + codegen.genDeclValueFwd(&dg, &aw.writer, .{ + .name = .{ .constant = val }, + .@"const" = true, + .@"threadlocal" = false, + .init_val = val, + }) catch |err| switch (err) { + error.AnalysisFail => { + @panic("TODO: CBE error.AnalysisFail on uav"); + }, + error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, + }; + break :fwd_decl .{ + .start = @intCast(start), + .len = @intCast(aw.written().len - start), + }; }; - gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.written()); - gop.value_ptr.code = try self.addString(object.code.written()); - try self.addUavsFromCodegen(&object.dg.uavs); + + rendered_decl.code = code: { + var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); + defer c.string_bytes = aw.toArrayList(); + const start = aw.written().len; + codegen.genDeclValue(&dg, &aw.writer, .{ + .name = .{ .constant = val }, + .@"const" = true, + .@"threadlocal" = false, + .init_val = val, + }) catch |err| switch (err) { + error.AnalysisFail => { + @panic("TODO: CBE error.AnalysisFail on uav"); + }, + error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, + }; + break :code .{ + .start = @intCast(start), + .len = @intCast(aw.written().len - start), + }; + }; + + rendered_decl.ctype_deps = try c.addCTypeDependencies(pt, &dg.ctype_deps); } -pub fn updateLineNumber(self: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void { - // The C backend does not have the ability to fix line numbers without re-generating - // the entire Decl. - _ = self; +pub fn updateLineNumber(c: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) error{}!void { + // The C backend does not currently emit "#line" directives. Even if it did, it would not be + // capable of updating those line numbers without re-generating the entire declaration. + _ = c; _ = pt; _ = ti_id; } -fn abiDefines(w: *std.Io.Writer, target: *const std.Target) !void { - switch (target.abi) { - .msvc, .itanium => try w.writeAll("#define ZIG_TARGET_ABI_MSVC\n"), - else => {}, - } - try w.print("#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", .{ - target.cMaxIntAlignment(), - }); -} - -pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void { - _ = arena; // Has the same lifetime as the call to Compilation.update. - +pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void { const tracy = trace(@src()); defer tracy.end(); const sub_prog_node = prog_node.start("Flush Module", 0); defer sub_prog_node.end(); - const comp = self.base.comp; + const comp = c.base.comp; const diags = &comp.link_diags; const gpa = comp.gpa; const io = comp.io; - const zcu = self.base.comp.zcu.?; + const zcu = c.base.comp.zcu.?; const ip = &zcu.intern_pool; + const target = zcu.getTarget(); const pt: Zcu.PerThread = .activate(zcu, tid); defer pt.deactivate(); + // If it's somehow not made it into the pool, we need to generate the type `[:0]const u8` for + // error names. + const slice_const_u8_sentinel_0_pool_index = try c.type_pool.get( + pt, + .{ .c = c }, + .slice_const_u8_sentinel_0_type, + ); + try c.type_pool.flushPending(pt, .{ .c = c }); + + // Find the set of referenced NAVs; these are the ones we'll emit. It is important in this + // backend that we only emit referenced NAVs, because other ones may contain code from past + // incremental updates which is invalid C (due to e.g. types changing). Machine code backends + // don't have this problem because there are, of course, no type checking performed when you + // *execute* a binary! + var need_navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty; + defer need_navs.deinit(gpa); { - var i: usize = 0; - while (i < self.uavs.count()) : (i += 1) { - try self.updateUav(pt, i); + const unit_references = try zcu.resolveReferences(); + for (c.navs.keys()) |nav| { + const nav_val = ip.getNav(nav).status.fully_resolved.val; + const check_unit: ?InternPool.AnalUnit = switch (ip.indexToKey(nav_val)) { + else => .wrap(.{ .nav_val = nav }), + .func => .wrap(.{ .func = nav_val }), + // TODO: this is a hack to deal with the fact that there's currently no good way to + // know which `extern`s are alive. This can and will break in certain patterns of + // incremental update. We kind of need to think a bit more about how the frontend + // actually represents `extern`, it's a bit awkward right now. + .@"extern" => null, + }; + if (check_unit) |u| { + if (!unit_references.contains(u)) continue; + } + try need_navs.putNoClobber(gpa, nav, {}); } } - // This code path happens exclusively with -ofmt=c. The flush logic for - // emit-h is in `flushEmitH` below. + // Using our knowledge of which NAVs are referenced, we now need to discover the set of UAVs and + // C types which are referenced (and hence must be emitted). As above, this is necessary to make + // sure we only emit valid C code. + // + // At the same time, we will discover the set of lazy functions which are referenced. + + var need_uavs: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .empty; + defer need_uavs.deinit(gpa); + + var need_types: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, void) = .empty; + defer need_types.deinit(gpa); + var need_errunion_types: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, void) = .empty; + defer need_errunion_types.deinit(gpa); + var need_aligned_types: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, u64) = .empty; + defer need_aligned_types.deinit(gpa); + + var need_tag_name_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .empty; + defer need_tag_name_funcs.deinit(gpa); + + var need_never_tail_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty; + defer need_never_tail_funcs.deinit(gpa); + + var need_never_inline_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty; + defer need_never_inline_funcs.deinit(gpa); + + // As mentioned above, we need this type for error names. + try need_types.put(gpa, slice_const_u8_sentinel_0_pool_index, {}); + + // Every exported NAV should have been discovered via `zcu.resolveReferences`... + for (c.exported_navs.keys()) |nav| assert(need_navs.contains(nav)); + // ...but we *do* need to add exported UAVs to the set. + try need_uavs.ensureUnusedCapacity(gpa, c.exported_uavs.count()); + for (c.exported_uavs.keys()) |uav| { + const gop = need_uavs.getOrPutAssumeCapacity(uav); + if (!gop.found_existing) gop.value_ptr.* = .none; + } + + // For every referenced NAV, some UAVs, C types, and lazy functions may be referenced. + for (need_navs.keys()) |nav| { + const rendered = c.navs.getPtr(nav).?; + try mergeNeededCTypes( + c, + &need_types, + &need_errunion_types, + &need_aligned_types, + &rendered.ctype_deps, + ); + try mergeNeededUavs(zcu, &need_uavs, &rendered.need_uavs); + + try need_tag_name_funcs.ensureUnusedCapacity(gpa, rendered.need_tag_name_funcs.count()); + for (rendered.need_tag_name_funcs.keys()) |enum_type| { + need_tag_name_funcs.putAssumeCapacity(enum_type, {}); + } + + try need_never_tail_funcs.ensureUnusedCapacity(gpa, rendered.need_never_tail_funcs.count()); + for (rendered.need_never_tail_funcs.keys()) |fn_nav| { + need_never_tail_funcs.putAssumeCapacity(fn_nav, {}); + } - var f: Flush = .{ - .ctype_pool = .empty, - .ctype_global_from_decl_map = .empty, - .ctypes = .empty, + try need_never_inline_funcs.ensureUnusedCapacity(gpa, rendered.need_never_inline_funcs.count()); + for (rendered.need_never_inline_funcs.keys()) |fn_nav| { + need_never_inline_funcs.putAssumeCapacity(fn_nav, {}); + } + } + + // UAVs may reference other UAVs or C types. + { + var index: usize = 0; + while (need_uavs.count() > index) : (index += 1) { + const val = need_uavs.keys()[index]; + const rendered = c.uavs.getPtr(val).?; + try mergeNeededCTypes( + c, + &need_types, + &need_errunion_types, + &need_aligned_types, + &rendered.ctype_deps, + ); + try mergeNeededUavs(zcu, &need_uavs, &rendered.need_uavs); + } + } + + // Finally, C types may reference other C types. + { + var index: usize = 0; + var errunion_index: usize = 0; + var aligned_index: usize = 0; + while (true) { + if (index < need_types.count()) { + const pool_index = need_types.keys()[index]; + const rendered = &c.types.items[@intFromEnum(pool_index)]; + try mergeNeededCTypes( + c, + &need_types, + &need_errunion_types, + &need_aligned_types, + &rendered.definition_deps, // we're tasked with emitting the *definition* of this type + ); + index += 1; + continue; + } + + if (errunion_index < need_errunion_types.count()) { + const payload_pool_index = need_errunion_types.keys()[errunion_index]; + const rendered = &c.types.items[@intFromEnum(payload_pool_index)]; + try mergeNeededCTypes( + c, + &need_types, + &need_errunion_types, + &need_aligned_types, + &rendered.deps, // the error union type requires emitting this type's *name* + ); + errunion_index += 1; + continue; + } + + if (aligned_index < need_aligned_types.count()) { + const pool_index = need_aligned_types.keys()[aligned_index]; + const rendered = &c.types.items[@intFromEnum(pool_index)]; + try mergeNeededCTypes( + c, + &need_types, + &need_errunion_types, + &need_aligned_types, + &rendered.deps, // an aligned typedef requires emitting this type's *name* + ); + aligned_index += 1; + continue; + } + + break; + } + } + + // Now that we know which types are required, generate aligned typedefs. One buffer per aligned + // type, with *all* aligned typedefs for that type. + const aligned_type_strings = try arena.alloc([]const u8, need_aligned_types.count()); + { + var aw: std.Io.Writer.Allocating = .init(gpa); + defer aw.deinit(); + var unused_deps: codegen.CType.Dependencies = .empty; + defer unused_deps.deinit(gpa); + for ( + need_aligned_types.keys(), + need_aligned_types.values(), + aligned_type_strings, + ) |pool_index, align_mask, *str_out| { + const ty: Type = .fromInterned(pool_index.val(&c.type_pool)); + const has_layout = c.types.items[@intFromEnum(pool_index)].errunion_definition.len > 0; + for (0..@bitSizeOf(@TypeOf(align_mask))) |bit_index| { + switch (@as(u1, @truncate(align_mask >> @intCast(bit_index)))) { + 0 => continue, + 1 => {}, + } + codegen.CType.render_defs.defineAligned( + ty, + .fromLog2Units(@intCast(bit_index)), + has_layout, + &unused_deps, + arena, + &aw.writer, + pt, + ) catch |err| switch (err) { + error.WriteFailed => return error.OutOfMemory, + error.OutOfMemory => |e| return e, + }; + } + str_out.* = try arena.dupe(u8, aw.written()); + aw.clearRetainingCapacity(); + } + } - .lazy_ctype_pool = .empty, - .lazy_fns = .empty, - .lazy_fwd_decl = .empty, - .lazy_code = .empty, + // We have discovered the full set of NAVs, UAVs, and types we need to emit, and will now begin + // to build the output buffer. Our strategy is to emit the C source in this order: + // + // * ABI defines and `#include "zig.h"` + // * Big-int type definitions + // * Other CType definitions (traversing the dependency graph to sort topologically) + // * Global assembly + // * UAV exports + // * NAV exports + // * UAV forward declarations + // * NAV forward declarations + // * Lazy declarations (error names; @tagName functions; never_tail/never_inline wrappers) + // * UAV definitions + // * NAV definitions + // + // Most of these sections are order-independent within themselves, with the exception of the + // type definitions, which must be ordered to avoid a struct/union from embedding a type which + // is currently incomplete. + // + // When emitting UAV forward declarations, if the UAV requires alignment, we must prefix it with + // an alignment annotation. We couldn't emit the alignment into the UAV's `RenderedDecl` because + // we couldn't have known the required alignment until now! - .all_buffers = .empty, - .file_size = 0, - }; + var f: Flush = .{ .all_buffers = .empty, .file_size = 0 }; defer f.deinit(gpa); - var abi_defines_aw: std.Io.Writer.Allocating = .init(gpa); - defer abi_defines_aw.deinit(); - abiDefines(&abi_defines_aw.writer, zcu.getTarget()) catch |err| switch (err) { - error.WriteFailed => return error.OutOfMemory, - }; + // We know exactly what we'll be emitting, so can reserve capacity for all of our buffers! - // Covers defines, zig.h, ctypes, asm, lazy fwd. - try f.all_buffers.ensureUnusedCapacity(gpa, 5); + try f.all_buffers.ensureUnusedCapacity(gpa, 3 + // ABI defines and `#include "zig.h"` + 1 + // Big-int type definitions + need_types.count() + // `RenderedType.fwd_decl` (worst-case) + need_types.count() + // `RenderedType.definition` + need_errunion_types.count() + // `RenderedType.errunion_fwd_decl` (worst-case) + need_errunion_types.count() + // `RenderedType.errunion_definition` + need_aligned_types.count() + // `aligned_type_strings` + 1 + // Global assembly + c.exported_uavs.count() + // UAV export block + c.exported_navs.count() + // NAV export block + need_uavs.count() + // UAV forward declarations + need_navs.count() + // NAV forward declarations + 1 + // Lazy declarations + need_uavs.count() * 3 + // UAV definitions ("static ", "zig_align(4)", "") + need_navs.count() * 2); // NAV definitions ("static ", "") - f.appendBufAssumeCapacity(abi_defines_aw.written()); - f.appendBufAssumeCapacity(zig_h); + // ABI defines and `#include "zig.h"` + switch (target.abi) { + .msvc, .itanium => f.appendBufAssumeCapacity("#define ZIG_TARGET_ABI_MSVC\n"), + else => {}, + } + f.appendBufAssumeCapacity(try std.fmt.allocPrint( + arena, + "#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", + .{target.cMaxIntAlignment()}, + )); + f.appendBufAssumeCapacity( + \\#include "zig.h" + \\ + ); - const ctypes_index = f.all_buffers.items.len; - f.all_buffers.items.len += 1; + // Big-int type definitions + var bigint_aw: std.Io.Writer.Allocating = .init(gpa); + defer bigint_aw.deinit(); + for (c.bigint_types.keys()) |bigint| { + codegen.CType.render_defs.defineBigInt(bigint, &bigint_aw.writer, zcu) catch |err| switch (err) { + error.WriteFailed => return error.OutOfMemory, + }; + } + f.appendBufAssumeCapacity(bigint_aw.written()); + // CType definitions + { + var ft: FlushTypes = .{ + .c = c, + .f = &f, + .aligned_types = &need_aligned_types, + .aligned_type_strings = aligned_type_strings, + .status = .empty, + .errunion_status = .empty, + .aligned_status = .empty, + }; + defer { + ft.status.deinit(gpa); + ft.errunion_status.deinit(gpa); + ft.aligned_status.deinit(gpa); + } + try ft.status.ensureUnusedCapacity(gpa, need_types.count()); + try ft.errunion_status.ensureUnusedCapacity(gpa, need_errunion_types.count()); + try ft.aligned_status.ensureUnusedCapacity(gpa, need_aligned_types.count()); + + for (need_types.keys()) |pool_index| { + ft.doType(pool_index); + } + for (need_errunion_types.keys()) |pool_index| { + ft.doErrunionType(pool_index); + } + for (need_aligned_types.keys()) |pool_index| { + ft.doAlignedTypeFwd(pool_index); + } + } + + // Global assembly var asm_aw: std.Io.Writer.Allocating = .init(gpa); defer asm_aw.deinit(); codegen.genGlobalAsm(zcu, &asm_aw.writer) catch |err| switch (err) { @@ -424,435 +1059,228 @@ pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.P }; f.appendBufAssumeCapacity(asm_aw.written()); - const lazy_index = f.all_buffers.items.len; - f.all_buffers.items.len += 1; + var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty; + defer export_names.deinit(gpa); + try export_names.ensureTotalCapacity(gpa, @intCast(zcu.single_exports.count())); + for (zcu.single_exports.values()) |export_index| { + export_names.putAssumeCapacity(export_index.ptr(zcu).opts.name, {}); + } + for (zcu.multi_exports.values()) |info| { + try export_names.ensureUnusedCapacity(gpa, info.len); + for (zcu.all_exports.items[info.index..][0..info.len]) |@"export"| { + export_names.putAssumeCapacity(@"export".opts.name, {}); + } + } - try f.lazy_ctype_pool.init(gpa); - try self.flushErrDecls(pt, &f); + // UAV export block + for (c.exported_uavs.values()) |code| { + f.appendBufAssumeCapacity(code.get(c)); + } - // Unlike other backends, the .c code we are emitting has order-dependent decls. - // `CType`s, forward decls, and non-functions first. + // NAV export block + for (c.exported_navs.values()) |code| { + f.appendBufAssumeCapacity(code.get(c)); + } - { - var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty; - defer export_names.deinit(gpa); - try export_names.ensureTotalCapacity(gpa, @intCast(zcu.single_exports.count())); - for (zcu.single_exports.values()) |export_index| { - export_names.putAssumeCapacity(export_index.ptr(zcu).opts.name, {}); - } - for (zcu.multi_exports.values()) |info| { - try export_names.ensureUnusedCapacity(gpa, info.len); - for (zcu.all_exports.items[info.index..][0..info.len]) |@"export"| { - export_names.putAssumeCapacity(@"export".opts.name, {}); - } + // UAV forward declarations + for (need_uavs.keys()) |val| { + if (c.exported_uavs.contains(val)) continue; // the export was the declaration + const fwd_decl = c.uavs.getPtr(val).?.fwd_decl; + f.appendBufAssumeCapacity(fwd_decl.get(c)); + } + + // NAV forward declarations + for (need_navs.keys()) |nav| { + if (c.exported_navs.contains(nav)) continue; // the export was the declaration + if (ip.getNav(nav).getExtern(ip)) |e| { + if (export_names.contains(e.name)) continue; } + const fwd_decl = c.navs.getPtr(nav).?.fwd_decl; + f.appendBufAssumeCapacity(fwd_decl.get(c)); + } - for (self.uavs.keys(), self.uavs.values()) |uav, *av_block| try self.flushAvBlock( - pt, - zcu.root_mod, - &f, - av_block, - self.exported_uavs.getPtr(uav), - export_names, - .none, + // Lazy declarations + var lazy_decls_aw: std.Io.Writer.Allocating = .init(gpa); + defer lazy_decls_aw.deinit(); + { + var lazy_dg: codegen.DeclGen = .{ + .gpa = gpa, + .arena = arena, + .pt = pt, + .mod = pt.zcu.root_mod, + .owner_nav = .none, + .is_naked_fn = false, + .expected_block = null, + .error_msg = null, + .ctype_deps = .empty, + .uavs = .empty, + }; + defer { + assert(lazy_dg.uavs.count() == 0); + lazy_dg.ctype_deps.deinit(gpa); + } + const slice_const_u8_sentinel_0_cty: codegen.CType = try .lower( + .slice_const_u8_sentinel_0, + &lazy_dg.ctype_deps, + arena, + zcu, ); - - for (self.navs.keys(), self.navs.values()) |nav, *av_block| try self.flushAvBlock( - pt, - zcu.navFileScope(nav).mod.?, - &f, - av_block, - self.exported_navs.getPtr(nav), - export_names, - if (ip.getNav(nav).getExtern(ip) != null) - ip.getNav(nav).name.toOptional() - else - .none, + const slice_const_u8_sentinel_0_name = try std.fmt.allocPrint( + arena, + "{f}", + .{slice_const_u8_sentinel_0_cty.fmtTypeName(zcu)}, ); + codegen.genErrDecls(zcu, &lazy_decls_aw.writer, slice_const_u8_sentinel_0_name) catch |err| switch (err) { + error.WriteFailed => return error.OutOfMemory, + }; + for (need_tag_name_funcs.keys()) |enum_ty_ip| { + const enum_ty: Type = .fromInterned(enum_ty_ip); + const enum_cty: codegen.CType = try .lower( + enum_ty, + &lazy_dg.ctype_deps, + arena, + zcu, + ); + codegen.genTagNameFn( + zcu, + &lazy_decls_aw.writer, + slice_const_u8_sentinel_0_name, + enum_ty, + try std.fmt.allocPrint(arena, "{f}", .{enum_cty.fmtTypeName(zcu)}), + ) catch |err| switch (err) { + error.WriteFailed => return error.OutOfMemory, + }; + } + for (need_never_tail_funcs.keys()) |fn_nav| { + codegen.genLazyCallModifierFn(&lazy_dg, fn_nav, .never_tail, &lazy_decls_aw.writer) catch |err| switch (err) { + error.WriteFailed => return error.OutOfMemory, + error.OutOfMemory => |e| return e, + error.AnalysisFail => unreachable, + }; + } + for (need_never_inline_funcs.keys()) |fn_nav| { + codegen.genLazyCallModifierFn(&lazy_dg, fn_nav, .never_inline, &lazy_decls_aw.writer) catch |err| switch (err) { + error.WriteFailed => return error.OutOfMemory, + error.OutOfMemory => |e| return e, + error.AnalysisFail => unreachable, + }; + } } + f.appendBufAssumeCapacity(lazy_decls_aw.written()); - { - // We need to flush lazy ctypes after flushing all decls but before flushing any decl ctypes. - // This ensures that every lazy CType.Index exactly matches the global CType.Index. - try f.ctype_pool.init(gpa); - try self.flushCTypes(zcu, &f, .flush, &f.lazy_ctype_pool); - - for (self.uavs.keys(), self.uavs.values()) |uav, av_block| { - try self.flushCTypes(zcu, &f, .{ .uav = uav }, &av_block.ctype_pool); + // UAV definitions + for (need_uavs.keys(), need_uavs.values()) |val, overalign| { + const code = c.uavs.getPtr(val).?.code; + if (code.len == 0) continue; + if (!c.exported_uavs.contains(val)) { + f.appendBufAssumeCapacity("static "); } - - for (self.navs.keys(), self.navs.values()) |nav, av_block| { - try self.flushCTypes(zcu, &f, .{ .nav = nav }, &av_block.ctype_pool); + if (overalign != .none) { + // As long as `Alignment` isn't too big, it's reasonable to just generate all possible + // alignment annotations statically into a LUT, which avoids allocating strings on this + // path. + comptime assert(@bitSizeOf(Alignment) < 8); + const table_len = (1 << @bitSizeOf(Alignment)) - 1; + const table: [table_len][]const u8 = comptime table: { + @setEvalBranchQuota(16_000); + var table: [table_len][]const u8 = undefined; + for (&table, 0..) |*str, log2_align| { + const byte_align = Alignment.fromLog2Units(log2_align).toByteUnits().?; + str.* = std.fmt.comptimePrint("zig_align({d}) ", .{byte_align}); + } + break :table table; + }; + f.appendBufAssumeCapacity(table[overalign.toLog2Units()]); } + f.appendBufAssumeCapacity(code.get(c)); } - f.all_buffers.items[ctypes_index] = f.ctypes.items; - f.file_size += f.ctypes.items.len; - - f.all_buffers.items[lazy_index] = f.lazy_fwd_decl.items; - f.file_size += f.lazy_fwd_decl.items.len; - - // Now the code. - try f.all_buffers.ensureUnusedCapacity(gpa, 1 + (self.uavs.count() + self.navs.count()) * 2); - f.appendBufAssumeCapacity(f.lazy_code.items); - for (self.uavs.keys(), self.uavs.values()) |uav, av_block| f.appendCodeAssumeCapacity( - if (self.exported_uavs.contains(uav)) .default else switch (ip.indexToKey(uav)) { - .@"extern" => .zig_extern, - else => .static, - }, - self.getString(av_block.code), - ); - for (self.navs.keys(), self.navs.values()) |nav, av_block| f.appendCodeAssumeCapacity(storage: { - if (self.exported_navs.contains(nav)) break :storage .default; - if (ip.getNav(nav).getExtern(ip) != null) break :storage .zig_extern; - break :storage .static; - }, self.getString(av_block.code)); + // NAV definitions + for (need_navs.keys()) |nav| { + const code = c.navs.getPtr(nav).?.code; + if (code.len == 0) continue; + if (!c.exported_navs.contains(nav)) { + const is_extern = ip.getNav(nav).getExtern(ip) != null; + f.appendBufAssumeCapacity(if (is_extern) "zig_extern " else "static "); + } + f.appendBufAssumeCapacity(code.get(c)); + } - const file = self.base.file.?; + // We've collected all of our buffers; it's now time to actually write the file! + const file = c.base.file.?; file.setLength(io, f.file_size) catch |err| return diags.fail("failed to allocate file: {t}", .{err}); var fw = file.writer(io, &.{}); var w = &fw.interface; w.writeVecAll(f.all_buffers.items) catch |err| switch (err) { error.WriteFailed => return diags.fail("failed to write to '{f}': {s}", .{ - std.fmt.alt(self.base.emit, .formatEscapeChar), @errorName(fw.err.?), + std.fmt.alt(c.base.emit, .formatEscapeChar), @errorName(fw.err.?), }), }; } const Flush = struct { - ctype_pool: codegen.CType.Pool, - ctype_global_from_decl_map: std.ArrayList(codegen.CType), - ctypes: std.ArrayList(u8), - - lazy_ctype_pool: codegen.CType.Pool, - lazy_fns: LazyFns, - lazy_fwd_decl: std.ArrayList(u8), - lazy_code: std.ArrayList(u8), - /// We collect a list of buffers to write, and write them all at once with pwritev 😎 all_buffers: std.ArrayList([]const u8), /// Keeps track of the total bytes of `all_buffers`. file_size: u64, - const LazyFns = std.AutoHashMapUnmanaged(codegen.LazyFnKey, void); - fn appendBufAssumeCapacity(f: *Flush, buf: []const u8) void { if (buf.len == 0) return; f.all_buffers.appendAssumeCapacity(buf); f.file_size += buf.len; } - fn appendCodeAssumeCapacity(f: *Flush, storage: enum { default, zig_extern, static }, code: []const u8) void { - if (code.len == 0) return; - f.appendBufAssumeCapacity(switch (storage) { - .default => "\n", - .zig_extern => "\nzig_extern ", - .static => "\nstatic ", - }); - f.appendBufAssumeCapacity(code); - } - fn deinit(f: *Flush, gpa: Allocator) void { - f.ctype_pool.deinit(gpa); - assert(f.ctype_global_from_decl_map.items.len == 0); - f.ctype_global_from_decl_map.deinit(gpa); - f.ctypes.deinit(gpa); - f.lazy_ctype_pool.deinit(gpa); - f.lazy_fns.deinit(gpa); - f.lazy_fwd_decl.deinit(gpa); - f.lazy_code.deinit(gpa); f.all_buffers.deinit(gpa); } }; -const FlushDeclError = error{ - OutOfMemory, -}; - -fn flushCTypes( - self: *C, - zcu: *Zcu, - f: *Flush, - pass: codegen.DeclGen.Pass, - decl_ctype_pool: *const codegen.CType.Pool, -) FlushDeclError!void { - const gpa = self.base.comp.gpa; - const global_ctype_pool = &f.ctype_pool; - - const global_from_decl_map = &f.ctype_global_from_decl_map; - assert(global_from_decl_map.items.len == 0); - try global_from_decl_map.ensureTotalCapacity(gpa, decl_ctype_pool.items.len); - defer global_from_decl_map.clearRetainingCapacity(); - - var ctypes_aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &f.ctypes); - const ctypes_bw = &ctypes_aw.writer; - defer f.ctypes = ctypes_aw.toArrayList(); - - for (0..decl_ctype_pool.items.len) |decl_ctype_pool_index| { - const PoolAdapter = struct { - global_from_decl_map: []const codegen.CType, - pub fn eql(pool_adapter: @This(), decl_ctype: codegen.CType, global_ctype: codegen.CType) bool { - return if (decl_ctype.toPoolIndex()) |decl_pool_index| - decl_pool_index < pool_adapter.global_from_decl_map.len and - pool_adapter.global_from_decl_map[decl_pool_index].eql(global_ctype) - else - decl_ctype.index == global_ctype.index; - } - pub fn copy(pool_adapter: @This(), decl_ctype: codegen.CType) codegen.CType { - return if (decl_ctype.toPoolIndex()) |decl_pool_index| - pool_adapter.global_from_decl_map[decl_pool_index] - else - decl_ctype; - } - }; - const decl_ctype = codegen.CType.fromPoolIndex(decl_ctype_pool_index); - const global_ctype, const found_existing = try global_ctype_pool.getOrPutAdapted( - gpa, - decl_ctype_pool, - decl_ctype, - PoolAdapter{ .global_from_decl_map = global_from_decl_map.items }, - ); - global_from_decl_map.appendAssumeCapacity(global_ctype); - codegen.genTypeDecl( - zcu, - ctypes_bw, - global_ctype_pool, - global_ctype, - pass, - decl_ctype_pool, - decl_ctype, - found_existing, - ) catch |err| switch (err) { - error.WriteFailed => return error.OutOfMemory, - }; - } -} - -fn flushErrDecls(self: *C, pt: Zcu.PerThread, f: *Flush) FlushDeclError!void { - const gpa = self.base.comp.gpa; - - var object: codegen.Object = .{ - .dg = .{ - .gpa = gpa, - .pt = pt, - .mod = pt.zcu.root_mod, - .error_msg = null, - .pass = .flush, - .is_naked_fn = false, - .expected_block = null, - .fwd_decl = undefined, - .ctype_pool = f.lazy_ctype_pool, - .scratch = .initBuffer(self.scratch_buf), - .uavs = .empty, - }, - .code_header = undefined, - .code = undefined, - .indent_counter = 0, - }; - object.dg.fwd_decl = .fromArrayList(gpa, &f.lazy_fwd_decl); - object.code = .fromArrayList(gpa, &f.lazy_code); - defer { - object.dg.uavs.deinit(gpa); - f.lazy_ctype_pool = object.dg.ctype_pool.move(); - f.lazy_ctype_pool.freeUnusedCapacity(gpa); - - f.lazy_fwd_decl = object.dg.fwd_decl.toArrayList(); - f.lazy_code = object.code.toArrayList(); - self.scratch_buf = object.dg.scratch.allocatedSlice(); - } - - codegen.genErrDecls(&object) catch |err| switch (err) { - error.AnalysisFail => unreachable, - error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, - }; - - try self.addUavsFromCodegen(&object.dg.uavs); -} - -fn flushLazyFn( - self: *C, - pt: Zcu.PerThread, - mod: *Module, - f: *Flush, - lazy_ctype_pool: *const codegen.CType.Pool, - lazy_fn: codegen.LazyFnMap.Entry, -) FlushDeclError!void { - const gpa = self.base.comp.gpa; - - var object: codegen.Object = .{ - .dg = .{ - .gpa = gpa, - .pt = pt, - .mod = mod, - .error_msg = null, - .pass = .flush, - .is_naked_fn = false, - .expected_block = null, - .fwd_decl = undefined, - .ctype_pool = f.lazy_ctype_pool, - .scratch = .initBuffer(self.scratch_buf), - .uavs = .empty, - }, - .code_header = undefined, - .code = undefined, - .indent_counter = 0, - }; - object.dg.fwd_decl = .fromArrayList(gpa, &f.lazy_fwd_decl); - object.code = .fromArrayList(gpa, &f.lazy_code); - defer { - // If this assert trips just handle the anon_decl_deps the same as - // `updateFunc()` does. - assert(object.dg.uavs.count() == 0); - f.lazy_ctype_pool = object.dg.ctype_pool.move(); - f.lazy_ctype_pool.freeUnusedCapacity(gpa); - - f.lazy_fwd_decl = object.dg.fwd_decl.toArrayList(); - f.lazy_code = object.code.toArrayList(); - self.scratch_buf = object.dg.scratch.allocatedSlice(); - } - - codegen.genLazyFn(&object, lazy_ctype_pool, lazy_fn) catch |err| switch (err) { - error.AnalysisFail => unreachable, - error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, - }; -} - -fn flushLazyFns( - self: *C, - pt: Zcu.PerThread, - mod: *Module, - f: *Flush, - lazy_ctype_pool: *const codegen.CType.Pool, - lazy_fns: codegen.LazyFnMap, -) FlushDeclError!void { - const gpa = self.base.comp.gpa; - try f.lazy_fns.ensureUnusedCapacity(gpa, @intCast(lazy_fns.count())); - - var it = lazy_fns.iterator(); - while (it.next()) |entry| { - const gop = f.lazy_fns.getOrPutAssumeCapacity(entry.key_ptr.*); - if (gop.found_existing) continue; - gop.value_ptr.* = {}; - try self.flushLazyFn(pt, mod, f, lazy_ctype_pool, entry); - } -} - -fn flushAvBlock( - self: *C, - pt: Zcu.PerThread, - mod: *Module, - f: *Flush, - av_block: *const AvBlock, - exported_block: ?*const ExportedBlock, - export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void), - extern_name: InternPool.OptionalNullTerminatedString, -) FlushDeclError!void { - const gpa = self.base.comp.gpa; - try self.flushLazyFns(pt, mod, f, &av_block.ctype_pool, av_block.lazy_fns); - try f.all_buffers.ensureUnusedCapacity(gpa, 1); - // avoid emitting extern decls that are already exported - if (extern_name.unwrap()) |name| if (export_names.contains(name)) return; - f.appendBufAssumeCapacity(self.getString(if (exported_block) |exported| - exported.fwd_decl - else - av_block.fwd_decl)); -} - -pub fn flushEmitH(zcu: *Zcu) !void { - const tracy = trace(@src()); - defer tracy.end(); - - if (true) return; // emit-h is regressed - - const emit_h = zcu.emit_h orelse return; - const io = zcu.comp.io; - - // We collect a list of buffers to write, and write them all at once with pwritev 😎 - const num_buffers = emit_h.decl_table.count() + 1; - var all_buffers = try std.array_list.Managed(std.posix.iovec_const).initCapacity(zcu.gpa, num_buffers); - defer all_buffers.deinit(); - - var file_size: u64 = zig_h.len; - if (zig_h.len != 0) { - all_buffers.appendAssumeCapacity(.{ - .base = zig_h, - .len = zig_h.len, - }); - } - - for (emit_h.decl_table.keys()) |decl_index| { - const decl_emit_h = emit_h.declPtr(decl_index); - const buf = decl_emit_h.fwd_decl.items; - if (buf.len != 0) { - all_buffers.appendAssumeCapacity(.{ - .base = buf.ptr, - .len = buf.len, - }); - file_size += buf.len; - } - } - - const directory = emit_h.loc.directory orelse zcu.comp.local_cache_directory; - const file = try directory.handle.createFile(io, emit_h.loc.basename, .{ - // We set the end position explicitly below; by not truncating the file, we possibly - // make it easier on the file system by doing 1 reallocation instead of two. - .truncate = false, - }); - defer file.close(io); - - try file.setLength(io, file_size); - try file.pwritevAll(all_buffers.items, 0); -} - pub fn updateExports( - self: *C, + c: *C, pt: Zcu.PerThread, exported: Zcu.Exported, export_indices: []const Zcu.Export.Index, -) !void { +) Allocator.Error!void { const zcu = pt.zcu; const gpa = zcu.gpa; - const mod, const pass: codegen.DeclGen.Pass, const decl_block, const exported_block = switch (exported) { - .nav => |nav| .{ - zcu.navFileScope(nav).mod.?, - .{ .nav = nav }, - self.navs.getPtr(nav).?, - (try self.exported_navs.getOrPut(gpa, nav)).value_ptr, - }, - .uav => |uav| .{ - zcu.root_mod, - .{ .uav = uav }, - self.uavs.getPtr(uav).?, - (try self.exported_uavs.getOrPut(gpa, uav)).value_ptr, - }, - }; - const ctype_pool = &decl_block.ctype_pool; + + var arena: std.heap.ArenaAllocator = .init(gpa); + defer arena.deinit(); + var dg: codegen.DeclGen = .{ .gpa = gpa, + .arena = arena.allocator(), .pt = pt, - .mod = mod, - .error_msg = null, - .pass = pass, + .mod = zcu.root_mod, + .owner_nav = .none, .is_naked_fn = false, .expected_block = null, - .fwd_decl = undefined, - .ctype_pool = decl_block.ctype_pool, - .scratch = .initBuffer(self.scratch_buf), + .error_msg = null, + .ctype_deps = .empty, .uavs = .empty, }; - dg.fwd_decl = .initOwnedSlice(gpa, self.fwd_decl_buf); defer { assert(dg.uavs.count() == 0); - ctype_pool.* = dg.ctype_pool.move(); - ctype_pool.freeUnusedCapacity(gpa); + dg.ctype_deps.deinit(gpa); + } - self.fwd_decl_buf = dg.fwd_decl.toArrayList().allocatedSlice(); - self.scratch_buf = dg.scratch.allocatedSlice(); - } - codegen.genExports(&dg, exported, export_indices) catch |err| switch (err) { - error.WriteFailed, error.OutOfMemory => return error.OutOfMemory, + const code: String = code: { + var aw: std.Io.Writer.Allocating = .fromArrayList(gpa, &c.string_bytes); + defer c.string_bytes = aw.toArrayList(); + const start = aw.written().len; + codegen.genExports(&dg, &aw.writer, exported, export_indices) catch |err| switch (err) { + error.WriteFailed => return error.OutOfMemory, + error.OutOfMemory => |e| return e, + }; + break :code .{ + .start = @intCast(start), + .len = @intCast(aw.written().len - start), + }; }; - exported_block.* = .{ .fwd_decl = try self.addString(dg.fwd_decl.written()) }; + switch (exported) { + .nav => |nav| try c.exported_navs.put(gpa, nav, code), + .uav => |uav| try c.exported_uavs.put(gpa, uav, code), + } } pub fn deleteExport( @@ -866,20 +1294,237 @@ pub fn deleteExport( } } -fn addUavsFromCodegen(c: *C, uavs: *const std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment)) Allocator.Error!void { +fn mergeNeededCTypes( + c: *C, + need_types: *std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, void), + need_errunion_types: *std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, void), + need_aligned_types: *std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, u64), + deps: *const CTypeDependencies, +) Allocator.Error!void { const gpa = c.base.comp.gpa; - try c.uavs.ensureUnusedCapacity(gpa, uavs.count()); - try c.aligned_uavs.ensureUnusedCapacity(gpa, uavs.count()); - for (uavs.keys(), uavs.values()) |uav_val, uav_align| { - { - const gop = c.uavs.getOrPutAssumeCapacity(uav_val); - if (!gop.found_existing) gop.value_ptr.* = .{}; + + const resolved = deps.get(c); + + try need_types.ensureUnusedCapacity(gpa, resolved.type.len + resolved.type_fwd.len); + try need_errunion_types.ensureUnusedCapacity(gpa, resolved.errunion_type.len + resolved.errunion_type_fwd.len); + try need_aligned_types.ensureUnusedCapacity(gpa, resolved.aligned_type_fwd.len); + + for (resolved.type) |index| need_types.putAssumeCapacity(index, {}); + for (resolved.type_fwd) |index| need_types.putAssumeCapacity(index, {}); + + for (resolved.errunion_type) |index| need_errunion_types.putAssumeCapacity(index, {}); + for (resolved.errunion_type_fwd) |index| need_errunion_types.putAssumeCapacity(index, {}); + + for (resolved.aligned_type_fwd, resolved.aligned_type_masks) |ty_index, align_mask| { + const gop = need_aligned_types.getOrPutAssumeCapacity(ty_index); + if (!gop.found_existing) gop.value_ptr.* = 0; + gop.value_ptr.* |= align_mask; + } +} + +fn mergeNeededUavs( + zcu: *const Zcu, + global: *std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), + new: *const std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), +) Allocator.Error!void { + const gpa = zcu.comp.gpa; + + try global.ensureUnusedCapacity(gpa, new.count()); + for (new.keys(), new.values()) |uav_val, need_align| { + const gop = global.getOrPutAssumeCapacity(uav_val); + if (!gop.found_existing) gop.value_ptr.* = .none; + + if (need_align != .none) { + const cur_align = switch (gop.value_ptr.*) { + .none => Value.fromInterned(uav_val).typeOf(zcu).abiAlignment(zcu), + else => |a| a, + }; + if (need_align.compareStrict(.gt, cur_align)) { + gop.value_ptr.* = need_align; + } } - if (uav_align != .none) { - const gop = c.aligned_uavs.getOrPutAssumeCapacity(uav_val); - gop.value_ptr.* = if (gop.found_existing) max: { - break :max gop.value_ptr.*.maxStrict(uav_align); - } else uav_align; + } +} + +fn addCTypeDependencies( + c: *C, + pt: Zcu.PerThread, + deps: *const codegen.CType.Dependencies, +) Allocator.Error!CTypeDependencies { + const gpa = pt.zcu.comp.gpa; + + try c.bigint_types.ensureUnusedCapacity(gpa, deps.bigint.count()); + for (deps.bigint.keys()) |bigint| c.bigint_types.putAssumeCapacity(bigint, {}); + + const type_start = c.type_dependencies.items.len; + const errunion_type_start = type_start + deps.type.count(); + const type_fwd_start = errunion_type_start + deps.errunion_type.count(); + const errunion_type_fwd_start = type_fwd_start + deps.type_fwd.count(); + const aligned_type_fwd_start = errunion_type_fwd_start + deps.errunion_type_fwd.count(); + try c.type_dependencies.appendNTimes(gpa, undefined, deps.type.count() + + deps.errunion_type.count() + + deps.type_fwd.count() + + deps.errunion_type_fwd.count() + + deps.aligned_type_fwd.count()); + + const align_mask_start = c.align_dependency_masks.items.len; + try c.align_dependency_masks.appendSlice(gpa, deps.aligned_type_fwd.values()); + + for (deps.type.keys(), type_start..) |ty, i| { + const pool_index = try c.type_pool.get(pt, .{ .c = c }, ty); + c.type_dependencies.items[i] = pool_index; + } + + for (deps.errunion_type.keys(), errunion_type_start..) |ty, i| { + const pool_index = try c.type_pool.get(pt, .{ .c = c }, ty); + c.type_dependencies.items[i] = pool_index; + } + + for (deps.type_fwd.keys(), type_fwd_start..) |ty, i| { + const pool_index = try c.type_pool.get(pt, .{ .c = c }, ty); + c.type_dependencies.items[i] = pool_index; + } + + for (deps.errunion_type_fwd.keys(), errunion_type_fwd_start..) |ty, i| { + const pool_index = try c.type_pool.get(pt, .{ .c = c }, ty); + c.type_dependencies.items[i] = pool_index; + } + + for (deps.aligned_type_fwd.keys(), aligned_type_fwd_start..) |ty, i| { + const pool_index = try c.type_pool.get(pt, .{ .c = c }, ty); + c.type_dependencies.items[i] = pool_index; + } + + return .{ + .len = @intCast(deps.type.count()), + .errunion_len = @intCast(deps.errunion_type.count()), + .fwd_len = @intCast(deps.type_fwd.count()), + .errunion_fwd_len = @intCast(deps.errunion_type_fwd.count()), + .aligned_fwd_len = @intCast(deps.aligned_type_fwd.count()), + .type_start = @intCast(type_start), + .align_mask_start = @intCast(align_mask_start), + }; +} + +fn updateNewUavs(c: *C, pt: Zcu.PerThread, old_uavs_len: usize) Allocator.Error!void { + const gpa = pt.zcu.comp.gpa; + var index = old_uavs_len; + while (index < c.uavs.count()) : (index += 1) { + // `new_uavs` is UAVs discovered while lowering *this* UAV. + const new_uavs: []const InternPool.Index = new: { + c.uavs.lockPointers(); + defer c.uavs.unlockPointers(); + const val: Value = .fromInterned(c.uavs.keys()[index]); + const rendered_decl = &c.uavs.values()[index]; + rendered_decl.* = .init; + try c.updateUav(pt, val, rendered_decl); + break :new rendered_decl.need_uavs.keys(); + }; + try c.uavs.ensureUnusedCapacity(gpa, new_uavs.len); + for (new_uavs) |val| { + const gop = c.uavs.getOrPutAssumeCapacity(val); + if (!gop.found_existing) { + assert(gop.index > index); + } } } } + +const FlushTypes = struct { + c: *C, + f: *Flush, + + aligned_types: *const std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, u64), + aligned_type_strings: []const []const u8, + + status: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, bool), + errunion_status: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, bool), + aligned_status: std.AutoArrayHashMapUnmanaged(link.ConstPool.Index, void), + + fn processDeps(ft: *FlushTypes, deps: *const CTypeDependencies) void { + const resolved = deps.get(ft.c); + for (resolved.type) |pool_index| ft.doType(pool_index); + for (resolved.type_fwd) |pool_index| ft.doTypeFwd(pool_index); + for (resolved.errunion_type) |pool_index| ft.doErrunionType(pool_index); + for (resolved.errunion_type_fwd) |pool_index| ft.doErrunionTypeFwd(pool_index); + for (resolved.aligned_type_fwd) |pool_index| ft.doAlignedTypeFwd(pool_index); + } + fn processDepsAsFwd(ft: *FlushTypes, deps: *const CTypeDependencies) void { + const resolved = deps.get(ft.c); + for (resolved.type) |pool_index| ft.doTypeFwd(pool_index); + for (resolved.type_fwd) |pool_index| ft.doTypeFwd(pool_index); + for (resolved.errunion_type) |pool_index| ft.doErrunionTypeFwd(pool_index); + for (resolved.errunion_type_fwd) |pool_index| ft.doErrunionTypeFwd(pool_index); + for (resolved.aligned_type_fwd) |pool_index| ft.doAlignedTypeFwd(pool_index); + } + + fn doAlignedTypeFwd(ft: *FlushTypes, pool_index: link.ConstPool.Index) void { + const c = ft.c; + if (ft.aligned_status.contains(pool_index)) return; + if (ft.aligned_types.getIndex(pool_index)) |i| { + const rendered = &c.types.items[@intFromEnum(pool_index)]; + ft.processDepsAsFwd(&rendered.deps); + ft.f.appendBufAssumeCapacity(ft.aligned_type_strings[i]); + } + ft.aligned_status.putAssumeCapacity(pool_index, {}); + } + fn doTypeFwd(ft: *FlushTypes, pool_index: link.ConstPool.Index) void { + const c = ft.c; + if (ft.status.contains(pool_index)) return; + const rendered = &c.types.items[@intFromEnum(pool_index)]; + if (rendered.fwd_decl.len > 0) { + ft.f.appendBufAssumeCapacity(rendered.fwd_decl.get(c)); + ft.status.putAssumeCapacityNoClobber(pool_index, false); + } else { + ft.processDepsAsFwd(&rendered.definition_deps); + const gop = ft.status.getOrPutAssumeCapacity(pool_index); + if (!gop.found_existing) { + gop.value_ptr.* = false; + ft.f.appendBufAssumeCapacity(rendered.definition.get(c)); + } + } + } + fn doType(ft: *FlushTypes, pool_index: link.ConstPool.Index) void { + const c = ft.c; + if (ft.status.get(pool_index)) |completed| { + if (completed) return; + } + const rendered = &c.types.items[@intFromEnum(pool_index)]; + ft.processDeps(&rendered.definition_deps); + if (rendered.fwd_decl.len == 0 and ft.status.contains(pool_index)) { + // `doTypeFwd` already rendered the defintion, we just had to complete the type by + // fully resolving its dependencies. + } else if (rendered.definition.len > 0) { + ft.f.appendBufAssumeCapacity(rendered.definition.get(c)); + } else if (!ft.status.contains(pool_index)) { + // The type will never be completed, but it must be forward declared to avoid it being + // declared in the wrong scope. + ft.f.appendBufAssumeCapacity(rendered.fwd_decl.get(c)); + } + ft.status.putAssumeCapacity(pool_index, true); + } + fn doErrunionTypeFwd(ft: *FlushTypes, pool_index: link.ConstPool.Index) void { + const c = ft.c; + const gop = ft.errunion_status.getOrPutAssumeCapacity(pool_index); + if (gop.found_existing) return; + const rendered = &c.types.items[@intFromEnum(pool_index)]; + ft.f.appendBufAssumeCapacity(rendered.errunion_fwd_decl.get(c)); + gop.value_ptr.* = false; + } + fn doErrunionType(ft: *FlushTypes, pool_index: link.ConstPool.Index) void { + const c = ft.c; + if (ft.errunion_status.get(pool_index)) |completed| { + if (completed) return; + } + const rendered = &c.types.items[@intFromEnum(pool_index)]; + ft.processDeps(&rendered.deps); + if (rendered.errunion_definition.len > 0) { + ft.f.appendBufAssumeCapacity(rendered.errunion_definition.get(c)); + } else { + // The error union type will never be completed, but forward declare it to avoid the + // type being first declared in a different scope. + ft.f.appendBufAssumeCapacity(rendered.errunion_fwd_decl.get(c)); + } + ft.errunion_status.putAssumeCapacity(pool_index, true); + } +}; diff --git a/src/link/DebugConstPool.zig b/src/link/ConstPool.zig similarity index 83% rename from src/link/DebugConstPool.zig rename to src/link/ConstPool.zig index eb8c60b6f9d058d12ddcfecc39b92931f6403998..1282ad67c4b5fc49bac914bfeede2da46301ee91 100644 --- a/src/link/DebugConstPool.zig +++ b/src/link/ConstPool.zig @@ -9,14 +9,11 @@ /// Indices into the pool are dense, and constants are never removed from the pool, so the debug /// info implementation can store information for each one with a simple `ArrayList`. /// -/// To use `DebugConstPool`, the debug info implementation is required to: -/// * forward `updateContainerType` calls to its `DebugConstPool` -/// * expose some callback functions---see functions in `DebugInfo` +/// To use `ConstPool`, the debug info implementation is required to: +/// * forward `updateContainerType` calls to its `ConstPool` +/// * expose some callback functions---see functions in `User` /// * ensure that any `get` call is eventually followed by a `flushPending` call -/// -/// TODO: everything in this file should have the error set 'Allocator.Error', but right now the -/// self-hosted linkers can return all kinds of crap for some reason. This needs fixing. -const DebugConstPool = @This(); +const ConstPool = @This(); values: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), pending: std.ArrayList(Index), @@ -24,7 +21,7 @@ complete_containers: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), container_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, ContainerDepEntry.Index), container_dep_entries: std.ArrayList(ContainerDepEntry), -pub const empty: DebugConstPool = .{ +pub const empty: ConstPool = .{ .values = .empty, .pending = .empty, .complete_containers = .empty, @@ -32,7 +29,7 @@ pub const empty: DebugConstPool = .{ .container_dep_entries = .empty, }; -pub fn deinit(pool: *DebugConstPool, gpa: Allocator) void { +pub fn deinit(pool: *ConstPool, gpa: Allocator) void { pool.values.deinit(gpa); pool.pending.deinit(gpa); pool.complete_containers.deinit(gpa); @@ -42,13 +39,14 @@ pub fn deinit(pool: *DebugConstPool, gpa: Allocator) void { pub const Index = enum(u32) { _, - pub fn val(i: Index, pool: *const DebugConstPool) InternPool.Index { + pub fn val(i: Index, pool: *const ConstPool) InternPool.Index { return pool.values.keys()[@intFromEnum(i)]; } }; -pub const DebugInfo = union(enum) { +pub const User = union(enum) { dwarf: *@import("Dwarf.zig"), + c: *@import("C.zig"), llvm: @import("../codegen/llvm.zig").Object.Ptr, /// Inform the debug info implementation that the new constant `val` was added to the pool at @@ -56,12 +54,12 @@ pub const DebugInfo = union(enum) { /// that there will eventually be a call to either `updateConst` or `updateConstIncomplete` /// following the `addConst` call, to actually populate the constant's debug info. fn addConst( - di: DebugInfo, + user: User, pt: Zcu.PerThread, index: Index, val: InternPool.Index, - ) !void { - switch (di) { + ) Allocator.Error!void { + switch (user) { inline else => |impl| return impl.addConst(pt, index, val), } } @@ -71,12 +69,12 @@ pub const DebugInfo = union(enum) { /// * If it is a type, its layout is known. /// * Otherwise, the layout of its type is known. fn updateConst( - di: DebugInfo, + user: User, pt: Zcu.PerThread, index: Index, val: InternPool.Index, - ) !void { - switch (di) { + ) Allocator.Error!void { + switch (user) { inline else => |impl| return impl.updateConst(pt, index, val), } } @@ -87,12 +85,12 @@ pub const DebugInfo = union(enum) { /// initialized so never had its layout resolved). Instead, the implementation must emit some /// form of placeholder entry representing an incomplete/unknown constant. fn updateConstIncomplete( - di: DebugInfo, + user: User, pt: Zcu.PerThread, index: Index, val: InternPool.Index, - ) !void { - switch (di) { + ) Allocator.Error!void { + switch (user) { inline else => |impl| return impl.updateConstIncomplete(pt, index, val), } } @@ -100,7 +98,7 @@ pub const DebugInfo = union(enum) { const ContainerDepEntry = extern struct { next: ContainerDepEntry.Index.Optional, - depender: DebugConstPool.Index, + depender: ConstPool.Index, const Index = enum(u32) { _, const Optional = enum(u32) { @@ -116,7 +114,7 @@ const ContainerDepEntry = extern struct { fn toOptional(i: ContainerDepEntry.Index) Optional { return @enumFromInt(@intFromEnum(i)); } - fn ptr(i: ContainerDepEntry.Index, pool: *DebugConstPool) *ContainerDepEntry { + fn ptr(i: ContainerDepEntry.Index, pool: *ConstPool) *ContainerDepEntry { return &pool.container_dep_entries.items[@intFromEnum(i)]; } }; @@ -125,12 +123,12 @@ const ContainerDepEntry = extern struct { /// Calls to `link.File.updateContainerType` must be forwarded to this function so that the debug /// constant pool has up-to-date information about the resolution status of types. pub fn updateContainerType( - pool: *DebugConstPool, + pool: *ConstPool, pt: Zcu.PerThread, - di: DebugInfo, + user: User, container_ty: InternPool.Index, success: bool, -) !void { +) Allocator.Error!void { if (success) { const gpa = pt.zcu.comp.gpa; try pool.complete_containers.put(gpa, container_ty, {}); @@ -139,18 +137,18 @@ pub fn updateContainerType( } var opt_dep = pool.container_deps.get(container_ty); while (opt_dep) |dep| : (opt_dep = dep.ptr(pool).next.unwrap()) { - try pool.update(pt, di, dep.ptr(pool).depender); + try pool.update(pt, user, dep.ptr(pool).depender); } } /// After this is called, there may be a constant for which debug information (complete or not) has /// not yet been emitted, so the user must call `flushPending` at some point after this call. -pub fn get(pool: *DebugConstPool, pt: Zcu.PerThread, di: DebugInfo, val: InternPool.Index) !DebugConstPool.Index { +pub fn get(pool: *ConstPool, pt: Zcu.PerThread, user: User, val: InternPool.Index) Allocator.Error!ConstPool.Index { const zcu = pt.zcu; const ip = &zcu.intern_pool; const gpa = zcu.comp.gpa; const gop = try pool.values.getOrPut(gpa, val); - const index: DebugConstPool.Index = @enumFromInt(gop.index); + const index: ConstPool.Index = @enumFromInt(gop.index); if (!gop.found_existing) { const ty: Type = switch (ip.typeOf(val)) { .type_type => if (ip.isUndef(val)) .type else .fromInterned(val), @@ -158,17 +156,17 @@ pub fn get(pool: *DebugConstPool, pt: Zcu.PerThread, di: DebugInfo, val: InternP }; try pool.registerTypeDeps(index, ty, zcu); try pool.pending.append(gpa, index); - try di.addConst(pt, index, val); + try user.addConst(pt, index, val); } return index; } -pub fn flushPending(pool: *DebugConstPool, pt: Zcu.PerThread, di: DebugInfo) !void { +pub fn flushPending(pool: *ConstPool, pt: Zcu.PerThread, user: User) Allocator.Error!void { while (pool.pending.pop()) |pending_ty| { - try pool.update(pt, di, pending_ty); + try pool.update(pt, user, pending_ty); } } -fn update(pool: *DebugConstPool, pt: Zcu.PerThread, di: DebugInfo, index: DebugConstPool.Index) !void { +fn update(pool: *ConstPool, pt: Zcu.PerThread, user: User, index: ConstPool.Index) Allocator.Error!void { const zcu = pt.zcu; const ip = &zcu.intern_pool; const val = index.val(pool); @@ -177,12 +175,12 @@ fn update(pool: *DebugConstPool, pt: Zcu.PerThread, di: DebugInfo, index: DebugC else => |ty| .fromInterned(ty), }; if (pool.checkType(ty, zcu)) { - try di.updateConst(pt, index, val); + try user.updateConst(pt, index, val); } else { - try di.updateConstIncomplete(pt, index, val); + try user.updateConstIncomplete(pt, index, val); } } -fn checkType(pool: *const DebugConstPool, ty: Type, zcu: *const Zcu) bool { +fn checkType(pool: *const ConstPool, ty: Type, zcu: *const Zcu) bool { if (ty.isGenericPoison()) return true; return switch (ty.zigTypeTag(zcu)) { .type, @@ -227,7 +225,7 @@ fn checkType(pool: *const DebugConstPool, ty: Type, zcu: *const Zcu) bool { }, }; } -fn registerTypeDeps(pool: *DebugConstPool, root: Index, ty: Type, zcu: *const Zcu) Allocator.Error!void { +fn registerTypeDeps(pool: *ConstPool, root: Index, ty: Type, zcu: *const Zcu) Allocator.Error!void { if (ty.isGenericPoison()) return; switch (ty.zigTypeTag(zcu)) { .type, diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index e64346c17c52d305519b575101d70343cf2ef250..38021aa42f0a4b4211889afeb514e6ed3cda6933 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -18,7 +18,6 @@ const codegen = @import("../codegen.zig"); const dev = @import("../dev.zig"); const link = @import("../link.zig"); const target_info = @import("../target.zig"); -const DebugConstPool = link.DebugConstPool; gpa: Allocator, bin_file: *link.File, @@ -26,10 +25,10 @@ format: DW.Format, endian: std.builtin.Endian, address_size: AddressSize, -const_pool: DebugConstPool, +const_pool: link.ConstPool, mods: std.AutoArrayHashMapUnmanaged(*Module, ModInfo), -/// Indices are `DebugConstPool.Index`. +/// Indices are `link.ConstPool.Index`. values: std.ArrayList(struct { Unit.Index, Entry.Index }), navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, Entry.Index), decls: std.AutoArrayHashMapUnmanaged(InternPool.TrackedInst.Index, Entry.Index), @@ -1038,7 +1037,7 @@ const Entry = struct { const zcu = dwarf.bin_file.comp.zcu.?; const ip = &zcu.intern_pool; for (0.., dwarf.values.items) |raw_index, unit_and_entry| { - const index: DebugConstPool.Index = @enumFromInt(raw_index); + const index: link.ConstPool.Index = @enumFromInt(raw_index); const val = index.val(&dwarf.const_pool); const val_unit, const val_entry = unit_and_entry; if (sec.getUnit(val_unit) == unit and unit.getEntry(val_entry) == entry) @@ -3291,8 +3290,14 @@ pub fn updateContainerType( ) !void { try dwarf.const_pool.updateContainerType(pt, .{ .dwarf = dwarf }, ty, success); } -/// Should only be called by the `DebugConstPool` implementation. -pub fn addConst(dwarf: *Dwarf, pt: Zcu.PerThread, index: DebugConstPool.Index, val: InternPool.Index) !void { +/// Should only be called by the `link.ConstPool` implementation. +pub fn addConst(dwarf: *Dwarf, pt: Zcu.PerThread, index: link.ConstPool.Index, val: InternPool.Index) Allocator.Error!void { + addConstInner(dwarf, pt, index, val) catch |err| switch (err) { + error.OutOfMemory => |e| return e, + else => |e| std.debug.panic("DWARF TODO: '{t}' while registering constant\n", .{e}), + }; +} +fn addConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, index: link.ConstPool.Index, val: InternPool.Index) !void { const zcu = pt.zcu; const ip = &zcu.intern_pool; @@ -3321,11 +3326,17 @@ pub fn addConst(dwarf: *Dwarf, pt: Zcu.PerThread, index: DebugConstPool.Index, v assert(@intFromEnum(index) == dwarf.values.items.len); try dwarf.values.append(dwarf.gpa, .{ unit, entry }); } -/// Should only be called by the `DebugConstPool` implementation. +/// Should only be called by the `link.ConstPool` implementation. /// /// Emits a "dummy" DIE for the given comptime-only value (which may be a type). For types, this is /// an opaque type. Otherwise, it is an undefined value of the value's type. -pub fn updateConstIncomplete(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: DebugConstPool.Index, value_index: InternPool.Index) !void { +pub fn updateConstIncomplete(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.ConstPool.Index, value_index: InternPool.Index) Allocator.Error!void { + updateConstIncompleteInner(dwarf, pt, debug_const_index, value_index) catch |err| switch (err) { + error.OutOfMemory => |e| return e, + else => |e| std.debug.panic("DWARF TODO: '{t}' while updating incomplete constant\n", .{e}), + }; +} +fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.ConstPool.Index, value_index: InternPool.Index) !void { const zcu = pt.zcu; const val: Value = .fromInterned(value_index); @@ -3380,10 +3391,16 @@ pub fn updateConstIncomplete(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index try dwarf.debug_info.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_info.written()); try dwarf.debug_loclists.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_loclists.written()); } -/// Should only be called by the `DebugConstPool` implementation. +/// Should only be called by the `link.ConstPool` implementation. /// /// Emits a DIE for the given comptime-only value (which may be a type). -pub fn updateConst(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: DebugConstPool.Index, value_index: InternPool.Index) !void { +pub fn updateConst(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.ConstPool.Index, value_index: InternPool.Index) Allocator.Error!void { + updateConstInner(dwarf, pt, debug_const_index, value_index) catch |err| switch (err) { + error.OutOfMemory => |e| return e, + else => |e| std.debug.panic("DWARF TODO: '{t}' while updating constant\n", .{e}), + }; +} +fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.ConstPool.Index, value_index: InternPool.Index) !void { const zcu = pt.zcu; const ip = &zcu.intern_pool; diff --git a/src/link/Elf.zig b/src/link/Elf.zig index dd4c2abd248eafea4b6705a79a5c15eaf3b409d2..c45f73d97a35c8e6435bfded3f5f2defddd55ac4 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1716,19 +1716,8 @@ pub fn updateContainerType( if (build_options.skip_non_native and builtin.object_format != .elf) { @panic("Attempted to compile for object format that was disabled by build configuration"); } - const zcu = pt.zcu; - const gpa = zcu.gpa; return self.zigObjectPtr().?.updateContainerType(pt, ty, success) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, - else => |e| { - try zcu.failed_types.putNoClobber(gpa, ty, try Zcu.ErrorMsg.create( - gpa, - zcu.typeSrcLoc(ty), - "failed to update container type: {s}", - .{@errorName(e)}, - )); - return error.TypeFailureReported; - }, }; } -- 2.54.0 From 7bfe96fddcdc27db58a9a758b9e9aed2ed3370cc Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 22 Feb 2026 19:43:10 +0000 Subject: [PATCH 49/79] frontend: fix bugs did you know that if semantic analysis fails you should return error.AnalysisFail? --- src/Sema.zig | 17 +++++++++++------ src/Zcu/PerThread.zig | 12 +++++++----- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 79a97a3e379615f3787072565454acdc501d1fba..38fada09b0357a8a5c1012d5fc2d3c3d7d959a60 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -23393,8 +23393,13 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins const field_name_src = block.builtinCallArgSrc(extra.src_node, 0); const field_ptr_src = block.builtinCallArgSrc(extra.src_node, 1); - const parent_ptr_ty = try sema.resolveDestType(block, inst_src, extra.parent_ptr_type, .remove_eu, "@fieldParentPtr"); - try sema.checkPtrType(block, inst_src, parent_ptr_ty, true); + const maybe_opt_parent_ptr_ty = try sema.resolveDestType(block, inst_src, extra.parent_ptr_type, .remove_eu, "@fieldParentPtr"); + try sema.checkPtrType(block, inst_src, maybe_opt_parent_ptr_ty, true); + const parent_ptr_ty = switch (maybe_opt_parent_ptr_ty.zigTypeTag(zcu)) { + .optional => maybe_opt_parent_ptr_ty.optionalChild(zcu), + .pointer => maybe_opt_parent_ptr_ty, + else => unreachable, + }; const parent_ptr_info = parent_ptr_ty.ptrInfo(zcu); if (parent_ptr_info.flags.size != .one) { return sema.fail(block, inst_src, "expected single pointer type, found '{f}'", .{parent_ptr_ty.fmt(pt)}); @@ -23441,7 +23446,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins ); const unaligned_parent_ptr_ty = try pt.ptrType(info: { - var info = parent_ptr_ty.ptrInfo(zcu); + var info = parent_ptr_info; info.flags.alignment = hypothetical_field_ptr_ty.ptrAlignment(zcu); break :info info; }); @@ -23512,7 +23517,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins // a field pointer of type `*align(1) u16`. switch (hypothetical_field_ptr_ty.ptrAlignment(zcu).order(parent_ptr_ty.ptrAlignment(zcu))) { .gt => unreachable, // getting a field pointer can never increase alignment - .eq => return unaligned_parent_ptr, + .eq => return sema.coerce(block, maybe_opt_parent_ptr_ty, unaligned_parent_ptr, inst_src), .lt => if (flags.align_cast) { // Go through `ptrCastFull` for the safety check. return sema.ptrCastFull( @@ -23521,7 +23526,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins inst_src, unaligned_parent_ptr, inst_src, - parent_ptr_ty, + maybe_opt_parent_ptr_ty, "@fieldParentPtr", ); } else return sema.failWithOwnedErrorMsg(block, msg: { @@ -25184,7 +25189,7 @@ pub fn explainWhyTypeIsNotExtern( } }, .@"union" => { - const union_obj = zcu.intern_pool.loadStructType(ty.toIntern()); + const union_obj = zcu.intern_pool.loadUnionType(ty.toIntern()); switch (union_obj.layout) { .auto => try sema.errNote(src_loc, msg, "union with automatic layout has no guaranteed in-memory representation", .{}), .@"extern" => unreachable, diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index ef22213c9a9b143c2a3ce47ca46b99e362c51765..06377692c95e30cdd59fe374b49e09a3cd23995e 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -1393,17 +1393,17 @@ pub fn ensureTypeLayoutUpToDate( .@"union" => Sema.type_resolution.resolveUnionLayout(&sema, ty), else => unreachable, }; - const new_success: bool = if (result) s: { - break :s true; + const new_failed: bool = if (result) failed: { + break :failed false; } else |err| switch (err) { - error.AnalysisFail => success: { + error.AnalysisFail => failed: { if (!zcu.failed_analysis.contains(anal_unit)) { // If this unit caused the error, it would have an entry in `failed_analysis`. // Since it does not, this must be a transitive failure. try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)}); } - break :success false; + break :failed true; }, error.OutOfMemory, error.Canceled, @@ -1422,8 +1422,10 @@ pub fn ensureTypeLayoutUpToDate( comp.link_prog_node.increaseEstimatedTotalItems(1); try comp.link_queue.enqueueZcu(comp, pt.tid, .{ .debug_update_container_type = .{ .ty = ty.toIntern(), - .success = new_success, + .success = !new_failed, } }); + + if (new_failed) return error.AnalysisFail; } /// Ensures that the resolved value of the given `Nav` is fully up-to-date, performing re-analysis -- 2.54.0 From 160da8d6a4b82fa54f33e15025aaccc6f36f896f Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Mon, 23 Feb 2026 11:53:29 +0000 Subject: [PATCH 50/79] Dwarf: be even dumber about source locations --- src/link/Dwarf.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 38021aa42f0a4b4211889afeb514e6ed3cda6933..806a85ff23cb3a0b8ead4e6716b24de3b70995f5 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -3461,7 +3461,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co // without trying to tie them to a bogus source location. const src_loc: Zcu.LazySrcLoc = .{ .base_node_inst = inst: { - const mod_root_file_index = zcu.module_roots.get(dwarf.getUnitModule(unit)).?.unwrap().?; + const mod_root_file_index = zcu.module_roots.get(zcu.std_mod).?.unwrap().?; const mod_root_type_index = zcu.fileRootType(mod_root_file_index); break :inst ip.loadStructType(mod_root_type_index).zir_index; }, -- 2.54.0 From 2651b5ccdf2485172e9ba0345b9529733ee39273 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Mon, 23 Feb 2026 13:24:05 +0000 Subject: [PATCH 51/79] llvm: fix some bugs --- src/Sema.zig | 10 ++++++++++ src/Zcu/PerThread.zig | 10 ++++++++++ src/codegen/llvm.zig | 44 +++++++++++++++++++++++++++---------------- 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 38fada09b0357a8a5c1012d5fc2d3c3d7d959a60..fc5b147759df31eead062d8980961059ab7e5a2c 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -24756,6 +24756,16 @@ fn zirBuiltinExtern( } const ptr_info = ty.ptrInfo(zcu); + if (Type.fromInterned(ptr_info.child).zigTypeTag(zcu) == .@"fn") { + const func_type = ip.indexToKey(ptr_info.child).func_type; + for (func_type.param_types.get(ip)) |param_ty_ip| { + const param_ty: Type = .fromInterned(param_ty_ip); + if (param_ty.isPtrAtRuntime(zcu) or param_ty.isSliceAtRuntime(zcu)) { + // LLVM wants this information for an "align" attribute on the parameter. + try sema.ensureLayoutResolved(param_ty.nullablePtrElem(zcu), ty_src, .parameter); + } + } + } const extern_val = try pt.getExtern(.{ .name = options.name, .ty = ptr_info.child, diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 06377692c95e30cdd59fe374b49e09a3cd23995e..ee788c884e327fffe1fe5a1e6f09854ba6932803 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -1691,6 +1691,16 @@ fn analyzeNavVal( const lib_name_src = block.src(.{ .node_offset_lib_name = .zero }); try sema.handleExternLibName(&block, lib_name_src, l); } + if (nav_ty.zigTypeTag(zcu) == .@"fn") { + const func_type = ip.indexToKey(nav_ty.toIntern()).func_type; + for (func_type.param_types.get(ip)) |param_ty_ip| { + const param_ty: Type = .fromInterned(param_ty_ip); + if (param_ty.isPtrAtRuntime(zcu) or param_ty.isSliceAtRuntime(zcu)) { + // LLVM wants this information for an "align" attribute on the parameter. + try sema.ensureLayoutResolved(param_ty.nullablePtrElem(zcu), ty_src, .parameter); + } + } + } break :val .fromInterned(try pt.getExtern(.{ .name = old_nav.name, .ty = nav_ty.toIntern(), diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index f8d1310b1c7693c8b2f46fb03debc802d7eba69b..972a536eef0989e5c8f3055a4635f1e0397d32ba 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2327,16 +2327,21 @@ pub const Object = struct { const layout = Type.getUnionLayout(union_type, zcu); if (layout.payload_size == 0) { - const tag_member = try o.builder.debugMemberType( - try o.builder.metadataString("tag"), - null, // file - ty_fwd_ref, - 0, // line - try o.getDebugType(pt, enum_tag_ty), - layout.tag_size * 8, - layout.tag_align.toByteUnits().? * 8, - 0, // offset - ); + const fields_tuple: ?Builder.Metadata = fields: { + if (layout.tag_size == 0) break :fields null; + break :fields try o.builder.metadataTuple(&.{ + try o.builder.debugMemberType( + try o.builder.metadataString("tag"), + null, // file + ty_fwd_ref, + 0, // line + try o.getDebugType(pt, enum_tag_ty), + layout.tag_size * 8, + layout.tag_align.toByteUnits().? * 8, + 0, // offset + ), + }); + }; return o.builder.debugStructType( name, file, @@ -2345,7 +2350,7 @@ pub const Object = struct { null, // underlying type ty.abiSize(zcu) * 8, ty.abiAlignment(zcu).toByteUnits().? * 8, - try o.builder.metadataTuple(&.{tag_member}), + fields_tuple, ); } @@ -3141,12 +3146,16 @@ pub const Object = struct { var struct_kind: Builder.Type.Structure.Kind = .normal; // When we encounter a zero-bit field, we place it here so we know to map it to the next non-zero-bit field (if any). var it = struct_type.iterateRuntimeOrder(ip); + var max_field_ty_align: InternPool.Alignment = .@"1"; while (it.next()) |field_index| { const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); + const field_ty_align = field_ty.abiAlignment(zcu); + max_field_ty_align = max_field_ty_align.maxStrict(field_ty_align); + const prev_offset = offset; offset = struct_type.field_offsets.get(ip)[field_index]; - if (@ctz(offset) < field_ty.abiAlignment(zcu).toLog2Units()) { - struct_kind = .@"packed"; + if (@ctz(offset) < field_ty_align.toLog2Units()) { + struct_kind = .@"packed"; // prevent unexpected padding before this field } const padding_len = offset - prev_offset; @@ -3184,6 +3193,9 @@ pub const Object = struct { o.gpa, try o.builder.arrayType(padding_len, .i8), ); + if (@ctz(offset) < max_field_ty_align.toLog2Units()) { + struct_kind = .@"packed"; // prevent unexpected trailing padding + } } const ty = try o.builder.opaqueType(try o.builder.string(t.containerTypeName(ip).toSlice(ip))); @@ -3883,7 +3895,7 @@ pub const Object = struct { const payload = try o.lowerValue(pt, un.val); const payload_ty = payload.typeOf(&o.builder); if (payload_ty != union_ty.structFields(&o.builder)[ - @intFromBool(layout.tag_align.compare(.gte, layout.payload_align)) + @intFromBool(layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)) ]) need_unnamed = true; const field_size = field_ty.abiSize(zcu); if (field_size == layout.payload_size) break :p payload; @@ -6806,7 +6818,7 @@ pub const FuncGen = struct { .@"union" => { const union_llvm_ty = try o.lowerType(pt, struct_ty); const layout = struct_ty.unionGetLayout(zcu); - const payload_index = @intFromBool(layout.tag_align.compare(.gte, layout.payload_align)); + const payload_index = @intFromBool(layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)); const field_ptr = try self.wip.gepStruct(union_llvm_ty, struct_llvm_val, payload_index, ""); const payload_alignment = layout.payload_align.toLlvm(); @@ -11063,7 +11075,7 @@ pub const FuncGen = struct { .@"union" => { const layout = struct_ty.unionGetLayout(zcu); if (layout.payload_size == 0 or struct_ty.containerLayout(zcu) == .@"packed") return struct_ptr; - const payload_index = @intFromBool(layout.tag_align.compare(.gte, layout.payload_align)); + const payload_index = @intFromBool(layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)); const union_llvm_ty = try o.lowerType(pt, struct_ty); return self.wip.gepStruct(union_llvm_ty, struct_ptr, payload_index, ""); }, -- 2.54.0 From 82be338964ed5bbc596a48075e52724fdf92cde4 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Mon, 23 Feb 2026 13:24:54 +0000 Subject: [PATCH 52/79] aro: stop depending on ArrayList default field values --- lib/compiler/aro/aro/InitList.zig | 20 +++++++++++++------- lib/compiler/aro/aro/Parser.zig | 6 +++--- lib/compiler/aro/aro/Toolchain.zig | 6 +++--- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/lib/compiler/aro/aro/InitList.zig b/lib/compiler/aro/aro/InitList.zig index 9d8af869d75851b43b752427423f872b0493932e..ed7af8f998b9e37acd6d83e6c73ec6370b071783 100644 --- a/lib/compiler/aro/aro/InitList.zig +++ b/lib/compiler/aro/aro/InitList.zig @@ -22,9 +22,15 @@ const Item = struct { const InitList = @This(); -list: std.ArrayList(Item) = .empty, -node: Node.OptIndex = .null, -tok: TokenIndex = 0, +list: std.ArrayList(Item), +node: Node.OptIndex, +tok: TokenIndex, + +pub const empty: InitList = .{ + .list = .empty, + .node = .null, + .tok = 0, +}; /// Deinitialize freeing all memory. pub fn deinit(il: *InitList, gpa: Allocator) void { @@ -43,7 +49,7 @@ pub fn find(il: *InitList, gpa: Allocator, index: u64) !*InitList { if (il.list.items.len == 0) { const item = try il.list.addOne(gpa); item.* = .{ - .list = .{}, + .list = .empty, .index = index, }; return &item.list; @@ -51,7 +57,7 @@ pub fn find(il: *InitList, gpa: Allocator, index: u64) !*InitList { // Append a new value to the end of the list. const new = try il.list.addOne(gpa); new.* = .{ - .list = .{}, + .list = .empty, .index = index, }; return &new.list; @@ -70,7 +76,7 @@ pub fn find(il: *InitList, gpa: Allocator, index: u64) !*InitList { // Insert a new value into a sorted position. try il.list.insert(gpa, left, .{ - .list = .{}, + .list = .empty, .index = index, }); return &il.list.items[left].list; @@ -78,7 +84,7 @@ pub fn find(il: *InitList, gpa: Allocator, index: u64) !*InitList { test "basic usage" { const gpa = testing.allocator; - var il: InitList = .{}; + var il: InitList = .empty; defer il.deinit(gpa); { diff --git a/lib/compiler/aro/aro/Parser.zig b/lib/compiler/aro/aro/Parser.zig index fc21ee4d0b5f25f8f28b08c157d80a59b83adda8..6e60dbd623e6c729375c4e522cd4fbd43cb43b4c 100644 --- a/lib/compiler/aro/aro/Parser.zig +++ b/lib/compiler/aro/aro/Parser.zig @@ -3977,7 +3977,7 @@ fn initializer(p: *Parser, init_qt: QualType) Error!Result { final_init_qt = .invalid; } - var il: InitList = .{}; + var il: InitList = .empty; defer il.deinit(p.comp.gpa); try p.initializerItem(&il, final_init_qt, l_brace); @@ -4028,12 +4028,12 @@ fn initializerItem(p: *Parser, il: *InitList, init_qt: QualType, l_brace: TokenI try p.err(first_tok, .initializer_overrides, .{}); try p.err(item.il.tok, .previous_initializer, .{}); item.il.deinit(gpa); - item.il.* = .{}; + item.il.* = .empty; } try p.initializerItem(item.il, item.qt, inner_l_brace); } else { // discard further values - var tmp_il: InitList = .{}; + var tmp_il: InitList = .empty; defer tmp_il.deinit(gpa); try p.initializerItem(&tmp_il, .invalid, inner_l_brace); if (!warned_excess) try p.err(first_tok, switch (init_qt.base(p.comp).type) { diff --git a/lib/compiler/aro/aro/Toolchain.zig b/lib/compiler/aro/aro/Toolchain.zig index 0aa9d76fc88a176f9ac5690fbf40dd0563b48aab..9a923c08461ddb36dc055f81de813ddaac90e99c 100644 --- a/lib/compiler/aro/aro/Toolchain.zig +++ b/lib/compiler/aro/aro/Toolchain.zig @@ -43,13 +43,13 @@ const Toolchain = @This(); driver: *Driver, /// The list of toolchain specific path prefixes to search for libraries. -library_paths: PathList = .{}, +library_paths: PathList = .empty, /// The list of toolchain specific path prefixes to search for files. -file_paths: PathList = .{}, +file_paths: PathList = .empty, /// The list of toolchain specific path prefixes to search for programs. -program_paths: PathList = .{}, +program_paths: PathList = .empty, selected_multilib: Multilib = .{}, -- 2.54.0 From 0075c5a1d5ad1198b16e6a1c390c985a8e4354de Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Fri, 27 Feb 2026 10:27:29 +0000 Subject: [PATCH 53/79] Type: tiny refactors --- src/Type.zig | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/Type.zig b/src/Type.zig index 1eab734882f8d25b246e4bc754004d4ca2397e39..60adb6f10ffb7601d85eb337ff05cafe452b1cba 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -690,9 +690,9 @@ pub fn hasRuntimeBits(ty: Type, zcu: *const Zcu) bool { }; } -/// true if and only if the type has a well-defined memory layout -/// readFrom/writeToMemory are supported only for types with a well- -/// defined memory layout +/// Returns `true` iff the memory layout of `ty` is defined by the Zig language specification. +/// +/// Does not require `ty` to be resolved. pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool { const ip = &zcu.intern_pool; return switch (ip.indexToKey(ty.toIntern())) { @@ -3140,9 +3140,16 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool }, }; }, - .array => { - if (position == .ret_ty or position == .param_ty) return false; - return ty.childType(zcu).validateExtern(.element, zcu); + .array => switch (position) { + .ret_ty, + .param_ty, + => false, + + .union_field, + .struct_field, + .element, + .other, + => ty.childType(zcu).validateExtern(.element, zcu), }, .vector => ty.childType(zcu).validateExtern(.element, zcu), .optional => ty.isPtrLikeOptional(zcu), -- 2.54.0 From 51c23f7ba4f09f26f53b21299a456f2ed9d7839e Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Fri, 27 Feb 2026 10:40:12 +0000 Subject: [PATCH 54/79] compiler: split default field values back out from layout resolution I was trying out combining struct layout resolution with resolution of default field values, but it broke a few cases which it's not clear we want to break. The simplest such case was a struct with a field which was a slice of itself, with a default value of `&.{}`. So, at least for now, I'm accepting defeat and splitting this back out. This allows a couple of behavior tests which were removed to be re-introduced---I will do that in the commit following this one. I have *not* made this separate phase of resolution "lazy": instead, it is tied to layout resolution, in the sense that if a struct's layout is referenced, then its default field values are also referenced. I chose this approach for simplicity---not of the implementation (it's actually slightly *more* code to do it this way!), but in terms of the language specification. I think this behavior is easier to understand and keep in your head. It can be easily changed in future if we decide we want to. This partially reverts the commit titled "compiler: merge struct default value resolution into layout resolution". --- src/Compilation.zig | 6 +- src/IncrementalDebugServer.zig | 4 +- src/InternPool.zig | 18 ++- src/Sema.zig | 56 ++++++---- src/Sema/LowerZon.zig | 1 + src/Sema/type_resolution.zig | 198 ++++++++++++++++++++++++++------- src/Zcu.zig | 28 ++++- src/Zcu/PerThread.zig | 147 +++++++++++++++++++++++- src/link/Dwarf.zig | 10 +- 9 files changed, 396 insertions(+), 72 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index a4e712826d4a04f3ca0e6f15475def928a3562ad..dad807fcbef769a4f92cc38848f2292481866e95 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -3647,6 +3647,7 @@ const Header = extern struct { nav_val_deps_len: u32, nav_ty_deps_len: u32, type_layout_deps_len: u32, + struct_defaults_deps_len: u32, func_ies_deps_len: u32, zon_file_deps_len: u32, embed_file_deps_len: u32, @@ -3696,6 +3697,7 @@ pub fn saveState(comp: *Compilation) !void { .nav_val_deps_len = @intCast(ip.nav_val_deps.count()), .nav_ty_deps_len = @intCast(ip.nav_ty_deps.count()), .type_layout_deps_len = @intCast(ip.type_layout_deps.count()), + .struct_defaults_deps_len = @intCast(ip.struct_defaults_deps.count()), .func_ies_deps_len = @intCast(ip.func_ies_deps.count()), .zon_file_deps_len = @intCast(ip.zon_file_deps.count()), .embed_file_deps_len = @intCast(ip.embed_file_deps.count()), @@ -3720,7 +3722,7 @@ pub fn saveState(comp: *Compilation) !void { }, }); - try bufs.ensureTotalCapacityPrecise(24 + 9 * pt_headers.items.len); + try bufs.ensureTotalCapacityPrecise(26 + 9 * pt_headers.items.len); addBuf(&bufs, mem.asBytes(&header)); addBuf(&bufs, @ptrCast(pt_headers.items)); @@ -3732,6 +3734,8 @@ pub fn saveState(comp: *Compilation) !void { addBuf(&bufs, @ptrCast(ip.nav_ty_deps.values())); addBuf(&bufs, @ptrCast(ip.type_layout_deps.keys())); addBuf(&bufs, @ptrCast(ip.type_layout_deps.values())); + addBuf(&bufs, @ptrCast(ip.struct_defaults_deps.keys())); + addBuf(&bufs, @ptrCast(ip.struct_defaults_deps.values())); addBuf(&bufs, @ptrCast(ip.func_ies_deps.keys())); addBuf(&bufs, @ptrCast(ip.func_ies_deps.values())); addBuf(&bufs, @ptrCast(ip.zon_file_deps.keys())); diff --git a/src/IncrementalDebugServer.zig b/src/IncrementalDebugServer.zig index 782b34320586299b259336e70cca63d9fba32376..7d0dc8e89b6fd9fd257733839e924de1ce92a25f 100644 --- a/src/IncrementalDebugServer.zig +++ b/src/IncrementalDebugServer.zig @@ -307,7 +307,7 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const switch (dependee) { .src_hash, .namespace, .namespace_name, .zon_file, .embed_file => try w.print("{f}", .{zcu.fmtDependee(dependee)}), .nav_val, .nav_ty => |nav| try w.print("{t} {d}", .{ dependee, @intFromEnum(nav) }), - .type_layout, .func_ies => |ip_index| try w.print("{t} {d}", .{ dependee, @intFromEnum(ip_index) }), + .type_layout, .struct_defaults, .func_ies => |ip_index| try w.print("{t} {d}", .{ dependee, @intFromEnum(ip_index) }), .memoized_state => |stage| try w.print("memoized_state {s}", .{@tagName(stage)}), } try w.writeByte('\n'); @@ -374,6 +374,8 @@ fn parseAnalUnit(str: []const u8) ?AnalUnit { return .wrap(.{ .nav_ty = @enumFromInt(parseIndex(idx_str) orelse return null) }); } else if (std.mem.eql(u8, kind, "type_layout")) { return .wrap(.{ .type_layout = @enumFromInt(parseIndex(idx_str) orelse return null) }); + } else if (std.mem.eql(u8, kind, "struct_defaults")) { + return .wrap(.{ .struct_defaults = @enumFromInt(parseIndex(idx_str) orelse return null) }); } else if (std.mem.eql(u8, kind, "func")) { return .wrap(.{ .func = @enumFromInt(parseIndex(idx_str) orelse return null) }); } else if (std.mem.eql(u8, kind, "memoized_state")) { diff --git a/src/InternPool.zig b/src/InternPool.zig index ffabc7371b0c9d7221475b966fa059eccf275a48..da95ed6cc7a40f96b08a7e3a589afb5f93d568df 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -54,6 +54,9 @@ func_ies_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), /// Dependencies on the resolved layout of a `struct`, `union`, or `enum` type. /// Value is index into `dep_entries` of the first dependency on this type's layout. type_layout_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), +/// Dependencies on the resolved default field values of a `struct` type. +/// Value is index into `dep_entries` of the first dependency on this type's inits. +struct_defaults_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index), /// Dependencies on a ZON file. Triggered by `@import` of ZON. /// Value is index into `dep_entries` of the first dependency on this ZON file. zon_file_deps: std.AutoArrayHashMapUnmanaged(FileIndex, DepEntry.Index), @@ -108,6 +111,7 @@ pub const empty: InternPool = .{ .nav_ty_deps = .empty, .func_ies_deps = .empty, .type_layout_deps = .empty, + .struct_defaults_deps = .empty, .zon_file_deps = .empty, .embed_file_deps = .empty, .namespace_deps = .empty, @@ -419,6 +423,7 @@ pub const AnalUnit = packed struct(u64) { nav_val, nav_ty, type_layout, + struct_defaults, func, memoized_state, }; @@ -432,6 +437,8 @@ pub const AnalUnit = packed struct(u64) { nav_ty: Nav.Index, /// This `AnalUnit` resolves the layout of the given `struct`, `union`, or `enum` type. type_layout: InternPool.Index, + /// This `AnalUnit` resolves the default field values of the given `struct` type. + struct_defaults: InternPool.Index, /// This `AnalUnit` analyzes the body of the given runtime function. func: InternPool.Index, /// This `AnalUnit` resolves all state which is memoized in fields on `Zcu`. @@ -851,6 +858,7 @@ pub const Dependee = union(enum) { /// Index is the function, not its IES. func_ies: Index, type_layout: Index, + struct_defaults: Index, zon_file: FileIndex, embed_file: Zcu.EmbedFile.Index, namespace: TrackedInst.Index, @@ -904,6 +912,7 @@ pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyI .nav_ty => |x| ip.nav_ty_deps.get(x), .func_ies => |x| ip.func_ies_deps.get(x), .type_layout => |x| ip.type_layout_deps.get(x), + .struct_defaults => |x| ip.struct_defaults_deps.get(x), .zon_file => |x| ip.zon_file_deps.get(x), .embed_file => |x| ip.embed_file_deps.get(x), .namespace => |x| ip.namespace_deps.get(x), @@ -978,6 +987,7 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend .nav_ty => ip.nav_ty_deps, .func_ies => ip.func_ies_deps, .type_layout => ip.type_layout_deps, + .struct_defaults => ip.struct_defaults_deps, .zon_file => ip.zon_file_deps, .embed_file => ip.embed_file_deps, .namespace => ip.namespace_deps, @@ -6454,6 +6464,7 @@ pub fn deinit(ip: *InternPool, gpa: Allocator, io: Io) void { ip.nav_ty_deps.deinit(gpa); ip.func_ies_deps.deinit(gpa); ip.type_layout_deps.deinit(gpa); + ip.struct_defaults_deps.deinit(gpa); ip.zon_file_deps.deinit(gpa); ip.embed_file_deps.deinit(gpa); ip.namespace_deps.deinit(gpa); @@ -10619,6 +10630,7 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void { const nav_ty_deps_len = ip.nav_ty_deps.count(); const func_ies_deps_len = ip.func_ies_deps.count(); const type_layout_deps_len = ip.type_layout_deps.count(); + const struct_defaults_deps_len = ip.struct_defaults_deps.count(); const zon_file_deps_len = ip.zon_file_deps.count(); const embed_file_deps_len = ip.embed_file_deps.count(); const namespace_deps_len = ip.namespace_deps.count(); @@ -10629,6 +10641,7 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void { const nav_ty_deps_size = nav_ty_deps_len * 8; const func_ies_deps_size = func_ies_deps_len * 8; const type_layout_deps_size = type_layout_deps_len * 8; + const struct_defaults_deps_size = struct_defaults_deps_len * 8; const zon_file_deps_size = zon_file_deps_len * 8; const embed_file_deps_size = embed_file_deps_len * 8; const namespace_deps_size = namespace_deps_len * 8; @@ -10642,6 +10655,7 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void { \\ {d} nav_ty: {d} bytes \\ {d} func_ies: {d} bytes \\ {d} type_layout: {d} bytes + \\ {d} struct_defaults: {d} bytes \\ {d} zon_file: {d} bytes \\ {d} embed_file: {d} bytes \\ {d} namespace: {d} bytes @@ -10649,7 +10663,7 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void { \\ , .{ dep_entries_size + src_hash_deps_size + nav_val_deps_size + nav_ty_deps_size + - func_ies_deps_size + type_layout_deps_size + zon_file_deps_size + + func_ies_deps_size + type_layout_deps_size + struct_defaults_deps_size + zon_file_deps_size + embed_file_deps_size + namespace_deps_size + namespace_name_deps_size, dep_entries_len, dep_entries_size, @@ -10663,6 +10677,8 @@ fn dumpDependencyStatsFallible(ip: *const InternPool, w: *Io.Writer) !void { func_ies_deps_size, type_layout_deps_len, type_layout_deps_size, + struct_defaults_deps_len, + struct_defaults_deps_size, zon_file_deps_len, zon_file_deps_size, embed_file_deps_len, diff --git a/src/Sema.zig b/src/Sema.zig index fc5b147759df31eead062d8980961059ab7e5a2c..337f0d07cda987e326bdf5869949734578fcb9d7 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -4533,6 +4533,10 @@ fn validateStructInit( if (explicit) continue; if (struct_ty.structFieldIsComptime(i, zcu)) continue; + if (!struct_ty.isTuple(zcu)) { + try sema.ensureStructDefaultsResolved(struct_ty, init_src); + } + const default_val = struct_ty.structFieldDefaultValue(i, zcu) orelse { const field_name = struct_ty.structFieldName(i, zcu).unwrap() orelse { const template = "missing tuple field with index {d}"; @@ -5850,6 +5854,7 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void { .nav_val, .nav_ty, .type_layout, + .struct_defaults, .memoized_state, => return, // does nothing outside a function }; @@ -5868,6 +5873,7 @@ fn zirDisableIntrinsics(sema: *Sema) CompileError!void { .nav_val, .nav_ty, .type_layout, + .struct_defaults, .memoized_state, => return, // does nothing outside a function }; @@ -7091,7 +7097,14 @@ fn analyzeCall( }); if (func_ty_info.cc == .auto) { switch (sema.owner.unwrap()) { - .@"comptime", .nav_ty, .nav_val, .type_layout, .memoized_state => {}, + .@"comptime", + .nav_ty, + .nav_val, + .type_layout, + .struct_defaults, + .memoized_state, + => {}, + .func => |owner_func| ip.funcSetHasErrorTrace(io, owner_func, true), } } @@ -16907,6 +16920,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .struct_type => ip.loadStructType(ty.toIntern()), else => unreachable, }; + try sema.ensureStructDefaultsResolved(ty, src); // can't do this sooner, since it's not allowed on tuples struct_field_vals = try gpa.alloc(InternPool.Index, struct_type.field_types.len); for (struct_field_vals, 0..) |*field_val, field_index| { @@ -18788,6 +18802,8 @@ fn finishStructInit( continue; } + try sema.ensureStructDefaultsResolved(struct_ty, init_src); + const field_default: InternPool.Index = d: { if (struct_type.field_defaults.len == 0) break :d .none; break :d struct_type.field_defaults.get(ip)[i]; @@ -19454,7 +19470,14 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { .func => |func| if (ip.funcAnalysisUnordered(func).has_error_trace and block.ownerModule().error_tracing) { return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty); }, - .@"comptime", .nav_ty, .nav_val, .type_layout, .memoized_state => {}, + + .@"comptime", + .nav_ty, + .nav_val, + .type_layout, + .struct_defaults, + .memoized_state, + => {}, } return Air.internedToRef(try pt.intern(.{ .opt = .{ .ty = opt_ptr_stack_trace_ty.toIntern(), @@ -24784,7 +24807,7 @@ fn zirBuiltinExtern( // So, for now, just use our containing `declaration`. .zir_index = switch (sema.owner.unwrap()) { .@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index, - .type_layout => |owner_ty| Type.fromInterned(owner_ty).typeDeclInstAllowGeneratedTag(zcu).?, + .type_layout, .struct_defaults => |owner_ty| Type.fromInterned(owner_ty).typeDeclInstAllowGeneratedTag(zcu).?, .memoized_state => unreachable, .nav_ty, .nav_val => |nav| ip.getNav(nav).analysis.?.zir_index, .func => |func| zir_index: { @@ -25276,7 +25299,14 @@ fn getPanicIdFunc(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !In try sema.ensureMemoizedStateResolved(src, .panic); const panic_fn_index = zcu.builtin_decl_values.get(panic_id.toBuiltin()); switch (sema.owner.unwrap()) { - .@"comptime", .nav_ty, .nav_val, .type_layout, .memoized_state => {}, + .@"comptime", + .nav_ty, + .nav_val, + .type_layout, + .struct_defaults, + .memoized_state, + => {}, + .func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(io, owner_func, true), } return panic_fn_index; @@ -33541,23 +33571,6 @@ pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void { const gop = try sema.dependencies.getOrPut(sema.gpa, dependee); if (gop.found_existing) return; - // Avoid creating dependencies on ourselves. This situation can arise when we analyze the fields - // of a type and they use `@This()`. This dependency would be unnecessary, and in fact would - // just result in over-analysis since `Zcu.findOutdatedToAnalyze` would never be able to resolve - // the loop. - // Note that this also disallows a `nav_val` - switch (sema.owner.unwrap()) { - .nav_val => |this_nav| switch (dependee) { - .nav_val => |other_nav| if (this_nav == other_nav) return, - else => {}, - }, - .nav_ty => |this_nav| switch (dependee) { - .nav_ty => |other_nav| if (this_nav == other_nav) return, - else => {}, - }, - else => {}, - } - try pt.addDependency(sema.owner, dependee); } @@ -33923,6 +33936,7 @@ const ComptimeStoreResult = @import("Sema/comptime_ptr_access.zig").ComptimeStor pub const type_resolution = @import("Sema/type_resolution.zig"); pub const ensureLayoutResolved = type_resolution.ensureLayoutResolved; +pub const ensureStructDefaultsResolved = type_resolution.ensureStructDefaultsResolved; pub fn getBuiltinType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) SemaError!Type { assert(decl.kind() == .type); diff --git a/src/Sema/LowerZon.zig b/src/Sema/LowerZon.zig index 06218806a44b24cf4433ed9b7738b27515a55154..2012d5167c2111f133aac6916d7aa6e697395f2a 100644 --- a/src/Sema/LowerZon.zig +++ b/src/Sema/LowerZon.zig @@ -758,6 +758,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool const ip = &pt.zcu.intern_pool; try self.sema.ensureLayoutResolved(res_ty, self.import_loc, .init); + try self.sema.ensureStructDefaultsResolved(res_ty, self.import_loc); const struct_info = self.sema.pt.zcu.typeToStruct(res_ty).?; const fields: @FieldType(Zoir.Node, "struct_literal") = switch (node.get(self.file.zoir.?)) { diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig index 5e4e8a4ccd84e8080f71162262560a934977b34f..717d5b8b96e34893007f4f9e80fd100c3ce7b241 100644 --- a/src/Sema/type_resolution.zig +++ b/src/Sema/type_resolution.zig @@ -134,6 +134,33 @@ fn ensureLayoutResolvedInner(sema: *Sema, ty: Type, orig_ty: Type, reason: *cons } } +/// Asserts that `ty` is a non-tuple `struct` type, and ensures that its fields' default values +/// are resolved. Adds incremental dependencies tracking the required type resolution. +/// +/// It is not necessary to call this function to query the values of comptime fields: those values +/// are available from type *layout* resolution, see `ensureLayoutResolved`. +/// +/// Asserts that the *layout* of `ty` has already been resolved---see `ensureLayoutResolved`. +pub fn ensureStructDefaultsResolved(sema: *Sema, ty: Type, src: LazySrcLoc) SemaError!void { + const pt = sema.pt; + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + + assert(ip.indexToKey(ty.toIntern()) == .struct_type); + if (zcu.comp.config.incremental) assert(sema.dependencies.contains(.{ .type_layout = ty.toIntern() })); + + try sema.declareDependency(.{ .struct_defaults = ty.toIntern() }); + try sema.addReferenceEntry(null, src, .wrap(.{ .struct_defaults = ty.toIntern() })); + + const reason: Zcu.DependencyReason = .{ .src = src, .type_layout_reason = undefined }; + + if (zcu.analysis_in_progress.contains(.wrap(.{ .struct_defaults = ty.toIntern() }))) { + return sema.failWithDependencyLoop(.wrap(.{ .struct_defaults = ty.toIntern() }), &reason); + } + + try pt.ensureStructDefaultsUpToDate(ty, &reason); +} + /// Asserts that `struct_ty` is a non-packed non-tuple struct, and that `sema.owner` is that type. /// This function *does* register the `src_hash` dependency on the struct. pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { @@ -193,14 +220,8 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { @memset(struct_obj.field_is_comptime_bits.getAll(ip), 0); const zir_struct = sema.code.getStructDecl(zir_index); - - // If we have any default values to resolve, we'll need to map the struct decl instruction - // to the result type. - if (zir_struct.field_default_body_lens != null) { - try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index}); - } - var field_it = zir_struct.iterateFields(); + var any_comptime_fields = false; while (field_it.next()) |zir_field| { { const name_slice = sema.code.nullTerminatedString(zir_field.name); @@ -212,18 +233,21 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { const bit_bag_index = zir_field.idx / 32; const mask = @as(u32, 1) << @intCast(zir_field.idx % 32); struct_obj.field_is_comptime_bits.getAll(ip)[bit_bag_index] |= mask; + any_comptime_fields = true; } - const field_ty: Type = field_ty: { + { const field_ty_src = block.src(.{ .container_field_type = zir_field.idx }); - block.comptime_reason = .{ .reason = .{ - .src = field_ty_src, - .r = .{ .simple = .struct_field_types }, - } }; - const type_ref = try sema.resolveInlineBody(&block, zir_field.type_body, zir_index); - break :field_ty try sema.analyzeAsType(&block, field_ty_src, .struct_field_types, type_ref); - }; - struct_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern(); + const field_ty: Type = field_ty: { + block.comptime_reason = .{ .reason = .{ + .src = field_ty_src, + .r = .{ .simple = .struct_field_types }, + } }; + const type_ref = try sema.resolveInlineBody(&block, zir_field.type_body, zir_index); + break :field_ty try sema.analyzeAsType(&block, field_ty_src, .struct_field_types, type_ref); + }; + struct_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern(); + } if (struct_obj.field_aligns.len == 0) { assert(zir_field.align_body == null); @@ -240,31 +264,13 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { }; struct_obj.field_aligns.get(ip)[zir_field.idx] = field_align; } + } - if (struct_obj.field_defaults.len == 0) { - assert(zir_field.default_body == null); - } else { - const field_default_src = block.src(.{ .container_field_value = zir_field.idx }); - const field_default: InternPool.Index = d: { - block.comptime_reason = .{ .reason = .{ - .src = field_default_src, - .r = .{ .simple = .struct_field_default_value }, - } }; - const default_body = zir_field.default_body orelse break :d .none; - // Provide the result type - sema.inst_map.putAssumeCapacity(zir_index, .fromType(field_ty)); - defer assert(sema.inst_map.remove(zir_index)); - const uncoerced_default_val = try sema.resolveInlineBody(&block, default_body, zir_index); - const coerced_default_val = try sema.coerce(&block, field_ty, uncoerced_default_val, field_default_src); - const default_val = try sema.resolveConstValue(&block, field_default_src, coerced_default_val, null); - if (default_val.canMutateComptimeVarState(zcu)) { - const field_name = struct_obj.field_names.get(ip)[zir_field.idx]; - return sema.failWithContainsReferenceToComptimeVar(&block, field_default_src, field_name, "field default value", default_val); - } - break :d default_val.toIntern(); - }; - struct_obj.field_defaults.get(ip)[zir_field.idx] = field_default; - } + // We also resolve the default values of any `comptime` fields now. This is not necessary in + // the case of a reified struct because the the default values were already poulated and + // validated by `Sema.zirReifyStruct`. + if (any_comptime_fields) { + try resolveStructDefaultsInner(sema, &block, &struct_obj, .comptime_fields); } } @@ -523,6 +529,118 @@ fn resolvePackedStructLayout( ); } +/// Asserts that `struct_ty` is a non-tuple struct, and that `sema.owner` is that type. +/// +/// Also asserts that the layout of `struct_ty` has *already* been resolved (though it is okay for +/// that resolution to have failed). This requirement exists to ensure better error messages in the +/// event of a dependency loop. +/// +/// This function *does* register the `src_hash` dependency on the struct. +pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void { + const pt = sema.pt; + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const ip = &zcu.intern_pool; + + assert(sema.owner.unwrap().struct_defaults == struct_ty.toIntern()); + + // We always depend on the layout of `struct_ty`. However, we don't actually need to resolve it + // now, because the caller has done so for us. Just mark the dependency so that the incremental + // compilation handling understands the dependency graph. + try sema.declareDependency(.{ .type_layout = struct_ty.toIntern() }); + struct_ty.assertHasLayout(zcu); + const layout_unit: InternPool.AnalUnit = .wrap(.{ .type_layout = struct_ty.toIntern() }); + if (zcu.failed_analysis.contains(layout_unit) or zcu.transitive_failed_analysis.contains(layout_unit)) { + return error.AnalysisFail; + } + + const struct_obj = ip.loadStructType(struct_ty.toIntern()); + assert(struct_obj.want_layout); + + if (struct_obj.is_reified) { + // `Sema.zirReifyStruct` has already populated the default field values *and* (by loading + // the default values from pointers) validated their types, so we have nothing to do. + return; + } + + try sema.declareDependency(.{ .src_hash = struct_obj.zir_index }); + + if (struct_obj.field_defaults.len == 0) { + // The struct has no default field values, so the slice has been omitted. + return; + } + + var block: Block = .{ + .parent = null, + .sema = sema, + .namespace = struct_obj.namespace, + .instructions = .empty, + .inlining = null, + .comptime_reason = undefined, // always set before using `block` + .src_base_inst = struct_obj.zir_index, + .type_name_ctx = struct_obj.name, + }; + defer block.instructions.deinit(gpa); + + return resolveStructDefaultsInner(sema, &block, &struct_obj, .normal_fields); +} + +/// Asserts that the struct is not reified, and that `struct_obj.field_defaults.len` is non-zero. +fn resolveStructDefaultsInner( + sema: *Sema, + block: *Block, + struct_obj: *const InternPool.LoadedStructType, + mode: enum { comptime_fields, normal_fields }, +) CompileError!void { + const pt = sema.pt; + const zcu = pt.zcu; + const comp = zcu.comp; + const gpa = comp.gpa; + const ip = &zcu.intern_pool; + + assert(struct_obj.field_defaults.len > 0); + + // We'll need to map the struct decl instruction to provide result types + const zir_index = struct_obj.zir_index.resolve(ip) orelse return error.AnalysisFail; + try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index}); + + const field_types = struct_obj.field_types.get(ip); + + const zir_struct = sema.code.getStructDecl(zir_index); + var field_it = zir_struct.iterateFields(); + while (field_it.next()) |zir_field| { + switch (mode) { + .comptime_fields => if (!zir_field.is_comptime) continue, + .normal_fields => if (zir_field.is_comptime) continue, + } + + const default_val_src = block.src(.{ .container_field_value = zir_field.idx }); + block.comptime_reason = .{ .reason = .{ + .src = default_val_src, + .r = .{ .simple = .struct_field_default_value }, + } }; + const default_body = zir_field.default_body orelse { + struct_obj.field_defaults.get(ip)[zir_field.idx] = .none; + continue; + }; + const field_ty: Type = .fromInterned(field_types[zir_field.idx]); + const uncoerced = ref: { + // Provide the result type + sema.inst_map.putAssumeCapacity(zir_index, .fromIntern(field_ty.toIntern())); + defer assert(sema.inst_map.remove(zir_index)); + break :ref try sema.resolveInlineBody(block, default_body, zir_index); + }; + const coerced = try sema.coerce(block, field_ty, uncoerced, default_val_src); + const default_val = try sema.resolveConstValue(block, default_val_src, coerced, null); + if (default_val.canMutateComptimeVarState(zcu)) { + const field_name = struct_obj.field_names.get(ip)[zir_field.idx]; + return sema.failWithContainsReferenceToComptimeVar(block, default_val_src, field_name, "field default value", default_val); + } + struct_obj.field_defaults.get(ip)[zir_field.idx] = default_val.toIntern(); + } +} + /// This logic must be kept in sync with `Type.getUnionLayout`. pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { const pt = sema.pt; diff --git a/src/Zcu.zig b/src/Zcu.zig index faa535da5d6e12ae12c1ba6aaed1341fde2147d6..c623c1ec49f110d79676431c59481e6339613948 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -3175,6 +3175,7 @@ fn markPoDependeeUpToDateInner(zcu: *Zcu, dependee: InternPool.Dependee) !void { .nav_val => |nav| try zcu.markPoDependeeUpToDateInner(.{ .nav_val = nav }), .nav_ty => |nav| try zcu.markPoDependeeUpToDateInner(.{ .nav_ty = nav }), .type_layout => |ty| try zcu.markPoDependeeUpToDateInner(.{ .type_layout = ty }), + .struct_defaults => |ty| try zcu.markPoDependeeUpToDateInner(.{ .struct_defaults = ty }), .func => |func| try zcu.markPoDependeeUpToDateInner(.{ .func_ies = func }), .memoized_state => |stage| try zcu.markPoDependeeUpToDateInner(.{ .memoized_state = stage }), } @@ -3193,6 +3194,7 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni .nav_val => |nav| .{ .nav_val = nav }, .nav_ty => |nav| .{ .nav_ty = nav }, .type_layout => |ty| .{ .type_layout = ty }, + .struct_defaults => |ty| .{ .struct_defaults = ty }, .func => |func_index| .{ .func_ies = func_index }, .memoized_state => |stage| .{ .memoized_state = stage }, }; @@ -4249,11 +4251,18 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.AutoArrayHashMapUnmanag unit_idx += 1; // `nav_val` and `nav_ty` reference each other *implicitly* to save memory. + // Likewise for `type_layout` and `struct_defaults` of a struct type. queue_paired: { const other: AnalUnit = .wrap(switch (unit.unwrap()) { .nav_val => |n| .{ .nav_ty = n }, .nav_ty => |n| .{ .nav_val = n }, - .@"comptime", .type_layout, .func, .memoized_state => break :queue_paired, + .struct_defaults => |ty| .{ .type_layout = ty }, + .type_layout => |ty| switch (ip.indexToKey(ty)) { + .struct_type => .{ .struct_defaults = ty }, + .union_type, .enum_type, .opaque_type => break :queue_paired, + else => unreachable, + }, + .@"comptime", .func, .memoized_state => break :queue_paired, }); const gop = try units.getOrPut(gpa, other); if (gop.found_existing) break :queue_paired; @@ -4406,7 +4415,7 @@ fn formatAnalUnit(data: FormatAnalUnit, writer: *Io.Writer) Io.Writer.Error!void } }, .nav_val, .nav_ty => |nav, tag| return writer.print("{t}('{f}' [{}])", .{ tag, ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }), - .type_layout => |ty, tag| return writer.print("{t}('{f}' [{}])", .{ tag, Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }), + .type_layout, .struct_defaults => |ty, tag| return writer.print("{t}('{f}' [{}])", .{ tag, Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }), .func => |func| { const nav = zcu.funcInfo(func).owner_nav; return writer.print("func('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(func) }); @@ -4431,7 +4440,7 @@ fn formatDependee(data: FormatDependee, writer: *Io.Writer) Io.Writer.Error!void const fqn = ip.getNav(nav).fqn; return writer.print("{t}('{f}')", .{ tag, fqn.fmt(ip) }); }, - .type_layout => |ip_index, tag| { + .type_layout, .struct_defaults => |ip_index, tag| { const name = Type.fromInterned(ip_index).containerTypeName(ip); return writer.print("{t}('{f}')", .{ tag, name.fmt(ip) }); }, @@ -4920,6 +4929,10 @@ fn addDependencyLoopErrorLine( fmt_source, dep_node.reason.type_layout_reason.msg(), }), + .struct_defaults => |ty| try eb.printString( + "default field values of '{f}' depend on themselves for initialization here", + .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)}, + ), } else switch (dep_node.unit.unwrap()) { .@"comptime" => unreachable, // cannot be involved in a dependency loop .nav_val => |nav| try eb.printString("{f} uses value of declaration '{f}' here", .{ @@ -4940,6 +4953,10 @@ fn addDependencyLoopErrorLine( Type.fromInterned(ty).containerTypeName(ip).fmt(ip), dep_node.reason.type_layout_reason.msg(), }), + .struct_defaults => |ty| try eb.printString( + "{f} uses default field values of '{f}' here", + .{ fmt_source, Type.fromInterned(ty).containerTypeName(ip).fmt(ip) }, + ), }; const src_loc = dep_node.reason.src.upgrade(zcu); @@ -4982,6 +4999,9 @@ fn formatDependencyLoopSourceUnit(data: FormatAnalUnit, w: *Io.Writer) Io.Writer .type_layout => |ty| try w.print("type '{f}'", .{ Type.fromInterned(ty).containerTypeName(ip).fmt(ip), }), + .struct_defaults => |ty| try w.print("default field value of '{f}'", .{ + Type.fromInterned(ty).containerTypeName(ip).fmt(ip), + }), .func => |func| try w.print("function '{f}'", .{ ip.getNav(zcu.funcInfo(func).owner_nav).fqn.fmt(ip), }), @@ -5030,7 +5050,7 @@ pub fn populateReferenceTrace( const root_name: ?[]const u8 = switch (ref.referencer.unwrap()) { .@"comptime" => "comptime", .nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip), - .type_layout => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), + .type_layout, .struct_defaults => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip), .memoized_state => null, }; diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index ee788c884e327fffe1fe5a1e6f09854ba6932803..8a786edb4903b031464efdadf108966bd8f63af0 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -324,6 +324,17 @@ pub fn update( .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav, null), .nav_val => |nav| pt.ensureNavValUpToDate(nav, null), .type_layout => |ty| pt.ensureTypeLayoutUpToDate(.fromInterned(ty), null), + .struct_defaults => |ty| res: { + // Unlike the other functions, this one requires that the type layout is resolved first. + pt.ensureTypeLayoutUpToDate(.fromInterned(ty), null) catch |err| switch (err) { + error.OutOfMemory, + error.Canceled, + => |e| return e, + + error.AnalysisFail => {}, // already reported + }; + break :res pt.ensureStructDefaultsUpToDate(.fromInterned(ty), null); + }, .memoized_state => |stage| pt.ensureMemoizedStateUpToDate(stage, null), .func => |func| pt.ensureFuncBodyUpToDate(func, null), }; @@ -1326,6 +1337,7 @@ pub fn ensureTypeLayoutUpToDate( defer tracy_trace.end(); const zcu = pt.zcu; + const ip = &zcu.intern_pool; const comp = zcu.comp; const gpa = comp.gpa; @@ -1335,8 +1347,23 @@ pub fn ensureTypeLayoutUpToDate( assert(!zcu.analysis_in_progress.contains(anal_unit)); - const was_outdated = zcu.clearOutdatedState(anal_unit) or - zcu.intern_pool.setWantTypeLayout(comp.io, ty.toIntern()); + const was_outdated: bool = outdated: { + if (zcu.clearOutdatedState(anal_unit)) break :outdated true; + if (ip.setWantTypeLayout(comp.io, ty.toIntern())) { + // We'll analyze the layout for the first time, but if this is a struct type then its + // default field values also need to be analyzed. + if (ip.indexToKey(ty.toIntern()) == .struct_type) { + if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); + defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(zcu.comp.io); + try zcu.outdated.ensureUnusedCapacity(gpa, 1); + try zcu.outdated_ready.other.ensureUnusedCapacity(gpa, 1); + zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .struct_defaults = ty.toIntern() }), 0); + zcu.outdated_ready.other.putAssumeCapacityNoClobber(.wrap(.{ .struct_defaults = ty.toIntern() }), {}); + } + break :outdated true; + } + break :outdated false; + }; if (was_outdated) { // `was_outdated` is true in the initial update, so this isn't a `dev.check`. @@ -1359,7 +1386,7 @@ pub fn ensureTypeLayoutUpToDate( info.deps.clearRetainingCapacity(); } - const unit_tracking = zcu.trackUnitSema(ty.containerTypeName(&zcu.intern_pool).toSlice(&zcu.intern_pool), null); + const unit_tracking = zcu.trackUnitSema(ty.containerTypeName(ip).toSlice(ip), null); defer unit_tracking.end(zcu); try zcu.analysis_in_progress.put(gpa, anal_unit, reason); @@ -1428,6 +1455,120 @@ pub fn ensureTypeLayoutUpToDate( if (new_failed) return error.AnalysisFail; } +/// Ensures that the default field values of the given `struct` type are fully up-to-date, +/// performing re-analysis if necessary. Asserts that `ty` is a struct (not a tuple!) type. Unlike +/// the other "ensure X up to date" functions, this particular function also asserts that the +/// *layout* of `ty` is *already* up-to-date (though it is okay for that resolution to have failed). +/// Returns `error.AnalysisFail` if an analysis error is encountered while resolving the default +/// field values; the caller is free to ignore this, since the error is already registered. +pub fn ensureStructDefaultsUpToDate( + pt: Zcu.PerThread, + ty: Type, + /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. + reason: ?*const Zcu.DependencyReason, +) Zcu.SemaError!void { + const tracy_trace = trace(@src()); + defer tracy_trace.end(); + + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + const comp = zcu.comp; + const gpa = comp.gpa; + + assert(ip.indexToKey(ty.toIntern()) == .struct_type); + + const anal_unit: AnalUnit = .wrap(.{ .struct_defaults = ty.toIntern() }); + + log.debug("ensureStructDefaultsUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)}); + + assert(!zcu.analysis_in_progress.contains(anal_unit)); + + const was_outdated: bool = outdated: { + if (zcu.clearOutdatedState(anal_unit)) break :outdated true; + // The type layout should already be marked as "wanted" by this point, because a struct's + // layout must always be analyzed before its default values are. + assert(!ip.setWantTypeLayout(comp.io, ty.toIntern())); + break :outdated false; + }; + + if (was_outdated) { + // `was_outdated` is true in the initial update, so this isn't a `dev.check`. + if (dev.env.supports(.incremental)) { + zcu.resetUnit(anal_unit); + } + // For types, we already know that we have to invalidate all dependees. + // TODO: we actually *could* detect whether everything was the same. should we bother? + try zcu.markDependeeOutdated(.marked_po, .{ .struct_defaults = ty.toIntern() }); + } else { + // We can trust the current information about this unit. + if (zcu.failed_analysis.contains(anal_unit)) return error.AnalysisFail; + if (zcu.transitive_failed_analysis.contains(anal_unit)) return error.AnalysisFail; + return; + } + + if (zcu.comp.debugIncremental()) { + const info = try zcu.incremental_debug_state.getUnitInfo(gpa, anal_unit); + info.last_update_gen = zcu.generation; + info.deps.clearRetainingCapacity(); + } + + const unit_tracking = zcu.trackUnitSema(ty.containerTypeName(ip).toSlice(ip), null); + defer unit_tracking.end(zcu); + + try zcu.analysis_in_progress.put(gpa, anal_unit, reason); + defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); + + var analysis_arena: std.heap.ArenaAllocator = .init(gpa); + defer analysis_arena.deinit(); + + var comptime_err_ret_trace: std.array_list.Managed(Zcu.LazySrcLoc) = .init(gpa); + defer comptime_err_ret_trace.deinit(); + + const file = zcu.namespacePtr(ty.getNamespaceIndex(zcu)).fileScope(zcu); + + var sema: Sema = .{ + .pt = pt, + .gpa = gpa, + .arena = analysis_arena.allocator(), + .code = file.zir.?, + .owner = anal_unit, + .func_index = .none, + .func_is_naked = false, + .fn_ret_ty = .void, + .fn_ret_ty_ies = null, + .comptime_err_ret_trace = &comptime_err_ret_trace, + }; + defer sema.deinit(); + + const new_failed: bool = if (Sema.type_resolution.resolveStructDefaults(&sema, ty)) failed: { + break :failed false; + } else |err| switch (err) { + error.AnalysisFail => failed: { + if (!zcu.failed_analysis.contains(anal_unit)) { + // If this unit caused the error, it would have an entry in `failed_analysis`. + // Since it does not, this must be a transitive failure. + try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); + log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)}); + } + break :failed true; + }, + error.OutOfMemory, + error.Canceled, + => |e| return e, + error.ComptimeReturn => unreachable, + error.ComptimeBreak => unreachable, + }; + + sema.flushExports() catch |err| switch (err) { + error.OutOfMemory => |e| return e, + }; + + // We don't need to `markDependeeOutdated`/`markPoDependeeUpToDate` here, because we already + // marked the struct defaults as outdated at the top of this function. + + if (new_failed) return error.AnalysisFail; +} + /// Ensures that the resolved value of the given `Nav` is fully up-to-date, performing re-analysis /// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is /// free to ignore this, since the error is already registered. diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 806a85ff23cb3a0b8ead4e6716b24de3b70995f5..d09012fe948ba1a70b1b93fb99a8966abf89c8bc 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -3827,7 +3827,15 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co try diw.writeUleb128(ty.abiAlignment(zcu).toByteUnits().?); for (0..loaded_struct.field_types.len) |field_index| { const is_comptime = loaded_struct.field_is_comptime_bits.get(ip, field_index); - const field_init = loaded_struct.field_defaults.getOrNone(ip, field_index); + // TODO: we currently don't emit information about default values for + // non-`comptime` fields, because these default values are resolved at a + // separate time in the compiler frontend. To emit this information, the + // frontend needs to tell us when the default values are available: like + // how `Zcu.PerThread.ensureTypeLayoutUpToDate` enqueues a link task to + // indicate completion of the type's layout, a task should be enqueued + // by `Zcu.PerThread.ensureStructDefaultsUpToDate`, and upon receiving + // it we should patch the correct default field values in. + const field_init: InternPool.Index = if (is_comptime) loaded_struct.field_defaults.getOrNone(ip, field_index) else .none; assert(!(is_comptime and field_init == .none)); const field_type: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); const has_runtime_bits, const has_comptime_state = switch (field_init) { -- 2.54.0 From bb78871aa44594a1b4782792942664e532491d5a Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Fri, 27 Feb 2026 11:23:05 +0000 Subject: [PATCH 55/79] behavior: re-introduce some previously-removed tests Now that struct default value resolution is separate from struct layout resolution, a handful of old behavior tests are now once again valid. This partially reverts the commit titled "behavior: update for changes to struct field default value resolution". --- test/behavior/struct.zig | 58 +++++++++++++++++++++++++++++++++++++--- test/behavior/union.zig | 49 +++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 3 deletions(-) diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 37dc873d60385608367b1841362aaadb21254e5c..e6a355864629600f6294492ee11e4cf7c73f5674 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -1249,6 +1249,20 @@ test "store to comptime field" { } } +test "struct field init value is size of the struct" { + if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO + + const namespace = struct { + const S = extern struct { + size: u8 = @sizeOf(S), + blah: u16, + }; + }; + var s: namespace.S = .{ .blah = 1234 }; + _ = &s; + try expect(s.size == 4); +} + test "under-aligned struct field" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO @@ -1696,19 +1710,41 @@ test "comptimeness of optional and error union payload is analyzed properly" { try std.testing.expectEqual(3, x); } +test "initializer uses own alignment" { + const S = struct { + x: u32 = @alignOf(@This()) + 1, + }; + + var s: S = .{}; + _ = &s; + try expectEqual(4, @alignOf(S)); + try expectEqual(@as(usize, 5), s.x); +} + +test "initializer uses own size" { + const S = struct { + x: u32 = @sizeOf(@This()) + 1, + }; + + var s: S = .{}; + _ = &s; + try expectEqual(4, @sizeOf(S)); + try expectEqual(@as(usize, 5), s.x); +} + test "initializer takes a pointer to a variable inside its struct" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const namespace = struct { const S = struct { - x: *u32 = &S.int, - var int: u32 = undefined; + s: *S = &S.instance, + var instance: S = undefined; }; fn doTheTest() !void { var foo: S = .{}; _ = &foo; - try expectEqual(&S.int, foo.x); + try expectEqual(&S.instance, foo.s); } }; @@ -1739,6 +1775,22 @@ test "circular dependency through pointer field of a struct" { try expect(outer.middle.inner == null); } +test "field calls do not force struct field init resolution" { + const S = struct { + x: u32 = blk: { + _ = @TypeOf(make().dummyFn()); // runtime field call - S not fully resolved - dummyFn call should not force field init resolution + break :blk 123; + }, + dummyFn: *const fn () void = undefined, + fn make() @This() { + return .{}; + } + }; + var s: S = .{}; + _ = &s; + try expect(s.x == 123); +} + test "tuple with comptime-only field" { const S = struct { fn getTuple() struct { comptime_int } { diff --git a/test/behavior/union.zig b/test/behavior/union.zig index b081d9b33a06e41df101c7f55f2d716821be30fe..9badc9dabd11bd6709c95ae32ba755f6cc3b9bd2 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -1796,6 +1796,55 @@ test "reinterpret packed union inside packed struct" { try S.doTheTest(); } +test "inner struct initializer uses union layout" { + const namespace = struct { + const U = union { + a: struct { + x: u32 = @alignOf(U) + 1, + }, + b: struct { + y: u16 = @sizeOf(U) + 2, + }, + }; + }; + + { + const u: namespace.U = .{ .a = .{} }; + try expectEqual(4, @alignOf(namespace.U)); + try expectEqual(@as(usize, 5), u.a.x); + } + + { + const u: namespace.U = .{ .b = .{} }; + try expectEqual(@as(usize, @sizeOf(namespace.U) + 2), u.b.y); + } +} + +test "inner struct initializer uses packed union layout" { + const namespace = struct { + const U = packed union { + a: packed struct { + x: u32 = @alignOf(U) + 1, + }, + b: packed struct(u32) { + y: u16 = @sizeOf(U) + 2, + padding: u16 = 0, + }, + }; + }; + + { + const u: namespace.U = .{ .a = .{} }; + try expectEqual(4, @alignOf(namespace.U)); + try expectEqual(@as(usize, 5), u.a.x); + } + + { + const u: namespace.U = .{ .b = .{} }; + try expectEqual(@as(usize, @sizeOf(namespace.U) + 2), u.b.y); + } +} + test "extern union initialized via reintepreted struct field initializer" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; -- 2.54.0 From d462794e20127f396753c7d6064a9d2b4e0304d9 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Fri, 27 Feb 2026 14:40:01 +0000 Subject: [PATCH 56/79] get the compiler building The change in codegen/x86_64/CodeGen.zig was not strictly necessary (the Sema change I did solves the error I was getting there), I just think it's better style anyway. --- lib/std/os/windows.zig | 10 +++---- src/Sema.zig | 52 ++++++++++++++++++++-------------- src/Sema/type_resolution.zig | 2 +- src/Zcu/PerThread.zig | 22 +++++++++++++- src/codegen/spirv/CodeGen.zig | 2 +- src/codegen/x86_64/CodeGen.zig | 2 +- 6 files changed, 59 insertions(+), 31 deletions(-) diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index 8832b1add949df3245eed397ff6f614c54c33d6e..6f2c8f49381ca695d388f87a4be5070e42271959 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -4160,7 +4160,7 @@ pub const RUNTIME_FUNCTION = switch (native_arch) { BeginAddress: DWORD, DUMMYUNIONNAME: extern union { UnwindData: DWORD, - DUMMYSTRUCTNAME: packed struct { + DUMMYSTRUCTNAME: packed struct(u32) { Flag: u2, FunctionLength: u11, Ret: u2, @@ -4177,7 +4177,7 @@ pub const RUNTIME_FUNCTION = switch (native_arch) { BeginAddress: DWORD, DUMMYUNIONNAME: extern union { UnwindData: DWORD, - DUMMYSTRUCTNAME: packed struct { + DUMMYSTRUCTNAME: packed struct(u32) { Flag: u2, FunctionLength: u11, RegF: u3, @@ -5013,7 +5013,7 @@ pub const KUSER_SHARED_DATA = extern struct { KdDebuggerEnabled: BOOLEAN, DummyUnion1: extern union { MitigationPolicies: UCHAR, - Alt: packed struct { + Alt: packed struct(u8) { NXSupportPolicy: u2, SEHValidationPolicy: u2, CurDirDevicesSkippedForDlls: u2, @@ -5029,7 +5029,7 @@ pub const KUSER_SHARED_DATA = extern struct { SafeBootMode: BOOLEAN, DummyUnion2: extern union { VirtualizationFlags: UCHAR, - Alt: packed struct { + Alt: packed struct(u8) { ArchStartedInEl2: u1, QcSlIsSupported: u1, SpareBits: u6, @@ -5038,7 +5038,7 @@ pub const KUSER_SHARED_DATA = extern struct { Reserved12: [2]UCHAR, DummyUnion3: extern union { SharedDataFlags: ULONG, - Alt: packed struct { + Alt: packed struct(u32) { DbgErrorPortPresent: u1, DbgElevationEnabled: u1, DbgVirtEnabled: u1, diff --git a/src/Sema.zig b/src/Sema.zig index 337f0d07cda987e326bdf5869949734578fcb9d7..02c2efd2ee7f27c1312ed8d04ed808debeca71f1 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -3081,7 +3081,7 @@ fn zirRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_tok; const operand = sema.resolveInst(inst_data.operand); - return sema.analyzeRef(block, block.tokenOffset(inst_data.src_tok), operand); + return sema.analyzeRef(block, block.tokenOffset(inst_data.src_tok), operand, .none); } fn zirEnsureResultUsed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { @@ -18690,7 +18690,7 @@ fn zirStructInit( const union_val = try sema.bitCast(block, resolved_ty, init_inst, src, field_src); const result_val = try sema.coerce(block, result_ty, union_val, src); if (is_ref) { - return sema.analyzeRef(block, src, result_val); + return sema.analyzeRef(block, src, result_val, .none); } else { return result_val; } @@ -24192,7 +24192,7 @@ fn zirMemcpy( } } else if (dest_len == .none and len_val == null) { // Change the dest to a slice, since its type must have the length. - const dest_ptr_ptr = try sema.analyzeRef(block, dest_src, new_dest_ptr); + const dest_ptr_ptr = try sema.analyzeRef(block, dest_src, new_dest_ptr, .none); new_dest_ptr = try sema.analyzeSlice(block, dest_src, dest_ptr_ptr, .zero, src_len, .none, LazySrcLoc.unneeded, dest_src, dest_src, dest_src, false); const new_src_ptr_ty = sema.typeOf(new_src_ptr); if (new_src_ptr_ty.isSlice(zcu)) { @@ -26301,7 +26301,7 @@ fn structFieldPtr( const field_index: u32 = if (struct_ty.isTuple(zcu)) field_index: { if (field_name.eqlSlice("len", ip)) { const len_inst = try pt.intRef(.usize, struct_ty.structFieldCount(zcu)); - return sema.analyzeRef(block, src, len_inst); + return sema.analyzeRef(block, src, len_inst, .none); } break :field_index try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src); } else field_index: { @@ -29787,10 +29787,7 @@ fn coerceTupleToSlicePtrs( .child = slice_info.child, }); const array_inst = try sema.coerceTupleToArray(block, array_ty, slice_ty_src, tuple, tuple_src); - if (slice_info.flags.alignment != .none) { - return sema.fail(block, slice_ty_src, "TODO: override the alignment of the array decl we create here", .{}); - } - const ptr_array = try sema.analyzeRef(block, slice_ty_src, array_inst); + const ptr_array = try sema.analyzeRef(block, slice_ty_src, array_inst, slice_info.flags.alignment); return sema.coerceArrayPtrToSlice(block, slice_ty, ptr_array, slice_ty_src); } @@ -29809,10 +29806,7 @@ fn coerceTupleToArrayPtrs( const ptr_info = ptr_array_ty.ptrInfo(zcu); const array_ty: Type = .fromInterned(ptr_info.child); const array_inst = try sema.coerceTupleToArray(block, array_ty, array_ty_src, tuple, tuple_src); - if (ptr_info.flags.alignment != .none) { - return sema.fail(block, array_ty_src, "TODO: override the alignment of the array decl we create here", .{}); - } - const ptr_array = try sema.analyzeRef(block, array_ty_src, array_inst); + const ptr_array = try sema.analyzeRef(block, array_ty_src, array_inst, ptr_info.flags.alignment); return ptr_array; } @@ -30137,33 +30131,47 @@ fn analyzeRef( block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref, + alignment: Alignment, ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; const operand_ty = sema.typeOf(operand); + const address_space = target_util.defaultAddressSpace(zcu.getTarget(), .local); + const ptr_type = try pt.ptrType(.{ + .child = operand_ty.toIntern(), + .flags = .{ + .alignment = alignment, + .is_const = true, + .address_space = address_space, + }, + }); + if (sema.resolveValue(operand)) |val| { switch (zcu.intern_pool.indexToKey(val.toIntern())) { .@"extern" => |e| return sema.analyzeNavRef(block, src, e.owner_nav), .func => |f| return sema.analyzeNavRef(block, src, f.owner_nav), - else => return uavRef(sema, val), + else => return .fromIntern(try pt.intern(.{ .ptr = .{ + .ty = ptr_type.toIntern(), + .base_addr = .{ .uav = .{ + .val = val.toIntern(), + .orig_ty = ptr_type.toIntern(), + } }, + .byte_offset = 0, + } })), } } // No `requireRuntimeBlock`; it's okay to `ref` to a runtime value in a comptime context, // it's just that we can only use the *type* of the result, since the value is runtime-known. - const address_space = target_util.defaultAddressSpace(zcu.getTarget(), .local); - const ptr_type = try pt.ptrType(.{ - .child = operand_ty.toIntern(), - .flags = .{ - .is_const = true, - .address_space = address_space, - }, - }); const mut_ptr_type = try pt.ptrType(.{ .child = operand_ty.toIntern(), - .flags = .{ .address_space = address_space }, + .flags = .{ + .alignment = alignment, + .is_const = false, + .address_space = address_space, + }, }); const alloc = try block.addTy(.alloc, mut_ptr_type); diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig index 717d5b8b96e34893007f4f9e80fd100c3ce7b241..8009838a8837025a3895e90207dd95cc922559a1 100644 --- a/src/Sema/type_resolution.zig +++ b/src/Sema/type_resolution.zig @@ -147,7 +147,7 @@ pub fn ensureStructDefaultsResolved(sema: *Sema, ty: Type, src: LazySrcLoc) Sema const ip = &zcu.intern_pool; assert(ip.indexToKey(ty.toIntern()) == .struct_type); - if (zcu.comp.config.incremental) assert(sema.dependencies.contains(.{ .type_layout = ty.toIntern() })); + ty.assertHasLayout(zcu); try sema.declareDependency(.{ .struct_defaults = ty.toIntern() }); try sema.addReferenceEntry(null, src, .wrap(.{ .struct_defaults = ty.toIntern() })); diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 8a786edb4903b031464efdadf108966bd8f63af0..bf45502faceaabe69c5fc10a3d4aa020224c0276 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -4112,7 +4112,27 @@ pub fn enumValueFieldIndex(pt: Zcu.PerThread, ty: Type, field_index: u32) Alloca pub fn undefValue(pt: Zcu.PerThread, ty: Type) Allocator.Error!Value { if (std.debug.runtime_safety) { - assert(ty.classify(pt.zcu) != .one_possible_value); + // TODO: values of type `struct { comptime x: u8 = undefined }` are currently represented as + // undef. This is wrong: they should really be represented as empty aggregates instead, + // because `comptime` fields shouldn't factor into that decision! This is implemented + // through logic in `aggregateValue` and requires this weird workaround in what ought to be + // a straightforward assertion: + //assert(ty.classify(pt.zcu) != .one_possible_value); + if (ty.classify(pt.zcu) == .one_possible_value) { + const ip = &pt.zcu.intern_pool; + switch (ip.indexToKey(ty.toIntern())) { + else => unreachable, // assertion failure + .struct_type => { + const comptime_bits = ip.loadStructType(ty.toIntern()).field_is_comptime_bits.getAll(ip); + for (comptime_bits) |bag| { + if (@popCount(bag) > 0) break; + } else unreachable; // assertion failure + }, + .tuple_type => |tuple| for (tuple.values.get(ip)) |val| { + if (val != .none) break; + } else unreachable, // assertion failure + } + } } return .fromInterned(try pt.intern(.{ .undef = ty.toIntern() })); } diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig index 34a7f99ce4f30d39e8dd4caf710390816abf220f..71cd46be02740ea78411ff0f8bed98d92ed7ef3d 100644 --- a/src/codegen/spirv/CodeGen.zig +++ b/src/codegen/spirv/CodeGen.zig @@ -689,7 +689,7 @@ fn constInt(cg: *CodeGen, ty: Type, value: anytype) !Id { .comptime_int => if (value < 0) .signed else .unsigned, else => unreachable, }; - if (@sizeOf(@TypeOf(value)) >= 4 and big_int) { + if (@TypeOf(value) != comptime_int and @sizeOf(@TypeOf(value)) >= 4 and big_int) { const value64: u64 = switch (signedness) { .signed => @bitCast(@as(i64, @intCast(value))), .unsigned => @as(u64, @intCast(value)), diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index f46f87ccff5846df798fc470fbb97e06c3cd59e7..7bd81c13ffeb499bfd44209daee0204bd08f4865 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -181111,7 +181111,7 @@ fn resolveCallingConventionValues( var ret_sse = abi.getCAbiSseReturnRegs(cc); var ret_x87 = abi.getCAbiX87ReturnRegs(cc); - const classes = switch (cc) { + const classes: []const abi.Class = switch (cc) { .x86_64_sysv => std.mem.sliceTo(&abi.classifySystemV(ret_ty, zcu, cg.target, .ret), .none), .x86_64_win => &.{abi.classifyWindows(ret_ty, zcu, cg.target, .ret)}, else => unreachable, -- 2.54.0 From 0a246f5e67118328a11df51cd6dfa419793ebeb1 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sat, 28 Feb 2026 10:10:15 +0000 Subject: [PATCH 57/79] compiler: stop LLVM bossing the frontend around I previously wrote some weird code in the compiler frontend solely because the LLVM backend has some weird requirements, but the better solution is to avoid those requirements. This commit does that by introducing "alignment forward references" to `std.zig.llvm.Builder`. Much like debug forward references, they allow you to reference an alignment value which will be populated at a later time (and which can be updated many times, which is important for incremental compilation). Then, when we want to reference a type's ABI alignment while the type is not necessarily resolved (required for `@"align"` attributes on function parameters and function call arguments), we create a forward reference and use `link.ConstPool` to populate it when ready. This allows us to remove from the compiler frontend some extremely arbitrary calls to `Sema.ensureLayoutResolved`, so that the language specification is not being built around the particular needs of our compiler implementation's LLVM code generation backend. --- lib/std/zig/llvm/Builder.zig | 217 ++++++++++++++++++++++------------- src/Sema.zig | 15 --- src/Zcu/PerThread.zig | 14 --- src/codegen/llvm.zig | 154 ++++++++++++++++--------- 4 files changed, 237 insertions(+), 163 deletions(-) diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig index f40b63c85fdb0536b7b75cc9915de558d0f105fb..5001a0c375a55f2c49a26e5f697086d65f34c2dd 100644 --- a/lib/std/zig/llvm/Builder.zig +++ b/lib/std/zig/llvm/Builder.zig @@ -7,6 +7,7 @@ const Allocator = std.mem.Allocator; const assert = std.debug.assert; const DW = std.dwarf; const log = std.log.scoped(.llvm); +const maxInt = std.math.maxInt; const Writer = std.Io.Writer; const bitcode_writer = @import("bitcode_writer.zig"); @@ -55,6 +56,8 @@ constant_items: std.MultiArrayList(Constant.Item), constant_extra: std.ArrayList(u32), constant_limbs: std.ArrayList(std.math.big.Limb), +alignment_forward_references: std.ArrayList(Alignment), + metadata_map: std.AutoArrayHashMapUnmanaged(void, void), metadata_items: std.MultiArrayList(Metadata.Item), metadata_extra: std.ArrayList(u32), @@ -85,7 +88,7 @@ pub const Options = struct { }; pub const String = enum(u32) { - none = std.math.maxInt(u31), + none = maxInt(u31), empty, _, @@ -245,7 +248,7 @@ pub const Type = enum(u32) { ptr, @"ptr addrspace(4)", - none = std.math.maxInt(u32), + none = maxInt(u32), _, pub const ptr_amdgpu_constant = @@ -941,7 +944,7 @@ pub const Attribute = union(Kind) { inalloca: Type, sret: Type, elementtype: Type, - @"align": Alignment, + @"align": Alignment.Lazy, @"noalias", nocapture, nofree, @@ -956,7 +959,7 @@ pub const Attribute = union(Kind) { immarg, noundef, nofpclass: FpClass, - alignstack: Alignment, + alignstack: Alignment.Lazy, allocalign, allocptr, readnone, @@ -964,7 +967,7 @@ pub const Attribute = union(Kind) { writeonly, // Function Attributes - //alignstack: Alignment, + //alignstack: Alignment.Lazy, allockind: AllocKind, allocsize: AllocSize, alwaysinline, @@ -1145,7 +1148,7 @@ pub const Attribute = union(Kind) { return @unionInit(Attribute, field.name, switch (field.type) { void => {}, u32 => storage.value, - Alignment, String, Type, UwTable => @enumFromInt(storage.value), + Alignment.Lazy, String, Type, UwTable => @enumFromInt(storage.value), AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(storage.value), else => @compileError("bad payload type: " ++ field.name ++ ": " ++ @typeName(field.type)), @@ -1246,7 +1249,7 @@ pub const Attribute = union(Kind) { .sret, .elementtype, => |ty| try w.print(" {s}({f})", .{ @tagName(attribute), ty.fmt(data.builder, .percent) }), - .@"align" => |alignment| try w.print("{f}", .{alignment.fmt(" ")}), + .@"align" => |alignment| try w.print("{f}", .{alignment.resolve(data.builder).fmt(" ")}), .dereferenceable, .dereferenceable_or_null, => |size| try w.print(" {s}({d})", .{ @tagName(attribute), size }), @@ -1270,7 +1273,7 @@ pub const Attribute = union(Kind) { }, .alignstack => |alignment| { try w.print(" {t}", .{attribute}); - const alignment_bytes = alignment.toByteUnits() orelse return; + const alignment_bytes = alignment.resolve(data.builder).toByteUnits() orelse return; if (data.flags.pound) { try w.print("={d}", .{alignment_bytes}); } else { @@ -1435,8 +1438,8 @@ pub const Attribute = union(Kind) { //sanitize_memtag, sanitize_address_dyninit = 102, - string = std.math.maxInt(u31), - none = std.math.maxInt(u32), + string = maxInt(u31), + none = maxInt(u32), _, pub const len = @typeInfo(Kind).@"enum".fields.len - 2; @@ -1516,12 +1519,12 @@ pub const Attribute = union(Kind) { elem_size: u16, num_elems: u16, - pub const none = std.math.maxInt(u16); + pub const none = maxInt(u16); fn toLlvm(self: AllocSize) packed struct(u64) { num_elems: u32, elem_size: u32 } { return .{ .num_elems = switch (self.num_elems) { else => self.num_elems, - none => std.math.maxInt(u32), + none => maxInt(u32), }, .elem_size = self.elem_size }; } }; @@ -1577,7 +1580,7 @@ pub const Attribute = union(Kind) { inline else => |value, tag| .{ .kind = @as(Kind, self), .value = switch (@TypeOf(value)) { void => 0, u32 => value, - Alignment, String, Type, UwTable => @intFromEnum(value), + Alignment.Lazy, String, Type, UwTable => @intFromEnum(value), AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(value), else => @compileError("bad payload type: " ++ @tagName(tag) ++ @typeName(@TypeOf(value))), } }, @@ -2017,9 +2020,32 @@ pub const ExternallyInitialized = enum { }; pub const Alignment = enum(u6) { - default = std.math.maxInt(u6), + default = maxInt(u6), _, + pub const Lazy = enum(u32) { + /// Values which fit in a `u6` are already-resolved `Alignment` values. Other values are + /// indices into `Builder.alignment_forward_references`, offset by `maxInt(u6)`. + _, + + pub fn wrap(a: Alignment) Lazy { + return @enumFromInt(@intFromEnum(a)); + } + pub fn resolve(l: Lazy, b: *const Builder) Alignment { + return switch (@intFromEnum(l)) { + 0...maxInt(u6) => |raw| @enumFromInt(raw), + else => |offset_index| b.alignment_forward_references.items[offset_index - maxInt(u6)], + }; + } + + fn fromFwdRefIndex(index: usize) Lazy { + return @enumFromInt(index + maxInt(u6)); + } + fn toFwdRefIndex(l: Lazy) usize { + return @intFromEnum(l) - maxInt(u6); + } + }; + pub fn fromByteUnits(bytes: u64) Alignment { if (bytes == 0) return .default; assert(std.math.isPowerOfTwo(bytes)); @@ -2028,11 +2054,17 @@ pub const Alignment = enum(u6) { } pub fn toByteUnits(self: Alignment) ?u64 { - return if (self == .default) null else @as(u64, 1) << @intFromEnum(self); + return switch (self) { + .default => null, + else => @as(u64, 1) << @intFromEnum(self), + }; } pub fn toLlvm(self: Alignment) u6 { - return if (self == .default) 0 else (@intFromEnum(self) + 1); + return switch (self) { + .default => 0, + else => @intFromEnum(self) + 1, + }; } pub const Prefixed = struct { @@ -2180,7 +2212,7 @@ pub const CallConv = enum(u10) { }; pub const StrtabString = enum(u32) { - none = std.math.maxInt(u31), + none = maxInt(u31), empty, _, @@ -2308,7 +2340,7 @@ pub const Global = struct { }, pub const Index = enum(u32) { - none = std.math.maxInt(u32), + none = maxInt(u32), _, pub fn unwrap(self: Index, builder: *const Builder) Index { @@ -2478,7 +2510,7 @@ pub const Alias = struct { aliasee: Constant = .no_init, pub const Index = enum(u32) { - none = std.math.maxInt(u32), + none = maxInt(u32), _, pub fn ptr(self: Index, builder: *Builder) *Alias { @@ -2530,7 +2562,7 @@ pub const Variable = struct { alignment: Alignment = .default, pub const Index = enum(u32) { - none = std.math.maxInt(u32), + none = maxInt(u32), _, pub fn ptr(self: Index, builder: *Builder) *Variable { @@ -3949,7 +3981,7 @@ pub const Intrinsic = enum { .params = &.{ .{ .kind = .{ .type = Type.ptr_amdgpu_constant }, - .attrs = &.{.{ .@"align" = Builder.Alignment.fromByteUnits(4) }}, + .attrs = &.{.{ .@"align" = .wrap(.fromByteUnits(4)) }}, }, }, .attrs = &.{ .nocallback, .nofree, .nosync, .nounwind, .speculatable, .willreturn, .{ .memory = Attribute.Memory.all(.none) } }, @@ -4057,7 +4089,7 @@ pub const Function = struct { extra: []const u32 = &.{}, pub const Index = enum(u32) { - none = std.math.maxInt(u32), + none = maxInt(u32), _, pub fn ptr(self: Index, builder: *Builder) *Function { @@ -4411,7 +4443,7 @@ pub const Function = struct { }; pub const Index = enum(u32) { - none = std.math.maxInt(u31), + none = maxInt(u31), _, pub fn name(self: Instruction.Index, function: *const Function) String { @@ -5007,7 +5039,7 @@ pub const Function = struct { fsub = 12, fmax = 13, fmin = 14, - none = std.math.maxInt(u5), + none = maxInt(u5), }; }; @@ -6132,8 +6164,8 @@ pub const WipFunction = struct { kind: MemoryAccessKind, @"inline": bool, ) Allocator.Error!Instruction.Index { - var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })}; - var src_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = src_align })}; + var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = .wrap(dst_align) })}; + var src_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = .wrap(src_align) })}; const value = try self.callIntrinsic( .normal, try self.builder.fnAttrs(&.{ @@ -6162,8 +6194,8 @@ pub const WipFunction = struct { len: Value, kind: MemoryAccessKind, ) Allocator.Error!Instruction.Index { - var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })}; - var src_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = src_align })}; + var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = .wrap(dst_align) })}; + var src_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = .wrap(src_align) })}; const value = try self.callIntrinsic( .normal, try self.builder.fnAttrs(&.{ @@ -6192,7 +6224,7 @@ pub const WipFunction = struct { kind: MemoryAccessKind, @"inline": bool, ) Allocator.Error!Instruction.Index { - var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = dst_align })}; + var dst_attrs = [_]Attribute.Index{try self.builder.attr(.{ .@"align" = .wrap(dst_align) })}; const value = try self.callIntrinsic( .normal, try self.builder.fnAttrs(&.{ .none, .none, try self.builder.attrs(&dst_attrs) }), @@ -7329,7 +7361,7 @@ pub const Constant = enum(u32) { //indices: [info.indices_len]Constant, pub const Kind = enum { normal, inbounds }; - pub const InRangeIndex = enum(u16) { none = std.math.maxInt(u16), _ }; + pub const InRangeIndex = enum(u16) { none = maxInt(u16), _ }; pub const Info = packed struct(u32) { indices_len: u16, inrange: InRangeIndex }; }; @@ -7579,7 +7611,7 @@ pub const Constant = enum(u32) { string: [ (std.math.big.int.Const{ .limbs = &([1]std.math.big.Limb{ - std.math.maxInt(std.math.big.Limb), + maxInt(std.math.big.Limb), } ** expected_limbs), .positive = false, }).sizeInBaseUpperBound(10) @@ -7643,7 +7675,7 @@ pub const Constant = enum(u32) { std.math.minInt(Exponent64), else => @as(Exponent64, repr.exponent) + (std.math.floatExponentMax(f64) - std.math.floatExponentMax(f32)), - std.math.maxInt(Exponent32) => std.math.maxInt(Exponent64), + maxInt(Exponent32) => maxInt(Exponent64), }, .sign = repr.sign, }))}); @@ -7820,7 +7852,7 @@ pub const Constant = enum(u32) { }; pub const Value = enum(u32) { - none = std.math.maxInt(u31), + none = maxInt(u31), false = first_constant + @intFromEnum(Constant.false), true = first_constant + @intFromEnum(Constant.true), @"0" = first_constant + @intFromEnum(Constant.@"0"), @@ -8688,6 +8720,8 @@ pub fn init(options: Options) Allocator.Error!Builder { .constant_extra = .empty, .constant_limbs = .empty, + .alignment_forward_references = .empty, + .metadata_map = .empty, .metadata_items = .empty, .metadata_extra = .empty, @@ -8800,51 +8834,55 @@ pub fn clearAndFree(self: *Builder) void { } pub fn deinit(self: *Builder) void { - self.module_asm.deinit(self.gpa); - - self.string_map.deinit(self.gpa); - self.string_indices.deinit(self.gpa); - self.string_bytes.deinit(self.gpa); - - self.types.deinit(self.gpa); - self.next_unique_type_id.deinit(self.gpa); - self.type_map.deinit(self.gpa); - self.type_items.deinit(self.gpa); - self.type_extra.deinit(self.gpa); - - self.attributes.deinit(self.gpa); - self.attributes_map.deinit(self.gpa); - self.attributes_indices.deinit(self.gpa); - self.attributes_extra.deinit(self.gpa); - - self.function_attributes_set.deinit(self.gpa); - - self.globals.deinit(self.gpa); - self.next_unique_global_id.deinit(self.gpa); - self.aliases.deinit(self.gpa); - self.variables.deinit(self.gpa); - for (self.functions.items) |*function| function.deinit(self.gpa); - self.functions.deinit(self.gpa); - - self.strtab_string_map.deinit(self.gpa); - self.strtab_string_indices.deinit(self.gpa); - self.strtab_string_bytes.deinit(self.gpa); - - self.constant_map.deinit(self.gpa); - self.constant_items.deinit(self.gpa); - self.constant_extra.deinit(self.gpa); - self.constant_limbs.deinit(self.gpa); - - self.metadata_map.deinit(self.gpa); - self.metadata_items.deinit(self.gpa); - self.metadata_extra.deinit(self.gpa); - self.metadata_limbs.deinit(self.gpa); - self.metadata_forward_references.deinit(self.gpa); - self.metadata_named.deinit(self.gpa); - - self.metadata_string_map.deinit(self.gpa); - self.metadata_string_indices.deinit(self.gpa); - self.metadata_string_bytes.deinit(self.gpa); + const gpa = self.gpa; + + self.module_asm.deinit(gpa); + + self.string_map.deinit(gpa); + self.string_indices.deinit(gpa); + self.string_bytes.deinit(gpa); + + self.types.deinit(gpa); + self.next_unique_type_id.deinit(gpa); + self.type_map.deinit(gpa); + self.type_items.deinit(gpa); + self.type_extra.deinit(gpa); + + self.attributes.deinit(gpa); + self.attributes_map.deinit(gpa); + self.attributes_indices.deinit(gpa); + self.attributes_extra.deinit(gpa); + + self.function_attributes_set.deinit(gpa); + + self.globals.deinit(gpa); + self.next_unique_global_id.deinit(gpa); + self.aliases.deinit(gpa); + self.variables.deinit(gpa); + for (self.functions.items) |*function| function.deinit(gpa); + self.functions.deinit(gpa); + + self.strtab_string_map.deinit(gpa); + self.strtab_string_indices.deinit(gpa); + self.strtab_string_bytes.deinit(gpa); + + self.constant_map.deinit(gpa); + self.constant_items.deinit(gpa); + self.constant_extra.deinit(gpa); + self.constant_limbs.deinit(gpa); + + self.alignment_forward_references.deinit(gpa); + + self.metadata_map.deinit(gpa); + self.metadata_items.deinit(gpa); + self.metadata_extra.deinit(gpa); + self.metadata_limbs.deinit(gpa); + self.metadata_forward_references.deinit(gpa); + self.metadata_named.deinit(gpa); + + self.metadata_string_map.deinit(gpa); + self.metadata_string_indices.deinit(gpa); + self.metadata_string_bytes.deinit(gpa); self.* = undefined; } @@ -8962,7 +9000,7 @@ pub fn structType( pub fn opaqueType(self: *Builder, name: String) Allocator.Error!Type { try self.string_map.ensureUnusedCapacity(self.gpa, 1); if (name.slice(self)) |id| { - const count: usize = comptime std.fmt.count("{d}", .{std.math.maxInt(u32)}); + const count: usize = comptime std.fmt.count("{d}", .{maxInt(u32)}); try self.string_bytes.ensureUnusedCapacity(self.gpa, id.len + count); } try self.string_indices.ensureUnusedCapacity(self.gpa, 1); @@ -9578,6 +9616,21 @@ pub fn asmValue( return (try self.asmConst(ty, info, assembly, constraints)).toValue(); } +/// The initial "resolved" value of the forward reference is `Alignment.default`. +pub fn alignmentForwardReference(b: *Builder) Allocator.Error!Alignment.Lazy { + const index = b.alignment_forward_references.items.len; + try b.alignment_forward_references.append(b.gpa, .default); + return .fromFwdRefIndex(index); +} + +/// Updates the "resolved" value of the alignment forward reference `fwd_ref` to `value`. +/// +/// Asserts that `fwd_ref` is a forward reference, as opposed to a resolved alignment value. +pub fn resolveAlignmentForwardReference(b: *Builder, fwd_ref: Alignment.Lazy, value: Alignment) void { + const index = fwd_ref.toFwdRefIndex(); + b.alignment_forward_references.items[index] = value; +} + pub fn dump(b: *Builder, io: Io) void { var buffer: [4000]u8 = undefined; const stderr: Io.File = .stderr(); @@ -10515,7 +10568,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void string: [ (std.math.big.int.Const{ .limbs = &([1]std.math.big.Limb{ - std.math.maxInt(std.math.big.Limb), + maxInt(std.math.big.Limb), } ** expected_limbs), .positive = false, }).sizeInBaseUpperBound(10) @@ -10665,7 +10718,7 @@ fn printEscapedString(slice: []const u8, quotes: QuoteBehavior, w: *Writer) Writ fn ensureUnusedGlobalCapacity(self: *Builder, name: StrtabString) Allocator.Error!void { try self.strtab_string_map.ensureUnusedCapacity(self.gpa, 1); if (name.slice(self)) |id| { - const count: usize = comptime std.fmt.count("{d}", .{std.math.maxInt(u32)}); + const count: usize = comptime std.fmt.count("{d}", .{maxInt(u32)}); try self.strtab_string_bytes.ensureUnusedCapacity(self.gpa, id.len + count); } try self.strtab_string_indices.ensureUnusedCapacity(self.gpa, 1); @@ -13518,7 +13571,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco try record.ensureUnusedCapacity(self.gpa, 3); record.appendAssumeCapacity(1); record.appendAssumeCapacity(@intFromEnum(kind)); - record.appendAssumeCapacity(alignment.toByteUnits() orelse 0); + record.appendAssumeCapacity(alignment.resolve(self).toByteUnits() orelse 0); }, .dereferenceable, .dereferenceable_or_null, diff --git a/src/Sema.zig b/src/Sema.zig index 02c2efd2ee7f27c1312ed8d04ed808debeca71f1..9e3024b7eda20650eb9bbf1978658a3061d5c742 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -7110,12 +7110,7 @@ fn analyzeCall( } for (args, 0..) |arg, arg_idx| { const arg_src = args_info.argSrc(block, arg_idx); - const arg_ty = sema.typeOf(arg); try sema.validateRuntimeValue(block, arg_src, arg); - if (arg_ty.isPtrAtRuntime(zcu) or arg_ty.isSliceAtRuntime(zcu)) { - // LLVM wants this information for an "align" attribute on the argument. - try sema.ensureLayoutResolved(arg_ty.nullablePtrElem(zcu), arg_src, .init); - } } const runtime_func: Air.Inst.Ref, const runtime_args: []const Air.Inst.Ref = func: { if (!any_generic_types and !any_comptime_params) break :func .{ callee, args }; @@ -24779,16 +24774,6 @@ fn zirBuiltinExtern( } const ptr_info = ty.ptrInfo(zcu); - if (Type.fromInterned(ptr_info.child).zigTypeTag(zcu) == .@"fn") { - const func_type = ip.indexToKey(ptr_info.child).func_type; - for (func_type.param_types.get(ip)) |param_ty_ip| { - const param_ty: Type = .fromInterned(param_ty_ip); - if (param_ty.isPtrAtRuntime(zcu) or param_ty.isSliceAtRuntime(zcu)) { - // LLVM wants this information for an "align" attribute on the parameter. - try sema.ensureLayoutResolved(param_ty.nullablePtrElem(zcu), ty_src, .parameter); - } - } - } const extern_val = try pt.getExtern(.{ .name = options.name, .ty = ptr_info.child, diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index bf45502faceaabe69c5fc10a3d4aa020224c0276..9fde840232d2ec4d598ef192a6379bb86138af5b 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -1832,16 +1832,6 @@ fn analyzeNavVal( const lib_name_src = block.src(.{ .node_offset_lib_name = .zero }); try sema.handleExternLibName(&block, lib_name_src, l); } - if (nav_ty.zigTypeTag(zcu) == .@"fn") { - const func_type = ip.indexToKey(nav_ty.toIntern()).func_type; - for (func_type.param_types.get(ip)) |param_ty_ip| { - const param_ty: Type = .fromInterned(param_ty_ip); - if (param_ty.isPtrAtRuntime(zcu) or param_ty.isSliceAtRuntime(zcu)) { - // LLVM wants this information for an "align" attribute on the parameter. - try sema.ensureLayoutResolved(param_ty.nullablePtrElem(zcu), ty_src, .parameter); - } - } - } break :val .fromInterned(try pt.getExtern(.{ .name = old_nav.name, .ty = nav_ty.toIntern(), @@ -3398,10 +3388,6 @@ fn analyzeFuncBodyInner( const param_ty_src = inner_block.src(.{ .func_decl_param_ty = @intCast(zir_param_index) }); try sema.ensureLayoutResolved(param_ty, param_ty_src, .parameter); - if (param_ty.isPtrAtRuntime(zcu) or param_ty.isSliceAtRuntime(zcu)) { - // LLVM wants this information for an "align" attribute on the parameter. - try sema.ensureLayoutResolved(param_ty.nullablePtrElem(zcu), param_ty_src, .parameter); - } if (try param_ty.onePossibleValue(pt)) |opv| { gop.value_ptr.* = .fromValue(opv); continue; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 972a536eef0989e5c8f3055a4635f1e0397d32ba..009e472d06f4229c067d4e96f0dee78bc0f22aa3 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -520,6 +520,21 @@ pub const Object = struct { gpa: Allocator, builder: Builder, + /// This pool contains only types (and not `@as(type, undefined)`). It has two purposes: + /// + /// * Lazily tracking ABI alignment of types, so that `@"align"` attributes can be set to a + /// type's ABI alignment before that type is fully resolved. Each type in the pool has a + /// corresponding entry in `lazy_abi_aligns`. + /// + /// * If `!Object.builder.strip`, lazily tracking debug information types, so that debug + /// information can handle indirect self-reference (and so that debug information works + /// correctly across incremental updates). Each type has a corresponding entry in + /// `debug_types`, provided that `Object.builder.strip` is `false`. + type_pool: link.ConstPool, + + /// Keyed on `link.ConstPool.Index`. + lazy_abi_aligns: std.ArrayList(Builder.Alignment.Lazy), + debug_compile_unit: Builder.Metadata.Optional, debug_enums_fwd_ref: Builder.Metadata.Optional, @@ -530,8 +545,6 @@ pub const Object = struct { debug_file_map: std.AutoHashMapUnmanaged(Zcu.File.Index, Builder.Metadata), - /// This pool *only* contains types (and does not contain `@as(type, undefined)`). - debug_type_pool: link.ConstPool, /// Keyed on `link.ConstPool.Index`. debug_types: std.ArrayList(Builder.Metadata), /// Initially `.none`, set if the type `anyerror` is lowered to a debug type. The type will not @@ -660,13 +673,14 @@ pub const Object = struct { obj.* = .{ .gpa = gpa, .builder = builder, + .type_pool = .empty, + .lazy_abi_aligns = .empty, .debug_compile_unit = debug_compile_unit, .debug_enums_fwd_ref = debug_enums_fwd_ref, .debug_globals_fwd_ref = debug_globals_fwd_ref, .debug_enums = .empty, .debug_globals = .empty, .debug_file_map = .empty, - .debug_type_pool = .empty, .debug_types = .empty, .debug_anyerror_fwd_ref = .none, .target = target, @@ -685,10 +699,11 @@ pub const Object = struct { pub fn deinit(self: *Object) void { const gpa = self.gpa; + self.type_pool.deinit(gpa); + self.lazy_abi_aligns.deinit(gpa); self.debug_enums.deinit(gpa); self.debug_globals.deinit(gpa); self.debug_file_map.deinit(gpa); - self.debug_type_pool.deinit(gpa); self.debug_types.deinit(gpa); self.nav_map.deinit(gpa); self.uav_map.deinit(gpa); @@ -836,7 +851,7 @@ pub const Object = struct { o.builder.resolveDebugForwardReference(fwd_ref, debug_anyerror_type); } - try o.flushPendingDebugTypes(pt); + try o.flushTypePool(pt); o.builder.resolveDebugForwardReference( o.debug_enums_fwd_ref.unwrap().?, @@ -1396,10 +1411,10 @@ pub const Object = struct { if (ptr_info.flags.is_const) { try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); } - const elem_align = (if (ptr_info.flags.alignment != .none) - @as(InternPool.Alignment, ptr_info.flags.alignment) - else - Type.fromInterned(ptr_info.child).abiAlignment(zcu).max(.@"1")).toLlvm(); + const elem_align: Builder.Alignment.Lazy = switch (ptr_info.flags.alignment) { + else => |a| .wrap(a.toLlvm()), + .none => try o.lazyAbiAlignment(pt, .fromInterned(ptr_info.child)), + }; try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder); const ptr_param = wip.arg(llvm_arg_i); llvm_arg_i += 1; @@ -1600,7 +1615,7 @@ pub const Object = struct { } try fg.wip.finish(); - try o.flushPendingDebugTypes(pt); + try o.flushTypePool(pt); } pub fn updateNav(self: *Object, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { @@ -1617,11 +1632,11 @@ pub const Object = struct { }, else => |e| return e, }; - try self.flushPendingDebugTypes(pt); + try self.flushTypePool(pt); } - fn flushPendingDebugTypes(o: *Object, pt: Zcu.PerThread) Allocator.Error!void { - try o.debug_type_pool.flushPending(pt, .{ .llvm = o }); + fn flushTypePool(o: *Object, pt: Zcu.PerThread) Allocator.Error!void { + try o.type_pool.flushPending(pt, .{ .llvm = o }); } pub fn updateExports( @@ -1818,51 +1833,81 @@ pub const Object = struct { } pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Allocator.Error!void { - if (!o.builder.strip) { - try o.debug_type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success); - } + try o.type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success); } /// Should only be called by the `link.ConstPool` implementation. /// - /// `val` is always a type because `o.debug_type_pool` only contains types. + /// `val` is always a type because `o.type_pool` only contains types. pub fn addConst(o: *Object, pt: Zcu.PerThread, index: link.ConstPool.Index, val: InternPool.Index) Allocator.Error!void { const zcu = pt.zcu; const gpa = zcu.comp.gpa; assert(zcu.intern_pool.typeOf(val) == .type_type); - assert(@intFromEnum(index) == o.debug_types.items.len); - try o.debug_types.ensureUnusedCapacity(gpa, 1); - const fwd_ref = try o.builder.debugForwardReference(); - o.debug_types.appendAssumeCapacity(fwd_ref); - if (val == .anyerror_type) { - assert(o.debug_anyerror_fwd_ref.is_none); - o.debug_anyerror_fwd_ref = fwd_ref.toOptional(); + + { + assert(@intFromEnum(index) == o.lazy_abi_aligns.items.len); + try o.lazy_abi_aligns.ensureUnusedCapacity(gpa, 1); + const fwd_ref = try o.builder.alignmentForwardReference(); + o.lazy_abi_aligns.appendAssumeCapacity(fwd_ref); + } + + if (!o.builder.strip) { + assert(@intFromEnum(index) == o.debug_types.items.len); + try o.debug_types.ensureUnusedCapacity(gpa, 1); + const fwd_ref = try o.builder.debugForwardReference(); + o.debug_types.appendAssumeCapacity(fwd_ref); + if (val == .anyerror_type) { + assert(o.debug_anyerror_fwd_ref.is_none); + o.debug_anyerror_fwd_ref = fwd_ref.toOptional(); + } } } /// Should only be called by the `link.ConstPool` implementation. /// - /// `val` is always a type because `o.debug_type_pool` only contains types. + /// `val` is always a type because `o.type_pool` only contains types. pub fn updateConstIncomplete(o: *Object, pt: Zcu.PerThread, index: link.ConstPool.Index, val: InternPool.Index) Allocator.Error!void { - assert(pt.zcu.intern_pool.typeOf(val) == .type_type); - const fwd_ref = o.debug_types.items[@intFromEnum(index)]; - assert(val != .anyerror_type); - const name_str = try o.builder.metadataStringFmt("{f}", .{Type.fromInterned(val).fmt(pt)}); - const debug_incomplete_type = try o.builder.debugSignedType(name_str, 0); - o.builder.resolveDebugForwardReference(fwd_ref, debug_incomplete_type); + const zcu = pt.zcu; + assert(zcu.intern_pool.typeOf(val) == .type_type); + + const ty: Type = .fromInterned(val); + + { + const fwd_ref = o.lazy_abi_aligns.items[@intFromEnum(index)]; + o.builder.resolveAlignmentForwardReference(fwd_ref, .fromByteUnits(1)); + } + + if (!o.builder.strip) { + assert(val != .anyerror_type); + const fwd_ref = o.debug_types.items[@intFromEnum(index)]; + const name_str = try o.builder.metadataStringFmt("{f}", .{ty.fmt(pt)}); + const debug_incomplete_type = try o.builder.debugSignedType(name_str, 0); + o.builder.resolveDebugForwardReference(fwd_ref, debug_incomplete_type); + } } /// Should only be called by the `link.ConstPool` implementation. /// - /// `val` is always a type because `o.debug_type_pool` only contains types. + /// `val` is always a type because `o.type_pool` only contains types. pub fn updateConst(o: *Object, pt: Zcu.PerThread, index: link.ConstPool.Index, val: InternPool.Index) Allocator.Error!void { - assert(pt.zcu.intern_pool.typeOf(val) == .type_type); - const fwd_ref = o.debug_types.items[@intFromEnum(index)]; - if (val == .anyerror_type) { - // Don't lower this now; it will be populated in `emit` instead. - assert(o.debug_anyerror_fwd_ref == fwd_ref.toOptional()); - return; + const zcu = pt.zcu; + assert(zcu.intern_pool.typeOf(val) == .type_type); + + const ty: Type = .fromInterned(val); + + { + const fwd_ref = o.lazy_abi_aligns.items[@intFromEnum(index)]; + o.builder.resolveAlignmentForwardReference(fwd_ref, ty.abiAlignment(zcu).toLlvm()); + } + + if (!o.builder.strip) { + const fwd_ref = o.debug_types.items[@intFromEnum(index)]; + if (val == .anyerror_type) { + // Don't lower this now; it will be populated in `emit` instead. + assert(o.debug_anyerror_fwd_ref == fwd_ref.toOptional()); + } else { + const debug_type = try o.lowerDebugType(pt, ty, fwd_ref); + o.builder.resolveDebugForwardReference(fwd_ref, debug_type); + } } - const debug_type = try o.lowerDebugType(pt, .fromInterned(val), fwd_ref); - o.builder.resolveDebugForwardReference(fwd_ref, debug_type); } fn getDebugFile(o: *Object, pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator.Error!Builder.Metadata { @@ -1883,7 +1928,7 @@ pub const Object = struct { fn getDebugType(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error!Builder.Metadata { assert(!o.builder.strip); - const index = try o.debug_type_pool.get(pt, .{ .llvm = o }, ty.toIntern()); + const index = try o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern()); return o.debug_types.items[@intFromEnum(index)]; } @@ -2680,7 +2725,7 @@ pub const Object = struct { function_index.setCallConv(cc_info.llvm_cc, &o.builder); if (cc_info.align_stack) { - try attributes.addFnAttr(.{ .alignstack = .fromByteUnits(target.stackAlignment()) }, &o.builder); + try attributes.addFnAttr(.{ .alignstack = .wrap(.fromByteUnits(target.stackAlignment())) }, &o.builder); } else { _ = try attributes.removeFnAttr(.alignstack); } @@ -4166,11 +4211,11 @@ pub const Object = struct { if (ptr_info.flags.is_const) { try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); } - const elem_align = if (ptr_info.flags.alignment != .none) - ptr_info.flags.alignment - else - Type.fromInterned(ptr_info.child).abiAlignment(zcu).max(.@"1"); - try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align.toLlvm() }, &o.builder); + const elem_align: Builder.Alignment.Lazy = switch (ptr_info.flags.alignment) { + else => |a| .wrap(a.toLlvm()), + .none => try o.lazyAbiAlignment(pt, .fromInterned(ptr_info.child)), + }; + try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder); } else if (ccAbiPromoteInt(fn_info.cc, zcu, param_ty)) |s| switch (s) { .signed => try attributes.addParamAttr(llvm_arg_i, .signext, &o.builder), .unsigned => try attributes.addParamAttr(llvm_arg_i, .zeroext, &o.builder), @@ -4187,7 +4232,7 @@ pub const Object = struct { ) Allocator.Error!void { try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); - try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = alignment }, &o.builder); + try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = .wrap(alignment) }, &o.builder); if (byval) try attributes.addParamAttr(llvm_arg_i, .{ .byval = param_llvm_ty }, &o.builder); } @@ -4297,6 +4342,11 @@ pub const Object = struct { try wip.finish(); return function_index; } + + fn lazyAbiAlignment(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error!Builder.Alignment.Lazy { + const index = try o.type_pool.get(pt, .{ .llvm = o }, ty.toIntern()); + return o.lazy_abi_aligns.items[@intFromEnum(index)]; + } }; pub const NavGen = struct { @@ -5259,10 +5309,10 @@ pub const FuncGen = struct { if (ptr_info.flags.is_const) { try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); } - const elem_align = (if (ptr_info.flags.alignment != .none) - @as(InternPool.Alignment, ptr_info.flags.alignment) - else - Type.fromInterned(ptr_info.child).abiAlignment(zcu).max(.@"1")).toLlvm(); + const elem_align: Builder.Alignment.Lazy = switch (ptr_info.flags.alignment) { + else => |a| .wrap(a.toLlvm()), + .none => try o.lazyAbiAlignment(pt, .fromInterned(ptr_info.child)), + }; try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = elem_align }, &o.builder); }, }; -- 2.54.0 From 978f7fb1ff1cdb36f48b774516aa09ab6a1dfbc0 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sat, 28 Feb 2026 11:40:25 +0000 Subject: [PATCH 58/79] Zcu: improve error message sorting --- src/Compilation.zig | 55 ++++++++------------------------------------- src/Zcu.zig | 53 ++++++++++++++++++++++++------------------- 2 files changed, 39 insertions(+), 69 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index dad807fcbef769a4f92cc38848f2292481866e95..9bf91302d891715a058ee152eecb35e8157b70e6 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -4054,21 +4054,12 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { const SortOrder = struct { zcu: *Zcu, errors: []const *Zcu.ErrorMsg, - read_err: *?ReadError, - const ReadError = struct { - file: *Zcu.File, - err: Zcu.File.GetSourceError, - }; pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool { - if (ctx.read_err.* != null) return lhs_index < rhs_index; - var bad_file: *Zcu.File = undefined; - return ctx.errors[lhs_index].src_loc.lessThan(ctx.errors[rhs_index].src_loc, ctx.zcu, &bad_file) catch |err| { - ctx.read_err.* = .{ - .file = bad_file, - .err = err, - }; - return lhs_index < rhs_index; - }; + return Zcu.ErrorMsg.order( + ctx.errors[lhs_index], + ctx.errors[rhs_index], + ctx.zcu, + ).compare(.lt); } }; @@ -4078,16 +4069,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { var entries = try zcu.failed_analysis.entries.clone(gpa); errdefer entries.deinit(gpa); - var read_err: ?SortOrder.ReadError = null; entries.sort(SortOrder{ .zcu = zcu, .errors = entries.items(.value), - .read_err = &read_err, }); - if (read_err) |e| { - try unableToLoadZcuFile(zcu, &bundle, e.file, e.err); - break :zcu_errors; - } break :s entries.slice(); }; defer sorted_failed_analysis.deinit(gpa); @@ -4208,33 +4193,11 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { // Okay, there *are* referenced compile logs. Sort them into a consistent order. - { - const SortContext = struct { - zcu: *Zcu, - read_err: *?ReadError, - const ReadError = struct { - file: *Zcu.File, - err: Zcu.File.GetSourceError, - }; - fn lessThan(ctx: @This(), lhs: Zcu.ErrorMsg, rhs: Zcu.ErrorMsg) bool { - if (ctx.read_err.* != null) return false; - var bad_file: *Zcu.File = undefined; - return lhs.src_loc.lessThan(rhs.src_loc, ctx.zcu, &bad_file) catch |err| { - ctx.read_err.* = .{ - .file = bad_file, - .err = err, - }; - return false; - }; - } - }; - var read_err: ?SortContext.ReadError = null; - std.mem.sort(Zcu.ErrorMsg, messages.items, @as(SortContext, .{ .read_err = &read_err, .zcu = zcu }), SortContext.lessThan); - if (read_err) |e| { - try unableToLoadZcuFile(zcu, &bundle, e.file, e.err); - break :compile_log_text ""; + std.mem.sort(Zcu.ErrorMsg, messages.items, zcu, struct { + fn lessThan(zcu_inner: *Zcu, lhs: Zcu.ErrorMsg, rhs: Zcu.ErrorMsg) bool { + return Zcu.ErrorMsg.order(&lhs, &rhs, zcu_inner).compare(.lt); } - } + }.lessThan); var log_text: std.ArrayList(u8) = .empty; defer log_text.deinit(gpa); diff --git a/src/Zcu.zig b/src/Zcu.zig index c623c1ec49f110d79676431c59481e6339613948..eb4b8bdb05be4006f163fe2e48ff5746537a8905 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -1250,6 +1250,15 @@ pub const ErrorMsg = struct { notes: []ErrorMsg = &.{}, reference_trace_root: AnalUnit.Optional = .none, + pub fn order(lhs: *const ErrorMsg, rhs: *const ErrorMsg, zcu: *Zcu) std.math.Order { + return lhs.src_loc.order(rhs.src_loc, zcu).differ() orelse + std.mem.order(u8, lhs.msg, rhs.msg).differ() orelse + std.math.order(lhs.notes.len, rhs.notes.len).differ() orelse + for (lhs.notes, rhs.notes) |*lhs_note, *rhs_note| { + if (order(lhs_note, rhs_note, zcu).differ()) |o| break o; + } else .eq; + } + pub fn create( gpa: Allocator, src_loc: LazySrcLoc, @@ -2724,36 +2733,34 @@ pub const LazySrcLoc = struct { }; } - /// Used to sort error messages, so that they're printed in a consistent order. - /// If an error is returned, a file could not be read in order to resolve a source location. - /// In that case, `bad_file_out` is populated, and sorting is impossible. - pub fn lessThan(lhs_lazy: LazySrcLoc, rhs_lazy: LazySrcLoc, zcu: *Zcu, bad_file_out: **Zcu.File) File.GetSourceError!bool { - const lhs_src = lhs_lazy.upgradeOrLost(zcu) orelse { + pub fn order(lhs: LazySrcLoc, rhs: LazySrcLoc, zcu: *Zcu) std.math.Order { + const lhs_resolved = lhs.upgradeOrLost(zcu) orelse { // LHS source location lost, so should never be referenced. Just sort it to the end. - return false; + return .gt; }; - const rhs_src = rhs_lazy.upgradeOrLost(zcu) orelse { + const rhs_resolved = rhs.upgradeOrLost(zcu) orelse { // RHS source location lost, so should never be referenced. Just sort it to the end. - return true; + return .lt; }; - if (lhs_src.file_scope != rhs_src.file_scope) { - const lhs_path = lhs_src.file_scope.path; - const rhs_path = rhs_src.file_scope.path; - if (lhs_path.root != rhs_path.root) { - return @intFromEnum(lhs_path.root) < @intFromEnum(rhs_path.root); - } - return std.mem.order(u8, lhs_path.sub_path, rhs_path.sub_path).compare(.lt); + if (lhs_resolved.file_scope != rhs_resolved.file_scope) { + const lhs_path = lhs_resolved.file_scope.path; + const rhs_path = rhs_resolved.file_scope.path; + return std.math.order(@intFromEnum(lhs_path.root), @intFromEnum(rhs_path.root)).differ() orelse + std.mem.order(u8, lhs_path.sub_path, rhs_path.sub_path).differ().?; } - - const lhs_span = lhs_src.span(zcu) catch |err| { - bad_file_out.* = lhs_src.file_scope; - return err; + const prev_prot = zcu.comp.io.swapCancelProtection(.blocked); + defer _ = zcu.comp.io.swapCancelProtection(prev_prot); + const lhs_span = lhs_resolved.span(zcu) catch |err| { + assert(err != error.Canceled); // we're protected + // Failed to read LHS, so we'll get a transient error. Just sort it to the end. + return .gt; }; - const rhs_span = rhs_src.span(zcu) catch |err| { - bad_file_out.* = rhs_src.file_scope; - return err; + const rhs_span = rhs_resolved.span(zcu) catch |err| { + assert(err != error.Canceled); // we're protected + // Failed to read RHS, so we'll get a transient error. Just sort it to the end. + return .lt; }; - return lhs_span.main < rhs_span.main; + return std.math.order(lhs_span.main, rhs_span.main); } }; -- 2.54.0 From c64755fb2f3178b4f593ef9f2cb54beef03af36f Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sat, 28 Feb 2026 11:58:23 +0000 Subject: [PATCH 59/79] Type: fix assertion failure --- src/Type.zig | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Type.zig b/src/Type.zig index 60adb6f10ffb7601d85eb337ff05cafe452b1cba..4aca4ed834a968cebfb940e7e912809e75dbc5f1 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -3094,7 +3094,7 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool if (ty.isSlice(zcu)) return false; const child_ty = ty.childType(zcu); if (child_ty.zigTypeTag(zcu) == .@"fn") { - return ty.isConstPtr(zcu) and child_ty.validateExtern(.other, zcu); + return ty.isConstPtr(zcu) and validateExternCallconv(child_ty.fnCallingConvention(zcu)); } return true; }, @@ -3104,12 +3104,7 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool }, .@"fn" => { if (position != .other) return false; - // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI. - // The goal is to experiment with more integrated CPU/GPU code. - if (ty.fnCallingConvention(zcu) == .nvptx_kernel) { - return true; - } - return !target_util.fnCallConvAllowsZigTypes(ty.fnCallingConvention(zcu)); + return validateExternCallconv(ty.fnCallingConvention(zcu)); }, .@"enum" => { const enum_obj = zcu.intern_pool.loadEnumType(ty.toIntern()); @@ -3155,6 +3150,14 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool .optional => ty.isPtrLikeOptional(zcu), }; } +fn validateExternCallconv(cc: std.builtin.CallingConvention) bool { + return switch (cc) { + // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI. + // The goal is to experiment with more integrated CPU/GPU code. + .nvptx_kernel => true, + else => !target_util.fnCallConvAllowsZigTypes(cc), + }; +} /// Asserts that `ty` has resolved layout. pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void { -- 2.54.0 From 4eb8360911d80d4891be6ed47792121a2ccde353 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 1 Mar 2026 07:32:09 +0000 Subject: [PATCH 60/79] compiler: various lil' fixes --- lib/compiler/objcopy.zig | 4 +- lib/std/pdb.zig | 4 +- lib/std/zig/AstGen.zig | 5 + src/Compilation.zig | 3 +- src/Sema.zig | 191 +++++++++++++++++------------------ src/Sema/arith.zig | 3 + src/Sema/type_resolution.zig | 46 ++++++--- src/Type.zig | 14 ++- src/Value.zig | 14 ++- src/Zcu.zig | 44 +++++++- src/Zcu/PerThread.zig | 97 +++++++++++------- src/codegen/c.zig | 15 ++- src/codegen/c/type.zig | 14 ++- src/codegen/llvm.zig | 32 ++---- src/link/Dwarf.zig | 6 ++ src/print_value.zig | 23 ++++- 16 files changed, 312 insertions(+), 203 deletions(-) diff --git a/lib/compiler/objcopy.zig b/lib/compiler/objcopy.zig index 57d019bc95b8887c9bce708d6be08fb3abc9205a..9c3fffc67f07b8e6c918d554747ba6a421ba026d 100644 --- a/lib/compiler/objcopy.zig +++ b/lib/compiler/objcopy.zig @@ -388,8 +388,8 @@ const BinaryElfOutput = struct { pub fn parse(allocator: Allocator, in: *File.Reader, elf_hdr: elf.Header) !Self { var self: Self = .{ - .segments = .{}, - .sections = .{}, + .segments = .empty, + .sections = .empty, .allocator = allocator, .shstrtab = null, }; diff --git a/lib/std/pdb.zig b/lib/std/pdb.zig index 7e479de8d4fe196594c6184b9721d11f31e2051d..094537972b3c7e7e560019f56178631f52663312 100644 --- a/lib/std/pdb.zig +++ b/lib/std/pdb.zig @@ -332,7 +332,7 @@ pub const ProcSym = extern struct { name: [1]u8, // null-terminated }; -pub const ProcSymFlags = packed struct { +pub const ProcSymFlags = packed struct(u8) { has_fp: bool, has_iret: bool, has_fret: bool, @@ -373,7 +373,7 @@ pub const LineFragmentHeader = extern struct { code_size: u32, }; -pub const LineFlags = packed struct { +pub const LineFlags = packed struct(u16) { /// CV_LINES_HAVE_COLUMNS have_columns: bool, unused: u15, diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index 1fcb9f5eb2aac77802763ac742913899c71ede4e..377c9fb8dc6eda208b5581264399180cec8388f8 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -5513,6 +5513,11 @@ fn containerDecl( if (next_field_idx != fields_len) { return astgen.failNode(member_node, "'_' field of non-exhaustive enum must be last", .{}); } + if (tag_type_body_len == null) { + return astgen.failNodeNotes(node, "non-exhaustive enum missing integer tag type", .{}, &.{ + try astgen.errNoteNode(member_node, "marked non-exhaustive here", .{}), + }); + } opt_nonexhaustive_node = member_node.toOptional(); continue; } diff --git a/src/Compilation.zig b/src/Compilation.zig index 9bf91302d891715a058ee152eecb35e8157b70e6..9fbc36f070b5239b2a2d2ff0ec113055b929c79d 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -4180,7 +4180,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { if (!refs.contains(logging_unit)) continue; try messages.append(gpa, .{ .src_loc = compile_log.src(), - .msg = undefined, // populated later + .msg = "", // populated later, but must be valid for `sort` call below .notes = &.{}, // We actually clear this later for most of these, but we populate // 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 { break :compile_log_text try log_text.toOwnedSlice(gpa); }; + defer gpa.free(compile_log_text); // TODO: eventually, this should be behind `std.debug.runtime_safety`. But right now, this is a // very common way for incremental compilation bugs to manifest, so let's always check it. diff --git a/src/Sema.zig b/src/Sema.zig index 9e3024b7eda20650eb9bbf1978658a3061d5c742..2af1c8cf107895931f393e0298defc8bd6ddcbda 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -416,7 +416,7 @@ pub const Block = struct { return block.comptime_reason != null; } - fn builtinCallArgSrc(block: *Block, builtin_call_node: std.zig.Ast.Node.Offset, arg_index: u32) LazySrcLoc { + pub fn builtinCallArgSrc(block: *Block, builtin_call_node: std.zig.Ast.Node.Offset, arg_index: u32) LazySrcLoc { return block.src(.{ .node_offset_builtin_call_arg = .{ .builtin_call_node = builtin_call_node, .arg_index = arg_index, @@ -4654,47 +4654,14 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr .slice => return sema.fail(block, src, "index syntax required for slice type '{f}'", .{operand_ty.fmt(pt)}), } - const elem_ty = operand_ty.childType(zcu); - try sema.ensureLayoutResolved(elem_ty, src, .ptr_access); - - const need_comptime = switch (elem_ty.classify(zcu)) { - .no_possible_value => return sema.fail(block, src, "cannot load {s} type '{f}'", .{ - if (elem_ty.zigTypeTag(zcu) == .@"opaque") "opaque" else "uninstantiable", - elem_ty.fmt(pt), - }), - .one_possible_value => return, // no need to validate the actual pointer value! - .runtime => false, - .partially_comptime, .fully_comptime => true, - }; - if (sema.resolveValue(operand)) |val| { - if (val.isUndef(zcu)) { + // Error for deref of undef pointer, unless the pointee is OPV in which case it's legal. + if (val.isUndef(zcu) and operand_ty.childType(zcu).classify(zcu) != .one_possible_value) { return sema.fail(block, src, "cannot dereference undefined value", .{}); } - } else if (need_comptime) { - const msg = msg: { - const msg = try sema.errMsg( - src, - "values of type '{f}' must be comptime-known, but operand value is runtime-known", - .{elem_ty.fmt(pt)}, - ); - errdefer msg.destroy(sema.gpa); - - try sema.explainWhyTypeIsComptime(msg, src, elem_ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); } } -fn typeIsDestructurable(ty: Type, zcu: *const Zcu) bool { - return switch (ty.zigTypeTag(zcu)) { - .array, .vector => true, - .@"struct" => ty.isTuple(zcu), - else => false, - }; -} - fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const pt = sema.pt; const zcu = pt.zcu; @@ -4705,14 +4672,14 @@ fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp const operand = sema.resolveInst(extra.operand); const operand_ty = sema.typeOf(operand); - if (!typeIsDestructurable(operand_ty, zcu)) { + if (!operand_ty.destructurable(zcu)) { return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(src, "type '{f}' cannot be destructured", .{operand_ty.fmt(pt)}); errdefer msg.destroy(sema.gpa); try sema.errNote(destructure_src, msg, "result destructured here", .{}); if (operand_ty.zigTypeTag(pt.zcu) == .error_union) { const base_op_ty = operand_ty.errorUnionPayload(zcu); - if (typeIsDestructurable(base_op_ty, zcu)) + if (base_op_ty.destructurable(zcu)) try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); } break :msg msg; @@ -8247,8 +8214,15 @@ fn zirOptionalPayload( else => return sema.failWithExpectedOptionalType(block, src, operand_ty), }; - if (try sema.resolveDefinedValue(block, src, operand)) |val| { - if (val.optionalValue(zcu)) |payload| return Air.internedToRef(payload.toIntern()); + ct: { + if (try sema.resolveDefinedValue(block, src, operand)) |val| { + if (val.optionalValue(zcu)) |payload| return .fromValue(payload); // comptime-known payload + } else if (try sema.resolveIsNullFromType(block, src, operand_ty)) |is_null| { + if (!is_null) break :ct; // fully runtime-known + } else { + break :ct; // fully runtime-known + } + // Comptime-known to be `null`. if (block.isComptime()) return sema.fail(block, src, "unable to unwrap null", .{}); if (safety_check and block.wantSafety()) { try sema.safetyPanic(block, src, .unwrap_null); @@ -21085,7 +21059,8 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData continue :check ip.funcIesResolvedUnordered(func_index); }, .error_set_type => |dest| { - if (operand_err_ty.isAnyError(zcu)) break :check .superset; + if (dest.names.len == 0) break :check .disjoint; // dest is 'error{}' + if (operand_err_ty.isAnyError(zcu)) break :check .overlap; // anyerror -> error{...} (non-empty) var dest_has_all = true; var dest_has_any = false; for (operand_err_ty.errorSetNames(zcu).get(ip)) |operand_err_name| { @@ -24741,15 +24716,30 @@ fn zirBuiltinExtern( const ty_src = block.builtinCallArgSrc(extra.node, 0); const options_src = block.builtinCallArgSrc(extra.node, 1); - var ty = try sema.resolveType(block, ty_src, extra.lhs); - if (!ty.isPtrAtRuntime(zcu)) { + const ptr_ty = try sema.resolveType(block, ty_src, extra.lhs); + if (!ptr_ty.isPtrAtRuntime(zcu)) { return sema.fail(block, ty_src, "expected (optional) pointer", .{}); } - if (!ty.validateExtern(.other, zcu)) { + + const ptr_info = ptr_ty.ptrInfo(zcu); + + const elem_ty: Type = .fromInterned(ptr_info.child); + try sema.ensureLayoutResolved(elem_ty, src, .@"extern"); + + if (!elem_ty.validateExtern(.other, zcu)) { return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(ty_src, "extern symbol cannot have type '{f}'", .{ty.fmt(pt)}); + const msg = try sema.errMsg(ty_src, "extern symbol cannot have type '{f}'", .{ptr_ty.fmt(pt)}); errdefer msg.destroy(sema.gpa); - try sema.explainWhyTypeIsNotExtern(msg, ty_src, ty, .other); + try sema.errNote(ty_src, msg, "pointer element type '{f}' is not extern compatible", .{elem_ty.fmt(pt)}); + try sema.explainWhyTypeIsNotExtern(msg, ty_src, elem_ty, .other); + break :msg msg; + }); + } + if (elem_ty.zigTypeTag(zcu) == .@"fn" and !ptr_info.flags.is_const) { + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(ty_src, "extern symbol cannot have type '{f}'", .{ptr_ty.fmt(pt)}); + errdefer msg.destroy(sema.gpa); + try sema.errNote(ty_src, msg, "pointer to extern function must be 'const'", .{}); break :msg msg; }); } @@ -24769,14 +24759,9 @@ fn zirBuiltinExtern( // TODO: error for threadlocal functions, non-const functions, etc - if (options.linkage == .weak and !ty.ptrAllowsZero(zcu)) { - ty = try pt.optionalType(ty.toIntern()); - } - const ptr_info = ty.ptrInfo(zcu); - const extern_val = try pt.getExtern(.{ .name = options.name, - .ty = ptr_info.child, + .ty = elem_ty.toIntern(), .lib_name = options.library_name, .linkage = options.linkage, .visibility = options.visibility, @@ -24807,13 +24792,17 @@ fn zirBuiltinExtern( .source = .builtin, }); + // For a weak symbol where the given type is not nullable, make the pointer optional. + const result_ptr_ty: Type = if (options.linkage == .weak and !ptr_ty.ptrAllowsZero(zcu)) ty: { + break :ty try pt.optionalType(ptr_ty.toIntern()); + } else ptr_ty; + const uncasted_ptr = try sema.analyzeNavRef(block, src, ip.indexToKey(extern_val).@"extern".owner_nav); - // We want to cast to `ty`, but that isn't necessarily an allowed coercion. if (sema.resolveValue(uncasted_ptr)) |uncasted_ptr_val| { - const casted_ptr_val = try pt.getCoerced(uncasted_ptr_val, ty); + const casted_ptr_val = try pt.getCoerced(uncasted_ptr_val, result_ptr_ty); return Air.internedToRef(casted_ptr_val.toIntern()); } else { - return block.addBitCast(ty, uncasted_ptr); + return block.addBitCast(result_ptr_ty, uncasted_ptr); } } @@ -25258,6 +25247,7 @@ pub fn explainWhyTypeIsUnpackable( try sema.errNote(src, msg, "non-packed unions do not have a bit-packed representation", .{}); try sema.addDeclaredHereNote(msg, union_ty); }, + .slice => try sema.errNote(src, msg, "slices do not have a bit-packed representation", .{}), .other => try sema.errNote(src, msg, "type does not have a bit-packed representation", .{}), } } @@ -25501,7 +25491,10 @@ fn addSafetyCheckSentinelMismatch( }; assert(sema.typeOf(actual_sentinel).toIntern() == sentinel_ty.toIntern()); assert(sentinel_ty.isSelfComparable(zcu, true)); - const ok = try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel); + const ok: Air.Inst.Ref = if (sentinel_ty.zigTypeTag(zcu) == .vector) ok: { + const elementwise = try parent_block.addCmpVector(expected_sentinel, actual_sentinel, .eq); + break :ok try parent_block.addReduce(elementwise, .And); + } else try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel); return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.sentinelMismatch", &.{ expected_sentinel, actual_sentinel, @@ -26574,8 +26567,13 @@ fn unionFieldVal( const active_tag_val = union_val.unionTag(zcu).?; const active_index = enum_tag_ty.enumTagFieldIndex(active_tag_val, zcu).?; if (active_index == field_index) return .fromValue(union_val.unionPayload(zcu)); - return sema.fail(block, src, "access of union field '{f}' while field '{f}' is active", .{ - field_name.fmt(ip), enum_tag_ty.enumFieldName(active_index, zcu).fmt(ip), + return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(src, "access of union field '{f}' while field '{f}' is active", .{ + field_name.fmt(ip), enum_tag_ty.enumFieldName(active_index, zcu).fmt(ip), + }); + errdefer msg.destroy(zcu.comp.gpa); + try sema.addDeclaredHereNote(msg, union_ty); + break :msg msg; }); }, .@"extern" => if (try sema.bitCastVal(union_val, field_ty, 0, 0, 0)) |field_val| { @@ -26745,9 +26743,17 @@ fn elemVal( return sema.analyzeLoad(block, src, .fromValue(elem_ptr_val), indexable_src); } - if (try child_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); + try sema.validateRuntimeElemAccess(block, elem_index_src, child_ty, indexable_ty, src); + switch (child_ty.classify(zcu)) { + .runtime => {}, + .one_possible_value => return .fromValue((try child_ty.onePossibleValue(pt)).?), + .no_possible_value => switch (child_ty.zigTypeTag(zcu)) { + .@"opaque" => return sema.fail(block, src, "cannot load opaque type '{f}'", .{child_ty.fmt(pt)}), + else => return sema.fail(block, src, "cannot load uninstantiable type '{f}'", .{child_ty.fmt(pt)}), + }, + .partially_comptime, .fully_comptime => unreachable, // caught by `validateRuntimeElemAccess` + } - try sema.checkLogicalPtrOperation(block, src, indexable_ty); return block.addBinOp(.ptr_elem_val, indexable, elem_index); }, .one => { @@ -29082,31 +29088,6 @@ fn storePtr2( const elem_ty = ptr_ty.childType(zcu); - // To generate better code for tuples, we detect a tuple operand here, and - // analyze field loads and stores directly. This avoids an extra allocation + memcpy - // which would occur if we used `coerce`. - // However, we avoid this mechanism if the destination element type is a tuple, - // because the regular store will be better for this case. - // If the destination type is a struct we don't want this mechanism to trigger, because - // this code does not handle tuple-to-struct coercion which requires dealing with missing - // fields. - const operand_ty = sema.typeOf(uncasted_operand); - if (operand_ty.isTuple(zcu) and elem_ty.zigTypeTag(zcu) == .array) { - const field_count = operand_ty.structFieldCount(zcu); - var i: u32 = 0; - while (i < field_count) : (i += 1) { - const elem_src = operand_src; // TODO better source location - const elem = try sema.tupleField(block, operand_src, uncasted_operand, elem_src, i); - const elem_index = try pt.intRef(.usize, i); - const elem_ptr = try sema.elemPtr(block, ptr_src, ptr, elem_index, elem_src, false, true); - try sema.storePtr2(block, src, elem_ptr, elem_src, elem, elem_src, .store); - } - return; - } - - // TODO do the same thing for anon structs as for tuples above. - // However, beware of the need to handle missing/extra fields. - const is_ret = air_tag == .ret_ptr; 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( return sema.storePtrVal(block, src, ptr_val, operand_val, elem_ty); }; - // We're performing the store at runtime; as such, we need to make sure the pointee type - // is not comptime-only. We can hit this case with a `@ptrFromInt` pointer. - if (comptime_only) { - return sema.failWithOwnedErrorMsg(block, msg: { - const msg = try sema.errMsg(src, "cannot store comptime-only type '{f}' at runtime", .{elem_ty.fmt(pt)}); - errdefer msg.destroy(sema.gpa); - try sema.errNote(ptr_src, msg, "operation is runtime due to this pointer", .{}); - break :msg msg; - }); - } + // We're performing the store at runtime, so the pointee type must not be comptime-only. + if (comptime_only) return sema.failWithOwnedErrorMsg(block, msg: { + const msg = try sema.errMsg(src, "cannot store comptime-only type '{f}' at runtime", .{elem_ty.fmt(pt)}); + errdefer msg.destroy(sema.gpa); + try sema.errNote(ptr_src, msg, "operation is runtime due to this pointer", .{}); + break :msg msg; + }); try sema.requireRuntimeBlock(block, src, runtime_src); @@ -29556,7 +29534,10 @@ fn coerceEnumToUnion( return sema.failWithOwnedErrorMsg(block, msg); } - if (union_ty.unionHasAllZeroBitFieldTypes(zcu)) { + for (union_obj.field_types.get(ip)) |field_ty_ip| { + if (Type.fromInterned(field_ty_ip).classify(zcu) != .one_possible_value) break; + } else { + // All fields are OPV, so the coercion is okay. if (try union_ty.onePossibleValue(pt)) |opv| { // 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. return .fromValue(opv); @@ -29566,6 +29547,8 @@ fn coerceEnumToUnion( } } + // The coercion is invalid because one or more fields is not OPV. + const msg = msg: { const msg = try sema.errMsg( inst_src, @@ -30186,12 +30169,18 @@ fn analyzeLoad( .pointer => ptr_ty.childType(zcu), else => return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{ptr_ty.fmt(pt)}), }; - if (elem_ty.zigTypeTag(zcu) == .@"opaque") { - return sema.fail(block, ptr_src, "cannot load opaque type '{f}'", .{elem_ty.fmt(pt)}); - } try sema.ensureLayoutResolved(elem_ty, src, .ptr_access); - if (try elem_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); + + const comptime_only = switch (elem_ty.classify(zcu)) { + .no_possible_value => switch (elem_ty.zigTypeTag(zcu)) { + .@"opaque" => return sema.fail(block, src, "cannot load opaque type '{f}'", .{elem_ty.fmt(pt)}), + else => return sema.fail(block, src, "cannot load uninstantiable type '{f}'", .{elem_ty.fmt(pt)}), + }, + .one_possible_value => return .fromValue((try elem_ty.onePossibleValue(pt)).?), + .runtime => false, + .partially_comptime, .fully_comptime => true, + }; if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| { @@ -30199,7 +30188,7 @@ fn analyzeLoad( } } - if (elem_ty.comptimeOnly(zcu)) return sema.failWithOwnedErrorMsg(block, msg: { + if (comptime_only) return sema.failWithOwnedErrorMsg(block, msg: { const msg = try sema.errMsg(src, "cannot load comptime-only type '{f}'", .{elem_ty.fmt(pt)}); errdefer msg.destroy(zcu.gpa); try sema.errNote(ptr_src, msg, "pointer of type '{f}' is runtime-known", .{ptr_ty.fmt(pt)}); diff --git a/src/Sema/arith.zig b/src/Sema/arith.zig index 161b6e1ce03ad4ffd9ee8372f49fb39a8a279207..024fc5da62cfb75b87d2f822b3450e8a5f431241 100644 --- a/src/Sema/arith.zig +++ b/src/Sema/arith.zig @@ -20,6 +20,9 @@ pub fn incrementDefinedInt( const zcu = pt.zcu; assert(prev_val.typeOf(zcu).toIntern() == ty.toIntern()); assert(!prev_val.isUndef(zcu)); + if (ty.intInfo(zcu).bits == 0) { + return .{ .overflow = true, .val = try comptimeIntAdd(sema, prev_val, .one_comptime_int) }; + } const res = try intAdd(sema, prev_val, try pt.intValue(ty, 1), ty); return .{ .overflow = res.overflow, .val = res.val }; } diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig index 8009838a8837025a3895e90207dd95cc922559a1..032f299531509224da563a7347ecd4c2459d8fd3 100644 --- a/src/Sema/type_resolution.zig +++ b/src/Sema/type_resolution.zig @@ -33,6 +33,7 @@ pub const LayoutResolveReason = enum { align_check, bit_ptr_child, @"export", + @"extern", builtin_type, /// Written after string: "while resolving type 'T' " @@ -58,6 +59,7 @@ pub const LayoutResolveReason = enum { .align_check => "for alignment check here", .bit_ptr_child => "for bit size check here", .@"export" => "for export here", + .@"extern" => "for extern declaration here", .builtin_type => "from 'std.builtin'", // zig fmt: on }; @@ -198,7 +200,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { const name = struct_obj.field_names.get(ip)[field_index]; if (ip.addFieldName(struct_obj.field_names, struct_obj.field_name_map, name)) |prev_field_index| { return sema.failWithOwnedErrorMsg(&block, msg: { - const src = block.nodeOffset(.zero); + const src = block.builtinCallArgSrc(.zero, 2); const msg = try sema.errMsg(src, "duplicate struct field '{f}' at index '{d}", .{ name.fmt(ip), field_index }); errdefer msg.destroy(gpa); try sema.errNote(src, msg, "previous field at index '{d}'", .{prev_field_index}); @@ -494,20 +496,22 @@ fn resolvePackedStructLayout( // Finally, either validate or infer the backing int type. const backing_int_ty: Type = if (explicit_backing_int_ty) |backing_ty| ty: { - // We only need to validate the type. - if (backing_ty.zigTypeTag(zcu) != .int) return sema.failWithOwnedErrorMsg(block, msg: { - const src = struct_ty.srcLoc(zcu); - const msg = try sema.errMsg(src, "expected backing integer type, found '{f}'", .{backing_ty.fmt(pt)}); - errdefer msg.destroy(gpa); - try sema.errNote(src, msg, "backing integer '{f}' has bit width '{d}'", .{ backing_ty.fmt(pt), backing_ty.bitSize(zcu) }); - try sema.errNote(src, msg, "struct fields have total bit width '{d}'", .{field_bits}); - break :msg msg; - }); + if (backing_ty.zigTypeTag(zcu) != .int) return sema.fail( + block, + block.src(.container_arg), + "expected backing integer type, found '{f}'", + .{backing_ty.fmt(pt)}, + ); if (field_bits != backing_ty.intInfo(zcu).bits) return sema.failWithOwnedErrorMsg(block, msg: { const src = struct_ty.srcLoc(zcu); const msg = try sema.errMsg(src, "backing integer bit width does not match total bit width of fields", .{}); errdefer msg.destroy(gpa); - try sema.errNote(src, msg, "backing integer '{f}' has bit width '{d}'", .{ backing_ty.fmt(pt), backing_ty.bitSize(zcu) }); + try sema.errNote( + block.src(.container_arg), + msg, + "backing integer '{f}' has bit width '{d}'", + .{ backing_ty.fmt(pt), backing_ty.bitSize(zcu) }, + ); try sema.errNote(src, msg, "struct fields have total bit width '{d}'", .{field_bits}); break :msg msg; }); @@ -1033,7 +1037,6 @@ fn resolvePackedUnionLayout( const msg = try sema.errMsg(field_ty_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)}); errdefer msg.destroy(gpa); try sema.explainWhyTypeIsUnpackable(msg, field_ty_src, reason); - try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; }); assert(!field_ty.comptimeOnly(zcu)); // packable types are not comptime-only @@ -1062,6 +1065,12 @@ fn resolvePackedUnionLayout( // Finally, either validate or infer the backing int type. const backing_int_ty: Type = if (explicit_backing_int_ty) |backing_ty| ty: { + if (backing_ty.zigTypeTag(zcu) != .int) return sema.fail( + block, + block.src(.container_arg), + "expected backing integer type, found '{f}'", + .{backing_ty.fmt(pt)}, + ); const backing_int_bits = backing_ty.intInfo(zcu).bits; for (union_obj.field_types.get(ip), 0..) |field_type_ip, field_idx| { const field_type: Type = .fromInterned(field_type_ip); @@ -1071,7 +1080,12 @@ fn resolvePackedUnionLayout( const msg = try sema.errMsg(field_ty_src, "field bit width does not match backing integer", .{}); errdefer msg.destroy(gpa); try sema.errNote(field_ty_src, msg, "field type '{f}' has bit width '{d}'", .{ field_type.fmt(pt), field_bits }); - try sema.errNote(field_ty_src, msg, "backing integer '{f}' has bit width '{d}'", .{ backing_ty.fmt(pt), backing_int_bits }); + try sema.errNote( + block.src(.container_arg), + msg, + "backing integer '{f}' has bit width '{d}'", + .{ backing_ty.fmt(pt), backing_int_bits }, + ); try sema.errNote(field_ty_src, msg, "all fields in a packed union must have the same bit width", .{}); break :msg msg; }); @@ -1157,7 +1171,7 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void { const name = enum_obj.field_names.get(ip)[field_index]; if (ip.addFieldName(enum_obj.field_names, enum_obj.field_name_map, name)) |prev_field_index| { return sema.failWithOwnedErrorMsg(&block, msg: { - const src = block.nodeOffset(.zero); + const src = block.builtinCallArgSrc(.zero, 2); const msg = try sema.errMsg(src, "duplicate union field '{f}' at index '{d}", .{ name.fmt(ip), field_index }); errdefer msg.destroy(gpa); 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 { const name = enum_obj.field_names.get(ip)[field_index]; if (ip.addFieldName(enum_obj.field_names, enum_obj.field_name_map, name)) |prev_field_index| { return sema.failWithOwnedErrorMsg(&block, msg: { - const src = block.nodeOffset(.zero); - const msg = try sema.errMsg(src, "duplicate enum field '{f}' at index '{d}", .{ name.fmt(ip), field_index }); + const src = block.builtinCallArgSrc(.zero, 2); + const msg = try sema.errMsg(src, "duplicate enum field '{f}' at index '{d}'", .{ name.fmt(ip), field_index }); errdefer msg.destroy(gpa); try sema.errNote(src, msg, "previous field at index '{d}'", .{prev_field_index}); break :msg msg; diff --git a/src/Type.zig b/src/Type.zig index 4aca4ed834a968cebfb940e7e912809e75dbc5f1..ea92d6befdc5202a8dd21ad01d5f5ac66fb3af9d 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -2985,12 +2985,21 @@ pub fn containerTypeName(ty: Type, ip: *const InternPool) InternPool.NullTermina }; } +pub fn destructurable(ty: Type, zcu: *const Zcu) bool { + return switch (ty.zigTypeTag(zcu)) { + .array, .vector => true, + .@"struct" => ty.isTuple(zcu), + else => false, + }; +} + pub const UnpackableReason = union(enum) { comptime_only, pointer, enum_inferred_int_tag: Type, non_packed_struct: Type, non_packed_union: Type, + slice, other, }; @@ -3027,7 +3036,10 @@ pub fn unpackable(ty: Type, zcu: *const Zcu) ?UnpackableReason { else .other, - .pointer => .pointer, + .pointer => switch (ty.ptrSize(zcu)) { + .slice => .slice, + .one, .many, .c => .pointer, + }, .@"enum" => switch (zcu.intern_pool.loadEnumType(ty.toIntern()).int_tag_mode) { .explicit => null, diff --git a/src/Value.zig b/src/Value.zig index 6a474c282133e10e15cfdd423b309df986bbf034..4cd7995b712a0c05b9e98960bc5198523bc21099 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -2014,7 +2014,11 @@ pub fn pointerDerivation(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread, op }, .field => |field| base: { const base_ptr = Value.fromInterned(field.base); - const base_ptr_ty = base_ptr.typeOf(zcu); + const base_ptr_ty = try pt.ptrType(info: { + var info = base_ptr.typeOf(zcu).ptrInfo(zcu); + info.flags.size = .one; + break :info info; + }); const parent_step = try arena.create(PointerDeriveStep); parent_step.* = try pointerDerivation(base_ptr, arena, pt, opt_sema); break :base .{ .field_ptr = .{ @@ -2155,13 +2159,17 @@ pub fn pointerDerivation(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread, op const start_off = cur_ty.structFieldOffset(field_idx, zcu); const end_off = start_off + field_ty.abiSize(zcu); if (cur_offset >= start_off and cur_offset + need_bytes <= end_off) { - const old_ptr_ty = try cur_derive.ptrType(pt); + const base_ptr_ty = try pt.ptrType(info: { + var info = (try cur_derive.ptrType(pt)).ptrInfo(zcu); + info.flags.size = .one; + break :info info; + }); const parent = try arena.create(PointerDeriveStep); parent.* = cur_derive; cur_derive = .{ .field_ptr = .{ .parent = parent, .field_idx = @intCast(field_idx), - .result_ptr_ty = try old_ptr_ty.fieldPtrType(@intCast(field_idx), pt), + .result_ptr_ty = try base_ptr_ty.fieldPtrType(@intCast(field_idx), pt), } }; cur_offset -= start_off; break; diff --git a/src/Zcu.zig b/src/Zcu.zig index eb4b8bdb05be4006f163fe2e48ff5746537a8905..78144bac16a817a931a23e5d1ba346f7aee374af 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -2028,9 +2028,15 @@ pub const SrcLoc = struct { const tree = try src_loc.file_scope.getTree(zcu); const node = src_loc.base_node; var buf: [2]Ast.Node.Index = undefined; - const container_decl = tree.fullContainerDecl(&buf, node) orelse return tree.nodeToSpan(node); - const arg_node = container_decl.ast.arg.unwrap() orelse return tree.nodeToSpan(node); - return tree.nodeToSpan(arg_node); + if (tree.fullContainerDecl(&buf, node)) |container_decl| { + const arg_node = container_decl.ast.arg.unwrap() orelse return tree.nodeToSpan(node); + return tree.nodeToSpan(arg_node); + } else if (tree.builtinCallParams(&buf, node)) |args| { + // Builtin calls (`@Enum` etc) should use the first argument. + return tree.nodeToSpan(if (args.len > 0) args[0] else node); + } else { + return tree.nodeToSpan(node); + } }, .container_field_name, .container_field_value, @@ -2040,8 +2046,38 @@ pub const SrcLoc = struct { const tree = try src_loc.file_scope.getTree(zcu); const node = src_loc.base_node; var buf: [2]Ast.Node.Index = undefined; - const container_decl = tree.fullContainerDecl(&buf, node) orelse + const container_decl = tree.fullContainerDecl(&buf, node) orelse { + // This could be a reification builtin. These are the args we care about: + // * `@Enum(_, _, names, values)` + // * `@Struct(_, _, names, types, values_and_aligns)` + // * `@Union(_, _, names, types, aligns)` + if (tree.builtinCallParams(&buf, node)) |args| { + const builtin_name = tree.tokenSlice(tree.firstToken(node)); + const arg_index: ?u3 = if (std.mem.eql(u8, builtin_name, "@Enum")) switch (src_loc.lazy) { + .container_field_name => 2, + .container_field_value => 3, + .container_field_type => null, + .container_field_align => null, + else => unreachable, + } else if (std.mem.eql(u8, builtin_name, "@Struct")) switch (src_loc.lazy) { + .container_field_name => 2, + .container_field_value => 4, + .container_field_type => 3, + .container_field_align => 4, + else => unreachable, + } else if (std.mem.eql(u8, builtin_name, "@Union")) switch (src_loc.lazy) { + .container_field_name => 2, + .container_field_value => 4, + .container_field_type => 3, + .container_field_align => null, + else => unreachable, + } else null; + if (arg_index) |i| { + if (args.len >= i) return tree.nodeToSpan(args[i]); + } + } return tree.nodeToSpan(node); + }; var cur_field_idx: usize = 0; for (container_decl.ast.members) |member_node| { diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 9fde840232d2ec4d598ef192a6379bb86138af5b..6a7054246eae094e485909243e340bd6865bc5cf 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -2176,6 +2176,9 @@ fn analyzeNavType( return .{ .type_changed = true }; } +/// If `func_index` is not a runtime function (e.g. it has a comptime-only parameter type) then it +/// is still valid to call this function and use its `func_body` unit in general---analysis of the +/// runtime function body will simply fail. pub fn ensureFuncBodyUpToDate( pt: Zcu.PerThread, func_index: InternPool.Index, @@ -2278,29 +2281,6 @@ fn analyzeFuncBody( const func = zcu.funcInfo(func_index); const anal_unit = AnalUnit.wrap(.{ .func = func_index }); - // Make sure that this function is still owned by the same `Nav`. Otherwise, analyzing - // it would be a waste of time in the best case, and could cause codegen to give bogus - // results in the worst case. - - if (func.generic_owner == .none) { - // Among another things, this ensures that the function's `zir_body_inst` is correct. - try pt.ensureNavValUpToDate(func.owner_nav, reason); - if (ip.getNav(func.owner_nav).status.fully_resolved.val != func_index) { - // This function is no longer referenced! There's no point in re-analyzing it. - // Just mark a transitive failure and move on. - return error.AnalysisFail; - } - } else { - const go_nav = zcu.funcInfo(func.generic_owner).owner_nav; - // Among another things, this ensures that the function's `zir_body_inst` is correct. - try pt.ensureNavValUpToDate(go_nav, reason); - if (ip.getNav(go_nav).status.fully_resolved.val != func.generic_owner) { - // The generic owner is no longer referenced, so this function is also unreferenced. - // There's no point in re-analyzing it. Just mark a transitive failure and move on. - return error.AnalysisFail; - } - } - // We'll want to remember what the IES used to be before the update for // dependency invalidation purposes. const old_resolved_ies = if (func.analysisUnordered(ip).inferred_error_set) @@ -3263,29 +3243,25 @@ fn analyzeFuncBodyInner( const anal_unit = AnalUnit.wrap(.{ .func = func_index }); const func = zcu.funcInfo(func_index); - const inst_info = func.zir_body_inst.resolveFull(ip) orelse return error.AnalysisFail; - const file = zcu.fileByIndex(inst_info.file); + + // This is the `Nav` corresponding to the `declaration` instruction which the function or its generic owner originates from. + const decl_analysis = if (func.generic_owner == .none) + ip.getNav(func.owner_nav).analysis.? + else + ip.getNav(zcu.funcInfo(func.generic_owner).owner_nav).analysis.?; + + const file = zcu.fileByIndex(decl_analysis.zir_index.resolveFile(ip)); const zir = file.zir.?; try zcu.analysis_in_progress.putNoClobber(gpa, anal_unit, reason); defer assert(zcu.analysis_in_progress.swapRemove(anal_unit)); - if (func.analysisUnordered(ip).inferred_error_set) { - func.setResolvedErrorSet(ip, io, .none); - } - if (zcu.comp.time_report) |*tr| { if (func.generic_owner != .none) { tr.stats.n_generic_instances += 1; } } - // This is the `Nau` corresponding to the `declaration` instruction which the function or its generic owner originates from. - const decl_nav = ip.getNav(if (func.generic_owner == .none) - func.owner_nav - else - zcu.funcInfo(func.generic_owner).owner_nav); - const func_nav = ip.getNav(func.owner_nav); var analysis_arena = std.heap.ArenaAllocator.init(gpa); @@ -3319,9 +3295,30 @@ fn analyzeFuncBodyInner( // Every runtime function has a dependency on the source of the Decl it originates from. // It also depends on the value of its owner Decl. - try sema.declareDependency(.{ .src_hash = decl_nav.analysis.?.zir_index }); + try sema.declareDependency(.{ .src_hash = decl_analysis.zir_index }); try sema.declareDependency(.{ .nav_val = func.owner_nav }); + // Make sure that the declaration `Nav` still refers to this function (or its generic owner). + // This will not be the case if the incremental update has changed a function type or turned a + // `fn` decl into some other declaration. In that case, we must not run analysis: this function + // will not be referenced this update, and trying to generate it could be problematic since we + // assume the owner NAV actually, um, owns us. + // + // If we *are* still owned by the right NAV, this analysis updates `zir_body_inst` if necessary. + + if (func.generic_owner == .none) { + try pt.ensureNavValUpToDate(func.owner_nav, reason); + if (ip.getNav(func.owner_nav).status.fully_resolved.val != func_index) { + return error.AnalysisFail; + } + } else { + const go_nav = zcu.funcInfo(func.generic_owner).owner_nav; + try pt.ensureNavValUpToDate(go_nav, reason); + if (ip.getNav(go_nav).status.fully_resolved.val != func.generic_owner) { + return error.AnalysisFail; + } + } + if (func.analysisUnordered(ip).inferred_error_set) { const ies = try analysis_arena.allocator().create(Sema.InferredErrorSet); ies.* = .{ .func = func_index }; @@ -3339,11 +3336,11 @@ fn analyzeFuncBodyInner( var inner_block: Sema.Block = .{ .parent = null, .sema = &sema, - .namespace = decl_nav.analysis.?.namespace, + .namespace = decl_analysis.namespace, .instructions = .empty, .inlining = null, .comptime_reason = null, - .src_base_inst = decl_nav.analysis.?.zir_index, + .src_base_inst = decl_analysis.zir_index, .type_name_ctx = func_nav.fqn, }; defer inner_block.instructions.deinit(gpa); @@ -3385,6 +3382,13 @@ fn analyzeFuncBodyInner( const param_ty: Type = .fromInterned(fn_ty_info.param_types.get(ip)[runtime_param_index]); runtime_param_index += 1; + if (param_ty.isGenericPoison()) { + // We're guaranteed to get a compile error on the `fnHasRuntimeBits` check after this + // loop (the generic poison means this is a generic function). But `continue` here to + // avoid an illegal call to `onePossibleValue` below. + continue; + } + const param_ty_src = inner_block.src(.{ .func_decl_param_ty = @intCast(zir_param_index) }); try sema.ensureLayoutResolved(param_ty, param_ty_src, .parameter); @@ -3406,6 +3410,23 @@ fn analyzeFuncBodyInner( try sema.ensureLayoutResolved(sema.fn_ret_ty, inner_block.src(.{ .node_offset_fn_type_ret_ty = .zero }), .return_type); + // The function type is now resolved, so we're ready to check whether it even makes sense to ask + // for it to be analyzed at runtime. + if (!fn_ty.fnHasRuntimeBits(zcu)) { + const description: []const u8 = switch (fn_ty_info.cc) { + .@"inline" => "inline", + else => "generic", + }; + // This error makes sense because the only reason this analysis would ever be requested is + // for IES resolution. + return sema.fail( + &inner_block, + inner_block.nodeOffset(.zero), + "cannot resolve inferred error set of {s} function type '{f}'", + .{ description, fn_ty.fmt(pt) }, + ); + } + const last_arg_index = inner_block.instructions.items.len; // Save the error trace as our first action in the function. diff --git a/src/codegen/c.zig b/src/codegen/c.zig index b31b0a40da9a5c9663bf7d3392bef966e6eed1a9..13e07dfcd05aa6a3f31b7de7ee49805f1225cecc 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -2112,7 +2112,7 @@ pub fn genTagNameFn( const loaded_enum = ip.loadEnumType(enum_ty.toIntern()); assert(loaded_enum.field_names.len > 0); if (Type.fromInterned(loaded_enum.int_tag_type).bitSize(zcu) > 64) { - @panic("TODO CBE: tagName for enum over 128 bits"); + @panic("TODO CBE: tagName for enum over 64 bits"); } try w.print("static {s} zig_tagName_{f}__{d}({s} tag) {{\n", .{ @@ -2130,10 +2130,10 @@ pub fn genTagNameFn( try w.writeAll(" switch (tag) {\n"); const field_values = loaded_enum.field_values.get(ip); for (loaded_enum.field_names.get(ip), 0..) |field_name, field_index| { - const field_int: u64 = int: { + const field_int: i65 = int: { if (field_values.len == 0) break :int field_index; const field_val: Value = .fromInterned(field_values[field_index]); - break :int field_val.toUnsignedInt(zcu); + break :int field_val.getUnsignedInt(zcu) orelse field_val.toSignedInt(zcu); }; try w.print(" case {d}: return ({s}){{name{d},{d}}};\n", .{ field_int, @@ -3278,7 +3278,10 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { const operand_ty = f.typeOf(ty_op.operand); const scalar_ty = operand_ty.scalarType(zcu); - if (f.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) return f.moveCValue(inst, inst_ty, operand); + // `intCastIsNoop` doesn't apply to vectors because every vector lowers to a different C struct. + if (inst_ty.zigTypeTag(zcu) != .vector and f.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) { + return f.moveCValue(inst, inst_ty, operand); + } const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); @@ -3491,6 +3494,8 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: const operand_ty = f.typeOf(bin_op.lhs); const scalar_ty = operand_ty.scalarType(zcu); + const ref_arg = lowersToBigInt(scalar_ty, zcu); + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); 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: try f.writeCValueMember(w, local, .{ .field = 0 }); try v.elem(f, w); try w.writeAll(", "); + if (ref_arg) try w.writeByte('&'); try f.writeCValue(w, lhs, .other); try v.elem(f, w); try w.writeAll(", "); + if (ref_arg) try w.writeByte('&'); try f.writeCValue(w, rhs, .other); if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w); try f.dg.renderBuiltinInfo(w, scalar_ty, info); diff --git a/src/codegen/c/type.zig b/src/codegen/c/type.zig index 64e63e4d6733980ea6cca735f53c82cb041e36d8..7a12a343f999179845a96febeaa15557605162e1 100644 --- a/src/codegen/c/type.zig +++ b/src/codegen/c/type.zig @@ -898,13 +898,23 @@ pub const CType = union(enum) { try w.writeAll("fn_"); // intentional double underscore to start for (func_type.param_types.get(ip)) |param_ty_ip| { const param_ty: Type = .fromInterned(param_ty_ip); - try w.print("_P{f}", .{fmtZigType(param_ty, zcu)}); + if (param_ty.isGenericPoison()) { + try w.writeAll("_Pgeneric"); + } else { + try w.print("_P{f}", .{fmtZigType(param_ty, zcu)}); + } } if (func_type.is_var_args) { try w.writeAll("_VA"); } const ret_ty: Type = .fromInterned(func_type.return_type); - try w.print("_R{f}", .{fmtZigType(ret_ty, zcu)}); + if (ret_ty.isGenericPoison()) { + try w.writeAll("_Rgeneric"); + } else if (ret_ty.zigTypeTag(zcu) == .error_union and ret_ty.errorUnionPayload(zcu).isGenericPoison()) { + try w.writeAll("_Rgeneric_ies"); + } else { + try w.print("_R{f}", .{fmtZigType(ret_ty, zcu)}); + } }, .vector => try w.print("vec_{d}_{f}", .{ diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 009e472d06f4229c067d4e96f0dee78bc0f22aa3..938706a42b82cdaf8639cd58738bd0fc3ad613a7 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3436,9 +3436,9 @@ pub const Object = struct { } if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) { - const stack_trace_ty = zcu.builtin_decl_values.get(.StackTrace); - const ptr_ty = try pt.ptrType(.{ .child = stack_trace_ty }); - try llvm_params.append(o.gpa, try o.lowerType(pt, ptr_ty)); + // First parameter is a pointer to `std.builtin.StackTrace`. + const llvm_ptr_ty = try o.builder.ptrType(toLlvmAddressSpace(.generic, target)); + try llvm_params.append(o.gpa, llvm_ptr_ty); } var it = iterateParamTypes(o, pt, fn_info); @@ -6719,16 +6719,11 @@ pub const FuncGen = struct { const zcu = pt.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ptr_ty = self.typeOf(bin_op.lhs); - const elem_ty = ptr_ty.childType(zcu); + const elem_ty = ptr_ty.indexableElem(zcu); const llvm_elem_ty = try o.lowerType(pt, elem_ty); const base_ptr = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); - // TODO: when we go fully opaque pointers in LLVM 16 we can remove this branch - const ptr = try self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, if (ptr_ty.isSinglePointer(zcu)) - // If this is a single-item pointer to an array, we need another index in the GEP. - &.{ try o.builder.intValue(try o.lowerType(pt, Type.usize), 0), rhs } - else - &.{rhs}, ""); + const ptr = try self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{rhs}, ""); if (isByRef(elem_ty, zcu)) { self.maybeMarkAllowZeroAccess(ptr_ty.ptrInfo(zcu)); const ptr_align = (ptr_ty.ptrAlignment(zcu).min(elem_ty.abiAlignment(zcu))).toLlvm(); @@ -6808,11 +6803,6 @@ pub const FuncGen = struct { const truncated_int = try self.wip.cast(.trunc, shifted_value, same_size_int, ""); return self.wip.cast(.bitcast, truncated_int, elem_llvm_ty, ""); - } else if (field_ty.isPtrAtRuntime(zcu)) { - const same_size_int = try o.builder.intType(@intCast(field_ty.bitSize(zcu))); - const truncated_int = - try self.wip.cast(.trunc, shifted_value, same_size_int, ""); - return self.wip.cast(.inttoptr, truncated_int, elem_llvm_ty, ""); } return self.wip.cast(.trunc, shifted_value, elem_llvm_ty, ""); }, @@ -6830,11 +6820,6 @@ pub const FuncGen = struct { const truncated_int = try self.wip.cast(.trunc, containing_int, same_size_int, ""); return self.wip.cast(.bitcast, truncated_int, elem_llvm_ty, ""); - } else if (field_ty.isPtrAtRuntime(zcu)) { - const same_size_int = try o.builder.intType(@intCast(field_ty.bitSize(zcu))); - const truncated_int = - try self.wip.cast(.trunc, containing_int, same_size_int, ""); - return self.wip.cast(.inttoptr, truncated_int, elem_llvm_ty, ""); } return self.wip.cast(.trunc, containing_int, elem_llvm_ty, ""); }, @@ -10110,7 +10095,7 @@ pub const FuncGen = struct { const ip = &zcu.intern_pool; const enum_type = ip.loadEnumType(enum_ty.toIntern()); - // TODO: detect when the type changes and re-emit this function. + // TODO: detect when the type changes (`updateContainerType` will be called) and re-emit this function const gop = try o.named_enum_map.getOrPut(o.gpa, enum_ty.toIntern()); if (gop.found_existing) return gop.value_ptr.*; errdefer assert(o.named_enum_map.remove(enum_ty.toIntern())); @@ -10728,10 +10713,7 @@ pub const FuncGen = struct { const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]); const non_int_val = try self.resolveInst(extra.init); const small_int_ty = try o.builder.intType(@intCast(field_ty.bitSize(zcu))); - const small_int_val = if (field_ty.isPtrAtRuntime(zcu)) - try self.wip.cast(.ptrtoint, non_int_val, small_int_ty, "") - else - try self.wip.cast(.bitcast, non_int_val, small_int_ty, ""); + const small_int_val = try self.wip.cast(.bitcast, non_int_val, small_int_ty, ""); return self.wip.conv(.unsigned, small_int_val, int_llvm_ty, ""); } diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index d09012fe948ba1a70b1b93fb99a8966abf89c8bc..97fb0294eb617c509e965995587ee6049a661941 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -2252,6 +2252,12 @@ pub const WipNav = struct { .generic_decl_const, .generic_decl_func, => true, + + // This comes from a decl which was previously generated as an incomplete value + // (I think that must mean either a function or an extern which previously had + // incomplete types). + .undefined_comptime_value => false, + else => |t| std.debug.panic("bad decl abbrev code: {t}", .{t}), }; if (parent_type.getCaptures(zcu).len == 0) { diff --git a/src/print_value.zig b/src/print_value.zig index 46fbe63a6b12c2d755efffb62c2ef98a590af966..626a11e1b335a197b855af6051e03adf760fba99 100644 --- a/src/print_value.zig +++ b/src/print_value.zig @@ -113,7 +113,7 @@ pub fn print( if (slice.len == .zero_usize) { return writer.writeAll("&.{}"); } - try print(.fromInterned(slice.ptr), writer, level - 1, pt, opt_sema); + try print(.fromInterned(slice.ptr), writer, level, pt, opt_sema); } else { const print_contents = switch (ip.getBackingAddrTag(slice.ptr).?) { .field, .arr_elem, .eu_payload, .opt_payload => unreachable, @@ -170,6 +170,9 @@ pub fn print( } }, .bitpack => |bitpack| { + if (level == 0) { + return writer.writeAll(".{ ... }"); + } const ty: Type = .fromInterned(bitpack.ty); switch (ty.zigTypeTag(zcu)) { .@"struct" => { @@ -464,18 +467,30 @@ pub fn printPtrDerivation( .uav_ptr => |uav| { const ty = Value.fromInterned(uav.val).typeOf(zcu); try writer.print("@as({f}, ", .{ty.fmt(pt)}); - try print(Value.fromInterned(uav.val), writer, x.level - 1, pt, x.opt_sema); + if (x.level == 0) { + try writer.writeAll("..."); + } else { + try print(Value.fromInterned(uav.val), writer, x.level - 1, pt, x.opt_sema); + } try writer.writeByte(')'); }, .comptime_alloc_ptr => |info| { try writer.print("@as({f}, ", .{info.val.typeOf(zcu).fmt(pt)}); - try print(info.val, writer, x.level - 1, pt, x.opt_sema); + if (x.level == 0) { + try writer.writeAll("..."); + } else { + try print(info.val, writer, x.level - 1, pt, x.opt_sema); + } try writer.writeByte(')'); }, .comptime_field_ptr => |val| { const ty = val.typeOf(zcu); try writer.print("@as({f}, ", .{ty.fmt(pt)}); - try print(val, writer, x.level - 1, pt, x.opt_sema); + if (x.level == 0) { + try writer.writeAll("..."); + } else { + try print(val, writer, x.level - 1, pt, x.opt_sema); + } try writer.writeByte(')'); }, else => unreachable, -- 2.54.0 From 6d997ebe47d91641e70971bf3c227df6cbae041a Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 1 Mar 2026 19:18:04 +0000 Subject: [PATCH 61/79] tests: get cases passing (and a few other bits) --- test/c_abi/main.zig | 4 +- .../compile_errors/@import_zon_bad_type.zig | 8 +- .../compile_errors/@import_zon_opt_in_err.zig | 20 +- .../@import_zon_opt_in_err_struct.zig | 8 +- .../@intFromPtr_with_bad_type.zig | 9 - ..._ABI_compatible_type_or_has_align_attr.zig | 12 - .../compile_errors/aggregate_too_large.zig | 16 +- .../cases/compile_errors/alignOf_bad_type.zig | 2 +- test/cases/compile_errors/align_zero.zig | 8 +- .../assign_inline_fn_to_non-comptime_var.zig | 10 - .../compile_errors/bit_ptr_non_packed.zig | 8 +- ...of_packed_struct_checks_backing_int_ty.zig | 4 +- .../compile_errors/c_pointer_to_void.zig | 9 - .../call_runtime_known_inline_fn_ptr.zig | 11 + .../compile_errors/coerce_int_to_float.zig | 12 +- .../comptime_var_referenced_by_type.zig | 2 +- .../compile_errors/direct_struct_loop.zig | 2 +- ...edding_opaque_type_in_struct_and_union.zig | 6 +- .../enum_field_value_references_enum.zig | 12 +- ..._value_references_nonexistent_circular.zig | 2 +- .../enum_value_already_taken.zig | 4 +- .../compile_errors/error_set_membership.zig | 3 +- ...ig => fn_body_in_struct_runtime_known.zig} | 0 .../compile_errors/function_ptr_alignment.zig | 2 +- ...non-extern_non-packed_struct_parameter.zig | 2 +- ..._non-extern_non-packed_union_parameter.zig | 2 +- ...generic_function_returning_opaque_type.zig | 2 +- .../indexing_an_array_of_size_zero.zig | 2 +- ..._array_of_size_zero_with_runtime_index.zig | 2 +- .../compile_errors/indirect_struct_loop.zig | 6 +- .../compile_errors/initialize_empty_union.zig | 36 +- ...an_invalid_struct_that_contains_itself.zig | 2 +- ..._an_invalid_union_that_contains_itself.zig | 2 +- .../invalid_dependency_on_struct_size.zig | 22 +- ...invalid_optional_type_in_extern_struct.zig | 4 +- .../invalid_pointer_arithmetic.zig | 8 +- .../invalid_type_in_builtin_extern.zig | 14 +- ...of_things_that_require_const_variables.zig | 41 +- ...xhaustive_enum_marker_assigned_a_value.zig | 11 - .../non-exhaustive_enum_missing_tag_type.zig | 10 + ...-exhaustive_enum_specifies_every_value.zig | 2 +- ..._loop_on_a_type_that_requires_comptime.zig | 2 +- .../non_constant_expression_in_array_size.zig | 2 +- .../compile_errors/noreturn_struct_field.zig | 10 - .../old_fn_ptr_in_extern_context.zig | 6 - .../overflow_in_enum_value_allocation.zig | 2 +- .../packed_struct_backing_int_wrong.zig | 8 +- ...truct_with_fields_of_not_allowed_types.zig | 27 +- .../packed_union_fields_mismatch.zig | 10 +- .../packed_union_given_enum_tag_type.zig | 18 - ...union_with_fields_of_not_allowed_types.zig | 15 +- .../compile_errors/pointer_in_bitpack.zig | 22 + .../reify_enum_with_duplicate_field.zig | 7 +- .../reify_enum_with_duplicate_tag_value.zig | 7 +- ...austive_enum_with_non-integer_tag_type.zig | 2 +- .../reify_type_for_tagged_packed_union.zig | 11 - ...for_tagged_union_with_extra_enum_field.zig | 5 +- ..._for_tagged_union_with_no_union_fields.zig | 6 +- ...reify_type_for_union_with_opaque_field.zig | 8 +- ...eify_type_with_invalid_field_alignment.zig | 8 +- ...solve_inferred_error_set_of_generic_fn.zig | 3 +- ...time_@ptrFromInt_to_comptime_only_type.zig | 5 +- ...time_index_into_comptime_only_many_ptr.zig | 6 +- ...runtime_index_into_comptime_type_slice.zig | 3 +- .../runtime_indexing_comptime_array.zig | 6 +- .../runtime_operation_in_comptime_scope.zig | 8 +- ...f_referential_struct_requires_comptime.zig | 1 - ...lf_referential_union_requires_comptime.zig | 1 - test/cases/compile_errors/sizeOf_bad_type.zig | 2 + .../sizeof_alignof_empty_union.zig | 24 +- .../slice_used_as_extern_fn_param.zig | 2 +- ...pecify_enum_tag_type_that_is_too_small.zig | 18 +- ..._comptime_only_type_to_runtime_pointer.zig | 11 +- ...epends_on_itself_via_non_initial_field.zig | 4 +- ...t_depends_on_itself_via_optional_field.zig | 5 +- .../struct_depends_on_pointer_alignment.zig | 11 - .../compile_errors/too_big_packed_struct.zig | 2 +- .../top_level_decl_dependency_loop.zig | 7 +- .../unable_to_evaluate_comptime_expr.zig | 19 - .../compile_errors/undef_arith_is_illegal.zig | 3016 ++++++++--------- .../undef_arith_returns_undef.zig | 3000 ++++++++-------- .../undef_shifts_are_illegal.zig | 1174 +++---- .../union_auto-enum_value_already_taken.zig | 4 +- .../union_depends_on_pointer_alignment.zig | 11 - .../union_enum_field_missing.zig | 5 +- ...on_field_ordered_differently_than_enum.zig | 7 +- .../union_noreturn_field_initialized.zig | 12 +- .../union_with_specified_enum_omits_field.zig | 5 +- ...ith_too_small_explicit_signed_tag_type.zig | 3 +- ...h_too_small_explicit_unsigned_tag_type.zig | 3 +- .../untagged_union_integer_conversion.zig | 2 +- .../variadic_arg_validation.zig | 2 +- .../zero_width_nonexhaustive_enum.zig | 15 +- test/incremental/change_enum_tag_type | 2 +- 94 files changed, 3919 insertions(+), 3998 deletions(-) delete mode 100644 test/cases/compile_errors/@intFromPtr_with_bad_type.zig delete mode 100644 test/cases/compile_errors/C_pointer_pointing_to_non_C_ABI_compatible_type_or_has_align_attr.zig delete mode 100644 test/cases/compile_errors/assign_inline_fn_to_non-comptime_var.zig delete mode 100644 test/cases/compile_errors/c_pointer_to_void.zig create mode 100644 test/cases/compile_errors/call_runtime_known_inline_fn_ptr.zig rename test/cases/compile_errors/{AstGen_comptime_known_struct_is_resolved_before_error.zig => fn_body_in_struct_runtime_known.zig} (100%) create mode 100644 test/cases/compile_errors/non-exhaustive_enum_missing_tag_type.zig delete mode 100644 test/cases/compile_errors/noreturn_struct_field.zig delete mode 100644 test/cases/compile_errors/packed_union_given_enum_tag_type.zig create mode 100644 test/cases/compile_errors/pointer_in_bitpack.zig delete mode 100644 test/cases/compile_errors/reify_type_for_tagged_packed_union.zig delete mode 100644 test/cases/compile_errors/struct_depends_on_pointer_alignment.zig delete mode 100644 test/cases/compile_errors/union_depends_on_pointer_alignment.zig diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index 5d02e5e87dda46805e24dd64bb3e741dff161e60..218c75189e11ac0f9369ea8de3cf865766a8b7fe 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -718,7 +718,7 @@ export fn zig_med_struct_ints(s: MedStructInts) void { expect(s.z == 3) catch @panic("test failure"); } -const SmallPackedStruct = packed struct { +const SmallPackedStruct = packed struct(u8) { a: u2, b: u2, c: u2, @@ -744,7 +744,7 @@ test "C ABI small packed struct" { try expect(s2.d == 3); } -const BigPackedStruct = packed struct { +const BigPackedStruct = packed struct(u128) { a: u64, b: u64, }; diff --git a/test/cases/compile_errors/@import_zon_bad_type.zig b/test/cases/compile_errors/@import_zon_bad_type.zig index 9fe3c887213b9f8972ee829c90f6c0e69fa6b53d..bcb1de5d4249cbdb50ba3ae7de4acb8395954602 100644 --- a/test/cases/compile_errors/@import_zon_bad_type.zig +++ b/test/cases/compile_errors/@import_zon_bad_type.zig @@ -116,13 +116,13 @@ export fn testMutablePointer() void { // tmp.zig:85:26: note: ZON does not allow nested optionals // tmp.zig:90:29: error: type '*i32' is not available in ZON // tmp.zig:90:29: note: ZON does not allow mutable pointers -// neg_inf.zon:1:1: error: expected type '@EnumLiteral()' -// tmp.zig:37:38: note: imported here // neg_inf.zon:1:1: error: expected type '?u8' // tmp.zig:57:28: note: imported here +// neg_inf.zon:1:1: error: expected type '@EnumLiteral()' +// tmp.zig:37:38: note: imported here // neg_inf.zon:1:1: error: expected type 'tmp.E' // tmp.zig:63:26: note: imported here -// neg_inf.zon:1:1: error: expected type 'tmp.U' -// tmp.zig:69:26: note: imported here // neg_inf.zon:1:1: error: expected type 'tmp.EU' // tmp.zig:75:27: note: imported here +// neg_inf.zon:1:1: error: expected type 'tmp.U' +// tmp.zig:69:26: note: imported here diff --git a/test/cases/compile_errors/@import_zon_opt_in_err.zig b/test/cases/compile_errors/@import_zon_opt_in_err.zig index 29cf412eab32989359bd57ed259598865064337a..f975a3fa1e25d53facf9f2366dcfac1004387a95 100644 --- a/test/cases/compile_errors/@import_zon_opt_in_err.zig +++ b/test/cases/compile_errors/@import_zon_opt_in_err.zig @@ -58,25 +58,25 @@ export fn testVector() void { // error // imports=zon/vec2.zon // -// vec2.zon:1:2: error: expected type '?f32' -// tmp.zig:2:29: note: imported here // vec2.zon:1:2: error: expected type '*const ?f32' // tmp.zig:7:36: note: imported here // vec2.zon:1:2: error: expected type '?*const f32' // tmp.zig:12:36: note: imported here +// vec2.zon:1:2: error: expected type '?@EnumLiteral()' +// tmp.zig:33:39: note: imported here +// vec2.zon:1:2: error: expected type '?@Vector(3, f32)' +// tmp.zig:54:41: note: imported here +// vec2.zon:1:2: error: expected type '?[1]u8' +// tmp.zig:38:31: note: imported here +// vec2.zon:1:2: error: expected type '?[]const u8' +// tmp.zig:49:36: note: imported here // vec2.zon:1:2: error: expected type '?bool' // tmp.zig:17:30: note: imported here +// vec2.zon:1:2: error: expected type '?f32' +// tmp.zig:2:29: note: imported here // vec2.zon:1:2: error: expected type '?i32' // tmp.zig:22:29: note: imported here // vec2.zon:1:2: error: expected type '?tmp.Enum' // tmp.zig:28:30: note: imported here -// vec2.zon:1:2: error: expected type '?@EnumLiteral()' -// tmp.zig:33:39: note: imported here -// vec2.zon:1:2: error: expected type '?[1]u8' -// tmp.zig:38:31: note: imported here // vec2.zon:1:2: error: expected type '?tmp.Union' // tmp.zig:44:31: note: imported here -// vec2.zon:1:2: error: expected type '?[]const u8' -// tmp.zig:49:36: note: imported here -// vec2.zon:1:2: error: expected type '?@Vector(3, f32)' -// tmp.zig:54:41: note: imported here diff --git a/test/cases/compile_errors/@import_zon_opt_in_err_struct.zig b/test/cases/compile_errors/@import_zon_opt_in_err_struct.zig index a284fd7c6dd6e2eac930fe48f74ad3fcff3d364a..a931f5a8cd305ae33bcc9e68ca296c74406134a7 100644 --- a/test/cases/compile_errors/@import_zon_opt_in_err_struct.zig +++ b/test/cases/compile_errors/@import_zon_opt_in_err_struct.zig @@ -13,7 +13,7 @@ export fn testTuple() void { // error // imports=zon/nan.zon // -//nan.zon:1:1: error: expected type '?tmp.Struct' -//tmp.zig:3:32: note: imported here -//nan.zon:1:1: error: expected type '?struct { bool }' -//tmp.zig:9:31: note: imported here +// nan.zon:1:1: error: expected type '?struct { bool }' +// tmp.zig:9:31: note: imported here +// nan.zon:1:1: error: expected type '?tmp.Struct' +// tmp.zig:3:32: note: imported here diff --git a/test/cases/compile_errors/@intFromPtr_with_bad_type.zig b/test/cases/compile_errors/@intFromPtr_with_bad_type.zig deleted file mode 100644 index ec98c1bc14425d91c36a56735502cdefc5d0eba4..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/@intFromPtr_with_bad_type.zig +++ /dev/null @@ -1,9 +0,0 @@ -const x = 42; -const y = @intFromPtr(&x); -pub export fn entry() void { - _ = y; -} - -// error -// -// :2:23: error: comptime-only type 'comptime_int' has no pointer address diff --git a/test/cases/compile_errors/C_pointer_pointing_to_non_C_ABI_compatible_type_or_has_align_attr.zig b/test/cases/compile_errors/C_pointer_pointing_to_non_C_ABI_compatible_type_or_has_align_attr.zig deleted file mode 100644 index a578ebd84b758fb18e4f688982f917dc5639a0b1..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/C_pointer_pointing_to_non_C_ABI_compatible_type_or_has_align_attr.zig +++ /dev/null @@ -1,12 +0,0 @@ -const Foo = struct { a: u32 }; -export fn a() void { - const T = [*c]Foo; - const t: T = undefined; - _ = t; -} - -// error -// -// :3:19: error: C pointers cannot point to non-C-ABI-compatible type 'tmp.Foo' -// :3:19: note: only extern structs and ABI sized packed structs are extern compatible -// :1:13: note: struct declared here diff --git a/test/cases/compile_errors/aggregate_too_large.zig b/test/cases/compile_errors/aggregate_too_large.zig index 4a4daeda939c6711fd1dd31ece3ad396f838815c..ecab43d01109669047fc167d811df43456df0105 100644 --- a/test/cases/compile_errors/aggregate_too_large.zig +++ b/test/cases/compile_errors/aggregate_too_large.zig @@ -12,16 +12,14 @@ const U = union { b: [1 << 32]u8, }; -const V = union { - a: u32, - b: T, -}; - comptime { - _ = S; - _ = T; - _ = U; - _ = V; + _ = @as(S, undefined); +} +comptime { + _ = @as(T, undefined); +} +comptime { + _ = @as(U, undefined); } // error diff --git a/test/cases/compile_errors/alignOf_bad_type.zig b/test/cases/compile_errors/alignOf_bad_type.zig index 93dcfa3b94922a74c2edb4720cd0232ddabbb795..4689fad821bd31e66f136101d1d1612c153ec9d0 100644 --- a/test/cases/compile_errors/alignOf_bad_type.zig +++ b/test/cases/compile_errors/alignOf_bad_type.zig @@ -9,5 +9,5 @@ export fn entry1() usize { // error // // :2:21: error: no align available for uninstantiable type 'noreturn' -// :6:21: error: no align available for uninstantiable type 'alignOf_bad_type.S' +// :6:21: error: no align available for uninstantiable type 'tmp.S' // :4:11: note: struct declared here diff --git a/test/cases/compile_errors/align_zero.zig b/test/cases/compile_errors/align_zero.zig index 632d146dc5c44ce161c54a425c7755f8686ba3f2..7b68dee5e44e13cf94437d5c885f8831befa9f8f 100644 --- a/test/cases/compile_errors/align_zero.zig +++ b/test/cases/compile_errors/align_zero.zig @@ -30,11 +30,11 @@ export fn g() void { } export fn h() void { - _ = struct { field: i32 align(0) }; + _ = @as(struct { field: i32 align(0) }, undefined); } export fn i() void { - _ = union { field: i32 align(0) }; + _ = @as(union { field: i32 align(0) }, undefined); } export fn j() void { @@ -54,7 +54,7 @@ export fn k() void { // :20:30: error: alignment must be >= 1 // :25:16: error: alignment must be >= 1 // :29:17: error: alignment must be >= 1 -// :33:35: error: alignment must be >= 1 -// :37:34: error: alignment must be >= 1 +// :33:39: error: alignment must be >= 1 +// :37:38: error: alignment must be >= 1 // :41:51: error: alignment must be >= 1 // :45:25: error: alignment must be >= 1 diff --git a/test/cases/compile_errors/assign_inline_fn_to_non-comptime_var.zig b/test/cases/compile_errors/assign_inline_fn_to_non-comptime_var.zig deleted file mode 100644 index ee666a028b1c633f35ae87e3de37ae0ff5126048..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/assign_inline_fn_to_non-comptime_var.zig +++ /dev/null @@ -1,10 +0,0 @@ -export fn entry() void { - var a = &b; - _ = &a; -} -inline fn b() void {} - -// error -// -// :2:9: error: variable of type '*const fn () callconv(.@"inline") void' must be const or comptime -// :2:9: note: function has inline calling convention diff --git a/test/cases/compile_errors/bit_ptr_non_packed.zig b/test/cases/compile_errors/bit_ptr_non_packed.zig index 2b8190836906e8f6975d135d7bdce0452de2c90c..706dc12b9963168cd79d4fc474c4e73fe129dbcd 100644 --- a/test/cases/compile_errors/bit_ptr_non_packed.zig +++ b/test/cases/compile_errors/bit_ptr_non_packed.zig @@ -16,7 +16,11 @@ export fn entry3() void { // error // // :3:23: error: bit-pointer cannot refer to value of type 'tmp.entry1.S' -// :3:23: note: only packed structs layout are allowed in packed types +// :3:23: note: non-packed structs do not have a bit-packed representation +// :2:22: note: struct declared here // :8:36: error: bit-pointer cannot refer to value of type 'tmp.entry2.S' -// :8:36: note: only packed structs layout are allowed in packed types +// :8:36: note: non-packed structs do not have a bit-packed representation +// :7:15: note: struct declared here // :13:23: error: bit-pointer cannot refer to value of type 'tmp.entry3.E' +// :12:15: note: integer tag type of enum is inferred +// :12:15: note: consider explicitly specifying the integer tag type diff --git a/test/cases/compile_errors/bitsize_of_packed_struct_checks_backing_int_ty.zig b/test/cases/compile_errors/bitsize_of_packed_struct_checks_backing_int_ty.zig index 9ee45b63565e0df5f6ceaa981c21f39578964ae4..f833ee08fe3056eb66d7d88feef4537a0a8a540e 100644 --- a/test/cases/compile_errors/bitsize_of_packed_struct_checks_backing_int_ty.zig +++ b/test/cases/compile_errors/bitsize_of_packed_struct_checks_backing_int_ty.zig @@ -8,4 +8,6 @@ pub export fn entry() void { // error // -// :1:27: error: backing integer type 'u32' has bit size 32 but the struct fields have a total bit size of 1 +// :1:20: error: backing integer bit width does not match total bit width of fields +// :1:27: note: backing integer 'u32' has bit width '32' +// :1:20: note: struct fields have total bit width '1' diff --git a/test/cases/compile_errors/c_pointer_to_void.zig b/test/cases/compile_errors/c_pointer_to_void.zig deleted file mode 100644 index 4a532a22ae1f1e914bd669294bb90513f65e6dc5..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/c_pointer_to_void.zig +++ /dev/null @@ -1,9 +0,0 @@ -export fn entry() void { - const a: [*c]void = undefined; - _ = a; -} - -// error -// -// :2:18: error: C pointers cannot point to non-C-ABI-compatible type 'void' -// :2:18: note: 'void' is a zero bit type; for C 'void' use 'anyopaque' diff --git a/test/cases/compile_errors/call_runtime_known_inline_fn_ptr.zig b/test/cases/compile_errors/call_runtime_known_inline_fn_ptr.zig new file mode 100644 index 0000000000000000000000000000000000000000..635b169df01fdc2498c537160e47bdceea6e39cd --- /dev/null +++ b/test/cases/compile_errors/call_runtime_known_inline_fn_ptr.zig @@ -0,0 +1,11 @@ +export fn entry() void { + var a = &b; + a = a; + a(); +} +inline fn b() void {} + +// error +// +// :4:5: error: unable to resolve comptime value +// :4:5: note: function being called inline must be comptime-known diff --git a/test/cases/compile_errors/coerce_int_to_float.zig b/test/cases/compile_errors/coerce_int_to_float.zig index bd167b36ad2b7a1947e23a1f422a7a7882b4220f..d1bf6eb2be077f38245412ee237a9c84f8291fbe 100644 --- a/test/cases/compile_errors/coerce_int_to_float.zig +++ b/test/cases/compile_errors/coerce_int_to_float.zig @@ -40,13 +40,13 @@ export fn entry() void { // error // -// :6:20: error: expected type 'f16', found 'u12' +// :6:20: error: expected type 'f128', found 'i115' +// :6:20: error: expected type 'f128', found 'u114' // :6:20: error: expected type 'f16', found 'i13' -// :6:20: error: expected type 'f32', found 'u25' +// :6:20: error: expected type 'f16', found 'u12' // :6:20: error: expected type 'f32', found 'i26' -// :6:20: error: expected type 'f64', found 'u54' +// :6:20: error: expected type 'f32', found 'u25' // :6:20: error: expected type 'f64', found 'i55' -// :6:20: error: expected type 'f80', found 'u65' +// :6:20: error: expected type 'f64', found 'u54' // :6:20: error: expected type 'f80', found 'i66' -// :6:20: error: expected type 'f128', found 'u114' -// :6:20: error: expected type 'f128', found 'i115' +// :6:20: error: expected type 'f80', found 'u65' diff --git a/test/cases/compile_errors/comptime_var_referenced_by_type.zig b/test/cases/compile_errors/comptime_var_referenced_by_type.zig index 1b476d9cdef1af9269ebe8ef4619dbf6a67e6bc9..62af2aed48b7446d40ede9c59864e50e1fe2f309 100644 --- a/test/cases/compile_errors/comptime_var_referenced_by_type.zig +++ b/test/cases/compile_errors/comptime_var_referenced_by_type.zig @@ -21,6 +21,6 @@ comptime { // error // // :7:16: error: captured value contains reference to comptime var -// :7:16: note: 'wrapper' points to '@as(*const tmp.Wrapper, @ptrCast(&v0)).*', where +// :7:16: note: 'wrapper' points to 'v0', where // :16:5: note: 'v0.ptr' points to comptime var declared here // :17:29: note: called at comptime here diff --git a/test/cases/compile_errors/direct_struct_loop.zig b/test/cases/compile_errors/direct_struct_loop.zig index 4abd10da714e359a4b7561775df063c6e42bd1e6..e50867d36a943c4a7a7f121fa3ed86e5661ca49e 100644 --- a/test/cases/compile_errors/direct_struct_loop.zig +++ b/test/cases/compile_errors/direct_struct_loop.zig @@ -7,4 +7,4 @@ export fn entry() usize { // error // -// :1:11: error: struct 'tmp.A' depends on itself +// :2:8: error: type 'tmp.A' depends on itself for field declared here diff --git a/test/cases/compile_errors/directly_embedding_opaque_type_in_struct_and_union.zig b/test/cases/compile_errors/directly_embedding_opaque_type_in_struct_and_union.zig index 7c5085daf03627737f765638539c5c775bdfa732..ff3edd5fc96c339bbb84d1a981d4fead2e68a851 100644 --- a/test/cases/compile_errors/directly_embedding_opaque_type_in_struct_and_union.zig +++ b/test/cases/compile_errors/directly_embedding_opaque_type_in_struct_and_union.zig @@ -26,9 +26,11 @@ export fn d() void { // error // -// :3:8: error: opaque types have unknown size and therefore cannot be directly embedded in structs +// :3:8: error: cannot directly embed opaque type 'tmp.O' in struct +// :3:8: note: opaque types have unknown size // :1:11: note: opaque declared here -// :7:10: error: opaque types have unknown size and therefore cannot be directly embedded in unions +// :7:10: error: cannot directly embed opaque type 'tmp.O' in union +// :7:10: note: opaque types have unknown size // :1:11: note: opaque declared here // :18:24: error: cannot cast to opaque type 'tmp.O' // :1:11: note: opaque declared here diff --git a/test/cases/compile_errors/enum_field_value_references_enum.zig b/test/cases/compile_errors/enum_field_value_references_enum.zig index 29150487089ec1e4f45f50080dec181d8dd72141..ba07e80bf8e058d273f9beb151059f8914aa118a 100644 --- a/test/cases/compile_errors/enum_field_value_references_enum.zig +++ b/test/cases/compile_errors/enum_field_value_references_enum.zig @@ -1,15 +1,11 @@ pub const Foo = enum(c_int) { - A = Foo.B, - C = D, - - pub const B = 0; + a = 10, + b = @intFromEnum(Foo.a) - 1, }; export fn entry() void { - const s: Foo = Foo.E; - _ = s; + _ = @as(Foo, .a); } -const D = 1; // error // -// :1:5: error: dependency loop detected +// :3:25: error: type 'tmp.Foo' depends on itself for field usage here diff --git a/test/cases/compile_errors/enum_field_value_references_nonexistent_circular.zig b/test/cases/compile_errors/enum_field_value_references_nonexistent_circular.zig index d658876cf63ab6c11a1bbf6862f3e723681ec148..69b6111bbf98285ea7067260a4099e8cf00d4828 100644 --- a/test/cases/compile_errors/enum_field_value_references_nonexistent_circular.zig +++ b/test/cases/compile_errors/enum_field_value_references_nonexistent_circular.zig @@ -10,4 +10,4 @@ const D = 1; // error // -// :1:5: error: dependency loop detected +// :2:12: error: type 'tmp.Foo' depends on itself for field usage here diff --git a/test/cases/compile_errors/enum_value_already_taken.zig b/test/cases/compile_errors/enum_value_already_taken.zig index 30e332b3be2cf931b2353f61efa9b57bfc997a4e..b83217ce788d97a32bbc6cdb3f7d58dc0f92d98e 100644 --- a/test/cases/compile_errors/enum_value_already_taken.zig +++ b/test/cases/compile_errors/enum_value_already_taken.zig @@ -12,5 +12,5 @@ export fn entry() void { // error // -// :6:9: error: enum tag value 60 already taken -// :4:9: note: other occurrence here +// :6:9: error: enum tag value '60' for field 'E' already taken +// :4:9: note: previous occurrence in field 'C' diff --git a/test/cases/compile_errors/error_set_membership.zig b/test/cases/compile_errors/error_set_membership.zig index 96c50a8ee6dc806a118431db096498af97e9547b..5caf26d46921cba6a2bbde4abc87da90ca6a4d50 100644 --- a/test/cases/compile_errors/error_set_membership.zig +++ b/test/cases/compile_errors/error_set_membership.zig @@ -26,5 +26,6 @@ pub fn main() Error!void { // error // target=x86_64-linux // -// :23:29: error: expected type 'error{InvalidCharacter}', found '@typeInfo(@typeInfo(@TypeOf(tmp.fooey)).@"fn".return_type.?).error_union.error_set' +// :23:29: error: expected type 'error{InvalidCharacter}!void', found '@typeInfo(@typeInfo(@TypeOf(tmp.fooey)).@"fn".return_type.?).error_union.error_set' // :23:29: note: 'error.InvalidDirection' not a member of destination error set +// :22:20: note: function return type declared here diff --git a/test/cases/compile_errors/AstGen_comptime_known_struct_is_resolved_before_error.zig b/test/cases/compile_errors/fn_body_in_struct_runtime_known.zig similarity index 100% rename from test/cases/compile_errors/AstGen_comptime_known_struct_is_resolved_before_error.zig rename to test/cases/compile_errors/fn_body_in_struct_runtime_known.zig diff --git a/test/cases/compile_errors/function_ptr_alignment.zig b/test/cases/compile_errors/function_ptr_alignment.zig index 66e80a95a6deaee73187dd3a4970685923d50a43..6396a08009a978d784698025616e9167eab397cf 100644 --- a/test/cases/compile_errors/function_ptr_alignment.zig +++ b/test/cases/compile_errors/function_ptr_alignment.zig @@ -11,5 +11,5 @@ comptime { // error // target=x86_64-linux // -// :8:41: error: expected type '*align(2) const fn () void', found '*const fn () void' +// :8:41: error: expected type '*align(2) const fn () void', found '*align(1) const fn () void' // :8:41: note: pointer alignment '1' cannot cast into pointer alignment '2' diff --git a/test/cases/compile_errors/function_with_non-extern_non-packed_struct_parameter.zig b/test/cases/compile_errors/function_with_non-extern_non-packed_struct_parameter.zig index bb41a2ddb981ef7eaa99bc5b45ae0f6cb8c85a9e..d3e995734fe20899d04201fc0ca33bbd148c9a64 100644 --- a/test/cases/compile_errors/function_with_non-extern_non-packed_struct_parameter.zig +++ b/test/cases/compile_errors/function_with_non-extern_non-packed_struct_parameter.zig @@ -11,5 +11,5 @@ export fn entry(foo: Foo) void { // target=x86_64-linux // // :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'x86_64_sysv' -// :6:17: note: only extern structs and ABI sized packed structs are extern compatible +// :6:17: note: struct with automatic layout has no guaranteed in-memory representation // :1:13: note: struct declared here diff --git a/test/cases/compile_errors/function_with_non-extern_non-packed_union_parameter.zig b/test/cases/compile_errors/function_with_non-extern_non-packed_union_parameter.zig index 220dbd146d714e4697264b627476f3cb77cbf543..e02e072aa05cf25c432637ee602eda0f975feec0 100644 --- a/test/cases/compile_errors/function_with_non-extern_non-packed_union_parameter.zig +++ b/test/cases/compile_errors/function_with_non-extern_non-packed_union_parameter.zig @@ -11,5 +11,5 @@ export fn entry(foo: Foo) void { // target=x86_64-linux // // :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'x86_64_sysv' -// :6:17: note: only extern unions and ABI sized packed unions are extern compatible +// :6:17: note: union with automatic layout has no guaranteed in-memory representation // :1:13: note: union declared here diff --git a/test/cases/compile_errors/generic_function_returning_opaque_type.zig b/test/cases/compile_errors/generic_function_returning_opaque_type.zig index 78ffde8961669985cf82192137bab6048197d6db..b3f4b757e1c43c7b9af8692452b283acde889992 100644 --- a/test/cases/compile_errors/generic_function_returning_opaque_type.zig +++ b/test/cases/compile_errors/generic_function_returning_opaque_type.zig @@ -11,6 +11,6 @@ export fn bar() void { // error // +// :1:30: error: opaque return type 'anyopaque' not allowed // :1:30: error: opaque return type 'tmp.MyOpaque' not allowed // :4:18: note: opaque declared here -// :1:30: error: opaque return type 'anyopaque' not allowed diff --git a/test/cases/compile_errors/indexing_an_array_of_size_zero.zig b/test/cases/compile_errors/indexing_an_array_of_size_zero.zig index 356425d8152c2d9847eeceaaa6f50fd9264fe246..92ded154c130014da0ab0206c44c260c63a448ab 100644 --- a/test/cases/compile_errors/indexing_an_array_of_size_zero.zig +++ b/test/cases/compile_errors/indexing_an_array_of_size_zero.zig @@ -6,4 +6,4 @@ export fn foo() void { // error // -// :3:27: error: indexing into empty array is not allowed +// :3:27: error: cannot index into empty array diff --git a/test/cases/compile_errors/indexing_an_array_of_size_zero_with_runtime_index.zig b/test/cases/compile_errors/indexing_an_array_of_size_zero_with_runtime_index.zig index 29d522aad96879fbaf79b175baf2408c76b50da2..b06b7bed554c13518c9a277557477f87ba630333 100644 --- a/test/cases/compile_errors/indexing_an_array_of_size_zero_with_runtime_index.zig +++ b/test/cases/compile_errors/indexing_an_array_of_size_zero_with_runtime_index.zig @@ -8,4 +8,4 @@ export fn foo() void { // error // -// :5:27: error: indexing into empty array is not allowed +// :5:27: error: cannot index into empty array diff --git a/test/cases/compile_errors/indirect_struct_loop.zig b/test/cases/compile_errors/indirect_struct_loop.zig index 7975ecddf5716171d803cc2549b7a59e4b864521..ac85a64a0c64ae17a78621f6b22bc8efd3c25c97 100644 --- a/test/cases/compile_errors/indirect_struct_loop.zig +++ b/test/cases/compile_errors/indirect_struct_loop.zig @@ -13,4 +13,8 @@ export fn entry() usize { // error // -// :1:11: error: struct 'tmp.A' depends on itself +// error: dependency loop with length 3 +// :2:8: note: type 'tmp.A' depends on type 'tmp.B' for field declared here +// :5:8: note: type 'tmp.B' depends on type 'tmp.C' for field declared here +// :8:8: note: type 'tmp.C' depends on type 'tmp.A' for field declared here +// note: eliminate any one of these dependencies to break the loop diff --git a/test/cases/compile_errors/initialize_empty_union.zig b/test/cases/compile_errors/initialize_empty_union.zig index c84633da268c5f4e885ffa33a993cb0d3eeeecf5..2847446b2516a1eb4f968a8bb31b24abc7bd132d 100644 --- a/test/cases/compile_errors/initialize_empty_union.zig +++ b/test/cases/compile_errors/initialize_empty_union.zig @@ -49,33 +49,33 @@ export fn deref5(ptr: *const U5) void { // error // -// :13:17: error: expected type 'initialize_empty_union.U0', found '@TypeOf(undefined)' -// :13:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U0' +// :13:17: error: expected type 'tmp.U0', found '@TypeOf(undefined)' +// :13:17: note: cannot coerce to uninstantiable type 'tmp.U0' // :5:12: note: union declared here -// :16:17: error: expected type 'initialize_empty_union.U1', found '@TypeOf(undefined)' -// :16:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U1' +// :16:17: error: expected type 'tmp.U1', found '@TypeOf(undefined)' +// :16:17: note: cannot coerce to uninstantiable type 'tmp.U1' // :6:12: note: union declared here -// :19:17: error: expected type 'initialize_empty_union.U2', found '@TypeOf(undefined)' -// :19:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U2' +// :19:17: error: expected type 'tmp.U2', found '@TypeOf(undefined)' +// :19:17: note: cannot coerce to uninstantiable type 'tmp.U2' // :7:12: note: union declared here -// :22:17: error: expected type 'initialize_empty_union.U3', found '@TypeOf(undefined)' -// :22:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U3' +// :22:17: error: expected type 'tmp.U3', found '@TypeOf(undefined)' +// :22:17: note: cannot coerce to uninstantiable type 'tmp.U3' // :8:12: note: union declared here -// :25:17: error: expected type 'initialize_empty_union.U4', found '@TypeOf(undefined)' -// :25:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U4' +// :25:17: error: expected type 'tmp.U4', found '@TypeOf(undefined)' +// :25:17: note: cannot coerce to uninstantiable type 'tmp.U4' // :9:12: note: union declared here -// :28:17: error: expected type 'initialize_empty_union.U5', found '@TypeOf(undefined)' -// :28:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U5' +// :28:17: error: expected type 'tmp.U5', found '@TypeOf(undefined)' +// :28:17: note: cannot coerce to uninstantiable type 'tmp.U5' // :10:12: note: union declared here -// :32:12: error: cannot load uninstantiable type 'initialize_empty_union.U0' +// :32:12: error: cannot load uninstantiable type 'tmp.U0' // :5:12: note: union declared here -// :35:12: error: cannot load uninstantiable type 'initialize_empty_union.U1' +// :35:12: error: cannot load uninstantiable type 'tmp.U1' // :6:12: note: union declared here -// :38:12: error: cannot load uninstantiable type 'initialize_empty_union.U2' +// :38:12: error: cannot load uninstantiable type 'tmp.U2' // :7:12: note: union declared here -// :41:12: error: cannot load uninstantiable type 'initialize_empty_union.U3' +// :41:12: error: cannot load uninstantiable type 'tmp.U3' // :8:12: note: union declared here -// :44:12: error: cannot load uninstantiable type 'initialize_empty_union.U4' +// :44:12: error: cannot load uninstantiable type 'tmp.U4' // :9:12: note: union declared here -// :47:12: error: cannot load uninstantiable type 'initialize_empty_union.U5' +// :47:12: error: cannot load uninstantiable type 'tmp.U5' // :10:12: note: union declared here diff --git a/test/cases/compile_errors/instantiating_an_undefined_value_for_an_invalid_struct_that_contains_itself.zig b/test/cases/compile_errors/instantiating_an_undefined_value_for_an_invalid_struct_that_contains_itself.zig index 5507dbc34e3d8243162cab38e7b9606d3856daa1..2e602ee6a6dd7d8bba15f763709350c3530bd325 100644 --- a/test/cases/compile_errors/instantiating_an_undefined_value_for_an_invalid_struct_that_contains_itself.zig +++ b/test/cases/compile_errors/instantiating_an_undefined_value_for_an_invalid_struct_that_contains_itself.zig @@ -10,4 +10,4 @@ export fn entry() usize { // error // -// :1:13: error: struct 'tmp.Foo' depends on itself +// :2:8: error: type 'tmp.Foo' depends on itself for field declared here diff --git a/test/cases/compile_errors/instantiating_an_undefined_value_for_an_invalid_union_that_contains_itself.zig b/test/cases/compile_errors/instantiating_an_undefined_value_for_an_invalid_union_that_contains_itself.zig index 9886c42bae362bbcdab8c490dfae04c0f0d4d86a..c503c0b3da6b991a661023701dfef7e09a05580a 100644 --- a/test/cases/compile_errors/instantiating_an_undefined_value_for_an_invalid_union_that_contains_itself.zig +++ b/test/cases/compile_errors/instantiating_an_undefined_value_for_an_invalid_union_that_contains_itself.zig @@ -10,4 +10,4 @@ export fn entry() usize { // error // -// :1:13: error: union 'tmp.Foo' depends on itself +// :2:8: error: type 'tmp.Foo' depends on itself for field declared here diff --git a/test/cases/compile_errors/invalid_dependency_on_struct_size.zig b/test/cases/compile_errors/invalid_dependency_on_struct_size.zig index 14cd363a1426188858d321d616f299e2e3607dc8..39fc37ab3e5520d1224cc83b08e9f27afb09d738 100644 --- a/test/cases/compile_errors/invalid_dependency_on_struct_size.zig +++ b/test/cases/compile_errors/invalid_dependency_on_struct_size.zig @@ -1,16 +1,18 @@ +const S = struct { + const Foo = struct { + y: Bar, + }; + const Bar = struct { + y: if (@sizeOf(Foo) == 0) u64 else void, + }; +}; comptime { - const S = struct { - const Foo = struct { - y: Bar, - }; - const Bar = struct { - y: if (@sizeOf(Foo) == 0) u64 else void, - }; - }; - _ = @sizeOf(S.Foo) + 1; } // error // -// :6:21: error: struct layout depends on it having runtime bits +// error: dependency loop with length 2 +// :3:12: note: type 'tmp.S.Foo' depends on type 'tmp.S.Bar' for field declared here +// :6:24: note: type 'tmp.S.Bar' depends on type 'tmp.S.Foo' for size query here +// note: eliminate any one of these dependencies to break the loop diff --git a/test/cases/compile_errors/invalid_optional_type_in_extern_struct.zig b/test/cases/compile_errors/invalid_optional_type_in_extern_struct.zig index 68d4603a4af51511417c417fe42be863c343e0f0..dfb497660015537a2d05a877430f776df61331a6 100644 --- a/test/cases/compile_errors/invalid_optional_type_in_extern_struct.zig +++ b/test/cases/compile_errors/invalid_optional_type_in_extern_struct.zig @@ -2,10 +2,10 @@ const stroo = extern struct { moo: ?[*c]u8, }; export fn testf(fluff: *stroo) void { - _ = fluff; + _ = fluff.*; } // error // // :2:10: error: extern structs cannot contain fields of type '?[*c]u8' -// :2:10: note: only pointer like optionals are extern compatible +// :2:10: note: non-pointer optionals have no guaranteed in-memory representation diff --git a/test/cases/compile_errors/invalid_pointer_arithmetic.zig b/test/cases/compile_errors/invalid_pointer_arithmetic.zig index a571d5d4c2771a1931d7ca4eb29cdfb399caad06..e590087dffdba353d60d60c36247978100045687 100644 --- a/test/cases/compile_errors/invalid_pointer_arithmetic.zig +++ b/test/cases/compile_errors/invalid_pointer_arithmetic.zig @@ -26,11 +26,6 @@ comptime { _ = x - y; } -comptime { - const x: [*]u0 = @ptrFromInt(1); - _ = x + 1; -} - comptime { const x: *u0 = @ptrFromInt(1); const y: *u0 = @ptrFromInt(2); @@ -46,5 +41,4 @@ comptime { // :12:11: error: invalid operands to binary expression: 'pointer' and 'pointer' // :20:11: error: incompatible pointer arithmetic operands '[*]u8' and '[*]u16' // :26:11: error: incompatible pointer arithmetic operands '*u8' and '*u16' -// :31:11: error: pointer arithmetic requires element type 'u0' to have runtime bits -// :37:11: error: pointer arithmetic requires element type 'u0' to have runtime bits +// :32:11: error: pointer subtraction requires element type 'u0' to have runtime bits diff --git a/test/cases/compile_errors/invalid_type_in_builtin_extern.zig b/test/cases/compile_errors/invalid_type_in_builtin_extern.zig index 5528c9c7132f197b9e702a7029c50bd49166be9f..444ab528b337a85ec6b776c37e15b8c513d7f3ea 100644 --- a/test/cases/compile_errors/invalid_type_in_builtin_extern.zig +++ b/test/cases/compile_errors/invalid_type_in_builtin_extern.zig @@ -1,16 +1,22 @@ const x = @extern(*comptime_int, .{ .name = "foo" }); const y = @extern(*fn (u8) u8, .{ .name = "bar" }); -pub export fn entry() void { +const z = @extern(*fn (u8) callconv(.c) u8, .{ .name = "bar" }); +comptime { _ = x; } -pub export fn entry2() void { +comptime { _ = y; } +comptime { + _ = z; +} // error // // :1:19: error: extern symbol cannot have type '*comptime_int' -// :1:19: note: pointer to comptime-only type 'comptime_int' +// :1:19: note: pointer element type 'comptime_int' is not extern compatible // :2:19: error: extern symbol cannot have type '*fn (u8) u8' -// :2:19: note: pointer to extern function must be 'const' +// :2:19: note: pointer element type 'fn (u8) u8' is not extern compatible // :2:19: note: extern function must specify calling convention +// :3:19: error: extern symbol cannot have type '*fn (u8) callconv(.c) u8' +// :3:19: note: pointer to extern function must be 'const' diff --git a/test/cases/compile_errors/non-const_variables_of_things_that_require_const_variables.zig b/test/cases/compile_errors/non-const_variables_of_things_that_require_const_variables.zig index 373ac8e2d92f1bd5e18a14f324e374bfae90337c..66fb6c6cec77ea4423874ca288abba11737c3a67 100644 --- a/test/cases/compile_errors/non-const_variables_of_things_that_require_const_variables.zig +++ b/test/cases/compile_errors/non-const_variables_of_things_that_require_const_variables.zig @@ -1,49 +1,44 @@ -export fn entry1() void { - var m2 = &2; - _ = &m2; -} -export fn entry2() void { +export fn entry0() void { var a = undefined; _ = &a; } -export fn entry3() void { +export fn entry1() void { var b = 1; _ = &b; } -export fn entry4() void { +export fn entry2() void { var c = 1.0; _ = &c; } -export fn entry5() void { +export fn entry3() void { var d = null; _ = &d; } -export fn entry6(opaque_: *Opaque) void { +export fn entry4(opaque_: *Opaque) void { var e = opaque_.*; _ = &e; } -export fn entry7() void { +export fn entry5() void { var f = i32; _ = &f; } const Opaque = opaque {}; -export fn entry8() void { +export fn entry6() void { var e: Opaque = undefined; _ = &e; } // error // -// :2:9: error: variable of type '*const comptime_int' must be const or comptime -// :6:9: error: variable of type '@TypeOf(undefined)' must be const or comptime -// :10:9: error: variable of type 'comptime_int' must be const or comptime +// :2:9: error: variable of type '@TypeOf(undefined)' must be const or comptime +// :6:9: error: variable of type 'comptime_int' must be const or comptime +// :6:9: note: to modify this variable at runtime, it must be given an explicit fixed-size number type +// :10:9: error: variable of type 'comptime_float' must be const or comptime // :10:9: note: to modify this variable at runtime, it must be given an explicit fixed-size number type -// :14:9: error: variable of type 'comptime_float' must be const or comptime -// :14:9: note: to modify this variable at runtime, it must be given an explicit fixed-size number type -// :18:9: error: variable of type '@TypeOf(null)' must be const or comptime -// :22:20: error: cannot load opaque type 'tmp.Opaque' -// :29:16: note: opaque declared here -// :26:9: error: variable of type 'type' must be const or comptime -// :26:9: note: types are not available at runtime -// :31:12: error: non-extern variable with opaque type 'tmp.Opaque' -// :29:16: note: opaque declared here +// :14:9: error: variable of type '@TypeOf(null)' must be const or comptime +// :18:20: error: cannot load opaque type 'tmp.Opaque' +// :25:16: note: opaque declared here +// :22:9: error: variable of type 'type' must be const or comptime +// :22:9: note: types are not available at runtime +// :27:12: error: non-extern variable with opaque type 'tmp.Opaque' +// :25:16: note: opaque declared here diff --git a/test/cases/compile_errors/non-exhaustive_enum_marker_assigned_a_value.zig b/test/cases/compile_errors/non-exhaustive_enum_marker_assigned_a_value.zig index bd659f8e32a2808cdfe63c4d987443aac7925ee0..01b999e924a65cf53a064d375f4ca52ee2c8386b 100644 --- a/test/cases/compile_errors/non-exhaustive_enum_marker_assigned_a_value.zig +++ b/test/cases/compile_errors/non-exhaustive_enum_marker_assigned_a_value.zig @@ -3,18 +3,7 @@ const A = enum { b, _ = 1, }; -const B = enum { - a, - b, - _, -}; -comptime { - _ = A; - _ = B; -} // error // // :4:9: error: '_' is used to mark an enum as non-exhaustive and cannot be assigned a value -// :6:11: error: non-exhaustive enum missing integer tag type -// :9:5: note: marked non-exhaustive here diff --git a/test/cases/compile_errors/non-exhaustive_enum_missing_tag_type.zig b/test/cases/compile_errors/non-exhaustive_enum_missing_tag_type.zig new file mode 100644 index 0000000000000000000000000000000000000000..fa0b9d432dd65bf8203dd39cbadcad909b8024ed --- /dev/null +++ b/test/cases/compile_errors/non-exhaustive_enum_missing_tag_type.zig @@ -0,0 +1,10 @@ +const E = enum { + a, + b, + _, +}; + +// error +// +// :1:11: error: non-exhaustive enum missing integer tag type +// :4:5: note: marked non-exhaustive here diff --git a/test/cases/compile_errors/non-exhaustive_enum_specifies_every_value.zig b/test/cases/compile_errors/non-exhaustive_enum_specifies_every_value.zig index 8adaac649f2297ece6a93388a80c7e4e779800b7..6c4902ba5c2733d12efeed907309bbc0a1d15547 100644 --- a/test/cases/compile_errors/non-exhaustive_enum_specifies_every_value.zig +++ b/test/cases/compile_errors/non-exhaustive_enum_specifies_every_value.zig @@ -4,7 +4,7 @@ const C = enum(u1) { _, }; pub export fn entry() void { - _ = C; + _ = C.a; } // error diff --git a/test/cases/compile_errors/non-inline_for_loop_on_a_type_that_requires_comptime.zig b/test/cases/compile_errors/non-inline_for_loop_on_a_type_that_requires_comptime.zig index adb6583757e58518f1200100d504eebbcb9259b4..a895c263a0e2acd38c343166cd9afbb65e569ac5 100644 --- a/test/cases/compile_errors/non-inline_for_loop_on_a_type_that_requires_comptime.zig +++ b/test/cases/compile_errors/non-inline_for_loop_on_a_type_that_requires_comptime.zig @@ -11,6 +11,6 @@ export fn entry() void { // error // -// :7:10: error: values of type '[2]tmp.Foo' must be comptime-known, but index value is runtime-known +// :7:10: error: values of type 'tmp.Foo' must be comptime-known, but index value is runtime-known // :3:8: note: struct requires comptime because of this field // :3:8: note: types are not available at runtime diff --git a/test/cases/compile_errors/non_constant_expression_in_array_size.zig b/test/cases/compile_errors/non_constant_expression_in_array_size.zig index 0f64e1263b2e2475c8335c0a0ae333a987ce4ca0..6b344ba4a1d6a3abc7e7bc36d7fc895a5dc73d01 100644 --- a/test/cases/compile_errors/non_constant_expression_in_array_size.zig +++ b/test/cases/compile_errors/non_constant_expression_in_array_size.zig @@ -14,4 +14,4 @@ export fn entry() usize { // // :6:12: error: unable to resolve comptime value // :2:12: note: called at comptime from here -// :1:13: note: types must be comptime-known +// :2:8: note: struct field types must be comptime-known diff --git a/test/cases/compile_errors/noreturn_struct_field.zig b/test/cases/compile_errors/noreturn_struct_field.zig deleted file mode 100644 index 8a68496bdedc29169071432fa7af33410c1c33fa..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/noreturn_struct_field.zig +++ /dev/null @@ -1,10 +0,0 @@ -const S = struct { - s: noreturn, -}; -comptime { - _ = @typeInfo(S); -} - -// error -// -// :2:8: error: struct fields cannot be 'noreturn' diff --git a/test/cases/compile_errors/old_fn_ptr_in_extern_context.zig b/test/cases/compile_errors/old_fn_ptr_in_extern_context.zig index 701636e7636541cb7e54d1b50107ab83f6dd71c6..85ff0539804cdcb553dfe521aa6f908148ecdb82 100644 --- a/test/cases/compile_errors/old_fn_ptr_in_extern_context.zig +++ b/test/cases/compile_errors/old_fn_ptr_in_extern_context.zig @@ -4,15 +4,9 @@ const S = extern struct { comptime { _ = @sizeOf(S) == 1; } -comptime { - _ = [*c][4]fn () callconv(.c) void; -} // error // // :2:8: error: extern structs cannot contain fields of type 'fn () callconv(.c) void' // :2:8: note: type has no guaranteed in-memory representation // :2:8: note: use '*const ' to make a function pointer type -// :8:13: error: C pointers cannot point to non-C-ABI-compatible type '[4]fn () callconv(.c) void' -// :8:13: note: type has no guaranteed in-memory representation -// :8:13: note: use '*const ' to make a function pointer type diff --git a/test/cases/compile_errors/overflow_in_enum_value_allocation.zig b/test/cases/compile_errors/overflow_in_enum_value_allocation.zig index 35f3c193dfe343fdc387c972f7fb145af8f4190d..fdf2cf4efb9ca5f02199f071ffe9550b597ac45f 100644 --- a/test/cases/compile_errors/overflow_in_enum_value_allocation.zig +++ b/test/cases/compile_errors/overflow_in_enum_value_allocation.zig @@ -9,4 +9,4 @@ pub export fn entry() void { // error // -// :3:5: error: enumeration value '256' too large for type 'u8' +// :3:5: error: enum tag value '256' too large for type 'u8' diff --git a/test/cases/compile_errors/packed_struct_backing_int_wrong.zig b/test/cases/compile_errors/packed_struct_backing_int_wrong.zig index 25872cbf7e8c975e74cfb3760f8faa382024eedc..5fa4f258d53e2d92c861f312e97e8bee68f866ff 100644 --- a/test/cases/compile_errors/packed_struct_backing_int_wrong.zig +++ b/test/cases/compile_errors/packed_struct_backing_int_wrong.zig @@ -44,8 +44,12 @@ export fn entry7() void { // error // -// :2:31: error: backing integer type 'u32' has bit size 32 but the struct fields have a total bit size of 29 -// :9:31: error: backing integer type 'i31' has bit size 31 but the struct fields have a total bit size of 32 +// :2:24: error: backing integer bit width does not match total bit width of fields +// :2:31: note: backing integer 'u32' has bit width '32' +// :2:24: note: struct fields have total bit width '29' +// :9:24: error: backing integer bit width does not match total bit width of fields +// :9:31: note: backing integer 'i31' has bit width '31' +// :9:24: note: struct fields have total bit width '32' // :17:31: error: expected backing integer type, found 'void' // :23:31: error: expected backing integer type, found 'void' // :27:31: error: expected backing integer type, found 'noreturn' diff --git a/test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig b/test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig index 5f4482421d65b8144ace994483cf8342aa35006b..d7a5d355c9d26a565b179d3610255a55bafaaab7 100644 --- a/test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig +++ b/test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig @@ -85,29 +85,32 @@ export fn entry15() void { // error // // :3:12: error: packed structs cannot contain fields of type 'anyerror' -// :3:12: note: type has no guaranteed in-memory representation +// :3:12: note: type does not have a bit-packed representation // :8:12: error: packed structs cannot contain fields of type '[2]u24' -// :8:12: note: type has no guaranteed in-memory representation +// :8:12: note: type does not have a bit-packed representation // :13:20: error: packed structs cannot contain fields of type 'anyerror!u32' -// :13:20: note: type has no guaranteed in-memory representation +// :13:20: note: type does not have a bit-packed representation // :18:12: error: packed structs cannot contain fields of type 'tmp.S' -// :18:12: note: only packed structs layout are allowed in packed types +// :18:12: note: non-packed structs do not have a bit-packed representation // :56:11: note: struct declared here // :23:12: error: packed structs cannot contain fields of type 'tmp.U' -// :23:12: note: only packed unions layout are allowed in packed types +// :23:12: note: non-packed unions do not have a bit-packed representation // :59:18: note: union declared here // :28:12: error: packed structs cannot contain fields of type '?anyerror' -// :28:12: note: type has no guaranteed in-memory representation +// :28:12: note: type does not have a bit-packed representation // :38:12: error: packed structs cannot contain fields of type 'fn () void' -// :38:12: note: type has no guaranteed in-memory representation -// :38:12: note: use '*const ' to make a function pointer type +// :38:12: note: type does not have a bit-packed representation +// :43:12: error: packed structs cannot contain fields of type '*const fn () void' +// :43:12: note: pointers cannot be directly bitpacked +// :43:12: note: consider using 'usize' and '@intFromPtr' // :65:31: error: packed structs cannot contain fields of type '[]u8' -// :65:31: note: slices have no guaranteed in-memory representation +// :65:31: note: slices do not have a bit-packed representation // :70:12: error: packed structs cannot contain fields of type '*type' -// :70:12: note: comptime-only pointer has no guaranteed in-memory representation -// :70:12: note: types are not available at runtime +// :70:12: note: pointers cannot be directly bitpacked +// :70:12: note: consider using 'usize' and '@intFromPtr' // :76:12: error: packed structs cannot contain fields of type 'tmp.entry14.E' -// :74:15: note: enum declared here +// :74:15: note: integer tag type of enum is inferred +// :74:15: note: consider explicitly specifying the integer tag type // :81:12: error: packed structs cannot contain fields of type '*const u32' // :81:12: note: pointers cannot be directly bitpacked // :81:12: note: consider using 'usize' and '@intFromPtr' diff --git a/test/cases/compile_errors/packed_union_fields_mismatch.zig b/test/cases/compile_errors/packed_union_fields_mismatch.zig index 7f5ac456bfe246c5a69c9b00545d64749d27871f..1e815838a9b948b4fceb619a9ef78dc6c5feaafd 100644 --- a/test/cases/compile_errors/packed_union_fields_mismatch.zig +++ b/test/cases/compile_errors/packed_union_fields_mismatch.zig @@ -1,12 +1,14 @@ export fn entry1() void { - _ = packed union { + const U = packed union { a: u1, b: u2, }; + _ = @as(U, undefined); } // error // -// :2:16: error: packed union has fields with mismatching bit sizes -// :3:12: note: 1 bits here -// :4:12: note: 2 bits here +// :4:12: error: field bit width does not match earlier field +// :4:12: note: field type 'u2' has bit width '2' +// :3:12: note: other field type 'u1' has bit width '1' +// :4:12: note: all fields in a packed union must have the same bit width diff --git a/test/cases/compile_errors/packed_union_given_enum_tag_type.zig b/test/cases/compile_errors/packed_union_given_enum_tag_type.zig deleted file mode 100644 index f95c1739c0cd3dcd3cfc865ab20415c9b95fddf1..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/packed_union_given_enum_tag_type.zig +++ /dev/null @@ -1,18 +0,0 @@ -const Letter = enum { - A, - B, - C, -}; -const Payload = packed union(Letter) { - A: i32, - B: f64, - C: bool, -}; -export fn entry() void { - const a: Payload = .{ .A = 1234 }; - _ = a; -} - -// error -// -// :6:30: error: packed union does not support enum tag type diff --git a/test/cases/compile_errors/packed_union_with_fields_of_not_allowed_types.zig b/test/cases/compile_errors/packed_union_with_fields_of_not_allowed_types.zig index cfbdf4e90aeaab22aa6637066e68d1a1ce0348ac..d0e09742b5080e165af9fc105ff62fad177ff993 100644 --- a/test/cases/compile_errors/packed_union_with_fields_of_not_allowed_types.zig +++ b/test/cases/compile_errors/packed_union_with_fields_of_not_allowed_types.zig @@ -1,6 +1,7 @@ +const S = struct { a: u32 }; export fn entry0() void { _ = @sizeOf(packed union { - foo: struct { a: u32 }, + foo: S, bar: bool, }); } @@ -12,9 +13,9 @@ export fn entry1() void { // error // -// :3:14: error: packed unions cannot contain fields of type 'packed_union_with_fields_of_not_allowed_types.entry0__union_180__struct_182' -// :3:14: note: non-packed structs do not have a bit-packed representation -// :3:14: note: struct declared here -// :9:12: error: packed unions cannot contain fields of type '*const u32' -// :9:12: note: pointers cannot be directly bitpacked -// :9:12: note: consider using 'usize' and '@intFromPtr' +// :4:14: error: packed unions cannot contain fields of type 'tmp.S' +// :4:14: note: non-packed structs do not have a bit-packed representation +// :1:11: note: struct declared here +// :10:12: error: packed unions cannot contain fields of type '*const u32' +// :10:12: note: pointers cannot be directly bitpacked +// :10:12: note: consider using 'usize' and '@intFromPtr' diff --git a/test/cases/compile_errors/pointer_in_bitpack.zig b/test/cases/compile_errors/pointer_in_bitpack.zig new file mode 100644 index 0000000000000000000000000000000000000000..fa3d8130fa11ea0e44562266b39dc6bc9ce67df9 --- /dev/null +++ b/test/cases/compile_errors/pointer_in_bitpack.zig @@ -0,0 +1,22 @@ +const S = packed struct { + ptr: *u32, +}; +export fn foo() void { + _ = @as(S, undefined); +} + +const U = packed union { + ptr: *u32, +}; +export fn bar() void { + _ = @as(U, undefined); +} + +// error +// +// :2:10: error: packed structs cannot contain fields of type '*u32' +// :2:10: note: pointers cannot be directly bitpacked +// :2:10: note: consider using 'usize' and '@intFromPtr' +// :9:10: error: packed unions cannot contain fields of type '*u32' +// :9:10: note: pointers cannot be directly bitpacked +// :9:10: note: consider using 'usize' and '@intFromPtr' diff --git a/test/cases/compile_errors/reify_enum_with_duplicate_field.zig b/test/cases/compile_errors/reify_enum_with_duplicate_field.zig index 73df5e1a869a3fe6c8255945fc6e98f8d82e2a85..efa0e51dee32d9058fc2f1f73d46cb3aaa953b6f 100644 --- a/test/cases/compile_errors/reify_enum_with_duplicate_field.zig +++ b/test/cases/compile_errors/reify_enum_with_duplicate_field.zig @@ -1,8 +1,9 @@ export fn entry() void { - _ = @Enum(u32, .nonexhaustive, &.{ "A", "A" }, &.{ 0, 1 }); + const E = @Enum(u32, .nonexhaustive, &.{ "A", "A" }, &.{ 0, 1 }); + _ = @as(E, undefined); } // error // -// :2:36: error: duplicate enum field 'A' -// :2:36: note: other field here +// :2:42: error: duplicate enum field 'A' at index '1' +// :2:42: note: previous field at index '0' diff --git a/test/cases/compile_errors/reify_enum_with_duplicate_tag_value.zig b/test/cases/compile_errors/reify_enum_with_duplicate_tag_value.zig index 6343782ca7b2e53a9c0f1bfe2b5f3189b7cd5b0b..c60589f7e02075a59a82f0f02423312b5c709c88 100644 --- a/test/cases/compile_errors/reify_enum_with_duplicate_tag_value.zig +++ b/test/cases/compile_errors/reify_enum_with_duplicate_tag_value.zig @@ -1,8 +1,9 @@ export fn entry() void { - _ = @Enum(u32, .nonexhaustive, &.{ "A", "B" }, &.{ 10, 10 }); + const E = @Enum(u32, .nonexhaustive, &.{ "a", "b" }, &.{ 10, 10 }); + _ = E.a; } // error // -// :2:52: error: enum tag value 10 already taken -// :2:52: note: other enum tag value here +// :2:58: error: enum tag value '10' for field 'b' already taken +// :2:58: note: previous occurrence in field 'a' diff --git a/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig b/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig index d74e0b2b53104178bae00a1799d6013a76f6df28..8e684cba560d5af4f7189fc9d0d16ed554e0e5e4 100644 --- a/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig +++ b/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig @@ -5,4 +5,4 @@ export fn entry() void { // error // -// :1:19: error: tag type must be an integer type +// :1:19: error: expected integer tag type, found 'bool' diff --git a/test/cases/compile_errors/reify_type_for_tagged_packed_union.zig b/test/cases/compile_errors/reify_type_for_tagged_packed_union.zig deleted file mode 100644 index f602771bc68874789ce8b2f79afbe12cdc571f5b..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/reify_type_for_tagged_packed_union.zig +++ /dev/null @@ -1,11 +0,0 @@ -const Tag = @Enum(u2, .exhaustive, &.{ "signed", "unsigned" }, &.{ 0, 1 }); -const Packed = @Union(.@"packed", Tag, &.{ "signed", "unsigned" }, &.{ i32, u32 }, &@splat(.{})); - -export fn entry() void { - const tagged: Packed = .{ .signed = -1 }; - _ = tagged; -} - -// error -// -// :2:35: error: packed union does not support enum tag type diff --git a/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig b/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig index 5b56a98eb3d9c058708f2685738d518e36759a8d..0b62e7b6d945bcb1808710411ce4f465cd859b1e 100644 --- a/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig +++ b/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig @@ -7,6 +7,5 @@ export fn entry() void { // error // -// :2:35: error: 1 enum fields missing in union -// :1:13: note: field 'arst' missing, declared here -// :1:13: note: enum declared here +// :2:16: error: enum field 'arst' missing from union +// :1:36: note: enum field here diff --git a/test/cases/compile_errors/reify_type_for_tagged_union_with_no_union_fields.zig b/test/cases/compile_errors/reify_type_for_tagged_union_with_no_union_fields.zig index 245bd472ccfdc6b1be0d3f78c7fa63f649e97f4b..ae4903c4d8739f08607d656306b9f013f21ccefc 100644 --- a/test/cases/compile_errors/reify_type_for_tagged_union_with_no_union_fields.zig +++ b/test/cases/compile_errors/reify_type_for_tagged_union_with_no_union_fields.zig @@ -7,7 +7,5 @@ export fn entry() void { // error // -// :2:35: error: 2 enum fields missing in union -// :1:13: note: field 'signed' missing, declared here -// :1:13: note: field 'unsigned' missing, declared here -// :1:13: note: enum declared here +// :2:16: error: enum field 'signed' missing from union +// :1:36: note: enum field here diff --git a/test/cases/compile_errors/reify_type_for_union_with_opaque_field.zig b/test/cases/compile_errors/reify_type_for_union_with_opaque_field.zig index e2be15f1a4239d4cd3721dc05652a203e8754d07..3a1b64e58ef3303189d885c757b25459a1668e3c 100644 --- a/test/cases/compile_errors/reify_type_for_union_with_opaque_field.zig +++ b/test/cases/compile_errors/reify_type_for_union_with_opaque_field.zig @@ -1,9 +1,11 @@ -const Untagged = @Union(.auto, null, &.{"foo"}, &.{opaque {}}, &.{.{}}); +const Opaque = opaque {}; +const Untagged = @Union(.auto, null, &.{"foo"}, &.{Opaque}, &.{.{}}); export fn entry() usize { return @sizeOf(Untagged); } // error // -// :1:49: error: opaque types have unknown size and therefore cannot be directly embedded in unions -// :1:52: note: opaque declared here +// :2:49: error: cannot directly embed opaque type 'tmp.Opaque' in union +// :2:49: note: opaque types have unknown size +// :1:16: note: opaque declared here diff --git a/test/cases/compile_errors/reify_type_with_invalid_field_alignment.zig b/test/cases/compile_errors/reify_type_with_invalid_field_alignment.zig index e6b9e1435a68f238a977042f4349d8b124682f74..b71480ed265099f5a5e88ddd407369b0b8431831 100644 --- a/test/cases/compile_errors/reify_type_with_invalid_field_alignment.zig +++ b/test/cases/compile_errors/reify_type_with_invalid_field_alignment.zig @@ -2,7 +2,11 @@ comptime { _ = @Union(.auto, null, &.{"foo"}, &.{usize}, &.{.{ .@"align" = 3 }}); } comptime { - _ = @Struct(.auto, null, &.{"a"}, &.{u32}, &.{.{ .@"comptime" = true, .@"align" = 5 }}); + _ = @Struct(.auto, null, &.{"a"}, &.{u32}, &.{.{ + .@"comptime" = true, + .@"align" = 5, + .default_value_ptr = &@as(u32, 0), + }}); } comptime { _ = @Pointer(.many, .{ .@"align" = 7 }, u8, null); @@ -12,4 +16,4 @@ comptime { // // :2:51: error: alignment value '3' is not a power of two // :5:48: error: alignment value '5' is not a power of two -// :8:26: error: alignment value '7' is not a power of two +// :12:26: error: alignment value '7' is not a power of two diff --git a/test/cases/compile_errors/resolve_inferred_error_set_of_generic_fn.zig b/test/cases/compile_errors/resolve_inferred_error_set_of_generic_fn.zig index f6c98d68b1e8aa8bc0b939e96dfca4f2ca479197..91ece712e03db5d6370c71e64623a46d9f213d37 100644 --- a/test/cases/compile_errors/resolve_inferred_error_set_of_generic_fn.zig +++ b/test/cases/compile_errors/resolve_inferred_error_set_of_generic_fn.zig @@ -12,5 +12,4 @@ export fn entry() void { // error // -// :10:15: error: unable to resolve inferred error set of generic function -// :1:1: note: generic function declared here +// :1:1: error: cannot resolve inferred error set of generic function type 'fn (anytype) @typeInfo(@typeInfo(@TypeOf(tmp.foo)).@"fn".return_type.?).error_union.error_set!void' diff --git a/test/cases/compile_errors/runtime_@ptrFromInt_to_comptime_only_type.zig b/test/cases/compile_errors/runtime_@ptrFromInt_to_comptime_only_type.zig index 04dc92f86ba16035fc5cd5f118b1e310e5617ff6..6e21501dcffbe65ccc1dddfe25508f5ad006f0ef 100644 --- a/test/cases/compile_errors/runtime_@ptrFromInt_to_comptime_only_type.zig +++ b/test/cases/compile_errors/runtime_@ptrFromInt_to_comptime_only_type.zig @@ -10,6 +10,5 @@ pub export fn callbackFin(id: c_int, arg: ?*anyopaque) void { // error // -// :5:54: error: pointer to comptime-only type '?*tmp.GuSettings' must be comptime-known, but operand is runtime-known -// :2:10: note: struct requires comptime because of this field -// :2:10: note: use '*const fn (c_int) callconv(.c) void' for a function pointer type +// :6:19: error: cannot load comptime-only type '?fn (c_int) callconv(.c) void' +// :6:20: note: pointer of type '*?fn (c_int) callconv(.c) void' is runtime-known diff --git a/test/cases/compile_errors/runtime_index_into_comptime_only_many_ptr.zig b/test/cases/compile_errors/runtime_index_into_comptime_only_many_ptr.zig index 4a2d475b1f14451e0a0370ba315d54b5f4ad66dd..3f645862fa7be40c0ed11d0e6c9505b00870f4f4 100644 --- a/test/cases/compile_errors/runtime_index_into_comptime_only_many_ptr.zig +++ b/test/cases/compile_errors/runtime_index_into_comptime_only_many_ptr.zig @@ -1,10 +1,10 @@ var rt: usize = 0; export fn foo() void { const x: [*]const type = &.{ u8, u16 }; - _ = &x[rt]; + _ = x[rt]; } // error // -// :4:12: error: values of type '[*]const type' must be comptime-known, but index value is runtime-known -// :4:11: note: types are not available at runtime +// :4:11: error: values of type 'type' must be comptime-known, but index value is runtime-known +// :4:10: note: types are not available at runtime diff --git a/test/cases/compile_errors/runtime_index_into_comptime_type_slice.zig b/test/cases/compile_errors/runtime_index_into_comptime_type_slice.zig index b4781a3c680abe53388eed2196ceeaa13c216527..b4cf100c19978597ccf5f987f69fdebe1345a848 100644 --- a/test/cases/compile_errors/runtime_index_into_comptime_type_slice.zig +++ b/test/cases/compile_errors/runtime_index_into_comptime_type_slice.zig @@ -12,7 +12,6 @@ export fn entry() void { // error // -// :9:54: error: values of type '[]const builtin.Type.StructField' must be comptime-known, but index value is runtime-known +// :9:54: error: values of type 'builtin.Type.StructField' must be comptime-known, but index value is runtime-known // : note: struct requires comptime because of this field // : note: types are not available at runtime -// : struct requires comptime because of this field diff --git a/test/cases/compile_errors/runtime_indexing_comptime_array.zig b/test/cases/compile_errors/runtime_indexing_comptime_array.zig index 3fcf57dd47bfe4883850f96fd955f481a8768b36..f82991dd3974cdfc754ae4746cc0ac6847f4829a 100644 --- a/test/cases/compile_errors/runtime_indexing_comptime_array.zig +++ b/test/cases/compile_errors/runtime_indexing_comptime_array.zig @@ -24,9 +24,9 @@ pub export fn entry3() void { } // error // -// :7:10: error: values of type '[2]fn () void' must be comptime-known, but index value is runtime-known +// :7:10: error: values of type 'fn () void' must be comptime-known, but index value is runtime-known // :7:10: note: use '*const fn () void' for a function pointer type -// :15:18: error: values of type '[2]fn () void' must be comptime-known, but index value is runtime-known +// :15:18: error: values of type 'fn () void' must be comptime-known, but index value is runtime-known // :15:17: note: use '*const fn () void' for a function pointer type -// :22:19: error: values of type '[2]fn () void' must be comptime-known, but index value is runtime-known +// :22:19: error: values of type 'fn () void' must be comptime-known, but index value is runtime-known // :22:18: note: use '*const fn () void' for a function pointer type diff --git a/test/cases/compile_errors/runtime_operation_in_comptime_scope.zig b/test/cases/compile_errors/runtime_operation_in_comptime_scope.zig index 73220b0ba4e1de7273b2bb2c7b85ef232d225596..1631fc07fc41aee4e21324478e9d294b0bb6459a 100644 --- a/test/cases/compile_errors/runtime_operation_in_comptime_scope.zig +++ b/test/cases/compile_errors/runtime_operation_in_comptime_scope.zig @@ -25,13 +25,13 @@ var rt: u32 = undefined; // // :19:8: error: unable to evaluate comptime expression // :19:5: note: operation is runtime due to this operand +// :6:8: note: called at comptime from here +// :5:1: note: 'comptime' keyword forces comptime evaluation +// :19:8: error: unable to evaluate comptime expression +// :19:5: note: operation is runtime due to this operand // :14:8: note: called at comptime from here // :10:12: note: called at comptime from here // :10:12: note: call to function with comptime-only return type 'type' is evaluated at comptime // :13:10: note: return type declared here // :10:12: note: types are not available at runtime // :2:8: note: called inline here -// :19:8: error: unable to evaluate comptime expression -// :19:5: note: operation is runtime due to this operand -// :6:8: note: called at comptime from here -// :5:1: note: 'comptime' keyword forces comptime evaluation diff --git a/test/cases/compile_errors/self_referential_struct_requires_comptime.zig b/test/cases/compile_errors/self_referential_struct_requires_comptime.zig index 5205702b679e3ca9d09351af5f8a76b7687983fb..81a0813d9b63b49cbda15cc79ba7b3bf4c67d5ec 100644 --- a/test/cases/compile_errors/self_referential_struct_requires_comptime.zig +++ b/test/cases/compile_errors/self_referential_struct_requires_comptime.zig @@ -12,4 +12,3 @@ pub export fn entry() void { // :6:12: error: variable of type 'tmp.S' must be const or comptime // :2:8: note: struct requires comptime because of this field // :2:8: note: use '*const fn () void' for a function pointer type -// :3:8: note: struct requires comptime because of this field diff --git a/test/cases/compile_errors/self_referential_union_requires_comptime.zig b/test/cases/compile_errors/self_referential_union_requires_comptime.zig index 6ab0af996596a9bc021466ff95d71c2ff6ec79db..fbf00ce69a6b4ccfeb763b394d9581377a81b16e 100644 --- a/test/cases/compile_errors/self_referential_union_requires_comptime.zig +++ b/test/cases/compile_errors/self_referential_union_requires_comptime.zig @@ -12,4 +12,3 @@ pub export fn entry() void { // :6:12: error: variable of type 'tmp.U' must be const or comptime // :2:8: note: union requires comptime because of this field // :2:8: note: use '*const fn () void' for a function pointer type -// :3:8: note: union requires comptime because of this field diff --git a/test/cases/compile_errors/sizeOf_bad_type.zig b/test/cases/compile_errors/sizeOf_bad_type.zig index c81ad7450f3d34e9af7e0eabcc2917e4303027f1..6d20251064f5be10e258283aaa6facb6451403c4 100644 --- a/test/cases/compile_errors/sizeOf_bad_type.zig +++ b/test/cases/compile_errors/sizeOf_bad_type.zig @@ -22,4 +22,6 @@ export fn entry4() usize { // :5:20: error: no size available for comptime-only type 'comptime_int' // :8:20: error: no size available for uninstantiable type 'noreturn' // :12:20: error: no size available for comptime-only type 'tmp.S3' +// :10:12: note: struct declared here // :16:20: error: no size available for uninstantiable type 'tmp.S4' +// :14:12: note: struct declared here diff --git a/test/cases/compile_errors/sizeof_alignof_empty_union.zig b/test/cases/compile_errors/sizeof_alignof_empty_union.zig index 920b3b5af8a6281cce83860996d8af8eca3011f4..58e6aa635088c30cab0c1d7306f088406fcb34d1 100644 --- a/test/cases/compile_errors/sizeof_alignof_empty_union.zig +++ b/test/cases/compile_errors/sizeof_alignof_empty_union.zig @@ -49,27 +49,27 @@ export fn align5() void { // error // -// :13:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U0' +// :13:17: error: no size available for uninstantiable type 'tmp.U0' // :5:12: note: union declared here -// :16:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U1' +// :16:17: error: no size available for uninstantiable type 'tmp.U1' // :6:12: note: union declared here -// :19:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U2' +// :19:17: error: no size available for uninstantiable type 'tmp.U2' // :7:12: note: union declared here -// :22:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U3' +// :22:17: error: no size available for uninstantiable type 'tmp.U3' // :8:12: note: union declared here -// :25:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U4' +// :25:17: error: no size available for uninstantiable type 'tmp.U4' // :9:12: note: union declared here -// :28:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U5' +// :28:17: error: no size available for uninstantiable type 'tmp.U5' // :10:12: note: union declared here -// :32:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U0' +// :32:18: error: no align available for uninstantiable type 'tmp.U0' // :5:12: note: union declared here -// :35:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U1' +// :35:18: error: no align available for uninstantiable type 'tmp.U1' // :6:12: note: union declared here -// :38:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U2' +// :38:18: error: no align available for uninstantiable type 'tmp.U2' // :7:12: note: union declared here -// :41:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U3' +// :41:18: error: no align available for uninstantiable type 'tmp.U3' // :8:12: note: union declared here -// :44:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U4' +// :44:18: error: no align available for uninstantiable type 'tmp.U4' // :9:12: note: union declared here -// :47:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U5' +// :47:18: error: no align available for uninstantiable type 'tmp.U5' // :10:12: note: union declared here diff --git a/test/cases/compile_errors/slice_used_as_extern_fn_param.zig b/test/cases/compile_errors/slice_used_as_extern_fn_param.zig index 522e4eba8ce278e56afc5643813d84db253bc0ea..e056aa23800a0a9810d3da6b3c66ce8ad82ac31d 100644 --- a/test/cases/compile_errors/slice_used_as_extern_fn_param.zig +++ b/test/cases/compile_errors/slice_used_as_extern_fn_param.zig @@ -1,6 +1,6 @@ extern fn Text(str: []const u8, num: i32) callconv(.c) void; export fn entry() void { - _ = Text; + Text(undefined, undefined); } // error diff --git a/test/cases/compile_errors/specify_enum_tag_type_that_is_too_small.zig b/test/cases/compile_errors/specify_enum_tag_type_that_is_too_small.zig index f00c363aae5fad3620c6d5c54625153b44ac3740..b6d9bd7d21ad217efe00ba4fa88c1cbe440d75a3 100644 --- a/test/cases/compile_errors/specify_enum_tag_type_that_is_too_small.zig +++ b/test/cases/compile_errors/specify_enum_tag_type_that_is_too_small.zig @@ -1,9 +1,9 @@ const Small = enum(u2) { - One, - Two, - Three, - Four, - Five, + one, + two, + three, + four, + five, }; const SmallUnion = union(enum(u2)) { @@ -14,13 +14,13 @@ const SmallUnion = union(enum(u2)) { }; comptime { - _ = Small; + _ = Small.one; } comptime { - _ = SmallUnion; + _ = SmallUnion.one; } // error // -// :6:5: error: enumeration value '4' too large for type 'u2' -// :13:5: error: enumeration value '4' too large for type 'u2' +// :6:5: error: enum tag value '4' too large for type 'u2' +// :13:5: error: enum tag value '4' too large for type 'u2' diff --git a/test/cases/compile_errors/store_comptime_only_type_to_runtime_pointer.zig b/test/cases/compile_errors/store_comptime_only_type_to_runtime_pointer.zig index af30c80f7040e148eadb1e0965c9d3b24c81c15f..05ae6f920205b98525020c71038b593a7d487f9b 100644 --- a/test/cases/compile_errors/store_comptime_only_type_to_runtime_pointer.zig +++ b/test/cases/compile_errors/store_comptime_only_type_to_runtime_pointer.zig @@ -21,22 +21,15 @@ export fn e() void { p.* = undefined; } -export fn f() void { - const p: **comptime_int = @ptrFromInt(16); // double pointer ('*comptime_int' is comptime-only) - p.* = undefined; -} - // error // // :3:9: error: cannot store comptime-only type 'fn () void' at runtime // :3:6: note: operation is runtime due to this pointer // :7:11: error: expected type 'anyopaque', found '@TypeOf(undefined)' -// :7:11: note: cannot coerce to 'anyopaque' +// :7:11: note: cannot coerce to uninstantiable type 'anyopaque' // :11:12: error: cannot load opaque type 'anyopaque' // :16:11: error: expected type 'tmp.Opaque', found '@TypeOf(undefined)' -// :16:11: note: cannot coerce to 'tmp.Opaque' +// :16:11: note: cannot coerce to uninstantiable type 'tmp.Opaque' // :14:16: note: opaque declared here // :21:9: error: cannot store comptime-only type 'comptime_int' at runtime // :21:6: note: operation is runtime due to this pointer -// :26:9: error: cannot store comptime-only type '*comptime_int' at runtime -// :26:6: note: operation is runtime due to this pointer diff --git a/test/cases/compile_errors/struct_depends_on_itself_via_non_initial_field.zig b/test/cases/compile_errors/struct_depends_on_itself_via_non_initial_field.zig index b514bc10e7bf8c1ced988e2b14e6c80afcc40605..7d2ddaa2096fd10f1be1f6c113bcf236ecd58ef5 100644 --- a/test/cases/compile_errors/struct_depends_on_itself_via_non_initial_field.zig +++ b/test/cases/compile_errors/struct_depends_on_itself_via_non_initial_field.zig @@ -4,9 +4,9 @@ const A = struct { }; comptime { - _ = A; + _ = @as(A, undefined); } // error // -// :1:11: error: struct 'tmp.A' depends on itself +// :3:21: error: type 'tmp.A' depends on itself for size query here diff --git a/test/cases/compile_errors/struct_depends_on_itself_via_optional_field.zig b/test/cases/compile_errors/struct_depends_on_itself_via_optional_field.zig index a8614baf79d03384d38c67044a32920a260b7ec2..bc4ad96555a6f9ff02d95637a74342104cb0566a 100644 --- a/test/cases/compile_errors/struct_depends_on_itself_via_optional_field.zig +++ b/test/cases/compile_errors/struct_depends_on_itself_via_optional_field.zig @@ -12,4 +12,7 @@ export fn entry() void { // error // -// :1:17: error: struct 'tmp.LhsExpr' depends on itself +// error: dependency loop with length 2 +// :2:14: note: type 'tmp.LhsExpr' depends on type 'tmp.AstObject' for field declared here +// :5:14: note: type 'tmp.AstObject' depends on type 'tmp.LhsExpr' for field declared here +// note: eliminate any one of these dependencies to break the loop diff --git a/test/cases/compile_errors/struct_depends_on_pointer_alignment.zig b/test/cases/compile_errors/struct_depends_on_pointer_alignment.zig deleted file mode 100644 index ca15cc6bf26d17527cd77fe73200130ab130609c..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/struct_depends_on_pointer_alignment.zig +++ /dev/null @@ -1,11 +0,0 @@ -const S = struct { - next: ?*align(1) S align(128), -}; - -export fn entry() usize { - return @alignOf(S); -} - -// error -// -// :1:11: error: struct layout depends on being pointer aligned diff --git a/test/cases/compile_errors/too_big_packed_struct.zig b/test/cases/compile_errors/too_big_packed_struct.zig index b5b585b70ca1f5a71867f8afe3751733bfea8f02..425442ae179ee3649a9247a8f8fa1d550ee5bebe 100644 --- a/test/cases/compile_errors/too_big_packed_struct.zig +++ b/test/cases/compile_errors/too_big_packed_struct.zig @@ -8,4 +8,4 @@ pub export fn entry() void { // error // -// :2:22: error: size of packed struct '131070' exceeds maximum bit width of 65535 +// :2:22: error: packed struct bit width '131070' exceeds maximum bit width of 65535 diff --git a/test/cases/compile_errors/top_level_decl_dependency_loop.zig b/test/cases/compile_errors/top_level_decl_dependency_loop.zig index fbfd0e9cb376a385b2f19c0edc239d97e6777a38..4412c38f6e672b4a6ca8e2e26dca77ba1fee3bb8 100644 --- a/test/cases/compile_errors/top_level_decl_dependency_loop.zig +++ b/test/cases/compile_errors/top_level_decl_dependency_loop.zig @@ -7,4 +7,9 @@ export fn entry() void { // error // -// :1:1: error: dependency loop detected +// error: dependency loop with length 4 +// :1:23: note: value of declaration 'tmp.a' uses type of declaration 'tmp.a' here +// :1:18: note: type of declaration 'tmp.a' uses value of declaration 'tmp.b' here +// :2:23: note: value of declaration 'tmp.b' uses type of declaration 'tmp.b' here +// :2:18: note: type of declaration 'tmp.b' uses value of declaration 'tmp.a' here +// note: eliminate any one of these dependencies to break the loop diff --git a/test/cases/compile_errors/unable_to_evaluate_comptime_expr.zig b/test/cases/compile_errors/unable_to_evaluate_comptime_expr.zig index ba9de49ebca46fe46ae1fb823f399b8926e978ae..e1cff784d522ac3fad1806c93fd3999eb379e930 100644 --- a/test/cases/compile_errors/unable_to_evaluate_comptime_expr.zig +++ b/test/cases/compile_errors/unable_to_evaluate_comptime_expr.zig @@ -16,22 +16,6 @@ pub export fn entry2() void { _ = b; } -const Int = @typeInfo(bar).@"struct".backing_integer.?; - -const foo = enum(Int) { - c = @bitCast(bar{ - .name = "test", - }), -}; - -const bar = packed struct { - name: [*:0]const u8, -}; - -pub export fn entry3() void { - _ = @field(foo, "c"); -} - // error // // :7:13: error: unable to evaluate comptime expression @@ -40,6 +24,3 @@ pub export fn entry3() void { // :13:13: error: unable to evaluate comptime expression // :13:16: note: operation is runtime due to this operand // :13:13: note: initializer of container-level variable must be comptime-known -// :22:9: error: unable to evaluate comptime expression -// :22:21: note: operation is runtime due to this operand -// :21:13: note: enum field values must be comptime-known diff --git a/test/cases/compile_errors/undef_arith_is_illegal.zig b/test/cases/compile_errors/undef_arith_is_illegal.zig index 21ca597e878507ab1d723017e061d3a201cdef6b..92279a055835346547e5143a031aa8f0612278bc 100644 --- a/test/cases/compile_errors/undef_arith_is_illegal.zig +++ b/test/cases/compile_errors/undef_arith_is_illegal.zig @@ -192,50 +192,30 @@ const std = @import("std"); // :65:17: error: use of undefined value here causes illegal behavior // :65:17: error: use of undefined value here causes illegal behavior // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: error: use of undefined value here causes illegal behavior // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: error: use of undefined value here causes illegal behavior -// :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' @@ -244,10 +224,6 @@ const std = @import("std"); // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '1' -// :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '1' -// :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' @@ -256,7 +232,9 @@ const std = @import("std"); // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior @@ -266,9 +244,9 @@ const std = @import("std"); // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '1' +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '1' +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior @@ -278,7 +256,9 @@ const std = @import("std"); // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior @@ -288,9 +268,9 @@ const std = @import("std"); // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '1' +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '1' +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior @@ -300,7 +280,9 @@ const std = @import("std"); // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior @@ -310,9 +292,9 @@ const std = @import("std"); // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '1' +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '1' +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior @@ -322,7 +304,9 @@ const std = @import("std"); // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior @@ -332,9 +316,9 @@ const std = @import("std"); // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '1' +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '1' +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior @@ -344,7 +328,9 @@ const std = @import("std"); // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior @@ -354,9 +340,9 @@ const std = @import("std"); // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '1' +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '1' +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior @@ -366,7 +352,9 @@ const std = @import("std"); // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior @@ -376,9 +364,9 @@ const std = @import("std"); // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '1' +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '1' +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior @@ -388,7 +376,9 @@ const std = @import("std"); // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '0' // :65:17: error: use of undefined value here causes illegal behavior @@ -402,35 +392,45 @@ const std = @import("std"); // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' +// :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' +// :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' +// :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' +// :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' +// :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' +// :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' +// :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' +// :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior // :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' +// :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' +// :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' +// :65:17: note: when computing vector element at index '1' // :65:17: error: use of undefined value here causes illegal behavior -// :65:17: note: when computing vector element at index '0' +// :65:17: note: when computing vector element at index '1' +// :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '1' +// :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '1' +// :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '1' +// :65:17: error: use of undefined value here causes illegal behavior +// :65:17: note: when computing vector element at index '1' // :65:21: error: use of undefined value here causes illegal behavior // :65:21: note: when computing vector element at index '0' // :65:21: error: use of undefined value here causes illegal behavior @@ -478,50 +478,30 @@ const std = @import("std"); // :69:27: error: use of undefined value here causes illegal behavior // :69:27: error: use of undefined value here causes illegal behavior // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: error: use of undefined value here causes illegal behavior // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: error: use of undefined value here causes illegal behavior -// :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' @@ -530,10 +510,6 @@ const std = @import("std"); // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '1' -// :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '1' -// :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' @@ -542,7 +518,9 @@ const std = @import("std"); // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior @@ -552,9 +530,9 @@ const std = @import("std"); // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '1' +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '1' +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior @@ -564,7 +542,9 @@ const std = @import("std"); // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior @@ -574,9 +554,9 @@ const std = @import("std"); // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '1' +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '1' +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior @@ -586,7 +566,9 @@ const std = @import("std"); // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior @@ -596,9 +578,9 @@ const std = @import("std"); // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '1' +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '1' +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior @@ -608,7 +590,9 @@ const std = @import("std"); // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior @@ -618,9 +602,9 @@ const std = @import("std"); // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '1' +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '1' +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior @@ -630,7 +614,9 @@ const std = @import("std"); // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior @@ -640,9 +626,9 @@ const std = @import("std"); // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '1' +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '1' +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior @@ -652,7 +638,9 @@ const std = @import("std"); // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior @@ -662,9 +650,9 @@ const std = @import("std"); // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '1' +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '1' +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior @@ -674,7 +662,9 @@ const std = @import("std"); // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '0' // :69:27: error: use of undefined value here causes illegal behavior @@ -688,35 +678,45 @@ const std = @import("std"); // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' +// :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' +// :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' +// :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' +// :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' +// :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' +// :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' +// :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' +// :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior // :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' +// :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' +// :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' +// :69:27: note: when computing vector element at index '1' // :69:27: error: use of undefined value here causes illegal behavior -// :69:27: note: when computing vector element at index '0' +// :69:27: note: when computing vector element at index '1' +// :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '1' +// :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '1' +// :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '1' +// :69:27: error: use of undefined value here causes illegal behavior +// :69:27: note: when computing vector element at index '1' // :69:30: error: use of undefined value here causes illegal behavior // :69:30: note: when computing vector element at index '0' // :69:30: error: use of undefined value here causes illegal behavior @@ -764,50 +764,30 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: error: use of undefined value here causes illegal behavior // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: error: use of undefined value here causes illegal behavior // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: error: use of undefined value here causes illegal behavior -// :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' @@ -816,10 +796,6 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' -// :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' -// :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' @@ -828,7 +804,9 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior @@ -838,9 +816,9 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior @@ -850,7 +828,9 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior @@ -860,9 +840,9 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior @@ -872,7 +852,9 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior @@ -882,9 +864,9 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior @@ -894,7 +876,9 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior @@ -904,9 +888,9 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior @@ -916,7 +900,9 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior @@ -926,9 +912,9 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior @@ -938,7 +924,9 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior @@ -948,9 +936,9 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior @@ -960,7 +948,9 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior @@ -974,35 +964,45 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' +// :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '1' +// :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '1' +// :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '1' +// :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '1' // :73:30: error: use of undefined value here causes illegal behavior // :73:30: note: when computing vector element at index '0' // :73:30: error: use of undefined value here causes illegal behavior @@ -1050,50 +1050,30 @@ const std = @import("std"); // :77:27: error: use of undefined value here causes illegal behavior // :77:27: error: use of undefined value here causes illegal behavior // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: error: use of undefined value here causes illegal behavior // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: error: use of undefined value here causes illegal behavior -// :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' @@ -1102,10 +1082,6 @@ const std = @import("std"); // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '1' -// :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '1' -// :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' @@ -1114,7 +1090,9 @@ const std = @import("std"); // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior @@ -1124,9 +1102,9 @@ const std = @import("std"); // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '1' +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '1' +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior @@ -1136,7 +1114,9 @@ const std = @import("std"); // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior @@ -1146,9 +1126,9 @@ const std = @import("std"); // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '1' +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '1' +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior @@ -1158,7 +1138,9 @@ const std = @import("std"); // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior @@ -1168,9 +1150,9 @@ const std = @import("std"); // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '1' +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '1' +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior @@ -1180,7 +1162,9 @@ const std = @import("std"); // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior @@ -1190,9 +1174,9 @@ const std = @import("std"); // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '1' +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '1' +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior @@ -1202,7 +1186,9 @@ const std = @import("std"); // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior @@ -1212,9 +1198,9 @@ const std = @import("std"); // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '1' +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '1' +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior @@ -1224,7 +1210,9 @@ const std = @import("std"); // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior @@ -1234,9 +1222,9 @@ const std = @import("std"); // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '1' +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '1' +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior @@ -1246,7 +1234,9 @@ const std = @import("std"); // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '0' // :77:27: error: use of undefined value here causes illegal behavior @@ -1260,35 +1250,45 @@ const std = @import("std"); // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' +// :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' +// :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' +// :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' +// :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' +// :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' +// :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' +// :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' +// :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior // :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' +// :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' +// :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' +// :77:27: note: when computing vector element at index '1' // :77:27: error: use of undefined value here causes illegal behavior -// :77:27: note: when computing vector element at index '0' +// :77:27: note: when computing vector element at index '1' +// :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '1' +// :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '1' +// :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '1' +// :77:27: error: use of undefined value here causes illegal behavior +// :77:27: note: when computing vector element at index '1' // :77:30: error: use of undefined value here causes illegal behavior // :77:30: note: when computing vector element at index '0' // :77:30: error: use of undefined value here causes illegal behavior @@ -1336,50 +1336,30 @@ const std = @import("std"); // :81:17: error: use of undefined value here causes illegal behavior // :81:17: error: use of undefined value here causes illegal behavior // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: error: use of undefined value here causes illegal behavior // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: error: use of undefined value here causes illegal behavior -// :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' @@ -1388,10 +1368,6 @@ const std = @import("std"); // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '1' -// :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '1' -// :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' @@ -1400,7 +1376,9 @@ const std = @import("std"); // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior @@ -1410,9 +1388,9 @@ const std = @import("std"); // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '1' +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '1' +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior @@ -1422,7 +1400,9 @@ const std = @import("std"); // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior @@ -1432,9 +1412,9 @@ const std = @import("std"); // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '1' +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '1' +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior @@ -1444,7 +1424,9 @@ const std = @import("std"); // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior @@ -1454,9 +1436,9 @@ const std = @import("std"); // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '1' +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '1' +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior @@ -1466,7 +1448,9 @@ const std = @import("std"); // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior @@ -1476,9 +1460,9 @@ const std = @import("std"); // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '1' +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '1' +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior @@ -1488,7 +1472,9 @@ const std = @import("std"); // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior @@ -1498,9 +1484,9 @@ const std = @import("std"); // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '1' +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '1' +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior @@ -1510,7 +1496,9 @@ const std = @import("std"); // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior @@ -1520,9 +1508,9 @@ const std = @import("std"); // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '1' +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '1' +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior @@ -1532,7 +1520,9 @@ const std = @import("std"); // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '0' // :81:17: error: use of undefined value here causes illegal behavior @@ -1546,35 +1536,45 @@ const std = @import("std"); // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' +// :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' +// :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' +// :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' +// :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' +// :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' +// :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' +// :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' +// :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior // :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' +// :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' +// :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' +// :81:17: note: when computing vector element at index '1' // :81:17: error: use of undefined value here causes illegal behavior -// :81:17: note: when computing vector element at index '0' +// :81:17: note: when computing vector element at index '1' +// :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '1' +// :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '1' +// :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '1' +// :81:17: error: use of undefined value here causes illegal behavior +// :81:17: note: when computing vector element at index '1' // :81:21: error: use of undefined value here causes illegal behavior // :81:21: note: when computing vector element at index '0' // :81:21: error: use of undefined value here causes illegal behavior @@ -1622,39 +1622,25 @@ const std = @import("std"); // :85:22: error: use of undefined value here causes illegal behavior // :85:22: error: use of undefined value here causes illegal behavior // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '1' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '1' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior // :85:22: error: use of undefined value here causes illegal behavior // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '1' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '1' +// :85:22: error: use of undefined value here causes illegal behavior +// :85:22: error: use of undefined value here causes illegal behavior // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior @@ -1664,7 +1650,9 @@ const std = @import("std"); // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior @@ -1674,9 +1662,9 @@ const std = @import("std"); // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '1' +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '1' +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior @@ -1686,7 +1674,9 @@ const std = @import("std"); // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior @@ -1696,9 +1686,9 @@ const std = @import("std"); // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '1' +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '1' +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior @@ -1708,7 +1698,9 @@ const std = @import("std"); // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior @@ -1718,10 +1710,6 @@ const std = @import("std"); // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '1' -// :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '1' -// :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' @@ -1730,8 +1718,6 @@ const std = @import("std"); // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: error: use of undefined value here causes illegal behavior -// :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' @@ -1740,10 +1726,6 @@ const std = @import("std"); // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '1' -// :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '1' -// :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' @@ -1752,7 +1734,9 @@ const std = @import("std"); // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior @@ -1762,9 +1746,9 @@ const std = @import("std"); // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '1' +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '1' +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior @@ -1774,7 +1758,9 @@ const std = @import("std"); // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior @@ -1784,9 +1770,9 @@ const std = @import("std"); // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '1' +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '1' +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior @@ -1796,7 +1782,9 @@ const std = @import("std"); // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior @@ -1806,9 +1794,9 @@ const std = @import("std"); // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '1' +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '1' +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior @@ -1818,7 +1806,9 @@ const std = @import("std"); // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '0' // :85:22: error: use of undefined value here causes illegal behavior @@ -1832,35 +1822,45 @@ const std = @import("std"); // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '1' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' +// :85:22: note: when computing vector element at index '1' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' +// :85:22: note: when computing vector element at index '1' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' +// :85:22: note: when computing vector element at index '1' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' +// :85:22: note: when computing vector element at index '1' // :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '1' // :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '1' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' +// :85:22: note: when computing vector element at index '1' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' +// :85:22: note: when computing vector element at index '1' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' +// :85:22: note: when computing vector element at index '1' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' +// :85:22: note: when computing vector element at index '1' // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '1' // :85:22: error: use of undefined value here causes illegal behavior // :85:22: note: when computing vector element at index '1' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' +// :85:22: note: when computing vector element at index '1' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' +// :85:22: note: when computing vector element at index '1' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' +// :85:22: note: when computing vector element at index '1' // :85:22: error: use of undefined value here causes illegal behavior -// :85:22: note: when computing vector element at index '0' +// :85:22: note: when computing vector element at index '1' +// :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '1' +// :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '1' +// :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '1' +// :85:22: error: use of undefined value here causes illegal behavior +// :85:22: note: when computing vector element at index '1' // :85:25: error: use of undefined value here causes illegal behavior // :85:25: note: when computing vector element at index '0' // :85:25: error: use of undefined value here causes illegal behavior @@ -1908,50 +1908,30 @@ const std = @import("std"); // :89:22: error: use of undefined value here causes illegal behavior // :89:22: error: use of undefined value here causes illegal behavior // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: error: use of undefined value here causes illegal behavior // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: error: use of undefined value here causes illegal behavior -// :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' @@ -1960,10 +1940,6 @@ const std = @import("std"); // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '1' -// :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '1' -// :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' @@ -1972,7 +1948,9 @@ const std = @import("std"); // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior @@ -1982,9 +1960,9 @@ const std = @import("std"); // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '1' +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '1' +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior @@ -1994,7 +1972,9 @@ const std = @import("std"); // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior @@ -2004,9 +1984,9 @@ const std = @import("std"); // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '1' +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '1' +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior @@ -2016,7 +1996,9 @@ const std = @import("std"); // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior @@ -2026,9 +2008,9 @@ const std = @import("std"); // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '1' +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '1' +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior @@ -2038,7 +2020,9 @@ const std = @import("std"); // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior @@ -2048,9 +2032,9 @@ const std = @import("std"); // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '1' +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '1' +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior @@ -2060,7 +2044,9 @@ const std = @import("std"); // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior @@ -2070,9 +2056,9 @@ const std = @import("std"); // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '1' +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '1' +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior @@ -2082,7 +2068,9 @@ const std = @import("std"); // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior @@ -2092,9 +2080,9 @@ const std = @import("std"); // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '1' +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '1' +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior @@ -2104,7 +2092,9 @@ const std = @import("std"); // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '0' // :89:22: error: use of undefined value here causes illegal behavior @@ -2118,35 +2108,45 @@ const std = @import("std"); // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' +// :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' +// :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' +// :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' +// :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' +// :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' +// :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' +// :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' +// :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior // :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' +// :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' +// :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' +// :89:22: note: when computing vector element at index '1' // :89:22: error: use of undefined value here causes illegal behavior -// :89:22: note: when computing vector element at index '0' +// :89:22: note: when computing vector element at index '1' +// :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '1' +// :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '1' +// :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '1' +// :89:22: error: use of undefined value here causes illegal behavior +// :89:22: note: when computing vector element at index '1' // :89:25: error: use of undefined value here causes illegal behavior // :89:25: note: when computing vector element at index '0' // :89:25: error: use of undefined value here causes illegal behavior @@ -2198,21 +2198,13 @@ const std = @import("std"); // :95:17: error: use of undefined value here causes illegal behavior // :95:17: error: use of undefined value here causes illegal behavior // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior // :95:17: error: use of undefined value here causes illegal behavior // :95:17: error: use of undefined value here causes illegal behavior @@ -2220,21 +2212,13 @@ const std = @import("std"); // :95:17: error: use of undefined value here causes illegal behavior // :95:17: error: use of undefined value here causes illegal behavior // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior // :95:17: error: use of undefined value here causes illegal behavior // :95:17: error: use of undefined value here causes illegal behavior @@ -2242,21 +2226,13 @@ const std = @import("std"); // :95:17: error: use of undefined value here causes illegal behavior // :95:17: error: use of undefined value here causes illegal behavior // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior // :95:17: error: use of undefined value here causes illegal behavior // :95:17: error: use of undefined value here causes illegal behavior @@ -2264,21 +2240,13 @@ const std = @import("std"); // :95:17: error: use of undefined value here causes illegal behavior // :95:17: error: use of undefined value here causes illegal behavior // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior // :95:17: error: use of undefined value here causes illegal behavior // :95:17: error: use of undefined value here causes illegal behavior @@ -2286,13 +2254,9 @@ const std = @import("std"); // :95:17: error: use of undefined value here causes illegal behavior // :95:17: error: use of undefined value here causes illegal behavior // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior // :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior @@ -2302,19 +2266,21 @@ const std = @import("std"); // :95:17: error: use of undefined value here causes illegal behavior // :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' -// :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' -// :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior // :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior @@ -2324,19 +2290,25 @@ const std = @import("std"); // :95:17: error: use of undefined value here causes illegal behavior // :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior // :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior @@ -2346,19 +2318,25 @@ const std = @import("std"); // :95:17: error: use of undefined value here causes illegal behavior // :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '1' +// :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior // :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior @@ -2368,11 +2346,17 @@ const std = @import("std"); // :95:17: error: use of undefined value here causes illegal behavior // :95:17: note: when computing vector element at index '0' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior // :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior @@ -2382,19 +2366,25 @@ const std = @import("std"); // :95:17: error: use of undefined value here causes illegal behavior // :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior // :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior @@ -2404,19 +2394,25 @@ const std = @import("std"); // :95:17: error: use of undefined value here causes illegal behavior // :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior // :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior @@ -2426,13 +2422,17 @@ const std = @import("std"); // :95:17: error: use of undefined value here causes illegal behavior // :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' +// :95:17: note: when computing vector element at index '1' // :95:17: error: use of undefined value here causes illegal behavior -// :95:17: note: when computing vector element at index '0' +// :95:17: note: when computing vector element at index '1' +// :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' +// :95:17: error: use of undefined value here causes illegal behavior +// :95:17: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior @@ -2440,21 +2440,13 @@ const std = @import("std"); // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior @@ -2462,21 +2454,13 @@ const std = @import("std"); // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior @@ -2484,21 +2468,13 @@ const std = @import("std"); // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior @@ -2506,21 +2482,13 @@ const std = @import("std"); // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior @@ -2528,13 +2496,9 @@ const std = @import("std"); // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior @@ -2544,19 +2508,21 @@ const std = @import("std"); // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' -// :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' -// :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior @@ -2566,19 +2532,25 @@ const std = @import("std"); // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior @@ -2588,19 +2560,25 @@ const std = @import("std"); // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior @@ -2610,11 +2588,17 @@ const std = @import("std"); // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior @@ -2624,19 +2608,25 @@ const std = @import("std"); // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior @@ -2646,19 +2636,25 @@ const std = @import("std"); // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior @@ -2668,13 +2664,17 @@ const std = @import("std"); // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' +// :99:27: note: when computing vector element at index '1' +// :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' +// :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior @@ -2682,21 +2682,13 @@ const std = @import("std"); // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior @@ -2704,21 +2696,13 @@ const std = @import("std"); // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior @@ -2726,21 +2710,13 @@ const std = @import("std"); // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior @@ -2748,21 +2724,13 @@ const std = @import("std"); // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior @@ -2770,13 +2738,9 @@ const std = @import("std"); // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior // :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior @@ -2786,19 +2750,21 @@ const std = @import("std"); // :103:27: error: use of undefined value here causes illegal behavior // :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' -// :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' -// :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior // :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior @@ -2808,19 +2774,25 @@ const std = @import("std"); // :103:27: error: use of undefined value here causes illegal behavior // :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior // :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior @@ -2830,19 +2802,25 @@ const std = @import("std"); // :103:27: error: use of undefined value here causes illegal behavior // :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '1' +// :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior // :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior @@ -2852,11 +2830,17 @@ const std = @import("std"); // :103:27: error: use of undefined value here causes illegal behavior // :103:27: note: when computing vector element at index '0' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior // :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior @@ -2866,19 +2850,25 @@ const std = @import("std"); // :103:27: error: use of undefined value here causes illegal behavior // :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior // :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior @@ -2888,19 +2878,25 @@ const std = @import("std"); // :103:27: error: use of undefined value here causes illegal behavior // :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior // :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior @@ -2910,13 +2906,17 @@ const std = @import("std"); // :103:27: error: use of undefined value here causes illegal behavior // :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' +// :103:27: note: when computing vector element at index '1' // :103:27: error: use of undefined value here causes illegal behavior -// :103:27: note: when computing vector element at index '0' +// :103:27: note: when computing vector element at index '1' +// :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' +// :103:27: error: use of undefined value here causes illegal behavior +// :103:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior @@ -2924,21 +2924,13 @@ const std = @import("std"); // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior @@ -2946,21 +2938,13 @@ const std = @import("std"); // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior @@ -2968,21 +2952,13 @@ const std = @import("std"); // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior @@ -2990,21 +2966,13 @@ const std = @import("std"); // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior @@ -3012,13 +2980,9 @@ const std = @import("std"); // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior // :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior @@ -3028,19 +2992,21 @@ const std = @import("std"); // :107:27: error: use of undefined value here causes illegal behavior // :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' -// :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' -// :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior // :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior @@ -3050,19 +3016,25 @@ const std = @import("std"); // :107:27: error: use of undefined value here causes illegal behavior // :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior // :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior @@ -3072,19 +3044,25 @@ const std = @import("std"); // :107:27: error: use of undefined value here causes illegal behavior // :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '1' +// :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior // :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior @@ -3094,11 +3072,17 @@ const std = @import("std"); // :107:27: error: use of undefined value here causes illegal behavior // :107:27: note: when computing vector element at index '0' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior // :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior @@ -3108,19 +3092,25 @@ const std = @import("std"); // :107:27: error: use of undefined value here causes illegal behavior // :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior // :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior @@ -3130,19 +3120,29 @@ const std = @import("std"); // :107:27: error: use of undefined value here causes illegal behavior // :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' +// :107:27: note: when computing vector element at index '1' +// :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' +// :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior // :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior @@ -3152,13 +3152,13 @@ const std = @import("std"); // :107:27: error: use of undefined value here causes illegal behavior // :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' +// :107:27: note: when computing vector element at index '1' // :107:27: error: use of undefined value here causes illegal behavior -// :107:27: note: when computing vector element at index '0' +// :107:27: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior @@ -3166,21 +3166,13 @@ const std = @import("std"); // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior @@ -3188,21 +3180,13 @@ const std = @import("std"); // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior @@ -3210,21 +3194,13 @@ const std = @import("std"); // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior @@ -3232,21 +3208,13 @@ const std = @import("std"); // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior @@ -3254,13 +3222,9 @@ const std = @import("std"); // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior // :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior @@ -3270,19 +3234,21 @@ const std = @import("std"); // :111:22: error: use of undefined value here causes illegal behavior // :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' -// :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' -// :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior // :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior @@ -3292,19 +3258,25 @@ const std = @import("std"); // :111:22: error: use of undefined value here causes illegal behavior // :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior // :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior @@ -3314,19 +3286,25 @@ const std = @import("std"); // :111:22: error: use of undefined value here causes illegal behavior // :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '1' +// :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior // :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior @@ -3336,11 +3314,17 @@ const std = @import("std"); // :111:22: error: use of undefined value here causes illegal behavior // :111:22: note: when computing vector element at index '0' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior // :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior @@ -3350,19 +3334,25 @@ const std = @import("std"); // :111:22: error: use of undefined value here causes illegal behavior // :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior // :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior @@ -3372,19 +3362,25 @@ const std = @import("std"); // :111:22: error: use of undefined value here causes illegal behavior // :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior // :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior @@ -3394,13 +3390,17 @@ const std = @import("std"); // :111:22: error: use of undefined value here causes illegal behavior // :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' +// :111:22: note: when computing vector element at index '1' // :111:22: error: use of undefined value here causes illegal behavior -// :111:22: note: when computing vector element at index '0' +// :111:22: note: when computing vector element at index '1' +// :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' +// :111:22: error: use of undefined value here causes illegal behavior +// :111:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior @@ -3408,21 +3408,13 @@ const std = @import("std"); // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior @@ -3430,21 +3422,13 @@ const std = @import("std"); // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior @@ -3452,21 +3436,13 @@ const std = @import("std"); // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior @@ -3474,21 +3450,13 @@ const std = @import("std"); // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior @@ -3496,13 +3464,9 @@ const std = @import("std"); // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior // :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior @@ -3512,19 +3476,21 @@ const std = @import("std"); // :115:22: error: use of undefined value here causes illegal behavior // :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' -// :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' -// :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior // :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior @@ -3534,19 +3500,25 @@ const std = @import("std"); // :115:22: error: use of undefined value here causes illegal behavior // :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior // :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior @@ -3556,19 +3528,25 @@ const std = @import("std"); // :115:22: error: use of undefined value here causes illegal behavior // :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '1' +// :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior // :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior @@ -3578,11 +3556,17 @@ const std = @import("std"); // :115:22: error: use of undefined value here causes illegal behavior // :115:22: note: when computing vector element at index '0' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior // :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior @@ -3592,19 +3576,25 @@ const std = @import("std"); // :115:22: error: use of undefined value here causes illegal behavior // :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior // :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior @@ -3614,19 +3604,27 @@ const std = @import("std"); // :115:22: error: use of undefined value here causes illegal behavior // :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' +// :115:22: note: when computing vector element at index '1' +// :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior // :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior @@ -3636,37 +3634,32 @@ const std = @import("std"); // :115:22: error: use of undefined value here causes illegal behavior // :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' +// :115:22: note: when computing vector element at index '1' // :115:22: error: use of undefined value here causes illegal behavior -// :115:22: note: when computing vector element at index '0' +// :115:22: note: when computing vector element at index '1' +// :115:22: error: use of undefined value here causes illegal behavior +// :115:22: note: when computing vector element at index '1' +// :121:17: error: use of undefined value here causes illegal behavior // :121:17: error: use of undefined value here causes illegal behavior // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '1' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '1' +// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior @@ -3674,6 +3667,7 @@ const std = @import("std"); // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior +// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior @@ -3681,7 +3675,7 @@ const std = @import("std"); // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '1' +// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior @@ -3689,6 +3683,7 @@ const std = @import("std"); // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior +// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior @@ -3696,7 +3691,7 @@ const std = @import("std"); // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '1' +// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior @@ -3704,6 +3699,7 @@ const std = @import("std"); // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior +// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior @@ -3711,7 +3707,7 @@ const std = @import("std"); // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '1' +// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior @@ -3719,6 +3715,7 @@ const std = @import("std"); // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior +// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior @@ -3726,7 +3723,7 @@ const std = @import("std"); // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '1' +// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior @@ -3734,6 +3731,7 @@ const std = @import("std"); // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior +// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior @@ -3741,7 +3739,7 @@ const std = @import("std"); // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '1' +// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior @@ -3749,6 +3747,7 @@ const std = @import("std"); // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior +// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior @@ -3756,7 +3755,7 @@ const std = @import("std"); // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '1' +// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior @@ -3764,6 +3763,7 @@ const std = @import("std"); // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior +// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior @@ -3771,7 +3771,7 @@ const std = @import("std"); // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '1' +// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior @@ -3779,6 +3779,7 @@ const std = @import("std"); // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior +// :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '0' // :121:17: error: use of undefined value here causes illegal behavior @@ -3788,126 +3789,120 @@ const std = @import("std"); // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '1' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '0' -// :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '0' +// :121:17: note: when computing vector element at index '1' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '0' +// :121:17: note: when computing vector element at index '1' // :121:17: error: use of undefined value here causes illegal behavior +// :121:17: note: when computing vector element at index '1' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '0' +// :121:17: note: when computing vector element at index '1' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '0' +// :121:17: note: when computing vector element at index '1' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '0' +// :121:17: note: when computing vector element at index '1' // :121:17: error: use of undefined value here causes illegal behavior // :121:17: note: when computing vector element at index '1' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '0' +// :121:17: note: when computing vector element at index '1' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '0' +// :121:17: note: when computing vector element at index '1' // :121:17: error: use of undefined value here causes illegal behavior -// :121:17: note: when computing vector element at index '0' +// :121:17: note: when computing vector element at index '1' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '1' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '1' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '1' -// :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior +// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '1' +// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior +// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '1' +// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior +// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '1' +// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior +// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '1' +// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior +// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '1' +// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior +// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '1' +// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior +// :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '0' // :121:21: error: use of undefined value here causes illegal behavior @@ -3915,44 +3910,42 @@ const std = @import("std"); // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '1' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '0' +// :121:21: note: when computing vector element at index '1' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '0' +// :121:21: note: when computing vector element at index '1' // :121:21: error: use of undefined value here causes illegal behavior +// :121:21: note: when computing vector element at index '1' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '0' +// :121:21: note: when computing vector element at index '1' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '0' +// :121:21: note: when computing vector element at index '1' // :121:21: error: use of undefined value here causes illegal behavior // :121:21: note: when computing vector element at index '1' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '0' +// :121:21: note: when computing vector element at index '1' // :121:21: error: use of undefined value here causes illegal behavior -// :121:21: note: when computing vector element at index '0' +// :121:21: note: when computing vector element at index '1' +// :121:21: error: use of undefined value here causes illegal behavior +// :121:21: note: when computing vector element at index '1' +// :121:21: error: use of undefined value here causes illegal behavior +// :121:21: note: when computing vector element at index '1' +// :125:27: error: use of undefined value here causes illegal behavior // :125:27: error: use of undefined value here causes illegal behavior // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '1' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '1' +// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior @@ -3960,6 +3953,7 @@ const std = @import("std"); // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior +// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior @@ -3967,7 +3961,7 @@ const std = @import("std"); // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '1' +// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior @@ -3975,6 +3969,7 @@ const std = @import("std"); // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior +// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior @@ -3982,7 +3977,7 @@ const std = @import("std"); // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '1' +// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior @@ -3990,6 +3985,7 @@ const std = @import("std"); // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior +// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior @@ -3997,7 +3993,7 @@ const std = @import("std"); // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '1' +// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior @@ -4005,6 +4001,7 @@ const std = @import("std"); // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior +// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior @@ -4012,7 +4009,7 @@ const std = @import("std"); // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '1' +// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior @@ -4020,6 +4017,7 @@ const std = @import("std"); // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior +// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior @@ -4027,7 +4025,7 @@ const std = @import("std"); // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '1' +// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior @@ -4035,6 +4033,7 @@ const std = @import("std"); // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior +// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior @@ -4042,7 +4041,7 @@ const std = @import("std"); // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '1' +// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior @@ -4050,6 +4049,7 @@ const std = @import("std"); // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior +// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior @@ -4057,7 +4057,7 @@ const std = @import("std"); // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '1' +// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior @@ -4065,6 +4065,7 @@ const std = @import("std"); // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior +// :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '0' // :125:27: error: use of undefined value here causes illegal behavior @@ -4074,126 +4075,120 @@ const std = @import("std"); // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '1' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '0' -// :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '0' +// :125:27: note: when computing vector element at index '1' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '0' +// :125:27: note: when computing vector element at index '1' // :125:27: error: use of undefined value here causes illegal behavior +// :125:27: note: when computing vector element at index '1' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '0' +// :125:27: note: when computing vector element at index '1' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '0' +// :125:27: note: when computing vector element at index '1' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '0' +// :125:27: note: when computing vector element at index '1' // :125:27: error: use of undefined value here causes illegal behavior // :125:27: note: when computing vector element at index '1' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '0' +// :125:27: note: when computing vector element at index '1' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '0' +// :125:27: note: when computing vector element at index '1' // :125:27: error: use of undefined value here causes illegal behavior -// :125:27: note: when computing vector element at index '0' +// :125:27: note: when computing vector element at index '1' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '1' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '1' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '1' -// :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior +// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '1' +// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior +// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '1' +// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior +// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '1' +// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior +// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '1' +// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior +// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '1' +// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior +// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '1' +// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior +// :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '0' // :125:30: error: use of undefined value here causes illegal behavior @@ -4201,44 +4196,42 @@ const std = @import("std"); // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '1' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '0' +// :125:30: note: when computing vector element at index '1' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '0' +// :125:30: note: when computing vector element at index '1' // :125:30: error: use of undefined value here causes illegal behavior +// :125:30: note: when computing vector element at index '1' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '0' +// :125:30: note: when computing vector element at index '1' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '0' +// :125:30: note: when computing vector element at index '1' // :125:30: error: use of undefined value here causes illegal behavior // :125:30: note: when computing vector element at index '1' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '0' +// :125:30: note: when computing vector element at index '1' // :125:30: error: use of undefined value here causes illegal behavior -// :125:30: note: when computing vector element at index '0' +// :125:30: note: when computing vector element at index '1' +// :125:30: error: use of undefined value here causes illegal behavior +// :125:30: note: when computing vector element at index '1' +// :125:30: error: use of undefined value here causes illegal behavior +// :125:30: note: when computing vector element at index '1' +// :129:27: error: use of undefined value here causes illegal behavior // :129:27: error: use of undefined value here causes illegal behavior // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '1' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '1' +// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior @@ -4246,6 +4239,7 @@ const std = @import("std"); // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior +// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior @@ -4253,7 +4247,7 @@ const std = @import("std"); // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '1' +// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior @@ -4261,6 +4255,7 @@ const std = @import("std"); // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior +// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior @@ -4268,7 +4263,7 @@ const std = @import("std"); // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '1' +// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior @@ -4276,6 +4271,7 @@ const std = @import("std"); // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior +// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior @@ -4283,7 +4279,7 @@ const std = @import("std"); // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '1' +// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior @@ -4291,6 +4287,7 @@ const std = @import("std"); // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior +// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior @@ -4298,7 +4295,7 @@ const std = @import("std"); // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '1' +// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior @@ -4306,6 +4303,7 @@ const std = @import("std"); // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior +// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior @@ -4313,7 +4311,7 @@ const std = @import("std"); // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '1' +// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior @@ -4321,6 +4319,7 @@ const std = @import("std"); // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior +// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior @@ -4328,7 +4327,7 @@ const std = @import("std"); // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '1' +// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior @@ -4336,6 +4335,7 @@ const std = @import("std"); // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior +// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior @@ -4343,7 +4343,7 @@ const std = @import("std"); // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '1' +// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior @@ -4351,6 +4351,7 @@ const std = @import("std"); // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior +// :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '0' // :129:27: error: use of undefined value here causes illegal behavior @@ -4360,126 +4361,120 @@ const std = @import("std"); // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '1' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '0' -// :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '0' +// :129:27: note: when computing vector element at index '1' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '0' +// :129:27: note: when computing vector element at index '1' // :129:27: error: use of undefined value here causes illegal behavior +// :129:27: note: when computing vector element at index '1' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '0' +// :129:27: note: when computing vector element at index '1' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '0' +// :129:27: note: when computing vector element at index '1' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '0' +// :129:27: note: when computing vector element at index '1' // :129:27: error: use of undefined value here causes illegal behavior // :129:27: note: when computing vector element at index '1' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '0' +// :129:27: note: when computing vector element at index '1' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '0' +// :129:27: note: when computing vector element at index '1' // :129:27: error: use of undefined value here causes illegal behavior -// :129:27: note: when computing vector element at index '0' +// :129:27: note: when computing vector element at index '1' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '1' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '1' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '1' -// :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior +// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '1' +// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior +// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '1' +// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior +// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '1' +// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior +// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '1' +// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior +// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '1' +// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior +// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '1' +// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior +// :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '0' // :129:30: error: use of undefined value here causes illegal behavior @@ -4487,44 +4482,42 @@ const std = @import("std"); // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '1' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '0' +// :129:30: note: when computing vector element at index '1' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '0' +// :129:30: note: when computing vector element at index '1' +// :129:30: error: use of undefined value here causes illegal behavior +// :129:30: note: when computing vector element at index '1' // :129:30: error: use of undefined value here causes illegal behavior +// :129:30: note: when computing vector element at index '1' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '0' +// :129:30: note: when computing vector element at index '1' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '0' +// :129:30: note: when computing vector element at index '1' // :129:30: error: use of undefined value here causes illegal behavior // :129:30: note: when computing vector element at index '1' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '0' +// :129:30: note: when computing vector element at index '1' // :129:30: error: use of undefined value here causes illegal behavior -// :129:30: note: when computing vector element at index '0' +// :129:30: note: when computing vector element at index '1' +// :129:30: error: use of undefined value here causes illegal behavior +// :129:30: note: when computing vector element at index '1' +// :133:27: error: use of undefined value here causes illegal behavior // :133:27: error: use of undefined value here causes illegal behavior // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '1' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '1' +// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior @@ -4532,6 +4525,7 @@ const std = @import("std"); // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior +// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior @@ -4539,7 +4533,7 @@ const std = @import("std"); // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '1' +// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior @@ -4547,6 +4541,7 @@ const std = @import("std"); // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior +// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior @@ -4554,7 +4549,7 @@ const std = @import("std"); // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '1' +// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior @@ -4562,6 +4557,7 @@ const std = @import("std"); // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior +// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior @@ -4569,7 +4565,7 @@ const std = @import("std"); // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '1' +// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior @@ -4577,6 +4573,7 @@ const std = @import("std"); // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior +// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior @@ -4584,7 +4581,7 @@ const std = @import("std"); // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '1' +// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior @@ -4592,6 +4589,7 @@ const std = @import("std"); // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior +// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior @@ -4599,7 +4597,7 @@ const std = @import("std"); // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '1' +// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior @@ -4607,6 +4605,7 @@ const std = @import("std"); // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior +// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior @@ -4614,7 +4613,7 @@ const std = @import("std"); // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '1' +// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior @@ -4622,6 +4621,7 @@ const std = @import("std"); // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior +// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior @@ -4629,7 +4629,7 @@ const std = @import("std"); // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '1' +// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior @@ -4637,6 +4637,7 @@ const std = @import("std"); // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior +// :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '0' // :133:27: error: use of undefined value here causes illegal behavior @@ -4646,126 +4647,120 @@ const std = @import("std"); // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '1' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '0' -// :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '0' +// :133:27: note: when computing vector element at index '1' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '0' +// :133:27: note: when computing vector element at index '1' // :133:27: error: use of undefined value here causes illegal behavior +// :133:27: note: when computing vector element at index '1' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '0' +// :133:27: note: when computing vector element at index '1' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '0' +// :133:27: note: when computing vector element at index '1' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '0' +// :133:27: note: when computing vector element at index '1' // :133:27: error: use of undefined value here causes illegal behavior // :133:27: note: when computing vector element at index '1' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '0' +// :133:27: note: when computing vector element at index '1' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '0' +// :133:27: note: when computing vector element at index '1' // :133:27: error: use of undefined value here causes illegal behavior -// :133:27: note: when computing vector element at index '0' +// :133:27: note: when computing vector element at index '1' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '1' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '1' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '1' -// :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior +// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '1' +// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior +// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '1' +// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior +// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '1' +// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior +// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '1' +// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior +// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '1' +// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior +// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '1' +// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior +// :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '0' // :133:30: error: use of undefined value here causes illegal behavior @@ -4773,44 +4768,42 @@ const std = @import("std"); // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '1' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '0' +// :133:30: note: when computing vector element at index '1' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '0' +// :133:30: note: when computing vector element at index '1' // :133:30: error: use of undefined value here causes illegal behavior +// :133:30: note: when computing vector element at index '1' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '0' +// :133:30: note: when computing vector element at index '1' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '0' +// :133:30: note: when computing vector element at index '1' // :133:30: error: use of undefined value here causes illegal behavior // :133:30: note: when computing vector element at index '1' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '0' +// :133:30: note: when computing vector element at index '1' // :133:30: error: use of undefined value here causes illegal behavior -// :133:30: note: when computing vector element at index '0' +// :133:30: note: when computing vector element at index '1' +// :133:30: error: use of undefined value here causes illegal behavior +// :133:30: note: when computing vector element at index '1' +// :133:30: error: use of undefined value here causes illegal behavior +// :133:30: note: when computing vector element at index '1' +// :137:17: error: use of undefined value here causes illegal behavior // :137:17: error: use of undefined value here causes illegal behavior // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '1' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '1' +// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior @@ -4818,6 +4811,7 @@ const std = @import("std"); // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior +// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior @@ -4825,7 +4819,7 @@ const std = @import("std"); // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '1' +// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior @@ -4833,6 +4827,7 @@ const std = @import("std"); // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior +// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior @@ -4840,7 +4835,7 @@ const std = @import("std"); // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '1' +// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior @@ -4848,6 +4843,7 @@ const std = @import("std"); // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior +// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior @@ -4855,7 +4851,7 @@ const std = @import("std"); // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '1' +// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior @@ -4863,6 +4859,7 @@ const std = @import("std"); // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior +// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior @@ -4870,7 +4867,7 @@ const std = @import("std"); // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '1' +// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior @@ -4878,6 +4875,7 @@ const std = @import("std"); // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior +// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior @@ -4885,7 +4883,7 @@ const std = @import("std"); // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '1' +// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior @@ -4893,6 +4891,7 @@ const std = @import("std"); // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior +// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior @@ -4900,7 +4899,7 @@ const std = @import("std"); // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '1' +// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior @@ -4908,6 +4907,7 @@ const std = @import("std"); // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior +// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior @@ -4915,7 +4915,7 @@ const std = @import("std"); // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '1' +// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior @@ -4923,6 +4923,7 @@ const std = @import("std"); // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior +// :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '0' // :137:17: error: use of undefined value here causes illegal behavior @@ -4932,126 +4933,120 @@ const std = @import("std"); // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '1' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '0' -// :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '0' +// :137:17: note: when computing vector element at index '1' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '0' +// :137:17: note: when computing vector element at index '1' // :137:17: error: use of undefined value here causes illegal behavior +// :137:17: note: when computing vector element at index '1' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '0' +// :137:17: note: when computing vector element at index '1' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '0' +// :137:17: note: when computing vector element at index '1' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '0' +// :137:17: note: when computing vector element at index '1' // :137:17: error: use of undefined value here causes illegal behavior // :137:17: note: when computing vector element at index '1' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '0' +// :137:17: note: when computing vector element at index '1' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '0' +// :137:17: note: when computing vector element at index '1' // :137:17: error: use of undefined value here causes illegal behavior -// :137:17: note: when computing vector element at index '0' +// :137:17: note: when computing vector element at index '1' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '1' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '1' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '1' -// :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior +// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '1' +// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior +// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '1' +// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior +// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '1' +// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior +// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '1' +// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior +// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '1' +// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior +// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '1' +// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior +// :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '0' // :137:21: error: use of undefined value here causes illegal behavior @@ -5059,44 +5054,42 @@ const std = @import("std"); // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '1' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '0' +// :137:21: note: when computing vector element at index '1' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '0' +// :137:21: note: when computing vector element at index '1' // :137:21: error: use of undefined value here causes illegal behavior +// :137:21: note: when computing vector element at index '1' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '0' +// :137:21: note: when computing vector element at index '1' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '0' +// :137:21: note: when computing vector element at index '1' // :137:21: error: use of undefined value here causes illegal behavior // :137:21: note: when computing vector element at index '1' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '0' +// :137:21: note: when computing vector element at index '1' // :137:21: error: use of undefined value here causes illegal behavior -// :137:21: note: when computing vector element at index '0' +// :137:21: note: when computing vector element at index '1' +// :137:21: error: use of undefined value here causes illegal behavior +// :137:21: note: when computing vector element at index '1' +// :137:21: error: use of undefined value here causes illegal behavior +// :137:21: note: when computing vector element at index '1' +// :141:22: error: use of undefined value here causes illegal behavior // :141:22: error: use of undefined value here causes illegal behavior // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '1' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '1' +// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior @@ -5104,6 +5097,7 @@ const std = @import("std"); // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior +// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior @@ -5111,7 +5105,7 @@ const std = @import("std"); // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '1' +// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior @@ -5119,6 +5113,7 @@ const std = @import("std"); // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior +// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior @@ -5126,7 +5121,7 @@ const std = @import("std"); // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '1' +// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior @@ -5134,6 +5129,7 @@ const std = @import("std"); // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior +// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior @@ -5141,7 +5137,7 @@ const std = @import("std"); // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '1' +// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior @@ -5149,6 +5145,7 @@ const std = @import("std"); // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior +// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior @@ -5156,7 +5153,7 @@ const std = @import("std"); // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '1' +// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior @@ -5164,6 +5161,7 @@ const std = @import("std"); // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior +// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior @@ -5171,7 +5169,7 @@ const std = @import("std"); // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '1' +// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior @@ -5179,6 +5177,7 @@ const std = @import("std"); // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior +// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior @@ -5186,7 +5185,7 @@ const std = @import("std"); // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '1' +// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior @@ -5194,6 +5193,7 @@ const std = @import("std"); // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior +// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior @@ -5201,7 +5201,7 @@ const std = @import("std"); // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '1' +// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior @@ -5209,6 +5209,7 @@ const std = @import("std"); // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior +// :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '0' // :141:22: error: use of undefined value here causes illegal behavior @@ -5218,126 +5219,120 @@ const std = @import("std"); // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '1' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '0' -// :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '0' +// :141:22: note: when computing vector element at index '1' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '0' +// :141:22: note: when computing vector element at index '1' // :141:22: error: use of undefined value here causes illegal behavior +// :141:22: note: when computing vector element at index '1' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '0' +// :141:22: note: when computing vector element at index '1' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '0' +// :141:22: note: when computing vector element at index '1' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '0' +// :141:22: note: when computing vector element at index '1' // :141:22: error: use of undefined value here causes illegal behavior // :141:22: note: when computing vector element at index '1' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '0' +// :141:22: note: when computing vector element at index '1' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '0' +// :141:22: note: when computing vector element at index '1' // :141:22: error: use of undefined value here causes illegal behavior -// :141:22: note: when computing vector element at index '0' +// :141:22: note: when computing vector element at index '1' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '1' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '1' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '1' -// :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior +// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '1' +// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior +// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '1' +// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior +// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '1' +// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior +// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '1' +// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior +// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '1' +// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior +// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '1' +// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior +// :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '0' // :141:25: error: use of undefined value here causes illegal behavior @@ -5345,44 +5340,42 @@ const std = @import("std"); // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '1' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '0' +// :141:25: note: when computing vector element at index '1' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '0' +// :141:25: note: when computing vector element at index '1' // :141:25: error: use of undefined value here causes illegal behavior +// :141:25: note: when computing vector element at index '1' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '0' +// :141:25: note: when computing vector element at index '1' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '0' +// :141:25: note: when computing vector element at index '1' // :141:25: error: use of undefined value here causes illegal behavior // :141:25: note: when computing vector element at index '1' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '0' +// :141:25: note: when computing vector element at index '1' // :141:25: error: use of undefined value here causes illegal behavior -// :141:25: note: when computing vector element at index '0' +// :141:25: note: when computing vector element at index '1' +// :141:25: error: use of undefined value here causes illegal behavior +// :141:25: note: when computing vector element at index '1' +// :141:25: error: use of undefined value here causes illegal behavior +// :141:25: note: when computing vector element at index '1' +// :145:22: error: use of undefined value here causes illegal behavior // :145:22: error: use of undefined value here causes illegal behavior // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '1' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '1' +// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior @@ -5390,6 +5383,7 @@ const std = @import("std"); // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior +// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior @@ -5397,7 +5391,7 @@ const std = @import("std"); // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '1' +// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior @@ -5405,6 +5399,7 @@ const std = @import("std"); // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior +// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior @@ -5412,7 +5407,7 @@ const std = @import("std"); // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '1' +// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior @@ -5420,6 +5415,7 @@ const std = @import("std"); // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior +// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior @@ -5427,7 +5423,7 @@ const std = @import("std"); // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '1' +// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior @@ -5435,6 +5431,7 @@ const std = @import("std"); // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior +// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior @@ -5442,7 +5439,7 @@ const std = @import("std"); // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '1' +// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior @@ -5450,6 +5447,7 @@ const std = @import("std"); // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior +// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior @@ -5457,7 +5455,7 @@ const std = @import("std"); // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '1' +// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior @@ -5465,6 +5463,7 @@ const std = @import("std"); // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior +// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior @@ -5472,7 +5471,7 @@ const std = @import("std"); // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '1' +// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior @@ -5480,6 +5479,7 @@ const std = @import("std"); // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior +// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior @@ -5487,7 +5487,7 @@ const std = @import("std"); // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '1' +// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior @@ -5495,6 +5495,7 @@ const std = @import("std"); // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior +// :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '0' // :145:22: error: use of undefined value here causes illegal behavior @@ -5504,126 +5505,120 @@ const std = @import("std"); // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '1' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '0' -// :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '0' +// :145:22: note: when computing vector element at index '1' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '0' +// :145:22: note: when computing vector element at index '1' // :145:22: error: use of undefined value here causes illegal behavior +// :145:22: note: when computing vector element at index '1' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '0' +// :145:22: note: when computing vector element at index '1' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '0' +// :145:22: note: when computing vector element at index '1' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '0' +// :145:22: note: when computing vector element at index '1' // :145:22: error: use of undefined value here causes illegal behavior // :145:22: note: when computing vector element at index '1' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '0' +// :145:22: note: when computing vector element at index '1' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '0' +// :145:22: note: when computing vector element at index '1' // :145:22: error: use of undefined value here causes illegal behavior -// :145:22: note: when computing vector element at index '0' +// :145:22: note: when computing vector element at index '1' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '1' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '1' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '1' -// :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior +// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '1' +// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior +// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '1' +// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior +// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '1' +// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior +// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '1' +// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior +// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '1' +// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior +// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '1' +// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior +// :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '0' // :145:25: error: use of undefined value here causes illegal behavior @@ -5631,20 +5626,25 @@ const std = @import("std"); // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '1' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '0' +// :145:25: note: when computing vector element at index '1' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '0' +// :145:25: note: when computing vector element at index '1' +// :145:25: error: use of undefined value here causes illegal behavior +// :145:25: note: when computing vector element at index '1' // :145:25: error: use of undefined value here causes illegal behavior +// :145:25: note: when computing vector element at index '1' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '0' +// :145:25: note: when computing vector element at index '1' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '0' +// :145:25: note: when computing vector element at index '1' // :145:25: error: use of undefined value here causes illegal behavior // :145:25: note: when computing vector element at index '1' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '0' +// :145:25: note: when computing vector element at index '1' // :145:25: error: use of undefined value here causes illegal behavior -// :145:25: note: when computing vector element at index '0' +// :145:25: note: when computing vector element at index '1' +// :145:25: error: use of undefined value here causes illegal behavior +// :145:25: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior @@ -5652,21 +5652,13 @@ const std = @import("std"); // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior @@ -5674,21 +5666,13 @@ const std = @import("std"); // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior @@ -5696,21 +5680,13 @@ const std = @import("std"); // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior @@ -5718,21 +5694,13 @@ const std = @import("std"); // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior @@ -5740,13 +5708,9 @@ const std = @import("std"); // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior // :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior @@ -5756,19 +5720,21 @@ const std = @import("std"); // :151:21: error: use of undefined value here causes illegal behavior // :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' -// :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' -// :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior // :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior @@ -5778,19 +5744,25 @@ const std = @import("std"); // :151:21: error: use of undefined value here causes illegal behavior // :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior // :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior @@ -5800,19 +5772,25 @@ const std = @import("std"); // :151:21: error: use of undefined value here causes illegal behavior // :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '1' +// :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior // :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior @@ -5822,11 +5800,17 @@ const std = @import("std"); // :151:21: error: use of undefined value here causes illegal behavior // :151:21: note: when computing vector element at index '0' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior // :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior @@ -5836,19 +5820,25 @@ const std = @import("std"); // :151:21: error: use of undefined value here causes illegal behavior // :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior // :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior @@ -5858,19 +5848,25 @@ const std = @import("std"); // :151:21: error: use of undefined value here causes illegal behavior // :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior // :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior @@ -5880,13 +5876,17 @@ const std = @import("std"); // :151:21: error: use of undefined value here causes illegal behavior // :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' +// :151:21: note: when computing vector element at index '1' // :151:21: error: use of undefined value here causes illegal behavior -// :151:21: note: when computing vector element at index '0' +// :151:21: note: when computing vector element at index '1' +// :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' +// :151:21: error: use of undefined value here causes illegal behavior +// :151:21: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior @@ -5894,21 +5894,13 @@ const std = @import("std"); // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior @@ -5916,21 +5908,13 @@ const std = @import("std"); // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior @@ -5938,21 +5922,13 @@ const std = @import("std"); // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior @@ -5960,21 +5936,13 @@ const std = @import("std"); // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior @@ -5982,13 +5950,9 @@ const std = @import("std"); // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior // :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior @@ -5998,19 +5962,21 @@ const std = @import("std"); // :155:30: error: use of undefined value here causes illegal behavior // :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' -// :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' -// :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior // :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior @@ -6020,19 +5986,25 @@ const std = @import("std"); // :155:30: error: use of undefined value here causes illegal behavior // :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior // :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior @@ -6042,19 +6014,25 @@ const std = @import("std"); // :155:30: error: use of undefined value here causes illegal behavior // :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '1' +// :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior // :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior @@ -6064,11 +6042,17 @@ const std = @import("std"); // :155:30: error: use of undefined value here causes illegal behavior // :155:30: note: when computing vector element at index '0' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior // :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior @@ -6078,19 +6062,25 @@ const std = @import("std"); // :155:30: error: use of undefined value here causes illegal behavior // :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior // :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior @@ -6100,19 +6090,25 @@ const std = @import("std"); // :155:30: error: use of undefined value here causes illegal behavior // :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior // :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior @@ -6122,13 +6118,17 @@ const std = @import("std"); // :155:30: error: use of undefined value here causes illegal behavior // :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' +// :155:30: note: when computing vector element at index '1' // :155:30: error: use of undefined value here causes illegal behavior -// :155:30: note: when computing vector element at index '0' +// :155:30: note: when computing vector element at index '1' +// :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' +// :155:30: error: use of undefined value here causes illegal behavior +// :155:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior @@ -6136,21 +6136,13 @@ const std = @import("std"); // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior @@ -6158,21 +6150,13 @@ const std = @import("std"); // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior @@ -6180,21 +6164,13 @@ const std = @import("std"); // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior @@ -6202,21 +6178,13 @@ const std = @import("std"); // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior @@ -6224,13 +6192,9 @@ const std = @import("std"); // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior // :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior @@ -6240,19 +6204,21 @@ const std = @import("std"); // :159:30: error: use of undefined value here causes illegal behavior // :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' -// :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' -// :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior // :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior @@ -6262,19 +6228,25 @@ const std = @import("std"); // :159:30: error: use of undefined value here causes illegal behavior // :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior // :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior @@ -6284,19 +6256,25 @@ const std = @import("std"); // :159:30: error: use of undefined value here causes illegal behavior // :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '1' +// :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior // :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior @@ -6306,11 +6284,17 @@ const std = @import("std"); // :159:30: error: use of undefined value here causes illegal behavior // :159:30: note: when computing vector element at index '0' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior // :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior @@ -6320,19 +6304,25 @@ const std = @import("std"); // :159:30: error: use of undefined value here causes illegal behavior // :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior // :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior @@ -6342,19 +6332,27 @@ const std = @import("std"); // :159:30: error: use of undefined value here causes illegal behavior // :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' +// :159:30: note: when computing vector element at index '1' +// :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior // :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior @@ -6364,13 +6362,15 @@ const std = @import("std"); // :159:30: error: use of undefined value here causes illegal behavior // :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' +// :159:30: note: when computing vector element at index '1' // :159:30: error: use of undefined value here causes illegal behavior -// :159:30: note: when computing vector element at index '0' +// :159:30: note: when computing vector element at index '1' +// :159:30: error: use of undefined value here causes illegal behavior +// :159:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior @@ -6378,21 +6378,13 @@ const std = @import("std"); // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior @@ -6400,21 +6392,13 @@ const std = @import("std"); // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior @@ -6422,21 +6406,13 @@ const std = @import("std"); // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior @@ -6444,21 +6420,13 @@ const std = @import("std"); // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior @@ -6466,13 +6434,9 @@ const std = @import("std"); // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior // :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior @@ -6482,19 +6446,21 @@ const std = @import("std"); // :163:30: error: use of undefined value here causes illegal behavior // :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' -// :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' -// :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior // :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior @@ -6504,19 +6470,25 @@ const std = @import("std"); // :163:30: error: use of undefined value here causes illegal behavior // :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior // :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior @@ -6526,19 +6498,25 @@ const std = @import("std"); // :163:30: error: use of undefined value here causes illegal behavior // :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '1' +// :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior // :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior @@ -6548,11 +6526,19 @@ const std = @import("std"); // :163:30: error: use of undefined value here causes illegal behavior // :163:30: note: when computing vector element at index '0' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' +// :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior // :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior @@ -6562,19 +6548,27 @@ const std = @import("std"); // :163:30: error: use of undefined value here causes illegal behavior // :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' +// :163:30: note: when computing vector element at index '1' +// :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior // :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior @@ -6584,19 +6578,25 @@ const std = @import("std"); // :163:30: error: use of undefined value here causes illegal behavior // :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior // :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior @@ -6606,13 +6606,13 @@ const std = @import("std"); // :163:30: error: use of undefined value here causes illegal behavior // :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' +// :163:30: note: when computing vector element at index '1' // :163:30: error: use of undefined value here causes illegal behavior -// :163:30: note: when computing vector element at index '0' +// :163:30: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior @@ -6620,21 +6620,13 @@ const std = @import("std"); // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior @@ -6642,21 +6634,13 @@ const std = @import("std"); // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior @@ -6664,21 +6648,13 @@ const std = @import("std"); // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior @@ -6686,21 +6662,13 @@ const std = @import("std"); // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior @@ -6708,13 +6676,9 @@ const std = @import("std"); // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior // :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior @@ -6724,19 +6688,21 @@ const std = @import("std"); // :167:25: error: use of undefined value here causes illegal behavior // :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' -// :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' -// :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior // :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior @@ -6746,19 +6712,25 @@ const std = @import("std"); // :167:25: error: use of undefined value here causes illegal behavior // :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior // :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior @@ -6768,19 +6740,25 @@ const std = @import("std"); // :167:25: error: use of undefined value here causes illegal behavior // :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '1' +// :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior // :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior @@ -6790,11 +6768,21 @@ const std = @import("std"); // :167:25: error: use of undefined value here causes illegal behavior // :167:25: note: when computing vector element at index '0' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' +// :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' +// :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior // :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior @@ -6804,19 +6792,25 @@ const std = @import("std"); // :167:25: error: use of undefined value here causes illegal behavior // :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior // :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior @@ -6826,19 +6820,25 @@ const std = @import("std"); // :167:25: error: use of undefined value here causes illegal behavior // :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior // :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior @@ -6848,13 +6848,13 @@ const std = @import("std"); // :167:25: error: use of undefined value here causes illegal behavior // :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' +// :167:25: note: when computing vector element at index '1' // :167:25: error: use of undefined value here causes illegal behavior -// :167:25: note: when computing vector element at index '0' +// :167:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior @@ -6862,21 +6862,13 @@ const std = @import("std"); // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior @@ -6884,21 +6876,13 @@ const std = @import("std"); // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior @@ -6906,21 +6890,13 @@ const std = @import("std"); // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior @@ -6928,21 +6904,13 @@ const std = @import("std"); // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior @@ -6950,13 +6918,9 @@ const std = @import("std"); // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior // :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior @@ -6966,19 +6930,21 @@ const std = @import("std"); // :171:25: error: use of undefined value here causes illegal behavior // :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' -// :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' -// :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior // :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior @@ -6988,19 +6954,25 @@ const std = @import("std"); // :171:25: error: use of undefined value here causes illegal behavior // :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior // :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior @@ -7010,19 +6982,25 @@ const std = @import("std"); // :171:25: error: use of undefined value here causes illegal behavior // :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '1' +// :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior // :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior @@ -7032,11 +7010,17 @@ const std = @import("std"); // :171:25: error: use of undefined value here causes illegal behavior // :171:25: note: when computing vector element at index '0' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior // :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior @@ -7046,19 +7030,25 @@ const std = @import("std"); // :171:25: error: use of undefined value here causes illegal behavior // :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior // :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior @@ -7068,19 +7058,25 @@ const std = @import("std"); // :171:25: error: use of undefined value here causes illegal behavior // :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior // :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior @@ -7090,37 +7086,33 @@ const std = @import("std"); // :171:25: error: use of undefined value here causes illegal behavior // :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' +// :171:25: note: when computing vector element at index '1' // :171:25: error: use of undefined value here causes illegal behavior -// :171:25: note: when computing vector element at index '0' +// :171:25: note: when computing vector element at index '1' +// :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' +// :171:25: error: use of undefined value here causes illegal behavior +// :171:25: note: when computing vector element at index '1' // :177:17: error: use of undefined value here causes illegal behavior // :177:17: error: use of undefined value here causes illegal behavior // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '1' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '1' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior +// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior +// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior // :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior @@ -7130,9 +7122,9 @@ const std = @import("std"); // :177:17: error: use of undefined value here causes illegal behavior // :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '1' +// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '1' +// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior // :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior @@ -7142,7 +7134,9 @@ const std = @import("std"); // :177:17: error: use of undefined value here causes illegal behavior // :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior +// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior +// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior // :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior @@ -7152,9 +7146,9 @@ const std = @import("std"); // :177:17: error: use of undefined value here causes illegal behavior // :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '1' +// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '1' +// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior // :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior @@ -7164,7 +7158,9 @@ const std = @import("std"); // :177:17: error: use of undefined value here causes illegal behavior // :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior +// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior +// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior // :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior @@ -7174,9 +7170,9 @@ const std = @import("std"); // :177:17: error: use of undefined value here causes illegal behavior // :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '1' +// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '1' +// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior // :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior @@ -7186,7 +7182,9 @@ const std = @import("std"); // :177:17: error: use of undefined value here causes illegal behavior // :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior +// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior +// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior // :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior @@ -7196,9 +7194,9 @@ const std = @import("std"); // :177:17: error: use of undefined value here causes illegal behavior // :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '1' +// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '1' +// :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior // :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior @@ -7208,27 +7206,29 @@ const std = @import("std"); // :177:17: error: use of undefined value here causes illegal behavior // :177:17: note: when computing vector element at index '0' // :177:17: error: use of undefined value here causes illegal behavior +// :177:17: note: when computing vector element at index '1' // :177:17: error: use of undefined value here causes illegal behavior +// :177:17: note: when computing vector element at index '1' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '0' +// :177:17: note: when computing vector element at index '1' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '0' +// :177:17: note: when computing vector element at index '1' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '0' +// :177:17: note: when computing vector element at index '1' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '0' +// :177:17: note: when computing vector element at index '1' // :177:17: error: use of undefined value here causes illegal behavior // :177:17: note: when computing vector element at index '1' // :177:17: error: use of undefined value here causes illegal behavior // :177:17: note: when computing vector element at index '1' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '0' +// :177:17: note: when computing vector element at index '1' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '0' +// :177:17: note: when computing vector element at index '1' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '0' +// :177:17: note: when computing vector element at index '1' // :177:17: error: use of undefined value here causes illegal behavior -// :177:17: note: when computing vector element at index '0' +// :177:17: note: when computing vector element at index '1' // :177:21: error: use of undefined value here causes illegal behavior // :177:21: note: when computing vector element at index '0' // :177:21: error: use of undefined value here causes illegal behavior @@ -7256,27 +7256,19 @@ const std = @import("std"); // :180:17: error: use of undefined value here causes illegal behavior // :180:17: error: use of undefined value here causes illegal behavior // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '1' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '1' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior +// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior +// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior // :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior @@ -7286,9 +7278,9 @@ const std = @import("std"); // :180:17: error: use of undefined value here causes illegal behavior // :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '1' +// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '1' +// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior // :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior @@ -7298,7 +7290,9 @@ const std = @import("std"); // :180:17: error: use of undefined value here causes illegal behavior // :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior +// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior +// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior // :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior @@ -7308,9 +7302,9 @@ const std = @import("std"); // :180:17: error: use of undefined value here causes illegal behavior // :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '1' +// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '1' +// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior // :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior @@ -7320,7 +7314,9 @@ const std = @import("std"); // :180:17: error: use of undefined value here causes illegal behavior // :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior +// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior +// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior // :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior @@ -7330,9 +7326,9 @@ const std = @import("std"); // :180:17: error: use of undefined value here causes illegal behavior // :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '1' +// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '1' +// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior // :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior @@ -7342,7 +7338,9 @@ const std = @import("std"); // :180:17: error: use of undefined value here causes illegal behavior // :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior +// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior +// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior // :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior @@ -7352,9 +7350,9 @@ const std = @import("std"); // :180:17: error: use of undefined value here causes illegal behavior // :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '1' +// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '1' +// :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior // :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior @@ -7364,27 +7362,29 @@ const std = @import("std"); // :180:17: error: use of undefined value here causes illegal behavior // :180:17: note: when computing vector element at index '0' // :180:17: error: use of undefined value here causes illegal behavior +// :180:17: note: when computing vector element at index '1' // :180:17: error: use of undefined value here causes illegal behavior +// :180:17: note: when computing vector element at index '1' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '0' +// :180:17: note: when computing vector element at index '1' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '0' +// :180:17: note: when computing vector element at index '1' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '0' +// :180:17: note: when computing vector element at index '1' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '0' +// :180:17: note: when computing vector element at index '1' // :180:17: error: use of undefined value here causes illegal behavior // :180:17: note: when computing vector element at index '1' // :180:17: error: use of undefined value here causes illegal behavior // :180:17: note: when computing vector element at index '1' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '0' +// :180:17: note: when computing vector element at index '1' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '0' +// :180:17: note: when computing vector element at index '1' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '0' +// :180:17: note: when computing vector element at index '1' // :180:17: error: use of undefined value here causes illegal behavior -// :180:17: note: when computing vector element at index '0' +// :180:17: note: when computing vector element at index '1' // :180:21: error: use of undefined value here causes illegal behavior // :180:21: note: when computing vector element at index '0' // :180:21: error: use of undefined value here causes illegal behavior @@ -7412,27 +7412,19 @@ const std = @import("std"); // :183:17: error: use of undefined value here causes illegal behavior // :183:17: error: use of undefined value here causes illegal behavior // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '1' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '1' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior +// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior +// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior // :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior @@ -7442,9 +7434,9 @@ const std = @import("std"); // :183:17: error: use of undefined value here causes illegal behavior // :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '1' +// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '1' +// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior // :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior @@ -7454,7 +7446,9 @@ const std = @import("std"); // :183:17: error: use of undefined value here causes illegal behavior // :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior +// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior +// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior // :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior @@ -7464,9 +7458,9 @@ const std = @import("std"); // :183:17: error: use of undefined value here causes illegal behavior // :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '1' +// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '1' +// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior // :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior @@ -7476,7 +7470,9 @@ const std = @import("std"); // :183:17: error: use of undefined value here causes illegal behavior // :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior +// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior +// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior // :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior @@ -7486,9 +7482,9 @@ const std = @import("std"); // :183:17: error: use of undefined value here causes illegal behavior // :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '1' +// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '1' +// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior // :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior @@ -7498,7 +7494,9 @@ const std = @import("std"); // :183:17: error: use of undefined value here causes illegal behavior // :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior +// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior +// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior // :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior @@ -7508,9 +7506,9 @@ const std = @import("std"); // :183:17: error: use of undefined value here causes illegal behavior // :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '1' +// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '1' +// :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior // :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior @@ -7520,27 +7518,29 @@ const std = @import("std"); // :183:17: error: use of undefined value here causes illegal behavior // :183:17: note: when computing vector element at index '0' // :183:17: error: use of undefined value here causes illegal behavior +// :183:17: note: when computing vector element at index '1' // :183:17: error: use of undefined value here causes illegal behavior +// :183:17: note: when computing vector element at index '1' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '0' +// :183:17: note: when computing vector element at index '1' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '0' +// :183:17: note: when computing vector element at index '1' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '0' +// :183:17: note: when computing vector element at index '1' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '0' +// :183:17: note: when computing vector element at index '1' // :183:17: error: use of undefined value here causes illegal behavior // :183:17: note: when computing vector element at index '1' // :183:17: error: use of undefined value here causes illegal behavior // :183:17: note: when computing vector element at index '1' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '0' +// :183:17: note: when computing vector element at index '1' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '0' +// :183:17: note: when computing vector element at index '1' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '0' +// :183:17: note: when computing vector element at index '1' // :183:17: error: use of undefined value here causes illegal behavior -// :183:17: note: when computing vector element at index '0' +// :183:17: note: when computing vector element at index '1' // :183:21: error: use of undefined value here causes illegal behavior // :183:21: note: when computing vector element at index '0' // :183:21: error: use of undefined value here causes illegal behavior diff --git a/test/cases/compile_errors/undef_arith_returns_undef.zig b/test/cases/compile_errors/undef_arith_returns_undef.zig index 4c2c096b98ebc47c05bc9246e08e047d1b312119..40dbe1671523e24358e9260f9d90a9ef70afdbec 100644 --- a/test/cases/compile_errors/undef_arith_returns_undef.zig +++ b/test/cases/compile_errors/undef_arith_returns_undef.zig @@ -681,810 +681,260 @@ inline fn testFloatWithValue(comptime Float: type, x: Float) void { // @as(@Vector(2, u8), undefined) // @as(@Vector(2, u8), [runtime value]) // @as(@Vector(2, u8), [runtime value]) -// @as(i8, undefined) -// @as(i8, undefined) -// @as(@Vector(2, i8), .{ 6, undefined }) -// @as(@Vector(2, i8), .{ undefined, 6 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ 6, undefined }) -// @as(@Vector(2, i8), .{ 6, undefined }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ undefined, 6 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ undefined, 6 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(i8, undefined) -// @as(i8, undefined) -// @as(@Vector(2, i8), .{ 6, undefined }) -// @as(@Vector(2, i8), .{ undefined, 6 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ 6, undefined }) -// @as(@Vector(2, i8), .{ 6, undefined }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ undefined, 6 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ undefined, 6 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(i8, undefined) -// @as(i8, undefined) -// @as(@Vector(2, i8), .{ 0, undefined }) -// @as(@Vector(2, i8), .{ undefined, 0 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ 0, undefined }) -// @as(@Vector(2, i8), .{ 0, undefined }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ undefined, 0 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ undefined, 0 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(i8, undefined) -// @as(i8, undefined) -// @as(@Vector(2, i8), .{ 0, undefined }) -// @as(@Vector(2, i8), .{ undefined, 0 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ 0, undefined }) -// @as(@Vector(2, i8), .{ 0, undefined }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ undefined, 0 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ undefined, 0 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(i8, undefined) -// @as(i8, undefined) -// @as(@Vector(2, i8), .{ 9, undefined }) -// @as(@Vector(2, i8), .{ undefined, 9 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ 9, undefined }) -// @as(@Vector(2, i8), .{ 9, undefined }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ undefined, 9 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ undefined, 9 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(i8, undefined) -// @as(i8, undefined) -// @as(@Vector(2, i8), .{ 9, undefined }) -// @as(@Vector(2, i8), .{ undefined, 9 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ 9, undefined }) -// @as(@Vector(2, i8), .{ 9, undefined }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ undefined, 9 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ undefined, 9 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(i8, undefined) -// @as(i8, undefined) -// @as(@Vector(2, i8), .{ 0, undefined }) -// @as(@Vector(2, i8), .{ undefined, 0 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ 0, undefined }) -// @as(@Vector(2, i8), .{ 0, undefined }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ undefined, 0 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), .{ undefined, 0 }) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(i8, undefined) -// @as(@Vector(2, i8), undefined) -// @as(i8, undefined) -// @as(i8, undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(i8, undefined) -// @as(@Vector(2, i8), undefined) -// @as(i8, undefined) -// @as(i8, undefined) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(i8, undefined) -// @as(i8, undefined) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(i8, undefined) -// @as(i8, undefined) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(i8, undefined) -// @as(i8, undefined) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(i8, undefined) -// @as(i8, undefined) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(i8, undefined) -// @as(i8, undefined) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(i8, [runtime value]) -// @as(i8, [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), [runtime value]) -// @as(@Vector(2, i8), undefined) -// @as(i8, undefined) -// @as(@Vector(2, i8), undefined) -// @as(i8, undefined) -// @as(i8, undefined) -// @as(@Vector(2, i8), undefined) -// @as(@Vector(2, i8), undefined) -// @as(i8, undefined) -// @as(@Vector(2, i8), undefined) -// @as(u32, undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), .{ 6, undefined }) -// @as(@Vector(2, u32), .{ undefined, 6 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ 6, undefined }) -// @as(@Vector(2, u32), .{ 6, undefined }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ undefined, 6 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ undefined, 6 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(u32, undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), .{ 6, undefined }) -// @as(@Vector(2, u32), .{ undefined, 6 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ 6, undefined }) -// @as(@Vector(2, u32), .{ 6, undefined }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ undefined, 6 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ undefined, 6 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(u32, undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), .{ 0, undefined }) -// @as(@Vector(2, u32), .{ undefined, 0 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ 0, undefined }) -// @as(@Vector(2, u32), .{ 0, undefined }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ undefined, 0 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ undefined, 0 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(u32, undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), .{ 0, undefined }) -// @as(@Vector(2, u32), .{ undefined, 0 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ 0, undefined }) -// @as(@Vector(2, u32), .{ 0, undefined }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ undefined, 0 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ undefined, 0 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(u32, undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), .{ 9, undefined }) -// @as(@Vector(2, u32), .{ undefined, 9 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ 9, undefined }) -// @as(@Vector(2, u32), .{ 9, undefined }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ undefined, 9 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ undefined, 9 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(u32, undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), .{ 9, undefined }) -// @as(@Vector(2, u32), .{ undefined, 9 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ 9, undefined }) -// @as(@Vector(2, u32), .{ 9, undefined }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ undefined, 9 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ undefined, 9 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(u32, undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), .{ 24, undefined }) -// @as(@Vector(2, u32), .{ undefined, 24 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ 24, undefined }) -// @as(@Vector(2, u32), .{ 24, undefined }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ undefined, 24 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ undefined, 24 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(u32, undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), .{ 0, undefined }) -// @as(@Vector(2, u32), .{ undefined, 0 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ 0, undefined }) -// @as(@Vector(2, u32), .{ 0, undefined }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ undefined, 0 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), .{ undefined, 0 }) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), undefined) -// @as(u32, undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(u1, undefined) -// @as(@Vector(2, u1), .{ 1, undefined }) -// @as(@Vector(2, u1), .{ undefined, 1 }) -// @as(@Vector(2, u1), undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), undefined) -// @as(u32, undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(u32, undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(u32, undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(u32, undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(u32, undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(u32, undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(u32, undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(u32, [runtime value]) -// @as(u32, [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), [runtime value]) -// @as(@Vector(2, u32), undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), undefined) -// @as(u32, undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), undefined) -// @as(@Vector(2, u32), undefined) -// @as(u1, undefined) -// @as(@Vector(2, u1), [runtime value]) -// @as(@Vector(2, u1), [runtime value]) -// @as(@Vector(2, u1), undefined) -// @as(u32, undefined) -// @as(@Vector(2, u32), undefined) -// @as(i32, undefined) -// @as(i32, undefined) -// @as(@Vector(2, i32), .{ 6, undefined }) -// @as(@Vector(2, i32), .{ undefined, 6 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ 6, undefined }) -// @as(@Vector(2, i32), .{ 6, undefined }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ undefined, 6 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ undefined, 6 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(i32, undefined) -// @as(i32, undefined) -// @as(@Vector(2, i32), .{ 6, undefined }) -// @as(@Vector(2, i32), .{ undefined, 6 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ 6, undefined }) -// @as(@Vector(2, i32), .{ 6, undefined }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ undefined, 6 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ undefined, 6 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(i32, undefined) -// @as(i32, undefined) -// @as(@Vector(2, i32), .{ 0, undefined }) -// @as(@Vector(2, i32), .{ undefined, 0 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ 0, undefined }) -// @as(@Vector(2, i32), .{ 0, undefined }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ undefined, 0 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ undefined, 0 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(i32, undefined) -// @as(i32, undefined) -// @as(@Vector(2, i32), .{ 0, undefined }) -// @as(@Vector(2, i32), .{ undefined, 0 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ 0, undefined }) -// @as(@Vector(2, i32), .{ 0, undefined }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ undefined, 0 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ undefined, 0 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(i32, undefined) -// @as(i32, undefined) -// @as(@Vector(2, i32), .{ 9, undefined }) -// @as(@Vector(2, i32), .{ undefined, 9 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ 9, undefined }) -// @as(@Vector(2, i32), .{ 9, undefined }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ undefined, 9 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ undefined, 9 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(i32, undefined) -// @as(i32, undefined) -// @as(@Vector(2, i32), .{ 9, undefined }) -// @as(@Vector(2, i32), .{ undefined, 9 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ 9, undefined }) -// @as(@Vector(2, i32), .{ 9, undefined }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ undefined, 9 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ undefined, 9 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(i32, undefined) -// @as(i32, undefined) -// @as(@Vector(2, i32), .{ 0, undefined }) -// @as(@Vector(2, i32), .{ undefined, 0 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ 0, undefined }) -// @as(@Vector(2, i32), .{ 0, undefined }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ undefined, 0 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), .{ undefined, 0 }) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(i32, undefined) -// @as(@Vector(2, i32), undefined) -// @as(i32, undefined) -// @as(i32, undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(i32, undefined) -// @as(@Vector(2, i32), undefined) -// @as(i32, undefined) -// @as(i32, undefined) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(i32, undefined) -// @as(i32, undefined) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(i32, undefined) -// @as(i32, undefined) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(i32, undefined) -// @as(i32, undefined) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(i32, undefined) -// @as(i32, undefined) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(i32, undefined) -// @as(i32, undefined) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(i32, [runtime value]) -// @as(i32, [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), [runtime value]) -// @as(@Vector(2, i32), undefined) -// @as(i32, undefined) -// @as(@Vector(2, i32), undefined) -// @as(i32, undefined) -// @as(i32, undefined) -// @as(@Vector(2, i32), undefined) -// @as(@Vector(2, i32), undefined) -// @as(i32, undefined) -// @as(@Vector(2, i32), undefined) +// @as(i500, undefined) +// @as(i500, undefined) +// @as(@Vector(2, i500), .{ 6, undefined }) +// @as(@Vector(2, i500), .{ undefined, 6 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ 6, undefined }) +// @as(@Vector(2, i500), .{ 6, undefined }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ undefined, 6 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ undefined, 6 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(i500, undefined) +// @as(i500, undefined) +// @as(@Vector(2, i500), .{ 6, undefined }) +// @as(@Vector(2, i500), .{ undefined, 6 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ 6, undefined }) +// @as(@Vector(2, i500), .{ 6, undefined }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ undefined, 6 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ undefined, 6 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(i500, undefined) +// @as(i500, undefined) +// @as(@Vector(2, i500), .{ 0, undefined }) +// @as(@Vector(2, i500), .{ undefined, 0 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ 0, undefined }) +// @as(@Vector(2, i500), .{ 0, undefined }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ undefined, 0 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ undefined, 0 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(i500, undefined) +// @as(i500, undefined) +// @as(@Vector(2, i500), .{ 0, undefined }) +// @as(@Vector(2, i500), .{ undefined, 0 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ 0, undefined }) +// @as(@Vector(2, i500), .{ 0, undefined }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ undefined, 0 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ undefined, 0 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(i500, undefined) +// @as(i500, undefined) +// @as(@Vector(2, i500), .{ 9, undefined }) +// @as(@Vector(2, i500), .{ undefined, 9 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ 9, undefined }) +// @as(@Vector(2, i500), .{ 9, undefined }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ undefined, 9 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ undefined, 9 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(i500, undefined) +// @as(i500, undefined) +// @as(@Vector(2, i500), .{ 9, undefined }) +// @as(@Vector(2, i500), .{ undefined, 9 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ 9, undefined }) +// @as(@Vector(2, i500), .{ 9, undefined }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ undefined, 9 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ undefined, 9 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(i500, undefined) +// @as(i500, undefined) +// @as(@Vector(2, i500), .{ 0, undefined }) +// @as(@Vector(2, i500), .{ undefined, 0 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ 0, undefined }) +// @as(@Vector(2, i500), .{ 0, undefined }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ undefined, 0 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), .{ undefined, 0 }) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(i500, undefined) +// @as(@Vector(2, i500), undefined) +// @as(i500, undefined) +// @as(i500, undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(i500, undefined) +// @as(@Vector(2, i500), undefined) +// @as(i500, undefined) +// @as(i500, undefined) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(i500, undefined) +// @as(i500, undefined) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(i500, undefined) +// @as(i500, undefined) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(i500, undefined) +// @as(i500, undefined) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(i500, undefined) +// @as(i500, undefined) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(i500, undefined) +// @as(i500, undefined) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(i500, [runtime value]) +// @as(i500, [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), [runtime value]) +// @as(@Vector(2, i500), undefined) +// @as(i500, undefined) +// @as(@Vector(2, i500), undefined) +// @as(i500, undefined) +// @as(i500, undefined) +// @as(@Vector(2, i500), undefined) +// @as(@Vector(2, i500), undefined) +// @as(i500, undefined) +// @as(@Vector(2, i500), undefined) // @as(u500, undefined) // @as(u500, undefined) // @as(@Vector(2, u500), .{ 6, undefined }) @@ -1779,702 +1229,812 @@ inline fn testFloatWithValue(comptime Float: type, x: Float) void { // @as(@Vector(2, u1), [runtime value]) // @as(@Vector(2, u1), [runtime value]) // @as(@Vector(2, u1), undefined) -// @as(u500, undefined) -// @as(@Vector(2, u500), undefined) -// @as(i500, undefined) -// @as(i500, undefined) -// @as(@Vector(2, i500), .{ 6, undefined }) -// @as(@Vector(2, i500), .{ undefined, 6 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ 6, undefined }) -// @as(@Vector(2, i500), .{ 6, undefined }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ undefined, 6 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ undefined, 6 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(i500, undefined) -// @as(i500, undefined) -// @as(@Vector(2, i500), .{ 6, undefined }) -// @as(@Vector(2, i500), .{ undefined, 6 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ 6, undefined }) -// @as(@Vector(2, i500), .{ 6, undefined }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ undefined, 6 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ undefined, 6 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(i500, undefined) -// @as(i500, undefined) -// @as(@Vector(2, i500), .{ 0, undefined }) -// @as(@Vector(2, i500), .{ undefined, 0 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ 0, undefined }) -// @as(@Vector(2, i500), .{ 0, undefined }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ undefined, 0 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ undefined, 0 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(i500, undefined) -// @as(i500, undefined) -// @as(@Vector(2, i500), .{ 0, undefined }) -// @as(@Vector(2, i500), .{ undefined, 0 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ 0, undefined }) -// @as(@Vector(2, i500), .{ 0, undefined }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ undefined, 0 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ undefined, 0 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(i500, undefined) -// @as(i500, undefined) -// @as(@Vector(2, i500), .{ 9, undefined }) -// @as(@Vector(2, i500), .{ undefined, 9 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ 9, undefined }) -// @as(@Vector(2, i500), .{ 9, undefined }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ undefined, 9 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ undefined, 9 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(i500, undefined) -// @as(i500, undefined) -// @as(@Vector(2, i500), .{ 9, undefined }) -// @as(@Vector(2, i500), .{ undefined, 9 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ 9, undefined }) -// @as(@Vector(2, i500), .{ 9, undefined }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ undefined, 9 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ undefined, 9 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(i500, undefined) -// @as(i500, undefined) -// @as(@Vector(2, i500), .{ 0, undefined }) -// @as(@Vector(2, i500), .{ undefined, 0 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ 0, undefined }) -// @as(@Vector(2, i500), .{ 0, undefined }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ undefined, 0 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), .{ undefined, 0 }) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(i500, undefined) -// @as(@Vector(2, i500), undefined) -// @as(i500, undefined) -// @as(i500, undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(i500, undefined) -// @as(@Vector(2, i500), undefined) -// @as(i500, undefined) -// @as(i500, undefined) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(i500, undefined) -// @as(i500, undefined) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(i500, undefined) -// @as(i500, undefined) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(i500, undefined) -// @as(i500, undefined) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(i500, undefined) -// @as(i500, undefined) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(i500, undefined) -// @as(i500, undefined) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(i500, [runtime value]) -// @as(i500, [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), [runtime value]) -// @as(@Vector(2, i500), undefined) -// @as(i500, undefined) -// @as(@Vector(2, i500), undefined) -// @as(i500, undefined) -// @as(i500, undefined) -// @as(@Vector(2, i500), undefined) -// @as(@Vector(2, i500), undefined) -// @as(i500, undefined) -// @as(@Vector(2, i500), undefined) -// @as(f16, undefined) -// @as(f16, undefined) -// @as(@Vector(2, f16), .{ 6, undefined }) -// @as(@Vector(2, f16), .{ undefined, 6 }) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), .{ 6, undefined }) -// @as(@Vector(2, f16), .{ 6, undefined }) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), .{ undefined, 6 }) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), .{ undefined, 6 }) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(f16, undefined) -// @as(f16, undefined) -// @as(@Vector(2, f16), .{ 0, undefined }) -// @as(@Vector(2, f16), .{ undefined, 0 }) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), .{ 0, undefined }) -// @as(@Vector(2, f16), .{ 0, undefined }) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), .{ undefined, 0 }) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), .{ undefined, 0 }) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(f16, undefined) -// @as(f16, undefined) -// @as(@Vector(2, f16), .{ 9, undefined }) -// @as(@Vector(2, f16), .{ undefined, 9 }) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), .{ 9, undefined }) -// @as(@Vector(2, f16), .{ 9, undefined }) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), .{ undefined, 9 }) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), .{ undefined, 9 }) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(f16, undefined) -// @as(@Vector(2, f16), .{ -3, undefined }) -// @as(@Vector(2, f16), .{ undefined, -3 }) -// @as(@Vector(2, f16), undefined) -// @as(f16, undefined) -// @as(f16, undefined) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(f16, undefined) -// @as(f16, undefined) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(f16, undefined) -// @as(f16, undefined) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(@Vector(2, f16), undefined) -// @as(f16, undefined) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), [runtime value]) -// @as(@Vector(2, f16), undefined) -// @as(f32, undefined) -// @as(f32, undefined) -// @as(@Vector(2, f32), .{ 6, undefined }) -// @as(@Vector(2, f32), .{ undefined, 6 }) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), .{ 6, undefined }) -// @as(@Vector(2, f32), .{ 6, undefined }) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), .{ undefined, 6 }) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), .{ undefined, 6 }) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(f32, undefined) -// @as(f32, undefined) -// @as(@Vector(2, f32), .{ 0, undefined }) -// @as(@Vector(2, f32), .{ undefined, 0 }) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), .{ 0, undefined }) -// @as(@Vector(2, f32), .{ 0, undefined }) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), .{ undefined, 0 }) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), .{ undefined, 0 }) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(f32, undefined) -// @as(f32, undefined) -// @as(@Vector(2, f32), .{ 9, undefined }) -// @as(@Vector(2, f32), .{ undefined, 9 }) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), .{ 9, undefined }) -// @as(@Vector(2, f32), .{ 9, undefined }) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), .{ undefined, 9 }) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), .{ undefined, 9 }) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(f32, undefined) -// @as(@Vector(2, f32), .{ -3, undefined }) -// @as(@Vector(2, f32), .{ undefined, -3 }) -// @as(@Vector(2, f32), undefined) -// @as(f32, undefined) -// @as(f32, undefined) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(f32, undefined) -// @as(f32, undefined) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(f32, undefined) -// @as(f32, undefined) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(@Vector(2, f32), undefined) -// @as(f32, undefined) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), [runtime value]) -// @as(@Vector(2, f32), undefined) -// @as(f64, undefined) -// @as(f64, undefined) -// @as(@Vector(2, f64), .{ 6, undefined }) -// @as(@Vector(2, f64), .{ undefined, 6 }) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), .{ 6, undefined }) -// @as(@Vector(2, f64), .{ 6, undefined }) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), .{ undefined, 6 }) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), .{ undefined, 6 }) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(f64, undefined) -// @as(f64, undefined) -// @as(@Vector(2, f64), .{ 0, undefined }) -// @as(@Vector(2, f64), .{ undefined, 0 }) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), .{ 0, undefined }) -// @as(@Vector(2, f64), .{ 0, undefined }) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), .{ undefined, 0 }) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), .{ undefined, 0 }) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(f64, undefined) -// @as(f64, undefined) -// @as(@Vector(2, f64), .{ 9, undefined }) -// @as(@Vector(2, f64), .{ undefined, 9 }) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), .{ 9, undefined }) -// @as(@Vector(2, f64), .{ 9, undefined }) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), .{ undefined, 9 }) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), .{ undefined, 9 }) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(f64, undefined) -// @as(@Vector(2, f64), .{ -3, undefined }) -// @as(@Vector(2, f64), .{ undefined, -3 }) -// @as(@Vector(2, f64), undefined) -// @as(f64, undefined) -// @as(f64, undefined) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(f64, undefined) -// @as(f64, undefined) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(f64, undefined) -// @as(f64, undefined) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(@Vector(2, f64), undefined) -// @as(f64, undefined) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), [runtime value]) -// @as(@Vector(2, f64), undefined) -// @as(f80, undefined) -// @as(f80, undefined) -// @as(@Vector(2, f80), .{ 6, undefined }) -// @as(@Vector(2, f80), .{ undefined, 6 }) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), .{ 6, undefined }) -// @as(@Vector(2, f80), .{ 6, undefined }) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), .{ undefined, 6 }) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), .{ undefined, 6 }) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(f80, undefined) -// @as(f80, undefined) -// @as(@Vector(2, f80), .{ 0, undefined }) -// @as(@Vector(2, f80), .{ undefined, 0 }) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), .{ 0, undefined }) -// @as(@Vector(2, f80), .{ 0, undefined }) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), .{ undefined, 0 }) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), .{ undefined, 0 }) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(f80, undefined) -// @as(f80, undefined) -// @as(@Vector(2, f80), .{ 9, undefined }) -// @as(@Vector(2, f80), .{ undefined, 9 }) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), .{ 9, undefined }) -// @as(@Vector(2, f80), .{ 9, undefined }) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), .{ undefined, 9 }) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), .{ undefined, 9 }) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(f80, undefined) -// @as(@Vector(2, f80), .{ -3, undefined }) -// @as(@Vector(2, f80), .{ undefined, -3 }) -// @as(@Vector(2, f80), undefined) -// @as(f80, undefined) -// @as(f80, undefined) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(f80, undefined) -// @as(f80, undefined) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(f80, undefined) -// @as(f80, undefined) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(@Vector(2, f80), undefined) -// @as(f80, undefined) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), [runtime value]) -// @as(@Vector(2, f80), undefined) +// @as(u500, undefined) +// @as(@Vector(2, u500), undefined) +// @as(i32, undefined) +// @as(i32, undefined) +// @as(@Vector(2, i32), .{ 6, undefined }) +// @as(@Vector(2, i32), .{ undefined, 6 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ 6, undefined }) +// @as(@Vector(2, i32), .{ 6, undefined }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ undefined, 6 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ undefined, 6 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(i32, undefined) +// @as(i32, undefined) +// @as(@Vector(2, i32), .{ 6, undefined }) +// @as(@Vector(2, i32), .{ undefined, 6 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ 6, undefined }) +// @as(@Vector(2, i32), .{ 6, undefined }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ undefined, 6 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ undefined, 6 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(i32, undefined) +// @as(i32, undefined) +// @as(@Vector(2, i32), .{ 0, undefined }) +// @as(@Vector(2, i32), .{ undefined, 0 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ 0, undefined }) +// @as(@Vector(2, i32), .{ 0, undefined }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ undefined, 0 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ undefined, 0 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(i32, undefined) +// @as(i32, undefined) +// @as(@Vector(2, i32), .{ 0, undefined }) +// @as(@Vector(2, i32), .{ undefined, 0 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ 0, undefined }) +// @as(@Vector(2, i32), .{ 0, undefined }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ undefined, 0 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ undefined, 0 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(i32, undefined) +// @as(i32, undefined) +// @as(@Vector(2, i32), .{ 9, undefined }) +// @as(@Vector(2, i32), .{ undefined, 9 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ 9, undefined }) +// @as(@Vector(2, i32), .{ 9, undefined }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ undefined, 9 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ undefined, 9 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(i32, undefined) +// @as(i32, undefined) +// @as(@Vector(2, i32), .{ 9, undefined }) +// @as(@Vector(2, i32), .{ undefined, 9 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ 9, undefined }) +// @as(@Vector(2, i32), .{ 9, undefined }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ undefined, 9 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ undefined, 9 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(i32, undefined) +// @as(i32, undefined) +// @as(@Vector(2, i32), .{ 0, undefined }) +// @as(@Vector(2, i32), .{ undefined, 0 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ 0, undefined }) +// @as(@Vector(2, i32), .{ 0, undefined }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ undefined, 0 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), .{ undefined, 0 }) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(i32, undefined) +// @as(@Vector(2, i32), undefined) +// @as(i32, undefined) +// @as(i32, undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(i32, undefined) +// @as(@Vector(2, i32), undefined) +// @as(i32, undefined) +// @as(i32, undefined) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(i32, undefined) +// @as(i32, undefined) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(i32, undefined) +// @as(i32, undefined) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(i32, undefined) +// @as(i32, undefined) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(i32, undefined) +// @as(i32, undefined) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(i32, undefined) +// @as(i32, undefined) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(i32, [runtime value]) +// @as(i32, [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), [runtime value]) +// @as(@Vector(2, i32), undefined) +// @as(i32, undefined) +// @as(@Vector(2, i32), undefined) +// @as(i32, undefined) +// @as(i32, undefined) +// @as(@Vector(2, i32), undefined) +// @as(@Vector(2, i32), undefined) +// @as(i32, undefined) +// @as(@Vector(2, i32), undefined) +// @as(u32, undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), .{ 6, undefined }) +// @as(@Vector(2, u32), .{ undefined, 6 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ 6, undefined }) +// @as(@Vector(2, u32), .{ 6, undefined }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ undefined, 6 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ undefined, 6 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(u32, undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), .{ 6, undefined }) +// @as(@Vector(2, u32), .{ undefined, 6 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ 6, undefined }) +// @as(@Vector(2, u32), .{ 6, undefined }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ undefined, 6 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ undefined, 6 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(u32, undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), .{ 0, undefined }) +// @as(@Vector(2, u32), .{ undefined, 0 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ 0, undefined }) +// @as(@Vector(2, u32), .{ 0, undefined }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ undefined, 0 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ undefined, 0 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(u32, undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), .{ 0, undefined }) +// @as(@Vector(2, u32), .{ undefined, 0 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ 0, undefined }) +// @as(@Vector(2, u32), .{ 0, undefined }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ undefined, 0 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ undefined, 0 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(u32, undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), .{ 9, undefined }) +// @as(@Vector(2, u32), .{ undefined, 9 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ 9, undefined }) +// @as(@Vector(2, u32), .{ 9, undefined }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ undefined, 9 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ undefined, 9 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(u32, undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), .{ 9, undefined }) +// @as(@Vector(2, u32), .{ undefined, 9 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ 9, undefined }) +// @as(@Vector(2, u32), .{ 9, undefined }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ undefined, 9 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ undefined, 9 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(u32, undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), .{ 24, undefined }) +// @as(@Vector(2, u32), .{ undefined, 24 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ 24, undefined }) +// @as(@Vector(2, u32), .{ 24, undefined }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ undefined, 24 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ undefined, 24 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(u32, undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), .{ 0, undefined }) +// @as(@Vector(2, u32), .{ undefined, 0 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ 0, undefined }) +// @as(@Vector(2, u32), .{ 0, undefined }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ undefined, 0 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), .{ undefined, 0 }) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), undefined) +// @as(u32, undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(u1, undefined) +// @as(@Vector(2, u1), .{ 1, undefined }) +// @as(@Vector(2, u1), .{ undefined, 1 }) +// @as(@Vector(2, u1), undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), undefined) +// @as(u32, undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(u32, undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(u32, undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(u32, undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(u32, undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(u32, undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(u32, undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(u32, [runtime value]) +// @as(u32, [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), [runtime value]) +// @as(@Vector(2, u32), undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), undefined) +// @as(u32, undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), undefined) +// @as(@Vector(2, u32), undefined) +// @as(u1, undefined) +// @as(@Vector(2, u1), [runtime value]) +// @as(@Vector(2, u1), [runtime value]) +// @as(@Vector(2, u1), undefined) +// @as(u32, undefined) +// @as(@Vector(2, u32), undefined) +// @as(i8, undefined) +// @as(i8, undefined) +// @as(@Vector(2, i8), .{ 6, undefined }) +// @as(@Vector(2, i8), .{ undefined, 6 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ 6, undefined }) +// @as(@Vector(2, i8), .{ 6, undefined }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ undefined, 6 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ undefined, 6 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(i8, undefined) +// @as(i8, undefined) +// @as(@Vector(2, i8), .{ 6, undefined }) +// @as(@Vector(2, i8), .{ undefined, 6 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ 6, undefined }) +// @as(@Vector(2, i8), .{ 6, undefined }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ undefined, 6 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ undefined, 6 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(i8, undefined) +// @as(i8, undefined) +// @as(@Vector(2, i8), .{ 0, undefined }) +// @as(@Vector(2, i8), .{ undefined, 0 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ 0, undefined }) +// @as(@Vector(2, i8), .{ 0, undefined }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ undefined, 0 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ undefined, 0 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(i8, undefined) +// @as(i8, undefined) +// @as(@Vector(2, i8), .{ 0, undefined }) +// @as(@Vector(2, i8), .{ undefined, 0 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ 0, undefined }) +// @as(@Vector(2, i8), .{ 0, undefined }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ undefined, 0 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ undefined, 0 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(i8, undefined) +// @as(i8, undefined) +// @as(@Vector(2, i8), .{ 9, undefined }) +// @as(@Vector(2, i8), .{ undefined, 9 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ 9, undefined }) +// @as(@Vector(2, i8), .{ 9, undefined }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ undefined, 9 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ undefined, 9 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(i8, undefined) +// @as(i8, undefined) +// @as(@Vector(2, i8), .{ 9, undefined }) +// @as(@Vector(2, i8), .{ undefined, 9 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ 9, undefined }) +// @as(@Vector(2, i8), .{ 9, undefined }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ undefined, 9 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ undefined, 9 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(i8, undefined) +// @as(i8, undefined) +// @as(@Vector(2, i8), .{ 0, undefined }) +// @as(@Vector(2, i8), .{ undefined, 0 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ 0, undefined }) +// @as(@Vector(2, i8), .{ 0, undefined }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ undefined, 0 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), .{ undefined, 0 }) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(i8, undefined) +// @as(@Vector(2, i8), undefined) +// @as(i8, undefined) +// @as(i8, undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(i8, undefined) +// @as(@Vector(2, i8), undefined) +// @as(i8, undefined) +// @as(i8, undefined) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(i8, undefined) +// @as(i8, undefined) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(i8, undefined) +// @as(i8, undefined) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(i8, undefined) +// @as(i8, undefined) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(i8, undefined) +// @as(i8, undefined) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(i8, undefined) +// @as(i8, undefined) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(i8, [runtime value]) +// @as(i8, [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), [runtime value]) +// @as(@Vector(2, i8), undefined) +// @as(i8, undefined) +// @as(@Vector(2, i8), undefined) +// @as(i8, undefined) +// @as(i8, undefined) +// @as(@Vector(2, i8), undefined) +// @as(@Vector(2, i8), undefined) +// @as(i8, undefined) +// @as(@Vector(2, i8), undefined) // @as(f128, undefined) // @as(f128, undefined) // @as(@Vector(2, f128), .{ 6, undefined }) @@ -2585,3 +2145,443 @@ inline fn testFloatWithValue(comptime Float: type, x: Float) void { // @as(@Vector(2, f128), [runtime value]) // @as(@Vector(2, f128), [runtime value]) // @as(@Vector(2, f128), undefined) +// @as(f80, undefined) +// @as(f80, undefined) +// @as(@Vector(2, f80), .{ 6, undefined }) +// @as(@Vector(2, f80), .{ undefined, 6 }) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), .{ 6, undefined }) +// @as(@Vector(2, f80), .{ 6, undefined }) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), .{ undefined, 6 }) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), .{ undefined, 6 }) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(f80, undefined) +// @as(f80, undefined) +// @as(@Vector(2, f80), .{ 0, undefined }) +// @as(@Vector(2, f80), .{ undefined, 0 }) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), .{ 0, undefined }) +// @as(@Vector(2, f80), .{ 0, undefined }) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), .{ undefined, 0 }) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), .{ undefined, 0 }) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(f80, undefined) +// @as(f80, undefined) +// @as(@Vector(2, f80), .{ 9, undefined }) +// @as(@Vector(2, f80), .{ undefined, 9 }) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), .{ 9, undefined }) +// @as(@Vector(2, f80), .{ 9, undefined }) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), .{ undefined, 9 }) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), .{ undefined, 9 }) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(f80, undefined) +// @as(@Vector(2, f80), .{ -3, undefined }) +// @as(@Vector(2, f80), .{ undefined, -3 }) +// @as(@Vector(2, f80), undefined) +// @as(f80, undefined) +// @as(f80, undefined) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(f80, undefined) +// @as(f80, undefined) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(f80, undefined) +// @as(f80, undefined) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(@Vector(2, f80), undefined) +// @as(f80, undefined) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), [runtime value]) +// @as(@Vector(2, f80), undefined) +// @as(f64, undefined) +// @as(f64, undefined) +// @as(@Vector(2, f64), .{ 6, undefined }) +// @as(@Vector(2, f64), .{ undefined, 6 }) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), .{ 6, undefined }) +// @as(@Vector(2, f64), .{ 6, undefined }) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), .{ undefined, 6 }) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), .{ undefined, 6 }) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(f64, undefined) +// @as(f64, undefined) +// @as(@Vector(2, f64), .{ 0, undefined }) +// @as(@Vector(2, f64), .{ undefined, 0 }) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), .{ 0, undefined }) +// @as(@Vector(2, f64), .{ 0, undefined }) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), .{ undefined, 0 }) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), .{ undefined, 0 }) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(f64, undefined) +// @as(f64, undefined) +// @as(@Vector(2, f64), .{ 9, undefined }) +// @as(@Vector(2, f64), .{ undefined, 9 }) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), .{ 9, undefined }) +// @as(@Vector(2, f64), .{ 9, undefined }) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), .{ undefined, 9 }) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), .{ undefined, 9 }) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(f64, undefined) +// @as(@Vector(2, f64), .{ -3, undefined }) +// @as(@Vector(2, f64), .{ undefined, -3 }) +// @as(@Vector(2, f64), undefined) +// @as(f64, undefined) +// @as(f64, undefined) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(f64, undefined) +// @as(f64, undefined) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(f64, undefined) +// @as(f64, undefined) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(@Vector(2, f64), undefined) +// @as(f64, undefined) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), [runtime value]) +// @as(@Vector(2, f64), undefined) +// @as(f32, undefined) +// @as(f32, undefined) +// @as(@Vector(2, f32), .{ 6, undefined }) +// @as(@Vector(2, f32), .{ undefined, 6 }) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), .{ 6, undefined }) +// @as(@Vector(2, f32), .{ 6, undefined }) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), .{ undefined, 6 }) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), .{ undefined, 6 }) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(f32, undefined) +// @as(f32, undefined) +// @as(@Vector(2, f32), .{ 0, undefined }) +// @as(@Vector(2, f32), .{ undefined, 0 }) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), .{ 0, undefined }) +// @as(@Vector(2, f32), .{ 0, undefined }) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), .{ undefined, 0 }) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), .{ undefined, 0 }) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(f32, undefined) +// @as(f32, undefined) +// @as(@Vector(2, f32), .{ 9, undefined }) +// @as(@Vector(2, f32), .{ undefined, 9 }) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), .{ 9, undefined }) +// @as(@Vector(2, f32), .{ 9, undefined }) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), .{ undefined, 9 }) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), .{ undefined, 9 }) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(f32, undefined) +// @as(@Vector(2, f32), .{ -3, undefined }) +// @as(@Vector(2, f32), .{ undefined, -3 }) +// @as(@Vector(2, f32), undefined) +// @as(f32, undefined) +// @as(f32, undefined) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(f32, undefined) +// @as(f32, undefined) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(f32, undefined) +// @as(f32, undefined) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(@Vector(2, f32), undefined) +// @as(f32, undefined) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), [runtime value]) +// @as(@Vector(2, f32), undefined) +// @as(f16, undefined) +// @as(f16, undefined) +// @as(@Vector(2, f16), .{ 6, undefined }) +// @as(@Vector(2, f16), .{ undefined, 6 }) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), .{ 6, undefined }) +// @as(@Vector(2, f16), .{ 6, undefined }) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), .{ undefined, 6 }) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), .{ undefined, 6 }) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(f16, undefined) +// @as(f16, undefined) +// @as(@Vector(2, f16), .{ 0, undefined }) +// @as(@Vector(2, f16), .{ undefined, 0 }) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), .{ 0, undefined }) +// @as(@Vector(2, f16), .{ 0, undefined }) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), .{ undefined, 0 }) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), .{ undefined, 0 }) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(f16, undefined) +// @as(f16, undefined) +// @as(@Vector(2, f16), .{ 9, undefined }) +// @as(@Vector(2, f16), .{ undefined, 9 }) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), .{ 9, undefined }) +// @as(@Vector(2, f16), .{ 9, undefined }) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), .{ undefined, 9 }) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), .{ undefined, 9 }) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(f16, undefined) +// @as(@Vector(2, f16), .{ -3, undefined }) +// @as(@Vector(2, f16), .{ undefined, -3 }) +// @as(@Vector(2, f16), undefined) +// @as(f16, undefined) +// @as(f16, undefined) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(f16, undefined) +// @as(f16, undefined) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(f16, undefined) +// @as(f16, undefined) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(@Vector(2, f16), undefined) +// @as(f16, undefined) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), [runtime value]) +// @as(@Vector(2, f16), undefined) diff --git a/test/cases/compile_errors/undef_shifts_are_illegal.zig b/test/cases/compile_errors/undef_shifts_are_illegal.zig index 20c4571408db755b1d38f99585342106b7a94d0c..518da69194e8c43a831a8745cf985780307ab5d9 100644 --- a/test/cases/compile_errors/undef_shifts_are_illegal.zig +++ b/test/cases/compile_errors/undef_shifts_are_illegal.zig @@ -125,27 +125,19 @@ const std = @import("std"); // :53:17: error: use of undefined value here causes illegal behavior // :53:17: error: use of undefined value here causes illegal behavior // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '1' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '1' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior +// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior +// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior // :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior @@ -155,9 +147,9 @@ const std = @import("std"); // :53:17: error: use of undefined value here causes illegal behavior // :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '1' +// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '1' +// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior // :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior @@ -167,7 +159,9 @@ const std = @import("std"); // :53:17: error: use of undefined value here causes illegal behavior // :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior +// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior +// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior // :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior @@ -177,9 +171,9 @@ const std = @import("std"); // :53:17: error: use of undefined value here causes illegal behavior // :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '1' +// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '1' +// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior // :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior @@ -189,7 +183,9 @@ const std = @import("std"); // :53:17: error: use of undefined value here causes illegal behavior // :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior +// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior +// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior // :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior @@ -199,9 +195,9 @@ const std = @import("std"); // :53:17: error: use of undefined value here causes illegal behavior // :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '1' +// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '1' +// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior // :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior @@ -211,7 +207,9 @@ const std = @import("std"); // :53:17: error: use of undefined value here causes illegal behavior // :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior +// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior +// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior // :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior @@ -221,9 +219,9 @@ const std = @import("std"); // :53:17: error: use of undefined value here causes illegal behavior // :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '1' +// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '1' +// :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior // :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior @@ -233,27 +231,29 @@ const std = @import("std"); // :53:17: error: use of undefined value here causes illegal behavior // :53:17: note: when computing vector element at index '0' // :53:17: error: use of undefined value here causes illegal behavior +// :53:17: note: when computing vector element at index '1' // :53:17: error: use of undefined value here causes illegal behavior +// :53:17: note: when computing vector element at index '1' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '0' +// :53:17: note: when computing vector element at index '1' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '0' +// :53:17: note: when computing vector element at index '1' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '0' +// :53:17: note: when computing vector element at index '1' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '0' +// :53:17: note: when computing vector element at index '1' // :53:17: error: use of undefined value here causes illegal behavior // :53:17: note: when computing vector element at index '1' // :53:17: error: use of undefined value here causes illegal behavior // :53:17: note: when computing vector element at index '1' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '0' +// :53:17: note: when computing vector element at index '1' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '0' +// :53:17: note: when computing vector element at index '1' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '0' +// :53:17: note: when computing vector element at index '1' // :53:17: error: use of undefined value here causes illegal behavior -// :53:17: note: when computing vector element at index '0' +// :53:17: note: when computing vector element at index '1' // :53:22: error: use of undefined value here causes illegal behavior // :53:22: note: when computing vector element at index '0' // :53:22: error: use of undefined value here causes illegal behavior @@ -281,27 +281,19 @@ const std = @import("std"); // :56:27: error: use of undefined value here causes illegal behavior // :56:27: error: use of undefined value here causes illegal behavior // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '1' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '1' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior +// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior +// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior // :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior @@ -311,9 +303,9 @@ const std = @import("std"); // :56:27: error: use of undefined value here causes illegal behavior // :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '1' +// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '1' +// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior // :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior @@ -323,7 +315,9 @@ const std = @import("std"); // :56:27: error: use of undefined value here causes illegal behavior // :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior +// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior +// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior // :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior @@ -333,9 +327,9 @@ const std = @import("std"); // :56:27: error: use of undefined value here causes illegal behavior // :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '1' +// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '1' +// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior // :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior @@ -345,7 +339,9 @@ const std = @import("std"); // :56:27: error: use of undefined value here causes illegal behavior // :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior +// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior +// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior // :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior @@ -355,9 +351,9 @@ const std = @import("std"); // :56:27: error: use of undefined value here causes illegal behavior // :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '1' +// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '1' +// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior // :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior @@ -367,7 +363,9 @@ const std = @import("std"); // :56:27: error: use of undefined value here causes illegal behavior // :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior +// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior +// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior // :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior @@ -377,9 +375,9 @@ const std = @import("std"); // :56:27: error: use of undefined value here causes illegal behavior // :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '1' +// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '1' +// :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior // :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior @@ -389,27 +387,29 @@ const std = @import("std"); // :56:27: error: use of undefined value here causes illegal behavior // :56:27: note: when computing vector element at index '0' // :56:27: error: use of undefined value here causes illegal behavior +// :56:27: note: when computing vector element at index '1' // :56:27: error: use of undefined value here causes illegal behavior +// :56:27: note: when computing vector element at index '1' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '0' +// :56:27: note: when computing vector element at index '1' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '0' +// :56:27: note: when computing vector element at index '1' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '0' +// :56:27: note: when computing vector element at index '1' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '0' +// :56:27: note: when computing vector element at index '1' // :56:27: error: use of undefined value here causes illegal behavior // :56:27: note: when computing vector element at index '1' // :56:27: error: use of undefined value here causes illegal behavior // :56:27: note: when computing vector element at index '1' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '0' +// :56:27: note: when computing vector element at index '1' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '0' +// :56:27: note: when computing vector element at index '1' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '0' +// :56:27: note: when computing vector element at index '1' // :56:27: error: use of undefined value here causes illegal behavior -// :56:27: note: when computing vector element at index '0' +// :56:27: note: when computing vector element at index '1' // :56:30: error: use of undefined value here causes illegal behavior // :56:30: note: when computing vector element at index '0' // :56:30: error: use of undefined value here causes illegal behavior @@ -437,27 +437,19 @@ const std = @import("std"); // :59:34: error: use of undefined value here causes illegal behavior // :59:34: error: use of undefined value here causes illegal behavior // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '1' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '1' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior +// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior +// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior // :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior @@ -467,9 +459,9 @@ const std = @import("std"); // :59:34: error: use of undefined value here causes illegal behavior // :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '1' +// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '1' +// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior // :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior @@ -479,7 +471,9 @@ const std = @import("std"); // :59:34: error: use of undefined value here causes illegal behavior // :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior +// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior +// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior // :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior @@ -489,9 +483,9 @@ const std = @import("std"); // :59:34: error: use of undefined value here causes illegal behavior // :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '1' +// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '1' +// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior // :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior @@ -501,7 +495,9 @@ const std = @import("std"); // :59:34: error: use of undefined value here causes illegal behavior // :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior +// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior +// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior // :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior @@ -511,9 +507,9 @@ const std = @import("std"); // :59:34: error: use of undefined value here causes illegal behavior // :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '1' +// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '1' +// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior // :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior @@ -523,7 +519,9 @@ const std = @import("std"); // :59:34: error: use of undefined value here causes illegal behavior // :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior +// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior +// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior // :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior @@ -533,9 +531,9 @@ const std = @import("std"); // :59:34: error: use of undefined value here causes illegal behavior // :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '1' +// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '1' +// :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior // :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior @@ -545,27 +543,29 @@ const std = @import("std"); // :59:34: error: use of undefined value here causes illegal behavior // :59:34: note: when computing vector element at index '0' // :59:34: error: use of undefined value here causes illegal behavior +// :59:34: note: when computing vector element at index '1' // :59:34: error: use of undefined value here causes illegal behavior +// :59:34: note: when computing vector element at index '1' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '0' +// :59:34: note: when computing vector element at index '1' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '0' +// :59:34: note: when computing vector element at index '1' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '0' +// :59:34: note: when computing vector element at index '1' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '0' +// :59:34: note: when computing vector element at index '1' // :59:34: error: use of undefined value here causes illegal behavior // :59:34: note: when computing vector element at index '1' // :59:34: error: use of undefined value here causes illegal behavior // :59:34: note: when computing vector element at index '1' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '0' +// :59:34: note: when computing vector element at index '1' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '0' +// :59:34: note: when computing vector element at index '1' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '0' +// :59:34: note: when computing vector element at index '1' // :59:34: error: use of undefined value here causes illegal behavior -// :59:34: note: when computing vector element at index '0' +// :59:34: note: when computing vector element at index '1' // :59:37: error: use of undefined value here causes illegal behavior // :59:37: note: when computing vector element at index '0' // :59:37: error: use of undefined value here causes illegal behavior @@ -593,27 +593,19 @@ const std = @import("std"); // :62:17: error: use of undefined value here causes illegal behavior // :62:17: error: use of undefined value here causes illegal behavior // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '1' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '1' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior +// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior +// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior // :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior @@ -623,9 +615,9 @@ const std = @import("std"); // :62:17: error: use of undefined value here causes illegal behavior // :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '1' +// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '1' +// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior // :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior @@ -635,7 +627,9 @@ const std = @import("std"); // :62:17: error: use of undefined value here causes illegal behavior // :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior +// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior +// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior // :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior @@ -645,9 +639,9 @@ const std = @import("std"); // :62:17: error: use of undefined value here causes illegal behavior // :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '1' +// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '1' +// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior // :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior @@ -657,7 +651,9 @@ const std = @import("std"); // :62:17: error: use of undefined value here causes illegal behavior // :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior +// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior +// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior // :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior @@ -667,9 +663,9 @@ const std = @import("std"); // :62:17: error: use of undefined value here causes illegal behavior // :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '1' +// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '1' +// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior // :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior @@ -679,7 +675,9 @@ const std = @import("std"); // :62:17: error: use of undefined value here causes illegal behavior // :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior +// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior +// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior // :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior @@ -689,9 +687,9 @@ const std = @import("std"); // :62:17: error: use of undefined value here causes illegal behavior // :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '1' +// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '1' +// :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior // :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior @@ -701,27 +699,29 @@ const std = @import("std"); // :62:17: error: use of undefined value here causes illegal behavior // :62:17: note: when computing vector element at index '0' // :62:17: error: use of undefined value here causes illegal behavior +// :62:17: note: when computing vector element at index '1' // :62:17: error: use of undefined value here causes illegal behavior +// :62:17: note: when computing vector element at index '1' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '0' +// :62:17: note: when computing vector element at index '1' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '0' +// :62:17: note: when computing vector element at index '1' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '0' +// :62:17: note: when computing vector element at index '1' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '0' +// :62:17: note: when computing vector element at index '1' // :62:17: error: use of undefined value here causes illegal behavior // :62:17: note: when computing vector element at index '1' // :62:17: error: use of undefined value here causes illegal behavior // :62:17: note: when computing vector element at index '1' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '0' +// :62:17: note: when computing vector element at index '1' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '0' +// :62:17: note: when computing vector element at index '1' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '0' +// :62:17: note: when computing vector element at index '1' // :62:17: error: use of undefined value here causes illegal behavior -// :62:17: note: when computing vector element at index '0' +// :62:17: note: when computing vector element at index '1' // :62:22: error: use of undefined value here causes illegal behavior // :62:22: note: when computing vector element at index '0' // :62:22: error: use of undefined value here causes illegal behavior @@ -749,27 +749,19 @@ const std = @import("std"); // :65:27: error: use of undefined value here causes illegal behavior // :65:27: error: use of undefined value here causes illegal behavior // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '1' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '1' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior +// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior +// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior // :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior @@ -779,9 +771,9 @@ const std = @import("std"); // :65:27: error: use of undefined value here causes illegal behavior // :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '1' +// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '1' +// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior // :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior @@ -791,7 +783,9 @@ const std = @import("std"); // :65:27: error: use of undefined value here causes illegal behavior // :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior +// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior +// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior // :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior @@ -801,9 +795,9 @@ const std = @import("std"); // :65:27: error: use of undefined value here causes illegal behavior // :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '1' +// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '1' +// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior // :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior @@ -813,7 +807,9 @@ const std = @import("std"); // :65:27: error: use of undefined value here causes illegal behavior // :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior +// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior +// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior // :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior @@ -823,9 +819,9 @@ const std = @import("std"); // :65:27: error: use of undefined value here causes illegal behavior // :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '1' +// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '1' +// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior // :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior @@ -835,7 +831,9 @@ const std = @import("std"); // :65:27: error: use of undefined value here causes illegal behavior // :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior +// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior +// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior // :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior @@ -845,9 +843,9 @@ const std = @import("std"); // :65:27: error: use of undefined value here causes illegal behavior // :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '1' +// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '1' +// :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior // :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior @@ -857,27 +855,29 @@ const std = @import("std"); // :65:27: error: use of undefined value here causes illegal behavior // :65:27: note: when computing vector element at index '0' // :65:27: error: use of undefined value here causes illegal behavior +// :65:27: note: when computing vector element at index '1' // :65:27: error: use of undefined value here causes illegal behavior +// :65:27: note: when computing vector element at index '1' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '0' +// :65:27: note: when computing vector element at index '1' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '0' +// :65:27: note: when computing vector element at index '1' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '0' +// :65:27: note: when computing vector element at index '1' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '0' +// :65:27: note: when computing vector element at index '1' // :65:27: error: use of undefined value here causes illegal behavior // :65:27: note: when computing vector element at index '1' // :65:27: error: use of undefined value here causes illegal behavior // :65:27: note: when computing vector element at index '1' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '0' +// :65:27: note: when computing vector element at index '1' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '0' +// :65:27: note: when computing vector element at index '1' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '0' +// :65:27: note: when computing vector element at index '1' // :65:27: error: use of undefined value here causes illegal behavior -// :65:27: note: when computing vector element at index '0' +// :65:27: note: when computing vector element at index '1' // :65:30: error: use of undefined value here causes illegal behavior // :65:30: note: when computing vector element at index '0' // :65:30: error: use of undefined value here causes illegal behavior @@ -909,21 +909,13 @@ const std = @import("std"); // :70:17: error: use of undefined value here causes illegal behavior // :70:17: error: use of undefined value here causes illegal behavior // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior // :70:17: error: use of undefined value here causes illegal behavior // :70:17: error: use of undefined value here causes illegal behavior @@ -931,21 +923,13 @@ const std = @import("std"); // :70:17: error: use of undefined value here causes illegal behavior // :70:17: error: use of undefined value here causes illegal behavior // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior // :70:17: error: use of undefined value here causes illegal behavior // :70:17: error: use of undefined value here causes illegal behavior @@ -953,13 +937,11 @@ const std = @import("std"); // :70:17: error: use of undefined value here causes illegal behavior // :70:17: error: use of undefined value here causes illegal behavior // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '1' +// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '1' +// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior // :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior @@ -969,19 +951,25 @@ const std = @import("std"); // :70:17: error: use of undefined value here causes illegal behavior // :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior +// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior +// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior +// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior +// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior +// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior +// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '1' +// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '1' +// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '1' +// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '1' +// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior // :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior @@ -991,11 +979,17 @@ const std = @import("std"); // :70:17: error: use of undefined value here causes illegal behavior // :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior +// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior +// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior +// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior +// :70:17: note: when computing vector element at index '0' // :70:17: error: use of undefined value here causes illegal behavior +// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior +// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior // :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior @@ -1005,19 +999,25 @@ const std = @import("std"); // :70:17: error: use of undefined value here causes illegal behavior // :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '0' +// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '0' +// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '0' +// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '0' +// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior +// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior +// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior +// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior +// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior +// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior +// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior // :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior @@ -1027,13 +1027,13 @@ const std = @import("std"); // :70:17: error: use of undefined value here causes illegal behavior // :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '0' +// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '0' +// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '0' +// :70:17: note: when computing vector element at index '1' // :70:17: error: use of undefined value here causes illegal behavior -// :70:17: note: when computing vector element at index '0' +// :70:17: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: error: use of undefined value here causes illegal behavior // :73:27: error: use of undefined value here causes illegal behavior @@ -1041,21 +1041,13 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: error: use of undefined value here causes illegal behavior // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: error: use of undefined value here causes illegal behavior // :73:27: error: use of undefined value here causes illegal behavior @@ -1063,21 +1055,13 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: error: use of undefined value here causes illegal behavior // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: error: use of undefined value here causes illegal behavior // :73:27: error: use of undefined value here causes illegal behavior @@ -1085,13 +1069,11 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: error: use of undefined value here causes illegal behavior // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior @@ -1101,19 +1083,25 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '1' +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior @@ -1123,11 +1111,17 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '0' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior @@ -1137,19 +1131,25 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior @@ -1159,13 +1159,13 @@ const std = @import("std"); // :73:27: error: use of undefined value here causes illegal behavior // :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' // :73:27: error: use of undefined value here causes illegal behavior -// :73:27: note: when computing vector element at index '0' +// :73:27: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior // :76:34: error: use of undefined value here causes illegal behavior // :76:34: error: use of undefined value here causes illegal behavior @@ -1173,21 +1173,13 @@ const std = @import("std"); // :76:34: error: use of undefined value here causes illegal behavior // :76:34: error: use of undefined value here causes illegal behavior // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior // :76:34: error: use of undefined value here causes illegal behavior // :76:34: error: use of undefined value here causes illegal behavior @@ -1195,21 +1187,13 @@ const std = @import("std"); // :76:34: error: use of undefined value here causes illegal behavior // :76:34: error: use of undefined value here causes illegal behavior // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior // :76:34: error: use of undefined value here causes illegal behavior // :76:34: error: use of undefined value here causes illegal behavior @@ -1217,13 +1201,11 @@ const std = @import("std"); // :76:34: error: use of undefined value here causes illegal behavior // :76:34: error: use of undefined value here causes illegal behavior // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '1' +// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '1' +// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior // :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior @@ -1233,19 +1215,25 @@ const std = @import("std"); // :76:34: error: use of undefined value here causes illegal behavior // :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior +// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior +// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior +// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior +// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior +// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior +// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '1' +// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '1' +// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '1' +// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '1' +// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior // :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior @@ -1255,11 +1243,17 @@ const std = @import("std"); // :76:34: error: use of undefined value here causes illegal behavior // :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior +// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior +// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior +// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior +// :76:34: note: when computing vector element at index '0' // :76:34: error: use of undefined value here causes illegal behavior +// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior +// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior // :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior @@ -1269,19 +1263,25 @@ const std = @import("std"); // :76:34: error: use of undefined value here causes illegal behavior // :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '0' +// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '0' +// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '0' +// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '0' +// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior +// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior +// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior +// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior +// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior +// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior +// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior // :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior @@ -1291,13 +1291,13 @@ const std = @import("std"); // :76:34: error: use of undefined value here causes illegal behavior // :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '0' +// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '0' +// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '0' +// :76:34: note: when computing vector element at index '1' // :76:34: error: use of undefined value here causes illegal behavior -// :76:34: note: when computing vector element at index '0' +// :76:34: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior // :79:17: error: use of undefined value here causes illegal behavior // :79:17: error: use of undefined value here causes illegal behavior @@ -1305,21 +1305,13 @@ const std = @import("std"); // :79:17: error: use of undefined value here causes illegal behavior // :79:17: error: use of undefined value here causes illegal behavior // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior // :79:17: error: use of undefined value here causes illegal behavior // :79:17: error: use of undefined value here causes illegal behavior @@ -1327,21 +1319,13 @@ const std = @import("std"); // :79:17: error: use of undefined value here causes illegal behavior // :79:17: error: use of undefined value here causes illegal behavior // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior // :79:17: error: use of undefined value here causes illegal behavior // :79:17: error: use of undefined value here causes illegal behavior @@ -1349,13 +1333,11 @@ const std = @import("std"); // :79:17: error: use of undefined value here causes illegal behavior // :79:17: error: use of undefined value here causes illegal behavior // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '1' +// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '1' +// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior // :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior @@ -1365,19 +1347,25 @@ const std = @import("std"); // :79:17: error: use of undefined value here causes illegal behavior // :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior +// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior +// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior +// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior +// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior +// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior +// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '1' +// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '1' +// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '1' +// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '1' +// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior // :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior @@ -1387,11 +1375,17 @@ const std = @import("std"); // :79:17: error: use of undefined value here causes illegal behavior // :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior +// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior +// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior +// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior +// :79:17: note: when computing vector element at index '0' // :79:17: error: use of undefined value here causes illegal behavior +// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior +// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior // :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior @@ -1401,19 +1395,25 @@ const std = @import("std"); // :79:17: error: use of undefined value here causes illegal behavior // :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '0' +// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '0' +// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '0' +// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '0' +// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior +// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior +// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior +// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior +// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior +// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior +// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior // :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior @@ -1423,13 +1423,13 @@ const std = @import("std"); // :79:17: error: use of undefined value here causes illegal behavior // :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '0' +// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '0' +// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '0' +// :79:17: note: when computing vector element at index '1' // :79:17: error: use of undefined value here causes illegal behavior -// :79:17: note: when computing vector element at index '0' +// :79:17: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior // :82:27: error: use of undefined value here causes illegal behavior // :82:27: error: use of undefined value here causes illegal behavior @@ -1437,21 +1437,13 @@ const std = @import("std"); // :82:27: error: use of undefined value here causes illegal behavior // :82:27: error: use of undefined value here causes illegal behavior // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior // :82:27: error: use of undefined value here causes illegal behavior // :82:27: error: use of undefined value here causes illegal behavior @@ -1459,21 +1451,13 @@ const std = @import("std"); // :82:27: error: use of undefined value here causes illegal behavior // :82:27: error: use of undefined value here causes illegal behavior // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior // :82:27: error: use of undefined value here causes illegal behavior // :82:27: error: use of undefined value here causes illegal behavior @@ -1481,13 +1465,11 @@ const std = @import("std"); // :82:27: error: use of undefined value here causes illegal behavior // :82:27: error: use of undefined value here causes illegal behavior // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '1' +// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '1' +// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior // :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior @@ -1497,19 +1479,25 @@ const std = @import("std"); // :82:27: error: use of undefined value here causes illegal behavior // :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior +// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior +// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior +// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior +// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior +// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior +// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '1' +// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '1' +// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '1' +// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '1' +// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior // :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior @@ -1519,11 +1507,17 @@ const std = @import("std"); // :82:27: error: use of undefined value here causes illegal behavior // :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior +// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior +// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior +// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior +// :82:27: note: when computing vector element at index '0' // :82:27: error: use of undefined value here causes illegal behavior +// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior +// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior // :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior @@ -1533,19 +1527,25 @@ const std = @import("std"); // :82:27: error: use of undefined value here causes illegal behavior // :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '0' +// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '0' +// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '0' +// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '0' +// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior +// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior +// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior +// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior +// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior +// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior +// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior // :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior @@ -1555,44 +1555,37 @@ const std = @import("std"); // :82:27: error: use of undefined value here causes illegal behavior // :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '0' +// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '0' +// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '0' +// :82:27: note: when computing vector element at index '1' // :82:27: error: use of undefined value here causes illegal behavior -// :82:27: note: when computing vector element at index '0' +// :82:27: note: when computing vector element at index '1' // :87:17: error: use of undefined value here causes illegal behavior // :87:17: error: use of undefined value here causes illegal behavior -// :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior -// :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior -// :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior -// :87:17: note: when computing vector element at index '1' // :87:17: error: use of undefined value here causes illegal behavior -// :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior -// :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior -// :87:17: note: when computing vector element at index '1' -// :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior +// :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior @@ -1600,7 +1593,7 @@ const std = @import("std"); // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior -// :87:17: note: when computing vector element at index '1' +// :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior @@ -1608,6 +1601,7 @@ const std = @import("std"); // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior +// :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior @@ -1615,7 +1609,7 @@ const std = @import("std"); // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior -// :87:17: note: when computing vector element at index '1' +// :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior @@ -1623,6 +1617,7 @@ const std = @import("std"); // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior +// :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior @@ -1630,7 +1625,7 @@ const std = @import("std"); // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior -// :87:17: note: when computing vector element at index '1' +// :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior @@ -1638,6 +1633,7 @@ const std = @import("std"); // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior +// :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '0' // :87:17: error: use of undefined value here causes illegal behavior @@ -1647,108 +1643,105 @@ const std = @import("std"); // :87:17: error: use of undefined value here causes illegal behavior // :87:17: note: when computing vector element at index '1' // :87:17: error: use of undefined value here causes illegal behavior -// :87:17: note: when computing vector element at index '0' +// :87:17: note: when computing vector element at index '1' // :87:17: error: use of undefined value here causes illegal behavior -// :87:17: note: when computing vector element at index '0' +// :87:17: note: when computing vector element at index '1' // :87:17: error: use of undefined value here causes illegal behavior -// :87:17: note: when computing vector element at index '0' +// :87:17: note: when computing vector element at index '1' +// :87:17: error: use of undefined value here causes illegal behavior +// :87:17: note: when computing vector element at index '1' +// :87:17: error: use of undefined value here causes illegal behavior +// :87:17: note: when computing vector element at index '1' // :87:22: error: use of undefined value here causes illegal behavior // :87:22: error: use of undefined value here causes illegal behavior -// :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior -// :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior -// :87:22: note: when computing vector element at index '1' // :87:22: error: use of undefined value here causes illegal behavior -// :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior -// :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior +// :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior // :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior // :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior -// :87:22: note: when computing vector element at index '1' +// :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior // :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior // :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior +// :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior // :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior // :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior -// :87:22: note: when computing vector element at index '1' +// :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior // :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior // :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior +// :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior // :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior // :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior -// :87:22: note: when computing vector element at index '1' +// :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior // :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior // :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior +// :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior // :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior // :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior -// :87:22: note: when computing vector element at index '1' +// :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior // :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior // :87:22: note: when computing vector element at index '0' // :87:22: error: use of undefined value here causes illegal behavior +// :87:22: note: when computing vector element at index '1' // :87:22: error: use of undefined value here causes illegal behavior -// :87:22: note: when computing vector element at index '0' +// :87:22: note: when computing vector element at index '1' // :87:22: error: use of undefined value here causes illegal behavior -// :87:22: note: when computing vector element at index '0' +// :87:22: note: when computing vector element at index '1' // :87:22: error: use of undefined value here causes illegal behavior // :87:22: note: when computing vector element at index '1' // :87:22: error: use of undefined value here causes illegal behavior -// :87:22: note: when computing vector element at index '0' +// :87:22: note: when computing vector element at index '1' // :87:22: error: use of undefined value here causes illegal behavior -// :87:22: note: when computing vector element at index '0' +// :87:22: note: when computing vector element at index '1' // :90:27: error: use of undefined value here causes illegal behavior // :90:27: error: use of undefined value here causes illegal behavior -// :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior -// :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior -// :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior -// :90:27: note: when computing vector element at index '1' // :90:27: error: use of undefined value here causes illegal behavior -// :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior -// :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior -// :90:27: note: when computing vector element at index '1' -// :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior +// :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior @@ -1756,7 +1749,7 @@ const std = @import("std"); // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior -// :90:27: note: when computing vector element at index '1' +// :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior @@ -1764,6 +1757,7 @@ const std = @import("std"); // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior +// :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior @@ -1771,7 +1765,7 @@ const std = @import("std"); // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior -// :90:27: note: when computing vector element at index '1' +// :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior @@ -1779,6 +1773,7 @@ const std = @import("std"); // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior +// :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior @@ -1786,7 +1781,7 @@ const std = @import("std"); // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior -// :90:27: note: when computing vector element at index '1' +// :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior @@ -1794,6 +1789,7 @@ const std = @import("std"); // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior +// :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '0' // :90:27: error: use of undefined value here causes illegal behavior @@ -1803,108 +1799,105 @@ const std = @import("std"); // :90:27: error: use of undefined value here causes illegal behavior // :90:27: note: when computing vector element at index '1' // :90:27: error: use of undefined value here causes illegal behavior -// :90:27: note: when computing vector element at index '0' +// :90:27: note: when computing vector element at index '1' // :90:27: error: use of undefined value here causes illegal behavior -// :90:27: note: when computing vector element at index '0' +// :90:27: note: when computing vector element at index '1' // :90:27: error: use of undefined value here causes illegal behavior -// :90:27: note: when computing vector element at index '0' +// :90:27: note: when computing vector element at index '1' +// :90:27: error: use of undefined value here causes illegal behavior +// :90:27: note: when computing vector element at index '1' +// :90:27: error: use of undefined value here causes illegal behavior +// :90:27: note: when computing vector element at index '1' // :90:30: error: use of undefined value here causes illegal behavior // :90:30: error: use of undefined value here causes illegal behavior -// :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior -// :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior -// :90:30: note: when computing vector element at index '1' // :90:30: error: use of undefined value here causes illegal behavior -// :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior -// :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior +// :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior // :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior // :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior -// :90:30: note: when computing vector element at index '1' +// :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior // :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior // :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior +// :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior // :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior // :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior -// :90:30: note: when computing vector element at index '1' +// :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior // :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior // :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior +// :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior // :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior // :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior -// :90:30: note: when computing vector element at index '1' +// :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior // :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior // :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior +// :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior // :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior // :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior -// :90:30: note: when computing vector element at index '1' +// :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior // :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior // :90:30: note: when computing vector element at index '0' // :90:30: error: use of undefined value here causes illegal behavior +// :90:30: note: when computing vector element at index '1' // :90:30: error: use of undefined value here causes illegal behavior -// :90:30: note: when computing vector element at index '0' +// :90:30: note: when computing vector element at index '1' // :90:30: error: use of undefined value here causes illegal behavior -// :90:30: note: when computing vector element at index '0' +// :90:30: note: when computing vector element at index '1' // :90:30: error: use of undefined value here causes illegal behavior // :90:30: note: when computing vector element at index '1' // :90:30: error: use of undefined value here causes illegal behavior -// :90:30: note: when computing vector element at index '0' +// :90:30: note: when computing vector element at index '1' // :90:30: error: use of undefined value here causes illegal behavior -// :90:30: note: when computing vector element at index '0' +// :90:30: note: when computing vector element at index '1' // :93:34: error: use of undefined value here causes illegal behavior // :93:34: error: use of undefined value here causes illegal behavior -// :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior -// :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior -// :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior -// :93:34: note: when computing vector element at index '1' // :93:34: error: use of undefined value here causes illegal behavior -// :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior -// :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior -// :93:34: note: when computing vector element at index '1' -// :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior +// :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior @@ -1912,7 +1905,7 @@ const std = @import("std"); // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior -// :93:34: note: when computing vector element at index '1' +// :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior @@ -1920,6 +1913,7 @@ const std = @import("std"); // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior +// :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior @@ -1927,7 +1921,7 @@ const std = @import("std"); // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior -// :93:34: note: when computing vector element at index '1' +// :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior @@ -1935,6 +1929,7 @@ const std = @import("std"); // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior +// :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior @@ -1942,7 +1937,7 @@ const std = @import("std"); // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior -// :93:34: note: when computing vector element at index '1' +// :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior @@ -1950,6 +1945,7 @@ const std = @import("std"); // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior +// :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '0' // :93:34: error: use of undefined value here causes illegal behavior @@ -1959,108 +1955,105 @@ const std = @import("std"); // :93:34: error: use of undefined value here causes illegal behavior // :93:34: note: when computing vector element at index '1' // :93:34: error: use of undefined value here causes illegal behavior -// :93:34: note: when computing vector element at index '0' +// :93:34: note: when computing vector element at index '1' // :93:34: error: use of undefined value here causes illegal behavior -// :93:34: note: when computing vector element at index '0' +// :93:34: note: when computing vector element at index '1' // :93:34: error: use of undefined value here causes illegal behavior -// :93:34: note: when computing vector element at index '0' +// :93:34: note: when computing vector element at index '1' +// :93:34: error: use of undefined value here causes illegal behavior +// :93:34: note: when computing vector element at index '1' +// :93:34: error: use of undefined value here causes illegal behavior +// :93:34: note: when computing vector element at index '1' // :93:37: error: use of undefined value here causes illegal behavior // :93:37: error: use of undefined value here causes illegal behavior -// :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior -// :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior -// :93:37: note: when computing vector element at index '1' // :93:37: error: use of undefined value here causes illegal behavior -// :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior -// :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior +// :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior // :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior // :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior -// :93:37: note: when computing vector element at index '1' +// :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior // :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior // :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior +// :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior // :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior // :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior -// :93:37: note: when computing vector element at index '1' +// :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior // :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior // :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior +// :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior // :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior // :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior -// :93:37: note: when computing vector element at index '1' +// :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior // :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior // :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior +// :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior // :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior // :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior -// :93:37: note: when computing vector element at index '1' +// :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior // :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior // :93:37: note: when computing vector element at index '0' // :93:37: error: use of undefined value here causes illegal behavior +// :93:37: note: when computing vector element at index '1' // :93:37: error: use of undefined value here causes illegal behavior -// :93:37: note: when computing vector element at index '0' +// :93:37: note: when computing vector element at index '1' // :93:37: error: use of undefined value here causes illegal behavior -// :93:37: note: when computing vector element at index '0' +// :93:37: note: when computing vector element at index '1' // :93:37: error: use of undefined value here causes illegal behavior // :93:37: note: when computing vector element at index '1' // :93:37: error: use of undefined value here causes illegal behavior -// :93:37: note: when computing vector element at index '0' +// :93:37: note: when computing vector element at index '1' // :93:37: error: use of undefined value here causes illegal behavior -// :93:37: note: when computing vector element at index '0' +// :93:37: note: when computing vector element at index '1' // :96:17: error: use of undefined value here causes illegal behavior // :96:17: error: use of undefined value here causes illegal behavior -// :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior -// :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior -// :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior -// :96:17: note: when computing vector element at index '1' // :96:17: error: use of undefined value here causes illegal behavior -// :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior -// :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior -// :96:17: note: when computing vector element at index '1' -// :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior +// :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior @@ -2068,7 +2061,7 @@ const std = @import("std"); // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior -// :96:17: note: when computing vector element at index '1' +// :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior @@ -2076,6 +2069,7 @@ const std = @import("std"); // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior +// :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior @@ -2083,7 +2077,7 @@ const std = @import("std"); // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior -// :96:17: note: when computing vector element at index '1' +// :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior @@ -2091,6 +2085,7 @@ const std = @import("std"); // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior +// :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior @@ -2098,7 +2093,7 @@ const std = @import("std"); // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior -// :96:17: note: when computing vector element at index '1' +// :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior @@ -2106,6 +2101,7 @@ const std = @import("std"); // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior +// :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '0' // :96:17: error: use of undefined value here causes illegal behavior @@ -2115,67 +2111,65 @@ const std = @import("std"); // :96:17: error: use of undefined value here causes illegal behavior // :96:17: note: when computing vector element at index '1' // :96:17: error: use of undefined value here causes illegal behavior -// :96:17: note: when computing vector element at index '0' +// :96:17: note: when computing vector element at index '1' // :96:17: error: use of undefined value here causes illegal behavior -// :96:17: note: when computing vector element at index '0' +// :96:17: note: when computing vector element at index '1' // :96:17: error: use of undefined value here causes illegal behavior -// :96:17: note: when computing vector element at index '0' -// :96:22: error: use of undefined value here causes illegal behavior -// :96:22: error: use of undefined value here causes illegal behavior -// :96:22: note: when computing vector element at index '0' +// :96:17: note: when computing vector element at index '1' +// :96:17: error: use of undefined value here causes illegal behavior +// :96:17: note: when computing vector element at index '1' +// :96:17: error: use of undefined value here causes illegal behavior +// :96:17: note: when computing vector element at index '1' // :96:22: error: use of undefined value here causes illegal behavior -// :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior -// :96:22: note: when computing vector element at index '1' // :96:22: error: use of undefined value here causes illegal behavior -// :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior -// :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior // :96:22: error: use of undefined value here causes illegal behavior -// :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior // :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior -// :96:22: note: when computing vector element at index '1' -// :96:22: error: use of undefined value here causes illegal behavior // :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior // :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior +// :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior // :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior // :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior -// :96:22: note: when computing vector element at index '1' +// :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior // :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior // :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior +// :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior // :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior // :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior -// :96:22: note: when computing vector element at index '1' +// :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior // :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior // :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior +// :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior // :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior // :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior -// :96:22: note: when computing vector element at index '1' +// :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior // :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior // :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior +// :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior // :96:22: note: when computing vector element at index '0' // :96:22: error: use of undefined value here causes illegal behavior @@ -2183,40 +2177,39 @@ const std = @import("std"); // :96:22: error: use of undefined value here causes illegal behavior // :96:22: note: when computing vector element at index '1' // :96:22: error: use of undefined value here causes illegal behavior -// :96:22: note: when computing vector element at index '0' +// :96:22: note: when computing vector element at index '1' // :96:22: error: use of undefined value here causes illegal behavior -// :96:22: note: when computing vector element at index '0' +// :96:22: note: when computing vector element at index '1' +// :96:22: error: use of undefined value here causes illegal behavior +// :96:22: note: when computing vector element at index '1' +// :96:22: error: use of undefined value here causes illegal behavior +// :96:22: note: when computing vector element at index '1' +// :96:22: error: use of undefined value here causes illegal behavior +// :96:22: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' -// :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior @@ -2224,7 +2217,7 @@ const std = @import("std"); // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior @@ -2232,6 +2225,7 @@ const std = @import("std"); // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior @@ -2239,7 +2233,7 @@ const std = @import("std"); // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior @@ -2247,6 +2241,7 @@ const std = @import("std"); // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior @@ -2254,7 +2249,7 @@ const std = @import("std"); // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '1' +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior @@ -2262,6 +2257,7 @@ const std = @import("std"); // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '0' // :99:27: error: use of undefined value here causes illegal behavior @@ -2271,77 +2267,81 @@ const std = @import("std"); // :99:27: error: use of undefined value here causes illegal behavior // :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' +// :99:27: note: when computing vector element at index '1' // :99:27: error: use of undefined value here causes illegal behavior -// :99:27: note: when computing vector element at index '0' +// :99:27: note: when computing vector element at index '1' +// :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' +// :99:27: error: use of undefined value here causes illegal behavior +// :99:27: note: when computing vector element at index '1' // :99:30: error: use of undefined value here causes illegal behavior // :99:30: error: use of undefined value here causes illegal behavior -// :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior -// :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior -// :99:30: note: when computing vector element at index '1' // :99:30: error: use of undefined value here causes illegal behavior -// :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior -// :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior +// :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior // :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior // :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior -// :99:30: note: when computing vector element at index '1' +// :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior // :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior // :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior +// :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior // :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior // :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior -// :99:30: note: when computing vector element at index '1' +// :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior // :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior // :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior +// :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior // :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior // :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior -// :99:30: note: when computing vector element at index '1' +// :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior // :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior // :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior +// :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior // :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior // :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior -// :99:30: note: when computing vector element at index '1' +// :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior // :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior // :99:30: note: when computing vector element at index '0' // :99:30: error: use of undefined value here causes illegal behavior +// :99:30: note: when computing vector element at index '1' // :99:30: error: use of undefined value here causes illegal behavior -// :99:30: note: when computing vector element at index '0' +// :99:30: note: when computing vector element at index '1' // :99:30: error: use of undefined value here causes illegal behavior -// :99:30: note: when computing vector element at index '0' +// :99:30: note: when computing vector element at index '1' // :99:30: error: use of undefined value here causes illegal behavior // :99:30: note: when computing vector element at index '1' // :99:30: error: use of undefined value here causes illegal behavior -// :99:30: note: when computing vector element at index '0' +// :99:30: note: when computing vector element at index '1' // :99:30: error: use of undefined value here causes illegal behavior -// :99:30: note: when computing vector element at index '0' +// :99:30: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior // :104:22: error: use of undefined value here causes illegal behavior // :104:22: error: use of undefined value here causes illegal behavior @@ -2349,21 +2349,13 @@ const std = @import("std"); // :104:22: error: use of undefined value here causes illegal behavior // :104:22: error: use of undefined value here causes illegal behavior // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior // :104:22: error: use of undefined value here causes illegal behavior // :104:22: error: use of undefined value here causes illegal behavior @@ -2371,21 +2363,13 @@ const std = @import("std"); // :104:22: error: use of undefined value here causes illegal behavior // :104:22: error: use of undefined value here causes illegal behavior // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior // :104:22: error: use of undefined value here causes illegal behavior // :104:22: error: use of undefined value here causes illegal behavior @@ -2393,13 +2377,11 @@ const std = @import("std"); // :104:22: error: use of undefined value here causes illegal behavior // :104:22: error: use of undefined value here causes illegal behavior // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '1' +// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '1' +// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior // :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior @@ -2409,19 +2391,25 @@ const std = @import("std"); // :104:22: error: use of undefined value here causes illegal behavior // :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior +// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior +// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior +// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior +// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior +// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior +// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '1' +// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '1' +// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '1' +// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '1' +// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior // :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior @@ -2431,11 +2419,17 @@ const std = @import("std"); // :104:22: error: use of undefined value here causes illegal behavior // :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior +// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior +// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior +// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior +// :104:22: note: when computing vector element at index '0' // :104:22: error: use of undefined value here causes illegal behavior +// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior +// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior // :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior @@ -2445,19 +2439,25 @@ const std = @import("std"); // :104:22: error: use of undefined value here causes illegal behavior // :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '0' +// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '0' +// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '0' +// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '0' +// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior +// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior +// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior +// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior +// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior +// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior +// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior // :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior @@ -2467,13 +2467,13 @@ const std = @import("std"); // :104:22: error: use of undefined value here causes illegal behavior // :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '0' +// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '0' +// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '0' +// :104:22: note: when computing vector element at index '1' // :104:22: error: use of undefined value here causes illegal behavior -// :104:22: note: when computing vector element at index '0' +// :104:22: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior // :107:30: error: use of undefined value here causes illegal behavior // :107:30: error: use of undefined value here causes illegal behavior @@ -2481,21 +2481,13 @@ const std = @import("std"); // :107:30: error: use of undefined value here causes illegal behavior // :107:30: error: use of undefined value here causes illegal behavior // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior // :107:30: error: use of undefined value here causes illegal behavior // :107:30: error: use of undefined value here causes illegal behavior @@ -2503,21 +2495,13 @@ const std = @import("std"); // :107:30: error: use of undefined value here causes illegal behavior // :107:30: error: use of undefined value here causes illegal behavior // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior // :107:30: error: use of undefined value here causes illegal behavior // :107:30: error: use of undefined value here causes illegal behavior @@ -2525,13 +2509,11 @@ const std = @import("std"); // :107:30: error: use of undefined value here causes illegal behavior // :107:30: error: use of undefined value here causes illegal behavior // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '1' +// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '1' +// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior // :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior @@ -2541,19 +2523,25 @@ const std = @import("std"); // :107:30: error: use of undefined value here causes illegal behavior // :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior +// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior +// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior +// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior +// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior +// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior +// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '1' +// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '1' +// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '1' +// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '1' +// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior // :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior @@ -2563,11 +2551,17 @@ const std = @import("std"); // :107:30: error: use of undefined value here causes illegal behavior // :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior +// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior +// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior +// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior +// :107:30: note: when computing vector element at index '0' // :107:30: error: use of undefined value here causes illegal behavior +// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior +// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior // :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior @@ -2577,19 +2571,25 @@ const std = @import("std"); // :107:30: error: use of undefined value here causes illegal behavior // :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '0' +// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '0' +// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '0' +// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '0' +// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior +// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior +// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior +// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior +// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior +// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior +// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior // :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior @@ -2599,13 +2599,13 @@ const std = @import("std"); // :107:30: error: use of undefined value here causes illegal behavior // :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '0' +// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '0' +// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '0' +// :107:30: note: when computing vector element at index '1' // :107:30: error: use of undefined value here causes illegal behavior -// :107:30: note: when computing vector element at index '0' +// :107:30: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior // :110:37: error: use of undefined value here causes illegal behavior // :110:37: error: use of undefined value here causes illegal behavior @@ -2613,21 +2613,13 @@ const std = @import("std"); // :110:37: error: use of undefined value here causes illegal behavior // :110:37: error: use of undefined value here causes illegal behavior // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior // :110:37: error: use of undefined value here causes illegal behavior // :110:37: error: use of undefined value here causes illegal behavior @@ -2635,21 +2627,13 @@ const std = @import("std"); // :110:37: error: use of undefined value here causes illegal behavior // :110:37: error: use of undefined value here causes illegal behavior // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior // :110:37: error: use of undefined value here causes illegal behavior // :110:37: error: use of undefined value here causes illegal behavior @@ -2657,13 +2641,11 @@ const std = @import("std"); // :110:37: error: use of undefined value here causes illegal behavior // :110:37: error: use of undefined value here causes illegal behavior // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '1' +// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '1' +// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior // :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior @@ -2673,19 +2655,25 @@ const std = @import("std"); // :110:37: error: use of undefined value here causes illegal behavior // :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior +// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior +// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior +// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior +// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior +// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior +// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '1' +// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '1' +// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '1' +// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '1' +// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior // :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior @@ -2695,11 +2683,17 @@ const std = @import("std"); // :110:37: error: use of undefined value here causes illegal behavior // :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior +// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior +// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior +// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior +// :110:37: note: when computing vector element at index '0' // :110:37: error: use of undefined value here causes illegal behavior +// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior +// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior // :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior @@ -2709,19 +2703,25 @@ const std = @import("std"); // :110:37: error: use of undefined value here causes illegal behavior // :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '0' +// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '0' +// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '0' +// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '0' +// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior +// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior +// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior +// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior +// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior +// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior +// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior // :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior @@ -2731,13 +2731,13 @@ const std = @import("std"); // :110:37: error: use of undefined value here causes illegal behavior // :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '0' +// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '0' +// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '0' +// :110:37: note: when computing vector element at index '1' // :110:37: error: use of undefined value here causes illegal behavior -// :110:37: note: when computing vector element at index '0' +// :110:37: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior // :113:22: error: use of undefined value here causes illegal behavior // :113:22: error: use of undefined value here causes illegal behavior @@ -2745,21 +2745,13 @@ const std = @import("std"); // :113:22: error: use of undefined value here causes illegal behavior // :113:22: error: use of undefined value here causes illegal behavior // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior // :113:22: error: use of undefined value here causes illegal behavior // :113:22: error: use of undefined value here causes illegal behavior @@ -2767,21 +2759,13 @@ const std = @import("std"); // :113:22: error: use of undefined value here causes illegal behavior // :113:22: error: use of undefined value here causes illegal behavior // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior // :113:22: error: use of undefined value here causes illegal behavior // :113:22: error: use of undefined value here causes illegal behavior @@ -2789,13 +2773,11 @@ const std = @import("std"); // :113:22: error: use of undefined value here causes illegal behavior // :113:22: error: use of undefined value here causes illegal behavior // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '1' +// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '1' +// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior // :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior @@ -2805,19 +2787,25 @@ const std = @import("std"); // :113:22: error: use of undefined value here causes illegal behavior // :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior +// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior +// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior +// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior +// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior +// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior +// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '1' +// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '1' +// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '1' +// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '1' +// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior // :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior @@ -2827,11 +2815,17 @@ const std = @import("std"); // :113:22: error: use of undefined value here causes illegal behavior // :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior +// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior +// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior +// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior +// :113:22: note: when computing vector element at index '0' // :113:22: error: use of undefined value here causes illegal behavior +// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior +// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior // :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior @@ -2841,19 +2835,25 @@ const std = @import("std"); // :113:22: error: use of undefined value here causes illegal behavior // :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '0' +// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '0' +// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '0' +// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '0' +// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior +// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior +// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior +// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior +// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior +// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior +// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior // :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior @@ -2863,13 +2863,13 @@ const std = @import("std"); // :113:22: error: use of undefined value here causes illegal behavior // :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '0' +// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '0' +// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '0' +// :113:22: note: when computing vector element at index '1' // :113:22: error: use of undefined value here causes illegal behavior -// :113:22: note: when computing vector element at index '0' +// :113:22: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior // :116:30: error: use of undefined value here causes illegal behavior // :116:30: error: use of undefined value here causes illegal behavior @@ -2877,21 +2877,13 @@ const std = @import("std"); // :116:30: error: use of undefined value here causes illegal behavior // :116:30: error: use of undefined value here causes illegal behavior // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior // :116:30: error: use of undefined value here causes illegal behavior // :116:30: error: use of undefined value here causes illegal behavior @@ -2899,21 +2891,13 @@ const std = @import("std"); // :116:30: error: use of undefined value here causes illegal behavior // :116:30: error: use of undefined value here causes illegal behavior // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior // :116:30: error: use of undefined value here causes illegal behavior // :116:30: error: use of undefined value here causes illegal behavior @@ -2921,13 +2905,11 @@ const std = @import("std"); // :116:30: error: use of undefined value here causes illegal behavior // :116:30: error: use of undefined value here causes illegal behavior // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '1' +// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '1' +// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior // :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior @@ -2937,19 +2919,25 @@ const std = @import("std"); // :116:30: error: use of undefined value here causes illegal behavior // :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior +// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior +// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior +// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior +// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior +// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior +// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '1' +// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '1' +// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '1' +// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '1' +// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior // :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior @@ -2959,11 +2947,17 @@ const std = @import("std"); // :116:30: error: use of undefined value here causes illegal behavior // :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior +// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior +// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior +// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior +// :116:30: note: when computing vector element at index '0' // :116:30: error: use of undefined value here causes illegal behavior +// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior +// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior // :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior @@ -2973,19 +2967,25 @@ const std = @import("std"); // :116:30: error: use of undefined value here causes illegal behavior // :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '0' +// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '0' +// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '0' +// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '0' +// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior +// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior +// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior +// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior +// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior +// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior +// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior // :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior @@ -2995,10 +2995,10 @@ const std = @import("std"); // :116:30: error: use of undefined value here causes illegal behavior // :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '0' +// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '0' +// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '0' +// :116:30: note: when computing vector element at index '1' // :116:30: error: use of undefined value here causes illegal behavior -// :116:30: note: when computing vector element at index '0' +// :116:30: note: when computing vector element at index '1' diff --git a/test/cases/compile_errors/union_auto-enum_value_already_taken.zig b/test/cases/compile_errors/union_auto-enum_value_already_taken.zig index 214fd1bdacd8144e9323c7b451d050c4cec3844f..8756e8400ff263abc78db857a657fbc56bef419d 100644 --- a/test/cases/compile_errors/union_auto-enum_value_already_taken.zig +++ b/test/cases/compile_errors/union_auto-enum_value_already_taken.zig @@ -12,5 +12,5 @@ export fn entry() void { // error // -// :6:9: error: enum tag value 60 already taken -// :4:9: note: other occurrence here +// :6:9: error: enum tag value '60' for field 'E' already taken +// :4:9: note: previous occurrence in field 'C' diff --git a/test/cases/compile_errors/union_depends_on_pointer_alignment.zig b/test/cases/compile_errors/union_depends_on_pointer_alignment.zig deleted file mode 100644 index 2b97a3fb54207efde38a61c0fc505f7b0721b984..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/union_depends_on_pointer_alignment.zig +++ /dev/null @@ -1,11 +0,0 @@ -const U = union { - next: ?*align(1) U align(128), -}; - -export fn entry() usize { - return @alignOf(U); -} - -// error -// -// :1:11: error: union layout depends on being pointer aligned diff --git a/test/cases/compile_errors/union_enum_field_missing.zig b/test/cases/compile_errors/union_enum_field_missing.zig index c376b72da18c895b2c6c565014f6cc38737f0147..6261d452960947b8ab9e8f8ff1ac17ca3abed35c 100644 --- a/test/cases/compile_errors/union_enum_field_missing.zig +++ b/test/cases/compile_errors/union_enum_field_missing.zig @@ -15,6 +15,5 @@ export fn entry() usize { // error // -// :7:11: error: enum field(s) missing in union -// :4:5: note: field 'c' missing, declared here -// :1:11: note: enum declared here +// :7:11: error: enum field 'c' missing from union +// :4:5: note: enum field here diff --git a/test/cases/compile_errors/union_field_ordered_differently_than_enum.zig b/test/cases/compile_errors/union_field_ordered_differently_than_enum.zig index 5c86fb4080cd7f25cccb3a44c0f9b6415be07b4f..6c1e1ccea8608307964a43ac2347d120b4ed4926 100644 --- a/test/cases/compile_errors/union_field_ordered_differently_than_enum.zig +++ b/test/cases/compile_errors/union_field_ordered_differently_than_enum.zig @@ -21,7 +21,6 @@ export fn entry() usize { // error // -// :4:5: error: union field 'b' ordered differently than corresponding enum field -// :1:23: note: enum field here -// :14:5: error: union field 'b' ordered differently than corresponding enum field -// :10:5: note: enum field here +// :3:15: error: union field order does not match tag enum field order +// :5:5: note: union field 'a' is index 1 +// :1:20: note: enum field 'a' is index 0 diff --git a/test/cases/compile_errors/union_noreturn_field_initialized.zig b/test/cases/compile_errors/union_noreturn_field_initialized.zig index 3fdc1958703ea9076a0399fac46b8bfdae50b822..da0bd8c5d89613e9e9a026d526491f65a1162055 100644 --- a/test/cases/compile_errors/union_noreturn_field_initialized.zig +++ b/test/cases/compile_errors/union_noreturn_field_initialized.zig @@ -15,8 +15,8 @@ pub export fn entry2() void { const U = union(enum) { a: noreturn, }; - var u: U = undefined; - u = .a; + const u: U = .a; + _ = u; } pub export fn entry3() void { const U = union(enum) { @@ -30,12 +30,12 @@ pub export fn entry3() void { // error // -// :11:14: error: cannot initialize 'noreturn' field of union +// :11:14: error: cannot initialize union field with uninstantiable type 'noreturn' // :4:9: note: field 'b' declared here // :2:15: note: union declared here -// :19:10: error: cannot initialize 'noreturn' field of union +// :18:19: error: cannot initialize union field with uninstantiable type 'noreturn' // :16:9: note: field 'a' declared here // :15:15: note: union declared here -// :28:13: error: runtime coercion from enum '@typeInfo(tmp.entry3.U).@"union".tag_type.?' to union 'tmp.entry3.U' which has a 'noreturn' field -// :23:9: note: 'noreturn' field here +// :28:13: error: runtime coercion from enum '@typeInfo(tmp.entry3.U).@"union".tag_type.?' to union 'tmp.entry3.U' which has non-void fields +// :23:9: note: field 'a' has uninstantiable type 'noreturn' // :22:15: note: union declared here diff --git a/test/cases/compile_errors/union_with_specified_enum_omits_field.zig b/test/cases/compile_errors/union_with_specified_enum_omits_field.zig index bae2cf2957016281fced4d06bb6464e644851869..e90e60494558730285faa258fab24e8e5253b9a6 100644 --- a/test/cases/compile_errors/union_with_specified_enum_omits_field.zig +++ b/test/cases/compile_errors/union_with_specified_enum_omits_field.zig @@ -13,6 +13,5 @@ export fn entry() usize { // error // -// :6:17: error: enum field(s) missing in union -// :4:5: note: field 'C' missing, declared here -// :1:16: note: enum declared here +// :6:17: error: enum field 'C' missing from union +// :4:5: note: enum field here diff --git a/test/cases/compile_errors/union_with_too_small_explicit_signed_tag_type.zig b/test/cases/compile_errors/union_with_too_small_explicit_signed_tag_type.zig index 6a6076e9465e594ea0403ad156d6c1fc8f45b6de..fb9e7091017241c16ce3bf8554102ddf7d6fe64b 100644 --- a/test/cases/compile_errors/union_with_too_small_explicit_signed_tag_type.zig +++ b/test/cases/compile_errors/union_with_too_small_explicit_signed_tag_type.zig @@ -10,5 +10,4 @@ export fn entry() void { // error // -// :1:22: error: specified integer tag type cannot represent every field -// :1:22: note: type 'i2' cannot fit values in range 0...3 +// :4:5: error: enum tag value '2' too large for type 'i2' diff --git a/test/cases/compile_errors/union_with_too_small_explicit_unsigned_tag_type.zig b/test/cases/compile_errors/union_with_too_small_explicit_unsigned_tag_type.zig index 830c5634a1281e73b8d1a453a5276503a0e88658..2df10ea0748171a74255c856e8072a2c2d7ab2b7 100644 --- a/test/cases/compile_errors/union_with_too_small_explicit_unsigned_tag_type.zig +++ b/test/cases/compile_errors/union_with_too_small_explicit_unsigned_tag_type.zig @@ -11,5 +11,4 @@ export fn entry() void { // error // -// :1:22: error: specified integer tag type cannot represent every field -// :1:22: note: type 'u2' cannot fit values in range 0...4 +// :6:5: error: enum tag value '4' too large for type 'u2' diff --git a/test/cases/compile_errors/untagged_union_integer_conversion.zig b/test/cases/compile_errors/untagged_union_integer_conversion.zig index e469cd125bc9a957cb9efe5a0e9922d45530cfdb..0a8fb54602598dfdc07f28c75ae06f8c3cd2b783 100644 --- a/test/cases/compile_errors/untagged_union_integer_conversion.zig +++ b/test/cases/compile_errors/untagged_union_integer_conversion.zig @@ -1,4 +1,4 @@ -const UntaggedUnion = union {}; +const UntaggedUnion = union { a: void }; comptime { @intFromEnum(@as(UntaggedUnion, undefined)); } diff --git a/test/cases/compile_errors/variadic_arg_validation.zig b/test/cases/compile_errors/variadic_arg_validation.zig index c7a8219f2f54889aa132458828a989856709db90..f28622426f76e7757b4bfa253ae7aac86a3250c9 100644 --- a/test/cases/compile_errors/variadic_arg_validation.zig +++ b/test/cases/compile_errors/variadic_arg_validation.zig @@ -25,4 +25,4 @@ pub export fn entry3() void { // :14:24: error: cannot pass 'u48' to variadic function // :14:24: note: only integers with 0 or power of two bits are extern compatible // :18:24: error: cannot pass 'void' to variadic function -// :18:24: note: 'void' is a zero bit type; for C 'void' use 'anyopaque' +// :18:24: note: 'void' is a zero bit type diff --git a/test/cases/compile_errors/zero_width_nonexhaustive_enum.zig b/test/cases/compile_errors/zero_width_nonexhaustive_enum.zig index a38c5f357adc794b0049473eea29e636bbad0203..4ec7297dce19ae33d988ffc96868f44552ff6752 100644 --- a/test/cases/compile_errors/zero_width_nonexhaustive_enum.zig +++ b/test/cases/compile_errors/zero_width_nonexhaustive_enum.zig @@ -1,17 +1,20 @@ comptime { - _ = enum(i0) { a, _ }; + const E = enum(i0) { a, _ }; + _ = @as(E, undefined); } comptime { - _ = enum(u0) { a, _ }; + const E = enum(u0) { a, _ }; + _ = @as(E, undefined); } comptime { - _ = enum(u0) { a, b, _ }; + const E = enum(u0) { a, b, _ }; + _ = @as(E, undefined); } // error // -// :2:9: error: non-exhaustive enum specifies every value -// :6:9: error: non-exhaustive enum specifies every value -// :10:23: error: enumeration value '1' too large for type 'u0' +// :2:15: error: non-exhaustive enum specifies every value +// :7:15: error: non-exhaustive enum specifies every value +// :12:29: error: enum tag value '1' too large for type 'u0' diff --git a/test/incremental/change_enum_tag_type b/test/incremental/change_enum_tag_type index 97103351995157bd82b99b96913ffaa6165d2f96..46681407cb6a259e44b1e6071281ecc302b14967 100644 --- a/test/incremental/change_enum_tag_type +++ b/test/incremental/change_enum_tag_type @@ -44,7 +44,7 @@ comptime { } const std = @import("std"); const io = std.Io.Threaded.global_single_threaded.io(); -#expect_error=main.zig:7:5: error: enumeration value '4' too large for type 'u2' +#expect_error=main.zig:7:5: error: enum tag value '4' too large for type 'u2' #update=increase tag size #file=main.zig const Tag = u3; -- 2.54.0 From 9c9a5e722b84d12de34d16f53355adbe1f5e11d3 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Mon, 2 Mar 2026 15:45:35 +0000 Subject: [PATCH 62/79] Sema: match master's weird pointer difference semantics for now ...except for master's handling of pointers to vectors, because that was unambiguously a bug. --- src/Sema.zig | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 2af1c8cf107895931f393e0298defc8bd6ddcbda..644bad5dcaf48938a4ecf925f54dbee7d4e1de86 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -15249,15 +15249,25 @@ fn analyzeArithmetic( return sema.failWithInvalidPtrArithmetic(block, src, "pointer-pointer", "subtraction"); } - // MLUGG TODO: these semantics are insane and matching them is causing my soul to fragment into a thousand pieces + // TODO: these semantics are really weird. Pointer subtraction works in increments + // of the pointer child for indexable pointers (excluding pointers to vectors), + // which makes sense, but we also allow it for arbitrary single-item pointers, which + // leads to the weird result that subtraction of '*T' works completely differently + // depending on whether 'T' is an array. That seems dangerous and confusing, and + // requires the odd logic below. This behavior originally came from a now-removed + // function `Type.elemType2`, which was removed precisely *because* the thing it did + // wasn't really well-defined; for that reason, these semantics were probably + // largely accidental to begin with. We should change the langauge to avoid this + // confusing behavior. For instance, perhaps pointer subtraction should only work on + // indexable pointers. const lhs_elem_ty = ty: { const ptr_elem_ty = lhs_ty.childType(zcu); - if (lhs_ty.ptrSize(zcu) == .one and ptr_elem_ty.isArrayOrVector(zcu)) break :ty ptr_elem_ty.childType(zcu); + if (lhs_ty.ptrSize(zcu) == .one and ptr_elem_ty.zigTypeTag(zcu) == .array) break :ty ptr_elem_ty.childType(zcu); break :ty ptr_elem_ty; }; const rhs_elem_ty = ty: { const ptr_elem_ty = rhs_ty.childType(zcu); - if (rhs_ty.ptrSize(zcu) == .one and ptr_elem_ty.isArrayOrVector(zcu)) break :ty ptr_elem_ty.childType(zcu); + if (rhs_ty.ptrSize(zcu) == .one and ptr_elem_ty.zigTypeTag(zcu) == .array) break :ty ptr_elem_ty.childType(zcu); break :ty ptr_elem_ty; }; if (lhs_elem_ty.toIntern() != rhs_elem_ty.toIntern()) { -- 2.54.0 From c2b42383eb058f4c2bd17738cd73382e6a6672eb Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Mon, 2 Mar 2026 17:35:02 +0000 Subject: [PATCH 63/79] compiler,std: various little fixes --- lib/std/hash_map.zig | 6 +-- src/InternPool.zig | 16 +++++- src/Sema.zig | 92 ++++++++++++++++++---------------- src/Value.zig | 4 +- src/Zcu.zig | 7 ++- src/Zcu/PerThread.zig | 80 ++++++++++++++++++++---------- src/codegen/c.zig | 6 +-- src/codegen/llvm.zig | 2 +- src/link.zig | 5 +- src/link/Dwarf.zig | 112 ++++++++++++++++++++++++++++++++++++++---- tools/incr-check.zig | 16 +++--- 11 files changed, 247 insertions(+), 99 deletions(-) diff --git a/lib/std/hash_map.zig b/lib/std/hash_map.zig index 58c9397a6b9955a7c0aefc2368a49cbd160cf68d..cb74cbc08b6eb554ff20eb5fe0c920a821ec51e0 100644 --- a/lib/std/hash_map.zig +++ b/lib/std/hash_map.zig @@ -1526,9 +1526,9 @@ pub fn HashMapUnmanaged( } comptime { - if (!builtin.strip_debug_info) _ = switch (builtin.zig_backend) { - .stage2_llvm => &dbHelper, - .stage2_x86_64 => KV, + if (!builtin.strip_debug_info) switch (builtin.zig_backend) { + .stage2_llvm => _ = &dbHelper, + .stage2_x86_64 => _ = @as(KV, undefined), else => {}, }; } diff --git a/src/InternPool.zig b/src/InternPool.zig index da95ed6cc7a40f96b08a7e3a589afb5f93d568df..7a561d6ca246553d16cc11f9f9a00c67e977ddfb 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -3334,11 +3334,17 @@ pub const LoadedStructType = struct { field_defaults: Index.Slice, field_aligns: Alignment.Slice, field_is_comptime_bits: ComptimeBits, + /// If `layout` is `.@"packed"`, this is `.empty`. field_runtime_order: RuntimeOrder.Slice, + /// If `layout` is `.@"packed"`, this is `.empty`. field_offsets: Offsets, + /// Only valid if `layout` is `.@"packed"`. packed_backing_int_type: Index, + /// Only valid if `layout` is *not* `.@"packed"`. class: TypeClass, + /// Only valid if `layout` is *not* `.@"packed"`. size: u32, + /// Only valid if `layout` is *not* `.@"packed"`. alignment: Alignment, pub const ComptimeBits = struct { @@ -3516,15 +3522,21 @@ pub const LoadedUnionType = struct { tag_usage: TagUsage, /// While `tag_usage` indicates whether the union should logically contain a tag, it may be /// omitted if the union layout is resolved as OPV or NPV. This field is `true` iff there is an - /// actual runtime tag in the union layout. + /// actual runtime tag, with one or more runtime bits, in the union layout. It is always `false` + /// if `layout` is not `.auto`. has_runtime_tag: bool, /// Even if `tag_usage == .none` and `has_runtime_tag == false`, this is still populated with /// the union's "hypothetical" tag type. enum_tag_type: Index, + /// Only valid if `layout` is `.@"packed"`. packed_backing_int_type: Index, + /// Not valid if `layout` is `.@"packed"`. class: TypeClass, + /// Not valid if `layout` is `.@"packed"`. size: u32, + /// Not valid if `layout` is `.@"packed"`. padding: u32, + /// Not valid if `layout` is `.@"packed"`. alignment: Alignment, pub const TagUsage = enum(u2) { @@ -3898,7 +3910,7 @@ pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { .want_layout = extra.data.bits.want_layout, .field_types = field_types, .field_aligns = .empty, - .has_runtime_tag = undefined, + .has_runtime_tag = false, .class = undefined, .size = undefined, .padding = undefined, diff --git a/src/Sema.zig b/src/Sema.zig index 644bad5dcaf48938a4ecf925f54dbee7d4e1de86..b266940c0e91e309c788d156f3ab99d760d8d6ff 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -13777,45 +13777,44 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const many_alloc = try block.addBitCast(many_ty, mutable_alloc); // lhs_dest_slice = dest[0..lhs.len] - const slice_ty_ref = Air.internedToRef(slice_ty.toIntern()); - const lhs_len_ref = try pt.intRef(.usize, lhs_len); - const lhs_dest_slice = try block.addInst(.{ - .tag = .slice, - .data = .{ .ty_pl = .{ - .ty = slice_ty_ref, - .payload = try sema.addExtra(Air.Bin{ - .lhs = many_alloc, - .rhs = lhs_len_ref, - }), - } }, - }); - - _ = try block.addBinOp(.memcpy, lhs_dest_slice, lhs); + if (lhs_len > 0) { + const lhs_dest_slice = try block.addInst(.{ + .tag = .slice, + .data = .{ .ty_pl = .{ + .ty = .fromType(slice_ty), + .payload = try sema.addExtra(Air.Bin{ + .lhs = many_alloc, + .rhs = try pt.intRef(.usize, lhs_len), + }), + } }, + }); + _ = try block.addBinOp(.memcpy, lhs_dest_slice, lhs); + } // rhs_dest_slice = dest[lhs.len..][0..rhs.len] - const rhs_len_ref = try pt.intRef(.usize, rhs_len); - const rhs_dest_offset = try block.addInst(.{ - .tag = .ptr_add, - .data = .{ .ty_pl = .{ - .ty = Air.internedToRef(many_ty.toIntern()), - .payload = try sema.addExtra(Air.Bin{ - .lhs = many_alloc, - .rhs = lhs_len_ref, - }), - } }, - }); - const rhs_dest_slice = try block.addInst(.{ - .tag = .slice, - .data = .{ .ty_pl = .{ - .ty = slice_ty_ref, - .payload = try sema.addExtra(Air.Bin{ - .lhs = rhs_dest_offset, - .rhs = rhs_len_ref, - }), - } }, - }); - - _ = try block.addBinOp(.memcpy, rhs_dest_slice, rhs); + if (rhs_len > 0) { + const rhs_dest_offset = try block.addInst(.{ + .tag = .ptr_add, + .data = .{ .ty_pl = .{ + .ty = Air.internedToRef(many_ty.toIntern()), + .payload = try sema.addExtra(Air.Bin{ + .lhs = many_alloc, + .rhs = try pt.intRef(.usize, lhs_len), + }), + } }, + }); + const rhs_dest_slice = try block.addInst(.{ + .tag = .slice, + .data = .{ .ty_pl = .{ + .ty = .fromType(slice_ty), + .payload = try sema.addExtra(Air.Bin{ + .lhs = rhs_dest_offset, + .rhs = try pt.intRef(.usize, rhs_len), + }), + } }, + }); + _ = try block.addBinOp(.memcpy, rhs_dest_slice, rhs); + } if (res_sent_val) |sent_val| { const elem_index = try pt.intRef(.usize, result_len); @@ -18829,7 +18828,7 @@ fn finishStructInit( return sema.addConstantMaybeRef(sema.resolveValue(final_val_ref).?, is_ref); }, .@"packed" => { - const buf = try sema.arena.alloc(u8, (struct_ty.bitSize(zcu) + 7) / 8); + const buf = try sema.arena.alloc(u8, @intCast((struct_ty.bitSize(zcu) + 7) / 8)); var bit_offset: u16 = 0; for (field_inits) |field_init| { const field_val = sema.resolveValue(field_init).?; @@ -21113,7 +21112,7 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData else => unreachable, }; - if (!dest_err_ty.isAnyError(zcu) and !dest_err_ty.errorSetHasField(err_name, zcu)) { + if (result != .superset and !dest_err_ty.errorSetHasField(err_name, zcu)) { return sema.fail(block, src, "'error.{f}' not a member of error set '{f}'", .{ err_name.fmt(ip), dest_err_ty.fmt(pt), }); @@ -25186,9 +25185,18 @@ pub fn explainWhyTypeIsNotExtern( else => |cc| try sema.errNote(src_loc, msg, "{t} function cannot be extern", .{cc}), }, .@"enum" => { - const tag_ty = ty.intTagType(zcu); - try sema.errNote(src_loc, msg, "enum tag type '{f}' is not extern compatible", .{tag_ty.fmt(pt)}); - try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position); + const enum_obj = zcu.intern_pool.loadEnumType(ty.toIntern()); + switch (enum_obj.int_tag_mode) { + .auto => { + try sema.errNote(ty.srcLoc(zcu), msg, "integer tag type of enum is inferred", .{}); + try sema.errNote(ty.srcLoc(zcu), msg, "consider explicitly specifying the integer tag type", .{}); + }, + .explicit => { + const tag_ty: Type = .fromInterned(enum_obj.int_tag_type); + try sema.errNote(ty.srcLoc(zcu), msg, "enum tag type '{f}' is not extern compatible", .{tag_ty.fmt(pt)}); + try sema.explainWhyTypeIsNotExtern(msg, ty.srcLoc(zcu), tag_ty, position); + }, + } }, .@"struct" => { const struct_obj = zcu.intern_pool.loadStructType(ty.toIntern()); diff --git a/src/Value.zig b/src/Value.zig index 4cd7995b712a0c05b9e98960bc5198523bc21099..3176520d3628f07050a6821e9040b8a7c12449db 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -895,7 +895,7 @@ pub fn fieldValue(val: Value, pt: Zcu.PerThread, index: usize) !Value { // Avoid hitting gpa for accesses to small packed structs var sfba_state = std.heap.stackFallback(128, zcu.comp.gpa); const sfba = sfba_state.get(); - const buf = try sfba.alloc(u8, (ty.bitSize(zcu) + 7) / 8); + const buf = try sfba.alloc(u8, @intCast((ty.bitSize(zcu) + 7) / 8)); defer sfba.free(buf); int_val.writeToPackedMemory(pt, buf, 0) catch |err| switch (err) { error.ReinterpretDeclRef => unreachable, // it's an integer @@ -2419,7 +2419,7 @@ pub fn uninterpret(val: anytype, ty: Type, pt: Zcu.PerThread) error{ OutOfMemory } for (field_vals, 0..) |*field_val, field_idx| { if (field_val.* == .none) { - const default_init = struct_obj.field_inits.get(ip)[field_idx]; + const default_init = struct_obj.field_defaults.get(ip)[field_idx]; if (default_init == .none) return error.TypeMismatch; field_val.* = default_init; } diff --git a/src/Zcu.zig b/src/Zcu.zig index 78144bac16a817a931a23e5d1ba346f7aee374af..0ab053b696e8a63de410bb15310ada4e80cd5e38 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -3686,6 +3686,11 @@ pub const ImportResult = struct { pub fn resetUnit(zcu: *Zcu, unit: AnalUnit) void { const gpa = zcu.comp.gpa; + if (!dev.env.supports(.incremental)) { + // This is the first time `unit` is being analyzed, so there is no stale data to clear. + return; + } + // Compile errors if (zcu.failed_analysis.fetchSwapRemove(unit)) |kv| { kv.value.destroy(gpa); @@ -4309,7 +4314,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.AutoArrayHashMapUnmanag }); const gop = try units.getOrPut(gpa, other); if (gop.found_existing) break :queue_paired; - gop.value_ptr.* = units.values()[unit_idx]; // same reference location + gop.value_ptr.* = units.values()[unit_idx - 1]; // same reference location } refs_log.debug("handle unit '{f}'", .{zcu.fmtAnalUnit(unit)}); diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 6a7054246eae094e485909243e340bd6865bc5cf..4abfb5157ce8538a27dd8cbeec9d3a0ac6852901 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -1075,7 +1075,6 @@ pub fn ensureMemoizedStateUpToDate( const prev_failed = zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit); if (was_outdated) { - dev.check(.incremental); zcu.resetUnit(unit); } else { if (prev_failed) return error.AnalysisFail; @@ -1193,10 +1192,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU const was_outdated = zcu.clearOutdatedState(anal_unit); if (was_outdated) { - // `was_outdated` can be true in the initial update for comptime units, so this isn't a `dev.check`. - if (dev.env.supports(.incremental)) { - zcu.resetUnit(anal_unit); - } + zcu.resetUnit(anal_unit); } else { // We can trust the current information about this unit. if (zcu.failed_analysis.contains(anal_unit)) return error.AnalysisFail; @@ -1366,10 +1362,7 @@ pub fn ensureTypeLayoutUpToDate( }; if (was_outdated) { - // `was_outdated` is true in the initial update, so this isn't a `dev.check`. - if (dev.env.supports(.incremental)) { - zcu.resetUnit(anal_unit); - } + zcu.resetUnit(anal_unit); // For types, we already know that we have to invalidate all dependees. // TODO: we actually *could* detect whether everything was the same. should we bother? try zcu.markDependeeOutdated(.marked_po, .{ .type_layout = ty.toIntern() }); @@ -1492,10 +1485,7 @@ pub fn ensureStructDefaultsUpToDate( }; if (was_outdated) { - // `was_outdated` is true in the initial update, so this isn't a `dev.check`. - if (dev.env.supports(.incremental)) { - zcu.resetUnit(anal_unit); - } + zcu.resetUnit(anal_unit); // For types, we already know that we have to invalidate all dependees. // TODO: we actually *could* detect whether everything was the same. should we bother? try zcu.markDependeeOutdated(.marked_po, .{ .struct_defaults = ty.toIntern() }); @@ -1609,7 +1599,6 @@ pub fn ensureNavValUpToDate( zcu.transitive_failed_analysis.contains(anal_unit); if (was_outdated) { - dev.check(.incremental); zcu.resetUnit(anal_unit); } else { // We can trust the current information about this unit. @@ -1893,6 +1882,30 @@ fn analyzeNavVal( } } + // We're about to resolve the value of the Nav. This causes the information about what the value + // was last update to be lost; therefore, if the `nav_ty` is currently out of date, it would + // incorrectly think it was unchanged when eventually analyzed. To avoid this, we need to detect + // that case and invalidate the dependee right now. + if (zcu.clearOutdatedState(.wrap(.{ .nav_ty = nav_id }))) { + assert(zir_decl.type_body == null); // otherwise we already resolved it with `Sema.ensureNavResolved` + zcu.resetUnit(.wrap(.{ .nav_ty = nav_id })); + try pt.addDependency(.wrap(.{ .nav_ty = nav_id }), .{ .nav_val = nav_id }); // inferred type depends on the value (that's us!) + if (comp.debugIncremental()) { + const info = try zcu.incremental_debug_state.getUnitInfo(gpa, .wrap(.{ .nav_ty = nav_id })); + info.last_update_gen = zcu.generation; + info.deps.clearRetainingCapacity(); + } + const type_changed: bool = switch (old_nav.status) { + .unresolved => true, + .type_resolved => |old| old.type != nav_ty.toIntern(), + .fully_resolved => |old| ip.typeOf(old.val) != nav_ty.toIntern(), + }; + if (type_changed) { + try zcu.markDependeeOutdated(.marked_po, .{ .nav_ty = nav_id }); + } else { + try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav_id }); + } + } ip.resolveNavValue(io, nav_id, .{ .val = nav_val.toIntern(), .is_const = is_const, @@ -1930,10 +1943,10 @@ fn analyzeNavVal( try zcu.ensureFuncBodyAnalysisQueued(nav_val.toIntern()); } - switch (old_nav.status) { - .unresolved, .type_resolved => return .{ .val_changed = true }, - .fully_resolved => |old| return .{ .val_changed = old.val != nav_val.toIntern() }, - } + return switch (old_nav.status) { + .unresolved, .type_resolved => .{ .val_changed = true }, + .fully_resolved => |old| .{ .val_changed = old.val != nav_val.toIntern() }, + }; } pub fn ensureNavTypeUpToDate( @@ -1973,7 +1986,6 @@ pub fn ensureNavTypeUpToDate( zcu.transitive_failed_analysis.contains(anal_unit); if (was_outdated) { - dev.check(.incremental); zcu.resetUnit(anal_unit); } else { // We can trust the current information about this unit. @@ -2107,12 +2119,29 @@ fn analyzeNavType( const type_body = zir_decl.type_body orelse { // There is no type annotation, so we just need to use the declaration's value. + // If the value had already been re-analyzed, it would have resolved the `nav_ty` unit as + // either outdated or up-to-date. So we know that `old_nav` does contain information from + // the previous update. As such, after this call, we will be able to determine whether the + // type changed. try sema.ensureNavResolved(&block, init_src, nav_id, .fully); - // We don't actually know what the type of this Nav was before it was resolved, so we just - // have to assume we were outdated. This isn't too bad, because assuming there was also no - // type annotation last update, we should only be re-analyzed if the value changes (it's our - // only dependency), or if there was a dependency loop. - return .{ .type_changed = true }; + const new = ip.getNav(nav_id).status.fully_resolved; + const new_is_extern_decl = ip.indexToKey(new.val) == .@"extern"; + const changed = switch (old_nav.status) { + .unresolved => true, + .type_resolved => |r| r.type != ip.typeOf(new.val) or + r.alignment != new.alignment or + r.@"linksection" != new.@"linksection" or + r.@"addrspace" != new.@"addrspace" or + r.is_const != new.is_const or + r.is_extern_decl != new_is_extern_decl, + .fully_resolved => |r| ip.typeOf(r.val) != ip.typeOf(new.val) or + r.alignment != new.alignment or + r.@"linksection" != new.@"linksection" or + r.@"addrspace" != new.@"addrspace" or + r.is_const != new.is_const or + (old_nav.getExtern(ip) != null) != new_is_extern_decl, + }; + return .{ .type_changed = changed }; }; block.comptime_reason = .{ .reason = .{ @@ -2210,7 +2239,6 @@ pub fn ensureFuncBodyUpToDate( const prev_failed = zcu.failed_analysis.contains(anal_unit) or zcu.transitive_failed_analysis.contains(anal_unit); if (was_outdated) { - dev.check(.incremental); zcu.resetUnit(anal_unit); } else { // We can trust the current information about this function. @@ -2292,7 +2320,7 @@ fn analyzeFuncBody( var air = try pt.analyzeFuncBodyInner(func_index, reason); var air_owned = true; - errdefer if (air_owned) air.deinit(gpa); + defer if (air_owned) air.deinit(gpa); const ies_outdated = !func.analysisUnordered(ip).inferred_error_set or func.resolvedErrorSetUnordered(ip) != old_resolved_ies; diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 13e07dfcd05aa6a3f31b7de7ee49805f1225cecc..97e5ca22498df706b2fff70e5aebe7f1bf892ec3 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -7132,9 +7132,9 @@ fn formatIntLiteral(data: FormatIntLiteralContext, w: *Writer) Writer.Error!void var limb_buf: [std.math.big.int.calcTwosCompLimbCount(65535)]std.math.big.Limb = undefined; for (0..big.limbs_len) |limb_index| { if (limb_index != 0) try w.writeAll(", "); - const limb_bit_offset: u64 = switch (target.cpu.arch.endian()) { - .little => limb_index * big.limb_size.bits(), - .big => (big.limbs_len - limb_index - 1) * big.limb_size.bits(), + const limb_bit_offset: u16 = switch (target.cpu.arch.endian()) { + .little => @intCast(limb_index * big.limb_size.bits()), + .big => @intCast((big.limbs_len - limb_index - 1) * big.limb_size.bits()), }; var limb_bigint: std.math.big.int.Mutable = .{ .limbs = &limb_buf, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 938706a42b82cdaf8639cd58738bd0fc3ad613a7..7bcd60d8a7964c4edfb1623b9ed9def47f8efa87 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2432,7 +2432,7 @@ pub const Object = struct { const debug_payload_type = try o.builder.debugUnionType( payload_name: { if (layout.tag_size == 0) break :payload_name name; - break :payload_name try o.builder.metadataStringFmt("{s}:Payload", .{name.slice(&o.builder)}); + break :payload_name try o.builder.metadataStringFmt("{f}:Payload", .{ty.fmt(pt)}); }, file, scope, diff --git a/src/link.zig b/src/link.zig index 3eb4add772149d4a5e149ecf842156cde14d0849..80141676d414a40cf3cbbd29c213afe62a65d20d 100644 --- a/src/link.zig +++ b/src/link.zig @@ -1557,7 +1557,10 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void .link_func => |codegen_task| nav: { timer.pause(io); const func, var mir = codegen_task.wait(&zcu.codegen_task_pool, io) catch |err| switch (err) { - error.Canceled, error.AlreadyReported => return, + error.Canceled, error.AlreadyReported => { + comp.link_prog_node.completeOne(); + return; + }, }; defer mir.deinit(zcu); timer.@"resume"(io); diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 97fb0294eb617c509e965995587ee6049a661941..fac71faf56ab2f6572f86e7ce71e66451eaddd58 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -3344,6 +3344,7 @@ pub fn updateConstIncomplete(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index } fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.ConstPool.Index, value_index: InternPool.Index) !void { const zcu = pt.zcu; + const ip = &zcu.intern_pool; const val: Value = .fromInterned(value_index); @@ -3383,20 +3384,109 @@ fn updateConstIncompleteInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_inde .debug_loclists = .init(dwarf.gpa), }; defer wip_nav.deinit(); - switch (val.typeOf(zcu).toIntern()) { - .type_type => { - try wip_nav.abbrevCode(.generated_empty_struct_type); - try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); - try wip_nav.debug_info.writer.writeByte(@intFromBool(true)); - }, - else => |ty| { - try wip_nav.abbrevCode(.undefined_comptime_value); - try wip_nav.refType(.fromInterned(ty)); + + switch (ip.indexToKey(value_index)) { + // Container types still need to be valid namespaces. + .struct_type => { + const loaded_struct = ip.loadStructType(value_index); + const root_of_file: ?Zcu.File.Index = if (loaded_struct.zir_index.resolveFull(ip)) |r| f: { + if (r.inst != .main_struct_inst) break :f null; + break :f r.file; + } else null; + if (root_of_file) |file_index| { + assert(loaded_struct.name_nav == .none); + const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file_index); + try wip_nav.abbrevCode(.empty_file); + try wip_nav.debug_info.writer.writeUleb128(file_gop.index); + try wip_nav.strp(loaded_struct.name.toSlice(ip)); + } else { + try dwarf.emitIncompleteContainerType( + &wip_nav, + loaded_struct.zir_index, + loaded_struct.name, + loaded_struct.name_nav, + ); + } + }, + .union_type => { + const loaded_union = ip.loadUnionType(value_index); + try dwarf.emitIncompleteContainerType( + &wip_nav, + loaded_union.zir_index, + loaded_union.name, + loaded_union.name_nav, + ); + }, + .enum_type => { + const loaded_enum = ip.loadEnumType(value_index); + if (loaded_enum.zir_index.unwrap()) |zir_index| { + try dwarf.emitIncompleteContainerType( + &wip_nav, + zir_index, + loaded_enum.name, + loaded_enum.name_nav, + ); + } else { + try wip_nav.abbrevCode(.generated_empty_struct_type); + try wip_nav.strp(loaded_enum.name.toSlice(ip)); + try wip_nav.debug_info.writer.writeByte(@intFromBool(true)); + } + }, + .opaque_type => { + const loaded_opaque = ip.loadOpaqueType(value_index); + try dwarf.emitIncompleteContainerType( + &wip_nav, + loaded_opaque.zir_index, + loaded_opaque.name, + loaded_opaque.name_nav, + ); + }, + // Not a container type, so just emit a dummy entry. If `val` happens to be a type, we'll + // emit it as if it were an opaque type so that we can name it. + else => |val_key| switch (val_key.typeOf()) { + .type_type => { + try wip_nav.abbrevCode(.generated_empty_struct_type); + try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); + try wip_nav.debug_info.writer.writeByte(@intFromBool(true)); + }, + else => |ty| { + try wip_nav.abbrevCode(.undefined_comptime_value); + try wip_nav.refType(.fromInterned(ty)); + }, }, } try dwarf.debug_info.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_info.written()); try dwarf.debug_loclists.section.replaceEntry(unit, entry, dwarf, wip_nav.debug_loclists.written()); } +fn emitIncompleteContainerType( + dwarf: *Dwarf, + wip_nav: *WipNav, + zir_index: InternPool.TrackedInst.Index, + name: InternPool.NullTerminatedString, + name_nav: InternPool.Nav.Index.Optional, +) !void { + const zcu = wip_nav.pt.zcu; + const ip = &zcu.intern_pool; + const file = zir_index.resolveFile(ip); + if (name_nav.unwrap()) |nav_index| { + const nav = ip.getNav(nav_index); + const decl_inst = nav.srcInst(ip).resolve(ip).?; + const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); + try wip_nav.declCommon(.{ + .decl = .decl_namespace_struct, + .generic_decl = .generic_decl_const, + .decl_instance = .decl_instance_namespace_struct, + }, &nav, file, &decl); + try wip_nav.debug_info.writer.writeByte(@intFromBool(true)); + } else { + const diw = &wip_nav.debug_info.writer; + const file_gop = try dwarf.getModInfo(wip_nav.unit).files.getOrPut(dwarf.gpa, file); + try wip_nav.abbrevCode(.empty_struct_type); + try diw.writeUleb128(file_gop.index); + try wip_nav.strp(name.toSlice(ip)); + try diw.writeByte(@intFromBool(true)); + } +} /// Should only be called by the `link.ConstPool` implementation. /// /// Emits a DIE for the given comptime-only value (which may be a type). @@ -3418,6 +3508,8 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co val.typeOf(zcu).assertHasLayout(zcu); } + if (value_index == .anyerror_type) return; // handled in `flush` instead + const value_ip_key = ip.indexToKey(value_index); switch (value_ip_key) { .func => return, // populated by the Nav instead (`updateComptimeNav` or `initWipNav`) @@ -3746,7 +3838,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co try wip_nav.abbrevCode(.void_type); try wip_nav.strpFmt("{f}", .{val.toType().fmt(pt)}); }, - .anyerror => return, // delay until flush + .anyerror => unreachable, // already did early return above .adhoc_inferred_error_set => unreachable, }, .tuple_type => |tuple_type| if (tuple_type.types.len == 0) { diff --git a/tools/incr-check.zig b/tools/incr-check.zig index 6b3351b315a3c23a443faca94c61bae0367a304e..8eb985408e54ba63be587055d8c559f9852fe4c4 100644 --- a/tools/incr-check.zig +++ b/tools/incr-check.zig @@ -311,12 +311,12 @@ const Eval = struct { .error_bundle => { const result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body); if (stderr.bufferedLen() > 0) { - const stderr_data = try mr.toOwnedSlice(1); if (eval.allow_stderr) { - std.log.info("error_bundle stderr:\n{s}", .{stderr_data}); + std.log.info("error_bundle stderr:\n{s}", .{stderr.buffered()}); } else { - eval.fatal("error_bundle unexpected stderr:\n{s}", .{stderr_data}); + eval.fatal("error_bundle unexpected stderr:\n{s}", .{stderr.buffered()}); } + stderr.tossBuffered(); } if (result_error_bundle.errorMessageCount() != 0) { try eval.checkErrorOutcome(update, result_error_bundle); @@ -327,15 +327,15 @@ const Eval = struct { .emit_digest => { var r: std.Io.Reader = .fixed(body); _ = r.takeStruct(std.zig.Server.Message.EmitDigest, .little) catch unreachable; + if (stderr.bufferedLen() > 0) { - const stderr_data = try mr.toOwnedSlice(1); if (eval.allow_stderr) { - std.log.info("emit_digest stderr:\n{s}", .{stderr_data}); + std.log.info("emit_digest stderr:\n{s}", .{stderr.buffered()}); } else { - eval.fatal("emit_digest unexpected stderr:\n{s}", .{stderr_data}); + eval.fatal("emit_digest unexpected stderr:\n{s}", .{stderr.buffered()}); } + stderr.tossBuffered(); } - if (eval.target.backend == .sema) { try eval.checkSuccessOutcome(update, null, prog_node); continue; @@ -369,7 +369,7 @@ const Eval = struct { } waitChild(eval.child, eval); - eval.fatal("compiler failed to send error_bundle or emit_bin_path", .{}); + eval.fatal("compiler failed to send terminating error_bundle", .{}); } fn checkErrorOutcome(eval: *Eval, update: Case.Update, error_bundle: std.zig.ErrorBundle) !void { -- 2.54.0 From 3a3ac1034519d1b0c58279345e7e0f6272bccbee Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Tue, 3 Mar 2026 13:14:05 +0000 Subject: [PATCH 64/79] cbe: fix type layouts, and statically assert them --- lib/zig.h | 8 +++ src/codegen/c/type/render_defs.zig | 101 +++++++++++++++++++++++------ 2 files changed, 88 insertions(+), 21 deletions(-) diff --git a/lib/zig.h b/lib/zig.h index f8744966c68276a8e160e77eb186d08f54caa8cb..0b9c6e58ca6d9f1800fd8059e5db9d3636faa35c 100644 --- a/lib/zig.h +++ b/lib/zig.h @@ -151,6 +151,14 @@ #define zig_has_attribute(attribute) 0 #endif +#if __STDC_VERSION__ >= 201112L +#define zig_static_assert(cond, msg) _Static_assert(cond, msg) +#elif zig_has_attribute(unused) +#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] __attribute__((unused)) +#else +#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] +#endif + #if __STDC_VERSION__ >= 202311L #define zig_threadlocal thread_local #elif __STDC_VERSION__ >= 201112L diff --git a/src/codegen/c/type/render_defs.zig b/src/codegen/c/type/render_defs.zig index a34b0d6d3ce720663b63202e7e4260243f9bbb0f..52bf57306426156917bcfbcda475d57edd972e06 100644 --- a/src/codegen/c/type/render_defs.zig +++ b/src/codegen/c/type/render_defs.zig @@ -246,6 +246,8 @@ pub fn defineComplete( ptr_cty.fmtDeclaratorPrefix(zcu), ptr_cty.fmtDeclaratorSuffix(zcu), }); + // Don't bother with `writeStaticAssertLayout`---there's not really any way we could mess + // slices up, and they're all obviously the same layout. }, .optional => switch (CType.classifyOptional(ty, zcu)) { .error_set, @@ -260,6 +262,7 @@ pub fn defineComplete( name_cty.fmtTypeName(zcu), ty.fmt(pt), }); + try writeStaticAssertLayout(ty, name_cty, w, zcu); }, .@"struct" => { @@ -277,6 +280,7 @@ pub fn defineComplete( payload_cty.fmtDeclaratorPrefix(zcu), payload_cty.fmtDeclaratorSuffix(zcu), }); + try writeStaticAssertLayout(ty, name_cty, w, zcu); }, }, .array => if (ty.hasRuntimeBits(zcu)) { @@ -297,6 +301,7 @@ pub fn defineComplete( array_cty.fmtDeclaratorSuffix(zcu), ty.fmt(pt), }); + try writeStaticAssertLayout(ty, name_cty, w, zcu); }, .vector => if (ty.hasRuntimeBits(zcu)) { const name_cty: CType = .{ .vec = ty }; @@ -312,6 +317,7 @@ pub fn defineComplete( array_cty.fmtDeclaratorSuffix(zcu), ty.fmt(pt), }); + try writeStaticAssertLayout(ty, name_cty, w, zcu); }, else => {}, } @@ -374,18 +380,21 @@ fn defineTuple( zig_offset = field_align.forward(zig_offset); if (!field_ty.hasRuntimeBits(zcu)) continue; c_offset = field_align.forward(c_offset); + try w.writeByte(' '); if (zig_offset == 0 and overalign) { // This is the first field; specify its alignment to align the tuple. - try w.print(" zig_align({d})", .{tuple_align.toByteUnits().?}); + try writeFieldAlign(field_ty, tuple_align, w, zcu); } else if (zig_offset > c_offset) { // This field needs to be overaligned compared to what its offset would otherwise be. - const need_align: Alignment = .fromLog2Units(@ctz(zig_offset)); - try w.print(" zig_align({d})", .{need_align.toByteUnits().?}); + const need_align: Alignment = .minStrict( + tuple_align, // don't make the struct more aligned than it should be + .fromLog2Units(@ctz(zig_offset)), + ); + try writeFieldAlign(field_ty, need_align, w, zcu); c_offset = need_align.forward(c_offset); - assert(c_offset == zig_offset); } const field_cty: CType = try .lower(field_ty, deps, arena, zcu); - try w.print(" {f}f{d}{f};\n", .{ + try w.print("{f}f{d}{f};\n", .{ field_cty.fmtDeclaratorPrefix(zcu), field_index, field_cty.fmtDeclaratorSuffix(zcu), @@ -395,6 +404,8 @@ fn defineTuple( c_offset += field_size; } try w.writeAll("};\n"); + + try writeStaticAssertLayout(ty, name_cty, w, zcu); } fn defineStruct( ty: Type, @@ -420,6 +431,8 @@ fn defineStruct( const natural_offset = natural_align.forward(offset); const actual_offset = struct_type.field_offsets.get(ip)[field_index]; if (actual_offset < natural_offset) break :pack true; + // Also pack if any field is more aligned than the struct should be. + if (natural_align.compareStrict(.gt, struct_type.alignment)) break :pack true; offset = actual_offset + field_ty.abiSize(zcu); } break :pack false; @@ -459,22 +472,22 @@ fn defineStruct( false => natural_align.forward(offset), }; const actual_offset = struct_type.field_offsets.get(ip)[field_index]; + try w.writeByte(' '); if (actual_offset == 0 and overalign) { // This is the first field; specify its alignment to align the struct. - try w.print(" zig_align({d})", .{struct_type.alignment.toByteUnits().?}); + try writeFieldAlign(field_ty, struct_type.alignment, w, zcu); } else if (actual_offset > natural_offset) { // This field needs to be underaligned or overaligned compared to what its // offset would otherwise be. - const need_align: Alignment = .fromLog2Units(@ctz(actual_offset)); - if (need_align.compareStrict(.lt, natural_align)) { - try w.print(" zig_under_align({d})", .{need_align.toByteUnits().?}); - } else { - try w.print(" zig_align({d})", .{need_align.toByteUnits().?}); - } + const need_align: Alignment = .minStrict( + struct_type.alignment, // don't make the struct more aligned than it should be + .fromLog2Units(@ctz(actual_offset)), + ); + try writeFieldAlign(field_ty, need_align, w, zcu); } const field_cty: CType = try .lower(field_ty, deps, arena, zcu); const field_name = struct_type.field_names.get(ip)[field_index].toSlice(ip); - try w.print(" {f}{f}{f};\n", .{ + try w.print("{f}{f}{f};\n", .{ field_cty.fmtDeclaratorPrefix(zcu), fmtIdentSolo(field_name), field_cty.fmtDeclaratorSuffix(zcu), @@ -485,6 +498,8 @@ fn defineStruct( try w.writeByte('}'); if (pack) try w.writeByte(')'); try w.writeAll(";\n"); + + try writeStaticAssertLayout(ty, name_cty, w, zcu); } fn defineUnionAuto( ty: Type, @@ -500,12 +515,20 @@ fn defineUnionAuto( const union_type = ip.loadUnionType(ty.toIntern()); const enum_tag_ty: Type = .fromInterned(union_type.enum_tag_type); + const layout = Type.getUnionLayout(union_type, zcu); + // If there are any underaligned fields, we need to byte-pack the union. const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| { const field_ty: Type = .fromInterned(field_ty_ip); if (!field_ty.hasRuntimeBits(zcu)) continue; const natural_align = field_ty.abiAlignment(zcu); if (natural_align.compareStrict(.gt, union_type.alignment)) break true; + // The tag will immediately follow the payload. This layout may put the tag in what would + // otherwise be padding on the payload union, because if the most-aligned union field is not + // the largest one, a larger field may make the payload "underaligned" overall. As such, we + // need to check whether this field is okay with the payload size, and if not then we must + // byte-pack. + if (!natural_align.check(layout.payload_size)) break true; } else false; // If the alignment of other fields would not give the union sufficient alignment, we @@ -536,6 +559,10 @@ fn defineUnionAuto( }); if (payload_has_bits) { try w.writeByte(' '); + if (overalign) { + // Specify the alignment of `union { ... } payload;` to align the union's `struct`. + try w.print("zig_align({d}) ", .{union_type.alignment.toByteUnits().?}); + } if (pack) try w.writeAll("zig_packed("); try w.writeAll("union {\n"); for (0..enum_tag_ty.enumFieldCount(zcu)) |field_index| { @@ -543,12 +570,7 @@ fn defineUnionAuto( if (!field_ty.hasRuntimeBits(zcu)) continue; const field_name = enum_tag_ty.enumFieldName(field_index, zcu).toSlice(ip); const field_cty: CType = try .lower(field_ty, deps, arena, zcu); - try w.writeAll(" "); - if (overalign and field_index == 0) { - // This is the first field; specify its alignment to align the union. - try w.print("zig_align({d}) ", .{union_type.alignment.toByteUnits().?}); - } - try w.print("{f}{f}{f};\n", .{ + try w.print(" {f}{f}{f};\n", .{ field_cty.fmtDeclaratorPrefix(zcu), fmtIdentSolo(field_name), field_cty.fmtDeclaratorSuffix(zcu), @@ -566,6 +588,8 @@ fn defineUnionAuto( }); } try w.writeAll("};\n"); + + try writeStaticAssertLayout(ty, name_cty, w, zcu); } fn defineUnionExtern( ty: Type, @@ -622,11 +646,12 @@ fn defineUnionExtern( if (!field_ty.hasRuntimeBits(zcu)) continue; const field_name = enum_tag_ty.enumFieldName(field_index, zcu).toSlice(ip); const field_cty: CType = try .lower(field_ty, deps, arena, zcu); + try w.writeByte(' '); if (overalign and field_index == 0) { // This is the first field; specify its alignment to align the union. - try w.print(" zig_align({d})", .{union_type.alignment.toByteUnits().?}); + try writeFieldAlign(field_ty, union_type.alignment, w, zcu); } - try w.print(" {f}{f}{f};\n", .{ + try w.print("{f}{f}{f};\n", .{ field_cty.fmtDeclaratorPrefix(zcu), fmtIdentSolo(field_name), field_cty.fmtDeclaratorSuffix(zcu), @@ -635,6 +660,40 @@ fn defineUnionExtern( try w.writeByte('}'); if (pack) try w.writeByte(')'); try w.writeAll(";\n"); + + try writeStaticAssertLayout(ty, name_cty, w, zcu); +} + +/// Writes an annotation which, placed before a struct/union field declaration with field type `ty`, +/// will specify that field as having the given alignment. +fn writeFieldAlign( + ty: Type, + alignment: Alignment, + w: *Writer, + zcu: *const Zcu, +) Writer.Error!void { + if (alignment.compareStrict(.lt, ty.abiAlignment(zcu))) { + try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?}); + } else { + try w.print("zig_align({d}) ", .{alignment.toByteUnits().?}); + } +} + +/// Emits static assertions that the size and alignment of `cty` match those of the Zig type `ty`. +fn writeStaticAssertLayout( + ty: Type, + cty: CType, + w: *Writer, + zcu: *const Zcu, +) Writer.Error!void { + try w.print( + \\zig_static_assert(sizeof ({f}) == {d}, "incorrect size"); + \\zig_static_assert(_Alignof ({f}) == {d}, "incorrect alignment"); + \\ + , .{ + cty.fmtTypeName(zcu), ty.abiSize(zcu), + cty.fmtTypeName(zcu), ty.abiAlignment(zcu).toByteUnits().?, + }); } const std = @import("std"); -- 2.54.0 From 0f3c883245f27870472978f738d6e81958e15c52 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 8 Mar 2026 13:49:24 +0000 Subject: [PATCH 65/79] Sema: always track references I think not tracking these already causes some bugs on master with `-freference-trace=0`, but it now definitely causes bugs, because we want the reference information to decide how to write dependency loop errors. Let's begin to lean into the incremental-by-default future by disabling this small optimization---the compiler is starting to use a lot of the "incremental" logic even in non-incremental builds at this point, so the separation is becoming less and less! This particular optimization wasn't even that useful, because it's very rare for users to build with `-freference-trace=0`. --- src/Sema.zig | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index b266940c0e91e309c788d156f3ab99d760d8d6ff..aa3bae74687d6774a75c4dd708187fbe1a4cf1cf 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -29920,7 +29920,6 @@ pub fn addReferenceEntry( .func => |f| assert(ip.unwrapCoercedFunc(f) == f), // for `.{ .func = f }`, `f` must be uncoerced else => {}, } - if (!zcu.comp.config.incremental and zcu.comp.reference_trace == 0) return; const gop = try sema.references.getOrPut(sema.gpa, referenced_unit); if (gop.found_existing) return; try zcu.addUnitReference(sema.owner, referenced_unit, src, inline_frame: { @@ -29937,7 +29936,6 @@ pub fn addTypeReferenceEntry( referenced_type: Type, ) !void { const zcu = sema.pt.zcu; - if (!zcu.comp.config.incremental and zcu.comp.reference_trace == 0) return; const gop = try sema.type_references.getOrPut(sema.gpa, referenced_type.toIntern()); if (gop.found_existing) return; try zcu.addTypeReference(sema.owner, referenced_type.toIntern(), src); -- 2.54.0 From ea7e34224a8c3c0551e17a60fd849efee82447f7 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Wed, 4 Mar 2026 10:51:45 +0000 Subject: [PATCH 66/79] compiler: don't call `getUnionLayout` on packed unions --- src/Type.zig | 4 + src/codegen/llvm.zig | 131 ++++++++++++++++----------------- src/codegen/spirv/CodeGen.zig | 72 +++++++----------- src/link/Dwarf.zig | 133 +++++++++++++++++++--------------- 4 files changed, 168 insertions(+), 172 deletions(-) diff --git a/src/Type.zig b/src/Type.zig index ea92d6befdc5202a8dd21ad01d5f5ac66fb3af9d..6442a13efaafbd68385233f49a52b4c2abc1c3c8 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -1571,6 +1571,7 @@ pub fn externUnionBackingType(ty: Type, pt: Zcu.PerThread) !Type { } } +/// Asserts that `ty` is a non-packed union type. pub fn unionGetLayout(ty: Type, zcu: *const Zcu) Zcu.UnionLayout { assertHasLayout(ty, zcu); const union_obj = zcu.intern_pool.loadUnionType(ty.toIntern()); @@ -2689,7 +2690,10 @@ pub fn arrayBase(ty: Type, zcu: *const Zcu) struct { Type, u64 } { return .{ cur_ty, cur_len }; } +/// Asserts that `loaded_union.layout` is not `.@"packed"`. pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) Zcu.UnionLayout { + assert(loaded_union.layout != .@"packed"); + const ip = &zcu.intern_pool; var most_aligned_field: u32 = 0; var most_aligned_field_align: InternPool.Alignment = .@"1"; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 7bcd60d8a7964c4edfb1623b9ed9def47f8efa87..fc487d5a2618d3357f8fa422fcd79760f835d916 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2369,6 +2369,30 @@ pub const Object = struct { const line = ty.typeDeclSrcLine(zcu).? + 1; const enum_tag_ty: Type = .fromInterned(union_type.enum_tag_type); + + if (union_type.layout == .@"packed") { + const bitpack_field = try o.builder.debugMemberType( + try o.builder.metadataString("bits"), + null, // file + ty_fwd_ref, + 0, // line + try o.getDebugType(pt, .fromInterned(union_type.packed_backing_int_type)), + ty.abiSize(zcu) * 8, + ty.abiAlignment(zcu).toByteUnits().? * 8, + 0, // offset + ); + return o.builder.debugStructType( + name, + file, + scope, + line, + null, // underlying type + ty.abiSize(zcu) * 8, + ty.abiAlignment(zcu).toByteUnits().? * 8, + try o.builder.metadataTuple(&.{bitpack_field}), + ); + } + const layout = Type.getUnionLayout(union_type, zcu); if (layout.payload_size == 0) { @@ -2411,10 +2435,7 @@ pub const Object = struct { const field_ty = union_type.field_types.get(ip)[field_index]; const field_size = Type.fromInterned(field_ty).abiSize(zcu); - const field_align: InternPool.Alignment = switch (union_type.layout) { - .@"packed" => .none, - .auto, .@"extern" => ty.explicitFieldAlignment(field_index, zcu), - }; + const field_align: InternPool.Alignment = ty.explicitFieldAlignment(field_index, zcu); const field_name = enum_tag_ty.enumFieldName(field_index, zcu); fields.appendAssumeCapacity(try o.builder.debugMemberType( @@ -3318,7 +3339,6 @@ pub const Object = struct { if (o.type_map.get(t.toIntern())) |value| return value; const union_obj = ip.loadUnionType(t.toIntern()); - const layout = Type.getUnionLayout(union_obj, zcu); if (union_obj.layout == .@"packed") { const int_ty = try o.lowerType(pt, .fromInterned(union_obj.packed_backing_int_type)); @@ -3326,6 +3346,8 @@ pub const Object = struct { return int_ty; } + const layout = Type.getUnionLayout(union_obj, zcu); + if (layout.payload_size == 0) { const enum_tag_ty = try o.lowerType(pt, .fromInterned(union_obj.enum_tag_type)); try o.type_map.put(o.gpa, t.toIntern(), enum_tag_ty); @@ -6760,7 +6782,7 @@ pub const FuncGen = struct { const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data; const struct_ptr = try self.resolveInst(struct_field.struct_operand); const struct_ptr_ty = self.typeOf(struct_field.struct_operand); - return self.fieldPtr(inst, struct_ptr, struct_ptr_ty, struct_field.field_index); + return self.fieldPtr(struct_ptr, struct_ptr_ty, struct_field.field_index); } fn airStructFieldPtrIndex( @@ -6771,7 +6793,7 @@ pub const FuncGen = struct { const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const struct_ptr = try self.resolveInst(ty_op.operand); const struct_ptr_ty = self.typeOf(ty_op.operand); - return self.fieldPtr(inst, struct_ptr, struct_ptr_ty, field_index); + return self.fieldPtr(struct_ptr, struct_ptr_ty, field_index); } fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { @@ -10704,18 +10726,11 @@ pub const FuncGen = struct { const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data; const union_ty = self.typeOfIndex(inst); const union_llvm_ty = try o.lowerType(pt, union_ty); - const layout = union_ty.unionGetLayout(zcu); const union_obj = zcu.typeToUnion(union_ty).?; - if (union_obj.layout == .@"packed") { - const big_bits = union_ty.bitSize(zcu); - const int_llvm_ty = try o.builder.intType(@intCast(big_bits)); - const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]); - const non_int_val = try self.resolveInst(extra.init); - const small_int_ty = try o.builder.intType(@intCast(field_ty.bitSize(zcu))); - const small_int_val = try self.wip.cast(.bitcast, non_int_val, small_int_ty, ""); - return self.wip.conv(.unsigned, small_int_val, int_llvm_ty, ""); - } + assert(union_obj.layout != .@"packed"); + + const layout = Type.getUnionLayout(union_obj, zcu); const tag_int_val = blk: { const tag_ty = union_ty.unionTagTypeHypothetical(zcu); @@ -11051,65 +11066,45 @@ pub const FuncGen = struct { fn fieldPtr( self: *FuncGen, - inst: Air.Inst.Index, - struct_ptr: Builder.Value, - struct_ptr_ty: Type, + aggregate_ptr: Builder.Value, + aggregate_ptr_ty: Type, field_index: u32, ) !Builder.Value { const o = self.ng.object; const pt = self.ng.pt; const zcu = pt.zcu; - const struct_ty = struct_ptr_ty.childType(zcu); - switch (struct_ty.zigTypeTag(zcu)) { - .@"struct" => switch (struct_ty.containerLayout(zcu)) { - .@"packed" => { - const result_ty = self.typeOfIndex(inst); - const result_ty_info = result_ty.ptrInfo(zcu); - const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(zcu); - const struct_type = zcu.typeToStruct(struct_ty).?; - - if (result_ty_info.packed_offset.host_size != 0) { - // From LLVM's perspective, a pointer to a packed struct and a pointer - // to a field of a packed struct are the same. The difference is in the - // Zig pointer type which provides information for how to mask and shift - // out the relevant bits when accessing the pointee. - return struct_ptr; - } - - // We have a pointer to a packed struct field that happens to be byte-aligned. - // Offset our operand pointer by the correct number of bytes. - const byte_offset = @divExact(zcu.structPackedFieldBitOffset(struct_type, field_index) + struct_ptr_ty_info.packed_offset.bit_offset, 8); - if (byte_offset == 0) return struct_ptr; - const usize_ty = try o.lowerType(pt, Type.usize); - const llvm_index = try o.builder.intValue(usize_ty, byte_offset); - return self.wip.gep(.inbounds, .i8, struct_ptr, &.{llvm_index}, ""); - }, - else => { - if (!struct_ty.hasRuntimeBits(zcu)) { - return struct_ptr; - } - const struct_llvm_ty = try o.lowerType(pt, struct_ty); - if (o.llvmFieldIndex(struct_ty, field_index)) |llvm_field_index| { - return self.wip.gepStruct(struct_llvm_ty, struct_ptr, llvm_field_index, ""); - } else { - // If we found no index then this means this is a zero sized field at the - // end of the struct. Treat our struct pointer as an array of two and get - // the index to the element at index `1` to get a pointer to the end of - // the struct. - const llvm_index = try o.builder.intValue( - try o.lowerType(pt, Type.usize), - @intFromBool(struct_ty.hasRuntimeBits(zcu)), - ); - return self.wip.gep(.inbounds, struct_llvm_ty, struct_ptr, &.{llvm_index}, ""); - } - }, + const aggregate_ty = aggregate_ptr_ty.childType(zcu); + if (aggregate_ty.containerLayout(zcu) == .@"packed") { + // A pointer to a bitpack field is equivalent to a pointer to the whole bitpack; the + // bit offset is represented in the pointer *type*. + return aggregate_ptr; + } + switch (aggregate_ty.zigTypeTag(zcu)) { + .@"struct" => { + if (!aggregate_ty.hasRuntimeBits(zcu)) { + return aggregate_ptr; + } + const struct_llvm_ty = try o.lowerType(pt, aggregate_ty); + if (o.llvmFieldIndex(aggregate_ty, field_index)) |llvm_field_index| { + return self.wip.gepStruct(struct_llvm_ty, aggregate_ptr, llvm_field_index, ""); + } else { + // If we found no index then this means this is a zero sized field at the + // end of the struct. Treat our struct pointer as an array of two and get + // the index to the element at index `1` to get a pointer to the end of + // the struct. + const llvm_index = try o.builder.intValue( + try o.lowerType(pt, Type.usize), + @intFromBool(aggregate_ty.hasRuntimeBits(zcu)), + ); + return self.wip.gep(.inbounds, struct_llvm_ty, aggregate_ptr, &.{llvm_index}, ""); + } }, .@"union" => { - const layout = struct_ty.unionGetLayout(zcu); - if (layout.payload_size == 0 or struct_ty.containerLayout(zcu) == .@"packed") return struct_ptr; + const layout = aggregate_ty.unionGetLayout(zcu); + if (layout.payload_size == 0) return aggregate_ptr; const payload_index = @intFromBool(layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)); - const union_llvm_ty = try o.lowerType(pt, struct_ty); - return self.wip.gepStruct(union_llvm_ty, struct_ptr, payload_index, ""); + const union_llvm_ty = try o.lowerType(pt, aggregate_ty); + return self.wip.gepStruct(union_llvm_ty, aggregate_ptr, payload_index, ""); }, else => unreachable, } diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig index 71cd46be02740ea78411ff0f8bed98d92ed7ef3d..d071952924eb9542036f80f13a2fc2dc3bf86d40 100644 --- a/src/codegen/spirv/CodeGen.zig +++ b/src/codegen/spirv/CodeGen.zig @@ -4519,30 +4519,7 @@ fn unionInit( const layout = cg.unionLayout(ty); const payload_ty: Type = .fromInterned(union_ty.field_types.get(ip)[active_field]); - if (union_ty.layout == .@"packed") { - if (!payload_ty.hasRuntimeBits(zcu)) { - const int_ty = try pt.intType(.unsigned, @intCast(ty.bitSize(zcu))); - return cg.constInt(int_ty, 0); - } - - assert(payload != null); - if (payload_ty.isInt(zcu)) { - if (ty.bitSize(zcu) == payload_ty.bitSize(zcu)) { - return cg.bitCast(ty, payload_ty, payload.?); - } - - const trunc = try cg.buildConvert(ty, .{ .ty = payload_ty, .value = .{ .singleton = payload.? } }); - return try trunc.materialize(cg); - } - - const payload_int_ty = try pt.intType(.unsigned, @intCast(payload_ty.bitSize(zcu))); - const payload_int = if (payload_ty.ip_index == .bool_type) - try cg.convertToIndirect(payload_ty, payload.?) - else - try cg.bitCast(payload_int_ty, payload_ty, payload.?); - const trunc = try cg.buildConvert(ty, .{ .ty = payload_int_ty, .value = .{ .singleton = payload_int } }); - return try trunc.materialize(cg); - } + assert(union_ty.layout != .@"packed"); const tag_int = if (layout.tag_size != 0) blk: { const tag_val = try pt.enumValueFieldIndex(tag_ty, active_field); @@ -4761,33 +4738,36 @@ fn structFieldPtr( }, .@"struct" => switch (object_ty.containerLayout(zcu)) { .@"packed" => return cg.todo("implement field access for packed structs", .{}), - else => { + .auto, .@"extern" => { return try cg.accessChain(result_ty_id, object_ptr, &.{field_index}); }, }, - .@"union" => { - const layout = cg.unionLayout(object_ty); - if (!layout.has_payload) { - // Asked to get a pointer to a zero-sized field. Just lower this - // to undefined, there is no reason to make it be a valid pointer. - return try cg.module.constUndef(result_ty_id); - } + .@"union" => switch (object_ty.containerLayout(zcu)) { + .@"packed" => return cg.todo("implement field access for packed unions", .{}), + .auto, .@"extern" => { + const layout = cg.unionLayout(object_ty); + if (!layout.has_payload) { + // Asked to get a pointer to a zero-sized field. Just lower this + // to undefined, there is no reason to make it be a valid pointer. + return try cg.module.constUndef(result_ty_id); + } - const storage_class = cg.module.storageClass(object_ptr_ty.ptrAddressSpace(zcu)); - const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect); - const pl_ptr_ty_id = try cg.module.ptrType(layout_payload_ty_id, storage_class); - const pl_ptr_id = blk: { - if (object_ty.containerLayout(zcu) == .@"packed") break :blk object_ptr; - break :blk try cg.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index}); - }; + const storage_class = cg.module.storageClass(object_ptr_ty.ptrAddressSpace(zcu)); + const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect); + const pl_ptr_ty_id = try cg.module.ptrType(layout_payload_ty_id, storage_class); + const pl_ptr_id = blk: { + if (object_ty.containerLayout(zcu) == .@"packed") break :blk object_ptr; + break :blk try cg.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index}); + }; - const active_pl_ptr_id = cg.module.allocId(); - try cg.body.emit(cg.module.gpa, .OpBitcast, .{ - .id_result_type = result_ty_id, - .id_result = active_pl_ptr_id, - .operand = pl_ptr_id, - }); - return active_pl_ptr_id; + const active_pl_ptr_id = cg.module.allocId(); + try cg.body.emit(cg.module.gpa, .OpBitcast, .{ + .id_result_type = result_ty_id, + .id_result = active_pl_ptr_id, + .operand = pl_ptr_id, + }); + return active_pl_ptr_id; + }, }, else => unreachable, } diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index fac71faf56ab2f6572f86e7ce71e66451eaddd58..4260ffb9e9d11ad488ef132553b82180bdc6d64a 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -4009,69 +4009,86 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co .union_type => { const loaded_union = ip.loadUnionType(value_index); const file = loaded_union.zir_index.resolveFile(ip); - const need_terminator: bool = if (loaded_union.name_nav.unwrap()) |nav_index| t: { - const nav = ip.getNav(nav_index); - const decl_inst = nav.srcInst(ip).resolve(ip).?; - const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); - try wip_nav.declCommon(.{ - .decl = .decl_union, - .generic_decl = .generic_decl_const, - .decl_instance = .decl_instance_union, - }, &nav, file, &decl); - break :t true; - } else t: { - const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); - try wip_nav.abbrevCode(if (loaded_union.field_types.len > 0) .union_type else .empty_union_type); - try diw.writeUleb128(file_gop.index); - try wip_nav.strp(loaded_union.name.toSlice(ip)); - break :t loaded_union.field_types.len > 0; - }; - const union_layout = Type.getUnionLayout(loaded_union, zcu); - try diw.writeUleb128(union_layout.abi_size); - try diw.writeUleb128(union_layout.abi_align.toByteUnits().?); - const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); - if (loaded_union.has_runtime_tag) { - try wip_nav.abbrevCode(.tagged_union); - try wip_nav.infoSectionOffset( - .debug_info, - wip_nav.unit, - wip_nav.entry, - @intCast(diw.end + dwarf.sectionOffsetBytes()), - ); - { - try wip_nav.abbrevCode(.generated_field); - try wip_nav.strp("tag"); - try wip_nav.refType(.fromInterned(loaded_union.enum_tag_type)); - try diw.writeUleb128(union_layout.tagOffset()); - - for (0..loaded_union.field_types.len) |field_index| { - try wip_nav.enumConstValue(loaded_tag, .{ - .sdata = .signed_tagged_union_field, - .udata = .unsigned_tagged_union_field, - .block = .big_tagged_union_field, - }, field_index); + switch (loaded_union.layout) { + .auto, .@"extern" => { + const need_terminator: bool = if (loaded_union.name_nav.unwrap()) |nav_index| t: { + const nav = ip.getNav(nav_index); + const decl_inst = nav.srcInst(ip).resolve(ip).?; + const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); + try wip_nav.declCommon(.{ + .decl = .decl_union, + .generic_decl = .generic_decl_const, + .decl_instance = .decl_instance_union, + }, &nav, file, &decl); + break :t true; + } else t: { + const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); + try wip_nav.abbrevCode(if (loaded_union.field_types.len > 0) .union_type else .empty_union_type); + try diw.writeUleb128(file_gop.index); + try wip_nav.strp(loaded_union.name.toSlice(ip)); + break :t loaded_union.field_types.len > 0; + }; + const union_layout = Type.getUnionLayout(loaded_union, zcu); + try diw.writeUleb128(union_layout.abi_size); + try diw.writeUleb128(union_layout.abi_align.toByteUnits().?); + const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); + if (loaded_union.has_runtime_tag) { + try wip_nav.abbrevCode(.tagged_union); + try wip_nav.infoSectionOffset( + .debug_info, + wip_nav.unit, + wip_nav.entry, + @intCast(diw.end + dwarf.sectionOffsetBytes()), + ); { - try wip_nav.abbrevCode(.struct_field); - try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); - const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); - try wip_nav.refType(field_type); - try diw.writeUleb128(union_layout.payloadOffset()); - try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse - if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); + try wip_nav.abbrevCode(.generated_field); + try wip_nav.strp("tag"); + try wip_nav.refType(.fromInterned(loaded_union.enum_tag_type)); + try diw.writeUleb128(union_layout.tagOffset()); + + for (0..loaded_union.field_types.len) |field_index| { + try wip_nav.enumConstValue(loaded_tag, .{ + .sdata = .signed_tagged_union_field, + .udata = .unsigned_tagged_union_field, + .block = .big_tagged_union_field, + }, field_index); + { + try wip_nav.abbrevCode(.struct_field); + try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); + const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); + try wip_nav.refType(field_type); + try diw.writeUleb128(union_layout.payloadOffset()); + try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse + if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); + } + try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); + } } try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); + } else for (0..loaded_union.field_types.len) |field_index| { + try wip_nav.abbrevCode(.untagged_union_field); + try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); + const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); + try wip_nav.refType(field_type); + try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse + if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); } - } - try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); - } else for (0..loaded_union.field_types.len) |field_index| { - try wip_nav.abbrevCode(.untagged_union_field); - try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); - const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); - try wip_nav.refType(field_type); - try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse - if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); + if (need_terminator) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); + }, + .@"packed" => { + // TODO: debug info for packed unions + try wip_nav.abbrevCode(.numeric_type); + try wip_nav.strp(loaded_union.name.toSlice(ip)); + const backing_int_ty: Type = .fromInterned(loaded_union.packed_backing_int_type); + const int_info = backing_int_ty.intInfo(zcu); + try diw.writeByte(switch (int_info.signedness) { + inline .signed, .unsigned => |signedness| @field(DW.ATE, @tagName(signedness)), + }); + try diw.writeUleb128(int_info.bits); + try diw.writeUleb128(backing_int_ty.abiSize(zcu)); + try diw.writeUleb128(backing_int_ty.abiAlignment(zcu).toByteUnits().?); + }, } - if (need_terminator) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); }, .enum_type => { const loaded_enum = ip.loadEnumType(value_index); -- 2.54.0 From c73db56b4543776ce157626361f1cb66df1dac69 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Thu, 5 Mar 2026 19:00:38 +0000 Subject: [PATCH 67/79] compiler: small optimizations With these optimizations in place, this branch is faster than master in ReleaseFast, and... not too much slower than master in ReleaseSafe. --- src/Sema.zig | 6 +- src/Type.zig | 167 ++++++++++++++++++++++++++++++++++----------------- 2 files changed, 117 insertions(+), 56 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index aa3bae74687d6774a75c4dd708187fbe1a4cf1cf..1e86fddb842377766fa0934a0115d35c38edd077 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2287,13 +2287,15 @@ fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) ?Value { .inferred_alloc_comptime => unreachable, // assertion failure else => {}, } - switch (sema.typeOf(inst).classify(zcu)) { + // LLVM fails to eliminate this `classify` call in ReleaseFast, which hurts performance, so + // we must explicitly check for `std.debug.runtime_safety`. + if (std.debug.runtime_safety) switch (sema.typeOf(inst).classify(zcu)) { .no_possible_value => unreachable, // values of this type do not exist .one_possible_value => unreachable, // the value should be comptime-known .partially_comptime => unreachable, // the value should be comptime-known .fully_comptime => unreachable, // the value should be comptime-known .runtime => {}, - } + }; return null; } } diff --git a/src/Type.zig b/src/Type.zig index 6442a13efaafbd68385233f49a52b4c2abc1c3c8..841ca38b0e536b79ca44817eb55941b864ac3f56 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -112,10 +112,17 @@ pub const Class = enum(u3) { }; /// Returns the `Class` for the type `ty`. Asserts that the layout of `ty` is resolved. -pub fn classify(ty: Type, zcu: *const Zcu) Class { - ty.assertHasLayout(zcu); +pub fn classify(start_ty: Type, zcu: *const Zcu) Class { const ip = &zcu.intern_pool; - return switch (ip.indexToKey(ty.toIntern())) { + + // We avoid recursion in most cases to make us more optimizer-friendly because this can be a + // very hot code path. The only case where recursion is necessary is tuples, so that case is + // outlined into a separate function; see `classifyTuple`. + + var extra_states: enum { none, one, many } = .none; + + var cur_ty = start_ty; + const base: Class = while (true) break switch (ip.indexToKey(cur_ty.toIntern())) { .simple_type => |t| switch (t) { .f16, .f32, @@ -165,17 +172,10 @@ pub fn classify(ty: Type, zcu: *const Zcu) Class { .opaque_type => .no_possible_value, - .error_union_type => |eu| switch (Type.fromInterned(eu.payload_type).classify(zcu)) { - .no_possible_value, - .one_possible_value, - .runtime, - => .runtime, - - .partially_comptime => .partially_comptime, - // It may seem that this should be `.partially_comptime` due to the error set, however - // there is no way to take a pointer to the error set of an error union, so it does not - // actually necessitate runtime bits. - .fully_comptime => .fully_comptime, + .error_union_type => |eu| { + extra_states = .many; + cur_ty = .fromInterned(eu.payload_type); + continue; }, .int_type => |int| switch (int.bits) { @@ -183,55 +183,58 @@ pub fn classify(ty: Type, zcu: *const Zcu) Class { else => .runtime, }, .array_type => |arr| { - if (arr.len == 0 and arr.sentinel == .none) return .one_possible_value; - return Type.fromInterned(arr.child).classify(zcu); + if (arr.len == 0 and arr.sentinel == .none) break .one_possible_value; + cur_ty = .fromInterned(arr.child); + continue; }, .vector_type => |vec| { - if (vec.len == 0) return .one_possible_value; - return Type.fromInterned(vec.child).classify(zcu); + if (vec.len == 0) break .one_possible_value; + cur_ty = .fromInterned(vec.child); + continue; }, - .opt_type => |child| switch (Type.fromInterned(child).classify(zcu)) { - .no_possible_value => .one_possible_value, - .one_possible_value => .runtime, - else => |class| class, + .opt_type => |child_ty_ip| { + extra_states = switch (extra_states) { + .none => .one, + .one, .many => .many, + }; + cur_ty = .fromInterned(child_ty_ip); + continue; }, .tuple_type => |tuple| { - var has_runtime_state = false; - var has_comptime_state = false; - for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, field_comptime_val| { - if (field_comptime_val != .none) continue; - switch (Type.fromInterned(field_ty).classify(zcu)) { - .no_possible_value => return .no_possible_value, - .one_possible_value => {}, - .runtime => has_runtime_state = true, - .fully_comptime => has_comptime_state = true, - .partially_comptime => { - has_runtime_state = true; - has_comptime_state = true; - }, - } - } - if (has_comptime_state) { - return if (has_runtime_state) .partially_comptime else .fully_comptime; - } else { - return if (has_runtime_state) .runtime else .one_possible_value; - } + @branchHint(.unlikely); + break classifyTuple(tuple.types.get(ip), tuple.values.get(ip), zcu); }, .struct_type => { - const struct_obj = ip.loadStructType(ty.toIntern()); - return switch (struct_obj.layout) { - .auto, .@"extern" => struct_obj.class, - .@"packed" => Type.fromInterned(struct_obj.packed_backing_int_type).classify(zcu), - }; + const struct_obj = ip.loadStructType(cur_ty.toIntern()); + switch (struct_obj.layout) { + .auto, .@"extern" => { + zcu.assertUpToDate(.wrap(.{ .type_layout = cur_ty.toIntern() })); + break struct_obj.class; + }, + .@"packed" => { + cur_ty = .fromInterned(struct_obj.packed_backing_int_type); + continue; + }, + } }, .union_type => { - const union_obj = ip.loadUnionType(ty.toIntern()); - return switch (union_obj.layout) { - .auto, .@"extern" => union_obj.class, - .@"packed" => Type.fromInterned(union_obj.packed_backing_int_type).classify(zcu), - }; + const union_obj = ip.loadUnionType(cur_ty.toIntern()); + switch (union_obj.layout) { + .auto, .@"extern" => { + zcu.assertUpToDate(.wrap(.{ .type_layout = cur_ty.toIntern() })); + break union_obj.class; + }, + .@"packed" => { + cur_ty = .fromInterned(union_obj.packed_backing_int_type); + continue; + }, + } + }, + .enum_type => { + zcu.assertUpToDate(.wrap(.{ .type_layout = cur_ty.toIntern() })); + cur_ty = .fromInterned(ip.loadEnumType(cur_ty.toIntern()).int_tag_type); + continue; }, - .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).classify(zcu), // values, not types .undef, @@ -255,6 +258,53 @@ pub fn classify(ty: Type, zcu: *const Zcu) Class { .memoized_call, => unreachable, }; + + return switch (base) { + .runtime => .runtime, // extra states are irrelevant, we already have many! + .partially_comptime => .partially_comptime, // likewise + .fully_comptime => { + // We do not need to change to `.partially_comptime` here because the extra states do + // not necessarily require runtime bits. This is because Zig does not provide a way to + // take the address of the "is null" bit of an optional or the error set "inside" of an + // error union. + return .fully_comptime; + }, + + .no_possible_value => switch (extra_states) { + .none => .no_possible_value, + .one => .one_possible_value, + .many => .runtime, + }, + + .one_possible_value => switch (extra_states) { + .none => .one_possible_value, + .one, .many => .runtime, + }, + }; +} +/// This is a separate function to `classify` to avoid recursion in the main `classify` function, +/// which can encourage the optimizer to e.g. inline `classify` where it would be beneficial. +fn classifyTuple(types: []const InternPool.Index, values: []const InternPool.Index, zcu: *const Zcu) Class { + var has_runtime_state = false; + var has_comptime_state = false; + for (types, values) |field_ty, field_comptime_val| { + if (field_comptime_val != .none) continue; + switch (Type.fromInterned(field_ty).classify(zcu)) { + .no_possible_value => return .no_possible_value, + .one_possible_value => {}, + .runtime => has_runtime_state = true, + .fully_comptime => has_comptime_state = true, + .partially_comptime => { + has_runtime_state = true; + has_comptime_state = true; + }, + } + } + if (has_comptime_state) { + return if (has_runtime_state) .partially_comptime else .fully_comptime; + } else { + return if (has_runtime_state) .runtime else .one_possible_value; + } } /// Asserts the type is resolved. @@ -1061,7 +1111,10 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 { .error_union_type => |error_union| { const payload_ty: Type = .fromInterned(error_union.payload_type); switch (payload_ty.classify(zcu)) { - .fully_comptime => return 0, // error set does not require runtime bits, see comment in `classify` + // Zig has no way to take the address of the error set "in" an error union (giving + // implementations more freedom in terms of data layout), so if the payload type is + // fully comptime, we don't need to dedicate runtime bits to the error set. + .fully_comptime => return 0, else => {}, } // The layout will either be (code, payload, padding) or (payload, code, padding) @@ -3177,6 +3230,12 @@ fn validateExternCallconv(cc: std.builtin.CallingConvention) bool { /// Asserts that `ty` has resolved layout. pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void { + if (!std.debug.runtime_safety) { + // This early exit isn't necessary (`Zcu.assertUpToDate` checks `std.debug.runtime_safety` + // itself), but LLVM has been observed to fail at optimizing away this safety check, which + // has a major performance impact on ReleaseFast compiler builds. + return; + } switch (zcu.intern_pool.indexToKey(ty.toIntern())) { .int_type, .ptr_type, -- 2.54.0 From a5219cd288c322f5f5bda89d608af5b243e9fd6f Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Wed, 4 Mar 2026 10:52:54 +0000 Subject: [PATCH 68/79] bootstrap: work around GCC bug GCC bug 119085, which affects versions 13.0--15.1, is being triggered by the C backend, resulting in a (small but critical) miscompilation in zig2. Unfortunately, we can't really work around that bug without a command-line flag, because the bug is sensitive to things like the order in which `struct` types are defined. Therefore, I have added an option to `bootstrap.c` which causes it to pass the appropriate flag to `gcc` to disable the optimization pass in question. This flag can likely be removed in future, once the affected GCC versions become less common. At least one of our x86_64-linux CI machines is using an affected GCC version, so I also updated the relevant CI script to pass this flag when testing no-LLVM bootstrap. CMakeLists also has a workaround, but no user intervention is required there: the GCC version range is automatically detected by CMakeLists. --- CMakeLists.txt | 12 ++++++++++-- bootstrap.c | 21 +++++++++++++++++++++ ci/x86_64-linux-release.sh | 3 ++- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 06cc1cd8ddba43e22ee6dd1a39eab58d67851132..146e507930706d8d779ce6a3977b39d7f9d9b78c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -330,7 +330,6 @@ set(ZIG_STAGE2_SOURCES src/Air/Liveness.zig src/Air/Liveness/Verify.zig src/Air/print.zig - src/Air/types_resolved.zig src/Builtin.zig src/Compilation.zig src/Compilation/Config.zig @@ -344,6 +343,7 @@ set(ZIG_STAGE2_SOURCES src/Sema.zig src/Sema/bitcast.zig src/Sema/comptime_ptr_access.zig + src/Sema/type_resolution.zig src/Type.zig src/Value.zig src/Zcu.zig @@ -360,7 +360,8 @@ set(ZIG_STAGE2_SOURCES src/codegen/aarch64/Mir.zig src/codegen/aarch64/Select.zig src/codegen/c.zig - src/codegen/c/Type.zig + src/codegen/c/type.zig + src/codegen/c/type/render_defs.zig src/codegen/llvm.zig src/codegen/llvm/bindings.zig src/crash_report.zig @@ -375,6 +376,7 @@ set(ZIG_STAGE2_SOURCES src/libs/libunwind.zig src/link.zig src/link/C.zig + src/link/ConstPool.zig src/link/Coff.zig src/link/Dwarf.zig src/link/Elf.zig @@ -623,6 +625,12 @@ else() else() set(ZIG2_LINK_FLAGS "-Wl,-z,stack-size=0x10000000") endif() + # Prevent GCC from miscompiling 'zig2.c'. See also 'workaround_gcc_sra_miscomp' in 'bootstrap.c'. + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND + CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "13.0" AND + CMAKE_C_COMPILER_VERSION VERSION_LESS_EQUAL "15.2") + set(ZIG2_COMPILE_FLAGS "${ZIG2_COMPILE_FLAGS} -fno-tree-sra") + endif() endif() set(ZIG1_WASM_MODULE "${PROJECT_SOURCE_DIR}/stage1/zig1.wasm") diff --git a/bootstrap.c b/bootstrap.c index 44ba0714764a387eff427c118e4a66c8bcfb3a69..329a1af10e5d9c4c61d5dc851587c1d80c0e0aa5 100644 --- a/bootstrap.c +++ b/bootstrap.c @@ -102,6 +102,26 @@ int main(int argc, char **argv) { const char *cc = get_c_compiler(); const char *host_triple = get_host_triple(); + // GCC versions 13.0--14.1 have a miscompilation where some bytes of a union may get clobbered + // depending on the union layout and the order in which types are defined. This miscompilation + // affects the output of the C backend, and thus can affect the bootstrap process. Specifically, + // we observe that using the self-hosted x86_64 backend in 'zig2' will cause all function calls + // to be relocated incorrectly, causing immediate crashes on any binary produced by it. + // + // The only reliable workaround for this bug is to disable the optimization pass containing it, + // so here we check for a CLI flag requesting that workaround. + // + // The upstream bug is fixed in GCC version 15.2 onwards (and was also backported to the 13 and + // 14 branches). Once this bug is no longer widespread, we can remove this CLI flag. + // + // Upstream bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119085 + bool workaround_gcc_sra_miscomp = false; + for (int i = 1; i < argc; ++i) { + if (!strcmp(argv[i], "--workaround-gcc-sra-miscomp")) { + workaround_gcc_sra_miscomp = true; + } + } + { const char *child_argv[] = { cc, "-o", "zig-wasm2c", "stage1/wasm2c.c", "-O2", "-std=c99", NULL, @@ -193,6 +213,7 @@ int main(int argc, char **argv) { #if defined(__GNUC__) "-pthread", #endif + workaround_gcc_sra_miscomp ? "-fno-tree-sra" : NULL, NULL, }; print_and_run(child_argv); diff --git a/ci/x86_64-linux-release.sh b/ci/x86_64-linux-release.sh index 21411ab2af64258aff7910c2dcd3abcdb834cbf3..0317ad55fc4b795de5e5671d987880a610c577c8 100755 --- a/ci/x86_64-linux-release.sh +++ b/ci/x86_64-linux-release.sh @@ -21,7 +21,8 @@ export ZIG_LOCAL_CACHE_DIR="$PWD/zig-local-cache" # Test building from source without LLVM. cc -o bootstrap bootstrap.c -./bootstrap +# See comments in bootstrap.c for an explanation of the flag given here. +./bootstrap --workaround-gcc-sra-miscomp ./zig2 build -Dno-lib ./zig-out/bin/zig test test/behavior.zig -- 2.54.0 From 4a310ce7c13c9aa485200a2b712562ba20854272 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Wed, 4 Mar 2026 16:31:39 +0000 Subject: [PATCH 69/79] Sema: expect 'alignment' fields in 'std.builtin.Type' to be '?usize' This is a language change which works nicely alongside some of the other changes in this branch. It will help to resolve the remaining couple of failures in the std and behavior tests. The actual std.builtin change is not in this commit, because we must update zig1.wasm first. --- src/Sema.zig | 98 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 38 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 1e86fddb842377766fa0934a0115d35c38edd077..f2c52697b420eeca9674ed4f2e5f75060a67809a 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -16250,11 +16250,6 @@ fn zirBuiltinSrc( return Air.internedToRef((try pt.aggregateValue(src_loc_ty, &fields)).toIntern()); } -/// MLUGG TODO: once this branch is in a more stable state, I need to make a language change so that -/// `std.builtin.Type` makes all `alignment` fields `?usize` instead of `comptime_int`, to prevent -/// explicit alignment annotations from sneaking in without the user requesting any; but doing that -/// right now would be really annoying because it would break the base compiler. I need to have the -/// compiler more-or-less fully migrated first. fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; @@ -16432,12 +16427,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai }, .pointer => { const info = ty.ptrInfo(zcu); - const alignment_val = try pt.intValue(.comptime_int, bytes: { - if (info.flags.alignment.toByteUnits()) |b| break :bytes b; - const elem_ty: Type = .fromInterned(info.child); - try sema.ensureLayoutResolved(elem_ty, src, .type_info); - break :bytes elem_ty.abiAlignment(zcu).toByteUnits().?; - }); + const alignment_ty = try pt.optionalType(.usize_type); + const alignment_val: Value = val: { + const bytes = info.flags.alignment.toByteUnits() orelse { + break :val try pt.nullValue(alignment_ty); + }; + const int_val = try pt.intValue(.usize, bytes); + break :val .fromInterned(try pt.intern(.{ .opt = .{ + .ty = alignment_ty.toIntern(), + .val = int_val.toIntern(), + } })); + }; const addrspace_ty = try sema.getBuiltinType(src, .AddressSpace); const pointer_ty = try sema.getBuiltinType(src, .@"Type.Pointer"); @@ -16450,7 +16450,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai Value.makeBool(info.flags.is_const).toIntern(), // is_volatile: bool, Value.makeBool(info.flags.is_volatile).toIntern(), - // alignment: comptime_int, + // alignment: ?usize, alignment_val.toIntern(), // address_space: AddressSpace (try pt.enumValueFieldIndex(addrspace_ty, @intFromEnum(info.flags.address_space))).toIntern(), @@ -16766,12 +16766,20 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); - const alignment = switch (layout) { - .auto, .@"extern" => switch (ty.explicitFieldAlignment(field_index, zcu)) { - .none => field_ty.abiAlignment(zcu), - else => |a| a, - }, - .@"packed" => .none, + const alignment_ty = try pt.optionalType(.usize_type); + const alignment_val: Value = val: { + const a: Alignment = switch (layout) { + .auto, .@"extern" => ty.explicitFieldAlignment(field_index, zcu), + .@"packed" => .none, + }; + const bytes = a.toByteUnits() orelse { + break :val try pt.nullValue(alignment_ty); + }; + const int_val = try pt.intValue(.usize, bytes); + break :val .fromInterned(try pt.intern(.{ .opt = .{ + .ty = alignment_ty.toIntern(), + .val = int_val.toIntern(), + } })); }; const union_field_fields = .{ @@ -16779,8 +16787,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai name_val, // type: type, field_ty.toIntern(), - // alignment: comptime_int, - (try pt.intValue(.comptime_int, alignment.toByteUnits() orelse 0)).toIntern(), + // alignment: ?usize, + alignment_val.toIntern(), }; field_val.* = (try pt.aggregateValue(union_field_ty, &union_field_fields)).toIntern(); } @@ -16881,6 +16889,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const is_comptime = field_val != .none; const opt_default_val = if (is_comptime) Value.fromInterned(field_val) else null; const default_val_ptr = try sema.optRefValue(opt_default_val); + const struct_field_fields = .{ // name: [:0]const u8, name_val, @@ -16890,8 +16899,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai default_val_ptr.toIntern(), // is_comptime: bool, Value.makeBool(is_comptime).toIntern(), - // alignment: comptime_int, - (try pt.intValue(.comptime_int, Type.fromInterned(field_ty).abiAlignment(zcu).toByteUnits() orelse 0)).toIntern(), + // alignment: ?usize, + (try pt.nullValue(try pt.optionalType(.usize_type))).toIntern(), }; struct_field_val.* = (try pt.aggregateValue(struct_field_ty, &struct_field_fields)).toIntern(); } @@ -16937,12 +16946,21 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const opt_default_val: ?Value = if (field_default == .none) null else .fromInterned(field_default); const default_val_ptr = try sema.optRefValue(opt_default_val); - const alignment = switch (struct_type.layout) { - .auto, .@"extern" => switch (ty.explicitFieldAlignment(field_index, zcu)) { - .none => field_ty.defaultStructFieldAlignment(struct_type.layout, zcu), - else => |a| a, - }, - .@"packed" => .none, + + const alignment_ty = try pt.optionalType(.usize_type); + const alignment_val: Value = val: { + const a: Alignment = switch (struct_type.layout) { + .auto, .@"extern" => ty.explicitFieldAlignment(field_index, zcu), + .@"packed" => .none, + }; + const bytes = a.toByteUnits() orelse { + break :val try pt.nullValue(alignment_ty); + }; + const int_val = try pt.intValue(.usize, bytes); + break :val .fromInterned(try pt.intern(.{ .opt = .{ + .ty = alignment_ty.toIntern(), + .val = int_val.toIntern(), + } })); }; const struct_field_fields = .{ @@ -16954,8 +16972,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai default_val_ptr.toIntern(), // is_comptime: bool, Value.makeBool(field_is_comptime).toIntern(), - // alignment: comptime_int, - (try pt.intValue(.comptime_int, alignment.toByteUnits() orelse 0)).toIntern(), + // alignment: ?usize, + alignment_val.toIntern(), }; field_val.* = (try pt.aggregateValue(struct_field_ty, &struct_field_fields)).toIntern(); } @@ -27434,7 +27452,7 @@ fn coerceExtra( const array_elem_ty = array_ty.childType(zcu); if (array_ty.arrayLen(zcu) != 1) break :single_item; const dest_is_mut = !dest_info.flags.is_const; - switch (try sema.coerceInMemoryAllowed(block, array_elem_ty, ptr_elem_ty, dest_is_mut, target, dest_ty_src, inst_src, maybe_inst_val)) { + switch (try sema.coerceInMemoryAllowed(block, array_elem_ty, ptr_elem_ty, dest_is_mut, target, dest_ty_src, inst_src, null)) { .ok => {}, else => break :single_item, } @@ -27452,7 +27470,7 @@ fn coerceExtra( const dest_is_mut = !dest_info.flags.is_const; const dst_elem_type: Type = .fromInterned(dest_info.child); - const elem_res = try sema.coerceInMemoryAllowed(block, dst_elem_type, array_elem_type, dest_is_mut, target, dest_ty_src, inst_src, maybe_inst_val); + const elem_res = try sema.coerceInMemoryAllowed(block, dst_elem_type, array_elem_type, dest_is_mut, target, dest_ty_src, inst_src, null); switch (elem_res) { .ok => {}, else => { @@ -27513,7 +27531,7 @@ fn coerceExtra( const src_elem_ty = inst_ty.childType(zcu); const dest_is_mut = !dest_info.flags.is_const; const dst_elem_type: Type = .fromInterned(dest_info.child); - switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, src_elem_ty, dest_is_mut, target, dest_ty_src, inst_src, maybe_inst_val)) { + switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, src_elem_ty, dest_is_mut, target, dest_ty_src, inst_src, null)) { .ok => {}, else => break :src_c_ptr, } @@ -27584,7 +27602,7 @@ fn coerceExtra( target, dest_ty_src, inst_src, - maybe_inst_val, + null, )) { .ok => {}, else => break :p, @@ -27655,7 +27673,7 @@ fn coerceExtra( target, dest_ty_src, inst_src, - maybe_inst_val, + null, )) { .ok => {}, else => break :p, @@ -27861,7 +27879,7 @@ fn coerceExtra( target, dest_ty_src, inst_src, - maybe_inst_val, + null, )) { break :array_to_array; } @@ -27940,7 +27958,7 @@ fn coerceExtra( // E!T to T if (inst_ty.zigTypeTag(zcu) == .error_union and - (try sema.coerceInMemoryAllowed(block, inst_ty.errorUnionPayload(zcu), dest_ty, false, target, dest_ty_src, inst_src, maybe_inst_val)) == .ok) + (try sema.coerceInMemoryAllowed(block, inst_ty.errorUnionPayload(zcu), dest_ty, false, target, dest_ty_src, inst_src, null)) == .ok) { try sema.errNote(inst_src, msg, "cannot convert error union to payload type", .{}); try sema.errNote(inst_src, msg, "consider using 'try', 'catch', or 'if'", .{}); @@ -27948,7 +27966,7 @@ fn coerceExtra( // ?T to T if (inst_ty.zigTypeTag(zcu) == .optional and - (try sema.coerceInMemoryAllowed(block, inst_ty.optionalChild(zcu), dest_ty, false, target, dest_ty_src, inst_src, maybe_inst_val)) == .ok) + (try sema.coerceInMemoryAllowed(block, inst_ty.optionalChild(zcu), dest_ty, false, target, dest_ty_src, inst_src, null)) == .ok) { try sema.errNote(inst_src, msg, "cannot convert optional to payload type", .{}); try sema.errNote(inst_src, msg, "consider using '.?', 'orelse', or 'if'", .{}); @@ -28395,6 +28413,10 @@ pub fn coerceInMemoryAllowed( const pt = sema.pt; const zcu = pt.zcu; + if (src_val) |val| { + assert(val.typeOf(zcu).toIntern() == src_ty.toIntern()); + } + if (dest_ty.eql(src_ty, zcu)) return .ok; -- 2.54.0 From 793fa93d9f99b49a6d91bd40195f5fcc783014d5 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Tue, 10 Mar 2026 10:38:21 +0000 Subject: [PATCH 70/79] stage1: update zig1.wasm Generated using a compiler bootstrapped from the merge base of this branch, and wasm-opt version 118. Signed-off-by: Matthew Lugg --- stage1/zig.h | 10 +++++++++- stage1/zig1.wasm | Bin 3183342 -> 3177173 bytes 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/stage1/zig.h b/stage1/zig.h index 81a815ab5568b57f5d48c8da91a04b761d4f9a2a..0b9c6e58ca6d9f1800fd8059e5db9d3636faa35c 100644 --- a/stage1/zig.h +++ b/stage1/zig.h @@ -151,6 +151,14 @@ #define zig_has_attribute(attribute) 0 #endif +#if __STDC_VERSION__ >= 201112L +#define zig_static_assert(cond, msg) _Static_assert(cond, msg) +#elif zig_has_attribute(unused) +#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] __attribute__((unused)) +#else +#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] +#endif + #if __STDC_VERSION__ >= 202311L #define zig_threadlocal thread_local #elif __STDC_VERSION__ >= 201112L @@ -259,7 +267,7 @@ #endif #if zig_has_attribute(packed) || defined(zig_tinyc) -#define zig_packed(definition) __attribute__((packed)) definition +#define zig_packed(definition) definition __attribute__((packed)) #elif defined(zig_msvc) #define zig_packed(definition) __pragma(pack(1)) definition __pragma(pack()) #else diff --git a/stage1/zig1.wasm b/stage1/zig1.wasm index 0c68522efc27ffeefbdc88b1591ea60c7ff102fc..11942012c73145171942c837b7c61c783f13203b 100644 GIT binary patch literal 3177173 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


rND@JP%6VwvxPFHXB5>l3-FPg+e7_ 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 z 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

)$y{w{=Kf@>w@oc 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

$FhxVwIzh`B4HWi-GdE#Zenn&8J5>8Htg3fJPX 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

<6}@;h#2)O5u56dMQo~JwX@_v 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

#q0M#%HrT?E)TbA`McDQmGVKp(sT%F+LRjD85} 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

5p&573d@v(T^rp3?eRka`rC-xX2 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 NQjSM23g(4`{s+!$CY=BP literal 3183342 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

*@B0S!v4c=I@x|?kZ^&B^@qsTjgYS=>h~3 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

kI(8hAYsOvZZEp` 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%0DO)Baoojc*KUMJ9D#)G6^50o``dw4~(XvI( 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

bdb7-#0@PZe@t2IFC1O% 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%0D1nRo?kLDyJ&C8{u5tc=7zvnf}XB&jzew8`1v&+ z6Oc@~y>^wq8}ak`;W9r*MTP~<4a0(ni$D9o6UNJ*07CoXd3_nqcaCGeFs!e@0XX7s z9WIpa3&Um2uu!@eh96Wb`J%nGhMixeI3if%#izi?m;95)&KFtn)itq}hQ-cJ$6oF7 z{IU(UYW#k*t?83YCSr!;>Nx_YX=f@;wcJYfwsTt<-K9np&>r4CbHnx1o>j4^T3GUu9);r?;{h{`^AP zc)=pXj&sQ`949}~HV+=(j`R2Z@JD;gS)F#=qgmfm`J)`o#-iES)9iGrq$aE&6vBR* z)o5EpLBl%{O{K)(I8LS@X2sDi#Jn$_xm~nd>CrCKFWM!#Y1IrJ?J}-jBeaMk7Rv2i z9_9Ve6t$EedObSzGgPw4lQ}Tr4q-C7V6VAFq^MvzjttWgzORQ;^x{qh1 zaTlH@W2hH0En;HPv}S05mdg%t<(oK%c{mkXnm4(oxq~Xh<$mv0foLrwGR~0Sn zQRKy-A5UIgqI|D#Wij|~OqIymHB@PAtB)GdM@rPVx_cvPG)Zcae#UK(8X0xx^ahR5 z2Pf}fGKFpou%ZPnO9@0RrdXkUCSNl>EaTncoWkUh{BJC#J(7PVP(aG}}>LLZ{sKSIhraM5nR&sg44#}ML3+Es}oJ8H>flEuC1-|h1cNHpo61l~<*WHaKy zm~=krTlfqX@l87)p*g4Vo|(xYWOGUz6So?%?Sl*9&r4kcR=m?4KI`!04tmdHa~*I+ z=je)HEINSVnP^if&q+!;2JEodsr+*8hdjWSJn$qBi`$zc)G{?>4GzyQ@ z)XXUp-N#a|4ti}zqS84F7>L4Iz+`!L&ERup%+js4AMzfek~NE8s2+u_Rx5}!%lTQW zOR}Dq|J>FA+_ynFyY-&vJn0zuf~8=b=P&(*ODCT))AhpOTYVJ6%SJJMc?*kb?xHof zIN010_2rBJjTac#SEhsVL71V7+=UeM{uO)wvi&8-R)T1GYgu8mCV2G;*SBlrOe+8u}g-EQ{+4mW7_GC;el8zg($6_KYp&#mh0X z1pCIyUM2slKSJ57Z6H<*jb-yzO3Gd(KQ@IdN=xtLq(mPB<>f(`))AJ8YHTSdlhVTs zmy?qtg~C|5wZdo_KLr6PvRIM!Ls3$w9V0Ij{hDYRH1cE{V&rAs$jb(dyaiJfU&_d1 zR=lF9a8n)&1^4j2ABfWxUb4CM0U#}uN@C;6+Vi1M_aLU|!=Y43wB`{(%fGPAJ=6ejR%rW0w&7@{Lr2NEl7N57m-sN6oYg_B{c`p#AI!$jQ*L7N zX8kSF5()}Cr?)QHTj#bPVGkpW!F&fB(I~r5RK>PMGKI8AoBHcq4vsE>ce)mQH)To-M<;{Hcis&`9~x=&ghuX5LZeFlC3XU4z8oSI!0U7K+nvOk+b;Sv1iEba zf+AxRvY!zKdLh!1-5`|3F~2m3NU=P+>1VTV{b=@ge#v_dCs$t#zR&#Go?ox%)tmO} zipQq(@ZGkE0os;yHFRR8HW@m_`L-uDIxp6b=G)*IpcVgLi&j%R%B-!3I;%?1RqMq> zbkkVdve4@9yg|qm1S_xq#~{JC`d>lt1N@@(F40~WuwcM7L$ONtz2(>cuLEeNo)=wi zOm#Y7>3gV(sct-;f2U9lb(~&z%()64ZF(-J?%UB9rjrlA_$j3HJegly*MIfr9?=W5 zsO|Tz+s8YHhn_z?^nR`w+h^jgK{Ae25oF@ri~z{~dI{I`NvABpwo2_6pjQ5YTGRXe zI471Oc*&aS2tcDzebCsHz2I<6e8zte6cj}|uJv26ExPW|t>}lRb+t1?IM#ibptPO) zc7$fry1?-`$Nbn1b)m$sA|*I<4nO-ohAVuoH|%Vi_uN#`F@Ah6;=aqo=G4?#Yie$X zV`Ahg%CZNuOGxLL7?MX=w<@d~y#>~t@54HC#WFbOz`7IGDe|p&g5a2brHti=#y~&R zfgsD$`gewn?2Zz|bSOxE*2!9otvj^aBfopHmOjAnPN^?o<;fjld=+~V3UU8Ed-&_V zk%ueK=0R0o_3bz*EPsZVziGU#1ZH@!HmUtL6Ko$F-OF9eO7+eO}n}Ur&TjG4x&i4mbH1GoahAwcN z9HW)he!yKC%F8uEE&JEoR@Vk?(dG4R(aZg|=z+g&w&=fm4qG%^#}<_YxrHry4F3Xp z1T*{J$rio*vTRXirQa51-d?FKip>-#)Q6+o`F>bEaR^S>%VUt|Ckz^mM!8?Xtvwz2ncJ&n9J0(K@nqCV+YPlY7w^S`!&)7ZU-oQ~Djev7)#O7yf%o!ejbafi zxhQURkw?2L)070WH1IBYJ*Woz;w5{xxe)|Gh>HVM08x~hep2>R5F> zKgn4=KQ+2;2Ib0VIm1E&LSFQ!a`5DlVXAMcu}Of0)6!6pJ3X~oSZOh!Y5GN2UcEbJ z&rMq&U5@n(JzI0g?t&Qq4DW=9YF3B7vKUY)hS$L;Tl%}0{|6M(>y&E>2<0g1-C z8P|^mBZYV8)x>%Gu1~Df*e-BEcvQ?wF}4eSYUcthpTE0xlB%o7bb#YBgbXV&K5;!Mp!fnTQ9X=!*))ik)N?*MD~YWW-q0kwRVzrB11)l76N|7c~N zz6fWnxNzI@9kiDgT1LvRUcQ6Y%*QN1Q!)c<@GRS*srnhVY?W&h(HWX@*$(`eYsd*Y zUS#oTFNwiy2e8Pp9je`I2W`7mB&@KsR@n|rxX#FSP);LfWII${wu2gU*$zq-l4D!U zj5L>CXxtFT0e+VO&hlZ>G^pY20jD@BcvNIZD11WQ47)}hpo!?-Y;*DvYNj0sA1Wh_ zp4%V1L9MGmGQR}fBO3dAqK9cid)wFYCHs4kzm4R-Y;m~!sC((HdWk(Kxdps`t)fG0 zB+p;=MeQQfyj{5(bP*??wJR9B1uEqy?aFl6eM`vo{iFQt^h zmZhg{shSm8<#Qsd1wF;_0>}J%?VR<68trJjr0SI&4s0*P@n45aVn0Wp$0v zXep!8EmqH2k)lcMf|@Vdg%V+CVJN9aTASJIO&J%##SKIsWt*Cjn;E|vTfrwR4d zd!`aI*~{xP5;EfH3-x_a=GASbcNFTI2WaVrXLN)P=5z!dPAOz>MEnw=z7pa4@p8lq zJ1B+v9Lc&+UkmSt%cWzyEuT|}DMA!G6AhL_eKl4&)?PZF6LwcC)HDnAfycG(lnKvQ zF$s*LGDRXahak*~NT~?*_1J6A*sx!p$CE1MlO$DWNcAKc8}(D(T}?n>?rT z`KKe&oe<-LoJtGiN~^*tYHXb9GBB1n)o-|LHw_g!!pJwos3Zb5W>nSuhcCdWww9QV z%RbF;pG_Sk!I9VDRP1(DE%B;q{*!ubsQg+AhjVWXKKp4syQTlx)&|dhPR}+=&x%O; zcppv`c%Qn30+XEZxj7QyYx81DywA@-kN5R**&Xj2vAkH7$Z@=n8Fa-7*n(D4U07*6 z&?GoKu+_`N1EDS(5A4f}B?S);v4kJ{1xuBH;dFVR<;5CCbP=4MUIrz_9+q{ar&olc zT)!HZn81~IeI{^C8DKQYZBs^GnhC79H&`wF5=?+VEMow3U*392*<8_ zELRAxzE81)-n5b_*6TKsPiS#)mvc$f&#JWb#-d)&=30^2C*rk+a~;B2=@AZCo8N09 z-qTI{8=@Oy;3XBJt6O^k|C>V8T_r><3wTzuIUTt_m*7#!Xyt7~&^5wYESuoJ>C4OxN;{yN(q3A00fMf)EFsOfmK``Y@*Y8*aNb>#&E08a z9~kswdNa+gBZhm0spQ0oq_;q{9v>GT6x!(uKj^eALYJZq`r4Hfm7XrDh2MyR(v{10 zWuf<$RMO)Wd_DAC=kuH|R=TVV&eZ9oDY^BE?UZ@@TqWBo?v5b=by8{;<_?utI_zTI zsqp`Hd`L5Hv))e4?}R^!A@NB?@q+{uE7+)BCa|o=5c-bO*(T3P?y%KBqr4;C)k_51 z^$*^P7N!jxOWNxUm$t8m+|xbNQONCcpgnfCUM6;H>w}Hu!EpYfaCCPWuQRlMkIz|) z#reIZ2*deWF+f=qo*sPeL>f>uV1Ray4>m3vxwiUG>erDXL0bkf2~<8c-|}IU-AO<85dptr8ybkUoDsF z-jc?463+&RRoL<4;27RFXj)}0chjl~Sccy7ua;`N*yMQrB|2y4AV=oXA1Lh584-z# z)Z;@4Pa|(Q!9JLW)BaT|0;{mcY4TaS0+;gN8IijHHQ!x;g^f5!;8Fg=rf@F9k!JX6 znqb4}hzIzTpjfc>W(@yiC3M*nzFM5kZMBk7R$;YD2^$7zsp_;*U8e{cy0ta1YJV}U zKW!TN&8n>qbBK)J8&S-olW0uFo^1`Vg`IFXd|f39xr?503|P&bhLe+1?;|>iu(f3C z4c;h^enY6*`@}90?=jl4vL-%udx_0)P+e0stUulRo=2zAHl#J%G zp{;JrGX_$l&geMGfU_E$c2NHM6vls}cL$W%O;Su*sgA&5Ui+2aTPm1CPP)OFc^9dk z4T*~lc`kOcky(%B`=YE6LpIyc?4^FN7BpBm1o^wb-K z{E4y~L>JAgHcF+UAh%y@y=pUV+GqNvoq|;00@>O$Ccm2fSgdELo8#0lg43~7Xb6W` zsxY8_`$a=T`S?-MoUY+GV_bEHGY#z2S=q@(Wu>ErAGq$@xoySbODSnT61e*Y?zCA4 z@oWLHIn>|`j*+*#9-$mJV-*HF{z+s*u_^}Qr4Yy98Z{JA>Eb}@b@A<g(10xaB={q@@p-ouA)R~NDBSYw17^8{&rJ zr~?QRFtsI2CBZ7tZ;z=hVJc2CT?12z#OVx7HJokrVJdQ>i>V{R)DaMt!cXm@@Y6zr zQktoSiDpL?VygQvk=F{lF^hbJU=>AXh?wN_NTbluNFk~p_F<-ZZN+9aOY(Dl5BziD zJ_o|{iHkH8MLASfQcG=oaA<)TWqyHuwUl+X!26BlImIy-eN(!;e&vptQ8lb}gr=7h zBeTf<{p4S2<(A3}TA=8L7W%G^DExGTzrB@Pt0My3R;WyFlKO5DSpq{-n>rQKjfrGU z7fUrXB7Z^6E}Eg3&@sRk+qmSbFDzM=29{xQ%x8g}I2~;goZD2a^E%-N!o#bSf_!eB z0XtI~Fzs37pI6K(KiPdAFlQ-d(w&8qHVbqHY?M{Y)Pm&5ukoA=l-Rambya;)&-+jwF9#maU~UZ>RQCH^oJXvy>zU07K-Wbk+O@@x^(I zFXGH}>lA@dU!PKv*ECupRYLgN!}jShVLM-2FX$a=x_4qHh_jWP&=2ynm(;SH8dYq# zN~wQc`YWjk!Mb!8Jk;b;5#m)^0*mi|=JTlerO+X?*YTpmuP%41?YNrttuAM=&`Yf@ zXAVG077ZD4vMLW7qmbOn*T5gN{_67bde&ZL2*0|#R~dq;T1=%?BzaqMS{!j{OclC~ zsLqTfbMjL(k}p=Yggc+OFPH%dylh^7MfzAFo82(iG|ex2MVRn-dfgT2)%=WBc8&EU zbZMA<;f>yk^q#X4C|JaAP}sU)zCiRKRqDqpTaj+cKje&rrl`@zE7Dil#+u%&Qpg7r z0`=efoVch7)gpv}73sZY=SXPiP3t2H2^}M$UEX;t2~BAi-9sEfjk+aIYP{3tee#1c@Jh<;li2x)W8Db885NQ~ew)*aV zghnfFAXf$l(l7^>^WPhdjPW#+4{quvGZZQS6_p+At9`JW?$EOrsH~$GK)lJFAl}qY zhj^1ag?P3;f0|QcdFvzI(oRc*FA(qYP9wX^J3ZMI*(f01;?91=TVK|7QzD$KdzCmJ zi1(@Yfq38g%_1HKg~>XVPg=kF%1a=g`K_F+Q@WV=7r)l>uVpuo%f&zr@-LHh1^)sI z*ULxh@-H!sm#n^G>n2SUT0T-N{uMj^Wz|=Ve<2{d`AF<5mi)+Q=1O&lEf+{|&B1=H zfZdS5Y|?w3q--W1F5WY{&*d?#xYt$&UMuOkh)A}vZse32^l3t9(PW%8L3W|D^uB?CP$Pa)wqTvY1!Z7bO28TL5r2Pg-6h`8a82 zrhJ=qbXJd??cLBwfbQBxjS(>>yFRY(?Ps#4QN3)vPMXmAdR---`*Co6@4C3YMz0%` z)dq#hYE!F_)u^d2iR<#zmSwe78qyjsVK;gm8uiAwer~rhjdKL{dU_q6mx9Um;ks2C z>eK7IzE+6l0lm&^eF$i%WIequZKK!8)OvZ7mi^b7v|rbx6-!%07CoEiZ{wsbxJg^+ zn>1{z|Avz$9SZX{E{eiSeIZ1g{OG7?6)Odk^nQ)x{$T13Z=m~R&m{-_QUQHePUZi3 zH+j?2^y~TOI9?QS2d@pjqN6Tcw+pOK<;a@7bo#rZtNzlmE=fMzfdgYVpiqPaw$MzD z7u>GQC085>D}5kFm@@2nqodRbe8#&om%WJP;J$-a&fXHL56@i^lVJrGr%9!F zYvY^ZxqL!FjyWO{2g190&)q5A>TU+Kl1#?f>J~?u3^REBy}W$I?H= zh@Q!Brz~<9Tkd|!d()OCHvz!)x$loqUWRdQEv{k-a++y`jT<`-6umz@QQn z6qty#1E)1bfk1QbJ2>IE$)8j)7mKZ!lH&qY0Fypu-vd_c<0)iOKTy+JE%86Iz|_7lzKJgyFzji3pCuI`L0?ot+mq$x$6F_G|d(bsz||+y{zhB zUYxd0r}dk3E)UomTp;OQ2U2P?2FL{4s|!@Ot)<*v#4u+#bl&Qiw-bvAorft=;v?8O z--?=UzrO-IO|)v3lv+=td6*pc*f^Fo4F9zYqU#>tC)}wFdyk<$!(LdduDI0s9>pjV zyueVh=<@}UmqTVSvyZq8DJJfT?xOJ<!kO^GT*gRE(koxG?Pd zs9%w>5i67ebyMzxy;<)OYhu$X;S?*H4;JLY0vd=>g9>_;{?iYSZ&oRsSCVriEzrr@mfi}*(hkL?tO=xnG_FZ<+ zkPr+MCiWe6*y-S#`=_|zoIN`CwDT&5+uJ!Cwh!%AKdM8!+8}0i zXlFZbbGWUY4{;b%|Eohg+W9Dl?d^OEhi&bA8;7m!d-hf&c(l?^iT zn8PN*k{tMKjl*!8L9en9G9Tv9)?ikNcjO6&W;@@^q0!E_a;Q^DgF~&Ik8!BB^V>Ku z7dtt`?R+-}=Hhk^Oahf}Mc&oq$Ba-bntzd>)>GI@;!QAAP;S#{_FeUPhn6i=WSIES zyi)$9{qwH$C_=?{p_F10n@%p278Qu!c$b#{Ev<*mzi)R$Uf%*R-tu}9b>!8qq_CLLg3 zd`QmbYA>S%FQUT4xTM9bZ1snYv=0@tbBe}}x$x5v!U(FU3OybmQga;hWYae7)RHCS zc?GSZ;>{5>W*Fr+{tvh!KAc59^9;VQJ*bCKy*bpV@n5x8iyQ5FtzIGQ;&=py-w|)F zypy_0PhmE}KA@ZKU2ah+NEde~)JoR&I1CToTgk_z7qG7YTSQKhmLP+wj;+l&IjF7Hy~|@Atb>sJxfm#S@AE#w)2tr`=uE zZ*`4n9U7iVbx#h+obU49fv{AW&$bn*><_3&qqW%9sPYt2%>>G$T$stv*kq)=C|;nw zet0X(!*?R*;av>illgnzJK4ZK9#SbxtEW{}JhE?W3c&BA<-628GN_vT8+^X|gNO3} zXaV8A!7E;PE6<7m)fFv9vX{c-0|PVi>^uFW6d*)zBsy!|Ld~g2gEG94y5r{`jx;d; z$87$!mb5&L#CENnQ)*|9mn!)w`^yOZkd5nnSRNuhuk{*P?Qr8=Y{xnFsIx_^k#lN9 zyNgzAnUoDP`BO~J`MySqSaBdxzd!h8_Si0Z*lZuh)Oh}|M*X?NROFC8$C9nXli~Mj zGnd+7mFbXWQSOCNXbD-75`7aSVQ*5N55|5hQBb?r3ZzH33-5;n76K}MhY+7_Ak){> zz^54wIFfX_r=3kR4||GXPuj&6r7mC(Nw?TKjkWJ{OUVJTG=6R;(-dlw0{O^2(PLbd zsEJLaM52CfJSm1S2nf*ow;a*rNM98bu|J zD$>MEZ-tw&9VuiheVY$hK|9>9+aIJ~bry@d%j`K2syLH-N4h;{y2gNU*5C{{;Zk&1 z8x&}eq=XB|Lq~z}U2bqD8JvM#v7zIH$zTl!D6_+rYJIe^wONC`yIBD3Tyet9m}c!J6lbV| z1L;v9){4g1l=Ue2pyrB+`+kWPxV}Ay#C{u3u&9y0=r6GG;<+Exb4UYw4)y8nJi&5E z{z~)dJ@*bhrvkNxD{B$FXzxiq2j>;;5PD)BcfVfufWGoX+ zHXZL@hJnSBjrrZSKW&`VH$y8a8Fto6z5sD9khdZa=0yXV?ui17@UPkxy4SsO-LBBRZpUzd zF1Sw7xr5OKouklQ))7a|C4X<0dsjHOWKLG}CI6BPu(Ec7SmP$U{b-=YCDoOSgu&V0 zC(dtj160xNE*jr#3hxkSeeD>Xz_=dbc`d8MF6~3=hxHO!O{^c1!5fp4sfWbQlaF!v zK=_8Tv@G(U#B*S@5A@_5RwNK29pvv*xSjSMp(SYnu`NmNf%;Z`lw2t{-`G{m2s7Q1 zo#)5;7GALw+S^d_0+6E4;O3tr z53$AZm}SnwuVTs{AbG;rm@O>5E~O4!aUBU91sF&1ooy;uw5Iph1Oz>vhLNbpQxxvx zDOiZ_EnjtgQpTi>#6Z6n6wlITl*YwW{{wT)7356xsY|{nm(ZwPUQiP^V1|4uR*6%qA5T0 zpA-sclgk2~v}c#4UqX|==>j{pX=MLkpSN}g;A5>p7rrw(7rN^xbhq!=TjjxiZoR>t zEDiR1Y?72Fjn~i6y<}&>LaIumts(?TqYYgettVcm1REnHeFp~JwPTfB3rd#QiH&`k^y;FB1W_99UNr-$N3r4dX(>6%(7}q z7}Gd!x5`rBl3giFfh+Fyeks5b0~=RKfwMYC3M}f#_+Ie$Bn2*Vu3hqME+qw2+`?FL zs8KR`{Ao&MNWsmouYpFp{6WMenRLvq49KKq|3yJ_Rp&snsw2?c@b?7GP0sUWgC=w` zsWfwNY-nf=2-=UYAB0nOWdMX#FZu)mTRs{HGadwXVYI;#2*(A&Did3XMY*9J2IMEK zZ{^uIyQcr=*X#cboKP%9A3v^h`ah>5{XgaJ>EmZOx1A2fCI)3PMp(tk7@V$aY-Tgj zN~48!Q6L-UFtV`$R2Vx3|h{<4^3$0FP$jGXETp{-WN~n*AXVmdi)oNx z41$<^11ysdj7C)#A6uz7gO$-2E=dmYFtsec9^uF6gd5u+-`Jh5#j>edt2e@Cv}bR6 zdwhGP0#t#F^9EBBe`iQ#kzgpp5Kq1uLC@V=q1(GkcRTb07_k;cwvCMq4UcR}MmKNS zx~<;8(Al|t$4+*ojB{4O(wRzE9h^s7xgrtb1kV-SE?IHCC1`-LFV+IHV2ItTqvS8K zZ%c4kp%pg53vjL%P#V6X4Mz_Q?=C&s1Nn9!0*wXt5Ss(P@J!ZtWO%3HIgK;+i|i}i zJY4%;u~DfvZvar|m6nQWfHLoo^t8){KHnW38h*YdUBRpJgWIhBi!NlgL*2qOQqQWAm38hAs`x+^BN;Nd4#97gZ?SP6&GiGu6qe!=DR=SD%Ozai``57Ug-WH665Y)?q1^eQul{E!S?>O?j?RNcYnyi z9KxO7+v-E&9%f?lqgiZxA5&khlMUa;#1Hd$t>1Q zjh`sYC3`~=Y^OXHvKS$V7{;2E0EsT?<;(W6HghUSmijfwV%T@_ewo@XM|^(Zw&_=}wi41S2H>eCzKf!?k3dM9PR;yXjN$GK&Q`LjHBONeaHdK`5{WWX$>8E?^B?YlS9_%hULkEL0!ta- zlp>%K8Ja8^t!re6w2wl#^Xii?P+mNKj+cbv*m9^Me>M^|oRf4ORirZRv=eIpTs{Pv z;Yg-buH%gS1f@RZj9mV+!WpTk1Mk3vDsIw%5C;?uyV5SKkg4QnaJ|W}nlqIoPCnFD zTq?rYA8zp|!kS2sqNR`U5CI|n$`MqNBghA;9_`J(?J;Ge%FwHm-`Ddi5w#*HuNVz? zysk0z2qj4kAl$#-Ppi@jD&_=+8UaRw@V0XM07tX`3;iNWZ|y<;s)cE-Kny>~`*Qb^ zuf^Y9D{n8i0)o(rM%3(4jVW&Fn+^ETse*dueH&52MsH-UU8mfIqd-Pv2x?a zmYG981W)va0E@ZeLMcoI>=Q`grELAw4bn3LcBSVjX4LHp3XXTf5{(l4jqh+!KU=qIo?0cxzkgUPb#+s6Wy@ptd1bjyzb9iD|qkvjePNOjC>~3`@9I* z%P6bxk(e@SgzR_`6DpZu-ErZB>a!$-6=IKl9)ShDdcpODzdcl7bHTc?6nLUGVG=HU zKDwV+N8gm2_%+KND^a)-NdB2936yC@hYc?CpA%`0Ri_i=#S6(K2+QUCgHJK%rE5rs zti`pPQQ>U1QM`mOnlr@j@K%L@!h+4pJVZq}d`rJ&T2khR+{*Q4ETWR}&2*0O&~BCZmA*!6BtH^Bz$1It_WS}v))s9O&^qGgE0F(cs(u~=n%L!!1?Z< z>AMmoC656g?n6&m^d33IYzq&9R$MqgMg5CSY zKeb<>>AL<~B=c(ZV9NJhRD~tEqvTx4YJFQ4uqxXEEf&25U>98`57dGt-Qd|>N3wuR zNb=$mnoRTtO5y^ms37XkjS{KkKl@2?s78Dam8DCuV#H@l1G9<@^WD~#^__YPR{cslWc`${%C-SN!q@$c! z)vsa|jlRyO6yc`J6YiWKlX8nf8q-pkK+9WrXkXNjSmL5z*%xR9AL3fqlA|&sbXH#N zhiRmKB{o{z4PBUH%yUgif2XPiE|mV6uouZ!wgJ7lFW5?-o!h7s!8U&nv6!JZaNyf?7NZ2_L-px{D zlz{!gT@v4XAI8)f#`WF=J4vo)0t`!ZW~oZxLh@la%7IX;l##XMxp#~y8IolP?|XUV zzi6%Tsn!wvW)*T3lj|*S2o8rd4BQu5raW=B&|;Eh(^ZaYBKUxDYuxNs$b=`(w-B)$ z&$Y5ZJN0mSw$*9n&uX@XZQ)ZX8`^LR0;b`ccER+YwE>djT^Iu*9Y|RbQwn`QoSl?N9&P|Gh(Vn*BO$lEwT_ z#6M`CKW%Mwn2LUCF8jn3nTO~;179)MS(tnZQKN*r8u}(9H%=?oFFx-@jrA?9DbUZ* zNf$cA+lQ!V&C;k(Kzoc1Lb}Bf%sR_a<06{i0z+^Qzcl82v`sO$ALY76i+d9gCRmP& z!t|PYG0~|*vVQW3(38R(RP$#^=CK_E#IK?uCWG9z2z<2PqDV56HQ}iRT=UP9j@EqyhU2h-ryWx0GxWLL{%n;T zbz4CpVu9A_hBDIKz7aIPo4UErD*Z-6BV)$FcEOBJCWe9xR#!aK7;gI_xm1PVV;yji z8$xyIh;FY^j8QNhwz#{eI97bt(U{V%Vr!=q?WEj@U#g-Ak5x>JH=?)^(G^hvHQwX*7)fUoYK5?k-!zLgNB$D)JE z5u&NlLapv-u>>(f)+w{49$lMI#8a)?sw!-I=q$+P}%zEpyKGD zO`9b9dpaOZ+S5VB=%8xZVh)K5?=h%cO^(~RK1|NCNvVfu#k$AmjSlSR#a2NFq!5d( z#9Czmkjc+Ofru#lKa85>36I+QO2_7g(ZQ0j4@h5y40u8Dlikojq@pVUkKs^A55k-y zaYap^SC}Iqyyn)=Y^34_W8gU-RNAm`%$5hZTsY*-!;-NsNdp(THvIT5zQBm{X`u;L zGu-~5lT=vo5>y}{2=*0Grb)ameR0cEny{Alw$YRx&ZEOO*-UTK;oZsajkVv4jPhA_ z5*%=Pry$Wc5rtmh%R%zvZC_5>IJnvUIFMM2$y2CGXbzujWQE4WHV|rxzLZl(E6GO~ zJ}n@sI$`l05(mX6!qO+;CbnjW4_pL85M;(^?k1yqw(YDquEfZ&j+Aa@?p{8J0r5KD zoC%Act0XgBsI{OYPQIXAeiH6!Qrty3d}+1)@2UiiLdnmCsI+v;k3`YSD*1FUaLpFP zs$Ep7`RgEDmm15)V2xeaRLG#TvFpCT7Gw%R0u~+pVud??Z!7C>^laLY&VYrX`NrF+ z%KcTbcWYnU*gfJdzm>~Od^`EMO4d?`x-C`B;bFB4J%3`H_C<4KQ9a5_^0%~-6IxVj zUxK|nMw4*acW@UC;_dG63g{Bx{PjAp881&5iwqx4|P*a$24ZDGeE^qo)Q z!uYugq5?DUzJNTVYT9B6mmZwv)-hS;hAVm?w?Q@|6$ID(C6#(eGQP zkV98Pd`EulIqa)l$;Gku|FO4-J1^lOsEVz4PKuud9{KYAA(doBu+xgOJh36R2V27C zmPR$+!hiKGTcS#flN!;j;sfZ~vM-@+x9~w8#{8fROvv~guDjvQ+!CQy^Rr!Fp(9Sp z3w3iy4S`r{iNf8xrs^su*u`KHl`sFL-=ez*drQ`hZ@6NCHBxMq6?;pd{%#ql(N_tm z8v^R@ZUEHgwo-6$`x}?F)JJ2o@Z>43zb1NEbm(UaL9T&(8-Upg60z6(&N9rDba~kW zDL=@%18E$zmjBrjaBu3ZZ=#mL3y0I^(-wtAjn|3C)k+0^YWd&jmA=B@eKVlpw`B@; zwPetP2N#3~fRCM|Y+#P(LxLahDA#Gp0(qvZ=Ke;B9d{O6uVw&^Je`qNf?&I!mcUah z8Ng~$LPKBH`bK&v1%6$^L?OI!ksg*RAN3)T#=Jydy`mfi zeR1FDi!T^`L1zVh8AUq+6J2jiV8}6iE<>Ka7?3se1sHUkH8if4nw>wU0L?g(_Wxt< zZJ_MBt~$^A@jj~Ft5RKAvQ>6D_N^B=Elpe4O&iOtm{`{<@kiTPNweHDUb8}vd)f<( z>!8%Hy9#<0Rbj)h(nab1Q84<(o?8kj zu=Vt{Pt@zeBBU+Dp8^8Xoz_ldF3`o0uKGpw=d>%=U>LlG{asb}I?R2tIHbkH4XhQmr6&ipD##Uc7S@0P=pV%zB13>R zc+$_n8jLhyx$0Wtic6Mp;tXWVJGiO;B=wsQ8_lF|9h~6RQmS ze!nT5I;u{cZk6c`Wg9g0ypi^Zm#`p!31C%0pf0{jF8fS z>rJP`X}%eqT2iMjI}M~dL)jl{nwrt(a7%%HDC&Q|s2`QLy)gCV(Cf>gSIZ}`T`x@Z z+42bhtr^`CrL6T}%3odhe*_HzVBxS%#l`K_!!U^O&#z`#q7T%>Nw8_{*5ii~?6k#` z-bx-sozdl2FHDpEJp1`%@Sxn-_s7DNgoVl0PcKZAL~o)bMn2)ZEK8{4z2UcKX)y9( zISre26GWp?{ulv!i)~tb zM8d)48bfz%QMs&o=zPZ}4 zbIl+h@L!TnO=sv1*r5tU174QZoE@lBc_*LllCgp{8J~~S1Kq)lC`5~mDOi8C#I31*+<$Z%`(KP>%xnf!Z#-^AGiI{GGVA&9D|v0` z){gZ)&-%tTxm)MKgqiV4s&-zE*mLRAsAQ}LPSfHseHpwnrr9l1h1MPQK3Z9?8v2%5A>{GEGI8zj+Qg>#DHOE z)JL1**3`yoF4}xK6%xdt+iu4F0|S^ECy0R?$d!o_BqlH=iV%?G7s4n#C0$8C48s-y zZb|HLCry^0%|L?YNfhJU==ZN3O`CVfT@og2YhF;IPt9aw)TD@;Ovy$MrI3Ns^F2Mh z0jd`%f+R1%)|cSJ%J{~gO?o^9F7@70;SIWYmwE$lmF4zmawos+U*sWf$8`8p8ENP2 zAra!(Q3O{TGeA<$QC?mT_@E{aPU<@XH%i@YNpya>Qe46D^z$5LzrqOt2J2@5wvIT* z7G78K^nc<)+0A;nEkV7hJHJOc%&gK%HKxVOxm-c?3Ku|i62B&%fB;gt#BUAn6tD`HDgKi9f&hCk%kF4wa({)lEn44! zyUvDiLK}Q+TUu*O3VFc@jmlHkau10Ru>US~O04tX@E6x-a{;QXDgzYh zdtjpBSR2h&_YHI+X!N6XP%K+-OYLXpG!LyR!EK9&8eo*Yn-*Ac^1F*m%7H=!rr;Lq z93a*&*Bx90$2VoAV-4KsoG8bQ_&jb_ap42o|L?9cmUxi9CIc11z@YcUd(Pp79?iaP zv_{_(f)>IX@PL)GA@(4?P$=CFGB|nn+loS=VQM%{yAmom%>{0Z=S4yQG6vBFF3ql~ zOhjJ@ICd{{(BYOuZhs;le_;QHHxT~Dm%~|HrF0s{tvWMeYau^7i#=93h;4B?*8rxj zrxwx!Grw{v5Hh+gxfG(C)=t%dHja@e09mV#BTdn6#F1;d6eKQIE60$6C)jqbErQA( zOj8sfXrRngoKt0}Lmko`oaYx(P0)-_Q}^j)IF@m~6hGwW>%()cjA67g!OEAJ6~E}@ zBm*jDmkJHSMAT!=OAr5|VVa3=hlrD@a22yK7#OqWMEzilI%sIz(ec=ChkknzrQlj-9O&?Nq+?xpSSsjp}0Uasy5K+~-Jp?5-5 zvlgWR9{0}iSDjJMAxKTnT7}Qjv!vZKb@MDe1EM3m?gre~jnx1`0p|4W)v3;A8TXBH zS%4geu1|ul^~ISwm?|N&qxCTvO<)c=r-V5z6v>PtSwxX+5=D%pvyoK@zed>tm^K^G zc2vYSJcPDtLPnq#>U4}YggphcA-60(wTL!j5@op+0wJ#mflRPPSxgYZY#`YplI$Au zuhClKvYF}@i;zisZD0{9YZd{C({QSg8;$cukfPnT8x38Ev}O1V>AF{d%qLkY9;Y0( zhQVrN?2o<1vaT`2&f~dmQSq8q=h1{jH@l!*SY7BCWOb7zifI#2s3{H1P~qxC6`3xy zvyMY=OHq8OAz7;>PPF>vgFN8OPa6**~HDsStU zL&b?H)i0#+HO2~f`tpe>nOj|MSF;h$}$u-^tYQCd9Ua$*N0DGd*3! z+rh3pMc>feyj-FY%Rn49(FB$;1`;SMRsjBqc^L8LSErhJO%4jtX{mtr=*My_KjR_}o##No2 zaI|_26<+7q8Bz?u^D$67R`%rh-MzRD97Co-?0R*o^Rb8ync=cd!DUG}`-ZdYkQ|4{ z(|T*!5ybHj29}YsNFo;|g|zsKUJw`13x@|qg%4`y!mesc6N^$+{G?Cl(gcS%N+R|V zn;g|TF#D7wKkehQBAHrNgkB*?`Q~z|W|C@psQLUt^Vi6O_xP5R;(SK~z^pVSXv=@FVH)J2A99HS3&Q(E8khr z*Sp@zcS!%hf_HHI<#l>K^lr*YB`lNqWXtH5he_kR_5HLzR-UJWc)fmZ{|Rp8aYaus+ruq4{~w6L6xu-x9*5gp^i zoWcTZ#w@-@VqGaRF@j92f>GKuAr)D!epuJaFsf1Y^t(A#;Z?;a=7(<%)gLD^J4BB@OWOvh->9>36Wv+llO635dn*ZKcqBf<1Ie_FTkf+v%AH+ zbHHH~P)}H|y&sN^%0)$n6Mix(>5LO|g}mT)ZllgW!=`Dx<}ZgE{4F57Ed8$b=38^+9S!eO{0VFecS)4zDR%;mOm=E z63z&Uzc>JtcApS-t5X>SzH0hE3Y}!B$n)*mm1N5!CXGtE1|_TcyT9APt2ZuSEaICT zAio5s#h9MV;`m{n2tAdaWf7Ud+L~(Q1B5Z{dUJoCpbI8L_SdL4Pcrp#@;u=#z7x(> zeVkjpA}kXGc-(;bINPfY8I*J9mk3L~Fzu-nonYuFR~U@JG~Cqeg0!D&_@ylHs@hH~ z9w8Do?*#R{-iwm6?W*$XYMoHPbM;y-0*|-rOMDW`Yy zgL|*npLrU6mpC}?`Sm7g=n?T)>zrC-?evkt>UdBs6TFNWd_gv3327P=c*e0S7l6BB zhb&fFzNJ&e?&u&5S>Eowexd5{md72*&M_!QXsWoa;yB)Zm@L3`^?;4FK%%v= zHsD9zZVaCOT6WsfteqSAo83%Seelybnp!custBYi4y^H#Ll3g*=Tv554{irvP;f@Y zvC4m_hve*kFBB?gl+ik~GYVlf!V5^%R(PRy;AXdrM+IjTpKZ=@CSsi*JEN#j&M4+e zGw*${f@X9^rQFhXDZPqmu8kRpIdzeflXfJ52eBRTL$qY2q(lm zQW@dL0XKWdJ{Jhpr1_aA%TviHzjjWTs+lprn+l}L;9x?UTLKETI6ByjtUP#`w2iJI zcb7N0OSj}Rj*o#z#5)2HLVefZK+F3(r$@_#j=W5?1X>eliB`G_TEdpJH3;Ntq2#R* zC2I_9P!f0QB>o8#cm!fMSSnVv93`*bnwJeq-XYXP>5G_oL|C^jxPEMV@D2zeC#gs0yqTNQ{e?Pvv=QBk}E{Gb8bB0g2zV42faXXGdZ- zcL$GZMB;jL_nDB`wg^b#+NAj8{P5k~TEafe(rww^yvnUh(uR#o7zYUfpk)05R6*9~ zBrUJePH?16QS#x=^9T|x(Z0z%R;mI zyccscpQjX%$C^@ovJx8HYG<~aUeChRh1&C-c*%x(MZ7R4&?;F%^Sp+`I&@po8Wi%%d!Fu;EC^VmHVW9{| zBBHA*Nftd5y7YZGT$4RYe5t*7Co+DC$A)l8iQI_ZZ03{ez7?($1PoOuHkcF#3x z1P-Uo5bxm*wc>qisg{WRdC4PrV6MN_4b`5E)<{>dXe7zDpZ*`L^XthjERbs|olNsG z{+p6gNf67*{}>`2*BYa)!avpRYUwka2zJN`A~8%jp*!Ay)H(K5`ay{>M8~*1yZx$D z;}6Jsl%i-lmm{ALcJBrb=o9u2_!DrwI{F7q8;9yoP(%0xhp<0E{3kM1Ah&CfnrMT8tQ3pBOOm~fp)2aUY1NUzz zo@vF`^{dbQ*zU`qF}56KWWf1(0`%R;z1&`x>teH zn#?64wvhiM5?jlHwyye9Wq6sY{!o{Tv=Q;o)3kdpgq7bdGVYB1r!xxxm^R>DJvm!= zi^Ukjbaq*)GZunZLMd&mTyP{1+AYe2trWBpOVHnt1v^cyDU8mhpwJ` z3G)0XoY_WG@I0a~AfnMQW>`7P?wEc52YC`0;;jNqgsVfNG;GmI7_>t?mKc?=jcKYb ztk%;-?Y6!S>zF1$s8Au=FD)_rh4xU_CF%*qKb=(n_1Um(x1ozs_26g1qZS&*{jlFs zeS~+_w+apaEDMMC$dVgY8hV4}l4W*8&Q%yRcaMId^ahS1NX8LvnH7U{MT}i4Zdj zTh*`Imi#-OA?or8^W;x%K;BeI3=$~h;nXj2E%otco+C`~m&8r{MO0vK6fCus@Yso9 z=+t-kd@l8xHg9p8GNb&@JV0NK$$)Be51iii>(yrAxn>src7S~ATqjD3g#|g=-u@>P zk~KLRl3SaOd%cWf;<6+Q|Mk)iH$8v^f%%)bSwfcOpnv02yAtU$=-yq9{&<BrQq)Kvk#%{@%7DCMls^`G*E)vwQmk`)UPJUo#lstwo+GdA5&LF#$+=p97zsW z)F6}b9oXNA`Pe>5u=N90z1SZ9$UlGrA!31H#x#htPAR|66a zhW%zT90Yp8o^`}Kl0nMbNSGo8{$)*_C~q}_>Q?U+K~ZV57r9MQ>fw0qy3*mhjUmd- zYwifT6-CiaDOa+m%1Xn!Y75P2XsR?#v7gZ@T5H!h3R^={wC~v?`%>7?NJDHOZEqV{ zb?X|oMD{cCH|}S|&f415iq^9;>}6$hYTUZUJ}E^mct4}HCT|m-E`lO*f{DWB1FH2FXlw z1W>y$6?BWY<3-()ypR%J`rEP*0UKHq?lZHL%;juCa@edC5QBRbm3s>765|0IPNbu0 z%k@#H&k^KO3GY}{WxA)eDBVLzQJ$w4ED}M!kwgy((pHe%k?4aMGq@JSzBK@hY`e7Y zJg}Kg@2KdsV_L$bOOGDU8AAY6uHFaPJH-MVWN*Kc>>d0Q2;1Ib zE~?_|CzR$LWRr7XxHUhSd!WOExU{3KXEpzTtsPmlPx_NGQ&+DEMlX7H7?B%6J#!-P zOxdY{h!(l5+T-FJoe>2MP#HZ$BYkN6Oe^(1VuVhGp5)bk-4Dl{ID>dl+!xsZdRg_1 z-fwK1MYHNu9_^yBqmR2~p0-R|^z}*limQ-lH|8S@7j`J~zCe8-H&zHp9pM9@R{Deq zv%U>k%ycm86UxfQjzGsDI==P_X!!Cy`2^xvwN|XN$ zmyx}PA_`O~jDWsk1T-Zc&{cK#w{}>Vl(m!TLZ4GF9d}XcV9?^lDB>q1e5MMvEpZk3 zlO>7tr6_{2ubER)r^U}07CZ-F4`mVUloLrX(FfwcAnW)`Xbw}|uZpsCteenP-(^xX z>FaZ`VNMHh!<;&hRmaDlXHJAGaC3^Lsy-1adA_OSRBW7&(03)Ji|Q<_xdn3gduU5s zHME!10$H2KLnC!FpACu+uZ3{Kih>W%THMPeA~k14!6)50O*7lp)JX9$@XEC=3`ecCOr$p0jHBs7S)D)8i5m2oqCJVdRc{cnetDtYAvmXOR z7IukHlb~&X+iIP2&P5DK_g)X4qn_`o*1g5LaOmyASV#XqrK4XnX?~Ga1?*!y@!Wy= zIy4AdCUOk$q*08pkhL8~zn)`AiRpyHf~=WVC%pTj(pSv}k+9dXl0Gt|saBeD*>oRu7lH94ZC3k?64H7 znN`yKhO7c8NKJ;{jXQ&}#`}GP?MK3#)E+v~7V?s6ekYK{oT$WpOr)K#V0kjUGgu*z zsW3uh_Xa&qF_-lk2tIv3=hR+MF$qvdSQtlHct~%V!6`-^QjD^J4L&%>$ILz!sx3)U z{H2V%LEO64#u>2#u`#NGOYy1i5_*>9+j-u(&UP9;AEi_vt`4VA93a1B5~U})z-#MB z&!102yg_ucTGo~=A+BW@d3>h;0=N^Jt3K7<8r3ZWOqJXKUS``faWN86|nq&0%#3jkT7LTq|vA-xKPUQSJ6x@6O;?yUx( zthbQ9&}#=LM$>A)diWru^$OXvew7oZ$C+aTPl%Fopcv8TMvZYch$K+hb`ojpajC~w z*YZeInXafop&12fbijH8633C{vL(X0k-2NZBUt%<{XIw?gSO-$$OfO9?YA|r!51rCU0l0se>+UaA&iGwQr!Su07! z@Xo1wh>R(IrNfK^>IKS> zOfAk)<1@${2tllOqe9W4Y}0fQtxgx3c9@;?Fh{{Ajt5cZ0p8`-bEMobln5lpsoGdJ z+8{rqK!imh`{al}F-^7sf+0)>OGy{v{i>O$T}Zo1r6ff9;@ z0)nAI_Trb^bGeG|Wyuu;r;6Rsh>U_Wj3UwTs%`-eE#u#ecD5Avi&rwMlC^-gu%f;_ zHNM@0K>g4!H+pxc+Q)-Ktq1z%HoCAD2#*M3(RnuecrR4SmLwt^sDI(Kv@z+8TnsyC z4OjNWPHs|&#+}?sPwn72Whv39yoo#|7`Qdx=W4h* zL_FIL>}L_T_ylZ1junI{VyQ@&b`{E#dIzA9?OB*C+Y?bj+uk@e*in2r9fetwx~&W) zpPmD@n!V*6@S1aoPgiN?Ky2o)t~BH5&jV_vnr^jW>^n;nViu^|z@B9Bx`HxCbOj9+ z#3}2;3;N9_tP{Gj75TWXFd>|-9kgfCDR0f5)w6RricDABHqYxCS^qQe(8s9vB+sff z+maV`#U;#NECB315$FNHrtFPC2ic)i03ZN?QnW^EFT)$HMTZT*E*%Q43F)mteKMJ^ zV}_Kan|k*$Kbr69h{gM|Q6R=MgCk;;rP#gMXq`d_7ta$lmr!*c**}|uuFM`{c-j`S zU&9nDI8QMcYI{FP;EucVGG_#$4=3O-Mjx(iXg?wx0V)S{1={diW5$cbUPxm9#kGj{X=BmQTtMi1nB^>!iH;uv^ z#Pf|!07$hG{*q9_^s!4%lQqpWYO=gKf}@_*L7j`dqX|B#P9RdA&~;{8qC<4_dr4QB zTLQhFq=SD)z%FwO%|4xvGI}67l;}Op_I8A90>3?&r}7CA;z<(qA5-neBySdfk0P8F zU(>n}Lgnme)c2FLuixit5Dk4gB5-*jn39iP`N?eT?d!AFlCDnYR1h2^-tAum+eopv zRh*qW8yGPF&hysmRbT6OpS7^~5(Y2r0o=H31>`HObfh96ZvjOwRe4xF5ZgJLLI`2{ z->~pl@eUeRlJO~k@>(u%4+Zj2@ukWjjuxYQ;_mzvTo8jm zt2fe^9D~|v?w($;qxci=Rb-EeTdLy>62p|HsW9w0=~u_?th-tQNX9aJ6CQLxa5L1& z<(8d7jcT`d;-Qd8XTY+Hzzgc~iR&AFUn{jl)JF;U8+E^PTE@%!_` z#$o*XN%h{(p3XbGrFwyPqz^@sUg@>mQoZL`{r20JsSOy=;FiUof|NF70X1i^BKlcM zJ483bt_)tfuebBHE$c8I^Rh)ic-o+VK$ZY0Mgai+kKMD2Nn%4vj}0KKP}LFq=0{)} zaWWJR@cuL)yyV4@ODc7n$Us%Hn21zOt{8iLQeP*{^8{~mN@ti2nQ1T4N#vP)ItWmb zohVBPdbI{@xKS!KhfA|SQu>Aw`|8*qb3LfAMA*cxMJx5ZVJ{5Nuj4n&pLS)jvXF=B z`_F28L2C@Ae=q^mD!z`ejmd+ewsX9tfp+lIXUfyUW){*eu=G?y*lVs|Al?9FRgA?b~K^qOE$`jqhN}pGVCs9~J$Gt51$@JC9+XYwDcj7g1Lm_4O zS3FdY`z^^MS`Wmqv*Hhiwz@BY)~vgxabOLl>(t?aU`!k0^X}Uo+l@nEB=iF|Nr35? z8LA#j2W|NbI!YJ&36a~9fV^(<@7WrQVM8timD-%2$gYK^9(!Okxc1)r?tw)5Flp7$Jysa2rU!Jb{&sUYy4gnkbILBKi0>BLf_w|v<6x>LDBxU7D9=3VysxH=B5!m&2;e0Y# z_|r?$nL%@ed$Nvw*ge)OOBQSD%tQ;{cPB5_eOvKFHDD1KBdMc zg3%i7-R{dg;e=v}aUMWbYCa0D)DQ<>D;`jmC`T2=F;`2)7T3CA{0ws0KSUSRevjuXl zQyslN0y(ay~RGt0<0oA>e%f8(^SdnnfDSyU2YZX3A&yse})XlT>47>{|e*j#a z@(1zMeN)PccHht_l=3I2$ zUnyNd&?2y-q(>-ul+sYiJ6Nq(7l}2Qjm<6_lWb)K_+q_s$&y~EG>x*cl=%U)A*af? zT{j48qxm=;AypIIHkrUk%OSlS4eN|b(;9-vT|*$XgnA4Z)c>aA?gUoF$&M3l?z~)@ zHHJe)DJw+(Cb$#{wOjRMtm~8rS#Cm(DtBUW*i1(QI=9K06!y>tqs7D`G_Cb^NOPbJGf(?{uHNvpVaL&BnZ>SAM|>Gst1^6k)L z*PZW{=XmFKFZ6z(-p7dQZkpaeql=b51DR7Ev-0J~Tiy%N*&l(4;FB}I|x$4GJ- ziXzChrYMy(MIpA(Y8EJ}NmDd#*e!l@ zidM3$RTGtZHYTc8MQ0}}3m@7|iNi)l0b~z}AQCggFQ93vYajFf%ovWAghD2S7x_U0!uxA6{I>YcZbR$EV~@WZ0$$E zjL+W}Cd$28GH_d|i92d(y@eb3wkhGVU zj{F%K)?Kq~>DS@Liya-H!bs2+1+zVQ8B#rju=QHWQmx0W^`XnDfhBUOEp@J2;9l*z z4(mqL@k4Y~A3Vft9+e)WbDjxR=kK_?PiOiLcupLk#cs4*7PrX|_VHJ5)JOH^q1UQX zLqZV_#Ljrj)eU3In2RQ|WC@#?>3`iEv88=If)t=3XRtHi(C+~(N#R$p&bt1M^U zFk~>jlP|U;&&B}#+4QtPyGQJ{aui85Pb#biVvtV_T&RYw1PzwuCup#JYuYSU-mh)} zHMQ=FP{)Fa_C%kx3j1(6kkHCLVT7UIMEgI7Y|26j88LnXZAkl3RYOS2?u>!*sL9bAp~X$XhVighsh$4lNe>i zi?xH#Fc>L@tN8Sk=^8L&FJxVTIT%c%?51FRW-$mxDCG7`V5a6W<&hefRStX9@hqK^ zKzO+~&A=wq+K8Z2E&?Gx6Fybt@lGbKEZ_9?Kv_ps+E@ zfdWq1VM`zRpi^vi?N03MUVDBK1lb87302xY%cwH|iuGR}Oa@;`L&Q=r_=Rx`EOpjD zL1X>c^(+DyzAsVDuDg zc(ytdr4s6St*v|#SieIxy*hm(@ZiJk3dO%c6D`0NAD%|&RlK4sW7rhb$Btl_suP_4 z8wsBvhEJ@mvTzDyC$y(kR~rhR_PTIq2(<=Ks>9rz9Zn3O?$NCxom@TouF#{~LyvAz zkKW`SvC^NWN9y_=LWAm`6C?2RgE)udSrWhB;$+F%+sjGnR1O#WlF2_~EYX zN8qhHSc5PW=Z&-;aF{I`EC4KB>L4?wC))$FycwDr$pOFJC2YKNd8_>`p$mi zO|)lHXNL6!` zD1XAqi|>0Q&gQFlwS6ZL%2@Wr7pd~KZK6|^Fe#BWT+eW46{ff~F$o(1wdh_TdoS0* z*YHoEM-bFyLPV_PJZzL#;A_grm|cWtl1D3qHRf* z)F4n1Ay zMGT2u=p357bZp0Pi_H=;Ud!slKVE2+2dE~GooIW92T@xDl+|X-^C5HDGHpkFlrA^? z>VS;JaMi=XxW)vB@oTPECYG?GUdxl5k(1K`sJmXL*KP2ZQFZXBY(#W5fuj=tWqMcd#;?F^T1rAvBMDE(7 zdxUoOmf4NJ#I-u4FS#xeQ5PiFN8|UKvO}B=0K6h6eJf_;VBPD9lLopZtpVSv|BVv1 zo4uUgoggxkePNoerbbG9M^L)x99p>9vV9Q!Ne39!~_%Ot#dyj?>4fCe#DMOvs1P8Ygy0hDLn4)gLtbj0#D(N5{ z&pa$x@-jJS2{h$wTA}~~W#!6R#VBxl6pvUR;Mn<&fF*V5Fj=LJ2&iSk{m~0JB*eIF zgo`tLGSp)WzieWQOqY{BfkUAsGCc*@J)cy65?XpBwzQX)4(J}Q&O@;!=|<93VoUpj z49{>L4fSaC^OOhKr^cu^8l$xI*|HEZsxgcQK4v@C>MKcDjmd!$R%0#087F(XvAC$% zfVdXxjOP%MM^31ich|jRDY}p1{t2VDsuO=Jd}i^S>RMR$T$(2-4K;>cGI>OQuASr)8e&y*8ryu zxjAg>=!{po>bH~Psrh02@!$O8iD*|_O~&Ocs37XHBx|~XTTnj{b#sZj(PUCHh3%s( z%CdkKQ7}x1R#i_CCYSc>5J@7Xpne_12SFO}@KluqH53xCBrLlOkgKej4K zjp&P!6Q((qZdIH5a0s0NG~JdwuA7s6#U-f^hx%c$nR%rG0qB$4SgW-SvE!xw?8Q9X zD=jXn9s3AMnq8FqW})60GuZA-33|PEYAo4P$k3)82o>B30SNqH`_Mu&1=A3Y5wI55 z8NoE-eDh3uVageJdRlE6j|*{kIK%pdLg60&k(YY9{B$3!2?4yr|MQs(D6uI!syMu? zdM3gTt^ll`?K6;#JU*t!adgkchnuovh!VU!9^nzbdA|O}Q&D`4+Am9As2>7VD*A|P zf3d0PWM5<$0c+tSK$ZapxZ#0xJr4=8piFhZ;12aX5+7<92XH4oiuS4%<&a`zpHPEb z53#$BMT@>Xsb*EjUozECsx03<0gHJ;_prUkbp;;|>w6~O-yi1tpu;`t?^J{$eoWe%C4I1Rt7a<&pHGc!) z$e^=i8`AIFT(XClxY<`q63=wCBA?~Q;<$E zDFcZJ5uS3@pLW$xE8K2&HVhNMu&Jg^bAQhOpAw9*h8b4a10$@S7O_GJ;FpN?VkSV4 z#kSV2;2)@f8^e$C`DuGNV=%=$8~*B9k+K3!W)8B8H;-h2tFQygA>y49Cgt2~%j1!yy$tPel(bD~k9i+zI#&ssN-X zz<7lUKPt?BQnhd;{YV_m5!H3BAoL_zJZ39@$dA!zu)Hlvf*?)9Z8MT!FZE*YVFjf2YEUSg_M z@&v5^lXWNq(!#OE5|hxPCc0ijboS}mi6G!T;clEC zr|8L^j8SBa&{QfAMK>gJd};d-=z@^cyo=z@sS1In-*VYgvLSd2t2#f8!dSR-|k zL|37$D&0fvkLu=dto=Y!`{Sye?KL2)YM=ES8t#W-&0{)xyvrmpb9xxD>&Y&kG6RuY z93f7D5=SUOZBKMtl3`FIVRj zPFvN$OvoixAySil%_>4n5LSku;n1t@0(mf4YFL*-p&P_!u|nkT1|Q#y&dsLv=_N>4Zh(mS_$N>5*M6&&y0tqF8VlZ&e0A!}A%>Y7faR&&^} zPzF?aMpd&MJ{_Als_OuJRHesarAM1epHt6d*AN_ymZ}ssX?Wr*mhUZSUV>+>2lQL; zWqv|zQQHU|x(G%86#X@|7nk@})e!^&)2As$AGW)IO@LE}Bk%c@dp z5{>Scyix?Q`GBMk7&7wTGU)^AVBnP!f9bR3lDNDAK@t}UpR(*1s$6QSJhe=uv@_s@ ziw1$_q+~BxiMD7>u4`dY5B=Ta{)R91s&bA?WmcE{*Gu}2{|O-VvY3otSW+1Hf7JKJwl)7^ zSAmP5ItzIl#-iXcf~RalgUW-uA*hZRDI-Z8(b}B^l6r#t9TR%uJMXO?Xf+iyOKF|a zh!FM1+GZF03xM=yxj@WQR#P6uQ>;6p@5YLv_E=Xm#KaIVXH+|)t@R1cGWzR!H3tdj zt@G$bLN!O8Fb~QiD(g>M=iDF{VlPdEyAp5^Y_N_tLf!8o)L9OKwMq6-tfGua+>NE4 zXNBg3)oBUQ{wi#*O*9&$E0zwGLbR~|YMbW4O`(9RsajG87FO3mU90M}s40-39$OqM z>7)|WLhDS!?e2Qbs6{<-8Y)24ICZsEPXV15vXlDh*6IiN4NgIRQO%D{Cc z;Mwa{29>)n;8Q0X?qqqYrPv@_J|qM}>%|%_A(nJdXD&C;>#X`6rdA7@2-6E4 zv+sqD3D5#qA-_k!kC(bfB+19AW`I)Y#{<+m?VF$r0?x{TI=bMSFwii7-U~z&PEKVGyYD*B9Dqw4kmVi~==u8`1O0@U@dh`x7ioZ4%)maIp&w(CmbP%NA9k zna8@u#;51Rr3qNI4>l}~l3g2_d{+CWBrRH%lxLG+1j}kD3}ai&a>{Vj#*?)W(|7AuWgU(?$d5`f+UO zlvdrW(q{0D44t8pKBVN18Ny5?@atq_xvjZys9Uh3On9!TAz2v%wFz9;rh%l6i=swc zAugz;7vOzkB72CQM`ZWJj!109(MnY&f&Gg~^@lAXnhkoA(kUSZZkfw1}4sVhw^ek717kk{)=dr-7Tuo=#MAWAGKQ9mJq~fkS*cNBaqQRdr(&x)gFC; z3ooMgp2no`kgM}bE-Jn?e0EFt>Wy63toA0iR)33YFM|Dcdg8#cRQkis3jWcOrhEGY zy?SF69Mg*IDFIClnQMT+FdJ7RQ_YiJLf`xd9D-DUdn|A2R zkRuE<$HVHc6S*Dwv$=6jW1FE<2>V3liHB*=k(VK3U?Itl6AZ7D_QL@u0L)vYd}z1e zMG!nPL81fe3f)cVRL`_3S1rjj#F8@LREw(?8dpd0fdcl}`MzpN%oMRY#}$Fh*ik9{ zidJbJG-Y4`+jm0T_hC1`EWN>5e43XmtvE5ak7f=c2{ch)h?rfr8nD<4O+(~RM-Rld z>jxIx;}6=9XCp+*(8^4^6|-aW7vu?Eu3!FAYNUb>9Kxws9K{|eye$uLZQ(PL`SB?B z93VirrGr1jeGq1XN0?K6Crfz&5DTZ}E0(_$??;f0f$R>vq1e?UPLE?lil}M*8P`Qdfw9ZBE0^tbh;pa*%)KO~tSt%! zmo1WaQoq*b)J9SYE_P#Z{CX8Z3OsMVewhwmI#PRjVI#&WF2X>$+yRXpzBe^7!rhID zmQwFK^6nH|@lcZT)s)`fQGBOP{hV?1ib+nC2ZI#nbX^y#5rABLpkGIWg$ad7A)n#D zZW70Y050SX^vdd*SEop}z*IX+Sgx47lD$2p_ZexYun0ZVwxXYw20*66BhxMVuum}@#=H>fk*EbH9&kAG9Q3<0dpJq9MiaEgD62MJBF?0I%hjdX0^B_i7cyrf{A)9GY5q@D#P{|;uXZO zui`zbVbmubf-!Thq!Y!qL5u9P^Ekv+ z61oUXvmKXl%jbNLF*lQcILf%UmKMSRZ{8Ac$@QmyqKq<7!-O(kI|5Mj_ZU1IWqLNcZC^j0ZBhQMp8Py3`x6_EQj^7lP0Yj#IxXuhLPp(-7W`Hv^158B`PJYIf<_0a(Q?Jy z*pD^QWyFTM?p9xI%A6?23SXCN^}$BRiE`G9#E@!x=j04XhYB+w)DQh@&FHH2)#Y04 z+H~1&cZeZncu>-00|B;Zw^^gZ3Zez(88Hq_ne5n(1PVhlF**wWXgV4mECZ8`Vfc^w zg!y)T`^1VOC*805WXbs}*Jr`L#g$hS6)fLl-e70ynTl$4l=uH}O@LU!K2~S*kGjhq z7^TMi<7stgx*{yc>qN20r!jUS5=gyXNX0HbXOzC0Z!93OQ;^zLfJ?mRt2MX~T_*Z) zIlh}UqTX_t?316^WEd762RBuTR)rU| zGdlzyP>8z1+EcG4UVEged+mvM;FX7mjw%xr!wOWd3toZr%^tD*7}WHj77IOe)Jd$! z>yIna`oqhx_%uOH4uy_OM+|E6qM?57X(8r=!UP_wOM5_^BP=vhte(_@qp9HXB+71x zX%Y&k28A@$%hpwK)mlE|r-5*%jdA;&J=hHrt7A*k)4GDWN7b@on%D>zmrt%BU0eda zgifIEfsBJEHGg3f&G9H@{FMAhY}(P3-Oh~V+jSo&tClWa^e+2aPN=1eiP;jeh1seN zsgtwSNEegy)oe(pXDo&Vq2Sa4f~S#~by4yva)PG*1FOjim?d70oZ#vw9Rpk>BSa!BsFjOuL@;F#LbC3D{9=@;p9(+1y=sQ_9(TSSwrn!P%a_o1Ch-Q{8 zLpC%i3V~ENWlIXVkL06n#^86|-b~PY?GbItKPdg%bS2R=%4jSi)+5b&CM@nU{ZQ4a z7WcF0kyiEM*Q;z*wVIh#4}(MppeC772u?Sd+2)1#M9{j-hPAW~@rur{`N}Q@|C8e+ z*cDdJsCMoHKs+QZ#&TF-pwdm*qkv6sAD;j#q5rwOT%4g}Fp0|q0IUwyr<(FdEa?*@ zm5O3k1#3t8d9Y{a6`pgjt4d*?6SRJQSMsrTL|X6lD$fgjir=wX7_FdziR?p z0!0w99-M(3U`Pm}JyQ}i5IbJt_TV{U>*B6V#eLb2I792B-`vEsayO35n0 zM*sRi_&a%W0e2hebU5m^g$G%F=Q1 zFjIyVW!e9R#gQz%5}5WN&DQE~&dl4~7bCohZ7uPy0Pp*jeH1&cM={#fy`utu`+^t?|*W|HoI}5I5H#X4R6fSd-TCS&pm1Z80(?rol06^9O z;3zi8^!72rL4_9z@WxT*%nOmstSoNDkIW2DWMT8X4rk6a|Ezhr0V7WM=$sLe^tNV< zd*&L>7}+AwgB{cJLvz}T2EU*RVNO!~IClRrC~=N>zp3r#s`}7eN!mVF`zW`{v7KNK zhLhc5sA8~EHw^_3D10vc0R|M@Vdiu+eiU%kyqX*3$oHPJ;!g(Rb*=r^p%U#bgUq)i zcfd1g%}XJ@2<-?sp>gO^3{5Bi?R!4lPO+~W&C%|vj%-tz=DSv>h5ksROvA%kaeTth zc0dKFIdpPKNJ5IDj-(A5lT23~{$MIr^_j)18wAyCG*W)bPHherx%^oK{%z-L%1 z1Rl(EbT^Dgy;m2Jz7bV4)D+5s8-hs6?a&Lr)R18jU~Qkd1SP2)+~vFC$ZX4jfTXR| zS~&G&+r#@S2eyZLshWl1=gLz(ef@&l-9%;2QW^EIf4lgl!J&fFFVmly;(F%UK8Ve$eoytH489+itQyA$%PKu) zhR5v?59fArw9BY;( zuZrafz@4Flmkbqx>xc>gSU7~s3!6{kQ9?8*v_>%H{|E?%b6lq~fneR?eggc$Myxkd>YfGn&T z9fHmgh`WHk*@YYgL-OJ)7@g&qg=Vx)3I7LLL{h~m zQt@s=y-mw?-nTd`*B!(wFu*US84itxogk87Nz9m*GhV)+=9!T2pTLfvBoA8y7|?oF6jYtw@*dlTj3(N(A%^8&SId#9 z#0hzo=-1+qK_F)eI74;5UkcP}mkK_iZ%o zOz3bhxnejCfwe)gIM_$FC6{u!bO&U?rlpy_@`R)LAm{>YE%BN#MKz-vNMMVC>_7xK z17Nz+3MePn9i!*N0c>K?$x?KOyzvXEW(f%&is4un^oDW}k0apu`tTfKXfX_VWR(q` z%y|T2lo|}|pUae>5&r4tjFT+YIi!aiD8b;tO!eRKs)9n-`OH}cm5m+jtJG0~NMWRF zZ(NX$+2okdw8;e^6JR4yvi!5!O#3ud27aBwPaDWh6MfWeU?r%St1BD@9Z?}VoP(31 z1J5v9V%mg4PL=$SnTF(=$pF?Pc*gf-m`n0N_RP zMt)9KrZ=lrM)hc+AszUP;S(aPxQD^tsB|h5y$V(({3RM0vj@JA(p381G!b26bRRBE zAVDRIFa?;28OT?mX>lgl3@YF{)q27~lAhKk6ULe6M>m z$dpWjbFg%pCO;^B7Pnx+$GkT-8#)oG%Uo`X&YOF%chU@C1d6u?g4}BSZz?bu#O_OU z4E>m0-hE8{4!nm!Yf*8}$Zm8K{2V3DG!!T*m0BHm7yR3#5gAdWkT5s1%jRaTJ_}~F zHojqQiohta=4oEeiSu%f1OO&SM5A=h;DAq%8bb%*iz1*Ek&g#gmTOlXT&cN%PZ5By z+T4^(DaT^Pxlv&T=Z!yr6(%<7g(DeitcXp94z%Y5J`Ps*Jp^_T?Eo-3<3?jZK?vE; znPH3KA})ZcGOhlPaVtvr#x3`s$)S>tv~5rRh~y({Fl913Vq8e~s&b7gQ`^jtjN&Ow z3x*}brPhgw>G`LVj>rr{he@YCnW2UfXe)*Q4vK|%e&$a@JDhOfY-*>Wo%spcQDM^# zrd-<20_|WQSV25yUG7DDl1@WB%}}iLY4wOb$M&Of!~v{MJsyB9f-+RpJktddSgq*tHzqH0EZRLrVI+dOjCyVIFk0uF=faIEVHr1E5%0GkU>o9 zhj28l9jms?6AQPGy&oGgI2PlpyW2Xe9hHqC1F+PF4Bs|}jN!G2=GWH#$J*|(YH=WM z8OaCg~bkkeKC?sa4%yAo@-sE>fp@kO%cjK1UX5$ppo3+T=eYm0w@s7?|QKFflgE znKd2N05DWT7|;i0%4bjr1_-hlkP{2U--6nBg!ppRh0TmUZ_aPi3oO=KlJ9xlUBz>2 zd8K;*wvE5yByb+e;)10{c+ed*&i)I&#%m-kkQ7UjcVWuA}Bd!RiIu+faLOU5I zE5eS&)WiIsRvw1{9LM<;?DYyS0Gb>cDw}W&X`gR?%Q+U_P;4qZM#rZAkOPO&Ua#IudFjO5=!U!G{uG0diaN zcWMI%>?y8HaR0G;w&o}GOvRCeG}^ECcNHIouqvf{;%{2dX0JNrCx^yQm;lT!_PU@T zA)k^4=0*uinEWKKCRHXjKP_g5BmfPt^r!eAsG}K&xFXf*L782fRAO_TyTBRh7Ahj8 zm&wl8qpi z{HDDOu{QqB?6evFZW_+csWap!a+ISICZZG=ra6lE>h~S=f`}}g?kfAQ*PO5tL*-dG z;6+Ra&M&fW9)Q4nzoXczKzoIQWhi23nWUFy9;)VBm3z z7ZYzX6o{O5sMB|a8Gub&hpDzGO2di?CnL&&Fr#p(Ca{9&5bD4~~mJT-)+d z177P?z&vcOGtd1N(1%r-|LJNwzi!q`YKUkWeoJd#KYTc)oGO~)61cJ+s5^G3>DjGY ziSP2W+jTsh?}`!MNN>}chLRW8Cjjan;$ytI(?9N%B+*$+nKu^ao#AqaN=OY$u7&T< z^RV2ZJ6e~#eH+j3-I{G0{(Tg;6oe;{#jy(Np2SczXNflOp63P`>|XwhDe-;YLxOS* z5J-oJbz!vDaJ$Kw*ZWpM^yc$$_S=I(3ak6(xt>fm%MB0bY}Xta2C5Sp9kr5c0fvxHs` zl*lOulkx%DENm$YTgCQL&Eky02KFLFlWb#dW!Mvim8PmVIP>y->VL9!6jV|ZQJ5PL zQ8V?Aa^@FCr|O?oAN|#LY$$$nei$FTqWa)Fmf8<4sy=Z40~?CZ%nv`7W?2xsAQsQL z@i7ty^UU-sas~fvTI|KQGFG8|-jgLyL?xn9q%f#D(vtp$b{g^F(J$JLDvD$%yW zR5-4nQ~ZMHM>yKk;gI5I7I!3v^mMFb^8|j#6Aq-Tp8&q>O_N(=5^yPNE^peos&9H^xo_%$m6 z$27Gvb0^DUhpFU%)_vJ!SCj|#E1pS+Sy{&^)gjbDDuCesewe*7AU|uhRtnhYR-_p& zS87Grl6;#~1#LyYSeHu|OIq-&?)4`AL7zt=3f- zsK(W29KBc}(5N?L&%S_D3RZy_k6s1=uS}7-PO`FOBWI9cLB~YB3Au+on9y5^}}!9 z7~ZDC#ex}-tX2F+oF^B`Gsppa1P8pd?|mBo&3b)6qE3b5#M2g)Lb?ywr?!7?ajhQj zo#Pbff)0<?%L#L6~}_SS82TE>1iEeandlgb-Xj@qjLDEHAnCq6bEo9K37djkxb) z*S`9J@{--GK(C=4#VnWSMDD(p$YdfeJ3{j^ThmFC#O}h_e?ZXmpU$CoAlto?22{E_ zAAgFWk3jI_hCd}dPu}HpraIQClgtn%$CuNjwxEFe)wB}7BAayi|4%YA&y4nMyolBcPe`}md|pMHzU)Nhr2h5Pt+ zF22n}l-jI9(ewIHow2yfLiV%TBEyo((K*!MC2VSx6h9}O8~ct(H&sTW5o?~Fu?(~D zW90}xwHi)UN7%(t{OUmUut8K6^{Pj*D0la?<~<~Z9^1r6tl(dnE%~<(s1bGc5%k&h zhg=1V+Lk<~TPS2^Gq&8VnGG7m0_@jgTsZsUb#J^r7_WOI5qMcHeuaD|TKo=c@hdyS zBWts@Vfj0N?atBoS~|MqatNj}Ela>}&m8MlKODUk1@f>bxFY1PcvisbUzR>ia3=GN z)PE<6ljofKJ0#9(L6>LE;rl27Wc!wu4mKQ9=n|t~dz7Ca*Ka<%+*J3Rf6=EaIpC%2 zZ%Mw8OVjZFWi2O5Y^^w#rET#%^yI!1M)a#^*e3By{pE|6zTTUSHi%uqgs4OAV?EuC z_g24`GFDiAbKcN8{l-``tC4XagSU+G=u|pdBebnup~B$tZpi`XT3B~jv_W=I{V}%H zq@1ZP7XM{&U_IEDyqg85oVmL!?piEt{J@5x>HR{^n!l#_wHekrnpz!(I7gjr)3H#? zJ5sKtoTT6}hnnIIa^zqz&v>15rmnF>Uie zqM6m6t`o-|VE>i|Z%aMV(RAJ)9m9r0G(hpmff{};8x0K5_TW~B*Ff-MpF4FP%NEH3 zU<|E}+a|=uglfLpP_A7l*AQy3zFfCZJmsN1pDEf5M4W)%>P;A}kzZ)yjuEVgxRLVQ zAkm%|E+G20dINP+7|HV|MC zq^4h!U%0K`3bBXYR@>^#HHtW-vkN;aw#cC4FirF!)Lana65KtVdV9@ z2X);iFN~QW;P*ip-RfTzzhac+7y%vIb=m=&6p&acunz>0g`;0R)Ku6ZEI1GqM+=<2 zBIH^sdPo&PuWpUR0rFx`kCr&0GUya{>RbD`NOv4LMW2#rh5pw#0 zyhf)Tp*a(L-bnVm;01SomaBQmfzJ?j1r|QN{J~Rtz*6`mR|R@;Zi0Uw)^8e9m^`;y zCI3v15Y&#xSC7!u=X4MII;QJ}D!G1J@~7NZrC8Np)Uzu9)R4%hYcepeMgsq$wgqIf3me z?v!TQ zoD5e*$2L+oqzdFG7M+c690Ah0y{+GF?&e+G)1Q z;(WaTjk?ZIk4-#Qwo7J?1qBG8pXEVG!^O*-;cAn#&ue6HQ6=N@#sq2a!RlSGBoI}p zlYt#5F;Bg8Ts9mtT>qki;7s-RM3!m!q`Sq%)Ey1WYDtSOFvSTYNw3~Ts@(WL_vqVg z2>jVK^$v}bSi&Uxg$;0sJOHV)C6SX?Q-LYJ__$VDuiqNLt+rqCmF;SST zG*a$#7W)T`B6o~32@#sn+po;-jPG^0JD5hP_hDAmek39hKyQMz1)bR#*fD#M1lt6D zj)l3L-nIY9$dW`;L@!A@9Yt#(oP!RC%H%=49#d0aPzIK4a%8v6Mf7HNYyM^)>lD?# z{SkDJMU*d!nMF6n7mShazE<|Z%ccys6KzfAcbmj}WD%qqUbB^e(>>_`!O%kW|uP*e6 zK-TNAy7iT?W%-DXs_th+@RrW$^i}Hl)nQ1_X-FosV{u5&N`MGsl6b#qJf=+=lWa{4 z>!M~@FK8GH>x8Zh>$t8AtK?t=H7(2E#IP{+F)ZZ!*U|9GVd1p`7RVTBwF$qW0yB_D z9?2AGUtNkLuTn-HC|_ra)<3}xoN@fJ*%-10U#Ld|m4WaOm}Cr;5w$NfXYrx+NYr$p zyGj?Z1!=eL%*~I z1f#B)aIK^IROU*Q!Z4!a{uIMyGopNzPc6<|zHH{u2|aV@gr2d>x9Sj7L>hoUF(OW^ ziX%E*-RjmpI1RdM=+wo59mj)ajFpD=wr6^3PX1?2;zZ(AFd(CdYun}=h7!l*k+8YrwSVemyqQ#>Z zR1vbcO3&!ZtaHd#zg*+pYR5A%JW8SkjZz@HB1|u>KJ^8n`OY6l^Q9i- zvS_|^)oqD@>^Sr3{f68>&%HM$a{nCn-h}22H>`qZD+-*#zI>p>8Vvj}0J4aBi{cny z@dfl9%vF@bvPOUi+oTvfOVJrhNJ^wDTJ4Steu$X{7R#Q1DBb5-0S}idz^u2TVHThl zVXts|lQ66StVqGw+wjF!6l9H9!2$5P>R>d6yDOs>-NS z78ILLP%$u%{L$JgvwP$YzcPC(7wo}HiYpU;(iPXXj6{6R`5W?8@(h;{vds_YA%Cr^ zpQd{I4rWG!+HXxvy$t%$8sg1}U}(9|*2wN$910u62KH!A(=BCE7}NqJ!4%OHBWsdp zOl6Q30TIa*PE&A1Tb|IFIzs|CcaLyXX!@{tXBak*5fojZ z`dP;?VRrhGRB(l4nn4FlGG>61*8G@u2;2#i%uacXL@cmsGVGV6rBhl4DvPa+c>_T? z1S&@Zs{m9PLIk%79PPJKUAiUtbmETa{0fZw%2oe>1w?6{CwngRKo%6`H-ARG)Y`O# zU5B|I5*sQ*hNU6FnyBCMlxPR+En$X=7p+UuCh`O7Ow2uh#TDhzqzi4RZ|bh#6DHH= z&((avt-0+(nuWsSnG)mblsALrU34E>wE3%I_lN?3#XLWjkB^EXg^VP(pf|IbFvQR#NP>IK>30e6K2`PmKR)U zXCUd+WgHnlcjqDDva30!3CEM_&tgndHfcNMSSvDF)u(7x32tch^-7=NT0Ku0mnI|C zuEonyyYz@OsC?CC@M~yJ? z;mh)#)WHJh16q_rqTrQ$Wci@iNZmNWUg4!bA$ER4^`*8om?N=uP$w|xQ0^4>%1@&E zliW}AuoAwHG$>7iHoWqYfC#`Rh6wCb@VD_3&m*uHUyJjv_xMPJH`lA?nc(Y@TZ)^O zUP%ebw3NdjH6?6ho04_Olms>v1R}+weEAA(rbN*wshUgt**hfDX|x?j?J-E&M9TH=uEVW|R65W5EGl zA{B{DbAHAjbp;s##*j26paW$Pg4eVj5!@wojcGE_(N((lzqsok?^n#Pn00 zRoxk*T7rhQ@PE*XCe6rvdd}4a31ny;q6r6iLkQYjs{hXKygt+AST2V<9ODIwSsml` zx$bOTWqx@2mB zE_-nwG5!M1$bp@Cb-*H#1zalzMF(utpa-;jxUpRYS5znRNw6J*VY-OZaMk+#^`4-E zx2CM>5aUTaLO+%VF4Y>z-aBAzx~%}P#8|37g|mc)z=~)H{XsYEw6AN>U&}$CJ_#7D zFQ2Jd&FHqNl6MB)I3MPMKt_889=LCHYkKZNbz01pes?9Wu*)%3)sI5##hJdG3xWdy zQ^ER&au0H;Jp@ZokR_iv&~70>hFL4XZw^VqIr7{S3|C?q0$lMXYkXG`_quVcImKu z-l8vZ%$iMfg=U@7+UScY(xHItU8cJZe?Jrco(CW%EE7{^UsOE}6L4#zHrdWYY_73GZiI-R5UN|7oQs$aQ1}ELrf&CAv6cnpisFy|72=r+agWhRqF}dkcA-$83iYK5aqkQDxk8{jB)})QfFfVbC5Ty|eSs(h z!cddo?8cuGoYzGxg%N)@AKH&HLd<5Q&-j=;jq{Qi2`zSVXLHCdLcP+&H3#g%&$%$s zKs~jzL+bdoVsw#Ihj2EQeWypk#YuQ55anV<(UJl;NtkH+F&|v)gL?l<9Ml{4)hPx^ z7l!kG>-<%HNmMU0?$m;a;42R56_r6)fcm8JSJ9wEbIdM^Om_LnjQ%SW50Ym=y{xjR z3asR$6oK7|A`mGBgxRDBB(c@#`;;oTIX_wOzf&qIS)E)qxxpk@w>$gu{$$v(p{2qJCR2$f&t4{*@_#?R7o09a^ohMMrad|CY`n;dt z#n;qb{g51z@|aRhDj|N;)c2MR*{VVgaTZPOQhji;;e$8FA0T`;d|-7>Bk8=ABF9jN z=A{e;UJK~_QO+E9)|I$vNzA@&v~kO;lF%gG!fr%=(>Te@V0tGj%kjEi1i`5|A7X<8 zCk^sQora~clzm&mKltE>HiX-%Ul{287AI&BSYX;M1;jE!({kb9QavZS&jvi(qu3q0 zRfsh!3kL~~pbb=KzsF>#ISUESb$;)1#hb7gI1@QAQtSdBG5$3X0iIrclor!aqj+$I zCwX~Ly^_rUT2UW4AxoLn{MVxNwQ9)o-?ge%HMuPRH55pHz_(gaMEUAZ_eTsrQ!ABDN>4YIw}~&{`Yo{R`0ns{@YHOOhz zO~rveJf&9BDj@=j`b5fg)JmpYZ*v=WF6&}3gLpz210$7u%36!Xs%70gS2Z4-#%#wZ zl9itnt<2~VPd5KPubmm-G&)M1_g%ZSw-D`Nub)-eC?R5aV{J-o`rGmi}_aMV;z+SuopR%4Cuu;DxTR+I$kN zcAEiT9W45#?96rhn)E*8VeO^G+E?W$`nd&)W#)fiF zL1j|zh)C?5Iz%Z+y^|_E*?EWy1`|S_xa^}DVhSIrJxa|~%A+ScYXOs1Q8>6o&r$uu z&(~|!i{{5O-%}e>u{YOt>++`BeYt(?Acl7w6+rc!6-LM4+Qaw4iAaqOd631dJ$#3; zCcR+S)YD)i=VG&}LC<3uEDfk|9>`#m!}vg-?RHo;JGEi$Y*Ys8_QTy!3L8DGh}T#B z{Ewq>DOVJ&qC8lgVTid`5sxJj59Aj{DrxR2#Z;!?< zpbkFzyZ|QJINYW-&iw~E(VP-kcsyHsQJAR#2(|n3(Y#fI-Oj)! z$C<9+K8qUC2Ecmr?+tX$Wfi?-lT0V4@z58L_F*_hON%kJR;*-$p4$Dv`r4ocjmaYi zjh(=@hF76fuN4MDaGpAX^C*{mrG4rP#!`A+%J0J>hJls*qnKf+5;d{U zdC*N9mOA!qmX0|_p}YFWy;?9hT(V;@V;#id{O4YUpj^l%r?a>M>eMVad@dV^$ym=P zbMV!FVl`NF9ll){2OlBw6kV*zyg8d^{HjnLORya7Jj4O-*a_VUxl9m91uNpiDo-ve z(YQ!f0b_~ar3D#)pAZ*ymg|hJE;09%;EZ;)^+jgR>iV!5$);6mie^9fr9o{S zAe-?{Lt)SRv3fI%&f0aci1BRky_>DP_J^wj!(u#*&f`wUWq8dTR3<5#ZCg<2nXNIap|#g)82ZON1PtKS zXk9TfASWKeEu^VNfOq{F)FR*&zuujLKzK7=T9^NbtlU!|)nL;gYv#zJg%71a8AX(K26*!f-fb|1x6}HnjdiGL#E#V3xmdcaLibgnP zOs zHv#a^WqZBo=qDcd_)7}~7vaIGusn^q&7 zBFx%>-*0D9fOocIRe)zzF`=FKW6^J`GYwxe_M`=TO^X1|MSWnp=?lN^kz#9J!utC(|J!`etro*;JACB(U&lFex$b{GO*{&{*t)B|1pt7#+Ms2buI0&$+Qp z=c4^&m1#G*%4Ps{d0tq46Kh{a@b-WsdKNk&6k|Nc0A84kbQ7+T?co9*7g>zLB+5dE z=CJ!}`UF*5Dae3c9RgHDm^nNS4-eKx8FQ#8|J@{L7cYVe}UL%GRfeJ_^y7%ey*e*=YyzQAGJ z$-q;_=b&fZ2Dz4=mAwb6I>8>7qSaL)xuRcYF4%%?c72KF37K~b*V80XelWrcwU_c_ zgePCe6-cjbMY0)`R1*wF63sbAC5dKGt0j@+9wZvcD>mZ_D`7BmMOc^YH%O-91-Hu9 zSfR8DE?#DkDB*;ZKgk>*H!@HvGDg#I9Q}>KV=+xK{~;jW@p%bzVtxn%gTVubg9n20 zVVzcB>R+d9ZkWcX3iE`5GwY9083rEd}efIY@Dk!C10~-({>oN&~LW zv62KUNS-eQFMf?Z1ZH@sclJCN^lC}1>z4aldK}XdY5JK?E6qo?wl6}L5J;h58!}uf ziy`{mZh>(w-A8jsc}RZ=ZdAUWzc%=up1W$3mu06BV6d$2qc#+%gwS* z{2G_D1gd=>p~^y9!*`lcbQ0{yY|0jOW z6l)KGMmh567$jbP4+~;6A;a&{?|X@W=6CQCf}(YODK6d04!D6bkm6y=h%_(honhsN za+j4g5G2M-vojjB4nft+@^Xjey%0d&$+)r9hK$Rmkc5jhLh>H~eP7D)Gs7NbR+{A8 z#3si=%Jj2L&K(z~T)q7E7oQ_j@O>+k-y}OoOCd*C6R4^zLX%8|gd59Ll1@>rNv3LG zSPPP^oDtDvE2E5)r6w%Tj%>qeW2}uCV?~Q~qg7qxnNQ()X;g^YtzM4Ns6B{SV?)JO z{bEU2z8Z0srB+y8_$t_{#uiKU4LC@3qAM}x?^;-1RZG^H@W6GPtAOhT{U(}tOjq{A z30(oM(|QkJo#HCMI;rPGAqyyZ1KWYZpcM2enE*TEs=3=Semh20yIA4>!TmzhZNbZo z5L==bFN3UOJtTv8ilX!hF-DFu2^cPTv3_0cI~t6fP7m}5si?SJ?GV! ze|=Tx$#gc7O+`0YBdNSnlta4PJ?N4C1O=DG+F`>dxo~6z(HZY0(`z;9avy#k{g)!c z;j)gE9ha31#FU0rQa1@%6b-i-E=3X(nqzN({h50*&`V>y&h%9z;3$JN*m3FhQTm`Z zkJ~y&^^G)M>YGF|fqv9CtHiK(^d#CxZNVOcnH?=42Ng~XISqY^KE_id zJ^6x{WF#kn+LmAKP=|N8wbhctJwZR|nAVq9>$E&6xtbXr5?1I!>++ReSrzz!tWDFl z!NO6oUH^p%BB>pX+UpyOO*V)Qt=9%up~Uu2_+wD1nEP7q7_DZWc=|oh4cJM z<`E6kdF@stD3hezB+l9-f*?o@ZBsd`DWvXqRBmDojj~*_dIS!V4?BZhUZh)CHE_{e z15t^7egm7xmvJIrp)SRVFjTu7ix>UqF2gT^Wsnt|i>M9x3Zkn$yi(@yZX8ZyA@L@b z*Yl;e`<%cB1Kl%dw*_t=g2OHy5%@X*59~sND-rGnwSxzJ)`b}V*j|HU=rd!9Cm(V^ z#Gm+3ZL=hh0o@IBdQ|J#z;L!x9s`fGv;wH&W$QR%e~j+S)Sc8!yzU40xz4Ns`E2GMt_G$vQ*2jY9H7eL>lNyKRi-xJ zyuzD$5w#jM=NjQ_mW1AfFKg_yitnXQIBE=WfydY$^)>Snia#io%XV=AW<@P2ys!c) zAU;bZA0ujMPbLtzp|}vpIpf8YTGyc2CP+v-8yJ={5!rn`*2aCG6JOO=$Q1ZU5t$ zpU;tQ^6e;dG6#W|KaRaAp03|B2qEgDJq#Zh0aynH^fqVZWt?PnN3Oqu)y0#=l9^!a z$CRb@a3!Xp?#hLMCYyl4=*JY|aY;eiuAZm>#3Mh2s(Z%zuIVD)^^E;^EJM6^DV(=Y z$OBLc$@aisV$Xwhs68;tFgQ|qb*ghpf97@c+&}46^qIgSDL_}Ha3QLQ1obRNj%hbd zKb2f2G0pWVF?6U(hH?uzv;>%Dd}ZM)sbqvTM_0b`N)|P+C924V_whY;624b4#!+!n4+M5O+VQI(68vxvf;`1R3@S>LdNoDr(VQ{2Q#*>co?EoZ?UV zAFoB+(k;m7ggx4w+xKwpxZUo_{0yc<91FhYe}2sU{9FI?wEIbxF2cO!@dST4&X3)> zG37s_sZ*SwOpmdZN%{r2bU8&4nYb?NJJgnoy0U{Wag}&?M(^qG6+H)>zeXmozx4Ni z%l%*Z`@iA-zx(^E+%It-4ui!@;c=!25i$mrV@ww7L@r8c7>J5AW6+H!pDnI@`xG25 zu+aeLsCw8I3>~)74i=8`W{fw=MCqvt;pz4uHgQ6CY}<|CF&>Ub)o?$;y*Cg6QKxRA zr`o0vyh2+51~c6_6`j6`irjX2QofmPxU+?5;j|zhW-YZK9x6WKe|o6+DgV<$#khWg z*~lhl&_xz8gFXO`#A3Ga)Aq;!4r8Uk#theG;6u}Bt?iQ&Tm?I$`VGvGl*?d-WMkH~ zk8s-KkLw-X{3-4~=|NpG+&k$6hsDNG>Xd-&2w;$bc)+MLA0 zET4}WeNg^1UT-V{i2bloiv#7K(vi4fh400G2v+5kd}t-~B9`4x^aOzD3T)NztN-HxFq zQ;DYQGin)TbIN*vWRCmh8SaJt&Z-}XwdZt=Et==`>%0txLPO5{oI*CTGAm(xMCLuR z83%Wn_1Zw1i3RmgvfoL+EachSIXZ_vrrK*#*IJ8st2=X`BmvuQ45_KB;ha544F)0f z937V#cv@G7IA>4{Q|mOPVJI{T*f9i9Csb%F-!hbN6r+J79E`OhG$1^mgLT2;$b4O5 zzHUoX1`bS^RFWitk3!CG8>CUScpec#TZ!s>DjqXjuL)*wJfGsp;1V2y<3(#eB^pPM z8Q+LDlp#d2fCw!N9P=nc2q}GJ2)X78t-fKH(1mtcQXJH^#zU*GRzg{jF|kd%1qTac z;~&boq|{O186pM8w_p0@4{p%$jnO}OwUd75aCaO2(U~m51s=zt9a4bECkGXB2|_;h zGc$4thBYdXD-EoKSg42{eG&G9fWqOd7Zm+h1Bs)cFSbd=wn~V_McS7Nno8L)ij0O0 zCEs`oZ(?|Akpzmg$i-fnjBT2^$B{cyJ6xlT_#o`hq#m)-xn?OJ zsjN}T$2HDN_|EvI-;xvp4Zvi9N(aP_PJb^&a~}kG(887 z&{$je8<-bZ8y}~l&dhN@gayNs01|}C69=}N)P?|P0ElF0hVDV8nKKkb0rFf{+64=Xx#R#|zOn{BjE5 zjKJ9n6hH~Ej|(ZJUhjTAsp<_j36Zr>8BJb6Id_7xByzdM(99d6?mwj%4gFi`++Z3Z zV9bkJHd(@m-{nU6Mw(inDF9d)E}SQv?n|~NZ*mQ4#=iR@+>l{UAIiO%A_}L==r|;m zSNPqRkm@zK2eNNV1!okP1uzfM8Rv6RN|iXE>XyK!*Z?+k0>2PjY`SVmTK&ZLyAdcV zCWF7dMp9*YqIK~A;q)>EgAB{spv57TgP!l@LPUXEk?kngQVXJG1rYQdS)N!tDciKR z3J{E@lMrV&o3BkuKcOV224bweTk&W%329Ev<{KJjla;aA^x>jk7k=g=gp1A%bbcn6 z-j(_EuJj3eq`XUSM!FnrMs5}5Vxbg-0iytFH`ppY&rI<$GU-tSZIE|Y&&zVbMvWMJ z8Kz-+rJU3^Q3wa$0NCRCi4Fo|3TLG_elZ~ygsS-s&#?K4D+AaG(tN!#XlX~~;~mi< zRKcq^@Jb<@EYcgfutDD>(0wRJ45^xUN}z48iM~=Pg^C);vaL9In8k@&d7G+|y9Fxe zyoc68=gZ@GE2dIaD>j>xjS=Apsc|7z8nDY>Mp_+YI1R)Q`^8)wV%3b;GXRH2?1t52 z)dyR|(~bnI3#GRxP%uJKw>(nPB)f!n!ggW4RZ+>PQ^5QwBUeDM7RWuA_+2;QeAN`8-Ps) zyq}v1c>ZEtSthWJ`l?|n3#JwBl3-reOi-$t9uOU%l;vV9%LPgH2G&|otgH}JSGEDM zead;s?&SlJ!IE;`znsepY|JO<8J&8yd(4JVF<&tvyPe@S35Cp`fsRQKSeU0&1=NrQh_*@C!9wTRGsPkqn`q*sdl6j5cM8U9aiX1h$gifAOwtZoN-FIg@eO%PG34h9ON{BP}4RfI!I5*F`?AHuPS#vL0fga(fOG zfVrhl&*W)|#~A5k6*E*6b6?-`aDHFT{WAvC-{V3fv%63zh64>DO-vo-wx~RzUr@kw z=$FovPP@ce0_5?XR0X+Sc!;YD{hH%8P`kPUEf;m&;u0aN)Z9ad!jJzfE^!06#F^Lb z{6px|@LW{qFL6)km)&3FzA^O6PL{9=;X>4qw7VD70KyXu7A?+51Yq_d^NGX5rYPqy zAVUcI*Bj!Ea35MPq_kcnfR$0g47%{fRm|VcyEA{Em|*^P-tGD8!B?Vjk7@ee#QsS| z0(XdSv?U@wLolJGu|tYBClRNbcn`5`+_?iDVx<{OAa?H4q)~iG6Yh{GJgo!RtsY=e zKiv>u=l0Ws7641L2C%@9!PnMCfc?txV;g9Dr2rdukhTE6T^v7Q$&4P(&2g_?aY0vr znBCbCj_-6lJ$q6aP4Q?Q-&tqNaM-G+7s~G7Xh7F`b6b4#P0VtH9)xyI!o_f2QY2Q` zaRmL4b|eVa&>cI_C_&h=awUwBSX(OVkytn-ZcMgLjO-h?j*z`yjyV2v^?T=9 z%W;Ff^VRp05O?Lv5qHq-omI}&brC*^$P;vgweec$$ZeEo>ST&c1H1)wcjM1_^kC3) z1SfcQ$}^bOT4Fnr#$Tg)9I8ktsWU)UxNePc$7{B3ANVjtMsdfhCDMlTZs)r7Ho*Ax z$V0US##saMF#dlsRn-+wRg6+vlLw)L8H-p!&vk(bO|}Fcy^KXpz;3+Fa!Zo1h`npT5f zZ*u3K|4F84&+4bi?R*mY+!2oMIy+w+zBs$|&c`ERMI4nj21&6tq$VJWx{GdZ}PT&Jn1`~)=?n@m&RsB?%O<=wW zHo16wjgkZ!%?_Me({a1Dszg3rgSQjsXl@klXs(L$h~NBtxXGWwIeM$T!!tW?YE%ti zTLL5t+stXv1Bt@y!li97kc@7R=bgE@v`s)VyxjrGRYImUtCzWI_80wig!c)MjHxvK zXC6p?TtAu6W7`{mFo)ST&0H|NX{mm1xQZv zh2C88*K@kk%`;pj$seOhsqf!qSAt8`1%@-J_s4fQAi2y;2}trDNJe)=Kr*>K1tfGx zK%&Xh7fryyq!uj|jE?o(cUV}3R4{GYcE@+rEBJ*eI;$tj|H9*yRo){xPAjHiP5ADg z^4D>HJ*g{3m@!=ez!N)yvM8J#s)>K1{z>I&oScCI2fQ$PM18EOwZ%MJ7;qH^2sq%hoUL5wd9|!ccJgG>W*)hEyk&9bI#=g zvXV0?8&tT9Ad1A22I)4GfkvGC?pUi3u$AbY5DXBBOd?#SaPnfOn%wPTFaQuhp5uMY zl!2lj^~s*h`5j;~jGpS#$`qk?FiaB*7194Ys0jU~3#ck|Sj=sav4DERPuEt4vdFiz z)XgeXajCahrP*zudC}@C>fBb}FS8j!0Q`*1$0)ji`Rf*iC}oJ&GAfFvkWC0SF+;)mrRM_>V;_H>AJn%HCQiuHm1`}k5U+z7161obZ!K@9oxos z8(WkclmjWsE~?)^jIOS-O0!GaGLL{r$lK;lAV}Bi*efinsckExoa>n?5cYLmPVKHU zbQI)B1`-)s_yOi+kqT)fGY7ts(Y7~y77}mnT{kzYiSi81>f8>w0gBGIzznUlW-n0g4M8f_e&y`ygA7tYe zr8PNhMgt@pbd(W%pHRjgl5U`6?hdye3ftZSdE{361R}X1+9$NKIyP;Ch@}og3%l`)cvPJtP51F>J>l<_Gi2;6!ZJLRhxf6DpUZE`&p2X6z92FTZ%3rIaQ0w7rJ z>>HD8sCBrmfP~bThlsPp;VT;QkSf2QkkzRZ!*o-K;tut4Pv&af zI03QcbJmNcdSY*#wI_@9*t#0dFe(Wb3&}HCT<7Z#=cnsDpXLj&+DMOVuE-!vzGbt{ zDAWN_ZRF05N2{k}6Agu*%GawA(m%FMd=QKw#It@69Jc_U1-MYhf<&k|S!91`n;54I zNjG?|4Fb~5!>wv(_FFwY;nt^#PTGLSKNy>`VfHOh$j)$>|K1AS*yt1bNY?_YKP_L^ zmI4y!orHx()B#R%l=0J&j7Wa=7<8XrE*VH#9Wf2<=1d3`;jDg#KEZj=if#`;IXI-85)A z5{A~lh)+^-q}fhVYP4OoDk1B-pbKKK%ytC>ZY-8taz|aXHPY0j0R=5v%!JO(00bj%r}CzRdmqY3+a{Z(R-rZ zIT`Ox2{xzl@;6YU)7uVJKdH$I4)F*4sH_CMz^P5XA}ROO5kuAu>dNhM=`O{M6@i%E~c1h_H~Q7bEV{Xcimz- zc2rVMTd@8{ML7eH?D2NSUI>b_Er|PQla#|0T7I@}pOLMLYYs%N)8K~5NEdXHRss_6 z%#on&+G5bjyySSzy3~0_Hrhoh7>!7gn=nNGw}e;ma>$Z%%)ALRYUuD=Y=%_Oi&1%i zu~CeIShXESyfK+;B46)1#C8zaMp9KA+1CUKM1I^97h~~#k&s0*MoveFGan=ih{K>g z4kWq->{>U6FMFaLJuE{5MA8dGor6JlO2}G$m3Hc%G2p{+Nu0jzgsgPEu3rF~>zRpV z0zB6rCh~`M` z9LTguM7u3Z)F`oS^Aej+n~uioaIMSbBayYIaMWBwth}S z-0Vt%m78;w#dMh8;Mso%cSPf>*O%RtRD3PR!M4uu?IGEcg4k!2+-saB+KtP3%Qv0E zeHN{fg#zFPi#mkdiPbOi_<`(eO$N%u2Li)9$tfAt2fOYGr};=03?0Uk+7M>Kn3s;k zn~5&%sGCN(BfPpJR{WpXc}PPS_eN#&JL(XQV>oS!#t!QWtSs(u()1O7JU7@lDV8&7 z!KF3F5@0+K3oy3J6lqM*nVs0tk+Ur###}5MYjt8*t=C7gi5f^x0Kri83M3l07V*KmXoCUeW!5_?0M4GF?FuI@AO zCw294C=*Y};Tf~6;D{WTd~NdTNjwKX(C2*soKgbw;214Lj%K536(2NfUCT*L<}Isw z)C-@MKaCG+@TSq69IRMQe2v^X2&zp60?z{4uxcD!()|hF{ZlLG{;6f%*Selimoc)c z>#{xEeAjcRQNk?wUT6OBgBzN>U|5`^0*uoDh;zm4m+Iy$V}Bq!*#sH5gL#e2>0Qdk z-DdV62zR&uT(LA5ga$whN;Vku9!AeaAWz^?Kyv) z))fxS{q6uJU0Y0%d8>kH0EJ!uOH6HeQhU>u zdi;P_?I}!+e{vhC}Ksb-zDS7%p zeSj(+%Y0PtcrbB*OtO0L)BeFJP?J44#RJ1!9pNb~@1(Xq^2+7j70Yw;N)}eS|BXCk88aNm0hO4{k{W_K% zQN!qDoh*pQgcgm8Le=Z*9?LwZ2lAk-qg8x|ewZuAz+;(b`7xBcauCfQ*TsV*k>q;$ zAXJy@f@m(+(Vb!dor;kJJQ5Eko-p>>W#Dv+8JdpK@jqfxE$1^DxN;a-j!nn72{=LR zVtGB}_`x}hXp+q7!<{=oO8L|S#=WuO0XjxgDaM~b!Ia7*sUy-c!asQ4Yjs;a>NpxI zr%&-s*_M|BLMI$iGQO6@&{0sVbfaR52}kJ@^d7)j=SGF4e3b%`;|Ok46bCRV5G6$_ za#)1Ya&Qd&f@mOk6NW8ttmXOEX#eF|(^) zatgxHosohtW~rN&k<1`XY@6*B+Z}vusQSdtdU+6aJNyQq*zMMnT&FI)nWseKN)5>F z!qa1?!DghND-Q-0r!2e4Dh<%>aI)iYrroXTb^R&_CD$`kzYA(y&m5KEFjwngDe6p> z98~E2qKpLO)^lH*p3z8~jZ2m343l2FdOs0{36tB!O4ABIkj>Fwd%fS8osR2G@yHF6 zoLJ^0(l>nOWN%wqd0fJ7LU*O*Sf4m}G^jbAl9~f98*8XP&mvYMCBi8}0 zl^B$7#KxdrEy@vUiS5M>AEhkH*DE2^0QQx7YZ<46xMuL1 z7N&$QZUd(zH&Iy3jfNDU)91xeV>h1B6}$08|9ei?`4p7%^SpjWaDHjET(alUrW+ye z+)YB>^r|55m3Im9K06NNz4HHuJTaN(pe)L|tA&I(--PItSHxVIVH^+Faz1yzQDWG^ z6eVsXsS4#O;~ppH0yAB}+l7-*M-th5so*k{jOPy5i`z470&@o_TP}=}r5lk#EXpUv zEs5jkYWU?J9Yb?jeF5W|EWSmF8B#v$EOi||#4fJBuaB1Tv(~Zi_%;~dpXI=N5#OSv z3<~eVG(Z;YqO$mjdm$Tx9QmxTWhXEUs7qvxl?D(?5{J$yZFS7r`RqUX0)GhoKeYxk#j%ydxdTI+#6baMezxQB!77C12x+?P54a zt-6k8U4CDN@ar~&lUe7rcH{bWG`G4-V$hP;`Y{Ek_}-lJu3G`Ynb_U%=ZX)G)rok- z-82tXRVCIVHAg<8t7Ik7G(KodwLg;9b7wXgV$L)f<_>`vV46#oQ4?j18|QdGlzUK} z7^6)XHKk7TSr%FBu^g+dx8peh*wt^%)m%oG`97D>r6cUqApt#6DtnT2Jdh!iepTz- zg}eyG*zPjEY(kpEk~Ba}H4iQEixNm})2}WPl5kNXEiQ%Hc6WLK8On5e0qJ^ldckfb z*~--JG0>x?puSZ(&*W8pZ}pvhSg|z&dgKQzC{?PUhGPyobj*Q{NT7Ut)j0fT zR`S$XXuVEiu0ZUiKkk4L?#Wb@(5NHmvS*~*On1+34(sJ$!x0E-S~^U&lT28fxcKAb zt&vw{YP+3fg&t~RQMFoO87Zn(J{VMI25Xz-U1U^^uIUJbhT;^$88z6gBM{84u$_z5 z!4U`@Is&01bp!%0$h~LV)xbnqADG-4-4kS4?tv~lO@2W0X?s5C*{^(&;IQhuT24F- z!mbbZ)Q8B?qcs@mso{4Y@N)tuz;GI{L0`aMk||;X<+9T_BCR_7tTgu&@WKuXGK+kw^2b zswH30L%BCmh<-j<-=TzgU}{QcZ42>Z!LkoBWi)~}l@Mj8ta0Qz>NKk%4qf3)-=SI% zlyK@QawGxHKF+FP&OsdN5v4EUwto;;DnNq6JokUu&^l@EYBsq%@i!h`$JS~ICG{sU~pV2d&IT3Z;8b+zvU6Brdi7r8E!ZVzUf!&zo zjx-+SboA*Q?|Z&p_sv~(!J5|Euxge=PpY*MJtJnbxix1=<2X^``s?>OtL-;yzC@PJ zu`h!AUIEbaoBdHE@hZ!;r1OVJW}D#y`RFcgeeOw4jXR2WjCQKgin#0dS$b38?Swmq z!g{EfO+)Xg9**l7NWHm-YH>72-4F{i%5h*i2L250!eqXNR&Xbae+D^ig9>dB=xDPm z6V-0p-RyQ5uUSk1ID5R#DKcVD-Wn-(?ALgoktO57 zSbvsAP7<8M)MvC4lrFMu>bx%H%#0s9T&dNpXo>`}sp=mOGmq1l&EMN?kpFbG2$ksMjKc2=1qn0ASKK3jf&4%}bx}gz{n`JW{ z&nF~eRO1IN#82vo6s0@*q<-Ue9T5Qh7_3e0LeG_^%(V{+VLYz!M zZf?gFqh-yTaUHrNr66B@q)k&4A2rkwK5q}=qlP#d9vdo(OmPRw10^jwM`*|}Alv^> zB6x^iaoW&_^%PD3`@ku?g{^-)^V4mCR{2Dm4i{24sXwR8&^uy+db%x&yPe5LtU2R9 zhjuL%Y-WVJ1T&nmfc!!wsrlp#1n@l1BABs=6v2#YQEY@e$wZpu>|tYZ1ww7o)aW1t zn<3nh3Wp>+05P1O0oICV2@L!@#NIAQ5F^=45mbEbN_H%of9)T%e~nV)B0OK88C54IZBM+ms! zpUvuu&Fj4OKHR{Z5%)#Tuhe!2JOS&i4xERP&Qri#eBo8w-(KJCQw3=gPlM%&m(K8a zH`(Q&(Ba$cXtrSJdA`gc&kw0M*s?d9saJ%-qjN=Sbxcd^`5z%z9^v5vUD#Rcc5JEY zrROk5jf|-s*oEP`+Ppkyqc7LW^cZZ9EL8i*Q)&Zbo{j9zhnhm`uruOP6XY|E;^@Kw3Zx1w1 zt6iNVnu12Gvg{w8MSEpH)DA`tMpNxh(r-rJgL7e_`pGULv%Ju5xX{AQbdcs6k7Q20 zwlhEzxo2L_bP{MZ5=&sfNOCOmM(-dfs}$lg0YoiDpc>%+E2ydN$u;DA`~qXAGwg=Cw_?pz;fA z-}gneyV%(GB|Tee(RUq0y`?%W!;6q_mk%A`w%;8J@KL}^tnOL7MvwXXDbA+^nZh6q zcNq;CCYgJDaz(ViMkpPQ;7+l|NM}^-j?!)leU9nb7|$Z4lYrqkPqX0+^0{)H1AnLR zQIEzjq3bqj7OxTgm%f!X4BstD>n9PMZ=kH&C}(4 z;?z28Pp;&}Tu8995CPaI*sa~15{VK($#3SYlzKrO75$y&iCCZ*0blGk@efpXr7OiF zEV4mj9^r}Rp~rctnt=ZP`eAXo7x(SdbY^3Xlqz*eaHAw^+p` zO3`nop&ON+!`4^3>pk{%MFSs}v->d8_8Jd-MD32yZffA8dM3#~8n`hc6=BLLp1Of1 zW(zRGS;T$8(TavTt?H-OeyB5QccyWuvwAk08mgf`8|qv<)ULo-+^HU)1mYs2UHQt+ ztBLuwAMS$MU1%KcqMj`_4_BK{z{|0?{-8j9k5Q@znWE1?nuGUP=94yXaKVb!d0dT+ zul>L$)Gi@HX^=(-3E5~Kc&Dr@=v(IUGGTFZAG~5b>v*4tJv!8GzLAzy zs=R8r{yJJ#jSe9tD;HVWp``c05D zW}?lAiAFRNCBn0eYRu z=#Dg3jz@~ghZZf~90z*?W21$7P`>WTUz@m7?zfNxVI4< z=-CL*B6JW>K{(1&x8Q%43I7ypn^e8OW(4m9CpoWp#mCgd7?rItS{PTmQRM{^Z1N}IvZpC3muN*& zbDXJkDXUr8Sv5Di_CudjyK{|0pVzbb=Any)V<-1w6@@)Mlv8dC{;Nn&_&}^kjJfJqIe9++M{|&}9Hd z0WL%b=TisctBy}+@HptH{#mcrii^`DyV4=N$JXn3<@FFw93}~Pki%qji~(Z$s3eBb zwb$T{sok+g4c@q(ji)qtCapTt<(gO}=H=-$Uusz21wC8fnFm!R6Oym8>1b+9D*@K~ z&8I|XoOSC#6s_(>j{6?Yw-PzR%@Q~q|AwIA+&W(5-8ybX;Gn%}fKna|CUCqca_b1f zzr0Eu#pV?X8_v3duS%Dx=3{vSd&OiQV-*|PAamIG@hy`;#a}ObxDj&Z8>=hD(1a{f z6OE1zlV+t_?uS9+8-fZgb=A<;IOiGjrg8g;NC);;Z&0s(0auKt6$aOdeFd;@qZCJi z_Xm9f`#v@SV87n`39A=xr4u^YFtwA1rT^iy!f2)Aqfk?_BZ8Ha9UDD#>erDS@1Tdy z#5w%O>nmK&EQj!ENhK6(Ee$qUOL>uK9dG2Fqty7}LZeICqMngzKbf*d?;LID`968S z{?>uqy+?Cz-z+q z#eS?rmhQ!mwdVX-n|cxWR-@)zBYaJC2E7S?6<|*HTIKiAsoKLjtV}N34@RBMgld%X z=FZAl)YUH=C-qu09OAtr3?~!1mIg(@Q0~<=%Lh#SBF7&Li7{C(#zXEb<~@wRWb8d` zx>fTYcHXW<^LA|udgblfq9DC+&ZXu#R7^aFUY|aQ)!d|fUY(~R-ypf0(z_??-SQ3U zjqJghfMu{_YpL2iJhPF{kGxSUu`f&bSx`<#_~LkJ!{4z7JL3ldYjPgsq-i{-EAu#= z!@>_$z}ZX=1HZ{05FdK~1hY2uSVq2Vdb<7b%zxt6++bmJasD#TpL6DWq}_v? zsPjy?K-0OXYl=XuCXNE!BFi{mPG|Yof{kxa#w)JJaA8;<;OH1@8s}9L+!2 z?ncvb(ND)>G9B}Jv=sF9~5!9Sw)&pc69V;iXLYN6~aFrKjUq>`QjDlRlIi z7OzM{BT;j1MB%uceUtS)eoIY>H2@>G)q6XMWq==z8go8dh7(4}_laxnEw!VO;G!$W zWz3oY9fb0_Dh}e~X7M+)aq^bi(6Xqdv9|i=X8HVPmLiS(#_2uBM>B+RhOk+P@756j zwVlLA3VgvG`?nrAoOBxJze<9Yj8B;MXK8q(;dYAr@+#r`j)w0&s*R~F`EK|MGRSsB z8-F_O19;Z?0NQ%o%#7gm&MZuJz}kUoI@I-Qa#W{fNFs+Bk8zIj?oj$*fYET-gj4@+ z7)Ca^Laksgz4Ja%6D)ol*iA1b&_=yXUVvHS7vy1xKX|i$oUy~4?Z}ewL^~~QPFG-z3v!#Pcv=mfvf(Cl;T9H!s3q^1 z?9}l9PWaonxP6wIY=BabAZ}^&(ZMRP0)D!&h-NPRWxWEm4_j6 zg+bqE%Z9azcVwlVWIS4|(MULkGJs^J$tEyuZ4>-g9sKvN5&UbHdiaNg3++0nYypp= zw|4*>mAPXAModPs<6Nb4c|pI~zGGaaPdTaIrf$@ET_;oueT)2?Bfn1aWvdJ+@Z<_V zYIhy+u4YV~HE=+!4|-TD^MA!?=ACU@Q#*risJxRb%oF`0kk=J)kcO)-6SQRRoz`^( z=!nLhE!UMAmnpxTcK2Lx?w*G5ZWmHAtB#|*Q)O9V&F|AV;?Sw-jlMfI{kd|ze~tRp zAIk_53c5w7`y&ZrE#@U|-(XWh1UkZztOc(Dfsbd0{j<063g>2NEbwhUX3PK`Jlj@Z zZx%rjWZ<_s>BAYEUgR)6Dd(5TZs#pji@k-U1|Y!{VTKRqXUdj)L0)kDO$!-!93yzW zL?~C!;-DR|YU>nxHMIp*X2$vSq8y2QdQDFvKga4vAv974%BS}VJ6QLLPw!&cBpp2N z<cBytw7L%iVQTv(!Z<4lGIdcay|E5y&8RCHkzuQ8y+{aGZj&+z_>;Jj=X8?j)xQ3epxU-s$;j z#Uhr6CKaNDLC~ zA-SfXmnuMsBXo6n;HS97xS1EvAf?z@UF+sCGObcmq+Goy7xe+$49xT}jhX@{e7ir# zeUt|NEcccOB<`R)fm9WO-%qJF+ziI`8`^M^f!gsJFz4aPZY2WoLyO$h@A{$zvPGeb z;4knd_wuw5boaa0?Oh~$S z?~a`t>2zXZfeDRGFEF9W3v`$9i`#0&5jTD}IpLH;p?F`y`S7Rt#qM11(X9Mw=JU>< zhCI<-WIN(ggh#fl(dGhEt@TS@aR2nYz?t0U1%oDLgxumu(kO0+>ZL(>KfrDdX9Z8y zu!KJw?J5sV5r(R~k@C1aH?mmams8gclCwhVx2_?h?abMO=CpP6Y!| zmL(Fy_+le@vtW=Irp^gsoccu6q`XoP&HeeD%Ig5$>X#X&Zt3rG4^C8^9)Rb748Mw=4)OgN587WPp0fUpC+q4N|WV3M~^^% zUH&Lvey&ydiz;tI)SSv2*_x)H=8#BanvZiyx-evCD>|poAX@6!G#Or%(?SPy5ck2_ zt0B@YDwAV4laIm~F8FVxAEy5#Yf_8AEp7o`%gutnfpY~Jd_NvlMWXBJg9Cs^mA$ACU7Dm9z3$MJaP!1lb+bnqVqaW%Eu?q`KtbU+F#At zaT0HUUQP{$&T-cjJH?#Ixl9d1x!0zo>?dOH9Qk3fR4o409z0I@UisTP!bfzJHDnY6 zI6528?U2RITXb4iCNoT9WyqtdOQ#{|@IPCzY3%4c#ZQT{G*EOlWRh)gLV|K?#ZFed zY~7H2uhI<_sj&;+j}~X*D_dfTTtJ_@sq}?+2U_aenM4Hq_dI1>8O5lxyQ6x0)dZtq2Gq%xf4PBG{j9 zi^Lt42=7ipZ1^abd_=X&zlqL|Bz-&o6xB@NcGV6{P~J4LJnM+rCMv}58LH(hz$KT4wF5#a!g+ito9j867v&t^dbnQN zPTTAPqa>bJE_q6_7m*@Al))%Gq&wX2hccOmGB0w;fQ^KL#UY`jPK$6kw=OR*Kx_V| z6{_ENm~GS@X@W|4_p>89r3osDg;QSPpiVweooC!tJ<}0U>zla-r9GK>SJ(+< z&FAfqOeeDXEJa$KvHFKJK(f+f# zBH6HW$|f+|Mx^}I7R#Oq)MgmbuY>;#+y|inUH76s_}}#(teJeIIl=Mh{{5Yq?>Tfh z`*^i{;Pv17_uur=m%aRZ|9RmR54>_;<%#`!|ISs(W7d#uwfH)Ia!#-~NX0_(#R{x%@Nxf8gJ~EwmKg z1!G*swu(d%t_+dk>`ZNHTuryi!YodmgJvGfjBaJA!Bb;f0R;%g|oLSlGBaiL{v~kN120@nh%cc7~|^39_}KHxfC*) z)h{I@|6wZEcDSjbcl|J96fwtY(=MhFt}P;i>^ayOkwMlgI^)@zBKUl#kf8HiVD4d{ zDYsGOS4aw3pjDAVN<#$0FMerc18wVsXQs)MG`sgC&F&pZ1ExD`mXDTwBGu9Y%Bi3A6Mj9<^6&n?JgTR;#E7H z`!%Sh?JYi2fuy|;*srKPn+`wjs)~(lh2Lwh5^)<1-+j*TwbQkC(}QQsku;<91_XrG zXj!9I>PQns-JG~jePX<2b5i*sD%C{cL1LqmtkEX+KACz>sV>64bnCP(w*p?}#}5`jDnGtLv3zl}<~G6t z=!ql=IOI2wV7!fisj6xn4v52fk5OZ^Y{1O0FL{&-pS;D8){-k3UXm7z;)U>m>Mt3D zT=hlOzojj845P<9;u;p>5+Jf0+}NuBZ-Ntru)*xJBJg}VaxJXy(Iuq?IW&!YlSY}; zBYY{?GDPM?d5|Vp4S3XcLQ1q$)iE}RWvHA|RmYEgd|XZl(4>Hz<<>S}agwtuDjmJZ z7Gj@E5gmE~lMJcPu(x??a<8qbrHkg6XT)9RhGmW(uBjF(b_Sp3Iw!jPR4rQ_vHT=-^J*_xA9f6c-(tb2h5{oh2a8o`X2wW9A&& zL*AUjy(b{xf8wA_CX!I#_Muh@4)q2E#F=!YsPO~@?ljGtqLzFwlh=d;S$rb^Tn+y_ z5^}kLgvb-mx`^ln#(!^wfe{!Bu1?znLLnj_u7wl{LG!0rGB!QsOj_61<`gaxy;LrT^m@N6!@tY^U+`ztD8l*PvNo`!L~hq*G=#57>vXix<| z1f>SQxiMD%Yj3UC^)3nm?kNgPLow-;2AiHkh>MkXSp%LBYo;I?aY;zFm1K%sNjG}j zHHD*S*?1PivEiRNoCeYKtQf;7R^F}gIs#{0C>tQ!Z!?=Q6X+BMV?858TYh_5NEm*`o$D_^o(ZW4j z$I66C z@w$twlGj<}KX19n$5uZ`xvj5sk>3&Z{@RP|imZB(>G(}7a$oZzYtmM^$XYuom$0Hd zoEvVJLM9v*>!WkxVQ<(azhZVF6o`>GE4PU?1{K@c9z+zbQ#}A<_UoWO1Jo(daTI@H z3w$^~Mf2H~5zY6ERK`jg@idwrKW?P?Y}knA1LBV6yQ2Fm2PGzUNWb7&UiJ#;1Ip?s zZaA5({PIm;3po+?bU+Zsj;Sps~LHkdzy@a__TpI&Pq$-Cs<~ zO;|ZcWE7R?%O#sW{Do}wc*S*c(h3X9f}~T0BOWgko=FN%S>X{YtWyP|nos;8p|D~H z!jC6~r>(G|Haim_DjehF@c&8*&sbsM0Yto1%}L>@r0}d2ey0_lOBGJ~{2!CTb5__k zU#R5&Q8y;yKL6iI;dv`;kZPv_M1?KZ*9Q1YN#O-6{0{4e68T4klRp1iQh3n{KWl{* z1i8HM`K0iY6&|+2iY8oM_%li2VLMXqsAf))f6L4MR#JAv%D!D?6{P3Ox~2Q&Z1qY6 zxmN54Rg9pz#$vyc6dSW*Z&R`H=3>)Hv2iQ*Z&hrfx!5O?ViQ*E2UKjbx!5O@Vv|BGBbFp7dicMLux2o85bFp(tv1u#zuT^ZOx!9+YVl!6kEh;wKTm1Pm0Z3vF}&0h2~;ZRsj=vY75$egI@(jZbc8P=tOhT&o>sGu%d@lblQsM!}}cYwwg0zNOPm{iN8q75gp~Qs+bbzH5B_|Qf$(S z{Sy^ap1X80H#Oxd>CkKzr>y9As;JW6Eic*`7oE1EZ&Xp2{w|@ouGX%&=!_Np$118U zcgt(7#6@SV=s!|XC8k?mv^y?3XGOn5MU}5^dC}hL4|$3@Z$;mrqL#5P#T~f5_QypR ztmwC^sM69cuk{bI)xY+$wPu%8*Zrnj|ejR1es5% zlrqURlp2UjjaaE~Qz_+ri%X$R`Dz4@R^;!ih|<6%MKW=bF)Q+|Dl*-lF0!tA)z>oJ zukO5FMP?d`^v6YJtjM>h$ZSKAd*ULqR^*#iWUise`nbrP75OG>2#r==R&AFTp3d2W zNWo7aGnzgbYdWffz<0?ue$-XaAZ5OZzF5F8Zqao znvDmwvNGIFy92#SI#@Thv;QuYQcKm@+564TF6;M~wpjgpGJmiIKP4V~aSL8_Tz_{< zZCy05+&+v-rr++~k1I#^;E~E}uqI+=BBK#Q%jI(nfa4Imp5PL0K7bELcX%~(02_IC zcs_Hmau5}-OE@9_789pYeIZUGRx)x)(SOs6cH}kkY{?!$q{kDb80IWT#q~d-Neb!{ zlr6=uu!2uuQ8I;VsO4PRVwNc>joElkH>-x3yk1U z0}zFs)&IxzM#r;tIrE_omf&hdaMT;kvV?SV1d9=8TAQi$l&-uR*A<^XffRQqxC7B- z@TmADhQqmb?sRMC#$+|BrU_~~qgoTy^`t7AQbpk_xSJ%^*Vhah&MvDVoVNCofFj3g zWknTU=d{h_xIrTj;a52talor#*JsUBw-taCz+BA$vit79#|u9PeC)nm;K6P*yQMs1 zH#0^nP*m%{`|+3DP! zz)m>Y>R{GP^*h`ogEt@?7tQ+$T@N-CnFQk9s+^GmDDBfiXy)Tsx!$}@b7@a1WnoJP za~M&+$!+@nU&b3o=Hu1wQss;^*DTy!WjdD4&6WVTkCz})N@F^1xkClY&c=SD>DhE$ zD7|CT^X_**XExo%=_!SO0fYiZ_bK}?oPmDfpcpY}(yi^~cpYJy%3~RfB;c_JvO|w& zz9MXM#fs1KSA-PDciwU0vT~n$d?je!li_4!bi*W$&Y~o5)Bv)Wkp__61lGeC8=tFy zPF!e|N)pqbcX>6_A3+$-^hdBy(5{TE-rNTSWB-Hq(V&KNXeYsn{^(Uwq*lMwtKH*| z-8E{vsJ-$<*iVke<&(UIgs4CYMGmoISi~7L4NLk}Z-z4hOZ>rlZPv@2c7kD0#zXyF z?5VfE&TJ`ecRF3J?Mph1rSvTUY4xgyFk|O}_HP)(KAwN3xfnEwJo1C{8}&f=my(6-NQQo z&PES_3i<4}g;mW`_x{SG%v-nEcsW^Lde7K~*Hs?vdbt?h$KBXiO!cTvvIxG`bTg)$ zM1#ObW^;0bGfrXSgYSWrKV;Gc>=In>EAbzIkLHQDvE({4_;{D;gY3DN@nV%6f=Sze ztWDptm{?$-m9KX&EU(D^dwhlkJ8uHSL>?GR z86QTTIl+hSv3wJ{yDAImMi)@8g=A39CSN9h-fwklt2SE3EX4`pZYt@-tIU z@n|GzsRE7IUOx zH`_EeNe>IQz<*Z@e8o?*rhTB%?X4T7mEhT@z92 zlq%Fw=h;xofm0lz&LI*EIKH-M8qr0 zY6zFCwWdX0vO%E(N+2`siUkYf_%WIs_`z4i?3i=IQ}mJN&zu{c`Dc~Ft59j<@mX*K zS2`ZSDeKtahn0rY8+c)XMBxy$G`YkR%TW7ByOsvE6i8G>Lap1gw!kL{aWdeuP&(X}EYW-NwK6HH7PY`oGVW+Q$jjx&2Q-&5H|Ws|a0g^$FQohhZk zhLTV@XUtM%lUj`kY^Kbh^$Hasqb4v>2-`efIA2QR1uMedpJg|zmKpLIT;NW4;gYVr zo7Z*0s*%`ofjc2x0;inv=<>1}VP;B>nQ>o*bIPr4=yHqy=t{$2)D1PiNb^^@GiFB3 z4&(Wo4L2L(v{Z`xvW}5hA=yASh7lF?yo?|!nu(FJw&CAlTD^BkIBF$x;n~<>;HAD# zCmO2d8|%|3DCH#dMJP`AW{mrA-1;@d-543y9DX~s?DKFU>D73;R}jJg9WM zyCY=hxU=P~`B@;3VvAbmeXW;#tz@9HTFE;{t#f5DF)sfbXuA|%a`ik=lQsl zBe^`5BR-C-PkA8olhb#^ z^mMnUr$F3op{G+e`^)L+RHrub<659;D^du1B37qiomB(|r_9ZN~;(-D63lPJ>%z@afnw?W!;SSUtkS>7i9Y)MAF003Irmt^~`Mac#0kSK) z0%VK2Di4v{fS0&4)HoDvm1Q+z73y?bg%z>kc#r)edQXRhk99QhnBL5hOH%G-h8= zx0TpY+fJ&|1uoYdVRwI9*)g&#+Qe4xqN?M~8%_fI) zkU)c-qiA>S99^|@xUzF9R^hlRG zJo{S`OkdAkBSYwwait+9qNgXqz2 zx7B=2(y)!iHJ$2C@7-uNCsY&5dRkpzCdmM2Gf8GR=4RYgIBhw_)Ungt+1}k7?Xs4& zl48zkCFPvedePT9XSGgu+uogzYd!C3t%fi0wO(>5%Ya@fnCWZt-ktBhYkQa8{4ce4 z@4xlEyI?D|oX=e7*4}+Yd-sYJDTKYA?k+XJzlxw=>^460s$X~DDAGn^wo6ectB~D% z48xD0eMANzU~^1Yo}b`~;?dQnKto3XM&tw_74rW_+}l9ObyfGC_oJ%1x~r>oCAHLT zwLrHjg2)dGDa2Tg(FENd{DmQQczzjY#xvtti#3ne?Rg71UWAz^tTqy+Nkq~iN|22L zouE7^i3Lhf5+(6un#2T=CxY@u5XFelfRZRgnKX%bX%d0w_uuE-TerGevTQJsm-|-T zIv@M&v-dvx>ztD>y0bm4O1(F3Kjdna829@<=^g2*q|OelkU4eS1H=J{WiK8FiQryP zi`mQh^yG@%JNZ;kTLOPhwQ2JNhig5pstoOnp8R%N&$Gplo_0eT%x?71om){})Id~; zF>LuhYm3{9yQtNcU(|r6!x**Y7Pap6XSqeKd&xqZ={B;ksk)6U7ByQbi)E{OF)OcO zo4jK)X%L|IZ1-T! zXfRxL%V5U%bcVq=^q%i&DZ9`a%zSw;7i=(FAwYJJyDTXaW??Clj2Gm6>c*eY&gGIy zrhKv*)@kQhDpY!Z90}!ZH+l48<&(YpH%aUJHzZ79aTZyh_St8B+UMuHo7~5nEUix- zSQ#2u$|(b3Xdiwe^F)9kt9g1{?3#TQMh|hbf7w^c#b71t^OdGnmx)-FRP8eJzi+jh z|7krt?6sG#+01Iq|8;!YyE>o${XH#Z2UN^?-)A^}vhcniSS^9LMZ@_hMLJ^Uh`#lT znOT8=n0Zo9CuWWcjAK@O)_N(6nd7U=d|>^YP@$})!5!mQfN`7LpITj3$E+wPRm@pO z=q;oGKCPalx9F);Ec85UeTpWZ=98&+ZbSLGE-a`$qZZmZuQuVQdDXvQ;LNkO@ns$y z`a^ztYG(`9lL>?iWgIRT4qqu8E?SWagy3Slm%D~ua85erUK%R;r>(v%|rf$awAvIH&; zmkGg@zA$X@iv?G@XONeAstA{het?%XKybWo4Nu-r^TY%nHl=)KjW|Q}bD74$b=}M3 z{cFmIb70J@kp*u0?~CccvGYQEb3uS1*LADevJv-ExZn!WcGG10v#%d$r+C1;t9P~7LxwlQ=oLcJ` zdoNFuEqd~Ph9{8)T4_Z!qHa$$XY|x6YgBV$tuf454*=B7 zr!sZ-fFX*TSDRq=yl?Z8p1fbMHqWkgPSB#w^RCT;y1OXR4Q+AlzorBRhMW?=T?zb` zIpHbMOKEx?#V!xi;xvEZ>3LHl;_oGyTT>&Vx_=|8o3`J(5=ZxqlnKvDNotG$93(i+ zuWVf6n`Fu%J^6K3&m+DqHZJiAs>qd(Cr8S}nYVaMEz;I;-`3NKjo^fsFly-5XEb{~>88RdPnv@0%-ziG_ ztLLV)Z%f227*=~l+=3C?^&+-KD&0D^W<{W-DV;3?<`+lMi}`G8m!6_RJr58) za=O}H?b}t3(@JkW9ULvwu3AJh9yLmub+vlL;Gt!z%#IqN99dE&r@bdf%XC67*t++N zOd#9Qf6XNlP;zp)!V=lwxcjcq+;XdA_d42HC2xkoB%@xWMe>-TyO)BFjY?c?5(Ryd zA|2~=PTzX1(-R^ftkb9Ubk^x7L^mg`_zCN!Y@MF!q5$oh=2O?Y(D4 z%QB5hos^5yqqgpz^>qsy-)mOqx~NCpsl&6QIM4(zYwra;wO;DUf}nJ^d5vH}O^#IE_e%7ZMHRM<>mcRR(|jtei08USt-jUHS=u?THo@7v>R&K;{>FPH3Y=Z+shurYPfKvN zU^si3aJJ|m>6!1#T{u%w1h1R#sde2XlF#?vb>;b16;+zzqVRoqQw969ys9&*o?URT zPp`}8dw);u?0|K&1oi{#G~XKq`>X@R&7Cvm4y`MbsY+obt}{7*rBoc zTT&&L^T(H|a%`OheRg6=l|i;FxOAJRx(4V#JF)Ixb5#I_=U5d=4g-=iSQ5Hd05U$V zWH@~}*D9FyE9kG^mR2!mcL& zDyJQloLy2Sr;>BaR5|OYWPVANT+uw=MI#Qd`R@*mTp=+P7&x zDdvJvOk2#m;HRY%LdwJTm%8Rsh4B!sv*mBmRdQ0?NukSK)2PxazlbE7+$L93p{Zl;2L2ykz?V9A5V|>zjMzW(5dndbw zqgGY#Y4%~C@hzX$vt!<#QU_<%V78u5r$CI0Tb=7^DVw)`m#h%;h82RDx#pE!bl~+Y zatmEZq6Uy%bR)Xts+4DSv8#WTR{2YeWG{f)tm^6YvdbFA^m+|r3!g3*!`QdJJilrt zn^7@8zw68MyI%9Vp)`^MRuWoC1Z2TwhW1xMac=9?xh|Ajk@*hF&z4a>Zzx}{RxVhPa^QWP=lzRa?WwRh<^mLO z$y0z&1y~RfEE+Vg=F>t!1ebeS$foSB0yAP3%MeYyM9eZKh^F0j2BlPh9HMfHq-NdIEqP;E^;9yS+*=z@*18j9FLSC~5(KS-aH>p*m(4AGoHbe+yIpp&a#K1Cld^!}g0kr%y( zHA2+2@pyL{!gr0wKYxfDzm$e>4Y^VDk!(GjeCph`-&>s-O!62L$jRs`b&_p}jf4+DX zwWH<_0Et*k?a)3uww!A+Obc%hJe=+RF*cSDCes|rk%gJ=bbB`3$>C-z?;OLAF_87& zJ!Z$)MRAA*%7tm}7>`y&bDRreCtXnMHZFb#O#iQFhX`MsUsmIYJG^R#5{6j~20Gtk3?{11x?V&B9 zHT7(4C+lqqBenHxOk>=D+0|HlrN%g117&F^hp^Bd{Q?^I2!uKX3IOipQ+Gq^LQokv zDW|q5V7aEDL-vL=@)h9M+Nm0T6OXc$dNO6J^ej)AA)a$|Kz!9BzS=>27#QM(aGjdc zm#zeBe5t0ZK#Rka=8yB>T6GHOOpwIkxhXu8tY+sEHq*M!4Qi&2OeIp4tRp~IlvRHo5D4BuHHtUbSAea z(CLznGIZ6Havb=eI}SRKl?p!xWI-7+f%zPeiK?2SD$DZou)QWU*j@v9m0_b?i z9TnxrjSW+P9V%S^snd57clr*(4eqaSGLZq$Uc=Q+PDIdTziuQ(Yg?7BQ6;pOyfi(B z?LJ41cP{PRXxG8u(PT){Wk@zJb&Ua7@g#Dfjbsg~XrM!?{6OFV?yO1)IcfVLXKxq` zW$0Iyp|9zbMUc(`Om#^#!B$UK+=cY!bfi*SP^L;qByiM$V-o>l2bl7bg;>nbExAkP zXO&0KM0-tVeullsXgbk6;^$^$qMc}h#5_bDH7;YG()>hj-wvlPx$BP@A#utzUGw8d zNah^#gV0(9z|3B~XMU(zPlw(76s7Ilh)TPDSNGib9$o)S<_0R$T^mwHk_nKaxzQLz z4iK4*ff*N1Ba6AEiZW&JyUA;nn;-{}CP?Ced!=l>X%BEAGboJ2=)t8~)(fYU$uu z-s|Al{kjjV<8;wIkM1DY>_!7w!{VYFw^{R`j;s~MNN@Cx3Qj&VOXuo-gLbR?ND0S3i9}x|oeW*+X8n-CQ)#1eXqJ zK6SQ(k}I8_t9!x&4(ofCe=GKsFSxvJuU&81>@HC6+<@r|G@h$Kzeo}xh1P#LKQ36* z*SXQjNP}y$?4l|ZE~3;*#TWJ>-D~fT7`}R)D0`GeCYFTtP207HhG&}At%n+Ee6%!1 z8(?1!UQOUR_AI)xHgfRPhV(%Xo`|I;@UEp!PE|3hGJtwgH5Aat?XJTDPH315Nk@CH zg3|fW<6LUfHEDf4b5gN6S?;z{c(?b|SH{%yQdpVYFu`@;zYs_D-J#tE&h>{ew}Hp0 z<=bzIN1<(wDhDB4@y(&q#ewB^==k*Xc9lwv%o|MI!;rp}4b*ws~r*W7YCJ%J7 z_3IQQDjY)sTokY8a28D_KO1o#tjrln9ct-L)^>$YmAl4T{j8}-17R`F<^zt7Eq8-W zLqS$j>qsrup^;8MgR~q@%I{`^U8i>25uSFwc&NcW=?=#v1$hOw8!wKmn8*gCITb%6 zE~3e{lKm)C(E)*0j4i~n;(*}tfE{O<<0JF{B>OqUs5V|PWMp}Jj#ZC^@f-sJ2eNa}ErIXUfaGu@XY*E*rwl5Y_wf%#)GR=Z@twcbKv$SYSmTiZ4NeIeGkI65pz9> ziB{FeM4w=BR8A&la0o1mtmOBj~vSk;wcOv+i(JI>8a0eIjQLY*KDn*s<gaBQ-3V!JU#<(enb%E=3evj#iM0!fkm39^UoJyUb z+dYrt=~;`Xr%wRSv7WFQ(>_1VX9(0jKgH)GsEDlsz?u#)-meCc#4~D*1C00SJ7Lyo zeV>Jtshmx7#OyPK7_N_JqxLFeM%Rkpz;8%J*}!5=gguY1l|A@Uqr#Nk7+(P5Ftz$S zfGK+H!qn<+OuhH#z*PDIFeO*y0f2W4=QhKZu=d>8Vy+Nf%VH}>(`qis%*hG@Mz$Ho zanSdY)9~{^(ySUau4@SrQE%8PT*GPm~ zS+Aie9A?+1iUd(S;U#u3vkGzKajnE^{)f;ED9$dT9H+|S*yAi<=w3>*tI8{cc6W(% zRjv;)S&vCefP$$d2FoYh_>l7^j`L0v4+8uA5$m<=80^7bEL&GYT@LN0+wPrTA;bK} zvMAc#4ow^z)9^E*(Tkj$oyfWId59c46nqIIeHTQ|?9VgpIu!gGrtn1+IYMqn)-20J zuUdwQo{yxt5))lX(sVJ=rLV(8n>}}6x=9UKhKc^=tM3`%RPk3ijYr3FT_ak*Jtl%` zubGKhddf^BKgCie(ove|69iXia%L=krb43O&Mo)Yt`5op;0gaf*N=|bImQAcocN1p07>m6a z>-=2Ew=Vpe8?#%C@v1xnRzhmQW9cd{zmQQ^lwVBda`MZJg-G(tL1gl)*)WP0ilr#w z?iRJogpzOgVp%D?acpk)WaPq-UMbcXyYEd{IbC=808?zx~O7 z9%h12E9UH450jM#Z5ngE?NAr$jo)k6M+Yf>MD3eiRz^R~nNCIzLO+e`-jd|M=93_M zf<^Hfk)!HfxSPJ)jT$3SJgTPz2_rwLkuq}bnX{3f)_2{KpvS`Sr#s{3GFFrSTEp( zZMi7uTSDCL=pE~*Vh7`39oQt?&ja1(%>`KZ6<|HUPZwN!9;~xKRFf&`NRn0`Y)24w zwE?}?vPFK7+lle%_=tQ)-mZW@eq`UX*hdCjMHX0K3O~f~5`LEOL{vvuCT7oaQlbkr z8Hh}rARR6smBAsU;3nK6HLPRI=p26-w>25k#yNnwzFpNsm;r0fiW+A3a#uOMW`9#^egX7Ay|1I5Hf9+f^B)^2k)Zemv@LCU(84nrfgdS6F3ivBqWb zu>1nm5`qUok>pbxLQCh`u<63$ASBNtg#;Wz;IRWMz%0)h9f8CXqd{mw zk%rvE)`))<`xEMu{^?us&)&rR^FLX1VdHJM20tE5W_@=) z1P#M}VD^^a2I;6bMVolw;MvH_tp&(@**KB>q%Ob&?yX)-_OT<#kfF?rZf!jnsVl-A{~wDPFVW5a|EX&mNFUew4AI=`ar7_GRbkrIMT*;N!mp z6O!8eA}`8YDFDAb$PdA5g8!3mboIJhg15U*J8lVf@zazo#j+ePsv!YDeJGYFcaZ!f zc@5mN(Y1mbW~TiLPRS{a?(>kI5Ib!vw1Ge4T24O3z%@JHP^JTp7D)INCn?gaGZ3?<}gR2#MC0&Bz(#)`hCa@PWuse3cdr_sIR-LdgCo zM?QWND$PW#fh=YMa`ZRg#=h*=a1c4v3Yot`(X^klm3a!)v-&>3d4GD+=rkG_j=-WZQRlw?T8~Sn56|O#XQyy%M26b$+p+fSTgFfOWH=Aoa`+f)^NKuxIUgv6GSM4RELF4T)qm=lNv6@Rxf>lFyDd{w@q7$u?GhL|ZPA;51&#Osm+0 zR|pEzuhS+l+5+Wgg1K>! z;aQb^`U9BuBgyAS8}IDkprRGcu}FmD89Y>M6kx%WL}`Iq8V6A;d2o$_0iDM3Qd4w& z$Ii5(R*F+hkn73ytS)c6|| zL#JMDbpx|*84u^lF?3dEsObu^sCHeRR~H1K{jPI^H2{IhzB|DIVPL(-A(XUf0K)jJK*R zoRHRs!Z6+)gXzwH)QA-1Dg|FED9Tkjz&=7W-4dV+r4#Z)x=*mL>TWeZ0i9 z=Tz|$Q=QlA6G(P3lq@7Aga)-Q1*KZ3Wnp-zMe{9H6zN2k@OLOQRbPZtLDS9X0+Ip% zaVJDS2{yyziv#Wc!>QPwt7N3HBcZs*i=N}1Er@0O2c{1zVJ;F!R3>gfIjPE@5bi zP3_893m3cluZ(SaiKQwrj-i8Lr4onF=U>Gajyjbp`MctkDOHs^|7f3o{4IWSAM`!$ z<6qZ%DnwC@f7Geh;ZUX~9;_>lXK^vpQW;zxjjcGX$jpr^{)P&kMbwWQ*&`VY337$2 zT(fd*=uO?LzkD1XBSC3WNMe4n8*c-Z5R#g?Lj4v5jGVw62r?fAhIOD4E=9u6gbpP7 z(w|Cl9JbmV+^rxT&)3s*XepM`3z^5b@#exnMapUdr7SDNnAMcsqCWnffv7bpW|LCjuagZM^7z#PDT}YjTjgK#p<)y{f)N`%AYRp-7-2r6de9VJe0`@ki zWFGj<1=s}=SXd@@U{P%5l0l?ylP|1nyE{*9kubLh5NVxnL;EskVl!AYK=Upz2s2J> zq-Lz>d$APkiNmH}lC>1%0xtQBm3&5M#~4qNeuI*JCaX08*qi#6wDGDi)9ofE6iWv> zDk=*fu|Ly_(?Ui;J=roGsA%3huviBh88?5S9C*fxtgJdX=a8RdBu#n&48UHYp!YgoHopowT#;01w%GVHqdgB z=eVuFm_vueP9?9VDPzu!ln>VmyU}eI?8U-0)cEraao_Ifk#Lu{`z%f`9y3xv31QJ9 zBPM4zKKfhRVcI4dyD8e(9!NgW6f^K&DT?pkh)Gbw z9@g5fbps;7fAf}hb3FVJR_f+qerTHbr__URD^0#d9X!96rC?zwX>|6?xt>(DiSN`g(!17PCnGk6)_mWLem!O zW-=9f6LDDV4O%aJ*8&l(-^bp{kvF`E<|{^pm7ApKH16uOlFW8>n)`*tV9R!14*V(U zcEbT94vmtLgKaTq^$=O2ENIyb+PTqnt)CSZ^xq&1ymfS@3e zJ}#6)`sm5xWKN465Yf0jBM?ktWVK%!d=P6E|C zSDVQN3xw_s+wrYz$-@|sP3|R}-D)!payAEVF$IU%FjaA|CO^l5fk%%mIHrf2C9hga zyW}t7YV>Uv5jkLQj)l1cUrP(&=xy-~Et><9-N9LeSrumkw~w_+&mTzR$>c!O+-&$W@9-^1t$;AX)98(%mh&XOf$QN6iIS+g1phPA*3WKP*i#=eTwrsr5^Vy z@5TLOX;}tX^6T=+7Z}OD$b4I7lc{7z)fVW1%6Wsi!nQ|1keZWUygQ&RI+Zq_QFL>{ z+Ok3h%?d#|0y3xF2{wKw_fRf)+B(8@>J#|Yi`(1#l_4wq;;Mh^T-fFl&d9JmlnzXlnM;_-6(uP`)LT$by5a{c z*A7>V!?dO|6`2U9zYlV+M>$0ySCZgTGtkJ-V)Ln#_1yDM6&IUl<;;V8x+UF$d^Yz* zkPi_6%UD>;1^Lub*E_7Ep{^I4sy5^c)v_<;^nn)cGT#cT76E89OY24_?gFH4S~2K4 zVL*zCbQNARTJaeS49+IMG`_H&??C68mgO=@%bj-wHse?4k{*@h zgL(HRJ7l_B@aaWJrEKP@lt8;Al~UH#RZ#BIDZ8yI(7Pm^QZ%42Si{o=1G0=_3VsX8 z1`UxHf*>c>h5QfUMU!?~l!;`E^(+eEVrX!Z%YxC0m`xjJnsA|-NHr|VhqOo%NtTIBRCX%X!p`AQMXPzB+8f#KvStQYvK2=;kBv2f?5gq(pE zgu;0^#HFw<#dxT|DVy|zb`y|qGlW|P4-)!M5n!8xH&}0q-zv5Q^h9b4?A_x7yiFGH z+u4r!H~4wwz#*6%H_Nss zgnG@{_ELKkXI#{C&a&+dMf3@3koau;)pM1lM=xmM!2be2h1ogfb&i(vI^`uf@R5Tf z$@_|A+%S9ZFLTVw>LRZbBDB2D1^F<1R{kYE=NbAJ`Rp?E<(5T1z{6XQcbGCTkT&E@ z>&L~#RAgHxZATZEl6#pzC^!z`_Sf@Y?WXD5E!g`(}1>zL6W$QO*HF1&(ORmny z9mqb$_Qfc>?yijaemHyd(J6A4T|BX0VOy6u;Yi7*1U(9I=_pCWvPxMBG|L?$C=xVF zNL@uz6@hbr4_$)-8-TmlPcT|{v5wxs%hY|mmNGSOeK|LfixR>-0#e1X8*<#?Qbnezle`R zDP)XbA(Izy_n5oANkl`|eqWJx1C!CA;vdEz1PGJgbv#Cnl#&Im*iXS?Dsn^Hrw$&` z0*1k(78L|@`Gb}qE=DF6=9DjXEh~YL$fiZLyk!T1@(e<37-ww}y&{8V4Srrj>JRD2Hm!LP7O%DVN`%&>A2UZ${eSrBDb5{;;qgN(WNtPo#@(jhy`RS!_f0k8MlKc zr#X3rQAy==caI>vDI(`w#`Al&#Se%Bm6Qk@%t={fuatBCXzhFdPoNe24u9~RyymvC zEb3JqpPBhdDgXJFpj;bxprbjyxuZDVU+9gMMt1T`kL!v8=G!*-ddzb)6_}6WSdrqs zTcOkyw>`w)KMu(7F{RLSfvdEyq2Cm}p`&TMj?toMFi`0k+i6V3L``|1wQRdHC*1ms z!K3^y$#YSfld*0(2a4(Jy2?q*x&&^YBP2fvc0Mo&a#t0}jBbS_7zA=4Vi=Yd0^yWJ zdyvayH77n(_BPI2WpA4lHyOx6qLduO7lPcxpotIF$z?XM6fzs8QsRyjiyl2jRnU}K z)7}?{l{^o{7PSrqla46?&B9SBC#aH(U{i-_sHrn1>d1O>;0k7utapjM*{hV0<+!Q5 zYUV3h_D&u8Q}yfA@DeGHuSmHHbz9qn9D8wtdu-ytOu~13;AF&nk-f2uBge&CTi8a7 zs92cL;BsL3xD2oyv7mW!`4cYjE?;^`R}(QI0B(wIrt2M(z|hB9RVRH|^90^rw-g4S z_-l(l$qCN*WO2R2GOX$@homtVxfGIl)}AVo&C(Y_rr#%GTdG6|c^2PUEJE;Fd}j$) zLQC--1d%q?`A&j!RBDfN6I_aSRhQ4AW2TsAVGO3S^fvj-t2R8h!K0cxm?P0<)d)0y z73z33Y3xcd(4weA6Y{p5$GHTC&zGK3j$@H$j@P?ti--EmeGkF`Ny&I8<&8}x>?>rC z{fAWfI2ei2Rjf- z;OkT=WykAD+J!U-w(u$UNXcC2HV7{sqpeVndW#eb@%Hh_^ z?5|H9K3!|A%HH*b4}ShXwT82Q_^aRhO57UAe)p^Y&#(Sp981R;V+P$qU|5$5^UYs* zV#HP$msAG5>Fw9M-!hw$T>9m|_58wtb0muYSeE=a=YO^NF#O|fobtN7PZj=tX$1~D zbWJVv{K82_^>n2*rBc>ZKL=x_@sDMrKi*!MB0xFy<;Sw?ew<)J-p;pr+o^NtnL7W+ zr9WZ!;3DCdOFh3RHjxfm=aixo#=&7yWGz|e{AGkOUUgOf+S2OP2{MNC%Rlt|k`61k z#;U87HN2LS2GgoF%<+p8ZBF*01U-^h$<7Y@fl3_OmX2z;TEJ=iU%DFy^)kIyTk!@5 zUm0d}02|F&h0EO)m`HfR!4jpbaQj=Qt2NBXTHydb;g}}r6qA`wztP=EOwWX z)rVUsM=%kWd{887InB^hXE%A;jD;Lk3VmCp`ZJsHQCb}jM z_H}6QAqVx5dzO+my^#mI(r)H~wlm6u+jZeq$?8o!&~LZ%K!C63f%+>;oHNL7KsVSi zxiJ6)HXAV)NQMAq0y$AghQ^o4eUxk=3)SuV!I2j1Y?IwejxsX+4{Fg4x64O+akbBf z#8ei|W-H2mXaC-jR_Jtv^53*FRPV2cwHoAi&m043EwWdk~rw}?GqohdSpSW5$QTiu`s!>p_N>LB9Kl(ZD zmu0s&2~J^l`e$%4=3gHDZ&RHwKjAl(gC(jl44o?qT-k@|Y{GS!weRG`7fLTG^2_q> zZ0X&NcPr&KWZTuBRp>MaS0Y@8Q-;~sKIr=OHZ}S?77C}j1li?ZW#iz*nt^(0ic)d% zs=O2!%GaCW-syqX?j$IjY@`XY6zisy z@qt4i)VwvZmD=0Y1R6%1pzTTNiE%PeZU;h<$9A_QzF8(`0|*S72hxU%t6D4g;Y~9F zh=eoQjoVq%#n=znc$JsUTLyho^k$fprfSwy%tuA7YpylW#9k@%HQBxQ>C3&0i6W%o zBSAou+c3wtiF}7UCvOQhG7v}~wOQRE5Aw}f+H`S>!~fKGrO57mTb}684hH3I5VG=`|suD}x0k-FQe6VXR14RZ$9Q z&^C13?_`eaG=i2jHgaL#D67KLR0#zAs-)O3d4JP`A`+5z$Mv#xHz?OM8OvXaLfiO< zM3cISdd!XpJ@C=fmyN>qMSvpbEU*M!jFRLTh(vo9NKvLyR5xitjy!CBw9AuSrFXUQ zSgNhix&A}+2t`wwNB)3bO=w1#i0Ui*i7ipN-`m_Z(zhvL?d+rs-z$<7^1Mc_POvhh zjw{D)w*JyZ1CE~%~GL*F<=_yXK$dn zO17&Nt69w^$sn3I=1&U|1ji&gf%?0Zu%<<029+K;ke$QN8-b4OWfmaGz7XDN6U15) z?)+Ht!O=AS*#7@M2!j7^|9dZo;D+RbpKp3Ygp#!H$7#~yUVYz~g3-Oexm^{Td zt2ET2b|wwc86!NV`1f{jW1BfP-^R&;@+QK^qtarf;mXJ{IB$yX zL24LbTSsqj{oSC47FuY79TlLe$~N+dO(W{S8fGA04CFbgn7FG#sQ)XUB}uf+p7XcX z(Me@<@FQ|oSmXEU1xA_#fPG3O9PFou^|(o~996l&Hk`agU&OWA>{x+`kd_tf2gxdJ zYGe?|tmN?~PwGx<(~E0=<+1&ow>@RwSg2@xuZ)+9g_J4^1SC(8)f$td zq=7SQw)TrQ)VL9G-_Er55d1EzQ}gLyqJglr>4aXSNA^nyvRhfE3|sr(6NPor4$Lq1 zM0nI&ER^C>+Y=0z(mpdB$Oo#&0Gq+}Nk`)HV56}ZEWEWnD1oG08OILk((e#D*b}qb zp#?_mPH-|s+C-{eXjI3P^G1Q0y82RrGg20Xlzbw1`qp;ML?28VJITECdsShyoo)8F zt_OkU>p(6_kz-ZUM(!%&ls6zEd7lozH8FUrw(Hr*V;fitdQL<9tv|bp))*Uj1{mZ8 zE0;TD3ETiP1Pgqc>7db=ZbZrMSdnp1Isi8g=x}wym|@HN@ilc4t;##IKyODE(z}pE zr$0bLlZ&SsXlF?!lEC`1-mz7gcYJ##2B#8*`m@gj+M9ehI+Y%Ib(S zEpKvi0IZHEVG%G;RXb1y2#C+$v%ZMqkbo$56^KY+qXBAnOOz3wX4oxBcytBLR7>;- z4v zo`zTi9F9}5rl38)_L*u@3dCx)lgvi6&%PBAWZs zayobKRslGfMt46129YayFk7K)O;^%e4fqCcWk^HTKYM|fwwq|OFf4Cv_R|6ZyQKvH z=!%uu$L1@m)-shz<`1$Jy^R8{(8WUEg{cst2wU}X~SvVl9Le}|d&((C&=9o5gJ z_MNXG%@7Y?3OwnJ!ft5_IKZ}42&Uq+$Y2ofkdEnLxi^s_!XMO2&OCBF?B7ca>3xuL z5}a57SI^)ey#yJDoG;TbiD+T=XB@t0Tb#md8=oYjY+P+K0s`I5RH{l>k|A2Fb&AUn zN4nF-z?}~Pi^jrfl3nF}L3oDftEDlZGq+a2j^jaVI9+XrYhcQb2kDyeAo-IKge})^ z)W?H2Nvz_nNRx-~74eSpI&qtAvmBHf?%9P)X82we8uf+5nEby&Sr%F>m_+Lfp(sV# zL_%jMcJPuU#>)IRiIH=ketbllf{74h$9cXZ4>eqbhR%la3{lNq*=at=8oi@7qpXXm zT$c#1SSwv@8yg*1>iYDOuFn=-Gi)c%{XXsW+1C#38A(1l+VC%K$Yx1NDZOZCGvAmh zzxbZ)iy!EE@zU(zKe5-l)5eDE7cqfLFRsgetWMX^|kLpId;%f2A`z*$g_7 zo%rw*eqxyo7-hYCph)@<5F*kU7^oOxC)R8W0pVFfxUrJjx@yKrUFurIB0$3m44r#o zBwJAm3`y}X4g(9b&*=AB`FC3B4HcdH2L6Cfu}qe03~uRoj4%CZt0 zv2X;-m?4O^hq90VSB&%(4zx5mS5VIC>@)mQn)MCYm;H;Pc9hvcb|cwm1^9Z^Ui#bG z?4o`fE46%G_K$zlMLw-;*0=m~-X-KUG%Q?G&ViPsQ@9pXO7)i`Odg`o4zxRFJvm4$ z(}5|ape=cdE!{Tvs0yrpGD&eq$%}<7aQYEi4Em8QS+SYUo+E)Z8=Oc!Hy{#ox)OGs zXQuDT7JkzK{vl3K=^?l8TZY__HH-kNGkx#dCAXR*x9SpdLyzjFvv+=BDIImw*|dHi zDbpF-3QBbNkwpk>sQCQ_5ZK(tsJXi)&2au)U>wQRMQ$D7;G*e2L72K69M=DdY^wYn z9$b{f%YR=ezQ|i5O_H$kD<-pVvaqz_HYqg$;gN5vRl;kfFt)ku(DW);3RxtJa)544 zfz48EI=+SQb7x^6OG78l7SYQP3DPw$xu|`_QoVrm!??g;Fo()Teo>s|a0bGaH^hd7ZN~EwwgF+ccq&5MNOm<^D~-UL0Sbl{Sl~DX6}*Vp z!eED%aH^^dzVLQK)P&)#j9AzLiizl+>8>a%7GZ9i?p@Aj)-QLXsu>A7RT9-QlA^Ry z$_G92zx+lOz2g5w%AK0TY7SUc=_SlwuC!fS(mr>8d4l<6vctGkR;O=nz{+XHHOWC*PHjKhvai65s@;Bj`&Fj z`Ymk^Av+~|dGgzQWIqV}K@wSbuO27wCx*lGMA%+=FX6A1KRl*!xk)iB+BACBk%>m) z2W>V|B6UZ1xpMlu7)~CA)|pnBcCP^?Fr^?NsbaKw@g8fIA&>!*^@$sFfLS|j=fPxAe$cKKk<#ZM9(xGtpevmg>!WMd z-Xj=j)$Gg{P%Pr)cb!nl>X}x=7_}>lC$q=)pov!9k7KRKx4*+b=ZH@kBaTU^sId{FU*&lryQ#Q1X-1M&!jyd1z|RmKXXu;PSrTgGfh~6^?l9+r6FZ?J}h>djpGDk zBx4AfReSGgM(e=AKL$(|@;tHhYkcY9j|f4@c*se-q5SSf`ymwESAN98T}0w%Qbb)7>;eUg;s$ z%NpK9)0oZ4_z$XdG`+XITD4b=$9wjU$3NVZpNsq8uA#*o-vofMzQbMZk28zZWlO5~D_Ws=&Gm8>vHk5&?f)KeW^ zvhrJ9`I|*CaYo(?_#qH}*lK07KS4$ajkj4bv6{$9QZXx;rLtAj5L&Am`l zZ<2fBO*;kCH0slv9@3|`=N~vk+N8vkjr*;;z+}4e-iPFvm_n67Xi}Q|S6X}%tvS?A zEnz2>GH*MRE;Pn+#jD~2`tz3YcYgEp@B8_K|K)S97=QQg969~#fBgQ>%mse*_qfsD zCvIRM-t+UCP~VE~Y*VF{1B%e_(_Ho?J~6%b|1Z2%IOEzc_dPDY{S zVddWyNW#W;?;mANLc0ak`-C&J@Smb&fiI zK6O8OsiItMB!095$t_1YQ55oB1ivm2B!g9h^#%hOtjgb{2AV3P&bFe1GDdvCleC3S zN)Aa%bcUNS)tL=cU)df8+WYU4sFff4!_NeF$uCbtV&ZzRmyG|>zQ=##{K=pB@E>s) zW-@+ke(updkL^3K^&RbG@A%ZC@7y~*Gdnl6dk^$))yN@BwgogmyB1v+qDf6T>E@`= zvP#JPb3<+=^T@?1Frg_Cg3mexLuSknv#Q4M0>FA08N#GU!J&APpcWCRNP4mqBrs&Z z0D@85-@yUl^DO*WV*U>gzJtlYs8?Xa2! zX*4N187l_e$X<@OxG#J88^-_;e;{pB-;(jbzs-?+Yt$6>tRZAeVkTRkQ#z5g)$EBM zy@PcZH;$~SYW9hjzuv{iX%8=s(@Jy$z5V*0&3j5yAE!s zIvc9Wg}0f`w`BlT?HpP4MqX@}=;8gO0Uc#X!`Ewtx7M@m**lSr@?=tG``yIGlBb#) znjZw?LF&C89mvWfLB7V>mr^E?SYh(}O%_Mw_9#MMad`d(C;@uq%uo%1O4cf72^Bzt zwRu~!zRqJy#p}}Y5qAjC>|4(&Lq|)KldyBaz2r?m^}KPNympVBw!S$yz5j`k28T!p zBsNJ!76=btulO3SDh7rPr)(x1vD=ZLRd51$?9)=k7MQVN$-Cx94f*+Y9-VsRha@;e zeyEoXRv*@xu2l#B{8rSH?zP}utOYW#wEU=j97f8V+ESeU7UIqgi!i;?bLCB|>(5}a zfqAe@s|TXcg(6A5AfE(!z`IGwWZ#JVvWk<0IOACE(6@UsuSAXQF zey;N)n&S59y}PswiJP_10MJu~&yN6)GFAjcD~@--Ykbr?U7xVz1BFRr6M>a35m+gU zz{)ZrP(2xp4w9)q__Hle+hAs(5Jld{2Oi;1eR@~BGM-G2Kl|v^6ep3hX7lgM{rW9` zbzZMdp6+{O7a6w{cLSvz9adMp_o&9l3~3Yq-o~45!!^XcQiy~9LEIJ)hqeOZ98d!# zh&TpPXnbXXMp{?447e;|Z>zBPlbmQ+9PBCVDZXxUO5t_l_Ab0`vd*QtxBDOpOYZ1X zXfzJO0GS27Au$YEq_zH&7%NrtJ7qJ1i$P8Vp&!c%?b_13r*-hS3lUj2mI?puSaHd< z{BmFgl-MUIfJnJTFmCf-~#y*cM}IFl`OER#-Hn3$zMhc|*pid=V)b zGBQgFG}Pns5%FjMJOkKPOYkcvIZRI>!&mXc_`5WdXx(XWl+{fEln#- zcsuSejE(Yt0z?bRIF58eH5@0Yj(O3lqLmne_5>x7YjjQ=-!wl)Wo8*O zZbdp|A>~n5a*r6F^U!MbjSulHchA=De5mn+5LWf63ZlO#Gt<5YTXlymeD+tw7I%{7 zVuh>fm}|q9lPi6~&r1t-!}WCUQn^w_lqF-VV=y!l-%SDtl0$e&J{q!wH5!kF>?#p& zaB{L^5&M}t5uMd@nflKLcey~Hahr@RB}IhEr!iKva6)=h zHm}p+UTJ#L>;-N`Zfxy>gBKkMnDpRJ(3W6Alk1=Oz9878vl9?k=%OWE4($e$9B^I# z*0;8-_w@Z%0r2*`XOU02OV^@`j7rxPm-PGStMMff055JN-&x}B0O%rWCWt;6{;U)s0p>>fHh?0EJLhr}HKV_WqEk&Y|QAwk(*Ha$Je1|MvroF4c!v=d^2L<#lDROcCevb57^ zheny!@CQlan4u?WQ*|C+=$N=6E4D`$WG8)*y&Dq6aFgvrmQf^!7+NiY`A%vx6p4Ht zDb1U9jLkwnItkg3rRil}z>z4zP33^*U`KmkS6eQu1}X>N???yn4K&9GlG7^29P@H3 z%07>q+k@k88{aJ#1gnSUZ)jJGg-_#*~l7cSdxr($}}G;$i?7?u+Zpze0MA2f7Ze5WoQcY zCo&kveByud7K9UP0L&@_3->o_p%+x_2-FhGgYxik9ZNz3hCJ@(2r?qd*u$cszO1Ta zt&xd1QkDEet~wqa(w3Bu<)S=tl~y%ANp`hn?7XWTv8E~t?L?G#71EQqh13enMB57a{u+t0ZVaFS&d|Brh6Wv3|!1sENe#)h%HO6Qr%*r%!n zRO3kH$)N@tENW3LuGeaPOh7GbD=Dp(eXnxXYUFd?u7lWka&5XxGaAq*vWiGJ(kB%C zAmgS8OBD*T@6{)gV}q=%PsUjSj~6UnS`3IL>4bBoOELm7Ow&G+@RXe=e}o^Wy%qa8 z9=FOBW9338>36!0N*DOooB&@r5emhCvGGQam<3SzRVoh!fquyQxAl z7F(gqK}Ow$Ju!7e#|6)J7!dx&5Uc3qbF!uS!$@Z>bJQ{fB)Jb?B89^2_%9yp+|1e} zH5oHK&+6b?_O73L+;*6Y56ksF(^ap(s~+Dv_261AjXT3dpf5>YC5J+}m9MImcAhhW zkE_(XJYGfb@Oha1`B#bE{6Ro7FnhU~eZNFAYw~8yCs7Q7Z=GheAe09Gi(U2bxRtu+ zTc@5RYN_6Dsa^p#W>cvi-#Yc6<8r;Ts`ttqPS9Vfr^zUW3$c^T~EMIb% zb?x_8OcpWm{F1nQR?^F|3;%alI@MTq@llt#^$!szm)Xtkm|)tJ9&uemYY48kWl`#R zwp-#U_E$G(O=?J!%<%nkfElk@ZTr)q!#j~&Lw1(~cpwqWHX(q=cJl_UbGN3oTNSf{ zRJBambq=VuKjfl^DaV&cR+2fcGbKzQ)tzXMvq8J&P1~mG6SfRu@C;B$_D{-flT-xr z

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

#hN`qM2*J3S3Q~L$@LKImSY5JsiY=SLqy1GZ=+h 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 z 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

`3NOTLxoS_b5pK9hR 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

A;~m+Z>T2W~?|*Wq~Jgl8nP- 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

xmL32)G$a5(G%fARr(iIY1VeW`>3MysUWRKpzvZ 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

O-&uQuW*h`dD;^Uiz`6Dpa_ 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

l3b(=T?Jbg|~#y@~9lk8u5TnbdEmkmn}m@HUaI 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

B2+lC5AOJ(dBd0AIUHq(PpB~p6&pG3{ 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ⅅ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 NK|e^t;`G`1e*w~!hAIF6 -- 2.54.0 From 5ec3a0cd54351494dfc64a4d91f72a6020505c1d Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Wed, 4 Mar 2026 16:33:51 +0000 Subject: [PATCH 71/79] std: update for language changes Now that zig1.wasm is updated, apply the matching standard library changes. The main one is in `std.builtin.Type`, where `alignment` fields now have type `?usize` rather than `comptime_int`. Additionally, we need to add explicit backing integers to some packed unions, because (due to https://github.com/ziglang/zig/issues/24714) they need explicit backing integers to be used in `extern` contexts. This change could not happen before now, because prior to this branch, packed unions did not allow explicit backing integer types (that is, this branch implemented https://github.com/ziglang/zig/issues/25350). --- lib/compiler/resinator/cvtres.zig | 2 +- lib/std/builtin.zig | 12 ++-- lib/std/c/darwin.zig | 2 +- lib/std/c/darwin/dispatch.zig | 2 +- lib/std/macho.zig | 2 +- lib/std/mem.zig | 16 +++-- lib/std/mem/Allocator.zig | 97 ++++++++++++++++--------------- lib/std/meta.zig | 2 +- lib/std/multi_array_list.zig | 4 +- lib/std/zon/parse.zig | 6 +- 10 files changed, 81 insertions(+), 64 deletions(-) diff --git a/lib/compiler/resinator/cvtres.zig b/lib/compiler/resinator/cvtres.zig index 26b6620af23224ab147ad7ceeafe802bfcb1ae46..6973be714c66540f51a6633ba8c9affff6085a26 100644 --- a/lib/compiler/resinator/cvtres.zig +++ b/lib/compiler/resinator/cvtres.zig @@ -410,7 +410,7 @@ pub const ResourceDirectoryTable = extern struct { }; pub const ResourceDirectoryEntry = extern struct { - entry: packed union { + entry: packed union(u32) { name_offset: packed struct(u32) { address: u31, /// This is undocumented in the PE/COFF spec, but the high bit diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index e10935f0c6a6fa15da09bf0611463a4d4347e6cc..00ae6199d1d9cdf96e8202a29b3f0b7385b5d387 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -592,8 +592,8 @@ pub const Type = union(enum) { size: Size, is_const: bool, is_volatile: bool, - /// TODO make this u16 instead of comptime_int - alignment: comptime_int, + /// `null` means implicit alignment, which is equivalent to `@alignOf(child)`. + alignment: ?usize, address_space: AddressSpace, child: type, is_allowzero: bool, @@ -670,7 +670,9 @@ pub const Type = union(enum) { /// See also: `defaultValue`. default_value_ptr: ?*const anyopaque, is_comptime: bool, - alignment: comptime_int, + /// `null` means the field alignment was not explicitly specified. The + /// field will still be aligned to at least `@alignOf` its `type`. + alignment: ?usize, /// Loads the field's default value from `default_value_ptr`. /// Returns `null` if the field has no default value. @@ -747,7 +749,9 @@ pub const Type = union(enum) { pub const UnionField = struct { name: [:0]const u8, type: type, - alignment: comptime_int, + /// `null` means the field alignment was not explicitly specified. The + /// field will still be aligned to at least `@alignOf` its `type`. + alignment: ?usize, /// This data structure is used by the Zig language code generation and /// therefore must be kept in sync with the compiler implementation. diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig index f18b61187c92fb2ddfb2ed4d4e922aaa957632fc..452411c52e94af5122ce5265edf95689f54f2b5c 100644 --- a/lib/std/c/darwin.zig +++ b/lib/std/c/darwin.zig @@ -436,7 +436,7 @@ pub const thread_state_flavor_t = c_int; pub const ipc_space_t = mach_port_t; pub const ipc_space_port_t = ipc_space_t; -pub const mach_msg_option_t = packed union { +pub const mach_msg_option_t = packed union(integer_t) { RCV: MACH.RCV, SEND: MACH.SEND, diff --git a/lib/std/c/darwin/dispatch.zig b/lib/std/c/darwin/dispatch.zig index 68b0b48782b02295064a6362b9ed0e249a92659e..770eadf7170f915d877d3d079c7d13b9585ae0a1 100644 --- a/lib/std/c/darwin/dispatch.zig +++ b/lib/std/c/darwin/dispatch.zig @@ -210,7 +210,7 @@ pub const source_timer_flags_t = packed struct(usize) { STRICT: bool = false, unused1: @Int(.unsigned, @bitSizeOf(usize) - 1) = 0, }; -pub const source_flags_t = packed union { +pub const source_flags_t = packed union(usize) { raw: usize, MACH_SEND: source_mach_send_flags_t, MACH_RECV: source_mach_recv_flags_t, diff --git a/lib/std/macho.zig b/lib/std/macho.zig index 57f892bdf7bb3f3be0c8b32a798b8fd305c14e15..9fdce9dd6605f450ab7eb9fee2b19b4f3787783d 100644 --- a/lib/std/macho.zig +++ b/lib/std/macho.zig @@ -851,7 +851,7 @@ pub const nlist = extern struct { pub const nlist_64 = extern struct { n_strx: u32, - n_type: packed union { + n_type: packed union(u8) { bits: packed struct(u8) { ext: bool, type: enum(u3) { diff --git a/lib/std/mem.zig b/lib/std/mem.zig index cc03e5b2c54ccd67ccefe7e854a4385f614f1dae..4b34ad12385bc77b2d67f988d60cde2d9a277027 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -38,6 +38,10 @@ pub const Alignment = enum(math.Log2Int(usize)) { return @enumFromInt(@ctz(n)); } + pub fn fromByteUnitsOptional(maybe_n: ?usize) ?Alignment { + return if (maybe_n) |n| .fromByteUnits(n) else null; + } + pub inline fn of(comptime T: type) Alignment { return comptime fromByteUnits(@alignOf(T)); } @@ -2287,8 +2291,8 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*)))); } else inline for (std.meta.fields(S)) |f| { switch (@typeInfo(f.type)) { - .@"struct" => byteSwapAllFieldsAligned(f.type, .fromByteUnits(f.alignment), &@field(ptr, f.name)), - .@"union", .array => byteSwapAllFieldsAligned(f.type, .fromByteUnits(f.alignment), &@field(ptr, f.name)), + .@"struct" => byteSwapAllFieldsAligned(f.type, .fromByteUnits(f.alignment orelse @alignOf(f.type)), &@field(ptr, f.name)), + .@"union", .array => byteSwapAllFieldsAligned(f.type, .fromByteUnits(f.alignment orelse @alignOf(f.type)), &@field(ptr, f.name)), .@"enum" => { @field(ptr, f.name) = @enumFromInt(@byteSwap(@intFromEnum(@field(ptr, f.name)))); }, @@ -4330,7 +4334,7 @@ pub fn alignPointerOffset(ptr: anytype, align_to: usize) ?usize { @compileError("expected many item pointer, got " ++ @typeName(T)); // Do nothing if the pointer is already well-aligned. - if (align_to <= info.pointer.alignment) + if (align_to <= info.pointer.alignment orelse @alignOf(info.pointer.child)) return 0; // Calculate the aligned base address with an eye out for overflow. @@ -4388,7 +4392,11 @@ fn CopyPtrAttrs( .@"const" = ptr.is_const, .@"volatile" = ptr.is_volatile, .@"allowzero" = ptr.is_allowzero, - .@"align" = ptr.alignment, + .@"align" = ptr.alignment orelse a: { + // If the new child is aligned differently than the old one, explicitly align the type. + const want = @alignOf(ptr.child); + break :a if (@alignOf(child) == want) null else want; + }, .@"addrspace" = ptr.address_space, }, child, null); } diff --git a/lib/std/mem/Allocator.zig b/lib/std/mem/Allocator.zig index db1ea978eaf21d31fa846db8dc591fb9749f746d..caf049f296fbc3f9a7fb1d92dc0dd0aa98e571ff 100644 --- a/lib/std/mem/Allocator.zig +++ b/lib/std/mem/Allocator.zig @@ -179,7 +179,11 @@ pub fn destroy(self: Allocator, ptr: anytype) void { const T = info.child; if (@sizeOf(T) == 0) return; const non_const_ptr = @as([*]u8, @ptrCast(@constCast(ptr))); - self.rawFree(non_const_ptr[0..@sizeOf(T)], .fromByteUnits(info.alignment), @returnAddress()); + self.rawFree( + non_const_ptr[0..@sizeOf(T)], + .fromByteUnits(info.alignment orelse @alignOf(T)), + @returnAddress(), + ); } /// Allocates an array of `n` items of type `T` and sets all the @@ -266,7 +270,7 @@ pub inline fn allocAdvancedWithRetAddr( n: usize, return_address: usize, ) Error![]align(if (alignment) |a| a.toByteUnits() else @alignOf(T)) T { - const a = comptime (alignment orelse Alignment.of(T)); + const a: Alignment = alignment orelse comptime .of(T); const ptr: [*]align(a.toByteUnits()) T = @ptrCast(try self.allocWithSizeAndAlignment(@sizeOf(T), a, n, return_address)); return ptr[0..n]; } @@ -278,7 +282,7 @@ fn allocWithSizeAndAlignment( n: usize, return_address: usize, ) Error![*]align(alignment.toByteUnits()) u8 { - const byte_count = math.mul(usize, size, n) catch return Error.OutOfMemory; + const byte_count = math.mul(usize, size, n) catch return error.OutOfMemory; return self.allocBytesWithAlignment(alignment, byte_count, return_address); } @@ -293,7 +297,7 @@ fn allocBytesWithAlignment( return @as([*]align(alignment.toByteUnits()) u8, @ptrFromInt(ptr)); } - const byte_ptr = self.rawAlloc(byte_count, alignment, return_address) orelse return Error.OutOfMemory; + const byte_ptr = self.rawAlloc(byte_count, alignment, return_address) orelse return error.OutOfMemory; @memset(byte_ptr[0..byte_count], undefined); return @alignCast(byte_ptr); } @@ -308,9 +312,9 @@ fn allocBytesWithAlignment( /// /// `new_len` may be zero, in which case the allocation is freed. pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { - const Slice = @typeInfo(@TypeOf(allocation)).pointer; - const T = Slice.child; - const alignment = Slice.alignment; + const slice_info = @typeInfo(@TypeOf(allocation)).pointer; + comptime assert(slice_info.size == .slice); + const T = slice_info.child; if (new_len == 0) { self.free(allocation); return true; @@ -323,7 +327,12 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { // on WebAssembly: https://github.com/ziglang/zig/issues/9660 //const new_len_bytes = new_len *| @sizeOf(T); const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return false; - return self.rawResize(old_memory, .fromByteUnits(alignment), new_len_bytes, @returnAddress()); + return self.rawResize( + old_memory, + .fromByteUnits(slice_info.alignment orelse @alignOf(T)), + new_len_bytes, + @returnAddress(), + ); } /// Request to modify the size of an allocation, allowing relocation. @@ -342,14 +351,11 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { /// `new_len` may be zero, in which case the allocation is freed. /// /// If the allocation's elements' type is zero bytes sized, `allocation.len` is set to `new_len`. -pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: { - const Slice = @typeInfo(@TypeOf(allocation)).pointer; - break :t ?[]align(Slice.alignment) Slice.child; -} { - const Slice = @typeInfo(@TypeOf(allocation)).pointer; - const T = Slice.child; +pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?@TypeOf(allocation) { + const slice_info = @typeInfo(@TypeOf(allocation)).pointer; + comptime assert(slice_info.size == .slice); + const T = slice_info.child; - const alignment = Slice.alignment; if (new_len == 0) { self.free(allocation); return allocation[0..0]; @@ -367,9 +373,13 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: { // on WebAssembly: https://github.com/ziglang/zig/issues/9660 //const new_len_bytes = new_len *| @sizeOf(T); const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return null; - const new_ptr = self.rawRemap(old_memory, .fromByteUnits(alignment), new_len_bytes, @returnAddress()) orelse return null; - const new_memory: []align(alignment) u8 = @alignCast(new_ptr[0..new_len_bytes]); - return mem.bytesAsSlice(T, new_memory); + const new_ptr = self.rawRemap( + old_memory, + .fromByteUnits(slice_info.alignment orelse @alignOf(T)), + new_len_bytes, + @returnAddress(), + ) orelse return null; + return @ptrCast(@alignCast(new_ptr[0..new_len_bytes])); } /// This function requests a new size for an existing allocation, which @@ -386,10 +396,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: { /// do the realloc more efficiently than the caller /// * `resize` which returns `false` when the `Allocator` implementation cannot /// change the size without relocating the allocation. -pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) t: { - const Slice = @typeInfo(@TypeOf(old_mem)).pointer; - break :t Error![]align(Slice.alignment) Slice.child; -} { +pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) Error!@TypeOf(old_mem) { return self.reallocAdvanced(old_mem, new_n, @returnAddress()); } @@ -398,51 +405,49 @@ pub fn reallocAdvanced( old_mem: anytype, new_n: usize, return_address: usize, -) t: { - const Slice = @typeInfo(@TypeOf(old_mem)).pointer; - break :t Error![]align(Slice.alignment) Slice.child; -} { - const Slice = @typeInfo(@TypeOf(old_mem)).pointer; - const T = Slice.child; +) Error!@TypeOf(old_mem) { + const slice_info = @typeInfo(@TypeOf(old_mem)).pointer; + comptime assert(slice_info.size == .slice); + const T = slice_info.child; if (old_mem.len == 0) { - return self.allocAdvancedWithRetAddr(T, .fromByteUnits(Slice.alignment), new_n, return_address); + return self.allocAdvancedWithRetAddr(T, .fromByteUnitsOptional(slice_info.alignment), new_n, return_address); } if (new_n == 0) { self.free(old_mem); - const ptr = comptime std.mem.alignBackward(usize, math.maxInt(usize), Slice.alignment); - return @as([*]align(Slice.alignment) T, @ptrFromInt(ptr))[0..0]; + const alignment = slice_info.alignment orelse @alignOf(T); + const addr = comptime std.mem.alignBackward(usize, math.maxInt(usize), alignment); + const ptr: *align(alignment) [0]T = @ptrFromInt(addr); + return ptr; } const old_byte_slice = mem.sliceAsBytes(old_mem); - const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return Error.OutOfMemory; + const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return error.OutOfMemory; // Note: can't set shrunk memory to undefined as memory shouldn't be modified on realloc failure - if (self.rawRemap(old_byte_slice, .fromByteUnits(Slice.alignment), byte_count, return_address)) |p| { - const new_bytes: []align(Slice.alignment) u8 = @alignCast(p[0..byte_count]); - return mem.bytesAsSlice(T, new_bytes); + if (self.rawRemap(old_byte_slice, .fromByteUnits(slice_info.alignment orelse @alignOf(T)), byte_count, return_address)) |p| { + return @ptrCast(@alignCast(p[0..byte_count])); } - const new_mem = self.rawAlloc(byte_count, .fromByteUnits(Slice.alignment), return_address) orelse + const new_mem = self.rawAlloc(byte_count, .fromByteUnits(slice_info.alignment orelse @alignOf(T)), return_address) orelse return error.OutOfMemory; const copy_len = @min(byte_count, old_byte_slice.len); @memcpy(new_mem[0..copy_len], old_byte_slice[0..copy_len]); @memset(old_byte_slice, undefined); - self.rawFree(old_byte_slice, .fromByteUnits(Slice.alignment), return_address); + self.rawFree(old_byte_slice, .fromByteUnits(slice_info.alignment orelse @alignOf(T)), return_address); - const new_bytes: []align(Slice.alignment) u8 = @alignCast(new_mem[0..byte_count]); - return mem.bytesAsSlice(T, new_bytes); + return @ptrCast(@alignCast(new_mem[0..byte_count])); } /// Free an array allocated with `alloc`. /// If memory has length 0, free is a no-op. /// To free a single item, see `destroy`. pub fn free(self: Allocator, memory: anytype) void { - const Slice = @typeInfo(@TypeOf(memory)).pointer; - const bytes = mem.sliceAsBytes(memory); - const bytes_len = bytes.len + if (Slice.sentinel() != null) @sizeOf(Slice.child) else 0; - if (bytes_len == 0) return; - const non_const_ptr = @constCast(bytes.ptr); - @memset(non_const_ptr[0..bytes_len], undefined); - self.rawFree(non_const_ptr[0..bytes_len], .fromByteUnits(Slice.alignment), @returnAddress()); + const slice_info = @typeInfo(@TypeOf(memory)).pointer; + comptime assert(slice_info.size == .slice); + const mem_with_sent = memory[0 .. memory.len + @intFromBool(slice_info.sentinel() != null)]; + const bytes: []u8 = @ptrCast(@constCast(mem_with_sent)); + if (bytes.len == 0) return; + @memset(bytes, undefined); + self.rawFree(bytes, .fromByteUnits(slice_info.alignment orelse @alignOf(slice_info.child)), @returnAddress()); } /// Copies `m` to newly allocated memory. Caller owns the memory. diff --git a/lib/std/meta.zig b/lib/std/meta.zig index 6236f1a56bfc9c841044d35362699d555df19cff..632c65678f28107c8f20444c68a74d27cae02309 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -63,7 +63,7 @@ pub fn alignment(comptime T: type) comptime_int { .pointer, .@"fn" => alignment(info.child), else => @alignOf(T), }, - .pointer => |info| info.alignment, + .pointer => |info| info.alignment orelse @alignOf(info.child), else => @alignOf(T), }; } diff --git a/lib/std/multi_array_list.zig b/lib/std/multi_array_list.zig index 92d094f0cc93e96600b03d33f46db1c298c159c1..fde7e93ed652c3d6d360516e9441ece0ca88dacc 100644 --- a/lib/std/multi_array_list.zig +++ b/lib/std/multi_array_list.zig @@ -194,9 +194,9 @@ pub fn MultiArrayList(comptime T: type) type { data[i] = .{ .size = @sizeOf(field_info.type), .size_index = i, - .alignment = if (@sizeOf(field_info.type) == 0) 1 else field_info.alignment, + .alignment = field_info.alignment orelse @alignOf(field_info.type), }; - big_align = @max(big_align, @alignOf(field_info.type)); + big_align = @max(big_align, data[i].alignment); } const Sort = struct { fn lessThan(context: void, lhs: Data, rhs: Data) bool { diff --git a/lib/std/zon/parse.zig b/lib/std/zon/parse.zig index 3527f03342b64f5c6f19bad7e163873aeeabcd2b..9f492ddbea6eafdf1841d86cb0d9f383c42b8638 100644 --- a/lib/std/zon/parse.zig +++ b/lib/std/zon/parse.zig @@ -591,7 +591,7 @@ const Parser = struct { if (pointer.child == u8 and pointer.is_const and (pointer.sentinel() == null or pointer.sentinel() == 0) and - pointer.alignment == 1) + (pointer.alignment == null or pointer.alignment == 1)) { if (opt) { return self.failNode(node, "expected optional string"); @@ -717,7 +717,7 @@ const Parser = struct { pointer.size != .slice or !pointer.is_const or (pointer.sentinel() != null and pointer.sentinel() != 0) or - pointer.alignment != 1) + (pointer.alignment != null and pointer.alignment != 1)) { return error.WrongType; } @@ -742,7 +742,7 @@ const Parser = struct { const slice = try self.gpa.allocWithOptions( pointer.child, nodes.len, - .fromByteUnits(pointer.alignment), + .fromByteUnitsOptional(pointer.alignment), pointer.sentinel(), ); errdefer self.gpa.free(slice); -- 2.54.0 From ce1f28a7497903cf00431d6976c162c37683232a Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Wed, 4 Mar 2026 16:34:09 +0000 Subject: [PATCH 72/79] behavior: update for `std.builtin.Type` changes --- test/behavior/tuple_declarations.zig | 4 ++-- test/behavior/type_info.zig | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/behavior/tuple_declarations.zig b/test/behavior/tuple_declarations.zig index 643d79baa1c84073b106b70cdd3fc5509f4e0c42..cc87913975fdd126f85239fa83765d34f7d5c80c 100644 --- a/test/behavior/tuple_declarations.zig +++ b/test/behavior/tuple_declarations.zig @@ -22,13 +22,13 @@ test "tuple declaration type info" { try expect(info.fields[0].type == u32); try expect(info.fields[0].defaultValue() == 1); try expect(info.fields[0].is_comptime); - try expect(info.fields[0].alignment == @alignOf(u32)); + try expect(info.fields[0].alignment == null); try expectEqualStrings(info.fields[1].name, "1"); try expect(info.fields[1].type == []const u8); try expect(info.fields[1].defaultValue() == null); try expect(!info.fields[1].is_comptime); - try expect(info.fields[1].alignment == @alignOf([]const u8)); + try expect(info.fields[1].alignment == null); } } diff --git a/test/behavior/type_info.zig b/test/behavior/type_info.zig index 48b10c458aa325007a6975dbf78373248d717ee3..cd1455e5235a5bacd1a783f2309a0c4fe30839bd 100644 --- a/test/behavior/type_info.zig +++ b/test/behavior/type_info.zig @@ -82,7 +82,7 @@ fn testPointer() !void { try expect(u32_ptr_info.pointer.size == .one); try expect(u32_ptr_info.pointer.is_const == false); try expect(u32_ptr_info.pointer.is_volatile == false); - try expect(u32_ptr_info.pointer.alignment == @alignOf(u32)); + try expect(u32_ptr_info.pointer.alignment == null); try expect(u32_ptr_info.pointer.child == u32); try expect(u32_ptr_info.pointer.sentinel() == null); } @@ -99,7 +99,7 @@ fn testUnknownLenPtr() !void { try expect(u32_ptr_info.pointer.is_const == true); try expect(u32_ptr_info.pointer.is_volatile == true); try expect(u32_ptr_info.pointer.sentinel() == null); - try expect(u32_ptr_info.pointer.alignment == @alignOf(f64)); + try expect(u32_ptr_info.pointer.alignment == null); try expect(u32_ptr_info.pointer.child == f64); } @@ -130,7 +130,7 @@ fn testSlice() !void { try expect(u32_slice_info.pointer.size == .slice); try expect(u32_slice_info.pointer.is_const == false); try expect(u32_slice_info.pointer.is_volatile == false); - try expect(u32_slice_info.pointer.alignment == 4); + try expect(u32_slice_info.pointer.alignment == null); try expect(u32_slice_info.pointer.child == u32); } @@ -266,9 +266,9 @@ fn testUnion() !void { try expect(notag_union_info.@"union".tag_type == null); try expect(notag_union_info.@"union".layout == .auto); try expect(notag_union_info.@"union".fields.len == 2); - try expect(notag_union_info.@"union".fields[0].alignment == @alignOf(void)); + try expect(notag_union_info.@"union".fields[0].alignment == null); try expect(notag_union_info.@"union".fields[1].type == u32); - try expect(notag_union_info.@"union".fields[1].alignment == @alignOf(u32)); + try expect(notag_union_info.@"union".fields[1].alignment == null); const TestExternUnion = extern union { foo: *anyopaque, @@ -292,7 +292,7 @@ fn testStruct() !void { const unpacked_struct_info = @typeInfo(TestStruct); try expect(unpacked_struct_info.@"struct".is_tuple == false); try expect(unpacked_struct_info.@"struct".backing_integer == null); - try expect(unpacked_struct_info.@"struct".fields[0].alignment == @alignOf(u32)); + try expect(unpacked_struct_info.@"struct".fields[0].alignment == null); try expect(unpacked_struct_info.@"struct".fields[0].defaultValue().? == 4); try expect(mem.eql(u8, "foobar", unpacked_struct_info.@"struct".fields[1].defaultValue().?)); } @@ -314,11 +314,11 @@ fn testPackedStruct() !void { try expect(struct_info.@"struct".layout == .@"packed"); try expect(struct_info.@"struct".backing_integer == u128); try expect(struct_info.@"struct".fields.len == 4); - try expect(struct_info.@"struct".fields[0].alignment == 0); + try expect(struct_info.@"struct".fields[0].alignment == null); try expect(struct_info.@"struct".fields[2].type == f32); try expect(struct_info.@"struct".fields[2].defaultValue() == null); try expect(struct_info.@"struct".fields[3].defaultValue().? == 4); - try expect(struct_info.@"struct".fields[3].alignment == 0); + try expect(struct_info.@"struct".fields[3].alignment == null); try expect(struct_info.@"struct".decls.len == 1); } -- 2.54.0 From 34d780f4bbefa8344cae5da49fe84bed83d8274f Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Thu, 5 Mar 2026 22:13:22 +0000 Subject: [PATCH 73/79] langref: update for language changes --- doc/langref.html.in | 5 +++-- doc/langref/test_comptime_invalid_error_code.zig | 7 ++----- doc/langref/test_missized_packed_struct.zig | 2 +- doc/langref/test_variable_alignment.zig | 15 ++++++++++----- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index e87decdf4a9ab51de65bc8ae0c8d6a8378b47dcd..643c948b68e99e11236f9c24e180af848736a820 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2103,8 +2103,9 @@ or less than {#syntax#}1 << 29{#endsyntax#}.

- In Zig, a pointer type has an alignment value. If the value is equal to the - alignment of the underlying type, it can be omitted from the type: + Pointer types may explicitly specify an alignment in bytes. If it is not + specified, the alignment is assumed to be equal to the alignment of the + underlying type.

{#code|test_variable_alignment.zig#} diff --git a/doc/langref/test_comptime_invalid_error_code.zig b/doc/langref/test_comptime_invalid_error_code.zig index ebc6314764b399fcbbb5a1b03225e4d9611f5f21..e4fedf5812a972af6168e26c7689de92a204165c 100644 --- a/doc/langref/test_comptime_invalid_error_code.zig +++ b/doc/langref/test_comptime_invalid_error_code.zig @@ -1,8 +1,5 @@ comptime { - const err = error.AnError; - const number = @intFromError(err) + 10; - const invalid_err = @errorFromInt(number); - _ = invalid_err; + _ = @errorFromInt(12345); } -// test_error=integer value '11' represents no error +// test_error=integer value '12345' represents no error diff --git a/doc/langref/test_missized_packed_struct.zig b/doc/langref/test_missized_packed_struct.zig index 791f97cc311b6f33b5859e1612c684cde6d0d6c3..df323244d4bebdf34dd6dde9bdbdfe6d8720dfd2 100644 --- a/doc/langref/test_missized_packed_struct.zig +++ b/doc/langref/test_missized_packed_struct.zig @@ -3,4 +3,4 @@ test "missized packed struct" { _ = S{ .a = 4, .b = 2 }; } -// test_error=backing integer type 'u32' has bit size 32 but the struct fields have a total bit size of 24 +// test_error=backing integer bit width does not match total bit width of fields diff --git a/doc/langref/test_variable_alignment.zig b/doc/langref/test_variable_alignment.zig index 01768e29eb0e81d5924644fbbbbd6739047fb690..d0a4560fa2954930d7d2f460c2d74d6b64b0d3cf 100644 --- a/doc/langref/test_variable_alignment.zig +++ b/doc/langref/test_variable_alignment.zig @@ -1,15 +1,20 @@ const std = @import("std"); const builtin = @import("builtin"); +const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; test "variable alignment" { var x: i32 = 1234; - const align_of_i32 = @alignOf(@TypeOf(x)); + try expectEqual(*i32, @TypeOf(&x)); - try expectEqual(*align(align_of_i32) i32, *i32); - if (builtin.target.cpu.arch == .x86_64) { - try expectEqual(4, @typeInfo(*i32).pointer.alignment); - } + + try expect(@intFromPtr(&x) % @alignOf(i32) == 0); + + // The implicitly-aligned pointer can be coerced to be explicitly-aligned to + // the alignment of the underlying type `i32`: + const ptr: *align(@alignOf(i32)) i32 = &x; + + try expectEqual(1234, ptr.*); } // test -- 2.54.0 From 1293f080fdfc74966b541b44f0a907561df3d617 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Fri, 6 Mar 2026 12:47:11 +0000 Subject: [PATCH 74/79] build.zig: bump max_rss values --- build.zig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.zig b/build.zig index 06ba1aab65bb127957fb1abb3ba8dafc3d40db9d..4e6efa41a6e6dbca14bf3d37f17117a61f1fcb85 100644 --- a/build.zig +++ b/build.zig @@ -568,7 +568,7 @@ pub fn build(b: *std.Build) !void { .skip_linux = skip_linux, .skip_llvm = skip_llvm, .skip_libc = skip_libc, - .max_rss = 8_500_000_000, + .max_rss = 9_300_000_000, })); const unit_tests_step = b.step("test-unit", "Run the compiler source unit tests"); @@ -584,7 +584,7 @@ pub fn build(b: *std.Build) !void { .use_llvm = use_llvm, .use_lld = use_llvm, .zig_lib_dir = b.path("lib"), - .max_rss = 2_500_000_000, + .max_rss = 2_700_000_000, }); if (link_libc) { unit_tests.root_module.link_libc = true; @@ -611,7 +611,7 @@ pub fn build(b: *std.Build) !void { .skip_linux = skip_linux, .skip_llvm = skip_llvm, .skip_release = skip_release, - .max_rss = 3_000_000_000, + .max_rss = 3_300_000_000, })); test_step.dependOn(tests.addLinkTests(b, enable_macos_sdk, enable_ios_sdk, enable_symlinks_windows)); test_step.dependOn(tests.addStackTraceTests(b, test_filters, skip_non_native)); @@ -767,7 +767,7 @@ fn addCompilerMod(b: *std.Build, options: AddCompilerModOptions) *std.Build.Modu fn addCompilerStep(b: *std.Build, options: AddCompilerModOptions) *std.Build.Step.Compile { const exe = b.addExecutable(.{ .name = "zig", - .max_rss = 7_900_000_000, + .max_rss = 8_700_000_000, .root_module = addCompilerMod(b, options), }); exe.stack_size = stack_size; -- 2.54.0 From f92b998f9fe985d554d6078bb2bb11d094d94b91 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Fri, 6 Mar 2026 16:30:56 +0000 Subject: [PATCH 75/79] behavior: disable some tests under the C backend targeting MSVC The bugs here actually exist on master branch too, but they are being caught by the new static assertions which check type size and alignment. It turns out that MSVC's struct/union "pack" pragma and its "align" declspec interact in undocumented ways which are extremely problematic for generated code. Solving this will require changing how the C backend lowers various types; the disabled tests are all tagged unions, but there are also issues with structs with underaligned fields which the behavior tests just happen to not currently be triggering. --- test/behavior/align.zig | 1 + test/behavior/union.zig | 2 ++ 2 files changed, 3 insertions(+) diff --git a/test/behavior/align.zig b/test/behavior/align.zig index a59bed56ba8c4e46892b25ca834cf7f45e54ec21..550d7008b419474cbb9b207fc2b22fcd5549960f 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -18,6 +18,7 @@ test "global variable alignment" { test "large alignment of local constant" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // flaky + if (builtin.zig_backend == .stage2_c and builtin.target.abi == .msvc) return error.SkipZigTest; const x: f32 align(128) = 12.34; try std.testing.expect(@intFromPtr(&x) % 128 == 0); diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 9badc9dabd11bd6709c95ae32ba755f6cc3b9bd2..faa3f42ea5f8f1415efdf5dcf2b887a0ba0066c4 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -148,6 +148,7 @@ const err = @as(anyerror!Agg, Agg{ const array = [_]Value{ v1, v2, v1, v2 }; test "unions embedded in aggregate types" { + if (builtin.zig_backend == .stage2_c and builtin.target.abi == .msvc) return error.SkipZigTest; switch (array[1]) { Value.Array => |arr| try expect(arr[4] == 3), else => unreachable, @@ -2022,6 +2023,7 @@ test "runtime union init, most-aligned field != largest" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c and builtin.target.abi == .msvc) return error.SkipZigTest; const U = union(enum) { x: u128, -- 2.54.0 From a3d2f2999f9708cbcc6f3082547b5f68a3b593cd Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 8 Mar 2026 16:18:18 +0000 Subject: [PATCH 76/79] tests: add new tests Some for bugs which have been fixed, some for language changes. --- test/behavior/alignof.zig | 5 ++ test/behavior/enum.zig | 15 ++++++ test/behavior/error.zig | 33 ++++++++++++ test/behavior/packed-union.zig | 22 ++++++++ test/behavior/struct.zig | 51 +++++++++++++++++++ test/behavior/tuple.zig | 11 ++++ .../compile_errors/enum_uses_own_typeinfo.zig | 15 ++++++ ...enum_without_explicit_integer_tag_type.zig | 4 +- ...mpatible_but_inferred_integer_tag_type.zig | 45 ---------------- ...non-extern-compatible_integer_tag_type.zig | 4 +- .../fn_type_returning_pointer_to_itself.zig | 8 +++ ...h_non-extern_non-packed_enum_parameter.zig | 4 +- ...mplicit_backing_type_in_extern_context.zig | 51 +++++++++++++++++++ .../packed_struct_uses_own_size.zig | 10 ++++ .../packed_struct_uses_own_typeinfo.zig | 13 +++++ .../compile_errors/simple_struct_loop.zig | 16 ++++++ test/cases/compile_errors/sizeOf_bad_type.zig | 4 ++ ...truct_field_queries_hasfield_of_itself.zig | 14 +++++ ...ed_type_which_queries_struct_alignment.zig | 13 +++++ .../struct_uses_sizeof_self_as_array_len.zig | 10 ++++ 20 files changed, 297 insertions(+), 51 deletions(-) create mode 100644 test/cases/compile_errors/enum_uses_own_typeinfo.zig delete mode 100644 test/cases/compile_errors/extern_struct_with_extern-compatible_but_inferred_integer_tag_type.zig create mode 100644 test/cases/compile_errors/fn_type_returning_pointer_to_itself.zig create mode 100644 test/cases/compile_errors/implicit_backing_type_in_extern_context.zig create mode 100644 test/cases/compile_errors/packed_struct_uses_own_size.zig create mode 100644 test/cases/compile_errors/packed_struct_uses_own_typeinfo.zig create mode 100644 test/cases/compile_errors/simple_struct_loop.zig create mode 100644 test/cases/compile_errors/struct_field_queries_hasfield_of_itself.zig create mode 100644 test/cases/compile_errors/struct_uses_reified_type_which_queries_struct_alignment.zig create mode 100644 test/cases/compile_errors/struct_uses_sizeof_self_as_array_len.zig diff --git a/test/behavior/alignof.zig b/test/behavior/alignof.zig index 7adec6168fa79169d21894fe63116f32b49c286d..f8914ead80b5dc4ee8eed3039e0ad96d7f880961 100644 --- a/test/behavior/alignof.zig +++ b/test/behavior/alignof.zig @@ -39,3 +39,8 @@ test "correct alignment for elements and slices of aligned array" { try expect(@alignOf(@TypeOf(&buf[start..end])) == @alignOf(*u8)); try expect(@alignOf(@TypeOf(&buf[start])) == @alignOf(*u8)); } + +test "@alignOf(anyerror!noreturn)" { + try expect(@alignOf(anyerror!noreturn) == @alignOf(anyerror)); + try expect(@alignOf(anyerror!anyerror!noreturn) == @alignOf(anyerror)); +} diff --git a/test/behavior/enum.zig b/test/behavior/enum.zig index 4dd5ae08da6e0bf73f81b148ae060c99b7ca2be2..9ec1ed8c35b920957ed77582a56775c6b0618519 100644 --- a/test/behavior/enum.zig +++ b/test/behavior/enum.zig @@ -1354,3 +1354,18 @@ test "empty enum passed as argument" { }; E.f(@as(E, undefined)); } + +test "enum int tag type uses declaration inside the enum" { + const static = struct { + const E = enum(E.IntTag) { + const IntTag = u8; + a, + b, + c, + }; + }; + try expect(@sizeOf(static.E) == @sizeOf(u8)); + const val: static.E = .b; + try expect(val == .b); + try expect(@intFromEnum(val) == 1); +} diff --git a/test/behavior/error.zig b/test/behavior/error.zig index d74a7668a97eb29982a0ebf50a87948b8a629ee5..0679736ac34d478cdaa2212e4836670ce9d3fabb 100644 --- a/test/behavior/error.zig +++ b/test/behavior/error.zig @@ -1109,3 +1109,36 @@ test "'if' ignores error via local while 'else' ignores error directly" { try S.testOne(false); try S.testOne(true); } + +test "@errorCast into own inferred error set" { + const static = struct { + fn foo(b: bool) !void { + if (b) { + return @errorCast(error.Bad); + } + } + }; + try static.foo(false); + if (static.foo(true)) { + return error.ExpectedError; + } else |err| { + try expect(err == error.Bad); + } + + const errors = @typeInfo(@typeInfo(@TypeOf(static.foo(false))).error_union.error_set).error_set.?; + comptime assert(errors.len == 1); + comptime assert(std.mem.eql(u8, errors[0].name, "Bad")); +} + +test "@errorCast into other inferred error set" { + const static = struct { + fn foo() !void { + return error.Bad; + } + }; + const Ies = @typeInfo(@TypeOf(static.foo())).error_union.error_set; + const err: Ies = @errorCast(error.Bad); + try expect(err == error.Bad); + const non_err: Ies!u32 = @errorCast(@as(error{}!u32, 123)); + try expect(try non_err == 123); +} diff --git a/test/behavior/packed-union.zig b/test/behavior/packed-union.zig index f625c8b0733ba6b0819feaf568ab6e4796f6cf47..330a4853b13383b05fc4b7363c8b35e916085d9f 100644 --- a/test/behavior/packed-union.zig +++ b/test/behavior/packed-union.zig @@ -1,6 +1,7 @@ const std = @import("std"); const builtin = @import("builtin"); const assert = std.debug.assert; +const expect = std.testing.expect; const expectEqual = std.testing.expectEqual; test "flags in packed union" { @@ -177,3 +178,24 @@ test "assigning to non-active field at comptime" { test_bits.bits = .{}; } } + +test "packed union with explicit backing integer" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; + + const U = packed union(i32) { + raw: i32, + unsigned_halves: packed struct { low: u16, high: u16 }, + + fn check(val: @This()) !void { + try expect(@as(i32, @bitCast(val)) == -2); + try expect(@as(u32, @bitCast(val)) == 0xFFFFFFFE); + try expect(val.raw == -2); + try expect(val.unsigned_halves.low == 0xFFFE); + try expect(val.unsigned_halves.high == 0xFFFF); + } + }; + try U.check(.{ .raw = -2 }); + try comptime U.check(.{ .raw = -2 }); +} diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index e6a355864629600f6294492ee11e4cf7c73f5674..3c2d01f6a4014556c4b87ef66a804e5eacb381af 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -2254,3 +2254,54 @@ test "runtime-known slice of comptime-only struct" { .{ .index = 15, .T = Mixed }, }); } + +test "struct contains aligned pointer to itself through type decl" { + const Slab = struct { + const Ptr = *align(64) const @This(); + next: Ptr, + }; + // We intentionally use `Slab.Ptr` before `Slab`. + var ptr: Slab.Ptr = undefined; + var slab: Slab align(64) = undefined; + ptr = &slab; + slab.next = ptr; + + try expect(ptr == &slab); + try expect(slab.next == &slab); + try expect(slab.next.next == &slab); + try expect(slab.next.next.next == &slab); +} + +test "struct contains underaligned field with overaligned pointer to itself" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + const S = struct { + ptr: *align(8) @This() align(1), + }; + var val: S align(8) = undefined; + val.ptr = &val; + try expect(val.ptr == &val); + try expect(val.ptr.ptr == &val); + try expect(val.ptr.ptr.ptr == &val); +} + +test "struct contains pointer to function accepting that struct" { + const S = struct { + const FnPtr = ?*const fn (@This()) void; + fn_ptr: FnPtr, + }; + const dummy_fn_ptr: S.FnPtr = @ptrFromInt(0x100000); + const dummy_s: S = .{ .fn_ptr = dummy_fn_ptr }; + try expect(dummy_s.fn_ptr == dummy_fn_ptr); + try expect(@TypeOf(dummy_s.fn_ptr.?) == *const fn (S) void); +} + +test "struct queries typeinfo of struct containing pointer back to first struct" { + const static = struct { + const A = struct { b: *B }; + const B = struct { a: T: { + _ = @typeInfo(A); + break :T u32; + } }; + }; + _ = @as(static.A, undefined); +} diff --git a/test/behavior/tuple.zig b/test/behavior/tuple.zig index a88a99171b9ed3e7106d48abf76f1c57afce0da0..75cf4515a514512b24fff32410d0d3ccb397552c 100644 --- a/test/behavior/tuple.zig +++ b/test/behavior/tuple.zig @@ -592,3 +592,14 @@ test "array of tuples that end with a zero-bit field followed by padding" { try expect(S.foo[1][1] == 4); try expect(S.foo[1][2] == {}); } + +test "call function at comptime through container-level const tuple" { + const static = struct { + const MyTuple = struct { (fn () u32) }; + const val: MyTuple = .{foo}; + fn foo() u32 { + return 1234; + } + }; + comptime assert(static.val[0]() == 1234); +} diff --git a/test/cases/compile_errors/enum_uses_own_typeinfo.zig b/test/cases/compile_errors/enum_uses_own_typeinfo.zig new file mode 100644 index 0000000000000000000000000000000000000000..5906ba6bcb386e4f36bb1f7d343675e5ba8c248e --- /dev/null +++ b/test/cases/compile_errors/enum_uses_own_typeinfo.zig @@ -0,0 +1,15 @@ +const E = enum(u9) { + const a_val: @typeInfo(E).@"enum".tag_type = 0; + a = a_val, +}; +comptime { + _ = E.a; +} + +// error +// +// error: dependency loop with length 3 +// :3:9: note: type 'tmp.E' uses value of declaration 'tmp.E.a_val' here +// :2:50: note: value of declaration 'tmp.E.a_val' uses type of declaration 'tmp.E.a_val' here +// :2:18: note: type of declaration 'tmp.E.a_val' depends on type 'tmp.E' for type information query here +// note: eliminate any one of these dependencies to break the loop diff --git a/test/cases/compile_errors/exported_enum_without_explicit_integer_tag_type.zig b/test/cases/compile_errors/exported_enum_without_explicit_integer_tag_type.zig index 3ff9961de81d96f945efd09d7eee724ca0bcaf2c..aa79ee1ad631d7658cd64346ad84d8fe531db306 100644 --- a/test/cases/compile_errors/exported_enum_without_explicit_integer_tag_type.zig +++ b/test/cases/compile_errors/exported_enum_without_explicit_integer_tag_type.zig @@ -11,6 +11,6 @@ comptime { // // :3:5: error: unable to export type 'type' // :7:5: error: unable to export type 'tmp.E' -// :7:5: note: enum tag type 'u1' is not extern compatible -// :7:5: note: only integers with 0, 8, 16, 32, 64 and 128 bits are extern compatible +// :1:11: note: integer tag type of enum is inferred +// :1:11: note: consider explicitly specifying the integer tag type // :1:11: note: enum declared here diff --git a/test/cases/compile_errors/extern_struct_with_extern-compatible_but_inferred_integer_tag_type.zig b/test/cases/compile_errors/extern_struct_with_extern-compatible_but_inferred_integer_tag_type.zig deleted file mode 100644 index a0e476f087629eb0e720a4f06e8db692d46508e6..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/extern_struct_with_extern-compatible_but_inferred_integer_tag_type.zig +++ /dev/null @@ -1,45 +0,0 @@ -// zig fmt: off -pub const E = enum { -@"0",@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"10",@"11",@"12", -@"13",@"14",@"15",@"16",@"17",@"18",@"19",@"20",@"21",@"22",@"23", -@"24",@"25",@"26",@"27",@"28",@"29",@"30",@"31",@"32",@"33",@"34", -@"35",@"36",@"37",@"38",@"39",@"40",@"41",@"42",@"43",@"44",@"45", -@"46",@"47",@"48",@"49",@"50",@"51",@"52",@"53",@"54",@"55",@"56", -@"57",@"58",@"59",@"60",@"61",@"62",@"63",@"64",@"65",@"66",@"67", -@"68",@"69",@"70",@"71",@"72",@"73",@"74",@"75",@"76",@"77",@"78", -@"79",@"80",@"81",@"82",@"83",@"84",@"85",@"86",@"87",@"88",@"89", -@"90",@"91",@"92",@"93",@"94",@"95",@"96",@"97",@"98",@"99",@"100", -@"101",@"102",@"103",@"104",@"105",@"106",@"107",@"108",@"109", -@"110",@"111",@"112",@"113",@"114",@"115",@"116",@"117",@"118", -@"119",@"120",@"121",@"122",@"123",@"124",@"125",@"126",@"127", -@"128",@"129",@"130",@"131",@"132",@"133",@"134",@"135",@"136", -@"137",@"138",@"139",@"140",@"141",@"142",@"143",@"144",@"145", -@"146",@"147",@"148",@"149",@"150",@"151",@"152",@"153",@"154", -@"155",@"156",@"157",@"158",@"159",@"160",@"161",@"162",@"163", -@"164",@"165",@"166",@"167",@"168",@"169",@"170",@"171",@"172", -@"173",@"174",@"175",@"176",@"177",@"178",@"179",@"180",@"181", -@"182",@"183",@"184",@"185",@"186",@"187",@"188",@"189",@"190", -@"191",@"192",@"193",@"194",@"195",@"196",@"197",@"198",@"199", -@"200",@"201",@"202",@"203",@"204",@"205",@"206",@"207",@"208", -@"209",@"210",@"211",@"212",@"213",@"214",@"215",@"216",@"217", -@"218",@"219",@"220",@"221",@"222",@"223",@"224",@"225",@"226", -@"227",@"228",@"229",@"230",@"231",@"232",@"233",@"234",@"235", -@"236",@"237",@"238",@"239",@"240",@"241",@"242",@"243",@"244", -@"245",@"246",@"247",@"248",@"249",@"250",@"251",@"252",@"253", -@"254",@"255", @"256" -}; -// zig fmt: on -pub const S = extern struct { - e: E, -}; -export fn entry() void { - const s: S = undefined; - _ = s; -} - -// error -// -// :33:8: error: extern structs cannot contain fields of type 'tmp.E' -// :33:8: note: enum tag type 'u9' is not extern compatible -// :33:8: note: only integers with 0 or power of two bits are extern compatible -// :2:15: note: enum declared here diff --git a/test/cases/compile_errors/extern_struct_with_non-extern-compatible_integer_tag_type.zig b/test/cases/compile_errors/extern_struct_with_non-extern-compatible_integer_tag_type.zig index 373f10444d3ce322d0c3822a031461a74c2d97ed..fdf0f9aadd08021eb5a34367e80b93ade4ea1b3b 100644 --- a/test/cases/compile_errors/extern_struct_with_non-extern-compatible_integer_tag_type.zig +++ b/test/cases/compile_errors/extern_struct_with_non-extern-compatible_integer_tag_type.zig @@ -10,6 +10,6 @@ export fn entry() void { // error // // :3:8: error: extern structs cannot contain fields of type 'tmp.E' -// :3:8: note: enum tag type 'u31' is not extern compatible -// :3:8: note: only integers with 0 or power of two bits are extern compatible +// :1:15: note: enum tag type 'u31' is not extern compatible +// :1:15: note: only integers with 0 or power of two bits are extern compatible // :1:15: note: enum declared here diff --git a/test/cases/compile_errors/fn_type_returning_pointer_to_itself.zig b/test/cases/compile_errors/fn_type_returning_pointer_to_itself.zig new file mode 100644 index 0000000000000000000000000000000000000000..4afacccc8d813ddaa9a7cdd0e2641e4f6d492de0 --- /dev/null +++ b/test/cases/compile_errors/fn_type_returning_pointer_to_itself.zig @@ -0,0 +1,8 @@ +const MyFn = fn () ?*const MyFn; +comptime { + _ = MyFn; +} + +// error +// +// :1:28: error: value of declaration 'tmp.MyFn' depends on itself here diff --git a/test/cases/compile_errors/function_with_non-extern_non-packed_enum_parameter.zig b/test/cases/compile_errors/function_with_non-extern_non-packed_enum_parameter.zig index 8122a89adc26bafa30189e9a3217b2e1dd19d372..ed9828c6921f5e46fc658d2857dc4f06f6971687 100644 --- a/test/cases/compile_errors/function_with_non-extern_non-packed_enum_parameter.zig +++ b/test/cases/compile_errors/function_with_non-extern_non-packed_enum_parameter.zig @@ -7,6 +7,6 @@ export fn entry(foo: Foo) void { // target=x86_64-linux // // :2:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'x86_64_sysv' -// :2:17: note: enum tag type 'u2' is not extern compatible -// :2:17: note: only integers with 0, 8, 16, 32, 64 and 128 bits are extern compatible +// :1:13: note: integer tag type of enum is inferred +// :1:13: note: consider explicitly specifying the integer tag type // :1:13: note: enum declared here diff --git a/test/cases/compile_errors/implicit_backing_type_in_extern_context.zig b/test/cases/compile_errors/implicit_backing_type_in_extern_context.zig new file mode 100644 index 0000000000000000000000000000000000000000..5d1b8e75ae054a60dbccb25435130acbfe6039f8 --- /dev/null +++ b/test/cases/compile_errors/implicit_backing_type_in_extern_context.zig @@ -0,0 +1,51 @@ +const PackedStruct = packed struct { x: u32 }; +const PackedUnion = packed union { x: u32 }; + +/// This enum has 256 fields, so `u8` will be its inferred tag type. +const Enum = enum { + // zig fmt: off + _00, _01, _02, _03, _04, _05, _06, _07, _08, _09, _0a, _0b, _0c, _0d, _0e, _0f, + _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _1a, _1b, _1c, _1d, _1e, _1f, + _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _2a, _2b, _2c, _2d, _2e, _2f, + _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _3a, _3b, _3c, _3d, _3e, _3f, + _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _4a, _4b, _4c, _4d, _4e, _4f, + _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _5a, _5b, _5c, _5d, _5e, _5f, + _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _6a, _6b, _6c, _6d, _6e, _6f, + _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _7a, _7b, _7c, _7d, _7e, _7f, + _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _8a, _8b, _8c, _8d, _8e, _8f, + _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _9a, _9b, _9c, _9d, _9e, _9f, + _a0, _a1, _a2, _a3, _a4, _a5, _a6, _a7, _a8, _a9, _aa, _ab, _ac, _ad, _ae, _af, + _b0, _b1, _b2, _b3, _b4, _b5, _b6, _b7, _b8, _b9, _ba, _bb, _bc, _bd, _be, _bf, + _c0, _c1, _c2, _c3, _c4, _c5, _c6, _c7, _c8, _c9, _ca, _cb, _cc, _cd, _ce, _cf, + _d0, _d1, _d2, _d3, _d4, _d5, _d6, _d7, _d8, _d9, _da, _db, _dc, _dd, _de, _df, + _e0, _e1, _e2, _e3, _e4, _e5, _e6, _e7, _e8, _e9, _ea, _eb, _ec, _ed, _ee, _ef, + _f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _fa, _fb, _fc, _fd, _fe, _ff, + // zig fmt: on +}; + +const Extern0 = extern struct { val: PackedStruct }; +const Extern1 = extern struct { val: PackedUnion }; +const Extern2 = extern struct { val: Enum }; + +comptime { + _ = @as(Extern0, undefined); +} +comptime { + _ = @as(Extern1, undefined); +} +comptime { + _ = @as(Extern2, undefined); +} + +// error +// +// :26:38: error: extern structs cannot contain fields of type 'tmp.PackedStruct' +// :26:38: note: inferred backing integer of packed struct has unspecified signedness +// :1:29: note: struct declared here +// :27:38: error: extern structs cannot contain fields of type 'tmp.PackedUnion' +// :27:38: note: inferred backing integer of packed union has unspecified signedness +// :2:28: note: union declared here +// :28:38: error: extern structs cannot contain fields of type 'tmp.Enum' +// :5:14: note: integer tag type of enum is inferred +// :5:14: note: consider explicitly specifying the integer tag type +// :5:14: note: enum declared here diff --git a/test/cases/compile_errors/packed_struct_uses_own_size.zig b/test/cases/compile_errors/packed_struct_uses_own_size.zig new file mode 100644 index 0000000000000000000000000000000000000000..7d5a7613df01e43086ba47b73ff741ece4e0ab04 --- /dev/null +++ b/test/cases/compile_errors/packed_struct_uses_own_size.zig @@ -0,0 +1,10 @@ +const S = packed struct { + x: @Int(.unsigned, @sizeOf(S)), +}; +comptime { + _ = @as(S, undefined); +} + +// error +// +// :2:32: error: type 'tmp.S' depends on itself for size query here diff --git a/test/cases/compile_errors/packed_struct_uses_own_typeinfo.zig b/test/cases/compile_errors/packed_struct_uses_own_typeinfo.zig new file mode 100644 index 0000000000000000000000000000000000000000..6a1fe41eb9463f994ae44f7e12c02cb5b57f230e --- /dev/null +++ b/test/cases/compile_errors/packed_struct_uses_own_typeinfo.zig @@ -0,0 +1,13 @@ +const S = packed struct(u16) { + a: bool, + b: bool, + _padding: @Int(.unsigned, 17 - @typeInfo(S).Struct.fields.len) = 0, +}; + +comptime { + _ = @as(S, .{ .a = true, .b = true }); +} + +// error +// +// :4:36: error: type 'tmp.S' depends on itself for type information query here diff --git a/test/cases/compile_errors/simple_struct_loop.zig b/test/cases/compile_errors/simple_struct_loop.zig new file mode 100644 index 0000000000000000000000000000000000000000..3ae0b2ed82862430fcfaf2f301cae7c4eadc7d09 --- /dev/null +++ b/test/cases/compile_errors/simple_struct_loop.zig @@ -0,0 +1,16 @@ +const A = struct { + b: B, +}; +const B = struct { + a: A, +}; +comptime { + _ = @as(A, undefined); +} + +// error +// +// error: dependency loop with length 2 +// :2:8: note: type 'tmp.A' depends on type 'tmp.B' for field declared here +// :5:8: note: type 'tmp.B' depends on type 'tmp.A' for field declared here +// note: eliminate any one of these dependencies to break the loop diff --git a/test/cases/compile_errors/sizeOf_bad_type.zig b/test/cases/compile_errors/sizeOf_bad_type.zig index 6d20251064f5be10e258283aaa6facb6451403c4..08ce7f4358f19781ba6fa007f5120978894c049b 100644 --- a/test/cases/compile_errors/sizeOf_bad_type.zig +++ b/test/cases/compile_errors/sizeOf_bad_type.zig @@ -15,6 +15,9 @@ const S4 = struct { a: u32, b: noreturn }; export fn entry4() usize { return @sizeOf(S4); } +export fn entry5() usize { + return @sizeOf([1]fn () void); +} // error // @@ -25,3 +28,4 @@ export fn entry4() usize { // :10:12: note: struct declared here // :16:20: error: no size available for uninstantiable type 'tmp.S4' // :14:12: note: struct declared here +// :19:20: error: no size available for comptime-only type '[1]fn () void' diff --git a/test/cases/compile_errors/struct_field_queries_hasfield_of_itself.zig b/test/cases/compile_errors/struct_field_queries_hasfield_of_itself.zig new file mode 100644 index 0000000000000000000000000000000000000000..593b440149a93b4a1d0f2aec20ad1b58b6f2bdff --- /dev/null +++ b/test/cases/compile_errors/struct_field_queries_hasfield_of_itself.zig @@ -0,0 +1,14 @@ +const Foo = packed struct { + bar: (T: { + _ = @hasField(Foo, "bar"); + break :T void; + }), +}; + +comptime { + _ = @as(Foo, undefined); +} + +// error +// +// :3:23: error: type 'tmp.Foo' depends on itself for field query here diff --git a/test/cases/compile_errors/struct_uses_reified_type_which_queries_struct_alignment.zig b/test/cases/compile_errors/struct_uses_reified_type_which_queries_struct_alignment.zig new file mode 100644 index 0000000000000000000000000000000000000000..f3f7361de750573d0fc15298c42ae95c7c3873f0 --- /dev/null +++ b/test/cases/compile_errors/struct_uses_reified_type_which_queries_struct_alignment.zig @@ -0,0 +1,13 @@ +const A = struct { b: *B }; +const B = @Struct(.auto, null, &.{"x"}, &.{A}, &.{.{ .@"align" = @alignOf(A) }}); +comptime { + _ = @as(A, undefined); + _ = @as(B, undefined); +} + +// error +// +// error: dependency loop with length 2 +// :1:24: note: type 'tmp.A' uses value of declaration 'tmp.B' here +// :2:75: note: value of declaration 'tmp.B' depends on type 'tmp.A' for alignment query here +// note: eliminate any one of these dependencies to break the loop diff --git a/test/cases/compile_errors/struct_uses_sizeof_self_as_array_len.zig b/test/cases/compile_errors/struct_uses_sizeof_self_as_array_len.zig new file mode 100644 index 0000000000000000000000000000000000000000..a8e0183465c2f643d026231f7ad6b28f0879f345 --- /dev/null +++ b/test/cases/compile_errors/struct_uses_sizeof_self_as_array_len.zig @@ -0,0 +1,10 @@ +const S = struct { + a: *[@sizeOf(S)]u8, +}; +comptime { + _ = @as(S, undefined); +} + +// error +// +// :2:18: error: type 'tmp.S' depends on itself for size query here -- 2.54.0 From 57114044db85717bea7204f2693d6c8a62111635 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 8 Mar 2026 16:21:19 +0000 Subject: [PATCH 77/79] Revert "ci: disable incremental tests" Since we don't know what causes the various flaky test-incremental failures we've seen, and this branch changes a bunch of incremental stuff, let's try turning these back on... maybe they'll magically work now! This reverts commit 953ca759c2446adc21648a9017b656ac84171291. --- ci/aarch64-freebsd-debug.sh | 1 - ci/aarch64-freebsd-release.sh | 1 - ci/aarch64-linux-debug.sh | 1 - ci/aarch64-linux-release.sh | 1 - ci/aarch64-macos-debug.sh | 1 - ci/aarch64-macos-release.sh | 1 - ci/aarch64-netbsd-debug.sh | 1 - ci/aarch64-netbsd-release.sh | 1 - ci/aarch64-windows.ps1 | 1 - ci/loongarch64-linux-debug.sh | 1 - ci/loongarch64-linux-release.sh | 1 - ci/powerpc64le-linux-debug.sh | 1 - ci/powerpc64le-linux-release.sh | 1 - ci/s390x-linux-debug.sh | 1 - ci/s390x-linux-release.sh | 1 - ci/x86_64-freebsd-debug.sh | 1 - ci/x86_64-freebsd-release.sh | 1 - ci/x86_64-linux-debug-llvm.sh | 1 - ci/x86_64-linux-debug.sh | 1 - ci/x86_64-linux-release.sh | 1 - ci/x86_64-netbsd-debug.sh | 1 - ci/x86_64-netbsd-release.sh | 1 - ci/x86_64-openbsd-debug.sh | 1 - ci/x86_64-openbsd-release.sh | 1 - 24 files changed, 24 deletions(-) diff --git a/ci/aarch64-freebsd-debug.sh b/ci/aarch64-freebsd-debug.sh index c296a50fd15388ae07286336b32bd0b9157849ec..87ffb3110223a6dfb7192833c0f3d7fd91f2c947 100755 --- a/ci/aarch64-freebsd-debug.sh +++ b/ci/aarch64-freebsd-debug.sh @@ -47,7 +47,6 @@ stage3-debug/bin/zig build test docs \ --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ - -Dskip-test-incremental \ --search-prefix "$PREFIX" \ --zig-lib-dir "$PWD/../lib" \ --test-timeout 2m diff --git a/ci/aarch64-freebsd-release.sh b/ci/aarch64-freebsd-release.sh index 1686327fb0b7da983d1f98fbd5d4188f01768d62..d5911241d6150e43e7273142c2882e956956fed2 100755 --- a/ci/aarch64-freebsd-release.sh +++ b/ci/aarch64-freebsd-release.sh @@ -47,7 +47,6 @@ stage3-release/bin/zig build test docs \ --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ - -Dskip-test-incremental \ --search-prefix "$PREFIX" \ --zig-lib-dir "$PWD/../lib" \ --test-timeout 2m diff --git a/ci/aarch64-linux-debug.sh b/ci/aarch64-linux-debug.sh index 37a09b539845be9864c06f336eca482ab02983c9..7a4a6daa2aef60e1a9194184b1307f85992db3de 100755 --- a/ci/aarch64-linux-debug.sh +++ b/ci/aarch64-linux-debug.sh @@ -47,7 +47,6 @@ stage3-debug/bin/zig build test docs \ --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ - -Dskip-test-incremental \ -Dtarget=native-native-musl \ --search-prefix "$PREFIX" \ --zig-lib-dir "$PWD/../lib" \ diff --git a/ci/aarch64-linux-release.sh b/ci/aarch64-linux-release.sh index 8cde024ab11450376913d68816fd9d02a3a9c00e..39ad9767ab62264b19846ef8bc22e2d6ad23ed85 100755 --- a/ci/aarch64-linux-release.sh +++ b/ci/aarch64-linux-release.sh @@ -47,7 +47,6 @@ stage3-release/bin/zig build test docs \ --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ - -Dskip-test-incremental \ -Dtarget=native-native-musl \ --search-prefix "$PREFIX" \ --zig-lib-dir "$PWD/../lib" \ diff --git a/ci/aarch64-macos-debug.sh b/ci/aarch64-macos-debug.sh index 369afc8d9e94a02ed77965bffc9692a5b5e344c4..7dc60c1f4ed13f8835538a2609955423ef8d551e 100755 --- a/ci/aarch64-macos-debug.sh +++ b/ci/aarch64-macos-debug.sh @@ -47,7 +47,6 @@ stage3-debug/bin/zig build test docs \ -Denable-macos-sdk \ -Dstatic-llvm \ -Dskip-non-native \ - -Dskip-test-incremental \ --search-prefix "$PREFIX" \ --test-timeout 2m diff --git a/ci/aarch64-macos-release.sh b/ci/aarch64-macos-release.sh index f7e6ae6fd3f4dba1970b94f6bc8e98305b2585be..00b6571f170a7fece1dcfb53755f9b271f438aae 100755 --- a/ci/aarch64-macos-release.sh +++ b/ci/aarch64-macos-release.sh @@ -46,7 +46,6 @@ stage3-release/bin/zig build test docs \ -Denable-macos-sdk \ -Dstatic-llvm \ -Dskip-non-native \ - -Dskip-test-incremental \ --search-prefix "$PREFIX" \ --test-timeout 2m diff --git a/ci/aarch64-netbsd-debug.sh b/ci/aarch64-netbsd-debug.sh index 5c87d14f47d15ab5bb82158ef0aa28c2dbafdb07..4f5eb0d41089778c97d4fe8e4eea70d1e88cea62 100755 --- a/ci/aarch64-netbsd-debug.sh +++ b/ci/aarch64-netbsd-debug.sh @@ -47,7 +47,6 @@ stage3-debug/bin/zig build test docs \ --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ - -Dskip-test-incremental \ --search-prefix "$PREFIX" \ --zig-lib-dir "$PWD/../lib" \ --test-timeout 4m diff --git a/ci/aarch64-netbsd-release.sh b/ci/aarch64-netbsd-release.sh index bf54c10efc835b51f87731bfd082132a7ec8fd19..d9d9477904cc721a9c40080e3d5470d129e0b8b0 100755 --- a/ci/aarch64-netbsd-release.sh +++ b/ci/aarch64-netbsd-release.sh @@ -47,7 +47,6 @@ stage3-release/bin/zig build test docs \ --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ - -Dskip-test-incremental \ --search-prefix "$PREFIX" \ --zig-lib-dir "$PWD/../lib" \ --test-timeout 4m diff --git a/ci/aarch64-windows.ps1 b/ci/aarch64-windows.ps1 index 57d77993519f230c2fc6e14de5a7e6957c51062a..96e07642565019c9a805ecc8c5ac29f461341df1 100644 --- a/ci/aarch64-windows.ps1 +++ b/ci/aarch64-windows.ps1 @@ -60,7 +60,6 @@ Write-Output "Main test suite..." --search-prefix "$PREFIX_PATH" ` -Dstatic-llvm ` -Dskip-non-native ` - -Dskip-test-incremental ` -Denable-symlinks-windows ` --test-timeout 30m CheckLastExitCode diff --git a/ci/loongarch64-linux-debug.sh b/ci/loongarch64-linux-debug.sh index 2d966f37427b1408febbc92abd516cebca096047..4cba17b0319039daf2d132ece4908cfdf542cffa 100755 --- a/ci/loongarch64-linux-debug.sh +++ b/ci/loongarch64-linux-debug.sh @@ -48,7 +48,6 @@ stage3-debug/bin/zig build test docs \ --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ - -Dskip-test-incremental \ -Dtarget=native-native-musl \ --search-prefix "$PREFIX" \ --zig-lib-dir "$PWD/../lib" \ diff --git a/ci/loongarch64-linux-release.sh b/ci/loongarch64-linux-release.sh index 558177a8d99ea2c6885cb2ab0d405cecf4cb8ca5..5b05284d26668d01020f204f09d3a73921883ce5 100755 --- a/ci/loongarch64-linux-release.sh +++ b/ci/loongarch64-linux-release.sh @@ -48,7 +48,6 @@ stage3-release/bin/zig build test docs \ --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ - -Dskip-test-incremental \ -Dtarget=native-native-musl \ --search-prefix "$PREFIX" \ --zig-lib-dir "$PWD/../lib" \ diff --git a/ci/powerpc64le-linux-debug.sh b/ci/powerpc64le-linux-debug.sh index 2875dcba955eeee80cda7eeadc38b3a0526f01be..1b9a51e44debff61729207ec1529e1d494b8c84b 100755 --- a/ci/powerpc64le-linux-debug.sh +++ b/ci/powerpc64le-linux-debug.sh @@ -48,7 +48,6 @@ stage3-debug/bin/zig build test docs \ --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ - -Dskip-test-incremental \ -Dtarget=native-native-musl \ -Dcpu=native+longcall \ --search-prefix "$PREFIX" \ diff --git a/ci/powerpc64le-linux-release.sh b/ci/powerpc64le-linux-release.sh index fffcbe2bd2c8bc72f18f21db76b557df1f1b8798..77e1ca803ae27db49ed7a2b8fed48392f485c4d4 100755 --- a/ci/powerpc64le-linux-release.sh +++ b/ci/powerpc64le-linux-release.sh @@ -48,7 +48,6 @@ stage3-release/bin/zig build test docs \ --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ - -Dskip-test-incremental \ -Dtarget=native-native-musl \ -Dcpu=native+longcall \ --search-prefix "$PREFIX" \ diff --git a/ci/s390x-linux-debug.sh b/ci/s390x-linux-debug.sh index a76ed6f04df534ee6d124bc0848a0d8ce3b0669f..ffe4d0f02b3cada3b36e24fcc3572a1a14d5b389 100755 --- a/ci/s390x-linux-debug.sh +++ b/ci/s390x-linux-debug.sh @@ -48,7 +48,6 @@ stage3-debug/bin/zig build test docs \ --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ - -Dskip-test-incremental \ -Dtarget=native-native-musl \ --search-prefix "$PREFIX" \ --zig-lib-dir "$PWD/../lib" \ diff --git a/ci/s390x-linux-release.sh b/ci/s390x-linux-release.sh index 0a9b82620d5a9176a3542b5fd953054ee4f1feed..7fb6cd3641fa73752ca4f6eb1967f1a2de9dd8bf 100755 --- a/ci/s390x-linux-release.sh +++ b/ci/s390x-linux-release.sh @@ -48,7 +48,6 @@ stage3-release/bin/zig build test docs \ --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ - -Dskip-test-incremental \ -Dtarget=native-native-musl \ --search-prefix "$PREFIX" \ --zig-lib-dir "$PWD/../lib" \ diff --git a/ci/x86_64-freebsd-debug.sh b/ci/x86_64-freebsd-debug.sh index 8bf492540eadd7cc68db8d43d06a5c0296165ab3..a4d7034325b33dc92b9d8ba97442d4449ad6a4c5 100755 --- a/ci/x86_64-freebsd-debug.sh +++ b/ci/x86_64-freebsd-debug.sh @@ -53,7 +53,6 @@ stage3-debug/bin/zig build test docs \ -Dskip-openbsd \ -Dskip-windows \ -Dskip-darwin \ - -Dskip-test-incremental \ --search-prefix "$PREFIX" \ --zig-lib-dir "$PWD/../lib" \ --test-timeout 2m diff --git a/ci/x86_64-freebsd-release.sh b/ci/x86_64-freebsd-release.sh index 44c4e76da2558d4fd399cee1452f4bc76ea8404d..0ce708c63d7715c4e6ad4e4e3927d4a100b9f65e 100755 --- a/ci/x86_64-freebsd-release.sh +++ b/ci/x86_64-freebsd-release.sh @@ -53,7 +53,6 @@ stage3-release/bin/zig build test docs \ -Dskip-openbsd \ -Dskip-windows \ -Dskip-darwin \ - -Dskip-test-incremental \ --search-prefix "$PREFIX" \ --zig-lib-dir "$PWD/../lib" \ --test-timeout 2m diff --git a/ci/x86_64-linux-debug-llvm.sh b/ci/x86_64-linux-debug-llvm.sh index a37fc6c2a6214888856401ee0d7f1ba1939eb38b..96bb795e18e23d72eb8715951a1c9bfc9e28243d 100755 --- a/ci/x86_64-linux-debug-llvm.sh +++ b/ci/x86_64-linux-debug-llvm.sh @@ -64,7 +64,6 @@ stage3-debug/bin/zig build test docs \ -Dskip-openbsd \ -Dskip-windows \ -Dskip-darwin \ - -Dskip-test-incremental \ -Dtarget=native-native-musl \ --search-prefix "$PREFIX" \ --zig-lib-dir "$PWD/../lib" \ diff --git a/ci/x86_64-linux-debug.sh b/ci/x86_64-linux-debug.sh index 60203bdcd0c4a66929be7b4d55bdfe416744a20b..aeaf5b8678badc181f79fdc76597edf1fa8ed203 100755 --- a/ci/x86_64-linux-debug.sh +++ b/ci/x86_64-linux-debug.sh @@ -63,7 +63,6 @@ stage3-debug/bin/zig build test docs \ -Dskip-windows \ -Dskip-darwin \ -Dskip-llvm \ - -Dskip-test-incremental \ -Dtarget=native-native-musl \ --search-prefix "$PREFIX" \ --zig-lib-dir "$PWD/../lib" \ diff --git a/ci/x86_64-linux-release.sh b/ci/x86_64-linux-release.sh index 0317ad55fc4b795de5e5671d987880a610c577c8..b1f6b84dcd10681631d1ad5fde7e36356d042ac4 100755 --- a/ci/x86_64-linux-release.sh +++ b/ci/x86_64-linux-release.sh @@ -65,7 +65,6 @@ stage3-release/bin/zig build test docs \ --libc-runtimes $HOME/deps/glibc-2.43-musl-1.2.5 \ -fwasmtime \ -Dstatic-llvm \ - -Dskip-test-incremental \ -Dtarget=native-native-musl \ --search-prefix "$PREFIX" \ --zig-lib-dir "$PWD/../lib" \ diff --git a/ci/x86_64-netbsd-debug.sh b/ci/x86_64-netbsd-debug.sh index 416ab6a5e0168464e4295d1dc54c5e2c19ac4366..68e9081f3ba040c83e4116b194ba17a46692798e 100755 --- a/ci/x86_64-netbsd-debug.sh +++ b/ci/x86_64-netbsd-debug.sh @@ -47,7 +47,6 @@ stage3-debug/bin/zig build test docs \ --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ - -Dskip-test-incremental \ --search-prefix "$PREFIX" \ --zig-lib-dir "$PWD/../lib" \ --test-timeout 2m diff --git a/ci/x86_64-netbsd-release.sh b/ci/x86_64-netbsd-release.sh index d8c54ca28d095b3a7e65a53fab1f572162fc4ea5..225a527686ac06cc1da2241f0fb624956f2d5a58 100755 --- a/ci/x86_64-netbsd-release.sh +++ b/ci/x86_64-netbsd-release.sh @@ -47,7 +47,6 @@ stage3-release/bin/zig build test docs \ --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ - -Dskip-test-incremental \ --search-prefix "$PREFIX" \ --zig-lib-dir "$PWD/../lib" \ --test-timeout 2m diff --git a/ci/x86_64-openbsd-debug.sh b/ci/x86_64-openbsd-debug.sh index 58363e52d3b9339395b4270f35f9e6b9427d7df1..133c8dd4d642a9d4a019d297a3648567231d6078 100755 --- a/ci/x86_64-openbsd-debug.sh +++ b/ci/x86_64-openbsd-debug.sh @@ -47,7 +47,6 @@ stage3-debug/bin/zig build test docs \ --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ - -Dskip-test-incremental \ --search-prefix "$PREFIX" \ --zig-lib-dir "$PWD/../lib" \ --test-timeout 2m diff --git a/ci/x86_64-openbsd-release.sh b/ci/x86_64-openbsd-release.sh index ebdaac1ee0c4e0c092929534517096bd5051a450..535b1a147166a1b724dd39358db56f18f17e09cd 100755 --- a/ci/x86_64-openbsd-release.sh +++ b/ci/x86_64-openbsd-release.sh @@ -47,7 +47,6 @@ stage3-release/bin/zig build test docs \ --maxrss ${ZSF_MAX_RSS:-0} \ -Dstatic-llvm \ -Dskip-non-native \ - -Dskip-test-incremental \ --search-prefix "$PREFIX" \ --zig-lib-dir "$PWD/../lib" \ --test-timeout 2m -- 2.54.0 From 79e7b719a362959fd172bbe7f7d9abe3e2f6f0cc Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Mon, 9 Mar 2026 12:02:58 +0000 Subject: [PATCH 78/79] bootstrap: disable strict aliasing The C backend has always gleefully violated C's strict aliasing rules, and I just got bitten by it for the first time when bootstrapping on macOS. This probably hasn't been helping with some of the weird bootstrap-related CI failures we've seen. So, update `bootstrap.c` and `CMakeLists.txt` to tell GCC/Clang to disable type-based alias analysis. No change is needed to the MSVC flags because MSVC does not, and never has, implemented TBAA. --- CMakeLists.txt | 4 ++-- bootstrap.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 146e507930706d8d779ce6a3977b39d7f9d9b78c..af1f64bd83e317f91670a19b3a95113639f59193 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -608,8 +608,8 @@ if(MSVC) set(ZIG2_LINK_FLAGS "/STACK:16777216 /FORCE:MULTIPLE") else() set(ZIG_WASM2C_COMPILE_FLAGS "-std=c99 -O2") - set(ZIG1_COMPILE_FLAGS "-std=c99 -Os") - set(ZIG2_COMPILE_FLAGS "-std=c99 -O0 -fno-sanitize=undefined -fno-stack-protector") + set(ZIG1_COMPILE_FLAGS "-std=c99 -Os -fno-strict-aliasing") + set(ZIG2_COMPILE_FLAGS "-std=c99 -O0 -fno-sanitize=undefined -fno-stack-protector -fno-strict-aliasing") # Must match the condition in build.zig. if(ZIG_HOST_TARGET_ARCH MATCHES "^(arm|thumb)(eb)?$" OR ZIG_HOST_TARGET_ARCH MATCHES "^powerpc(64)?(le)?$") set(ZIG1_COMPILE_FLAGS "${ZIG1_COMPILE_FLAGS} -ffunction-sections -fdata-sections") diff --git a/bootstrap.c b/bootstrap.c index 329a1af10e5d9c4c61d5dc851587c1d80c0e0aa5..ad4ccec54a67fd3b94f880d0669be25303afd14f 100644 --- a/bootstrap.c +++ b/bootstrap.c @@ -136,7 +136,7 @@ int main(int argc, char **argv) { } { const char *child_argv[] = { - cc, "-o", "zig1", "zig1.c", "stage1/wasi.c", "-std=c99", "-Os", "-lm", NULL, + cc, "-o", "zig1", "zig1.c", "stage1/wasi.c", "-std=c99", "-Os", "-fno-strict-aliasing", "-lm", NULL, }; print_and_run(child_argv); } @@ -213,6 +213,7 @@ int main(int argc, char **argv) { #if defined(__GNUC__) "-pthread", #endif + "-fno-strict-aliasing", workaround_gcc_sra_miscomp ? "-fno-tree-sra" : NULL, NULL, }; -- 2.54.0 From 502cab9ae30b001a8da2f724711330a73e7e2e4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 9 Mar 2026 22:41:21 +0100 Subject: [PATCH 79/79] test_runner: actually print the error that caused a runner failure part of the Stop Throwing Away Useful Information initiative --- lib/compiler/test_runner.zig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/compiler/test_runner.zig b/lib/compiler/test_runner.zig index 899b5dafbfb7fa2683854b81ff198eb2a7be4573..db8958519a4d44ef96cd006980146276b93d29cf 100644 --- a/lib/compiler/test_runner.zig +++ b/lib/compiler/test_runner.zig @@ -38,10 +38,10 @@ pub fn main(init: std.process.Init.Minimal) void { } if (need_simple) { - return mainSimple() catch @panic("test failure"); + return mainSimple() catch |err| std.debug.panic("test failure: {t}", .{err}); } - const args = init.args.toSlice(fba.allocator()) catch @panic("unable to parse command line args"); + const args = init.args.toSlice(fba.allocator()) catch |err| std.debug.panic("unable to parse command line args: {t}", .{err}); var listen = false; var opt_cache_dir: ?[]const u8 = null; @@ -55,7 +55,7 @@ pub fn main(init: std.process.Init.Minimal) void { } else if (std.mem.startsWith(u8, arg, "--cache-dir")) { opt_cache_dir = arg["--cache-dir=".len..]; } else { - @panic("unrecognized command line argument"); + std.debug.panic("unrecognized command line argument: {s}", .{arg}); } } @@ -65,7 +65,7 @@ pub fn main(init: std.process.Init.Minimal) void { } if (listen) { - return mainServer(init) catch @panic("internal test runner failure"); + return mainServer(init) catch |err| std.debug.panic("internal test runner failure: {t}", .{err}); } else { return mainTerminal(init); } -- 2.54.0

>UNs$=pV1|r4k^`o3JKb27Fq+EO-tdczyJ*; zlV7W#Wsn9w(moof{eBDZ?Hi~1niP$EqHy!}Pz`27NJgeIB0q~@DJW@A;9aDkELloaA-1UwV7)Dz zt__Q`*LVsRN@uSzX;!Y^4QO1R9yKxkn)Lhi$YDkxbuYA>~%fWp3%h%jyq?s3U`3$AnpM3 z=ZZVbi=ZY$5NA4ROQQ$INUUio;r!#IypIU$JU?~tJgI3j5&n~HJg z-M>pN?tj$h&P>05KADz4Hch*O+<9>l(vtj39e4I~RpfxZEpTVaQHPvsH1W1ZVdXw|Mplw(!;X-gbH$wvqMpLcm}{!F9)w`m^<;Jg zxz@T^Eq#>2hw6gG5AsiJ_~r9h5b2?5tU zhMOEO;uhVKDXZ01Ot%t8WNjWzMQX>bMl&P*6?UL(lt-<3#8!dPlg;U0%Mt|kO%R0`v1HprknJKdU!Joe-2?~|@e^Nh5uO%JW z+MK^BGEb)}#PGIxJu0Y(5h$pc*eD;=91R3D!y0`kbCeO(j5?KLN=B4jlnzOsqXvl( zvTq<1JDXFDl!Q5A!r`$t6Dg*Whak(6!KEbYS-<*quPJ50%+ra9iX?+DduI_ zVJi!>4YQwADsG-PO&PPe=MgRBddiIW7i|*WQQX?6+$;QRXjsz|6$z;RNb8TVtUWJP zf~ou8EdIM#*3M+je_P5g6Zc-OjLMN23Q1Q`OYC{@+<`5RIe5gdL%R2f)f~+3mKF&6e!tZr_nH}+_O;|@oHM7# zd{Z;$RNmv+oWIgOcjs-a&?crBW#9OD%)P7oByDHdsy~A~NLATrqQVg*TGB@%9o*wE z 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

v4SC-KUU9oGLs^gAC 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 z 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

KsK0sr)m(O=V*1D8ZlwnZ^B?3iUWM8DO zQu!WqvCh1}HHYyTHdS-o`cvF|W*a<)+_|%%U+|zn3EVoCxyE-qQP(G*?|^vdtSr6P z^pu-@gmgc0|U0N6c64gr+v2vicL;dYXi zUMvrFR2qn6cW4C$GR^hUYS5F>5$ACG7RPe#oL$T}_VM!xDY%N@3jBfZ;(t~;$1+S5-G=vQf)seR( z-yw@0|6!N5=yt4iBfUX+2^k&>B|M(tNqH|$Hk2rPE)sSL2Dl&p;7io5sU=^*rK+-3 zy7i4ua!N~i3&3ei_*9NXd~S*PHuBjR4=021LapJGUe0TXRQcf0$d;0P^V`fR*T|pa zp0-tW&UHE_)$=>6O8g#m#4OG7J*9jI^_udzymOKjw=i z&Bj6*9rV36dM>^rO5NVnGkQDp-^gDuWVALUYh%?s7hdRSC~yxT(|bKjyH4v&4sIl& z)krh!7tLN98^~7%jWA?%1q?6hdLtT2lx8+e{v2oApGFh}U5a+=a2bdJrx3;6Tq34w zQweud{jt1q)h#moO}eW*+S(TJ?oGmb5^HYO-B~o_$@F?iOgJY%!1fwuO=uLL^-)b@ zgQg3fkYeq3l(QE13$bOkTNM+MtZY|0hyc#0iV0B6=fEwVEH|7t^1XIvW@|~OyTM@r zZDU~_Gz9PsglJ;NuJcnLoWJ9I6)>o7C1)f-{~G>IKw-q$*g^D63WL`hXhDk()u5jAp4TirGx z^#*0j9J{a12T{s=XnmxAHdJY#3HNep@9|}O*1QiDqo(x1 zF8VV|qT*z_jK|_D&HJ3}rI_19vDLnwKeI#e(6<24ah=IfPm??12i%g*+z~&_CxfxJ ze%4i(jK3;WujQd4PjU-knDEK0>0~!!P$jMa{)0>|h9!6_8##00Sc4_NEHNd9N`*aJ zAk1CAK&ezE8rcF(+5*}4a)DyRM4bHJ1PR^S0?wUfozQFXZ?26Wz5_IZXG>*s@eYFR z#RE;XG*z~4drC$n@L+}tdXsl3flzkBx~mUz7HpAmbH$J4^?&+Ct-B(VG}TlL_^vtw zZ#N55PH071w$spdi7qxA`_YfzB8_f6X37;%5LAn(O+H$SX?nert9IW>-!T z!ay_d*iU9jH{=<*k{C032I*Q>2ST`jqsB;}tp}cB*CDHQQRqQW0&}|nBDSnH5CZ0< zCs(0f)|$ud)lxLBg!+;Lc-eTkmW>v0*_LtimYbHNZ1wG@g`TBBQ>lt!NCT!}=wz{b z$bGKoq~K1e{;4lV5Rh*D!gw_9xT`8i8h4fCono!g2SEXS)B3kI1)@l98m@>X!Ob@c zZ!}O|{c86)$S5($iRe_S=>qa~!E!0i>w;x4D=ySLFDC7U!kgAdI=-ptcBFtdC@0{?f_?tS=95!-+ zYVV{wP|(<|Saov5N?fz|hAuM>qMnmaMFfzoz~QJbU>xiZf;Be{O%CfWzgkj{HqS~q zvy2`D8?jUzCeNrzL)+rPr-SYbnn#Aq0{XTzgQHw6B|S_&7H6ZTDKJ<+D26#&&f4~T z8GLHVrvMV^v7wP&uQBB1Kt#H1NJ&m?AxQ)GFCCV;r+v+VDokP^3zpBvf*m{0z$D>s z-74qRbL~8HbzY$VwZH&B4=w(s42)gXk$pi? zi=F^^1AOP)9JZS`5;b{(IaBsgHz!u%V%d`Xd6ZpaV32}>uA+bvqqeG+y_sI4nc4)- zh4UwH#_kN5z$pQp37prJ39yNvo}Z$%G#^G^j+&8x6pV!ZUqoM7kVOX)6$25opxz&p zfP+dJ0Cog5gAi>vk#vPncIdv&xrGYRpZ{_Qk!d|YNZ_yuk9`o9DC1IZl<*}W&#*W^ z(0SEa9P~L`F56?{7EC&xEf_oMizQ>0&+Dbk@;P1o63%G=bJ3Rk%!i*|flK``BqDXu zlr-1dQNH!{gB4)?UQ;;5 zU-Oc>K2`0SV>WB~H5OB*DPTS+1O&_{bOpReg@|D9DSdC=ZAMhYZIB*gC?&r`0$ zT#**(1lQRM;p2pD^psl+G-F!~I1btZtVXcs56fZ;U>YmJ1fJTzP`%d0N|}Zs!ctwl z`75PLbZ(`Z&t9C)7I|JQRSBe^Tm6bv><}B;ViqH9H_vz~UC9RAa zxa>peUn%1;Rz$Ez_kG>@$H`=KH1E59LERm!c86`t%3FUY=)tC3_NlUI19{0&-|s2k z?@9H0lzwfx9T2l)T*3N1zo1_nF@yU(U_ zISo>dEwmnN!BR9bn!UnNMzcp(MA~j$8O=^z8O^M&vha{D+g5D~_Uk*Nn&WDoBv1iL zyXdGCCv~IJ_}r*8zP?cj;;x$Br)tHC^OP8=O$8EnrXkAknWfw{DHTXc^dzu}ijLF^ zVVaF6a*i0iahn7mU#S3sS3n6b=p)2Juw|h4qn36jt%KWhp`BJ6Yddn*G|a@`5$ac7 zgclAk!O4bYx0}di@_Lt7<3k-DOA8zwY|vHA$h0~{kXcB;-7F+^Cx?pD$Wy>MBt-^o zR6aw5>)HqliAWx8bOy?5u2Yg+s}(4qz6EiKThiK(hPP#HZP+H#f&V45b&zyN(PnCz zOh%Dw@ml1KeX`r=dWDIkHxbk{w^fbALFx5v&WGq)Xc{w1HVocn<@V~^oW7}HMvQAl zRuMziK-~lwZ9co3A!2cTNH4d=@Ew~Oy}L=*4%E|rh?)^3WSHntb51McAEUJ!pVE=Q z&rl07i>jstb{-@Is+P4}OMYl=Pn(ZZj(;<;K^$1h5qfrq3=Gadk+0$PfjmY*23i>Y z@b`W+5DV_e9dGoVTI%pGJ{jn6f1^MZ}@~MIwoI5X} z&vV5+G*yf*qHGK=z(H7ink+wUgbUG{0SijD@i0GMxgmkEpGBhPw$^HY*m-*#)>R2c zM|(tgQeXv!zAU&3HmVp6ALUPGD2{?mqeUY|)6N=Ncbeea%MijF`RtET(H5&2{e-dT zbxxfDkh~vr)GvqM6RalpyO#Ird6kBUa;(eb18R#dmc>65>J*6JUODx6!|ZJIxOQ8k zQ47_Ad>5&u8j^BTsmlH#5^tTOjrqvw%Hrt$^OgGuaAlhtAXd|p_FX2wRZBjs8Yl3( z)crJNKarDF{A4(8Pu<4KN34i``cM9;4eqH|+fP_7_LC6V0gTbgO@^{c8Bv}6mByW| zpa?5)i0z`R0Kw1zLkWTa+{1d3cj@z_ofE?uV)=xyFS2TxTF?#lgG?S8^8Fz@>|J3D zdz!2py^RVJpz{Ul7`fvCv^&)qcf(uMJw+fIaQOdNW7V*fQmJo&V`$)as`IbWi_Ln1 zO*lJGYYWq$5Sb<@c=D{4^De&4Z0#_6>cs!1N;g{KqIeFqwfKwWW8G!VRs0A-q)lW5 z%dMxuT=>E}o7Kl~DKUw%Vlr~vZj_~l&6LHyI$0LF1>j~AKFpBBYU_8zZ{^MGS5>ik z%|$TAJA#G@uAOMR$rh6oF!q!qmyv+b+bJVqCxDg^(^Kzhx~J^dUHTPMwEXqG{3^iM z9##(g_$gQX$`{egpE;;)oWLxk#E7}y@k#J73+|U2@p5Or-0r%9Y80sxOGaj3z`jMS zr{+@(V`s~E-srH23SbSet9qD(2KO=YZU3yzW4L{XDM|cPN{K4danWc3ie}-H;UOy` z^PuY~H95+AaFSJ4Ku4$Zy<7m;fPq`$iEYyCw_Z)himhWkeXh+l6#{;@Q=IT|4g_>V zT)ibf!oc)6YmaJ;3mKuR-5-Q8ieD!91-O8x_-|a8OB_lM_=p!v3Fjj?C$M!*OmD!c z0CUo5KU}5>1EwO0=L>79YXHxIa09D}R0X;QW^B zf`44ke@p>gEm=b@XL}IMtL*;GET<5DPnEF(=mkAHi8_~?S>=2V@I z9+n4nI(mfaM?vywY*I4s=@{U1LUBfJ@y?KGjvau}ZpdS-s4;V&3-qcLAcdN=!=_jQ z5f-SS!QKTgkqEHZjoS)$4F>PpXo}n}-jg4(-ypC2rb-~^6sRCGEI({NpDeu-1X1k{ zCnp%@sSR9C!_SZP?&%Fj~7Xnnct=oB>@*` zhkeJKgxzl5%-D8sXrij1fa8kmX%xdW-u#p>6T~7pgLi{{MMC-%cM)+Z7gU+m^adRn zT)g$BQkUESavo@gN6D|Xx}?M7*Y?Y6I@1qyQC5Aw7Uk*BvM8(mTUeBa#V6Vji!ol6 zeg0LW=(or03N-uT3Esi2-6FM7B-)_)#bSu*^ba zQ^@83VvdK5t>4z=hMe(AaH8OYZJ1+Yedksug$6!jyKg5|(!q4~i+8U)+y3q^{!DrW z&rB_N=B(^eJ4A2J>3Ohyv@VsA@OrlR05C}24J`8uL#i@}T22}X0$M680Swb~eUTz7 zfhl>Mya&~@Utx=wqzPWn7g4J1(=-B`+yDxBl98Rf7wv}i4+VD|;w*|(uMj&>iaJUX zjs`^W#=I_llg~(U-MBOPvmvjV5hgQ9=6-7>dkUQmYtocYQ}mSmSdIj1f=H6rU)><& z+|?L}ZbdSTEf$26*Mf68TIjEbR`Le)WgAp9)BC6KP)mL5Xd?(CDh`8>kyN9H0WUv2 zXw_1d_^#dhK~UKC_mlbu&zKIbtpFlZ!H_X#TufJR(rHaR+QH_ z1v|vA-MgQ(me5|cr9q5ri%kJSuV{&4skbBhs!cr%sZ+kM*L06-x~IRX90ieth6t;( z2BHyqP0F=XD3|x3I?zq>`!Q?T>AWkB>JB5(@T7>LQ*K3uFk-`cqfmLawWBc%N*i>-ykOQp(LmH-T%a6l7vxi_`&d+W`$8*TLx2ln}EUC2^ z`Rbu=J=ho~83VGL-U92AgmgyloK~1MVu>O#0YE%a`fytB{7&e&qAYM3WTxXn>~hZ; zoCMh2zl-8_sue+pQrt_vZK(nH`2<|F3i1q1ok-5g1J6L~`2?MyS%{eH@(Wp(^`uNh z3*_AoVe{a<8k;QzU9HZ4=`-)-01#SWrzL;gR-l%Z!q^apU;^BbU1Jt(=hI__%T26J zQvd>IL#J{hp`w}oe_CQ2o0Mq{1CJ~o)#TTy9KH=!0Kb!_*%6oM9AG<;Q@1*%W+LBA z&1}G6AamD3h2k%XfZZrJkS1fu^(4vKq+)&d{`&0wWgK@KD0Q%oy~{(2UqjBZcmZdkR<1qB1_rTG#Ry z4x$<@>tziwzh~2yoy@A@m)?+0K1LB*?F^JT_$fV7Xj3p~EtE`EQ*vFv{YvI{bD{ke zbJUDvOuw=@+AN>ekh9C0VI$dSk!-Ze!s5E|FakQZu<%<}^dY37Ei5)%VW1TY z+h?Dd_YbyP+Gmx8HSCuhL?8#|tLsoMG95vSr!Qyi`Wh8h2 z1%Kg;pAB9KhAqY(;dH>^9||7g0>t=`D8LASifqMR0mg#9#U|=`YT$$+^My5) zhaC5jK0heoJypmYsa;OmbWx9_hhek{r-?|R+HZ9jz~1Vu1vf&?;0zsMqCQP*ReVyP zI3iw0`r2o-iH`dOrvgEw_w@J-Ng%J)wx_z+A#0t#Us;?^d`N0jA=Y(R$T5O5PNt`P zJ6=a|zl~Uc6uIOhk(2I}WdD`6VoFY$<2O3Y#-I6KBOqI_F9g4pGVT++$3db2lJ}?@ zlQqHL!?=r%^kGiJqq*Pg8Pug81;T-aQk*5v3bK-uxY*7~NM< z3?%3|jDVL7lCIURmc#Xm$%kXVO7qvEP=cMWmB6M`f?d$|3fJOm-=DP*V*oXdexCKX zu_yY?%0xN>kkyxKHXCwx#R3vAQ z#Jo1wPhzH_HI16#*04YJs$0Es=HE!ZK}G6MD^I_PH?G^@9v|HK&XaF|4jcLFx8*;A z@H7VsJ~No;?JBxWA~XD99xZ-9*8l83g!O;sBfi@J5eF0ps%q$b91(+X3yuH zWO2fOc*(FlMI)5`wmlLZE6hIZ^a2a%Qm%$n&WAY|h$m*U|88`Zf-0hMMX@<}$w9JjXcfWD-8tvbIJ+@o{N?Y!6}n^04%Q zR5jI|&lX3+sSu4&zEB;HsC*T-X<-N0q$FE&sF*Xxsc&uz1^S;hPz_1<^INIV>qa~W zb`nY$p=cmj^$PU5Zq;zOYHFPqP~R3ynY<|HnZIufZzS|s-QIPD>`0rQoX`STgZ0Ai zpU^@tgdP3ccF)~*aRprtpDR=~e((DuYS14(EVYmBud3Q7pV<#cK_{5!g5~%u@n>36 zH>Osz^S@Q|IA8&C`SxdXBwx13^l&dQXWK&qbI+!MtX7$U=D965&dBj>*&T<5qHEnY zkK>qkG4CXOPyB=w!6LgNyUs$_F25pMsT?rk0jeENz)7|AJCn^w5otX*L1f}7a&!DWi=9`v%B8V-D$#4pcfg0c?WOenaK@6ql&K@j}i`WT(ZH#9WM{VRuiSUVsXYP4NvIG8;bx%tT}!0sCJJfcrfNJEcu z-Kp!a1$W=4k0XGGV&c{@sVmwJvs+)<7WI9akABw!AV+Vhu2L*}J2?m9fKB>?|3h-t z+!DA+7miQ zu{}Q=Y$Gq7blBl-_I>`5%$zoATrseXOz_0*OBHdz-{iwgtEsl0G

Hv6huC>@%NbWbmbC4Qnu^$c}(BZG|TOo#l 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

%hbygDOxG1i7rBv&Qr9q!HO0; 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

nL|+EstKfwJ03k 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

J}O{=%xz|ZHU&PilVaV5_~P1YDmh{ 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