authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-02-12 11:10:52+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-03-10 10:26:12+00:00
logf7a1ccfc56ed2d5605aa6ee25ac8d609f4c0d2a5
tree147da05e3c2b3e90c0cdcd41e902ceeda6bf9551
parent0a7387c41004b8378c75e476c8a4bd058b15030d
signaturelock-open Commit is signed but in an unrecognized format.

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

13 files changed, 851 insertions(+), 967 deletions(-)

lib/std/zig/llvm/BitcodeReader.zig+5-5
...@@ -34,8 +34,8 @@ pub const Block = struct {...@@ -34,8 +34,8 @@ pub const Block = struct {
3434
35 const default: Info = .{35 const default: Info = .{
36 .block_name = &.{},36 .block_name = &.{},
37 .record_names = .{},37 .record_names = .empty,
38 .abbrevs = .{ .abbrevs = .{} },38 .abbrevs = .{ .abbrevs = .empty },
39 };39 };
4040
41 const set_bid_id: u32 = 1;41 const set_bid_id: u32 = 1;
...@@ -109,8 +109,8 @@ pub fn init(allocator: std.mem.Allocator, options: InitOptions) BitcodeReader {...@@ -109,8 +109,8 @@ pub fn init(allocator: std.mem.Allocator, options: InitOptions) BitcodeReader {
109 .keep_names = options.keep_names,109 .keep_names = options.keep_names,
110 .bit_buffer = 0,110 .bit_buffer = 0,
111 .bit_offset = 0,111 .bit_offset = 0,
112 .stack = .{},112 .stack = .empty,
113 .block_info = .{},113 .block_info = .empty,
114 };114 };
115}115}
116116
...@@ -278,7 +278,7 @@ fn startBlock(bc: *BitcodeReader, block_id: ?u32, new_abbrev_len: u6) !void {...@@ -278,7 +278,7 @@ fn startBlock(bc: *BitcodeReader, block_id: ?u32, new_abbrev_len: u6) !void {
278 state.* = .{278 state.* = .{
279 .block_id = block_id,279 .block_id = block_id,
280 .abbrev_id_width = new_abbrev_len,280 .abbrev_id_width = new_abbrev_len,
281 .abbrevs = .{ .abbrevs = .{} },281 .abbrevs = .{ .abbrevs = .empty },
282 };282 };
283 try state.abbrevs.abbrevs.ensureTotalCapacity(283 try state.abbrevs.abbrevs.ensureTotalCapacity(
284 bc.allocator,284 bc.allocator,
lib/std/zig/llvm/Builder.zig+54-53
...@@ -1627,7 +1627,7 @@ pub const FunctionAttributes = enum(u32) {...@@ -1627,7 +1627,7 @@ pub const FunctionAttributes = enum(u32) {
1627 const params_index = 2;1627 const params_index = 2;
16281628
1629 pub const Wip = struct {1629 pub const Wip = struct {
1630 maps: Maps = .{},1630 maps: Maps = .empty,
16311631
1632 const Map = std.AutoArrayHashMapUnmanaged(Attribute.Kind, Attribute.Index);1632 const Map = std.AutoArrayHashMapUnmanaged(Attribute.Kind, Attribute.Index);
1633 const Maps = std.ArrayList(Map);1633 const Maps = std.ArrayList(Map);
...@@ -4048,7 +4048,7 @@ pub const Function = struct {...@@ -4048,7 +4048,7 @@ pub const Function = struct {
4048 section: String = .none,4048 section: String = .none,
4049 alignment: Alignment = .default,4049 alignment: Alignment = .default,
4050 blocks: []const Block = &.{},4050 blocks: []const Block = &.{},
4051 instructions: std.MultiArrayList(Instruction) = .{},4051 instructions: std.MultiArrayList(Instruction) = .empty,
4052 names: [*]const String = &[0]String{},4052 names: [*]const String = &[0]String{},
4053 value_indices: [*]const u32 = &[0]u32{},4053 value_indices: [*]const u32 = &[0]u32{},
4054 strip: bool,4054 strip: bool,
...@@ -5222,13 +5222,13 @@ pub const WipFunction = struct {...@@ -5222,13 +5222,13 @@ pub const WipFunction = struct {
5222 .prev_debug_location = .no_location,5222 .prev_debug_location = .no_location,
5223 .debug_location = .no_location,5223 .debug_location = .no_location,
5224 .cursor = undefined,5224 .cursor = undefined,
5225 .blocks = .{},5225 .blocks = .empty,
5226 .instructions = .{},5226 .instructions = .empty,
5227 .names = .{},5227 .names = .empty,
5228 .strip = options.strip,5228 .strip = options.strip,
5229 .debug_locations = .{},5229 .debug_locations = .empty,
5230 .debug_values = .{},5230 .debug_values = .empty,
5231 .extra = .{},5231 .extra = .empty,
5232 };5232 };
5233 errdefer self.deinit();5233 errdefer self.deinit();
52345234
...@@ -5265,7 +5265,7 @@ pub const WipFunction = struct {...@@ -5265,7 +5265,7 @@ pub const WipFunction = struct {
5265 self.blocks.appendAssumeCapacity(.{5265 self.blocks.appendAssumeCapacity(.{
5266 .name = final_name,5266 .name = final_name,
5267 .incoming = incoming,5267 .incoming = incoming,
5268 .instructions = .{},5268 .instructions = .empty,
5269 });5269 });
5270 return index;5270 return index;
5271 }5271 }
...@@ -6325,7 +6325,7 @@ pub const WipFunction = struct {...@@ -6325,7 +6325,7 @@ pub const WipFunction = struct {
6325 function.blocks = &.{};6325 function.blocks = &.{};
6326 gpa.free(function.names[0..function.instructions.len]);6326 gpa.free(function.names[0..function.instructions.len]);
6327 function.debug_locations.deinit(gpa);6327 function.debug_locations.deinit(gpa);
6328 function.debug_locations = .{};6328 function.debug_locations = .empty;
6329 gpa.free(function.debug_values);6329 gpa.free(function.debug_values);
6330 function.debug_values = &.{};6330 function.debug_values = &.{};
6331 gpa.free(function.extra);6331 gpa.free(function.extra);
...@@ -8391,7 +8391,7 @@ pub const Metadata = packed struct(u32) {...@@ -8391,7 +8391,7 @@ pub const Metadata = packed struct(u32) {
8391 map: std.AutoArrayHashMapUnmanaged(union(enum) {8391 map: std.AutoArrayHashMapUnmanaged(union(enum) {
8392 metadata: Metadata,8392 metadata: Metadata,
8393 debug_location: DebugLocation.Location,8393 debug_location: DebugLocation.Location,
8394 }, void) = .{},8394 }, void) = .empty,
83958395
8396 const FormatData = struct {8396 const FormatData = struct {
8397 formatter: *Formatter,8397 formatter: *Formatter,
...@@ -8649,52 +8649,52 @@ pub fn init(options: Options) Allocator.Error!Builder {...@@ -8649,52 +8649,52 @@ pub fn init(options: Options) Allocator.Error!Builder {
8649 .source_filename = .none,8649 .source_filename = .none,
8650 .data_layout = .none,8650 .data_layout = .none,
8651 .target_triple = .none,8651 .target_triple = .none,
8652 .module_asm = .{},8652 .module_asm = .empty,
86538653
8654 .string_map = .{},8654 .string_map = .empty,
8655 .string_indices = .{},8655 .string_indices = .empty,
8656 .string_bytes = .{},8656 .string_bytes = .empty,
86578657
8658 .types = .{},8658 .types = .empty,
8659 .next_unnamed_type = @enumFromInt(0),8659 .next_unnamed_type = @enumFromInt(0),
8660 .next_unique_type_id = .{},8660 .next_unique_type_id = .empty,
8661 .type_map = .{},8661 .type_map = .empty,
8662 .type_items = .{},8662 .type_items = .empty,
8663 .type_extra = .{},8663 .type_extra = .empty,
86648664
8665 .attributes = .{},8665 .attributes = .empty,
8666 .attributes_map = .{},8666 .attributes_map = .empty,
8667 .attributes_indices = .{},8667 .attributes_indices = .empty,
8668 .attributes_extra = .{},8668 .attributes_extra = .empty,
86698669
8670 .function_attributes_set = .{},8670 .function_attributes_set = .empty,
86718671
8672 .globals = .{},8672 .globals = .empty,
8673 .next_unnamed_global = @enumFromInt(0),8673 .next_unnamed_global = @enumFromInt(0),
8674 .next_replaced_global = .none,8674 .next_replaced_global = .none,
8675 .next_unique_global_id = .{},8675 .next_unique_global_id = .empty,
8676 .aliases = .{},8676 .aliases = .empty,
8677 .variables = .{},8677 .variables = .empty,
8678 .functions = .{},8678 .functions = .empty,
86798679
8680 .strtab_string_map = .{},8680 .strtab_string_map = .empty,
8681 .strtab_string_indices = .{},8681 .strtab_string_indices = .empty,
8682 .strtab_string_bytes = .{},8682 .strtab_string_bytes = .empty,
86838683
8684 .constant_map = .{},8684 .constant_map = .empty,
8685 .constant_items = .{},8685 .constant_items = .empty,
8686 .constant_extra = .{},8686 .constant_extra = .empty,
8687 .constant_limbs = .{},8687 .constant_limbs = .empty,
86888688
8689 .metadata_map = .{},8689 .metadata_map = .empty,
8690 .metadata_items = .{},8690 .metadata_items = .empty,
8691 .metadata_extra = .{},8691 .metadata_extra = .empty,
8692 .metadata_limbs = .{},8692 .metadata_limbs = .empty,
8693 .metadata_forward_references = .{},8693 .metadata_forward_references = .empty,
8694 .metadata_named = .{},8694 .metadata_named = .empty,
8695 .metadata_string_map = .{},8695 .metadata_string_map = .empty,
8696 .metadata_string_indices = .{},8696 .metadata_string_indices = .empty,
8697 .metadata_string_bytes = .{},8697 .metadata_string_bytes = .empty,
8698 };8698 };
8699 errdefer self.deinit();8699 errdefer self.deinit();
87008700
...@@ -12069,7 +12069,7 @@ pub fn trailingMetadataStringAssumeCapacity(self: *Builder) Metadata.String {...@@ -12069,7 +12069,7 @@ pub fn trailingMetadataStringAssumeCapacity(self: *Builder) Metadata.String {
12069 const start = self.metadata_string_indices.getLast();12069 const start = self.metadata_string_indices.getLast();
12070 const bytes: []const u8 = self.metadata_string_bytes.items[start..];12070 const bytes: []const u8 = self.metadata_string_bytes.items[start..];
12071 assert(bytes.len > 0);12071 assert(bytes.len > 0);
12072 const gop = self.metadata_string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self });12072 const gop = self.metadata_string_map.getOrPutAssumeCapacityAdapted(bytes, Metadata.String.Adapter{ .builder = self });
12073 if (gop.found_existing) {12073 if (gop.found_existing) {
12074 self.metadata_string_bytes.shrinkRetainingCapacity(start);12074 self.metadata_string_bytes.shrinkRetainingCapacity(start);
12075 } else {12075 } else {
...@@ -12467,11 +12467,12 @@ pub fn metadataConstant(self: *Builder, value: Constant) Allocator.Error!Metadat...@@ -12467,11 +12467,12 @@ pub fn metadataConstant(self: *Builder, value: Constant) Allocator.Error!Metadat
12467 return self.metadataConstantAssumeCapacity(value);12467 return self.metadataConstantAssumeCapacity(value);
12468}12468}
1246912469
12470/// Resolves the given forward reference to the given value (which is not itself a forward
12471/// reference). If the forward reference is already resolved, its target is replaced.
12470pub fn resolveDebugForwardReference(self: *Builder, fwd_ref: Metadata, value: Metadata) void {12472pub fn resolveDebugForwardReference(self: *Builder, fwd_ref: Metadata, value: Metadata) void {
12471 assert(fwd_ref.kind == .forward);12473 assert(fwd_ref.kind == .forward);
12472 const resolved = &self.metadata_forward_references.items[fwd_ref.index];12474 assert(value.kind != .forward);
12473 assert(resolved.is_none);12475 self.metadata_forward_references.items[fwd_ref.index] = value.toOptional();
12474 resolved.* = value.toOptional();
12475}12476}
1247612477
12477fn metadataSimpleAssumeCapacity(self: *Builder, tag: Metadata.Tag, value: anytype) Metadata {12478fn metadataSimpleAssumeCapacity(self: *Builder, tag: Metadata.Tag, value: anytype) Metadata {
src/Sema.zig+28-1
...@@ -7096,7 +7096,13 @@ fn analyzeCall(...@@ -7096,7 +7096,13 @@ fn analyzeCall(
7096 }7096 }
7097 }7097 }
7098 for (args, 0..) |arg, arg_idx| {7098 for (args, 0..) |arg, arg_idx| {
7099 try sema.validateRuntimeValue(block, args_info.argSrc(block, arg_idx), arg);7099 const arg_src = args_info.argSrc(block, arg_idx);
7100 const arg_ty = sema.typeOf(arg);
7101 try sema.validateRuntimeValue(block, arg_src, arg);
7102 if (arg_ty.isPtrAtRuntime(zcu) or arg_ty.isSliceAtRuntime(zcu)) {
7103 // LLVM wants this information for an "align" attribute on the argument.
7104 try sema.ensureLayoutResolved(arg_ty.nullablePtrElem(zcu), arg_src, .init);
7105 }
7100 }7106 }
7101 const runtime_func: Air.Inst.Ref, const runtime_args: []const Air.Inst.Ref = func: {7107 const runtime_func: Air.Inst.Ref, const runtime_args: []const Air.Inst.Ref = func: {
7102 if (!any_generic_types and !any_comptime_params) break :func .{ callee, args };7108 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...@@ -24270,6 +24276,13 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2427024276
24271 const elem = try sema.coerce(block, dest_elem_ty, uncoerced_elem, value_src);24277 const elem = try sema.coerce(block, dest_elem_ty, uncoerced_elem, value_src);
2427224278
24279 const comptime_only_elem = switch (dest_elem_ty.classify(zcu)) {
24280 .no_possible_value => unreachable, // `elem` is a value of this type
24281 .one_possible_value => return, // no work to do
24282 .runtime => false,
24283 .partially_comptime, .fully_comptime => true,
24284 };
24285
24273 const runtime_src = rs: {24286 const runtime_src = rs: {
24274 const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls), dest_src);24287 const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls), dest_src);
24275 const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse break :rs dest_src;24288 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...@@ -24299,6 +24312,15 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
24299 return sema.storePtrVal(block, src, array_ptr_val, array_val, array_ty);24312 return sema.storePtrVal(block, src, array_ptr_val, array_val, array_ty);
24300 };24313 };
2430124314
24315 if (comptime_only_elem) {
24316 return sema.failWithOwnedErrorMsg(block, msg: {
24317 const msg = try sema.errMsg(src, "cannot store comptime-only element '{f}' at runtime", .{dest_elem_ty.fmt(pt)});
24318 errdefer msg.destroy(sema.gpa);
24319 try sema.errNote(dest_src, msg, "operation is runtime due to destination pointer", .{});
24320 break :msg msg;
24321 });
24322 }
24323
24302 try sema.requireRuntimeBlock(block, src, runtime_src);24324 try sema.requireRuntimeBlock(block, src, runtime_src);
24303 try sema.validateRuntimeValue(block, dest_src, dest_ptr);24325 try sema.validateRuntimeValue(block, dest_src, dest_ptr);
24304 try sema.validateRuntimeValue(block, value_src, elem);24326 try sema.validateRuntimeValue(block, value_src, elem);
...@@ -27063,6 +27085,11 @@ fn elemPtrArray(...@@ -27063,6 +27085,11 @@ fn elemPtrArray(
27063 try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op);27085 try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op);
27064 }27086 }
2706527087
27088 if (array_ty.childType(zcu).abiSize(zcu) == 0) {
27089 // zero-bit child type; just bitcast the pointer
27090 return block.addBitCast(elem_ptr_ty, array_ptr);
27091 }
27092
27066 return block.addPtrElemPtr(array_ptr, elem_index, elem_ptr_ty);27093 return block.addPtrElemPtr(array_ptr, elem_index, elem_ptr_ty);
27067}27094}
2706827095
src/Zcu/PerThread.zig+7-1
...@@ -2926,7 +2926,13 @@ fn analyzeFuncBodyInner(...@@ -2926,7 +2926,13 @@ fn analyzeFuncBodyInner(
2926 const param_ty: Type = .fromInterned(fn_ty_info.param_types.get(ip)[runtime_param_index]);2926 const param_ty: Type = .fromInterned(fn_ty_info.param_types.get(ip)[runtime_param_index]);
2927 runtime_param_index += 1;2927 runtime_param_index += 1;
29282928
2929 try sema.ensureLayoutResolved(param_ty, inner_block.src(.{ .func_decl_param_ty = @intCast(zir_param_index) }), .parameter);2929 const param_ty_src = inner_block.src(.{ .func_decl_param_ty = @intCast(zir_param_index) });
2930
2931 try sema.ensureLayoutResolved(param_ty, param_ty_src, .parameter);
2932 if (param_ty.isPtrAtRuntime(zcu) or param_ty.isSliceAtRuntime(zcu)) {
2933 // LLVM wants this information for an "align" attribute on the parameter.
2934 try sema.ensureLayoutResolved(param_ty.nullablePtrElem(zcu), param_ty_src, .parameter);
2935 }
2930 if (try param_ty.onePossibleValue(pt)) |opv| {2936 if (try param_ty.onePossibleValue(pt)) |opv| {
2931 gop.value_ptr.* = .fromValue(opv);2937 gop.value_ptr.* = .fromValue(opv);
2932 continue;2938 continue;
src/codegen/aarch64/abi.zig+1-1
...@@ -13,7 +13,7 @@ pub const Class = union(enum) {...@@ -13,7 +13,7 @@ pub const Class = union(enum) {
1313
14/// For `float_array` the second element will be the amount of floats.14/// For `float_array` the second element will be the amount of floats.
15pub fn classifyType(ty: Type, zcu: *Zcu) Class {15pub fn classifyType(ty: Type, zcu: *Zcu) Class {
16 assert(ty.hasRuntimeBitsIgnoreComptime(zcu));16 assert(ty.hasRuntimeBits(zcu));
1717
18 var maybe_float_bits: ?u16 = null;18 var maybe_float_bits: ?u16 = null;
19 switch (ty.zigTypeTag(zcu)) {19 switch (ty.zigTypeTag(zcu)) {
src/codegen/arm/abi.zig+13-11
...@@ -23,7 +23,7 @@ pub const Class = union(enum) {...@@ -23,7 +23,7 @@ pub const Class = union(enum) {
23pub const Context = enum { ret, arg };23pub const Context = enum { ret, arg };
2424
25pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {25pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
26 assert(ty.hasRuntimeBitsIgnoreComptime(zcu));26 assert(ty.hasRuntimeBits(zcu));
2727
28 var maybe_float_bits: ?u16 = null;28 var maybe_float_bits: ?u16 = null;
29 const max_byval_size = 512;29 const max_byval_size = 512;
...@@ -39,22 +39,22 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {...@@ -39,22 +39,22 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
39 const float_count = countFloats(ty, zcu, &maybe_float_bits);39 const float_count = countFloats(ty, zcu, &maybe_float_bits);
40 if (float_count <= byval_float_count) return .byval;40 if (float_count <= byval_float_count) return .byval;
4141
42 if (ty.abiAlignment(zcu).compare(.gt, .@"32")) {
43 return Class.arrSize(bit_size, 64);
44 }
45
42 const fields = ty.structFieldCount(zcu);46 const fields = ty.structFieldCount(zcu);
43 var i: u32 = 0;47 var i: u32 = 0;
44 while (i < fields) : (i += 1) {48 while (i < fields) : (i += 1) {
45 const field_ty = ty.fieldType(i, zcu);49 const field_ty = ty.fieldType(i, zcu);
46 const field_alignment = ty.fieldAlignment(i, zcu);50 if (field_ty.bitSize(zcu) > 32) return Class.arrSize(bit_size, 64);
47 const field_size = field_ty.bitSize(zcu);
48 if (field_size > 32 or field_alignment.compare(.gt, .@"32")) {
49 return Class.arrSize(bit_size, 64);
50 }
51 }51 }
52 return Class.arrSize(bit_size, 32);52 return Class.arrSize(bit_size, 32);
53 },53 },
54 .@"union" => {54 .@"union" => {
55 const bit_size = ty.bitSize(zcu);55 const bit_size = ty.bitSize(zcu);
56 const union_obj = zcu.typeToUnion(ty).?;56 const union_obj = zcu.typeToUnion(ty).?;
57 if (union_obj.flagsUnordered(ip).layout == .@"packed") {57 if (union_obj.layout == .@"packed") {
58 if (bit_size > 64) return .memory;58 if (bit_size > 64) return .memory;
59 return .byval;59 return .byval;
60 }60 }
...@@ -62,10 +62,12 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {...@@ -62,10 +62,12 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
62 const float_count = countFloats(ty, zcu, &maybe_float_bits);62 const float_count = countFloats(ty, zcu, &maybe_float_bits);
63 if (float_count <= byval_float_count) return .byval;63 if (float_count <= byval_float_count) return .byval;
6464
65 for (union_obj.field_types.get(ip), 0..) |field_ty, field_index| {65 if (union_obj.alignment.compareStrict(.gt, .@"32")) {
66 if (Type.fromInterned(field_ty).bitSize(zcu) > 32 or66 return Class.arrSize(bit_size, 64);
67 ty.fieldAlignment(field_index, zcu).compare(.gt, .@"32"))67 }
68 {68
69 for (union_obj.field_types.get(ip)) |field_ty| {
70 if (Type.fromInterned(field_ty).bitSize(zcu) > 32) {
69 return Class.arrSize(bit_size, 64);71 return Class.arrSize(bit_size, 64);
70 }72 }
71 }73 }
src/codegen/llvm.zig+729-886
...@@ -23,6 +23,7 @@ const Package = @import("../Package.zig");...@@ -23,6 +23,7 @@ const Package = @import("../Package.zig");
23const Air = @import("../Air.zig");23const Air = @import("../Air.zig");
24const Value = @import("../Value.zig");24const Value = @import("../Value.zig");
25const Type = @import("../Type.zig");25const Type = @import("../Type.zig");
26const DebugConstPool = link.DebugConstPool;
26const codegen = @import("../codegen.zig");27const codegen = @import("../codegen.zig");
27const x86_64_abi = @import("x86_64/abi.zig");28const x86_64_abi = @import("x86_64/abi.zig");
28const wasm_c_abi = @import("wasm/abi.zig");29const wasm_c_abi = @import("wasm/abi.zig");
...@@ -529,9 +530,15 @@ pub const Object = struct {...@@ -529,9 +530,15 @@ pub const Object = struct {
529 debug_globals: std.ArrayList(Builder.Metadata),530 debug_globals: std.ArrayList(Builder.Metadata),
530531
531 debug_file_map: std.AutoHashMapUnmanaged(Zcu.File.Index, Builder.Metadata),532 debug_file_map: std.AutoHashMapUnmanaged(Zcu.File.Index, Builder.Metadata),
532 debug_type_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Metadata),
533533
534 debug_unresolved_namespace_scopes: std.AutoArrayHashMapUnmanaged(InternPool.NamespaceIndex, Builder.Metadata),534 /// This pool *only* contains types (and does not contain `@as(type, undefined)`).
535 debug_type_pool: DebugConstPool,
536 /// Keyed on `DebugConstPool.Index`.
537 debug_types: std.ArrayList(Builder.Metadata),
538 /// Initially `.none`, set if the type `anyerror` is lowered to a debug type. The type will not
539 /// actually be created until `emit`, which must resolve this reference with an appropriate enum
540 /// type from the global error set.
541 debug_anyerror_fwd_ref: Builder.Metadata.Optional,
535542
536 target: *const std.Target,543 target: *const std.Target,
537 /// Ideally we would use `llvm_module.getNamedFunction` to go from *Decl to LLVM function,544 /// Ideally we would use `llvm_module.getNamedFunction` to go from *Decl to LLVM function,
...@@ -657,21 +664,22 @@ pub const Object = struct {...@@ -657,21 +664,22 @@ pub const Object = struct {
657 .debug_compile_unit = debug_compile_unit,664 .debug_compile_unit = debug_compile_unit,
658 .debug_enums_fwd_ref = debug_enums_fwd_ref,665 .debug_enums_fwd_ref = debug_enums_fwd_ref,
659 .debug_globals_fwd_ref = debug_globals_fwd_ref,666 .debug_globals_fwd_ref = debug_globals_fwd_ref,
660 .debug_enums = .{},667 .debug_enums = .empty,
661 .debug_globals = .{},668 .debug_globals = .empty,
662 .debug_file_map = .{},669 .debug_file_map = .empty,
663 .debug_type_map = .{},670 .debug_type_pool = .empty,
664 .debug_unresolved_namespace_scopes = .{},671 .debug_types = .empty,
672 .debug_anyerror_fwd_ref = .none,
665 .target = target,673 .target = target,
666 .nav_map = .{},674 .nav_map = .empty,
667 .uav_map = .{},675 .uav_map = .empty,
668 .enum_tag_name_map = .{},676 .enum_tag_name_map = .empty,
669 .named_enum_map = .{},677 .named_enum_map = .empty,
670 .type_map = .{},678 .type_map = .empty,
671 .error_name_table = .none,679 .error_name_table = .none,
672 .null_opt_usize = .no_init,680 .null_opt_usize = .no_init,
673 .struct_field_map = .{},681 .struct_field_map = .empty,
674 .used = .{},682 .used = .empty,
675 };683 };
676 return obj;684 return obj;
677 }685 }
...@@ -681,8 +689,8 @@ pub const Object = struct {...@@ -681,8 +689,8 @@ pub const Object = struct {
681 self.debug_enums.deinit(gpa);689 self.debug_enums.deinit(gpa);
682 self.debug_globals.deinit(gpa);690 self.debug_globals.deinit(gpa);
683 self.debug_file_map.deinit(gpa);691 self.debug_file_map.deinit(gpa);
684 self.debug_type_map.deinit(gpa);692 self.debug_type_pool.deinit(gpa);
685 self.debug_unresolved_namespace_scopes.deinit(gpa);693 self.debug_types.deinit(gpa);
686 self.nav_map.deinit(gpa);694 self.nav_map.deinit(gpa);
687 self.uav_map.deinit(gpa);695 self.uav_map.deinit(gpa);
688 self.enum_tag_name_map.deinit(gpa);696 self.enum_tag_name_map.deinit(gpa);
...@@ -824,19 +832,13 @@ pub const Object = struct {...@@ -824,19 +832,13 @@ pub const Object = struct {
824 }832 }
825833
826 if (!o.builder.strip) {834 if (!o.builder.strip) {
827 {835 if (o.debug_anyerror_fwd_ref.unwrap()) |fwd_ref| {
828 var i: usize = 0;836 const debug_anyerror_type = try o.lowerDebugAnyerrorType(pt);
829 while (i < o.debug_unresolved_namespace_scopes.count()) : (i += 1) {837 o.builder.resolveDebugForwardReference(fwd_ref, debug_anyerror_type);
830 const namespace_index = o.debug_unresolved_namespace_scopes.keys()[i];
831 const fwd_ref = o.debug_unresolved_namespace_scopes.values()[i];
832
833 const namespace = zcu.namespacePtr(namespace_index);
834 const debug_type = try o.lowerDebugType(pt, Type.fromInterned(namespace.owner_type));
835
836 o.builder.resolveDebugForwardReference(fwd_ref, debug_type);
837 }
838 }838 }
839839
840 try o.flushPendingDebugTypes(pt);
841
840 o.builder.resolveDebugForwardReference(842 o.builder.resolveDebugForwardReference(
841 o.debug_enums_fwd_ref.unwrap().?,843 o.debug_enums_fwd_ref.unwrap().?,
842 try o.builder.metadataTuple(o.debug_enums.items),844 try o.builder.metadataTuple(o.debug_enums.items),
...@@ -1472,7 +1474,7 @@ pub const Object = struct {...@@ -1472,7 +1474,7 @@ pub const Object = struct {
14721474
1473 const line_number = zcu.navSrcLine(func.owner_nav) + 1;1475 const line_number = zcu.navSrcLine(func.owner_nav) + 1;
1474 const is_internal_linkage = ip.indexToKey(nav.status.fully_resolved.val) != .@"extern";1476 const is_internal_linkage = ip.indexToKey(nav.status.fully_resolved.val) != .@"extern";
1475 const debug_decl_type = try o.lowerDebugType(pt, fn_ty);1477 const debug_decl_type = try o.getDebugType(pt, fn_ty);
14761478
1477 const subprogram = try o.builder.debugSubprogram(1479 const subprogram = try o.builder.debugSubprogram(
1478 file,1480 file,
...@@ -1522,7 +1524,7 @@ pub const Object = struct {...@@ -1522,7 +1524,7 @@ pub const Object = struct {
15221524
1523 break :f .{1525 break :f .{
1524 .counters_variable = counters_variable,1526 .counters_variable = counters_variable,
1525 .pcs = .{},1527 .pcs = .empty,
1526 };1528 };
1527 };1529 };
15281530
...@@ -1538,10 +1540,10 @@ pub const Object = struct {...@@ -1538,10 +1540,10 @@ pub const Object = struct {
1538 .args = args.items,1540 .args = args.items,
1539 .arg_index = 0,1541 .arg_index = 0,
1540 .arg_inline_index = 0,1542 .arg_inline_index = 0,
1541 .func_inst_table = .{},1543 .func_inst_table = .empty,
1542 .blocks = .{},1544 .blocks = .empty,
1543 .loops = .{},1545 .loops = .empty,
1544 .switch_dispatch_info = .{},1546 .switch_dispatch_info = .empty,
1545 .sync_scope = if (owner_mod.single_threaded) .singlethread else .system,1547 .sync_scope = if (owner_mod.single_threaded) .singlethread else .system,
1546 .file = file,1548 .file = file,
1547 .scope = subprogram,1549 .scope = subprogram,
...@@ -1599,6 +1601,7 @@ pub const Object = struct {...@@ -1599,6 +1601,7 @@ pub const Object = struct {
1599 }1601 }
16001602
1601 try fg.wip.finish();1603 try fg.wip.finish();
1604 try o.flushPendingDebugTypes(pt);
1602 }1605 }
16031606
1604 pub fn updateNav(self: *Object, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {1607 pub fn updateNav(self: *Object, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {
...@@ -1615,6 +1618,14 @@ pub const Object = struct {...@@ -1615,6 +1618,14 @@ pub const Object = struct {
1615 },1618 },
1616 else => |e| return e,1619 else => |e| return e,
1617 };1620 };
1621 try self.flushPendingDebugTypes(pt);
1622 }
1623
1624 fn flushPendingDebugTypes(o: *Object, pt: Zcu.PerThread) Allocator.Error!void {
1625 o.debug_type_pool.flushPending(pt, .{ .llvm = o }) catch |err| switch (err) {
1626 error.OutOfMemory => |e| return e,
1627 else => unreachable, // TODO: stop self-hosted backends from returning all of this crap!
1628 };
1618 }1629 }
16191630
1620 pub fn updateExports(1631 pub fn updateExports(
...@@ -1810,6 +1821,57 @@ pub const Object = struct {...@@ -1810,6 +1821,57 @@ pub const Object = struct {
1810 }1821 }
1811 }1822 }
18121823
1824 pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Allocator.Error!void {
1825 if (!o.builder.strip) {
1826 o.debug_type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success) catch |err| switch (err) {
1827 error.OutOfMemory => |e| return e,
1828 else => unreachable, // TODO: stop self-hosted backends from returning all of this crap!
1829 };
1830 }
1831 }
1832
1833 /// Should only be called by the `DebugConstPool` implementation.
1834 ///
1835 /// `val` is always a type because `o.debug_type_pool` only contains types.
1836 pub fn addConst(o: *Object, pt: Zcu.PerThread, index: DebugConstPool.Index, val: InternPool.Index) Allocator.Error!void {
1837 const zcu = pt.zcu;
1838 const gpa = zcu.comp.gpa;
1839 assert(zcu.intern_pool.typeOf(val) == .type_type);
1840 assert(@intFromEnum(index) == o.debug_types.items.len);
1841 try o.debug_types.ensureUnusedCapacity(gpa, 1);
1842 const fwd_ref = try o.builder.debugForwardReference();
1843 o.debug_types.appendAssumeCapacity(fwd_ref);
1844 if (val == .anyerror_type) {
1845 assert(o.debug_anyerror_fwd_ref.is_none);
1846 o.debug_anyerror_fwd_ref = fwd_ref.toOptional();
1847 }
1848 }
1849 /// Should only be called by the `DebugConstPool` implementation.
1850 ///
1851 /// `val` is always a type because `o.debug_type_pool` only contains types.
1852 pub fn updateConstIncomplete(o: *Object, pt: Zcu.PerThread, index: DebugConstPool.Index, val: InternPool.Index) Allocator.Error!void {
1853 assert(pt.zcu.intern_pool.typeOf(val) == .type_type);
1854 const fwd_ref = o.debug_types.items[@intFromEnum(index)];
1855 assert(val != .anyerror_type);
1856 const name_str = try o.builder.metadataStringFmt("{f}", .{Type.fromInterned(val).fmt(pt)});
1857 const debug_incomplete_type = try o.builder.debugSignedType(name_str, 0);
1858 o.builder.resolveDebugForwardReference(fwd_ref, debug_incomplete_type);
1859 }
1860 /// Should only be called by the `DebugConstPool` implementation.
1861 ///
1862 /// `val` is always a type because `o.debug_type_pool` only contains types.
1863 pub fn updateConst(o: *Object, pt: Zcu.PerThread, index: DebugConstPool.Index, val: InternPool.Index) Allocator.Error!void {
1864 assert(pt.zcu.intern_pool.typeOf(val) == .type_type);
1865 const fwd_ref = o.debug_types.items[@intFromEnum(index)];
1866 if (val == .anyerror_type) {
1867 // Don't lower this now; it will be populated in `emit` instead.
1868 assert(o.debug_anyerror_fwd_ref == fwd_ref.toOptional());
1869 return;
1870 }
1871 const debug_type = try o.lowerDebugType(pt, .fromInterned(val), fwd_ref);
1872 o.builder.resolveDebugForwardReference(fwd_ref, debug_type);
1873 }
1874
1813 fn getDebugFile(o: *Object, pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator.Error!Builder.Metadata {1875 fn getDebugFile(o: *Object, pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator.Error!Builder.Metadata {
1814 const gpa = o.gpa;1876 const gpa = o.gpa;
1815 const gop = try o.debug_file_map.getOrPut(gpa, file_index);1877 const gop = try o.debug_file_map.getOrPut(gpa, file_index);
...@@ -1826,10 +1888,22 @@ pub const Object = struct {...@@ -1826,10 +1888,22 @@ pub const Object = struct {
1826 return gop.value_ptr.*;1888 return gop.value_ptr.*;
1827 }1889 }
18281890
1829 pub fn lowerDebugType(1891 fn getDebugType(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error!Builder.Metadata {
1892 assert(!o.builder.strip);
1893 const index = o.debug_type_pool.get(pt, .{ .llvm = o }, ty.toIntern()) catch |err| switch (err) {
1894 error.OutOfMemory => |e| return e,
1895 else => unreachable, // TODO: stop self-hosted backends from returning all of this crap!
1896 };
1897 return o.debug_types.items[@intFromEnum(index)];
1898 }
1899
1900 /// In codegen logic, instead of calling this directly, use `getDebugType` to get a forward
1901 /// reference which will be populated only when all necessary type resolution is complete.
1902 fn lowerDebugType(
1830 o: *Object,1903 o: *Object,
1831 pt: Zcu.PerThread,1904 pt: Zcu.PerThread,
1832 ty: Type,1905 ty: Type,
1906 ty_fwd_ref: Builder.Metadata,
1833 ) Allocator.Error!Builder.Metadata {1907 ) Allocator.Error!Builder.Metadata {
1834 assert(!o.builder.strip);1908 assert(!o.builder.strip);
18351909
...@@ -1838,267 +1912,96 @@ pub const Object = struct {...@@ -1838,267 +1912,96 @@ pub const Object = struct {
1838 const zcu = pt.zcu;1912 const zcu = pt.zcu;
1839 const ip = &zcu.intern_pool;1913 const ip = &zcu.intern_pool;
18401914
1841 if (o.debug_type_map.get(ty.toIntern())) |debug_type| return debug_type;1915 const name = try o.builder.metadataStringFmt("{f}", .{ty.fmt(pt)});
18421916
1843 switch (ty.zigTypeTag(zcu)) {1917 switch (ty.zigTypeTag(zcu)) {
1844 .void,1918 .void,
1845 .noreturn,1919 .noreturn,
1846 => {1920 .comptime_int,
1847 const debug_void_type = try o.builder.debugSignedType(1921 .comptime_float,
1848 try o.builder.metadataString("void"),1922 .type,
1849 0,1923 .undefined,
1850 );1924 .null,
1851 try o.debug_type_map.put(gpa, ty.toIntern(), debug_void_type);1925 .enum_literal,
1852 return debug_void_type;1926 => return o.builder.debugSignedType(name, 0),
1853 },1927
1854 .int => {1928 .int => {
1855 const info = ty.intInfo(zcu);1929 const info = ty.intInfo(zcu);
1856 assert(info.bits != 0);1930 const bits = ty.abiSize(zcu) * 8; // lldb cannot handle non-byte sized types
1857 const name = try o.allocTypeName(pt, ty);1931 return switch (info.signedness) {
1858 defer gpa.free(name);1932 .signed => try o.builder.debugSignedType(name, bits),
1859 const builder_name = try o.builder.metadataString(name);1933 .unsigned => try o.builder.debugUnsignedType(name, bits),
1860 const debug_bits = ty.abiSize(zcu) * 8; // lldb cannot handle non-byte sized types
1861 const debug_int_type = switch (info.signedness) {
1862 .signed => try o.builder.debugSignedType(builder_name, debug_bits),
1863 .unsigned => try o.builder.debugUnsignedType(builder_name, debug_bits),
1864 };1934 };
1865 try o.debug_type_map.put(gpa, ty.toIntern(), debug_int_type);
1866 return debug_int_type;
1867 },
1868 .@"enum" => {
1869 if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) {
1870 const debug_enum_type = try o.makeEmptyNamespaceDebugType(pt, ty);
1871 try o.debug_type_map.put(gpa, ty.toIntern(), debug_enum_type);
1872 return debug_enum_type;
1873 }
1874
1875 const enum_type = ip.loadEnumType(ty.toIntern());
1876 const enumerators = try gpa.alloc(Builder.Metadata, enum_type.names.len);
1877 defer gpa.free(enumerators);
1878
1879 const int_ty = Type.fromInterned(enum_type.tag_ty);
1880 const int_info = ty.intInfo(zcu);
1881 assert(int_info.bits != 0);
1882
1883 for (enum_type.names.get(ip), 0..) |field_name_ip, i| {
1884 var bigint_space: Value.BigIntSpace = undefined;
1885 const bigint = if (enum_type.values.len != 0)
1886 Value.fromInterned(enum_type.values.get(ip)[i]).toBigInt(&bigint_space, zcu)
1887 else
1888 std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst();
1889
1890 enumerators[i] = try o.builder.debugEnumerator(
1891 try o.builder.metadataString(field_name_ip.toSlice(ip)),
1892 int_info.signedness == .unsigned,
1893 int_info.bits,
1894 bigint,
1895 );
1896 }
1897
1898 const file = try o.getDebugFile(pt, ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip));
1899 const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace|
1900 try o.namespaceToDebugScope(pt, parent_namespace)
1901 else
1902 file;
1903
1904 const name = try o.allocTypeName(pt, ty);
1905 defer gpa.free(name);
1906
1907 const debug_enum_type = try o.builder.debugEnumerationType(
1908 try o.builder.metadataString(name),
1909 file,
1910 scope,
1911 ty.typeDeclSrcLine(zcu).? + 1, // Line
1912 try o.lowerDebugType(pt, int_ty),
1913 ty.abiSize(zcu) * 8,
1914 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,
1915 try o.builder.metadataTuple(enumerators),
1916 );
1917
1918 try o.debug_type_map.put(gpa, ty.toIntern(), debug_enum_type);
1919 try o.debug_enums.append(gpa, debug_enum_type);
1920 return debug_enum_type;
1921 },1935 },
1922 .float => {1936 .float => {
1923 const bits = ty.floatBits(target);1937 return o.builder.debugFloatType(name, ty.floatBits(target));
1924 const name = try o.allocTypeName(pt, ty);
1925 defer gpa.free(name);
1926 const debug_float_type = try o.builder.debugFloatType(
1927 try o.builder.metadataString(name),
1928 bits,
1929 );
1930 try o.debug_type_map.put(gpa, ty.toIntern(), debug_float_type);
1931 return debug_float_type;
1932 },1938 },
1933 .bool => {1939 .bool => {
1934 const debug_bool_type = try o.builder.debugBoolType(1940 return o.builder.debugBoolType(
1935 try o.builder.metadataString("bool"),1941 name,
1936 8, // lldb cannot handle non-byte sized types1942 8, // lldb cannot handle non-byte sized types
1937 );1943 );
1938 try o.debug_type_map.put(gpa, ty.toIntern(), debug_bool_type);
1939 return debug_bool_type;
1940 },1944 },
1941 .pointer => {1945 .pointer => {
1942 // Normalize everything that the debug info does not represent.1946 const ptr_size = Type.ptrAbiSize(zcu.getTarget());
1943 const ptr_info = ty.ptrInfo(zcu);1947 const ptr_align = Type.ptrAbiAlignment(zcu.getTarget());
1944
1945 if (ptr_info.sentinel != .none or
1946 ptr_info.flags.address_space != .generic or
1947 ptr_info.packed_offset.bit_offset != 0 or
1948 ptr_info.packed_offset.host_size != 0 or
1949 ptr_info.flags.vector_index != .none or
1950 ptr_info.flags.is_allowzero or
1951 ptr_info.flags.is_const or
1952 ptr_info.flags.is_volatile or
1953 ptr_info.flags.size == .many or ptr_info.flags.size == .c or
1954 !Type.fromInterned(ptr_info.child).hasRuntimeBitsIgnoreComptime(zcu))
1955 {
1956 const bland_ptr_ty = try pt.ptrType(.{
1957 .child = if (!Type.fromInterned(ptr_info.child).hasRuntimeBitsIgnoreComptime(zcu))
1958 .anyopaque_type
1959 else
1960 ptr_info.child,
1961 .flags = .{
1962 .alignment = ptr_info.flags.alignment,
1963 .size = switch (ptr_info.flags.size) {
1964 .many, .c, .one => .one,
1965 .slice => .slice,
1966 },
1967 },
1968 });
1969 const debug_ptr_type = try o.lowerDebugType(pt, bland_ptr_ty);
1970 try o.debug_type_map.put(gpa, ty.toIntern(), debug_ptr_type);
1971 return debug_ptr_type;
1972 }
1973
1974 const debug_fwd_ref = try o.builder.debugForwardReference();
1975
1976 // Set as forward reference while the type is lowered in case it references itself
1977 try o.debug_type_map.put(gpa, ty.toIntern(), debug_fwd_ref);
19781948
1979 if (ty.isSlice(zcu)) {1949 if (ty.isSlice(zcu)) {
1980 const ptr_ty = ty.slicePtrFieldType(zcu);
1981 const len_ty = Type.usize;
1982
1983 const name = try o.allocTypeName(pt, ty);
1984 defer gpa.free(name);
1985 const line = 0;
1986
1987 const ptr_size = ptr_ty.abiSize(zcu);
1988 const ptr_align = ptr_ty.abiAlignment(zcu);
1989 const len_size = len_ty.abiSize(zcu);
1990 const len_align = len_ty.abiAlignment(zcu);
1991
1992 const len_offset = len_align.forward(ptr_size);
1993
1994 const debug_ptr_type = try o.builder.debugMemberType(1950 const debug_ptr_type = try o.builder.debugMemberType(
1995 try o.builder.metadataString("ptr"),1951 try o.builder.metadataString("ptr"),
1996 null, // File1952 null, // File
1997 debug_fwd_ref,1953 ty_fwd_ref,
1998 0, // Line1954 0, // Line
1999 try o.lowerDebugType(pt, ptr_ty),1955 try o.getDebugType(pt, ty.slicePtrFieldType(zcu)),
2000 ptr_size * 8,1956 ptr_size * 8,
2001 (ptr_align.toByteUnits() orelse 0) * 8,1957 ptr_align.toByteUnits().? * 8,
2002 0, // Offset1958 0, // Offset
2003 );1959 );
20041960
2005 const debug_len_type = try o.builder.debugMemberType(1961 const debug_len_type = try o.builder.debugMemberType(
2006 try o.builder.metadataString("len"),1962 try o.builder.metadataString("len"),
2007 null, // File1963 null, // File
2008 debug_fwd_ref,1964 ty_fwd_ref,
2009 0, // Line1965 0, // Line
2010 try o.lowerDebugType(pt, len_ty),1966 try o.getDebugType(pt, .usize),
2011 len_size * 8,1967 ptr_size * 8,
2012 (len_align.toByteUnits() orelse 0) * 8,1968 ptr_align.toByteUnits().? * 8,
2013 len_offset * 8,1969 ptr_size * 8,
2014 );1970 );
20151971
2016 const debug_slice_type = try o.builder.debugStructType(1972 return o.builder.debugStructType(
2017 try o.builder.metadataString(name),1973 name,
2018 null, // File1974 null, // File
2019 o.debug_compile_unit.unwrap().?, // Scope1975 o.debug_compile_unit.unwrap().?, // Scope
2020 line,1976 0, // Line
2021 null, // Underlying type1977 null, // Underlying type
2022 ty.abiSize(zcu) * 8,1978 ptr_size * 2 * 8,
2023 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,1979 ptr_align.toByteUnits().? * 8,
2024 try o.builder.metadataTuple(&.{1980 try o.builder.metadataTuple(&.{
2025 debug_ptr_type,1981 debug_ptr_type,
2026 debug_len_type,1982 debug_len_type,
2027 }),1983 }),
2028 );1984 );
2029
2030 o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_slice_type);
2031
2032 // Set to real type now that it has been lowered fully
2033 const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable;
2034 map_ptr.* = debug_slice_type;
2035
2036 return debug_slice_type;
2037 }1985 }
20381986
2039 const debug_elem_ty = try o.lowerDebugType(pt, Type.fromInterned(ptr_info.child));1987 return o.builder.debugPointerType(
20401988 name,
2041 const name = try o.allocTypeName(pt, ty);
2042 defer gpa.free(name);
2043
2044 const debug_ptr_type = try o.builder.debugPointerType(
2045 try o.builder.metadataString(name),
2046 null, // File1989 null, // File
2047 null, // Scope1990 null, // Scope
2048 0, // Line1991 0, // Line
2049 debug_elem_ty,1992 try o.getDebugType(pt, ty.childType(zcu)),
2050 target.ptrBitWidth(),1993 ptr_size * 8,
2051 (ty.ptrAlignment(zcu).toByteUnits() orelse 0) * 8,1994 ptr_align.toByteUnits().? * 8,
2052 0, // Offset1995 0, // Offset
2053 );1996 );
2054
2055 o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_ptr_type);
2056
2057 // Set to real type now that it has been lowered fully
2058 const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable;
2059 map_ptr.* = debug_ptr_type;
2060
2061 return debug_ptr_type;
2062 },
2063 .@"opaque" => {
2064 if (ty.toIntern() == .anyopaque_type) {
2065 const debug_opaque_type = try o.builder.debugSignedType(
2066 try o.builder.metadataString("anyopaque"),
2067 0,
2068 );
2069 try o.debug_type_map.put(gpa, ty.toIntern(), debug_opaque_type);
2070 return debug_opaque_type;
2071 }
2072
2073 const name = try o.allocTypeName(pt, ty);
2074 defer gpa.free(name);
2075
2076 const file = try o.getDebugFile(pt, ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip));
2077 const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace|
2078 try o.namespaceToDebugScope(pt, parent_namespace)
2079 else
2080 file;
2081
2082 const debug_opaque_type = try o.builder.debugStructType(
2083 try o.builder.metadataString(name),
2084 file,
2085 scope,
2086 ty.typeDeclSrcLine(zcu).? + 1, // Line
2087 null, // Underlying type
2088 0, // Size
2089 0, // Align
2090 null, // Fields
2091 );
2092 try o.debug_type_map.put(gpa, ty.toIntern(), debug_opaque_type);
2093 return debug_opaque_type;
2094 },1997 },
2095 .array => {1998 .array => {
2096 const debug_array_type = try o.builder.debugArrayType(1999 return o.builder.debugArrayType(
2097 null, // Name2000 null, // Name
2098 null, // File2001 null, // File
2099 null, // Scope2002 null, // Scope
2100 0, // Line2003 0, // Line
2101 try o.lowerDebugType(pt, ty.childType(zcu)),2004 try o.getDebugType(pt, ty.childType(zcu)),
2102 ty.abiSize(zcu) * 8,2005 ty.abiSize(zcu) * 8,
2103 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,2006 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,
2104 try o.builder.metadataTuple(&.{2007 try o.builder.metadataTuple(&.{
...@@ -2108,8 +2011,6 @@ pub const Object = struct {...@@ -2108,8 +2011,6 @@ pub const Object = struct {
2108 ),2011 ),
2109 }),2012 }),
2110 );2013 );
2111 try o.debug_type_map.put(gpa, ty.toIntern(), debug_array_type);
2112 return debug_array_type;
2113 },2014 },
2114 .vector => {2015 .vector => {
2115 const elem_ty = ty.childType(zcu);2016 const elem_ty = ty.childType(zcu);
...@@ -2120,23 +2021,17 @@ pub const Object = struct {...@@ -2120,23 +2021,17 @@ pub const Object = struct {
2120 const debug_elem_type = switch (elem_ty.zigTypeTag(zcu)) {2021 const debug_elem_type = switch (elem_ty.zigTypeTag(zcu)) {
2121 .int => blk: {2022 .int => blk: {
2122 const info = elem_ty.intInfo(zcu);2023 const info = elem_ty.intInfo(zcu);
2123 assert(info.bits != 0);
2124 const name = try o.allocTypeName(pt, ty);
2125 defer gpa.free(name);
2126 const builder_name = try o.builder.metadataString(name);
2127 break :blk switch (info.signedness) {2024 break :blk switch (info.signedness) {
2128 .signed => try o.builder.debugSignedType(builder_name, info.bits),2025 .signed => try o.builder.debugSignedType(name, info.bits),
2129 .unsigned => try o.builder.debugUnsignedType(builder_name, info.bits),2026 .unsigned => try o.builder.debugUnsignedType(name, info.bits),
2130 };2027 };
2131 },2028 },
2132 .bool => try o.builder.debugBoolType(2029 .bool => try o.builder.debugBoolType(try o.builder.metadataString("bool"), 1),
2133 try o.builder.metadataString("bool"),2030 .pointer, .optional, .float => try o.getDebugType(pt, elem_ty),
2134 1,2031 else => unreachable,
2135 ),
2136 else => try o.lowerDebugType(pt, ty.childType(zcu)),
2137 };2032 };
21382033
2139 const debug_vector_type = try o.builder.debugVectorType(2034 return o.builder.debugVectorType(
2140 null, // Name2035 null, // Name
2141 null, // File2036 null, // File
2142 null, // Scope2037 null, // Scope
...@@ -2151,71 +2046,64 @@ pub const Object = struct {...@@ -2151,71 +2046,64 @@ pub const Object = struct {
2151 ),2046 ),
2152 }),2047 }),
2153 );2048 );
2154
2155 try o.debug_type_map.put(gpa, ty.toIntern(), debug_vector_type);
2156 return debug_vector_type;
2157 },2049 },
2158 .optional => {2050 .optional => {
2159 const name = try o.allocTypeName(pt, ty);2051 const payload_ty = ty.optionalChild(zcu);
2160 defer gpa.free(name);2052 if (ty.optionalReprIsPayload(zcu)) {
2161 const child_ty = ty.optionalChild(zcu);2053 // MLUGG TODO: these should use DW_TAG_typedef instead, but std.zig.llvm.Builder currently lacks support for those.
2162 if (!child_ty.hasRuntimeBitsIgnoreComptime(zcu)) {2054 const payload_member = try o.builder.debugMemberType(
2163 const debug_bool_type = try o.builder.debugBoolType(2055 try o.builder.metadataString("payload"),
2164 try o.builder.metadataString(name),2056 null, // file
2165 8,2057 ty_fwd_ref,
2058 0, // line
2059 try o.getDebugType(pt, .anyerror),
2060 ty.abiSize(zcu) * 8,
2061 ty.abiAlignment(zcu).toByteUnits().? * 8,
2062 0, // offset
2063 );
2064 return o.builder.debugStructType(
2065 name,
2066 null, // file
2067 o.debug_compile_unit.unwrap().?, // scope
2068 0, // line
2069 null, // underlying type
2070 ty.abiSize(zcu) * 8,
2071 ty.abiAlignment(zcu).toByteUnits().? * 8,
2072 try o.builder.metadataTuple(&.{payload_member}),
2166 );2073 );
2167 try o.debug_type_map.put(gpa, ty.toIntern(), debug_bool_type);
2168 return debug_bool_type;
2169 }2074 }
21702075
2171 const debug_fwd_ref = try o.builder.debugForwardReference();2076 const payload_size = payload_ty.abiSize(zcu);
2172
2173 // Set as forward reference while the type is lowered in case it references itself
2174 try o.debug_type_map.put(gpa, ty.toIntern(), debug_fwd_ref);
2175
2176 if (ty.optionalReprIsPayload(zcu)) {
2177 const debug_optional_type = try o.lowerDebugType(pt, child_ty);
2178
2179 o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_optional_type);
2180
2181 // Set to real type now that it has been lowered fully
2182 const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable;
2183 map_ptr.* = debug_optional_type;
2184
2185 return debug_optional_type;
2186 }
21872077
2188 const non_null_ty = Type.u8;2078 const non_null_ty = Type.u8;
2189 const payload_size = child_ty.abiSize(zcu);
2190 const payload_align = child_ty.abiAlignment(zcu);
2191 const non_null_size = non_null_ty.abiSize(zcu);2079 const non_null_size = non_null_ty.abiSize(zcu);
2192 const non_null_align = non_null_ty.abiAlignment(zcu);2080 const non_null_align = non_null_ty.abiAlignment(zcu);
2193 const non_null_offset = non_null_align.forward(payload_size);2081 const non_null_offset = non_null_align.forward(payload_size);
21942082
2195 const debug_data_type = try o.builder.debugMemberType(2083 const debug_payload_type = try o.builder.debugMemberType(
2196 try o.builder.metadataString("data"),2084 try o.builder.metadataString("payload"),
2197 null, // File2085 null, // file
2198 debug_fwd_ref,2086 ty_fwd_ref,
2199 0, // Line2087 0, // line
2200 try o.lowerDebugType(pt, child_ty),2088 try o.getDebugType(pt, payload_ty),
2201 payload_size * 8,2089 payload_size * 8,
2202 (payload_align.toByteUnits() orelse 0) * 8,2090 payload_ty.abiAlignment(zcu).toByteUnits().? * 8,
2203 0, // Offset2091 0, // offset
2204 );2092 );
22052093
2206 const debug_some_type = try o.builder.debugMemberType(2094 const debug_some_type = try o.builder.debugMemberType(
2207 try o.builder.metadataString("some"),2095 try o.builder.metadataString("some"),
2208 null,2096 null,
2209 debug_fwd_ref,2097 ty_fwd_ref,
2210 0,2098 0,
2211 try o.lowerDebugType(pt, non_null_ty),2099 try o.getDebugType(pt, non_null_ty),
2212 non_null_size * 8,2100 non_null_size * 8,
2213 (non_null_align.toByteUnits() orelse 0) * 8,2101 non_null_align.toByteUnits().? * 8,
2214 non_null_offset * 8,2102 non_null_offset * 8,
2215 );2103 );
22162104
2217 const debug_optional_type = try o.builder.debugStructType(2105 return o.builder.debugStructType(
2218 try o.builder.metadataString(name),2106 name,
2219 null, // File2107 null, // File
2220 o.debug_compile_unit.unwrap().?, // Scope2108 o.debug_compile_unit.unwrap().?, // Scope
2221 0, // Line2109 0, // Line
...@@ -2223,494 +2111,498 @@ pub const Object = struct {...@@ -2223,494 +2111,498 @@ pub const Object = struct {
2223 ty.abiSize(zcu) * 8,2111 ty.abiSize(zcu) * 8,
2224 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,2112 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,
2225 try o.builder.metadataTuple(&.{2113 try o.builder.metadataTuple(&.{
2226 debug_data_type,2114 debug_payload_type,
2227 debug_some_type,2115 debug_some_type,
2228 }),2116 }),
2229 );2117 );
2230
2231 o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_optional_type);
2232
2233 // Set to real type now that it has been lowered fully
2234 const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable;
2235 map_ptr.* = debug_optional_type;
2236
2237 return debug_optional_type;
2238 },2118 },
2239 .error_union => {2119 .error_union => {
2120 const error_ty = ty.errorUnionSet(zcu);
2240 const payload_ty = ty.errorUnionPayload(zcu);2121 const payload_ty = ty.errorUnionPayload(zcu);
2241 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
2242 // TODO: Maybe remove?
2243 const debug_error_union_type = try o.lowerDebugType(pt, Type.anyerror);
2244 try o.debug_type_map.put(gpa, ty.toIntern(), debug_error_union_type);
2245 return debug_error_union_type;
2246 }
2247
2248 const name = try o.allocTypeName(pt, ty);
2249 defer gpa.free(name);
22502122
2251 const error_size = Type.anyerror.abiSize(zcu);2123 const error_size = error_ty.abiSize(zcu);
2252 const error_align = Type.anyerror.abiAlignment(zcu);2124 const error_align = error_ty.abiAlignment(zcu);
2253 const payload_size = payload_ty.abiSize(zcu);2125 const payload_size = payload_ty.abiSize(zcu);
2254 const payload_align = payload_ty.abiAlignment(zcu);2126 const payload_align = payload_ty.abiAlignment(zcu);
22552127
2256 var error_index: u32 = undefined;2128 const error_index: u1, const payload_index: u1, const error_offset: u64, const payload_offset: u64 = fields: {
2257 var payload_index: u32 = undefined;2129 if (error_align.compare(.gt, payload_align)) {
2258 var error_offset: u64 = undefined;2130 break :fields .{ 0, 1, 0, payload_align.forward(error_size) };
2259 var payload_offset: u64 = undefined;2131 } else {
2260 if (error_align.compare(.gt, payload_align)) {2132 break :fields .{ 1, 0, error_align.forward(payload_size), 0 };
2261 error_index = 0;2133 }
2262 payload_index = 1;2134 };
2263 error_offset = 0;
2264 payload_offset = payload_align.forward(error_size);
2265 } else {
2266 payload_index = 0;
2267 error_index = 1;
2268 payload_offset = 0;
2269 error_offset = error_align.forward(payload_size);
2270 }
2271
2272 const debug_fwd_ref = try o.builder.debugForwardReference();
22732135
2274 var fields: [2]Builder.Metadata = undefined;2136 var fields: [2]Builder.Metadata = undefined;
2275 fields[error_index] = try o.builder.debugMemberType(2137 fields[error_index] = try o.builder.debugMemberType(
2276 try o.builder.metadataString("tag"),2138 try o.builder.metadataString("error"),
2277 null, // File2139 null, // File
2278 debug_fwd_ref,2140 ty_fwd_ref,
2279 0, // Line2141 0, // Line
2280 try o.lowerDebugType(pt, Type.anyerror),2142 try o.getDebugType(pt, error_ty),
2281 error_size * 8,2143 error_size * 8,
2282 (error_align.toByteUnits() orelse 0) * 8,2144 error_align.toByteUnits().? * 8,
2283 error_offset * 8,2145 error_offset * 8,
2284 );2146 );
2285 fields[payload_index] = try o.builder.debugMemberType(2147 fields[payload_index] = try o.builder.debugMemberType(
2286 try o.builder.metadataString("value"),2148 try o.builder.metadataString("payload"),
2287 null, // File2149 null, // File
2288 debug_fwd_ref,2150 ty_fwd_ref,
2289 0, // Line2151 0, // Line
2290 try o.lowerDebugType(pt, payload_ty),2152 try o.getDebugType(pt, payload_ty),
2291 payload_size * 8,2153 payload_size * 8,
2292 (payload_align.toByteUnits() orelse 0) * 8,2154 payload_align.toByteUnits().? * 8,
2293 payload_offset * 8,2155 payload_offset * 8,
2294 );2156 );
22952157
2296 const debug_error_union_type = try o.builder.debugStructType(2158 return try o.builder.debugStructType(
2297 try o.builder.metadataString(name),2159 name,
2298 null, // File2160 null, // File
2299 o.debug_compile_unit.unwrap().?, // Sope2161 o.debug_compile_unit.unwrap().?, // Scope
2300 0, // Line2162 0, // Line
2301 null, // Underlying type2163 null, // Underlying type
2302 ty.abiSize(zcu) * 8,2164 ty.abiSize(zcu) * 8,
2303 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,2165 ty.abiAlignment(zcu).toByteUnits().? * 8,
2304 try o.builder.metadataTuple(&fields),2166 try o.builder.metadataTuple(&fields),
2305 );2167 );
2306
2307 o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_error_union_type);
2308
2309 try o.debug_type_map.put(gpa, ty.toIntern(), debug_error_union_type);
2310 return debug_error_union_type;
2311 },2168 },
2312 .error_set => {2169 .error_set => {
2313 const debug_error_set = try o.builder.debugUnsignedType(2170 assert(ty.toIntern() != .anyerror_type); // handled specially in `updateConst`; will be populated by `emit` instead
2314 try o.builder.metadataString("anyerror"),2171 // Error sets are just named wrappers around `anyerror`.
2315 16,2172 // MLUGG TODO: these should use DW_TAG_typedef instead, but std.zig.llvm.Builder currently lacks support for those.
2173 const anyerror_member = try o.builder.debugMemberType(
2174 try o.builder.metadataString("error"),
2175 null, // file
2176 ty_fwd_ref,
2177 0, // line
2178 try o.getDebugType(pt, .anyerror),
2179 ty.abiSize(zcu) * 8,
2180 ty.abiAlignment(zcu).toByteUnits().? * 8,
2181 0, // offset
2182 );
2183 return o.builder.debugStructType(
2184 name,
2185 null, // file
2186 o.debug_compile_unit.unwrap().?, // scope
2187 0, // line
2188 null, // underlying type
2189 ty.abiSize(zcu) * 8,
2190 ty.abiAlignment(zcu).toByteUnits().? * 8,
2191 try o.builder.metadataTuple(&.{anyerror_member}),
2316 );2192 );
2317 try o.debug_type_map.put(gpa, ty.toIntern(), debug_error_set);
2318 return debug_error_set;
2319 },2193 },
2320 .@"struct" => {2194 .@"fn" => {
2321 const name = try o.allocTypeName(pt, ty);2195 if (!ty.fnHasRuntimeBits(zcu)) {
2322 defer gpa.free(name);2196 return o.builder.debugSignedType(name, 0);
2323
2324 if (zcu.typeToPackedStruct(ty)) |struct_type| {
2325 const backing_int_ty = struct_type.backingIntTypeUnordered(ip);
2326 if (backing_int_ty != .none) {
2327 const info = Type.fromInterned(backing_int_ty).intInfo(zcu);
2328 const builder_name = try o.builder.metadataString(name);
2329 const debug_int_type = switch (info.signedness) {
2330 .signed => try o.builder.debugSignedType(builder_name, ty.abiSize(zcu) * 8),
2331 .unsigned => try o.builder.debugUnsignedType(builder_name, ty.abiSize(zcu) * 8),
2332 };
2333 try o.debug_type_map.put(gpa, ty.toIntern(), debug_int_type);
2334 return debug_int_type;
2335 }
2336 }2197 }
23372198
2338 switch (ip.indexToKey(ty.toIntern())) {2199 const fn_info = zcu.typeToFunc(ty).?;
2339 .tuple_type => |tuple| {
2340 var fields: std.ArrayList(Builder.Metadata) = .empty;
2341 defer fields.deinit(gpa);
23422200
2343 try fields.ensureUnusedCapacity(gpa, tuple.types.len);2201 var debug_param_types: std.ArrayList(Builder.Metadata) = try .initCapacity(gpa, 3 + fn_info.param_types.len);
2202 defer debug_param_types.deinit(gpa);
23442203
2345 comptime assert(struct_layout_version == 2);2204 // Return type goes first.
2346 var offset: u64 = 0;2205 const sret = firstParamSRet(fn_info, zcu, target);
2206 const ret_ty: Type = if (sret) .void else .fromInterned(fn_info.return_type);
2207 debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, ret_ty));
23472208
2348 const debug_fwd_ref = try o.builder.debugForwardReference();2209 if (sret) {
2210 const ptr_ty = try pt.singleMutPtrType(Type.fromInterned(fn_info.return_type));
2211 debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, ptr_ty));
2212 }
23492213
2350 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| {2214 if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) {
2351 if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue;2215 // Stack trace pointer.
2216 debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, .ptr_usize));
2217 }
23522218
2353 const field_size = Type.fromInterned(field_ty).abiSize(zcu);2219 for (fn_info.param_types.get(ip)) |param_ty_ip| {
2354 const field_align = Type.fromInterned(field_ty).abiAlignment(zcu);2220 const param_ty: Type = .fromInterned(param_ty_ip);
2355 const field_offset = field_align.forward(offset);2221 if (!param_ty.hasRuntimeBits(zcu)) continue;
2356 offset = field_offset + field_size;2222 if (isByRef(param_ty, zcu)) {
2223 const ptr_ty = try pt.singleConstPtrType(param_ty);
2224 debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, ptr_ty));
2225 } else {
2226 debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, param_ty));
2227 }
2228 }
23572229
2358 var name_buf: [32]u8 = undefined;2230 return o.builder.debugSubroutineType(
2359 const field_name = std.fmt.bufPrint(&name_buf, "{d}", .{i}) catch unreachable;2231 try o.builder.metadataTuple(debug_param_types.items),
2232 );
2233 },
2234 .@"struct" => {
2235 if (ty.isTuple(zcu)) {
2236 const tuple = ip.indexToKey(ty.toIntern()).tuple_type;
2237 var fields: std.ArrayList(Builder.Metadata) = .empty;
2238 defer fields.deinit(gpa);
23602239
2361 fields.appendAssumeCapacity(try o.builder.debugMemberType(2240 try fields.ensureUnusedCapacity(gpa, tuple.types.len);
2362 try o.builder.metadataString(field_name),
2363 null, // File
2364 debug_fwd_ref,
2365 0,
2366 try o.lowerDebugType(pt, Type.fromInterned(field_ty)),
2367 field_size * 8,
2368 (field_align.toByteUnits() orelse 0) * 8,
2369 field_offset * 8,
2370 ));
2371 }
23722241
2373 const debug_struct_type = try o.builder.debugStructType(2242 comptime assert(struct_layout_version == 2);
2374 try o.builder.metadataString(name),2243 var offset: u64 = 0;
2375 null, // File
2376 o.debug_compile_unit.unwrap().?, // Scope
2377 0, // Line
2378 null, // Underlying type
2379 ty.abiSize(zcu) * 8,
2380 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,
2381 try o.builder.metadataTuple(fields.items),
2382 );
2383
2384 o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_struct_type);
23852244
2386 try o.debug_type_map.put(gpa, ty.toIntern(), debug_struct_type);2245 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty_ip, field_val, i| {
2387 return debug_struct_type;2246 const field_ty: Type = .fromInterned(field_ty_ip);
2388 },2247 if (field_val != .none or !field_ty.hasRuntimeBits(zcu)) continue;
2389 .struct_type => {2248
2390 if (!ip.loadStructType(ty.toIntern()).haveFieldTypes(ip)) {2249 const field_size = field_ty.abiSize(zcu);
2391 // This can happen if a struct type makes it all the way to2250 const field_align = field_ty.abiAlignment(zcu);
2392 // flush() without ever being instantiated or referenced (even2251 const field_offset = field_align.forward(offset);
2393 // via pointer). The only reason we are hearing about it now is2252 offset = field_offset + field_size;
2394 // that it is being used as a namespace to put other debug types2253
2395 // into. Therefore we can satisfy this by making an empty namespace,2254 fields.appendAssumeCapacity(try o.builder.debugMemberType(
2396 // rather than changing the frontend to unnecessarily resolve the2255 try o.builder.metadataStringFmt("{d}", .{i}),
2397 // struct field types.2256 null, // file
2398 const debug_struct_type = try o.makeEmptyNamespaceDebugType(pt, ty);2257 ty_fwd_ref,
2399 try o.debug_type_map.put(gpa, ty.toIntern(), debug_struct_type);2258 0, // line
2400 return debug_struct_type;2259 try o.getDebugType(pt, field_ty),
2401 }2260 field_size * 8,
2402 },2261 field_align.toByteUnits().? * 8,
2403 else => {},2262 field_offset * 8,
2404 }2263 ));
2264 }
24052265
2406 if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) {2266 return o.builder.debugStructType(
2407 const debug_struct_type = try o.makeEmptyNamespaceDebugType(pt, ty);2267 name,
2408 try o.debug_type_map.put(gpa, ty.toIntern(), debug_struct_type);2268 null, // file
2409 return debug_struct_type;2269 o.debug_compile_unit.unwrap().?,
2270 0, // line
2271 null, // underlying type
2272 ty.abiSize(zcu) * 8,
2273 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,
2274 try o.builder.metadataTuple(fields.items),
2275 );
2410 }2276 }
24112277
2412 const struct_type = zcu.typeToStruct(ty).?;2278 const struct_type = zcu.typeToStruct(ty).?;
24132279
2414 var fields: std.ArrayList(Builder.Metadata) = .empty;2280 const file = try o.getDebugFile(pt, struct_type.zir_index.resolveFile(ip));
2415 defer fields.deinit(gpa);2281 const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace|
24162282 try o.namespaceToDebugScope(pt, parent_namespace)
2417 try fields.ensureUnusedCapacity(gpa, struct_type.field_types.len);2283 else
2284 file;
24182285
2419 const debug_fwd_ref = try o.builder.debugForwardReference();2286 const line = ty.typeDeclSrcLine(zcu).? + 1;
24202287
2421 // Set as forward reference while the type is lowered in case it references itself2288 var fields: std.ArrayList(Builder.Metadata) = .empty;
2422 try o.debug_type_map.put(gpa, ty.toIntern(), debug_fwd_ref);2289 defer fields.deinit(gpa);
24232290
2424 comptime assert(struct_layout_version == 2);2291 switch (struct_type.layout) {
2425 var it = struct_type.iterateRuntimeOrder(ip);2292 .@"packed" => {
2426 while (it.next()) |field_index| {2293 try fields.ensureTotalCapacityPrecise(gpa, 1);
2427 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);2294 fields.appendAssumeCapacity(try o.builder.debugMemberType(
2428 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;2295 try o.builder.metadataString("bits"),
2429 const field_size = field_ty.abiSize(zcu);2296 null, // file
2430 const field_align = ty.fieldAlignment(field_index, zcu);2297 ty_fwd_ref,
2431 const field_offset = ty.structFieldOffset(field_index, zcu);2298 0, // line
2432 const field_name = struct_type.fieldName(ip, field_index);2299 try o.getDebugType(pt, .fromInterned(struct_type.packed_backing_int_type)),
2433 fields.appendAssumeCapacity(try o.builder.debugMemberType(2300 ty.abiSize(zcu) * 8,
2434 try o.builder.metadataString(field_name.toSlice(ip)),2301 ty.abiAlignment(zcu).toByteUnits().? * 8,
2435 null, // File2302 0, // offset
2436 debug_fwd_ref,2303 ));
2437 0, // Line2304 },
2438 try o.lowerDebugType(pt, field_ty),2305 .auto, .@"extern" => {
2439 field_size * 8,2306 comptime assert(struct_layout_version == 2);
2440 (field_align.toByteUnits() orelse 0) * 8,2307 try fields.ensureTotalCapacityPrecise(gpa, struct_type.field_types.len);
2441 field_offset * 8,2308 var it = struct_type.iterateRuntimeOrder(ip);
2442 ));2309 while (it.next()) |field_index| {
2310 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);
2311 if (!field_ty.hasRuntimeBits(zcu)) continue;
2312 const field_size = field_ty.abiSize(zcu);
2313 const field_align = switch (ty.explicitFieldAlignment(field_index, zcu)) {
2314 .none => field_ty.abiAlignment(zcu),
2315 else => |a| a,
2316 };
2317 const field_offset = struct_type.field_offsets.get(ip)[field_index];
2318 const field_name = struct_type.field_names.get(ip)[field_index];
2319 fields.appendAssumeCapacity(try o.builder.debugMemberType(
2320 try o.builder.metadataString(field_name.toSlice(ip)),
2321 null, // file
2322 ty_fwd_ref,
2323 0, // line
2324 try o.getDebugType(pt, field_ty),
2325 field_size * 8,
2326 field_align.toByteUnits().? * 8,
2327 field_offset * 8,
2328 ));
2329 }
2330 },
2443 }2331 }
24442332
2445 const debug_struct_type = try o.builder.debugStructType(2333 return o.builder.debugStructType(
2446 try o.builder.metadataString(name),2334 name,
2447 null, // File2335 file,
2448 o.debug_compile_unit.unwrap().?, // Scope2336 scope,
2449 0, // Line2337 line,
2450 null, // Underlying type2338 null, // underlying type
2451 ty.abiSize(zcu) * 8,2339 ty.abiSize(zcu) * 8,
2452 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,2340 ty.abiAlignment(zcu).toByteUnits().? * 8,
2453 try o.builder.metadataTuple(fields.items),2341 try o.builder.metadataTuple(fields.items),
2454 );2342 );
2455
2456 o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_struct_type);
2457
2458 // Set to real type now that it has been lowered fully
2459 const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable;
2460 map_ptr.* = debug_struct_type;
2461
2462 return debug_struct_type;
2463 },2343 },
2464 .@"union" => {2344 .@"union" => {
2465 const name = try o.allocTypeName(pt, ty);
2466 defer gpa.free(name);
2467
2468 const union_type = ip.loadUnionType(ty.toIntern());2345 const union_type = ip.loadUnionType(ty.toIntern());
2469 if (!union_type.haveFieldTypes(ip) or
2470 !ty.hasRuntimeBitsIgnoreComptime(zcu) or
2471 !union_type.haveLayout(ip))
2472 {
2473 const debug_union_type = try o.makeEmptyNamespaceDebugType(pt, ty);
2474 try o.debug_type_map.put(gpa, ty.toIntern(), debug_union_type);
2475 return debug_union_type;
2476 }
24772346
2478 const layout = Type.getUnionLayout(union_type, zcu);2347 const file = try o.getDebugFile(pt, union_type.zir_index.resolveFile(ip));
2348 const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace|
2349 try o.namespaceToDebugScope(pt, parent_namespace)
2350 else
2351 file;
24792352
2480 const debug_fwd_ref = try o.builder.debugForwardReference();2353 const line = ty.typeDeclSrcLine(zcu).? + 1;
24812354
2482 // Set as forward reference while the type is lowered in case it references itself2355 const enum_tag_ty: Type = .fromInterned(union_type.enum_tag_type);
2483 try o.debug_type_map.put(gpa, ty.toIntern(), debug_fwd_ref);2356 const layout = Type.getUnionLayout(union_type, zcu);
24842357
2485 if (layout.payload_size == 0) {2358 if (layout.payload_size == 0) {
2486 const debug_union_type = try o.builder.debugStructType(2359 const tag_member = try o.builder.debugMemberType(
2487 try o.builder.metadataString(name),2360 try o.builder.metadataString("tag"),
2488 null, // File2361 null, // file
2489 o.debug_compile_unit.unwrap().?, // Scope2362 ty_fwd_ref,
2490 0, // Line2363 0, // line
2491 null, // Underlying type2364 try o.getDebugType(pt, enum_tag_ty),
2365 layout.tag_size * 8,
2366 layout.tag_align.toByteUnits().? * 8,
2367 0, // offset
2368 );
2369 return o.builder.debugStructType(
2370 name,
2371 file,
2372 scope,
2373 line,
2374 null, // underlying type
2492 ty.abiSize(zcu) * 8,2375 ty.abiSize(zcu) * 8,
2493 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,2376 ty.abiAlignment(zcu).toByteUnits().? * 8,
2494 try o.builder.metadataTuple(2377 try o.builder.metadataTuple(&.{tag_member}),
2495 &.{try o.lowerDebugType(pt, Type.fromInterned(union_type.enum_tag_ty))},
2496 ),
2497 );2378 );
2498
2499 // Set to real type now that it has been lowered fully
2500 const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable;
2501 map_ptr.* = debug_union_type;
2502
2503 return debug_union_type;
2504 }2379 }
25052380
2506 var fields: std.ArrayList(Builder.Metadata) = .empty;2381 var fields: std.ArrayList(Builder.Metadata) = try .initCapacity(gpa, union_type.field_types.len);
2507 defer fields.deinit(gpa);2382 defer fields.deinit(gpa);
25082383
2509 try fields.ensureUnusedCapacity(gpa, union_type.loadTagType(ip).names.len);2384 const payload_fwd_ref = if (layout.tag_size == 0)
25102385 ty_fwd_ref
2511 const debug_union_fwd_ref = if (layout.tag_size == 0)
2512 debug_fwd_ref
2513 else2386 else
2514 try o.builder.debugForwardReference();2387 try o.builder.debugForwardReference();
25152388
2516 const tag_type = union_type.loadTagType(ip);2389 for (0..union_type.field_types.len) |field_index| {
2517
2518 for (0..tag_type.names.len) |field_index| {
2519 const field_ty = union_type.field_types.get(ip)[field_index];2390 const field_ty = union_type.field_types.get(ip)[field_index];
2520 if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(zcu)) continue;
25212391
2522 const field_size = Type.fromInterned(field_ty).abiSize(zcu);2392 const field_size = Type.fromInterned(field_ty).abiSize(zcu);
2523 const field_align: InternPool.Alignment = switch (union_type.flagsUnordered(ip).layout) {2393 const field_align: InternPool.Alignment = switch (union_type.layout) {
2524 .@"packed" => .none,2394 .@"packed" => .none,
2525 .auto, .@"extern" => ty.fieldAlignment(field_index, zcu),2395 .auto, .@"extern" => ty.explicitFieldAlignment(field_index, zcu),
2526 };2396 };
25272397
2528 const field_name = tag_type.names.get(ip)[field_index];2398 const field_name = enum_tag_ty.enumFieldName(field_index, zcu);
2529 fields.appendAssumeCapacity(try o.builder.debugMemberType(2399 fields.appendAssumeCapacity(try o.builder.debugMemberType(
2530 try o.builder.metadataString(field_name.toSlice(ip)),2400 try o.builder.metadataString(field_name.toSlice(ip)),
2531 null, // File2401 null, // file
2532 debug_union_fwd_ref,2402 payload_fwd_ref,
2533 0, // Line2403 0, // line
2534 try o.lowerDebugType(pt, Type.fromInterned(field_ty)),2404 try o.getDebugType(pt, .fromInterned(field_ty)),
2535 field_size * 8,2405 field_size * 8,
2536 (field_align.toByteUnits() orelse 0) * 8,2406 (field_align.toByteUnits() orelse 0) * 8,
2537 0, // Offset2407 0, // offset
2538 ));2408 ));
2539 }2409 }
25402410
2541 var union_name_buf: ?[:0]const u8 = null;2411 const debug_payload_type = try o.builder.debugUnionType(
2542 defer if (union_name_buf) |buf| gpa.free(buf);2412 payload_name: {
2543 const union_name = if (layout.tag_size == 0) name else name: {2413 if (layout.tag_size == 0) break :payload_name name;
2544 union_name_buf = try std.fmt.allocPrintSentinel(gpa, "{s}:Payload", .{name}, 0);2414 break :payload_name try o.builder.metadataStringFmt("{s}:Payload", .{name.slice(&o.builder)});
2545 break :name union_name_buf.?;2415 },
2546 };2416 file,
25472417 scope,
2548 const debug_union_type = try o.builder.debugUnionType(2418 line,
2549 try o.builder.metadataString(union_name),2419 null, // underlying type
2550 null, // File
2551 o.debug_compile_unit.unwrap().?, // Scope
2552 0, // Line
2553 null, // Underlying type
2554 layout.payload_size * 8,2420 layout.payload_size * 8,
2555 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,2421 ty.abiAlignment(zcu).toByteUnits().? * 8,
2556 try o.builder.metadataTuple(fields.items),2422 try o.builder.metadataTuple(fields.items),
2557 );2423 );
25582424
2559 o.builder.resolveDebugForwardReference(debug_union_fwd_ref, debug_union_type);
2560
2561 if (layout.tag_size == 0) {2425 if (layout.tag_size == 0) {
2562 // Set to real type now that it has been lowered fully2426 return debug_payload_type;
2563 const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable;
2564 map_ptr.* = debug_union_type;
2565
2566 return debug_union_type;
2567 }2427 }
25682428
2569 var tag_offset: u64 = undefined;2429 o.builder.resolveDebugForwardReference(payload_fwd_ref, debug_payload_type);
2570 var payload_offset: u64 = undefined;
2571 if (layout.tag_align.compare(.gte, layout.payload_align)) {
2572 tag_offset = 0;
2573 payload_offset = layout.payload_align.forward(layout.tag_size);
2574 } else {
2575 payload_offset = 0;
2576 tag_offset = layout.tag_align.forward(layout.payload_size);
2577 }
25782430
2579 const debug_tag_type = try o.builder.debugMemberType(2431 const tag_offset: u64, const payload_offset: u64 = offsets: {
2432 if (layout.tag_align.compare(.gte, layout.payload_align)) {
2433 break :offsets .{ 0, layout.payload_align.forward(layout.tag_size) };
2434 } else {
2435 break :offsets .{ layout.tag_align.forward(layout.payload_size), 0 };
2436 }
2437 };
2438
2439 const tag_member_type = try o.builder.debugMemberType(
2580 try o.builder.metadataString("tag"),2440 try o.builder.metadataString("tag"),
2581 null, // File2441 null, // file
2582 debug_fwd_ref,2442 ty_fwd_ref,
2583 0, // Line2443 0, // line
2584 try o.lowerDebugType(pt, Type.fromInterned(union_type.enum_tag_ty)),2444 try o.getDebugType(pt, enum_tag_ty),
2585 layout.tag_size * 8,2445 layout.tag_size * 8,
2586 (layout.tag_align.toByteUnits() orelse 0) * 8,2446 layout.tag_align.toByteUnits().? * 8,
2587 tag_offset * 8,2447 tag_offset * 8,
2588 );2448 );
25892449
2590 const debug_payload_type = try o.builder.debugMemberType(2450 const payload_member_type = try o.builder.debugMemberType(
2591 try o.builder.metadataString("payload"),2451 try o.builder.metadataString("payload"),
2592 null, // File2452 null, // file
2593 debug_fwd_ref,2453 ty_fwd_ref,
2594 0, // Line2454 0, // line
2595 debug_union_type,2455 debug_payload_type,
2596 layout.payload_size * 8,2456 layout.payload_size * 8,
2597 (layout.payload_align.toByteUnits() orelse 0) * 8,2457 layout.payload_align.toByteUnits().? * 8,
2598 payload_offset * 8,2458 payload_offset * 8,
2599 );2459 );
26002460
2601 const full_fields: [2]Builder.Metadata =2461 const full_fields: [2]Builder.Metadata =
2602 if (layout.tag_align.compare(.gte, layout.payload_align))2462 if (layout.tag_align.compare(.gte, layout.payload_align))
2603 .{ debug_tag_type, debug_payload_type }2463 .{ tag_member_type, payload_member_type }
2604 else2464 else
2605 .{ debug_payload_type, debug_tag_type };2465 .{ payload_member_type, tag_member_type };
26062466
2607 const debug_tagged_union_type = try o.builder.debugStructType(2467 return o.builder.debugStructType(
2608 try o.builder.metadataString(name),2468 name,
2609 null, // File2469 file,
2610 o.debug_compile_unit.unwrap().?, // Scope2470 scope,
2611 0, // Line2471 line,
2612 null, // Underlying type2472 null, // underlying type
2613 ty.abiSize(zcu) * 8,2473 ty.abiSize(zcu) * 8,
2614 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,2474 ty.abiAlignment(zcu).toByteUnits().? * 8,
2615 try o.builder.metadataTuple(&full_fields),2475 try o.builder.metadataTuple(&full_fields),
2616 );2476 );
2477 },
2478 .@"enum" => {
2479 const file = try o.getDebugFile(pt, ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip));
2480 const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace|
2481 try o.namespaceToDebugScope(pt, parent_namespace)
2482 else
2483 file;
26172484
2618 o.builder.resolveDebugForwardReference(debug_fwd_ref, debug_tagged_union_type);2485 const line = ty.typeDeclSrcLine(zcu).? + 1;
2619
2620 // Set to real type now that it has been lowered fully
2621 const map_ptr = o.debug_type_map.getPtr(ty.toIntern()) orelse unreachable;
2622 map_ptr.* = debug_tagged_union_type;
26232486
2624 return debug_tagged_union_type;2487 if (!ty.hasRuntimeBits(zcu)) {
2625 },2488 return o.builder.debugStructType(
2626 .@"fn" => {2489 name,
2627 const fn_info = zcu.typeToFunc(ty).?;2490 file,
2491 scope,
2492 line,
2493 null, // underlying type
2494 ty.abiSize(zcu) * 8,
2495 ty.abiAlignment(zcu).toByteUnits().? * 8,
2496 null, // fields
2497 );
2498 }
26282499
2629 var debug_param_types = std.array_list.Managed(Builder.Metadata).init(gpa);2500 const enum_type = ip.loadEnumType(ty.toIntern());
2630 defer debug_param_types.deinit();2501 const enumerators = try gpa.alloc(Builder.Metadata, enum_type.field_names.len);
2502 defer gpa.free(enumerators);
26312503
2632 try debug_param_types.ensureUnusedCapacity(3 + fn_info.param_types.len);2504 const int_ty: Type = .fromInterned(enum_type.int_tag_type);
2505 const int_info = ty.intInfo(zcu);
2506 assert(int_info.bits != 0);
26332507
2634 // Return type goes first.2508 for (enumerators, enum_type.field_names.get(ip), 0..) |*out, field_name, field_index| {
2635 if (Type.fromInterned(fn_info.return_type).hasRuntimeBitsIgnoreComptime(zcu)) {2509 var space: Value.BigIntSpace = undefined;
2636 const sret = firstParamSRet(fn_info, zcu, target);2510 const field_val: std.math.big.int.Const = switch (enum_type.field_values.len) {
2637 const ret_ty = if (sret) Type.void else Type.fromInterned(fn_info.return_type);2511 0 => std.math.big.int.Mutable.init(&space.limbs, field_index).toConst(),
2638 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, ret_ty));2512 else => Value.fromInterned(enum_type.field_values.get(ip)[field_index]).toBigInt(&space, zcu),
26392513 };
2640 if (sret) {2514 out.* = try o.builder.debugEnumerator(
2641 const ptr_ty = try pt.singleMutPtrType(Type.fromInterned(fn_info.return_type));2515 try o.builder.metadataString(field_name.toSlice(ip)),
2642 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, ptr_ty));2516 int_info.signedness == .unsigned,
2643 }2517 int_info.bits,
2644 } else {2518 field_val,
2645 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, Type.void));2519 );
2646 }2520 }
26472521
2648 if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) {2522 const debug_enum_type = try o.builder.debugEnumerationType(
2649 // Stack trace pointer.2523 name,
2650 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, .fromInterned(.ptr_usize_type)));2524 file,
2525 scope,
2526 line,
2527 try o.getDebugType(pt, int_ty),
2528 ty.abiSize(zcu) * 8,
2529 ty.abiAlignment(zcu).toByteUnits().? * 8,
2530 try o.builder.metadataTuple(enumerators),
2531 );
2532 try o.debug_enums.append(gpa, debug_enum_type);
2533 return debug_enum_type;
2534 },
2535 .@"opaque" => {
2536 if (ty.toIntern() == .anyopaque_type) {
2537 return o.builder.debugSignedType(name, 0);
2651 }2538 }
26522539
2653 for (0..fn_info.param_types.len) |i| {2540 const file = try o.getDebugFile(pt, ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip));
2654 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[i]);2541 const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace|
2655 if (!param_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;2542 try o.namespaceToDebugScope(pt, parent_namespace)
2543 else
2544 file;
26562545
2657 if (isByRef(param_ty, zcu)) {2546 const line = ty.typeDeclSrcLine(zcu).? + 1;
2658 const ptr_ty = try pt.singleMutPtrType(param_ty);
2659 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, ptr_ty));
2660 } else {
2661 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, param_ty));
2662 }
2663 }
26642547
2665 const debug_function_type = try o.builder.debugSubroutineType(2548 return o.builder.debugStructType(
2666 try o.builder.metadataTuple(debug_param_types.items),2549 name,
2550 file,
2551 scope,
2552 line,
2553 null, // underlying type
2554 0, // size
2555 ty.abiAlignment(zcu).toByteUnits().? * 8,
2556 null, // fields
2667 );2557 );
2668
2669 try o.debug_type_map.put(gpa, ty.toIntern(), debug_function_type);
2670 return debug_function_type;
2671 },2558 },
2672 .comptime_int => unreachable,
2673 .comptime_float => unreachable,
2674 .type => unreachable,
2675 .undefined => unreachable,
2676 .null => unreachable,
2677 .enum_literal => unreachable,
2678
2679 .frame => @panic("TODO implement lowerDebugType for Frame types"),2559 .frame => @panic("TODO implement lowerDebugType for Frame types"),
2680 .@"anyframe" => @panic("TODO implement lowerDebugType for AnyFrame types"),2560 .@"anyframe" => @panic("TODO implement lowerDebugType for AnyFrame types"),
2681 }2561 }
2682 }2562 }
26832563
2684 fn namespaceToDebugScope(o: *Object, pt: Zcu.PerThread, namespace_index: InternPool.NamespaceIndex) !Builder.Metadata {2564 /// Called in `emit` so that the global error set is fully populated.
2565 fn lowerDebugAnyerrorType(o: *Object, pt: Zcu.PerThread) Allocator.Error!Builder.Metadata {
2685 const zcu = pt.zcu;2566 const zcu = pt.zcu;
2686 const namespace = zcu.namespacePtr(namespace_index);2567 const ip = &zcu.intern_pool;
2687 if (namespace.parent == .none) return try o.getDebugFile(pt, namespace.file_scope);2568 const gpa = zcu.comp.gpa;
26882569
2689 const gop = try o.debug_unresolved_namespace_scopes.getOrPut(o.gpa, namespace_index);2570 const error_set_bits = zcu.errorSetBits();
26902571 const error_names = ip.global_error_set.getNamesFromMainThread();
2691 if (!gop.found_existing) gop.value_ptr.* = try o.builder.debugForwardReference();2572
2573 const enumerators = try gpa.alloc(Builder.Metadata, error_names.len);
2574 defer gpa.free(enumerators);
2575
2576 for (enumerators, error_names, 1..) |*out, error_name, error_value| {
2577 var space: Value.BigIntSpace = undefined;
2578 var bigint: std.math.big.int.Mutable = .init(&space.limbs, error_value);
2579 out.* = try o.builder.debugEnumerator(
2580 try o.builder.metadataString(error_name.toSlice(ip)),
2581 true, // unsigned
2582 error_set_bits,
2583 bigint.toConst(),
2584 );
2585 }
26922586
2693 return gop.value_ptr.*;2587 const debug_enum_type = try o.builder.debugEnumerationType(
2588 try o.builder.metadataString("anyerror"),
2589 null, // file
2590 o.debug_compile_unit.unwrap().?, // scope
2591 0, // line
2592 try o.getDebugType(pt, try pt.intType(.unsigned, error_set_bits)),
2593 Type.anyerror.abiSize(zcu) * 8,
2594 Type.anyerror.abiAlignment(zcu).toByteUnits().? * 8,
2595 try o.builder.metadataTuple(enumerators),
2596 );
2597 try o.debug_enums.append(gpa, debug_enum_type);
2598 return debug_enum_type;
2694 }2599 }
26952600
2696 fn makeEmptyNamespaceDebugType(o: *Object, pt: Zcu.PerThread, ty: Type) !Builder.Metadata {2601 fn namespaceToDebugScope(o: *Object, pt: Zcu.PerThread, namespace_index: InternPool.NamespaceIndex) !Builder.Metadata {
2697 const zcu = pt.zcu;2602 const zcu = pt.zcu;
2698 const ip = &zcu.intern_pool;2603 const namespace = zcu.namespacePtr(namespace_index);
2699 const file = try o.getDebugFile(pt, ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip));2604 if (namespace.parent == .none) return try o.getDebugFile(pt, namespace.file_scope);
2700 const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace|2605 return o.getDebugType(pt, .fromInterned(namespace.owner_type));
2701 try o.namespaceToDebugScope(pt, parent_namespace)
2702 else
2703 file;
2704 return o.builder.debugStructType(
2705 try o.builder.metadataString(ty.containerTypeName(ip).toSlice(ip)), // TODO use fully qualified name
2706 file,
2707 scope,
2708 ty.typeDeclSrcLine(zcu).? + 1,
2709 null,
2710 0,
2711 0,
2712 null,
2713 );
2714 }2606 }
27152607
2716 fn allocTypeName(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error![:0]const u8 {2608 fn allocTypeName(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error![:0]const u8 {
...@@ -2885,40 +2777,6 @@ pub const Object = struct {...@@ -2885,40 +2777,6 @@ pub const Object = struct {
28852777
2886 if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder);2778 if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder);
28872779
2888 // Add parameter attributes. We handle only the case of extern functions (no body)
2889 // because functions with bodies are handled in `updateFunc`.
2890 if (is_extern) {
2891 var it = iterateParamTypes(o, pt, fn_info);
2892 it.llvm_index = llvm_arg_i;
2893 while (try it.next()) |lowering| switch (lowering) {
2894 .byval => {
2895 const param_index = it.zig_index - 1;
2896 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]);
2897 if (!isByRef(param_ty, zcu)) {
2898 try o.addByValParamAttrs(pt, &attributes, param_ty, param_index, fn_info, it.llvm_index - 1);
2899 }
2900 },
2901 .byref => {
2902 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
2903 const param_llvm_ty = try o.lowerType(pt, param_ty);
2904 const alignment = param_ty.abiAlignment(zcu);
2905 try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment.toLlvm(), it.byval_attr, param_llvm_ty);
2906 },
2907 .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder),
2908 // No attributes needed for these.
2909 .no_bits,
2910 .abi_sized_int,
2911 .multiple_llvm_types,
2912 .float_array,
2913 .i32_array,
2914 .i64_array,
2915 => continue,
2916
2917 .slice => unreachable, // extern functions do not support slice types.
2918
2919 };
2920 }
2921
2922 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);2780 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
2923 return function_index;2781 return function_index;
2924 }2782 }
...@@ -3223,7 +3081,7 @@ pub const Object = struct {...@@ -3223,7 +3081,7 @@ pub const Object = struct {
3223 ),3081 ),
3224 .opt_type => |child_ty| {3082 .opt_type => |child_ty| {
3225 // Must stay in sync with `opt_payload` logic in `lowerPtr`.3083 // Must stay in sync with `opt_payload` logic in `lowerPtr`.
3226 if (!Type.fromInterned(child_ty).hasRuntimeBitsIgnoreComptime(zcu)) return .i8;3084 if (!Type.fromInterned(child_ty).hasRuntimeBits(zcu)) return .i8;
32273085
3228 const payload_ty = try o.lowerType(pt, Type.fromInterned(child_ty));3086 const payload_ty = try o.lowerType(pt, Type.fromInterned(child_ty));
3229 if (t.optionalReprIsPayload(zcu)) return payload_ty;3087 if (t.optionalReprIsPayload(zcu)) return payload_ty;
...@@ -3245,7 +3103,7 @@ pub const Object = struct {...@@ -3245,7 +3103,7 @@ pub const Object = struct {
3245 // Must stay in sync with `codegen.errUnionPayloadOffset`.3103 // Must stay in sync with `codegen.errUnionPayloadOffset`.
3246 // See logic in `lowerPtr`.3104 // See logic in `lowerPtr`.
3247 const error_type = try o.errorIntType(pt);3105 const error_type = try o.errorIntType(pt);
3248 if (!Type.fromInterned(error_union_type.payload_type).hasRuntimeBitsIgnoreComptime(zcu))3106 if (!Type.fromInterned(error_union_type.payload_type).hasRuntimeBits(zcu))
3249 return error_type;3107 return error_type;
3250 const payload_type = try o.lowerType(pt, Type.fromInterned(error_union_type.payload_type));3108 const payload_type = try o.lowerType(pt, Type.fromInterned(error_union_type.payload_type));
32513109
...@@ -3287,7 +3145,7 @@ pub const Object = struct {...@@ -3287,7 +3145,7 @@ pub const Object = struct {
3287 const struct_type = ip.loadStructType(t.toIntern());3145 const struct_type = ip.loadStructType(t.toIntern());
32883146
3289 if (struct_type.layout == .@"packed") {3147 if (struct_type.layout == .@"packed") {
3290 const int_ty = try o.lowerType(pt, Type.fromInterned(struct_type.backingIntTypeUnordered(ip)));3148 const int_ty = try o.lowerType(pt, .fromInterned(struct_type.packed_backing_int_type));
3291 try o.type_map.put(o.gpa, t.toIntern(), int_ty);3149 try o.type_map.put(o.gpa, t.toIntern(), int_ty);
3292 return int_ty;3150 return int_ty;
3293 }3151 }
...@@ -3301,18 +3159,16 @@ pub const Object = struct {...@@ -3301,18 +3159,16 @@ pub const Object = struct {
33013159
3302 comptime assert(struct_layout_version == 2);3160 comptime assert(struct_layout_version == 2);
3303 var offset: u64 = 0;3161 var offset: u64 = 0;
3304 var big_align: InternPool.Alignment = .@"1";
3305 var struct_kind: Builder.Type.Structure.Kind = .normal;3162 var struct_kind: Builder.Type.Structure.Kind = .normal;
3306 // 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).3163 // 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).
3307 var it = struct_type.iterateRuntimeOrder(ip);3164 var it = struct_type.iterateRuntimeOrder(ip);
3308 while (it.next()) |field_index| {3165 while (it.next()) |field_index| {
3309 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);3166 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);
3310 const field_align = t.fieldAlignment(field_index, zcu);
3311 const field_ty_align = field_ty.abiAlignment(zcu);
3312 if (field_align.compare(.lt, field_ty_align)) struct_kind = .@"packed";
3313 big_align = big_align.max(field_align);
3314 const prev_offset = offset;3167 const prev_offset = offset;
3315 offset = field_align.forward(offset);3168 offset = struct_type.field_offsets.get(ip)[field_index];
3169 if (@ctz(offset) < field_ty.abiAlignment(zcu).toLog2Units()) {
3170 struct_kind = .@"packed";
3171 }
33163172
3317 const padding_len = offset - prev_offset;3173 const padding_len = offset - prev_offset;
3318 if (padding_len > 0) try llvm_field_types.append(3174 if (padding_len > 0) try llvm_field_types.append(
...@@ -3320,11 +3176,11 @@ pub const Object = struct {...@@ -3320,11 +3176,11 @@ pub const Object = struct {
3320 try o.builder.arrayType(padding_len, .i8),3176 try o.builder.arrayType(padding_len, .i8),
3321 );3177 );
33223178
3323 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) {3179 if (!field_ty.hasRuntimeBits(zcu)) {
3324 // This is a zero-bit field. If there are runtime bits after this field,3180 // This is a zero-bit field. If there are runtime bits after this field,
3325 // map to the next LLVM field (which we know exists): otherwise, don't3181 // map to the next LLVM field (which we know exists): otherwise, don't
3326 // map the field, indicating it's at the end of the struct.3182 // map the field, indicating it's at the end of the struct.
3327 if (offset != struct_type.sizeUnordered(ip)) {3183 if (offset != struct_type.size) {
3328 try o.struct_field_map.put(o.gpa, .{3184 try o.struct_field_map.put(o.gpa, .{
3329 .struct_ty = t.toIntern(),3185 .struct_ty = t.toIntern(),
3330 .field_index = field_index,3186 .field_index = field_index,
...@@ -3343,7 +3199,7 @@ pub const Object = struct {...@@ -3343,7 +3199,7 @@ pub const Object = struct {
3343 }3199 }
3344 {3200 {
3345 const prev_offset = offset;3201 const prev_offset = offset;
3346 offset = big_align.forward(offset);3202 offset = struct_type.alignment.forward(offset);
3347 const padding_len = offset - prev_offset;3203 const padding_len = offset - prev_offset;
3348 if (padding_len > 0) try llvm_field_types.append(3204 if (padding_len > 0) try llvm_field_types.append(
3349 o.gpa,3205 o.gpa,
...@@ -3391,7 +3247,7 @@ pub const Object = struct {...@@ -3391,7 +3247,7 @@ pub const Object = struct {
3391 o.gpa,3247 o.gpa,
3392 try o.builder.arrayType(padding_len, .i8),3248 try o.builder.arrayType(padding_len, .i8),
3393 );3249 );
3394 if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(zcu)) {3250 if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) {
3395 // This is a zero-bit field. If there are runtime bits after this field,3251 // This is a zero-bit field. If there are runtime bits after this field,
3396 // map to the next LLVM field (which we know exists): otherwise, don't3252 // map to the next LLVM field (which we know exists): otherwise, don't
3397 // map the field, indicating it's at the end of the struct.3253 // map the field, indicating it's at the end of the struct.
...@@ -3428,14 +3284,14 @@ pub const Object = struct {...@@ -3428,14 +3284,14 @@ pub const Object = struct {
3428 const union_obj = ip.loadUnionType(t.toIntern());3284 const union_obj = ip.loadUnionType(t.toIntern());
3429 const layout = Type.getUnionLayout(union_obj, zcu);3285 const layout = Type.getUnionLayout(union_obj, zcu);
34303286
3431 if (union_obj.flagsUnordered(ip).layout == .@"packed") {3287 if (union_obj.layout == .@"packed") {
3432 const int_ty = try o.builder.intType(@intCast(t.bitSize(zcu)));3288 const int_ty = try o.lowerType(pt, .fromInterned(union_obj.packed_backing_int_type));
3433 try o.type_map.put(o.gpa, t.toIntern(), int_ty);3289 try o.type_map.put(o.gpa, t.toIntern(), int_ty);
3434 return int_ty;3290 return int_ty;
3435 }3291 }
34363292
3437 if (layout.payload_size == 0) {3293 if (layout.payload_size == 0) {
3438 const enum_tag_ty = try o.lowerType(pt, Type.fromInterned(union_obj.enum_tag_ty));3294 const enum_tag_ty = try o.lowerType(pt, .fromInterned(union_obj.enum_tag_type));
3439 try o.type_map.put(o.gpa, t.toIntern(), enum_tag_ty);3295 try o.type_map.put(o.gpa, t.toIntern(), enum_tag_ty);
3440 return enum_tag_ty;3296 return enum_tag_ty;
3441 }3297 }
...@@ -3467,7 +3323,7 @@ pub const Object = struct {...@@ -3467,7 +3323,7 @@ pub const Object = struct {
3467 );3323 );
3468 return ty;3324 return ty;
3469 }3325 }
3470 const enum_tag_ty = try o.lowerType(pt, Type.fromInterned(union_obj.enum_tag_ty));3326 const enum_tag_ty = try o.lowerType(pt, .fromInterned(union_obj.enum_tag_type));
34713327
3472 // Put the tag before or after the payload depending on which one's3328 // Put the tag before or after the payload depending on which one's
3473 // alignment is greater.3329 // alignment is greater.
...@@ -3502,7 +3358,7 @@ pub const Object = struct {...@@ -3502,7 +3358,7 @@ pub const Object = struct {
3502 }3358 }
3503 return gop.value_ptr.*;3359 return gop.value_ptr.*;
3504 },3360 },
3505 .enum_type => try o.lowerType(pt, Type.fromInterned(ip.loadEnumType(t.toIntern()).tag_ty)),3361 .enum_type => try o.lowerType(pt, t.intTagType(zcu)),
3506 .func_type => |func_type| try o.lowerTypeFn(pt, func_type),3362 .func_type => |func_type| try o.lowerTypeFn(pt, func_type),
3507 .error_set_type, .inferred_error_set_type => try o.errorIntType(pt),3363 .error_set_type, .inferred_error_set_type => try o.errorIntType(pt),
3508 // values, not types3364 // values, not types
...@@ -3522,6 +3378,7 @@ pub const Object = struct {...@@ -3522,6 +3378,7 @@ pub const Object = struct {
3522 .opt,3378 .opt,
3523 .aggregate,3379 .aggregate,
3524 .un,3380 .un,
3381 .bitpack,
3525 // memoization, not types3382 // memoization, not types
3526 .memoized_call,3383 .memoized_call,
3527 => unreachable,3384 => unreachable,
...@@ -3529,20 +3386,6 @@ pub const Object = struct {...@@ -3529,20 +3386,6 @@ pub const Object = struct {
3529 };3386 };
3530 }3387 }
35313388
3532 /// Use this instead of lowerType when you want to handle correctly the case of elem_ty
3533 /// being a zero bit type, but it should still be lowered as an i8 in such case.
3534 /// There are other similar cases handled here as well.
3535 fn lowerPtrElemTy(o: *Object, pt: Zcu.PerThread, elem_ty: Type) Allocator.Error!Builder.Type {
3536 const zcu = pt.zcu;
3537 const lower_elem_ty = switch (elem_ty.zigTypeTag(zcu)) {
3538 .@"opaque" => true,
3539 .@"fn" => !zcu.typeToFunc(elem_ty).?.is_generic,
3540 .array => elem_ty.childType(zcu).hasRuntimeBitsIgnoreComptime(zcu),
3541 else => elem_ty.hasRuntimeBitsIgnoreComptime(zcu),
3542 };
3543 return if (lower_elem_ty) try o.lowerType(pt, elem_ty) else .i8;
3544 }
3545
3546 fn lowerTypeFn(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type {3389 fn lowerTypeFn(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type {
3547 const zcu = pt.zcu;3390 const zcu = pt.zcu;
3548 const ip = &zcu.intern_pool;3391 const ip = &zcu.intern_pool;
...@@ -3641,7 +3484,7 @@ pub const Object = struct {...@@ -3641,7 +3484,7 @@ pub const Object = struct {
3641 if (layout.payload_size == 0) return o.lowerValue(pt, un.tag);3484 if (layout.payload_size == 0) return o.lowerValue(pt, un.tag);
36423485
3643 const union_obj = zcu.typeToUnion(ty).?;3486 const union_obj = zcu.typeToUnion(ty).?;
3644 const container_layout = union_obj.flagsUnordered(ip).layout;3487 const container_layout = union_obj.layout;
36453488
3646 assert(container_layout == .@"packed");3489 assert(container_layout == .@"packed");
36473490
...@@ -3699,7 +3542,9 @@ pub const Object = struct {...@@ -3699,7 +3542,9 @@ pub const Object = struct {
3699 return o.builder.undefConst(try o.lowerType(pt, Type.fromInterned(val_key.typeOf())));3542 return o.builder.undefConst(try o.lowerType(pt, Type.fromInterned(val_key.typeOf())));
3700 }3543 }
37013544
3702 const ty = Type.fromInterned(val_key.typeOf());3545 const ty: Type = .fromInterned(val_key.typeOf());
3546 ty.assertHasLayout(zcu);
3547
3703 return switch (val_key) {3548 return switch (val_key) {
3704 .int_type,3549 .int_type,
3705 .ptr_type,3550 .ptr_type,
...@@ -3759,7 +3604,7 @@ pub const Object = struct {...@@ -3759,7 +3604,7 @@ pub const Object = struct {
3759 };3604 };
3760 const err_int_ty = try pt.errorIntType();3605 const err_int_ty = try pt.errorIntType();
3761 const payload_type = ty.errorUnionPayload(zcu);3606 const payload_type = ty.errorUnionPayload(zcu);
3762 if (!payload_type.hasRuntimeBitsIgnoreComptime(zcu)) {3607 if (!payload_type.hasRuntimeBits(zcu)) {
3763 // We use the error type directly as the type.3608 // We use the error type directly as the type.
3764 return o.lowerValue(pt, err_val);3609 return o.lowerValue(pt, err_val);
3765 }3610 }
...@@ -3821,7 +3666,7 @@ pub const Object = struct {...@@ -3821,7 +3666,7 @@ pub const Object = struct {
3821 const payload_ty = ty.optionalChild(zcu);3666 const payload_ty = ty.optionalChild(zcu);
38223667
3823 const non_null_bit = try o.builder.intConst(.i8, @intFromBool(opt.val != .none));3668 const non_null_bit = try o.builder.intConst(.i8, @intFromBool(opt.val != .none));
3824 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {3669 if (!payload_ty.hasRuntimeBits(zcu)) {
3825 return non_null_bit;3670 return non_null_bit;
3826 }3671 }
3827 const llvm_ty = try o.lowerType(pt, ty);3672 const llvm_ty = try o.lowerType(pt, ty);
...@@ -3857,6 +3702,7 @@ pub const Object = struct {...@@ -3857,6 +3702,7 @@ pub const Object = struct {
3857 fields[0..llvm_ty_fields.len],3702 fields[0..llvm_ty_fields.len],
3858 ), vals[0..llvm_ty_fields.len]);3703 ), vals[0..llvm_ty_fields.len]);
3859 },3704 },
3705 .bitpack => |bitpack| return o.lowerValue(pt, bitpack.backing_int_val),
3860 .aggregate => |aggregate| switch (ip.indexToKey(ty.toIntern())) {3706 .aggregate => |aggregate| switch (ip.indexToKey(ty.toIntern())) {
3861 .array_type => |array_type| switch (aggregate.storage) {3707 .array_type => |array_type| switch (aggregate.storage) {
3862 .bytes => |bytes| try o.builder.stringConst(try o.builder.string(3708 .bytes => |bytes| try o.builder.stringConst(try o.builder.string(
...@@ -3988,7 +3834,7 @@ pub const Object = struct {...@@ -3988,7 +3834,7 @@ pub const Object = struct {
3988 0..,3834 0..,
3989 ) |field_ty, field_val, field_index| {3835 ) |field_ty, field_val, field_index| {
3990 if (field_val != .none) continue;3836 if (field_val != .none) continue;
3991 if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(zcu)) continue;3837 if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue;
39923838
3993 const field_align = Type.fromInterned(field_ty).abiAlignment(zcu);3839 const field_align = Type.fromInterned(field_ty).abiAlignment(zcu);
3994 big_align = big_align.max(field_align);3840 big_align = big_align.max(field_align);
...@@ -4034,16 +3880,8 @@ pub const Object = struct {...@@ -4034,16 +3880,8 @@ pub const Object = struct {
4034 },3880 },
4035 .struct_type => {3881 .struct_type => {
4036 const struct_type = ip.loadStructType(ty.toIntern());3882 const struct_type = ip.loadStructType(ty.toIntern());
4037 assert(struct_type.haveLayout(ip));
4038 const struct_ty = try o.lowerType(pt, ty);3883 const struct_ty = try o.lowerType(pt, ty);
4039 if (struct_type.layout == .@"packed") {3884 assert(struct_type.layout != .@"packed");
4040 comptime assert(Type.packed_struct_layout_version == 2);
4041
4042 const bits = ty.bitSize(zcu);
4043 const llvm_int_ty = try o.builder.intType(@intCast(bits));
4044
4045 return o.lowerValueToInt(pt, llvm_int_ty, arg_val);
4046 }
4047 const llvm_len = struct_ty.aggregateLen(&o.builder);3885 const llvm_len = struct_ty.aggregateLen(&o.builder);
40483886
4049 const ExpectedContents = extern struct {3887 const ExpectedContents = extern struct {
...@@ -4063,15 +3901,12 @@ pub const Object = struct {...@@ -4063,15 +3901,12 @@ pub const Object = struct {
4063 comptime assert(struct_layout_version == 2);3901 comptime assert(struct_layout_version == 2);
4064 var llvm_index: usize = 0;3902 var llvm_index: usize = 0;
4065 var offset: u64 = 0;3903 var offset: u64 = 0;
4066 var big_align: InternPool.Alignment = .@"1";
4067 var need_unnamed = false;3904 var need_unnamed = false;
4068 var field_it = struct_type.iterateRuntimeOrder(ip);3905 var field_it = struct_type.iterateRuntimeOrder(ip);
4069 while (field_it.next()) |field_index| {3906 while (field_it.next()) |field_index| {
4070 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);3907 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);
4071 const field_align = ty.fieldAlignment(field_index, zcu);
4072 big_align = big_align.max(field_align);
4073 const prev_offset = offset;3908 const prev_offset = offset;
4074 offset = field_align.forward(offset);3909 offset = struct_type.field_offsets.get(ip)[field_index];
40753910
4076 const padding_len = offset - prev_offset;3911 const padding_len = offset - prev_offset;
4077 if (padding_len > 0) {3912 if (padding_len > 0) {
...@@ -4084,7 +3919,7 @@ pub const Object = struct {...@@ -4084,7 +3919,7 @@ pub const Object = struct {
4084 llvm_index += 1;3919 llvm_index += 1;
4085 }3920 }
40863921
4087 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) {3922 if (!field_ty.hasRuntimeBits(zcu)) {
4088 // This is a zero-bit field - we only needed it for the alignment.3923 // This is a zero-bit field - we only needed it for the alignment.
4089 continue;3924 continue;
4090 }3925 }
...@@ -4102,7 +3937,7 @@ pub const Object = struct {...@@ -4102,7 +3937,7 @@ pub const Object = struct {
4102 }3937 }
4103 {3938 {
4104 const prev_offset = offset;3939 const prev_offset = offset;
4105 offset = big_align.forward(offset);3940 offset = struct_type.alignment.forward(offset);
4106 const padding_len = offset - prev_offset;3941 const padding_len = offset - prev_offset;
4107 if (padding_len > 0) {3942 if (padding_len > 0) {
4108 fields[llvm_index] = try o.builder.arrayType(padding_len, .i8);3943 fields[llvm_index] = try o.builder.arrayType(padding_len, .i8);
...@@ -4126,19 +3961,13 @@ pub const Object = struct {...@@ -4126,19 +3961,13 @@ pub const Object = struct {
4126 if (layout.payload_size == 0) return o.lowerValue(pt, un.tag);3961 if (layout.payload_size == 0) return o.lowerValue(pt, un.tag);
41273962
4128 const union_obj = zcu.typeToUnion(ty).?;3963 const union_obj = zcu.typeToUnion(ty).?;
4129 const container_layout = union_obj.flagsUnordered(ip).layout;3964 const container_layout = union_obj.layout;
3965 assert(container_layout != .@"packed");
41303966
4131 var need_unnamed = false;3967 var need_unnamed = false;
4132 const payload = if (un.tag != .none) p: {3968 const payload = if (un.tag != .none) p: {
4133 const field_index = zcu.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?;3969 const field_index = zcu.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?;
4134 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);3970 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
4135 if (container_layout == .@"packed") {
4136 if (!field_ty.hasRuntimeBits(zcu)) return o.builder.intConst(union_ty, 0);
4137 const bits = ty.bitSize(zcu);
4138 const llvm_int_ty = try o.builder.intType(@intCast(bits));
4139
4140 return o.lowerValueToInt(pt, llvm_int_ty, arg_val);
4141 }
41423971
4143 // Sometimes we must make an unnamed struct because LLVM does3972 // Sometimes we must make an unnamed struct because LLVM does
4144 // not support bitcasting our payload struct to the true union payload type.3973 // not support bitcasting our payload struct to the true union payload type.
...@@ -4146,7 +3975,7 @@ pub const Object = struct {...@@ -4146,7 +3975,7 @@ pub const Object = struct {
4146 // must pointer cast to the expected type before accessing the union.3975 // must pointer cast to the expected type before accessing the union.
4147 need_unnamed = layout.most_aligned_field != field_index;3976 need_unnamed = layout.most_aligned_field != field_index;
41483977
4149 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) {3978 if (!field_ty.hasRuntimeBits(zcu)) {
4150 const padding_len = layout.payload_size;3979 const padding_len = layout.payload_size;
4151 break :p try o.builder.undefConst(try o.builder.arrayType(padding_len, .i8));3980 break :p try o.builder.undefConst(try o.builder.arrayType(padding_len, .i8));
4152 }3981 }
...@@ -4165,13 +3994,6 @@ pub const Object = struct {...@@ -4165,13 +3994,6 @@ pub const Object = struct {
4165 );3994 );
4166 } else p: {3995 } else p: {
4167 assert(layout.tag_size == 0);3996 assert(layout.tag_size == 0);
4168 if (container_layout == .@"packed") {
4169 const bits = ty.bitSize(zcu);
4170 const llvm_int_ty = try o.builder.intType(@intCast(bits));
4171
4172 return o.lowerValueToInt(pt, llvm_int_ty, arg_val);
4173 }
4174
4175 const union_val = try o.lowerValue(pt, un.val);3997 const union_val = try o.lowerValue(pt, un.val);
4176 need_unnamed = true;3998 need_unnamed = true;
4177 break :p union_val;3999 break :p union_val;
...@@ -4273,7 +4095,14 @@ pub const Object = struct {...@@ -4273,7 +4095,14 @@ pub const Object = struct {
4273 };4095 };
4274 return o.lowerPtr(pt, field.base, offset + field_off);4096 return o.lowerPtr(pt, field.base, offset + field_off);
4275 },4097 },
4276 .arr_elem, .comptime_field, .comptime_alloc => unreachable,4098 .arr_elem => |arr_elem| {
4099 const base_ptr_ty = Value.fromInterned(arr_elem.base).typeOf(zcu);
4100 assert(base_ptr_ty.ptrSize(zcu) == .many);
4101 const elem_size = base_ptr_ty.childType(zcu).abiSize(zcu);
4102 return o.lowerPtr(pt, arr_elem.base, offset + elem_size * arr_elem.index);
4103 },
4104 .comptime_field => unreachable,
4105 .comptime_alloc => unreachable,
4277 };4106 };
4278 }4107 }
42794108
...@@ -4298,12 +4127,11 @@ pub const Object = struct {...@@ -4298,12 +4127,11 @@ pub const Object = struct {
42984127
4299 const ptr_ty = Type.fromInterned(uav.orig_ty);4128 const ptr_ty = Type.fromInterned(uav.orig_ty);
43004129
4301 const is_fn_body = uav_ty.zigTypeTag(zcu) == .@"fn";4130 if (!uav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
4302 if ((!is_fn_body and !uav_ty.hasRuntimeBits(zcu)) or4131 return o.lowerPtrToVoid(pt, ptr_ty);
4303 (is_fn_body and zcu.typeToFunc(uav_ty).?.is_generic)) return o.lowerPtrToVoid(pt, ptr_ty);4132 }
43044133
4305 if (is_fn_body)4134 assert(uav_ty.zigTypeTag(zcu) != .@"fn"); // should be using a Nav ref
4306 @panic("TODO");
43074135
4308 const llvm_addr_space = toLlvmAddressSpace(ptr_ty.ptrAddressSpace(zcu), target);4136 const llvm_addr_space = toLlvmAddressSpace(ptr_ty.ptrAddressSpace(zcu), target);
4309 const alignment = ptr_ty.ptrAlignment(zcu);4137 const alignment = ptr_ty.ptrAlignment(zcu);
...@@ -4326,14 +4154,11 @@ pub const Object = struct {...@@ -4326,14 +4154,11 @@ pub const Object = struct {
4326 const nav_ty = Type.fromInterned(nav.typeOf(ip));4154 const nav_ty = Type.fromInterned(nav.typeOf(ip));
4327 const ptr_ty = try pt.navPtrType(nav_index);4155 const ptr_ty = try pt.navPtrType(nav_index);
43284156
4329 const is_fn_body = nav_ty.zigTypeTag(zcu) == .@"fn";4157 if (nav.getExtern(ip) == null and !nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
4330 if ((!is_fn_body and !nav_ty.hasRuntimeBits(zcu)) or
4331 (is_fn_body and zcu.typeToFunc(nav_ty).?.is_generic))
4332 {
4333 return o.lowerPtrToVoid(pt, ptr_ty);4158 return o.lowerPtrToVoid(pt, ptr_ty);
4334 }4159 }
43354160
4336 const llvm_global = if (is_fn_body)4161 const llvm_global = if (nav_ty.zigTypeTag(zcu) == .@"fn")
4337 (try o.resolveLlvmFunction(pt, nav_index)).ptrConst(&o.builder).global4162 (try o.resolveLlvmFunction(pt, nav_index)).ptrConst(&o.builder).global
4338 else4163 else
4339 (try o.resolveGlobalNav(pt, nav_index)).ptrConst(&o.builder).global;4164 (try o.resolveGlobalNav(pt, nav_index)).ptrConst(&o.builder).global;
...@@ -4376,21 +4201,18 @@ pub const Object = struct {...@@ -4376,21 +4201,18 @@ pub const Object = struct {
4376 /// types to work around a LLVM deficiency when targeting ARM/AArch64.4201 /// types to work around a LLVM deficiency when targeting ARM/AArch64.
4377 fn getAtomicAbiType(o: *Object, pt: Zcu.PerThread, ty: Type, is_rmw_xchg: bool) Allocator.Error!Builder.Type {4202 fn getAtomicAbiType(o: *Object, pt: Zcu.PerThread, ty: Type, is_rmw_xchg: bool) Allocator.Error!Builder.Type {
4378 const zcu = pt.zcu;4203 const zcu = pt.zcu;
4379 const ip = &zcu.intern_pool;4204 switch (ty.zigTypeTag(zcu)) {
4380 const int_ty = switch (ty.zigTypeTag(zcu)) {4205 .int, .@"enum", .@"struct", .@"union" => {},
4381 .int => ty,
4382 .@"enum" => ty.intTagType(zcu),
4383 .@"struct" => Type.fromInterned(ip.loadStructType(ty.toIntern()).backingIntTypeUnordered(ip)),
4384 .float => {4206 .float => {
4385 if (!is_rmw_xchg) return .none;4207 if (!is_rmw_xchg) return .none;
4386 return o.builder.intType(@intCast(ty.abiSize(zcu) * 8));4208 return o.builder.intType(@intCast(ty.abiSize(zcu) * 8));
4387 },4209 },
4388 .bool => return .i8,4210 .bool => return .i8,
4389 else => return .none,4211 else => return .none,
4390 };4212 }
4391 const bit_count = int_ty.intInfo(zcu).bits;4213 const bit_count = ty.bitSize(zcu);
4392 if (!std.math.isPowerOfTwo(bit_count) or (bit_count % 8) != 0) {4214 if (!std.math.isPowerOfTwo(bit_count) or (bit_count % 8) != 0) {
4393 return o.builder.intType(@intCast(int_ty.abiSize(zcu) * 8));4215 return o.builder.intType(@intCast(ty.abiSize(zcu) * 8));
4394 } else {4216 } else {
4395 return .none;4217 return .none;
4396 }4218 }
...@@ -4498,7 +4320,7 @@ pub const Object = struct {...@@ -4498,7 +4320,7 @@ pub const Object = struct {
4498 const ret_ty = try o.lowerType(pt, Type.slice_const_u8_sentinel_0);4320 const ret_ty = try o.lowerType(pt, Type.slice_const_u8_sentinel_0);
4499 const target = &zcu.root_mod.resolved_target.result;4321 const target = &zcu.root_mod.resolved_target.result;
4500 const function_index = try o.builder.addFunction(4322 const function_index = try o.builder.addFunction(
4501 try o.builder.fnType(ret_ty, &.{try o.lowerType(pt, Type.fromInterned(enum_type.tag_ty))}, .normal),4323 try o.builder.fnType(ret_ty, &.{try o.lowerType(pt, Type.fromInterned(enum_type.int_tag_type))}, .normal),
4502 try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_type.name.fmt(ip)}),4324 try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_type.name.fmt(ip)}),
4503 toLlvmAddressSpace(.generic, target),4325 toLlvmAddressSpace(.generic, target),
4504 );4326 );
...@@ -4521,12 +4343,16 @@ pub const Object = struct {...@@ -4521,12 +4343,16 @@ pub const Object = struct {
45214343
4522 const bad_value_block = try wip.block(1, "BadValue");4344 const bad_value_block = try wip.block(1, "BadValue");
4523 const tag_int_value = wip.arg(0);4345 const tag_int_value = wip.arg(0);
4524 var wip_switch =4346 var wip_switch = try wip.@"switch"(
4525 try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len), .none);4347 tag_int_value,
4348 bad_value_block,
4349 @intCast(enum_type.field_names.len),
4350 .none,
4351 );
4526 defer wip_switch.finish(&wip);4352 defer wip_switch.finish(&wip);
45274353
4528 for (0..enum_type.names.len) |field_index| {4354 for (0..enum_type.field_names.len) |field_index| {
4529 const name = try o.builder.stringNull(enum_type.names.get(ip)[field_index].toSlice(ip));4355 const name = try o.builder.stringNull(enum_type.field_names.get(ip)[field_index].toSlice(ip));
4530 const name_init = try o.builder.stringConst(name);4356 const name_init = try o.builder.stringConst(name);
4531 const name_variable_index =4357 const name_variable_index =
4532 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);4358 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
...@@ -4597,7 +4423,41 @@ pub const NavGen = struct {...@@ -4597,7 +4423,41 @@ pub const NavGen = struct {
4597 const ty = Type.fromInterned(nav.typeOf(ip));4423 const ty = Type.fromInterned(nav.typeOf(ip));
45984424
4599 if (linkage != .internal and ip.isFunctionType(ty.toIntern())) {4425 if (linkage != .internal and ip.isFunctionType(ty.toIntern())) {
4600 _ = try o.resolveLlvmFunction(pt, owner_nav);4426 const function_index = try o.resolveLlvmFunction(pt, owner_nav);
4427 // Add parameter attributes which weren't set by `resolveLlvmFunction`
4428 const fn_info = zcu.typeToFunc(ty).?;
4429 var attributes = try function_index.ptrConst(&o.builder).attributes.toWip(&o.builder);
4430 defer attributes.deinit(&o.builder);
4431 var it = iterateParamTypes(o, pt, fn_info);
4432 if (firstParamSRet(fn_info, zcu, zcu.getTarget())) it.llvm_index += 1;
4433 if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) it.llvm_index += 1;
4434 while (try it.next()) |lowering| switch (lowering) {
4435 .byval => {
4436 const param_index = it.zig_index - 1;
4437 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[param_index]);
4438 if (!isByRef(param_ty, zcu)) {
4439 try o.addByValParamAttrs(pt, &attributes, param_ty, param_index, fn_info, it.llvm_index - 1);
4440 }
4441 },
4442 .byref => {
4443 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]);
4444 const param_llvm_ty = try o.lowerType(pt, param_ty);
4445 const alignment = param_ty.abiAlignment(zcu);
4446 try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment.toLlvm(), it.byval_attr, param_llvm_ty);
4447 },
4448 .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder),
4449 // No attributes needed for these.
4450 .no_bits,
4451 .abi_sized_int,
4452 .multiple_llvm_types,
4453 .float_array,
4454 .i32_array,
4455 .i64_array,
4456 => continue,
4457
4458 .slice => unreachable, // extern functions do not support slice types.
4459 };
4460 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
4601 } else {4461 } else {
4602 const variable_index = try o.resolveGlobalNav(pt, nav_index);4462 const variable_index = try o.resolveGlobalNav(pt, nav_index);
4603 variable_index.setAlignment(zcu.navAlignment(nav_index).toLlvm(), &o.builder);4463 variable_index.setAlignment(zcu.navAlignment(nav_index).toLlvm(), &o.builder);
...@@ -4626,7 +4486,7 @@ pub const NavGen = struct {...@@ -4626,7 +4486,7 @@ pub const NavGen = struct {
4626 debug_file, // File4486 debug_file, // File
4627 debug_file, // Scope4487 debug_file, // Scope
4628 line_number,4488 line_number,
4629 try o.lowerDebugType(pt, ty),4489 try o.getDebugType(pt, ty),
4630 variable_index,4490 variable_index,
4631 .{ .local = linkage == .internal },4491 .{ .local = linkage == .internal },
4632 );4492 );
...@@ -4748,7 +4608,7 @@ pub const FuncGen = struct {...@@ -4748,7 +4608,7 @@ pub const FuncGen = struct {
4748 /// Have we seen loads or stores involving `allowzero` pointers?4608 /// Have we seen loads or stores involving `allowzero` pointers?
4749 allowzero_access: bool = false,4609 allowzero_access: bool = false,
47504610
4751 pub fn maybeMarkAllowZeroAccess(self: *FuncGen, info: InternPool.Key.PtrType) void {4611 fn maybeMarkAllowZeroAccess(self: *FuncGen, info: InternPool.Key.PtrType) void {
4752 // LLVM already considers null pointers to be valid in non-generic address spaces, so avoid4612 // LLVM already considers null pointers to be valid in non-generic address spaces, so avoid
4753 // pessimizing optimization for functions with accesses to such pointers.4613 // pessimizing optimization for functions with accesses to such pointers.
4754 if (info.flags.address_space == .generic and info.flags.is_allowzero) self.allowzero_access = true;4614 if (info.flags.address_space == .generic and info.flags.is_allowzero) self.allowzero_access = true;
...@@ -5216,7 +5076,7 @@ pub const FuncGen = struct {...@@ -5216,7 +5076,7 @@ pub const FuncGen = struct {
5216 try o.builder.metadataString(nav.fqn.toSlice(&zcu.intern_pool)),5076 try o.builder.metadataString(nav.fqn.toSlice(&zcu.intern_pool)),
5217 line_number,5077 line_number,
5218 line_number + func.lbrace_line,5078 line_number + func.lbrace_line,
5219 try o.lowerDebugType(pt, fn_ty),5079 try o.getDebugType(pt, fn_ty),
5220 .{5080 .{
5221 .di_flags = .{ .StaticMember = true },5081 .di_flags = .{ .StaticMember = true },
5222 .sp_flags = .{5082 .sp_flags = .{
...@@ -5514,7 +5374,7 @@ pub const FuncGen = struct {...@@ -5514,7 +5374,7 @@ pub const FuncGen = struct {
5514 return .none;5374 return .none;
5515 }5375 }
55165376
5517 if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBitsIgnoreComptime(zcu)) {5377 if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBits(zcu)) {
5518 return .none;5378 return .none;
5519 }5379 }
55205380
...@@ -5633,7 +5493,7 @@ pub const FuncGen = struct {...@@ -5633,7 +5493,7 @@ pub const FuncGen = struct {
5633 return;5493 return;
5634 }5494 }
5635 const fn_info = zcu.typeToFunc(Type.fromInterned(ip.getNav(self.ng.nav_index).typeOf(ip))).?;5495 const fn_info = zcu.typeToFunc(Type.fromInterned(ip.getNav(self.ng.nav_index).typeOf(ip))).?;
5636 if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) {5496 if (!ret_ty.hasRuntimeBits(zcu)) {
5637 if (Type.fromInterned(fn_info.return_type).isError(zcu)) {5497 if (Type.fromInterned(fn_info.return_type).isError(zcu)) {
5638 // Functions with an empty error set are emitted with an error code5498 // Functions with an empty error set are emitted with an error code
5639 // return type and return zero so they can be function pointers coerced5499 // return type and return zero so they can be function pointers coerced
...@@ -5698,7 +5558,7 @@ pub const FuncGen = struct {...@@ -5698,7 +5558,7 @@ pub const FuncGen = struct {
5698 const ptr_ty = self.typeOf(un_op);5558 const ptr_ty = self.typeOf(un_op);
5699 const ret_ty = ptr_ty.childType(zcu);5559 const ret_ty = ptr_ty.childType(zcu);
5700 const fn_info = zcu.typeToFunc(Type.fromInterned(ip.getNav(self.ng.nav_index).typeOf(ip))).?;5560 const fn_info = zcu.typeToFunc(Type.fromInterned(ip.getNav(self.ng.nav_index).typeOf(ip))).?;
5701 if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) {5561 if (!ret_ty.hasRuntimeBits(zcu)) {
5702 if (Type.fromInterned(fn_info.return_type).isError(zcu)) {5562 if (Type.fromInterned(fn_info.return_type).isError(zcu)) {
5703 // Functions with an empty error set are emitted with an error code5563 // Functions with an empty error set are emitted with an error code
5704 // return type and return zero so they can be function pointers coerced5564 // return type and return zero so they can be function pointers coerced
...@@ -5829,14 +5689,13 @@ pub const FuncGen = struct {...@@ -5829,14 +5689,13 @@ pub const FuncGen = struct {
5829 const o = self.ng.object;5689 const o = self.ng.object;
5830 const pt = self.ng.pt;5690 const pt = self.ng.pt;
5831 const zcu = pt.zcu;5691 const zcu = pt.zcu;
5832 const ip = &zcu.intern_pool;
5833 const scalar_ty = operand_ty.scalarType(zcu);5692 const scalar_ty = operand_ty.scalarType(zcu);
5834 const int_ty = switch (scalar_ty.zigTypeTag(zcu)) {5693 const int_ty = switch (scalar_ty.zigTypeTag(zcu)) {
5835 .@"enum" => scalar_ty.intTagType(zcu),5694 .@"enum" => scalar_ty.intTagType(zcu),
5836 .int, .bool, .pointer, .error_set => scalar_ty,5695 .int, .bool, .pointer, .error_set => scalar_ty,
5837 .optional => blk: {5696 .optional => blk: {
5838 const payload_ty = operand_ty.optionalChild(zcu);5697 const payload_ty = operand_ty.optionalChild(zcu);
5839 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu) or5698 if (!payload_ty.hasRuntimeBits(zcu) or
5840 operand_ty.optionalReprIsPayload(zcu))5699 operand_ty.optionalReprIsPayload(zcu))
5841 {5700 {
5842 break :blk operand_ty;5701 break :blk operand_ty;
...@@ -5908,12 +5767,7 @@ pub const FuncGen = struct {...@@ -5908,12 +5767,7 @@ pub const FuncGen = struct {
5908 return phi.toValue();5767 return phi.toValue();
5909 },5768 },
5910 .float => return self.buildFloatCmp(fast, op, operand_ty, .{ lhs, rhs }),5769 .float => return self.buildFloatCmp(fast, op, operand_ty, .{ lhs, rhs }),
5911 .@"struct" => blk: {5770 .@"struct" => scalar_ty.bitpackBackingInt(zcu),
5912 const struct_obj = ip.loadStructType(scalar_ty.toIntern());
5913 assert(struct_obj.layout == .@"packed");
5914 const backing_index = struct_obj.backingIntTypeUnordered(ip);
5915 break :blk Type.fromInterned(backing_index);
5916 },
5917 else => unreachable,5771 else => unreachable,
5918 };5772 };
5919 const is_signed = int_ty.isSignedInt(zcu);5773 const is_signed = int_ty.isSignedInt(zcu);
...@@ -6305,7 +6159,7 @@ pub const FuncGen = struct {...@@ -6305,7 +6159,7 @@ pub const FuncGen = struct {
6305 const pt = fg.ng.pt;6159 const pt = fg.ng.pt;
6306 const zcu = pt.zcu;6160 const zcu = pt.zcu;
6307 const payload_ty = err_union_ty.errorUnionPayload(zcu);6161 const payload_ty = err_union_ty.errorUnionPayload(zcu);
6308 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(zcu);6162 const payload_has_bits = payload_ty.hasRuntimeBits(zcu);
6309 const err_union_llvm_ty = try o.lowerType(pt, err_union_ty);6163 const err_union_llvm_ty = try o.lowerType(pt, err_union_ty);
6310 const error_type = try o.errorIntType(pt);6164 const error_type = try o.errorIntType(pt);
63116165
...@@ -6641,7 +6495,7 @@ pub const FuncGen = struct {...@@ -6641,7 +6495,7 @@ pub const FuncGen = struct {
6641 const len = try o.builder.intValue(llvm_usize, array_ty.arrayLen(zcu));6495 const len = try o.builder.intValue(llvm_usize, array_ty.arrayLen(zcu));
6642 const slice_llvm_ty = try o.lowerType(pt, self.typeOfIndex(inst));6496 const slice_llvm_ty = try o.lowerType(pt, self.typeOfIndex(inst));
6643 const operand = try self.resolveInst(ty_op.operand);6497 const operand = try self.resolveInst(ty_op.operand);
6644 if (!array_ty.hasRuntimeBitsIgnoreComptime(zcu))6498 if (!array_ty.hasRuntimeBits(zcu))
6645 return self.wip.buildAggregate(slice_llvm_ty, &.{ operand, len }, "");6499 return self.wip.buildAggregate(slice_llvm_ty, &.{ operand, len }, "");
6646 const ptr = try self.wip.gep(.inbounds, try o.lowerType(pt, array_ty), operand, &.{6500 const ptr = try self.wip.gep(.inbounds, try o.lowerType(pt, array_ty), operand, &.{
6647 try o.builder.intValue(llvm_usize, 0), try o.builder.intValue(llvm_usize, 0),6501 try o.builder.intValue(llvm_usize, 0), try o.builder.intValue(llvm_usize, 0),
...@@ -6824,7 +6678,7 @@ pub const FuncGen = struct {...@@ -6824,7 +6678,7 @@ pub const FuncGen = struct {
6824 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;6678 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
6825 const slice_ptr = try self.resolveInst(ty_op.operand);6679 const slice_ptr = try self.resolveInst(ty_op.operand);
6826 const slice_ptr_ty = self.typeOf(ty_op.operand);6680 const slice_ptr_ty = self.typeOf(ty_op.operand);
6827 const slice_llvm_ty = try o.lowerPtrElemTy(pt, slice_ptr_ty.childType(zcu));6681 const slice_llvm_ty = try o.lowerType(pt, slice_ptr_ty.childType(zcu));
68286682
6829 return self.wip.gepStruct(slice_llvm_ty, slice_ptr, index, "");6683 return self.wip.gepStruct(slice_llvm_ty, slice_ptr, index, "");
6830 }6684 }
...@@ -6838,7 +6692,7 @@ pub const FuncGen = struct {...@@ -6838,7 +6692,7 @@ pub const FuncGen = struct {
6838 const slice = try self.resolveInst(bin_op.lhs);6692 const slice = try self.resolveInst(bin_op.lhs);
6839 const index = try self.resolveInst(bin_op.rhs);6693 const index = try self.resolveInst(bin_op.rhs);
6840 const elem_ty = slice_ty.childType(zcu);6694 const elem_ty = slice_ty.childType(zcu);
6841 const llvm_elem_ty = try o.lowerPtrElemTy(pt, elem_ty);6695 const llvm_elem_ty = try o.lowerType(pt, elem_ty);
6842 const base_ptr = try self.wip.extractValue(slice, &.{0}, "");6696 const base_ptr = try self.wip.extractValue(slice, &.{0}, "");
6843 const ptr = try self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{index}, "");6697 const ptr = try self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{index}, "");
6844 if (isByRef(elem_ty, zcu)) {6698 if (isByRef(elem_ty, zcu)) {
...@@ -6863,7 +6717,7 @@ pub const FuncGen = struct {...@@ -6863,7 +6717,7 @@ pub const FuncGen = struct {
68636717
6864 const slice = try self.resolveInst(bin_op.lhs);6718 const slice = try self.resolveInst(bin_op.lhs);
6865 const index = try self.resolveInst(bin_op.rhs);6719 const index = try self.resolveInst(bin_op.rhs);
6866 const llvm_elem_ty = try o.lowerPtrElemTy(pt, slice_ty.childType(zcu));6720 const llvm_elem_ty = try o.lowerType(pt, slice_ty.childType(zcu));
6867 const base_ptr = try self.wip.extractValue(slice, &.{0}, "");6721 const base_ptr = try self.wip.extractValue(slice, &.{0}, "");
6868 return self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{index}, "");6722 return self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{index}, "");
6869 }6723 }
...@@ -6903,7 +6757,7 @@ pub const FuncGen = struct {...@@ -6903,7 +6757,7 @@ pub const FuncGen = struct {
6903 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;6757 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
6904 const ptr_ty = self.typeOf(bin_op.lhs);6758 const ptr_ty = self.typeOf(bin_op.lhs);
6905 const elem_ty = ptr_ty.childType(zcu);6759 const elem_ty = ptr_ty.childType(zcu);
6906 const llvm_elem_ty = try o.lowerPtrElemTy(pt, elem_ty);6760 const llvm_elem_ty = try o.lowerType(pt, elem_ty);
6907 const base_ptr = try self.resolveInst(bin_op.lhs);6761 const base_ptr = try self.resolveInst(bin_op.lhs);
6908 const rhs = try self.resolveInst(bin_op.rhs);6762 const rhs = try self.resolveInst(bin_op.rhs);
6909 // TODO: when we go fully opaque pointers in LLVM 16 we can remove this branch6763 // TODO: when we go fully opaque pointers in LLVM 16 we can remove this branch
...@@ -6930,8 +6784,8 @@ pub const FuncGen = struct {...@@ -6930,8 +6784,8 @@ pub const FuncGen = struct {
6930 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;6784 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
6931 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;6785 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
6932 const ptr_ty = self.typeOf(bin_op.lhs);6786 const ptr_ty = self.typeOf(bin_op.lhs);
6933 const elem_ty = ptr_ty.childType(zcu);6787 const elem_ty = ptr_ty.indexableElem(zcu);
6934 if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return self.resolveInst(bin_op.lhs);6788 assert(elem_ty.hasRuntimeBits(zcu));
69356789
6936 const base_ptr = try self.resolveInst(bin_op.lhs);6790 const base_ptr = try self.resolveInst(bin_op.lhs);
6937 const rhs = try self.resolveInst(bin_op.rhs);6791 const rhs = try self.resolveInst(bin_op.rhs);
...@@ -6939,12 +6793,8 @@ pub const FuncGen = struct {...@@ -6939,12 +6793,8 @@ pub const FuncGen = struct {
6939 const elem_ptr = ty_pl.ty.toType();6793 const elem_ptr = ty_pl.ty.toType();
6940 if (elem_ptr.ptrInfo(zcu).flags.vector_index != .none) return base_ptr;6794 if (elem_ptr.ptrInfo(zcu).flags.vector_index != .none) return base_ptr;
69416795
6942 const llvm_elem_ty = try o.lowerPtrElemTy(pt, elem_ty);6796 const llvm_elem_ty = try o.lowerType(pt, elem_ty);
6943 return self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, if (ptr_ty.isSinglePointer(zcu))6797 return self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{rhs}, "");
6944 // If this is a single-item pointer to an array, we need another index in the GEP.
6945 &.{ try o.builder.intValue(try o.lowerType(pt, Type.usize), 0), rhs }
6946 else
6947 &.{rhs}, "");
6948 }6798 }
69496799
6950 fn airStructFieldPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {6800 fn airStructFieldPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
...@@ -6976,7 +6826,7 @@ pub const FuncGen = struct {...@@ -6976,7 +6826,7 @@ pub const FuncGen = struct {
6976 const struct_llvm_val = try self.resolveInst(struct_field.struct_operand);6826 const struct_llvm_val = try self.resolveInst(struct_field.struct_operand);
6977 const field_index = struct_field.field_index;6827 const field_index = struct_field.field_index;
6978 const field_ty = struct_ty.fieldType(field_index, zcu);6828 const field_ty = struct_ty.fieldType(field_index, zcu);
6979 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) return .none;6829 if (!field_ty.hasRuntimeBits(zcu)) return .none;
69806830
6981 if (!isByRef(struct_ty, zcu)) {6831 if (!isByRef(struct_ty, zcu)) {
6982 assert(!isByRef(field_ty, zcu));6832 assert(!isByRef(field_ty, zcu));
...@@ -7037,15 +6887,17 @@ pub const FuncGen = struct {...@@ -7037,15 +6887,17 @@ pub const FuncGen = struct {
7037 const llvm_field_index = o.llvmFieldIndex(struct_ty, field_index).?;6887 const llvm_field_index = o.llvmFieldIndex(struct_ty, field_index).?;
7038 const field_ptr =6888 const field_ptr =
7039 try self.wip.gepStruct(struct_llvm_ty, struct_llvm_val, llvm_field_index, "");6889 try self.wip.gepStruct(struct_llvm_ty, struct_llvm_val, llvm_field_index, "");
7040 const alignment = struct_ty.fieldAlignment(field_index, zcu);6890 const explicit_alignment = struct_ty.explicitFieldAlignment(field_index, zcu);
7041 const field_ptr_ty = try pt.ptrType(.{6891 const field_ptr_ty = try pt.ptrType(.{
7042 .child = field_ty.toIntern(),6892 .child = field_ty.toIntern(),
7043 .flags = .{ .alignment = alignment },6893 .flags = .{ .alignment = explicit_alignment },
7044 });6894 });
7045 if (isByRef(field_ty, zcu)) {6895 if (isByRef(field_ty, zcu)) {
7046 assert(alignment != .none);6896 const alignment = switch (explicit_alignment) {
7047 const field_alignment = alignment.toLlvm();6897 .none => field_ty.abiAlignment(zcu),
7048 return self.loadByRef(field_ptr, field_ty, field_alignment, .normal);6898 else => |a| a,
6899 };
6900 return self.loadByRef(field_ptr, field_ty, alignment.toLlvm(), .normal);
7049 } else {6901 } else {
7050 return self.load(field_ptr, field_ptr_ty);6902 return self.load(field_ptr, field_ptr_ty);
7051 }6903 }
...@@ -7146,7 +6998,7 @@ pub const FuncGen = struct {...@@ -7146,7 +6998,7 @@ pub const FuncGen = struct {
7146 self.file,6998 self.file,
7147 self.scope,6999 self.scope,
7148 self.prev_dbg_line,7000 self.prev_dbg_line,
7149 try o.lowerDebugType(pt, ptr_ty.childType(zcu)),7001 try o.getDebugType(pt, ptr_ty.childType(zcu)),
7150 );7002 );
71517003
7152 _ = try self.wip.callIntrinsic(7004 _ = try self.wip.callIntrinsic(
...@@ -7179,7 +7031,7 @@ pub const FuncGen = struct {...@@ -7179,7 +7031,7 @@ pub const FuncGen = struct {
7179 self.file,7031 self.file,
7180 self.scope,7032 self.scope,
7181 self.prev_dbg_line,7033 self.prev_dbg_line,
7182 try o.lowerDebugType(pt, operand_ty),7034 try o.getDebugType(pt, operand_ty),
7183 arg_no: {7035 arg_no: {
7184 self.arg_inline_index += 1;7036 self.arg_inline_index += 1;
7185 break :arg_no self.arg_inline_index;7037 break :arg_no self.arg_inline_index;
...@@ -7189,7 +7041,7 @@ pub const FuncGen = struct {...@@ -7189,7 +7041,7 @@ pub const FuncGen = struct {
7189 self.file,7041 self.file,
7190 self.scope,7042 self.scope,
7191 self.prev_dbg_line,7043 self.prev_dbg_line,
7192 try o.lowerDebugType(pt, operand_ty),7044 try o.getDebugType(pt, operand_ty),
7193 );7045 );
71947046
7195 const zcu = pt.zcu;7047 const zcu = pt.zcu;
...@@ -7280,6 +7132,7 @@ pub const FuncGen = struct {...@@ -7280,6 +7132,7 @@ pub const FuncGen = struct {
7280 const llvm_param_attrs = try arena.alloc(Builder.Type, max_param_count);7132 const llvm_param_attrs = try arena.alloc(Builder.Type, max_param_count);
7281 const pt = self.ng.pt;7133 const pt = self.ng.pt;
7282 const zcu = pt.zcu;7134 const zcu = pt.zcu;
7135 const ip = &zcu.intern_pool;
7283 const target = zcu.getTarget();7136 const target = zcu.getTarget();
72847137
7285 var llvm_ret_i: usize = 0;7138 var llvm_ret_i: usize = 0;
...@@ -7304,7 +7157,7 @@ pub const FuncGen = struct {...@@ -7304,7 +7157,7 @@ pub const FuncGen = struct {
7304 const output_inst = try self.resolveInst(output.operand);7157 const output_inst = try self.resolveInst(output.operand);
7305 const output_ty = self.typeOf(output.operand);7158 const output_ty = self.typeOf(output.operand);
7306 assert(output_ty.zigTypeTag(zcu) == .pointer);7159 assert(output_ty.zigTypeTag(zcu) == .pointer);
7307 const elem_llvm_ty = try o.lowerPtrElemTy(pt, output_ty.childType(zcu));7160 const elem_llvm_ty = try o.lowerType(pt, output_ty.childType(zcu));
73087161
7309 switch (constraint[0]) {7162 switch (constraint[0]) {
7310 '=' => {},7163 '=' => {},
...@@ -7422,7 +7275,7 @@ pub const FuncGen = struct {...@@ -7422,7 +7275,7 @@ pub const FuncGen = struct {
7422 llvm_param_attrs[llvm_param_i] = if (constraint[0] == '*') blk: {7275 llvm_param_attrs[llvm_param_i] = if (constraint[0] == '*') blk: {
7423 if (!is_by_ref) self.maybeMarkAllowZeroAccess(arg_ty.ptrInfo(zcu));7276 if (!is_by_ref) self.maybeMarkAllowZeroAccess(arg_ty.ptrInfo(zcu));
74247277
7425 break :blk try o.lowerPtrElemTy(pt, if (is_by_ref) arg_ty else arg_ty.childType(zcu));7278 break :blk try o.lowerType(pt, if (is_by_ref) arg_ty else arg_ty.childType(zcu));
7426 } else .none;7279 } else .none;
74277280
7428 llvm_param_i += 1;7281 llvm_param_i += 1;
...@@ -7436,7 +7289,7 @@ pub const FuncGen = struct {...@@ -7436,7 +7289,7 @@ pub const FuncGen = struct {
7436 if (constraint[0] != '+') continue;7289 if (constraint[0] != '+') continue;
74377290
7438 const rw_ty = self.typeOf(output.operand);7291 const rw_ty = self.typeOf(output.operand);
7439 const llvm_elem_ty = try o.lowerPtrElemTy(pt, rw_ty.childType(zcu));7292 const llvm_elem_ty = try o.lowerType(pt, rw_ty.childType(zcu));
7440 if (llvm_ret_indirect[output.index]) {7293 if (llvm_ret_indirect[output.index]) {
7441 llvm_param_values[llvm_param_i] = llvm_rw_vals[output.index];7294 llvm_param_values[llvm_param_i] = llvm_rw_vals[output.index];
7442 llvm_param_types[llvm_param_i] = llvm_rw_vals[output.index].typeOfWip(&self.wip);7295 llvm_param_types[llvm_param_i] = llvm_rw_vals[output.index].typeOfWip(&self.wip);
...@@ -7463,7 +7316,7 @@ pub const FuncGen = struct {...@@ -7463,7 +7316,7 @@ pub const FuncGen = struct {
7463 total_i += 1;7316 total_i += 1;
7464 }7317 }
74657318
7466 const ip = &zcu.intern_pool;7319 if (total_i != 0) try llvm_constraints.append(gpa, ',');
7467 const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers);7320 const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers);
7468 const clobbers_ty = clobbers_val.typeOf(zcu);7321 const clobbers_ty = clobbers_val.typeOf(zcu);
7469 var clobbers_bigint_buf: Value.BigIntSpace = undefined;7322 var clobbers_bigint_buf: Value.BigIntSpace = undefined;
...@@ -7663,7 +7516,7 @@ pub const FuncGen = struct {...@@ -7663,7 +7516,7 @@ pub const FuncGen = struct {
76637516
7664 comptime assert(optional_layout_version == 3);7517 comptime assert(optional_layout_version == 3);
76657518
7666 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {7519 if (!payload_ty.hasRuntimeBits(zcu)) {
7667 const loaded = if (operand_is_ptr)7520 const loaded = if (operand_is_ptr)
7668 try self.wip.load(access_kind, optional_llvm_ty, operand, .default, "")7521 try self.wip.load(access_kind, optional_llvm_ty, operand, .default, "")
7669 else7522 else
...@@ -7706,7 +7559,7 @@ pub const FuncGen = struct {...@@ -7706,7 +7559,7 @@ pub const FuncGen = struct {
77067559
7707 if (operand_is_ptr) self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu));7560 if (operand_is_ptr) self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu));
77087561
7709 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {7562 if (!payload_ty.hasRuntimeBits(zcu)) {
7710 const loaded = if (operand_is_ptr)7563 const loaded = if (operand_is_ptr)
7711 try self.wip.load(access_kind, try o.lowerType(pt, err_union_ty), operand, .default, "")7564 try self.wip.load(access_kind, try o.lowerType(pt, err_union_ty), operand, .default, "")
7712 else7565 else
...@@ -7733,7 +7586,7 @@ pub const FuncGen = struct {...@@ -7733,7 +7586,7 @@ pub const FuncGen = struct {
7733 const operand = try self.resolveInst(ty_op.operand);7586 const operand = try self.resolveInst(ty_op.operand);
7734 const optional_ty = self.typeOf(ty_op.operand).childType(zcu);7587 const optional_ty = self.typeOf(ty_op.operand).childType(zcu);
7735 const payload_ty = optional_ty.optionalChild(zcu);7588 const payload_ty = optional_ty.optionalChild(zcu);
7736 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {7589 if (!payload_ty.hasRuntimeBits(zcu)) {
7737 // We have a pointer to a zero-bit value and we need to return7590 // We have a pointer to a zero-bit value and we need to return
7738 // a pointer to a zero-bit value.7591 // a pointer to a zero-bit value.
7739 return operand;7592 return operand;
...@@ -7761,7 +7614,7 @@ pub const FuncGen = struct {...@@ -7761,7 +7614,7 @@ pub const FuncGen = struct {
7761 const access_kind: Builder.MemoryAccessKind =7614 const access_kind: Builder.MemoryAccessKind =
7762 if (optional_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;7615 if (optional_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
77637616
7764 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {7617 if (!payload_ty.hasRuntimeBits(zcu)) {
7765 self.maybeMarkAllowZeroAccess(optional_ptr_ty.ptrInfo(zcu));7618 self.maybeMarkAllowZeroAccess(optional_ptr_ty.ptrInfo(zcu));
77667619
7767 // We have a pointer to a i8. We need to set it to 1 and then return the same pointer.7620 // 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 {...@@ -7797,7 +7650,7 @@ pub const FuncGen = struct {
7797 const operand = try self.resolveInst(ty_op.operand);7650 const operand = try self.resolveInst(ty_op.operand);
7798 const optional_ty = self.typeOf(ty_op.operand);7651 const optional_ty = self.typeOf(ty_op.operand);
7799 const payload_ty = self.typeOfIndex(inst);7652 const payload_ty = self.typeOfIndex(inst);
7800 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return .none;7653 if (!payload_ty.hasRuntimeBits(zcu)) return .none;
78017654
7802 if (optional_ty.optionalReprIsPayload(zcu)) {7655 if (optional_ty.optionalReprIsPayload(zcu)) {
7803 // Payload value is the same as the optional value.7656 // Payload value is the same as the optional value.
...@@ -7819,7 +7672,7 @@ pub const FuncGen = struct {...@@ -7819,7 +7672,7 @@ pub const FuncGen = struct {
7819 const result_ty = self.typeOfIndex(inst);7672 const result_ty = self.typeOfIndex(inst);
7820 const payload_ty = if (operand_is_ptr) result_ty.childType(zcu) else result_ty;7673 const payload_ty = if (operand_is_ptr) result_ty.childType(zcu) else result_ty;
78217674
7822 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {7675 if (!payload_ty.hasRuntimeBits(zcu)) {
7823 return if (operand_is_ptr) operand else .none;7676 return if (operand_is_ptr) operand else .none;
7824 }7677 }
7825 const offset = try errUnionPayloadOffset(payload_ty, pt);7678 const offset = try errUnionPayloadOffset(payload_ty, pt);
...@@ -7863,7 +7716,7 @@ pub const FuncGen = struct {...@@ -7863,7 +7716,7 @@ pub const FuncGen = struct {
7863 if (operand_is_ptr and operand_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;7716 if (operand_is_ptr and operand_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
78647717
7865 const payload_ty = err_union_ty.errorUnionPayload(zcu);7718 const payload_ty = err_union_ty.errorUnionPayload(zcu);
7866 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {7719 if (!payload_ty.hasRuntimeBits(zcu)) {
7867 if (!operand_is_ptr) return operand;7720 if (!operand_is_ptr) return operand;
78687721
7869 self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu));7722 self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu));
...@@ -7899,7 +7752,7 @@ pub const FuncGen = struct {...@@ -7899,7 +7752,7 @@ pub const FuncGen = struct {
7899 const access_kind: Builder.MemoryAccessKind =7752 const access_kind: Builder.MemoryAccessKind =
7900 if (err_union_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;7753 if (err_union_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
79017754
7902 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {7755 if (!payload_ty.hasRuntimeBits(zcu)) {
7903 self.maybeMarkAllowZeroAccess(err_union_ptr_ty.ptrInfo(zcu));7756 self.maybeMarkAllowZeroAccess(err_union_ptr_ty.ptrInfo(zcu));
79047757
7905 _ = try self.wip.store(access_kind, non_error_val, operand, .default);7758 _ = try self.wip.store(access_kind, non_error_val, operand, .default);
...@@ -7946,9 +7799,8 @@ pub const FuncGen = struct {...@@ -7946,9 +7799,8 @@ pub const FuncGen = struct {
7946 const struct_llvm_ty = try o.lowerType(pt, struct_ty);7799 const struct_llvm_ty = try o.lowerType(pt, struct_ty);
7947 const llvm_field_index = o.llvmFieldIndex(struct_ty, field_index).?;7800 const llvm_field_index = o.llvmFieldIndex(struct_ty, field_index).?;
7948 assert(self.err_ret_trace != .none);7801 assert(self.err_ret_trace != .none);
7949 const field_ptr =7802 const field_ptr = try self.wip.gepStruct(struct_llvm_ty, self.err_ret_trace, llvm_field_index, "");
7950 try self.wip.gepStruct(struct_llvm_ty, self.err_ret_trace, llvm_field_index, "");7803 const field_alignment = struct_ty.explicitFieldAlignment(field_index, zcu);
7951 const field_alignment = struct_ty.fieldAlignment(field_index, zcu);
7952 const field_ty = struct_ty.fieldType(field_index, zcu);7804 const field_ty = struct_ty.fieldType(field_index, zcu);
7953 const field_ptr_ty = try pt.ptrType(.{7805 const field_ptr_ty = try pt.ptrType(.{
7954 .child = field_ty.toIntern(),7806 .child = field_ty.toIntern(),
...@@ -7989,7 +7841,7 @@ pub const FuncGen = struct {...@@ -7989,7 +7841,7 @@ pub const FuncGen = struct {
7989 const payload_ty = self.typeOf(ty_op.operand);7841 const payload_ty = self.typeOf(ty_op.operand);
7990 const non_null_bit = try o.builder.intValue(.i8, 1);7842 const non_null_bit = try o.builder.intValue(.i8, 1);
7991 comptime assert(optional_layout_version == 3);7843 comptime assert(optional_layout_version == 3);
7992 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return non_null_bit;7844 assert(payload_ty.hasRuntimeBits(zcu));
7993 const operand = try self.resolveInst(ty_op.operand);7845 const operand = try self.resolveInst(ty_op.operand);
7994 const optional_ty = self.typeOfIndex(inst);7846 const optional_ty = self.typeOfIndex(inst);
7995 if (optional_ty.optionalReprIsPayload(zcu)) return operand;7847 if (optional_ty.optionalReprIsPayload(zcu)) return operand;
...@@ -8023,9 +7875,7 @@ pub const FuncGen = struct {...@@ -8023,9 +7875,7 @@ pub const FuncGen = struct {
8023 const err_un_ty = self.typeOfIndex(inst);7875 const err_un_ty = self.typeOfIndex(inst);
8024 const operand = try self.resolveInst(ty_op.operand);7876 const operand = try self.resolveInst(ty_op.operand);
8025 const payload_ty = self.typeOf(ty_op.operand);7877 const payload_ty = self.typeOf(ty_op.operand);
8026 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {7878 assert(payload_ty.hasRuntimeBits(zcu));
8027 return operand;
8028 }
8029 const ok_err_code = try o.builder.intValue(try o.errorIntType(pt), 0);7879 const ok_err_code = try o.builder.intValue(try o.errorIntType(pt), 0);
8030 const err_un_llvm_ty = try o.lowerType(pt, err_un_ty);7880 const err_un_llvm_ty = try o.lowerType(pt, err_un_ty);
80317881
...@@ -8065,7 +7915,7 @@ pub const FuncGen = struct {...@@ -8065,7 +7915,7 @@ pub const FuncGen = struct {
8065 const err_un_ty = self.typeOfIndex(inst);7915 const err_un_ty = self.typeOfIndex(inst);
8066 const payload_ty = err_un_ty.errorUnionPayload(zcu);7916 const payload_ty = err_un_ty.errorUnionPayload(zcu);
8067 const operand = try self.resolveInst(ty_op.operand);7917 const operand = try self.resolveInst(ty_op.operand);
8068 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return operand;7918 if (!payload_ty.hasRuntimeBits(zcu)) return operand;
8069 const err_un_llvm_ty = try o.lowerType(pt, err_un_ty);7919 const err_un_llvm_ty = try o.lowerType(pt, err_un_ty);
80707920
8071 const payload_offset = try errUnionPayloadOffset(payload_ty, pt);7921 const payload_offset = try errUnionPayloadOffset(payload_ty, pt);
...@@ -8517,7 +8367,7 @@ pub const FuncGen = struct {...@@ -8517,7 +8367,7 @@ pub const FuncGen = struct {
8517 const ptr = try self.resolveInst(bin_op.lhs);8367 const ptr = try self.resolveInst(bin_op.lhs);
8518 const offset = try self.resolveInst(bin_op.rhs);8368 const offset = try self.resolveInst(bin_op.rhs);
8519 const ptr_ty = self.typeOf(bin_op.lhs);8369 const ptr_ty = self.typeOf(bin_op.lhs);
8520 const llvm_elem_ty = try o.lowerPtrElemTy(pt, ptr_ty.childType(zcu));8370 const llvm_elem_ty = try o.lowerType(pt, ptr_ty.childType(zcu));
8521 switch (ptr_ty.ptrSize(zcu)) {8371 switch (ptr_ty.ptrSize(zcu)) {
8522 // It's a pointer to an array, so according to LLVM we need an extra GEP index.8372 // It's a pointer to an array, so according to LLVM we need an extra GEP index.
8523 .one => return self.wip.gep(.inbounds, llvm_elem_ty, ptr, &.{8373 .one => return self.wip.gep(.inbounds, llvm_elem_ty, ptr, &.{
...@@ -8541,7 +8391,7 @@ pub const FuncGen = struct {...@@ -8541,7 +8391,7 @@ pub const FuncGen = struct {
8541 const offset = try self.resolveInst(bin_op.rhs);8391 const offset = try self.resolveInst(bin_op.rhs);
8542 const negative_offset = try self.wip.neg(offset, "");8392 const negative_offset = try self.wip.neg(offset, "");
8543 const ptr_ty = self.typeOf(bin_op.lhs);8393 const ptr_ty = self.typeOf(bin_op.lhs);
8544 const llvm_elem_ty = try o.lowerPtrElemTy(pt, ptr_ty.childType(zcu));8394 const llvm_elem_ty = try o.lowerType(pt, ptr_ty.childType(zcu));
8545 switch (ptr_ty.ptrSize(zcu)) {8395 switch (ptr_ty.ptrSize(zcu)) {
8546 // It's a pointer to an array, so according to LLVM we need an extra GEP index.8396 // It's a pointer to an array, so according to LLVM we need an extra GEP index.
8547 .one => return self.wip.gep(.inbounds, llvm_elem_ty, ptr, &.{8397 .one => return self.wip.gep(.inbounds, llvm_elem_ty, ptr, &.{
...@@ -9502,7 +9352,7 @@ pub const FuncGen = struct {...@@ -9502,7 +9352,7 @@ pub const FuncGen = struct {
9502 self.file,9352 self.file,
9503 self.scope,9353 self.scope,
9504 lbrace_line,9354 lbrace_line,
9505 try o.lowerDebugType(pt, inst_ty),9355 try o.getDebugType(pt, inst_ty),
9506 self.arg_index,9356 self.arg_index,
9507 );9357 );
95089358
...@@ -9836,7 +9686,7 @@ pub const FuncGen = struct {...@@ -9836,7 +9686,7 @@ pub const FuncGen = struct {
9836 const ptr_ty = self.typeOf(atomic_load.ptr);9686 const ptr_ty = self.typeOf(atomic_load.ptr);
9837 const info = ptr_ty.ptrInfo(zcu);9687 const info = ptr_ty.ptrInfo(zcu);
9838 const elem_ty = Type.fromInterned(info.child);9688 const elem_ty = Type.fromInterned(info.child);
9839 if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return .none;9689 if (!elem_ty.hasRuntimeBits(zcu)) return .none;
9840 const ordering = toLlvmAtomicOrdering(atomic_load.order);9690 const ordering = toLlvmAtomicOrdering(atomic_load.order);
9841 const llvm_abi_ty = try o.getAtomicAbiType(pt, elem_ty, false);9691 const llvm_abi_ty = try o.getAtomicAbiType(pt, elem_ty, false);
9842 const ptr_alignment = (if (info.flags.alignment != .none)9692 const ptr_alignment = (if (info.flags.alignment != .none)
...@@ -10304,7 +10154,7 @@ pub const FuncGen = struct {...@@ -10304,7 +10154,7 @@ pub const FuncGen = struct {
1030410154
10305 const target = &zcu.root_mod.resolved_target.result;10155 const target = &zcu.root_mod.resolved_target.result;
10306 const function_index = try o.builder.addFunction(10156 const function_index = try o.builder.addFunction(
10307 try o.builder.fnType(.i1, &.{try o.lowerType(pt, Type.fromInterned(enum_type.tag_ty))}, .normal),10157 try o.builder.fnType(.i1, &.{try o.lowerType(pt, Type.fromInterned(enum_type.int_tag_type))}, .normal),
10308 try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_type.name.fmt(ip)}),10158 try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_type.name.fmt(ip)}),
10309 toLlvmAddressSpace(.generic, target),10159 toLlvmAddressSpace(.generic, target),
10310 );10160 );
...@@ -10325,13 +10175,13 @@ pub const FuncGen = struct {...@@ -10325,13 +10175,13 @@ pub const FuncGen = struct {
10325 defer wip.deinit();10175 defer wip.deinit();
10326 wip.cursor = .{ .block = try wip.block(0, "Entry") };10176 wip.cursor = .{ .block = try wip.block(0, "Entry") };
1032710177
10328 const named_block = try wip.block(@intCast(enum_type.names.len), "Named");10178 const named_block = try wip.block(@intCast(enum_type.field_names.len), "Named");
10329 const unnamed_block = try wip.block(1, "Unnamed");10179 const unnamed_block = try wip.block(1, "Unnamed");
10330 const tag_int_value = wip.arg(0);10180 const tag_int_value = wip.arg(0);
10331 var wip_switch = try wip.@"switch"(tag_int_value, unnamed_block, @intCast(enum_type.names.len), .none);10181 var wip_switch = try wip.@"switch"(tag_int_value, unnamed_block, @intCast(enum_type.field_names.len), .none);
10332 defer wip_switch.finish(&wip);10182 defer wip_switch.finish(&wip);
1033310183
10334 for (0..enum_type.names.len) |field_index| {10184 for (0..enum_type.field_names.len) |field_index| {
10335 const this_tag_int_value = try o.lowerValue(10185 const this_tag_int_value = try o.lowerValue(
10336 pt,10186 pt,
10337 (try pt.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(),10187 (try pt.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(),
...@@ -10800,15 +10650,14 @@ pub const FuncGen = struct {...@@ -10800,15 +10650,14 @@ pub const FuncGen = struct {
10800 },10650 },
10801 .@"struct" => {10651 .@"struct" => {
10802 if (zcu.typeToPackedStruct(result_ty)) |struct_type| {10652 if (zcu.typeToPackedStruct(result_ty)) |struct_type| {
10803 const backing_int_ty = struct_type.backingIntTypeUnordered(ip);10653 const backing_int_ty: Type = .fromInterned(struct_type.packed_backing_int_type);
10804 assert(backing_int_ty != .none);10654 const big_bits = backing_int_ty.bitSize(zcu);
10805 const big_bits = Type.fromInterned(backing_int_ty).bitSize(zcu);
10806 const int_ty = try o.builder.intType(@intCast(big_bits));10655 const int_ty = try o.builder.intType(@intCast(big_bits));
10807 comptime assert(Type.packed_struct_layout_version == 2);10656 comptime assert(Type.packed_struct_layout_version == 2);
10808 var running_int = try o.builder.intValue(int_ty, 0);10657 var running_int = try o.builder.intValue(int_ty, 0);
10809 var running_bits: u16 = 0;10658 var running_bits: u16 = 0;
10810 for (elements, struct_type.field_types.get(ip)) |elem, field_ty| {10659 for (elements, struct_type.field_types.get(ip)) |elem, field_ty| {
10811 if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(zcu)) continue;10660 if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue;
1081210661
10813 const non_int_val = try self.resolveInst(elem);10662 const non_int_val = try self.resolveInst(elem);
10814 const ty_bit_size: u16 = @intCast(Type.fromInterned(field_ty).bitSize(zcu));10663 const ty_bit_size: u16 = @intCast(Type.fromInterned(field_ty).bitSize(zcu));
...@@ -10840,12 +10689,12 @@ pub const FuncGen = struct {...@@ -10840,12 +10689,12 @@ pub const FuncGen = struct {
1084010689
10841 const llvm_elem = try self.resolveInst(elem);10690 const llvm_elem = try self.resolveInst(elem);
10842 const llvm_i = o.llvmFieldIndex(result_ty, i).?;10691 const llvm_i = o.llvmFieldIndex(result_ty, i).?;
10843 const field_ptr =10692 const field_ptr = try self.wip.gepStruct(llvm_result_ty, alloca_inst, llvm_i, "");
10844 try self.wip.gepStruct(llvm_result_ty, alloca_inst, llvm_i, "");10693
10845 const field_ptr_ty = try pt.ptrType(.{10694 const field_ptr_ty = try pt.ptrType(.{
10846 .child = self.typeOf(elem).toIntern(),10695 .child = self.typeOf(elem).toIntern(),
10847 .flags = .{10696 .flags = .{
10848 .alignment = result_ty.fieldAlignment(i, zcu),10697 .alignment = result_ty.explicitFieldAlignment(i, zcu),
10849 },10698 },
10850 });10699 });
10851 try self.store(field_ptr, field_ptr_ty, llvm_elem, .none);10700 try self.store(field_ptr, field_ptr_ty, llvm_elem, .none);
...@@ -10910,7 +10759,7 @@ pub const FuncGen = struct {...@@ -10910,7 +10759,7 @@ pub const FuncGen = struct {
10910 const layout = union_ty.unionGetLayout(zcu);10759 const layout = union_ty.unionGetLayout(zcu);
10911 const union_obj = zcu.typeToUnion(union_ty).?;10760 const union_obj = zcu.typeToUnion(union_ty).?;
1091210761
10913 if (union_obj.flagsUnordered(ip).layout == .@"packed") {10762 if (union_obj.layout == .@"packed") {
10914 const big_bits = union_ty.bitSize(zcu);10763 const big_bits = union_ty.bitSize(zcu);
10915 const int_llvm_ty = try o.builder.intType(@intCast(big_bits));10764 const int_llvm_ty = try o.builder.intType(@intCast(big_bits));
10916 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]);10765 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]);
...@@ -10925,10 +10774,8 @@ pub const FuncGen = struct {...@@ -10925,10 +10774,8 @@ pub const FuncGen = struct {
1092510774
10926 const tag_int_val = blk: {10775 const tag_int_val = blk: {
10927 const tag_ty = union_ty.unionTagTypeHypothetical(zcu);10776 const tag_ty = union_ty.unionTagTypeHypothetical(zcu);
10928 const union_field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index];10777 const tag_val = try pt.enumValueFieldIndex(tag_ty, extra.field_index);
10929 const enum_field_index = tag_ty.enumFieldIndex(union_field_name, zcu).?;10778 break :blk tag_val.intFromEnum(zcu);
10930 const tag_val = try pt.enumValueFieldIndex(tag_ty, enum_field_index);
10931 break :blk try tag_val.intFromEnum(tag_ty, pt);
10932 };10779 };
10933 if (layout.payload_size == 0) {10780 if (layout.payload_size == 0) {
10934 if (layout.tag_size == 0) {10781 if (layout.tag_size == 0) {
...@@ -10950,16 +10797,14 @@ pub const FuncGen = struct {...@@ -10950,16 +10797,14 @@ pub const FuncGen = struct {
10950 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]);10797 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]);
10951 const field_llvm_ty = try o.lowerType(pt, field_ty);10798 const field_llvm_ty = try o.lowerType(pt, field_ty);
10952 const field_size = field_ty.abiSize(zcu);10799 const field_size = field_ty.abiSize(zcu);
10953 const field_align = union_ty.fieldAlignment(extra.field_index, zcu);10800 const field_align = union_ty.explicitFieldAlignment(extra.field_index, zcu);
10954 const llvm_usize = try o.lowerType(pt, Type.usize);10801 const llvm_usize = try o.lowerType(pt, Type.usize);
10955 const usize_zero = try o.builder.intValue(llvm_usize, 0);10802 const usize_zero = try o.builder.intValue(llvm_usize, 0);
1095610803
10804 assert(field_ty.hasRuntimeBits(zcu));
10805
10957 const llvm_union_ty = t: {10806 const llvm_union_ty = t: {
10958 const payload_ty = p: {10807 const payload_ty = p: {
10959 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
10960 const padding_len = layout.payload_size;
10961 break :p try o.builder.arrayType(padding_len, .i8);
10962 }
10963 if (field_size == layout.payload_size) {10808 if (field_size == layout.payload_size) {
10964 break :p field_llvm_ty;10809 break :p field_llvm_ty;
10965 }10810 }
...@@ -10969,7 +10814,7 @@ pub const FuncGen = struct {...@@ -10969,7 +10814,7 @@ pub const FuncGen = struct {
10969 });10814 });
10970 };10815 };
10971 if (layout.tag_size == 0) break :t try o.builder.structType(.normal, &.{payload_ty});10816 if (layout.tag_size == 0) break :t try o.builder.structType(.normal, &.{payload_ty});
10972 const tag_ty = try o.lowerType(pt, Type.fromInterned(union_obj.enum_tag_ty));10817 const tag_ty = try o.lowerType(pt, .fromInterned(union_obj.enum_tag_type));
10973 var fields: [3]Builder.Type = undefined;10818 var fields: [3]Builder.Type = undefined;
10974 var fields_len: usize = 2;10819 var fields_len: usize = 2;
10975 if (layout.tag_align.compare(.gte, layout.payload_align)) {10820 if (layout.tag_align.compare(.gte, layout.payload_align)) {
...@@ -11010,11 +10855,11 @@ pub const FuncGen = struct {...@@ -11010,11 +10855,11 @@ pub const FuncGen = struct {
11010 const tag_index = @intFromBool(layout.tag_align.compare(.lt, layout.payload_align));10855 const tag_index = @intFromBool(layout.tag_align.compare(.lt, layout.payload_align));
11011 const indices: [2]Builder.Value = .{ usize_zero, try o.builder.intValue(.i32, tag_index) };10856 const indices: [2]Builder.Value = .{ usize_zero, try o.builder.intValue(.i32, tag_index) };
11012 const field_ptr = try self.wip.gep(.inbounds, llvm_union_ty, result_ptr, &indices, "");10857 const field_ptr = try self.wip.gep(.inbounds, llvm_union_ty, result_ptr, &indices, "");
11013 const tag_ty = try o.lowerType(pt, Type.fromInterned(union_obj.enum_tag_ty));10858 const tag_ty = try o.lowerType(pt, .fromInterned(union_obj.enum_tag_type));
11014 var big_int_space: Value.BigIntSpace = undefined;10859 var big_int_space: Value.BigIntSpace = undefined;
11015 const tag_big_int = tag_int_val.toBigInt(&big_int_space, zcu);10860 const tag_big_int = tag_int_val.toBigInt(&big_int_space, zcu);
11016 const llvm_tag = try o.builder.bigIntValue(tag_ty, tag_big_int);10861 const llvm_tag = try o.builder.bigIntValue(tag_ty, tag_big_int);
11017 const tag_alignment = Type.fromInterned(union_obj.enum_tag_ty).abiAlignment(zcu).toLlvm();10862 const tag_alignment = Type.fromInterned(union_obj.enum_tag_type).abiAlignment(zcu).toLlvm();
11018 _ = try self.wip.store(.normal, llvm_tag, field_ptr, tag_alignment);10863 _ = try self.wip.store(.normal, llvm_tag, field_ptr, tag_alignment);
11019 }10864 }
1102010865
...@@ -11295,8 +11140,10 @@ pub const FuncGen = struct {...@@ -11295,8 +11140,10 @@ pub const FuncGen = struct {
11295 return self.wip.gep(.inbounds, .i8, struct_ptr, &.{llvm_index}, "");11140 return self.wip.gep(.inbounds, .i8, struct_ptr, &.{llvm_index}, "");
11296 },11141 },
11297 else => {11142 else => {
11298 const struct_llvm_ty = try o.lowerPtrElemTy(pt, struct_ty);11143 if (!struct_ty.hasRuntimeBits(zcu)) {
1129911144 return struct_ptr;
11145 }
11146 const struct_llvm_ty = try o.lowerType(pt, struct_ty);
11300 if (o.llvmFieldIndex(struct_ty, field_index)) |llvm_field_index| {11147 if (o.llvmFieldIndex(struct_ty, field_index)) |llvm_field_index| {
11301 return self.wip.gepStruct(struct_llvm_ty, struct_ptr, llvm_field_index, "");11148 return self.wip.gepStruct(struct_llvm_ty, struct_ptr, llvm_field_index, "");
11302 } else {11149 } else {
...@@ -11306,7 +11153,7 @@ pub const FuncGen = struct {...@@ -11306,7 +11153,7 @@ pub const FuncGen = struct {
11306 // the struct.11153 // the struct.
11307 const llvm_index = try o.builder.intValue(11154 const llvm_index = try o.builder.intValue(
11308 try o.lowerType(pt, Type.usize),11155 try o.lowerType(pt, Type.usize),
11309 @intFromBool(struct_ty.hasRuntimeBitsIgnoreComptime(zcu)),11156 @intFromBool(struct_ty.hasRuntimeBits(zcu)),
11310 );11157 );
11311 return self.wip.gep(.inbounds, struct_llvm_ty, struct_ptr, &.{llvm_index}, "");11158 return self.wip.gep(.inbounds, struct_llvm_ty, struct_ptr, &.{llvm_index}, "");
11312 }11159 }
...@@ -11393,7 +11240,7 @@ pub const FuncGen = struct {...@@ -11393,7 +11240,7 @@ pub const FuncGen = struct {
11393 const zcu = pt.zcu;11240 const zcu = pt.zcu;
11394 const info = ptr_ty.ptrInfo(zcu);11241 const info = ptr_ty.ptrInfo(zcu);
11395 const elem_ty = Type.fromInterned(info.child);11242 const elem_ty = Type.fromInterned(info.child);
11396 if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return .none;11243 if (!elem_ty.hasRuntimeBits(zcu)) return .none;
1139711244
11398 const ptr_alignment = (if (info.flags.alignment != .none)11245 const ptr_alignment = (if (info.flags.alignment != .none)
11399 @as(InternPool.Alignment, info.flags.alignment)11246 @as(InternPool.Alignment, info.flags.alignment)
...@@ -12048,7 +11895,7 @@ fn returnTypeByRef(zcu: *Zcu, target: *const std.Target, ty: Type) bool {...@@ -12048,7 +11895,7 @@ fn returnTypeByRef(zcu: *Zcu, target: *const std.Target, ty: Type) bool {
1204811895
12049fn firstParamSRet(fn_info: InternPool.Key.FuncType, zcu: *Zcu, target: *const std.Target) bool {11896fn firstParamSRet(fn_info: InternPool.Key.FuncType, zcu: *Zcu, target: *const std.Target) bool {
12050 const return_type = Type.fromInterned(fn_info.return_type);11897 const return_type = Type.fromInterned(fn_info.return_type);
12051 if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) return false;11898 if (!return_type.hasRuntimeBits(zcu)) return false;
1205211899
12053 return switch (fn_info.cc) {11900 return switch (fn_info.cc) {
12054 .auto => returnTypeByRef(zcu, target, return_type),11901 .auto => returnTypeByRef(zcu, target, return_type),
...@@ -12088,11 +11935,9 @@ fn firstParamSRetSystemV(ty: Type, zcu: *Zcu, target: *const std.Target) bool {...@@ -12088,11 +11935,9 @@ fn firstParamSRetSystemV(ty: Type, zcu: *Zcu, target: *const std.Target) bool {
12088fn lowerFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type {11935fn lowerFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type {
12089 const zcu = pt.zcu;11936 const zcu = pt.zcu;
12090 const return_type = Type.fromInterned(fn_info.return_type);11937 const return_type = Type.fromInterned(fn_info.return_type);
12091 if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) {11938 if (!return_type.hasRuntimeBits(zcu)) {
12092 // If the return type is an error set or an error union, then we make this11939 assert(!return_type.isError(zcu));
12093 // anyerror return type instead, so that it can be coerced into a function11940 return .void;
12094 // pointer type which has anyerror as the return type.
12095 return if (return_type.isError(zcu)) try o.errorIntType(pt) else .void;
12096 }11941 }
12097 const target = zcu.getTarget();11942 const target = zcu.getTarget();
12098 switch (fn_info.cc) {11943 switch (fn_info.cc) {
...@@ -12136,7 +11981,7 @@ fn lowerFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType)...@@ -12136,7 +11981,7 @@ fn lowerFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType)
12136 var types: [8]Builder.Type = undefined;11981 var types: [8]Builder.Type = undefined;
12137 for (0..return_type.structFieldCount(zcu)) |field_index| {11982 for (0..return_type.structFieldCount(zcu)) |field_index| {
12138 const field_ty = return_type.fieldType(field_index, zcu);11983 const field_ty = return_type.fieldType(field_index, zcu);
12139 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;11984 if (!field_ty.hasRuntimeBits(zcu)) continue;
12140 types[types_len] = try o.lowerType(pt, field_ty);11985 types[types_len] = try o.lowerType(pt, field_ty);
12141 types_len += 1;11986 types_len += 1;
12142 }11987 }
...@@ -12174,6 +12019,7 @@ fn lowerSystemVFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.Fu...@@ -12174,6 +12019,7 @@ fn lowerSystemVFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.Fu
12174 const zcu = pt.zcu;12019 const zcu = pt.zcu;
12175 const ip = &zcu.intern_pool;12020 const ip = &zcu.intern_pool;
12176 const return_type = Type.fromInterned(fn_info.return_type);12021 const return_type = Type.fromInterned(fn_info.return_type);
12022 return_type.assertHasLayout(zcu);
12177 if (isScalar(zcu, return_type)) {12023 if (isScalar(zcu, return_type)) {
12178 return o.lowerType(pt, return_type);12024 return o.lowerType(pt, return_type);
12179 }12025 }
...@@ -12222,9 +12068,7 @@ fn lowerSystemVFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.Fu...@@ -12222,9 +12068,7 @@ fn lowerSystemVFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.Fu
12222 assert(first_non_integer orelse classes.len == types_index);12068 assert(first_non_integer orelse classes.len == types_index);
12223 switch (ip.indexToKey(return_type.toIntern())) {12069 switch (ip.indexToKey(return_type.toIntern())) {
12224 .struct_type => {12070 .struct_type => {
12225 const struct_type = ip.loadStructType(return_type.toIntern());12071 const size = return_type.abiSize(zcu);
12226 assert(struct_type.haveLayout(ip));
12227 const size: u64 = struct_type.sizeUnordered(ip);
12228 assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index);12072 assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index);
12229 if (size % 8 > 0) {12073 if (size % 8 > 0) {
12230 types_buffer[types_index - 1] = try o.builder.intType(@intCast(size % 8 * 8));12074 types_buffer[types_index - 1] = try o.builder.intType(@intCast(size % 8 * 8));
...@@ -12260,7 +12104,7 @@ const ParamTypeIterator = struct {...@@ -12260,7 +12104,7 @@ const ParamTypeIterator = struct {
12260 i64_array: u8,12104 i64_array: u8,
12261 };12105 };
1226212106
12263 pub fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering {12107 fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering {
12264 if (it.zig_index >= it.fn_info.param_types.len) return null;12108 if (it.zig_index >= it.fn_info.param_types.len) return null;
12265 const ip = &it.pt.zcu.intern_pool;12109 const ip = &it.pt.zcu.intern_pool;
12266 const ty = it.fn_info.param_types.get(ip)[it.zig_index];12110 const ty = it.fn_info.param_types.get(ip)[it.zig_index];
...@@ -12269,7 +12113,7 @@ const ParamTypeIterator = struct {...@@ -12269,7 +12113,7 @@ const ParamTypeIterator = struct {
12269 }12113 }
1227012114
12271 /// `airCall` uses this instead of `next` so that it can take into account variadic functions.12115 /// `airCall` uses this instead of `next` so that it can take into account variadic functions.
12272 pub fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) Allocator.Error!?Lowering {12116 fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) Allocator.Error!?Lowering {
12273 assert(std.meta.eql(it.pt, fg.ng.pt));12117 assert(std.meta.eql(it.pt, fg.ng.pt));
12274 const ip = &it.pt.zcu.intern_pool;12118 const ip = &it.pt.zcu.intern_pool;
12275 if (it.zig_index >= it.fn_info.param_types.len) {12119 if (it.zig_index >= it.fn_info.param_types.len) {
...@@ -12288,7 +12132,7 @@ const ParamTypeIterator = struct {...@@ -12288,7 +12132,7 @@ const ParamTypeIterator = struct {
12288 const zcu = pt.zcu;12132 const zcu = pt.zcu;
12289 const target = zcu.getTarget();12133 const target = zcu.getTarget();
1229012134
12291 if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) {12135 if (!ty.hasRuntimeBits(zcu)) {
12292 it.zig_index += 1;12136 it.zig_index += 1;
12293 return .no_bits;12137 return .no_bits;
12294 }12138 }
...@@ -12383,7 +12227,7 @@ const ParamTypeIterator = struct {...@@ -12383,7 +12227,7 @@ const ParamTypeIterator = struct {
12383 it.types_len = 0;12227 it.types_len = 0;
12384 for (0..ty.structFieldCount(zcu)) |field_index| {12228 for (0..ty.structFieldCount(zcu)) |field_index| {
12385 const field_ty = ty.fieldType(field_index, zcu);12229 const field_ty = ty.fieldType(field_index, zcu);
12386 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;12230 if (!field_ty.hasRuntimeBits(zcu)) continue;
12387 it.types_buffer[it.types_len] = try it.object.lowerType(pt, field_ty);12231 it.types_buffer[it.types_len] = try it.object.lowerType(pt, field_ty);
12388 it.types_len += 1;12232 it.types_len += 1;
12389 }12233 }
...@@ -12460,6 +12304,7 @@ const ParamTypeIterator = struct {...@@ -12460,6 +12304,7 @@ const ParamTypeIterator = struct {
12460 fn nextSystemV(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering {12304 fn nextSystemV(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering {
12461 const zcu = it.pt.zcu;12305 const zcu = it.pt.zcu;
12462 const ip = &zcu.intern_pool;12306 const ip = &zcu.intern_pool;
12307 ty.assertHasLayout(zcu);
12463 const classes = x86_64_abi.classifySystemV(ty, zcu, zcu.getTarget(), .arg);12308 const classes = x86_64_abi.classifySystemV(ty, zcu, zcu.getTarget(), .arg);
12464 if (classes[0] == .memory) {12309 if (classes[0] == .memory) {
12465 it.zig_index += 1;12310 it.zig_index += 1;
...@@ -12531,9 +12376,7 @@ const ParamTypeIterator = struct {...@@ -12531,9 +12376,7 @@ const ParamTypeIterator = struct {
12531 }12376 }
12532 switch (ip.indexToKey(ty.toIntern())) {12377 switch (ip.indexToKey(ty.toIntern())) {
12533 .struct_type => {12378 .struct_type => {
12534 const struct_type = ip.loadStructType(ty.toIntern());12379 const size = ty.abiSize(zcu);
12535 assert(struct_type.haveLayout(ip));
12536 const size: u64 = struct_type.sizeUnordered(ip);
12537 assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index);12380 assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index);
12538 if (size % 8 > 0) {12381 if (size % 8 > 0) {
12539 types_buffer[types_index - 1] =12382 types_buffer[types_index - 1] =
...@@ -12707,14 +12550,14 @@ fn isByRef(ty: Type, zcu: *Zcu) bool {...@@ -12707,14 +12550,14 @@ fn isByRef(ty: Type, zcu: *Zcu) bool {
12707 },12550 },
12708 .error_union => {12551 .error_union => {
12709 const payload_ty = ty.errorUnionPayload(zcu);12552 const payload_ty = ty.errorUnionPayload(zcu);
12710 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {12553 if (!payload_ty.hasRuntimeBits(zcu)) {
12711 return false;12554 return false;
12712 }12555 }
12713 return true;12556 return true;
12714 },12557 },
12715 .optional => {12558 .optional => {
12716 const payload_ty = ty.optionalChild(zcu);12559 const payload_ty = ty.optionalChild(zcu);
12717 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {12560 if (!payload_ty.hasRuntimeBits(zcu)) {
12718 return false;12561 return false;
12719 }12562 }
12720 if (ty.optionalReprIsPayload(zcu)) {12563 if (ty.optionalReprIsPayload(zcu)) {
src/codegen/mips/abi.zig+1-1
...@@ -13,7 +13,7 @@ pub const Context = enum { ret, arg };...@@ -13,7 +13,7 @@ pub const Context = enum { ret, arg };
1313
14pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {14pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
15 const target = zcu.getTarget();15 const target = zcu.getTarget();
16 std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(zcu));16 std.debug.assert(ty.hasRuntimeBits(zcu));
1717
18 const max_direct_size = target.ptrBitWidth() * 2;18 const max_direct_size = target.ptrBitWidth() * 2;
19 switch (ty.zigTypeTag(zcu)) {19 switch (ty.zigTypeTag(zcu)) {
src/codegen/riscv64/abi.zig+2-2
...@@ -11,7 +11,7 @@ pub const Class = enum { memory, byval, integer, double_integer, fields };...@@ -11,7 +11,7 @@ pub const Class = enum { memory, byval, integer, double_integer, fields };
1111
12pub fn classifyType(ty: Type, zcu: *Zcu) Class {12pub fn classifyType(ty: Type, zcu: *Zcu) Class {
13 const target = zcu.getTarget();13 const target = zcu.getTarget();
14 std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(zcu));14 std.debug.assert(ty.hasRuntimeBits(zcu));
1515
16 const max_byval_size = target.ptrBitWidth() * 2;16 const max_byval_size = target.ptrBitWidth() * 2;
17 switch (ty.zigTypeTag(zcu)) {17 switch (ty.zigTypeTag(zcu)) {
...@@ -27,7 +27,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class {...@@ -27,7 +27,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class {
27 var field_count: usize = 0;27 var field_count: usize = 0;
28 for (0..ty.structFieldCount(zcu)) |field_index| {28 for (0..ty.structFieldCount(zcu)) |field_index| {
29 const field_ty = ty.fieldType(field_index, zcu);29 const field_ty = ty.fieldType(field_index, zcu);
30 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;30 if (!field_ty.hasRuntimeBits(zcu)) continue;
31 if (field_ty.isRuntimeFloat())31 if (field_ty.isRuntimeFloat())
32 any_fp = true32 any_fp = true
33 else if (!field_ty.isAbiInt(zcu))33 else if (!field_ty.isAbiInt(zcu))
src/codegen/wasm/abi.zig+3-3
...@@ -22,7 +22,7 @@ pub const Class = union(enum) {...@@ -22,7 +22,7 @@ pub const Class = union(enum) {
22/// or returned as value within a wasm function.22/// or returned as value within a wasm function.
23pub fn classifyType(ty: Type, zcu: *const Zcu) Class {23pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
24 const ip = &zcu.intern_pool;24 const ip = &zcu.intern_pool;
25 assert(ty.hasRuntimeBitsIgnoreComptime(zcu));25 assert(ty.hasRuntimeBits(zcu));
26 switch (ty.zigTypeTag(zcu)) {26 switch (ty.zigTypeTag(zcu)) {
27 .int, .@"enum", .error_set => return .{ .direct = ty },27 .int, .@"enum", .error_set => return .{ .direct = ty },
28 .float => return .{ .direct = ty },28 .float => return .{ .direct = ty },
...@@ -47,7 +47,7 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {...@@ -47,7 +47,7 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
47 return .indirect;47 return .indirect;
48 }48 }
49 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[0]);49 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[0]);
50 const explicit_align = struct_type.fieldAlign(ip, 0);50 const explicit_align = struct_type.field_aligns.getOrNone(ip, 0);
51 if (explicit_align != .none) {51 if (explicit_align != .none) {
52 if (explicit_align.compareStrict(.gt, field_ty.abiAlignment(zcu)))52 if (explicit_align.compareStrict(.gt, field_ty.abiAlignment(zcu)))
53 return .indirect;53 return .indirect;
...@@ -56,7 +56,7 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {...@@ -56,7 +56,7 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
56 },56 },
57 .@"union" => {57 .@"union" => {
58 const union_obj = zcu.typeToUnion(ty).?;58 const union_obj = zcu.typeToUnion(ty).?;
59 if (union_obj.flagsUnordered(ip).layout == .@"packed") {59 if (union_obj.layout == .@"packed") {
60 return .{ .direct = ty };60 return .{ .direct = ty };
61 }61 }
62 const layout = ty.unionGetLayout(zcu);62 const layout = ty.unionGetLayout(zcu);
src/link.zig+4-2
...@@ -29,6 +29,7 @@ const codegen = @import("codegen.zig");...@@ -29,6 +29,7 @@ const codegen = @import("codegen.zig");
29pub const aarch64 = @import("link/aarch64.zig");29pub const aarch64 = @import("link/aarch64.zig");
30pub const LdScript = @import("link/LdScript.zig");30pub const LdScript = @import("link/LdScript.zig");
31pub const Queue = @import("link/Queue.zig");31pub const Queue = @import("link/Queue.zig");
32pub const DebugConstPool = @import("link/DebugConstPool.zig");
3233
33pub const Diags = struct {34pub const Diags = struct {
34 /// Stored here so that function definitions can distinguish between35 /// 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...@@ -1587,8 +1588,9 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void
1587 const ty_prog_node = comp.link_prog_node.start(name, 0);1588 const ty_prog_node = comp.link_prog_node.start(name, 0);
1588 defer ty_prog_node.end();1589 defer ty_prog_node.end();
1589 if (zcu.llvm_object) |llvm_object| {1590 if (zcu.llvm_object) |llvm_object| {
1590 _ = llvm_object;1591 llvm_object.updateContainerType(pt, container_update.ty, container_update.success) catch |err| switch (err) {
1591 @compileError("MLUGG TODO");1592 error.OutOfMemory => diags.setAllocFailure(),
1593 };
1592 } else {1594 } else {
1593 if (comp.bin_file) |lf| {1595 if (comp.bin_file) |lf| {
1594 lf.updateContainerType(pt, container_update.ty, container_update.success) catch |err| switch (err) {1596 lf.updateContainerType(pt, container_update.ty, container_update.success) catch |err| switch (err) {
src/link/DebugConstPool.zig+3
...@@ -13,6 +13,9 @@...@@ -13,6 +13,9 @@
13/// * forward `updateContainerType` calls to its `DebugConstPool`13/// * forward `updateContainerType` calls to its `DebugConstPool`
14/// * expose some callback functions---see functions in `DebugInfo`14/// * expose some callback functions---see functions in `DebugInfo`
15/// * ensure that any `get` call is eventually followed by a `flushPending` call15/// * ensure that any `get` call is eventually followed by a `flushPending` call
16///
17/// TODO: everything in this file should have the error set 'Allocator.Error', but right now the
18/// self-hosted linkers can return all kinds of crap for some reason. This needs fixing.
16const DebugConstPool = @This();19const DebugConstPool = @This();
1720
18values: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),21values: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
src/link/Dwarf.zig+1-1
...@@ -18,7 +18,7 @@ const codegen = @import("../codegen.zig");...@@ -18,7 +18,7 @@ const codegen = @import("../codegen.zig");
18const dev = @import("../dev.zig");18const dev = @import("../dev.zig");
19const link = @import("../link.zig");19const link = @import("../link.zig");
20const target_info = @import("../target.zig");20const target_info = @import("../target.zig");
21const DebugConstPool = @import("DebugConstPool.zig");21const DebugConstPool = link.DebugConstPool;
2222
23gpa: Allocator,23gpa: Allocator,
24bin_file: *link.File,24bin_file: *link.File,