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 {
3434
3535 const default: Info = .{
3636 .block_name = &.{},
37 .record_names = .{},
38 .abbrevs = .{ .abbrevs = .{} },
37 .record_names = .empty,
38 .abbrevs = .{ .abbrevs = .empty },
3939 };
4040
4141 const set_bid_id: u32 = 1;
......@@ -109,8 +109,8 @@ pub fn init(allocator: std.mem.Allocator, options: InitOptions) BitcodeReader {
109109 .keep_names = options.keep_names,
110110 .bit_buffer = 0,
111111 .bit_offset = 0,
112 .stack = .{},
113 .block_info = .{},
112 .stack = .empty,
113 .block_info = .empty,
114114 };
115115}
116116
......@@ -278,7 +278,7 @@ fn startBlock(bc: *BitcodeReader, block_id: ?u32, new_abbrev_len: u6) !void {
278278 state.* = .{
279279 .block_id = block_id,
280280 .abbrev_id_width = new_abbrev_len,
281 .abbrevs = .{ .abbrevs = .{} },
281 .abbrevs = .{ .abbrevs = .empty },
282282 };
283283 try state.abbrevs.abbrevs.ensureTotalCapacity(
284284 bc.allocator,
lib/std/zig/llvm/Builder.zig+54-53
......@@ -1627,7 +1627,7 @@ pub const FunctionAttributes = enum(u32) {
16271627 const params_index = 2;
16281628
16291629 pub const Wip = struct {
1630 maps: Maps = .{},
1630 maps: Maps = .empty,
16311631
16321632 const Map = std.AutoArrayHashMapUnmanaged(Attribute.Kind, Attribute.Index);
16331633 const Maps = std.ArrayList(Map);
......@@ -4048,7 +4048,7 @@ pub const Function = struct {
40484048 section: String = .none,
40494049 alignment: Alignment = .default,
40504050 blocks: []const Block = &.{},
4051 instructions: std.MultiArrayList(Instruction) = .{},
4051 instructions: std.MultiArrayList(Instruction) = .empty,
40524052 names: [*]const String = &[0]String{},
40534053 value_indices: [*]const u32 = &[0]u32{},
40544054 strip: bool,
......@@ -5222,13 +5222,13 @@ pub const WipFunction = struct {
52225222 .prev_debug_location = .no_location,
52235223 .debug_location = .no_location,
52245224 .cursor = undefined,
5225 .blocks = .{},
5226 .instructions = .{},
5227 .names = .{},
5225 .blocks = .empty,
5226 .instructions = .empty,
5227 .names = .empty,
52285228 .strip = options.strip,
5229 .debug_locations = .{},
5230 .debug_values = .{},
5231 .extra = .{},
5229 .debug_locations = .empty,
5230 .debug_values = .empty,
5231 .extra = .empty,
52325232 };
52335233 errdefer self.deinit();
52345234
......@@ -5265,7 +5265,7 @@ pub const WipFunction = struct {
52655265 self.blocks.appendAssumeCapacity(.{
52665266 .name = final_name,
52675267 .incoming = incoming,
5268 .instructions = .{},
5268 .instructions = .empty,
52695269 });
52705270 return index;
52715271 }
......@@ -6325,7 +6325,7 @@ pub const WipFunction = struct {
63256325 function.blocks = &.{};
63266326 gpa.free(function.names[0..function.instructions.len]);
63276327 function.debug_locations.deinit(gpa);
6328 function.debug_locations = .{};
6328 function.debug_locations = .empty;
63296329 gpa.free(function.debug_values);
63306330 function.debug_values = &.{};
63316331 gpa.free(function.extra);
......@@ -8391,7 +8391,7 @@ pub const Metadata = packed struct(u32) {
83918391 map: std.AutoArrayHashMapUnmanaged(union(enum) {
83928392 metadata: Metadata,
83938393 debug_location: DebugLocation.Location,
8394 }, void) = .{},
8394 }, void) = .empty,
83958395
83968396 const FormatData = struct {
83978397 formatter: *Formatter,
......@@ -8649,52 +8649,52 @@ pub fn init(options: Options) Allocator.Error!Builder {
86498649 .source_filename = .none,
86508650 .data_layout = .none,
86518651 .target_triple = .none,
8652 .module_asm = .{},
8652 .module_asm = .empty,
86538653
8654 .string_map = .{},
8655 .string_indices = .{},
8656 .string_bytes = .{},
8654 .string_map = .empty,
8655 .string_indices = .empty,
8656 .string_bytes = .empty,
86578657
8658 .types = .{},
8658 .types = .empty,
86598659 .next_unnamed_type = @enumFromInt(0),
8660 .next_unique_type_id = .{},
8661 .type_map = .{},
8662 .type_items = .{},
8663 .type_extra = .{},
8660 .next_unique_type_id = .empty,
8661 .type_map = .empty,
8662 .type_items = .empty,
8663 .type_extra = .empty,
86648664
8665 .attributes = .{},
8666 .attributes_map = .{},
8667 .attributes_indices = .{},
8668 .attributes_extra = .{},
8665 .attributes = .empty,
8666 .attributes_map = .empty,
8667 .attributes_indices = .empty,
8668 .attributes_extra = .empty,
86698669
8670 .function_attributes_set = .{},
8670 .function_attributes_set = .empty,
86718671
8672 .globals = .{},
8672 .globals = .empty,
86738673 .next_unnamed_global = @enumFromInt(0),
86748674 .next_replaced_global = .none,
8675 .next_unique_global_id = .{},
8676 .aliases = .{},
8677 .variables = .{},
8678 .functions = .{},
8679
8680 .strtab_string_map = .{},
8681 .strtab_string_indices = .{},
8682 .strtab_string_bytes = .{},
8683
8684 .constant_map = .{},
8685 .constant_items = .{},
8686 .constant_extra = .{},
8687 .constant_limbs = .{},
8688
8689 .metadata_map = .{},
8690 .metadata_items = .{},
8691 .metadata_extra = .{},
8692 .metadata_limbs = .{},
8693 .metadata_forward_references = .{},
8694 .metadata_named = .{},
8695 .metadata_string_map = .{},
8696 .metadata_string_indices = .{},
8697 .metadata_string_bytes = .{},
8675 .next_unique_global_id = .empty,
8676 .aliases = .empty,
8677 .variables = .empty,
8678 .functions = .empty,
8679
8680 .strtab_string_map = .empty,
8681 .strtab_string_indices = .empty,
8682 .strtab_string_bytes = .empty,
8683
8684 .constant_map = .empty,
8685 .constant_items = .empty,
8686 .constant_extra = .empty,
8687 .constant_limbs = .empty,
8688
8689 .metadata_map = .empty,
8690 .metadata_items = .empty,
8691 .metadata_extra = .empty,
8692 .metadata_limbs = .empty,
8693 .metadata_forward_references = .empty,
8694 .metadata_named = .empty,
8695 .metadata_string_map = .empty,
8696 .metadata_string_indices = .empty,
8697 .metadata_string_bytes = .empty,
86988698 };
86998699 errdefer self.deinit();
87008700
......@@ -12069,7 +12069,7 @@ pub fn trailingMetadataStringAssumeCapacity(self: *Builder) Metadata.String {
1206912069 const start = self.metadata_string_indices.getLast();
1207012070 const bytes: []const u8 = self.metadata_string_bytes.items[start..];
1207112071 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 });
1207312073 if (gop.found_existing) {
1207412074 self.metadata_string_bytes.shrinkRetainingCapacity(start);
1207512075 } else {
......@@ -12467,11 +12467,12 @@ pub fn metadataConstant(self: *Builder, value: Constant) Allocator.Error!Metadat
1246712467 return self.metadataConstantAssumeCapacity(value);
1246812468}
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.
1247012472pub fn resolveDebugForwardReference(self: *Builder, fwd_ref: Metadata, value: Metadata) void {
1247112473 assert(fwd_ref.kind == .forward);
12472 const resolved = &self.metadata_forward_references.items[fwd_ref.index];
12473 assert(resolved.is_none);
12474 resolved.* = value.toOptional();
12474 assert(value.kind != .forward);
12475 self.metadata_forward_references.items[fwd_ref.index] = value.toOptional();
1247512476}
1247612477
1247712478fn metadataSimpleAssumeCapacity(self: *Builder, tag: Metadata.Tag, value: anytype) Metadata {
src/Sema.zig+28-1
......@@ -7096,7 +7096,13 @@ fn analyzeCall(
70967096 }
70977097 }
70987098 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 }
71007106 }
71017107 const runtime_func: Air.Inst.Ref, const runtime_args: []const Air.Inst.Ref = func: {
71027108 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
2427024276
2427124277 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
2427324286 const runtime_src = rs: {
2427424287 const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls), dest_src);
2427524288 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
2429924312 return sema.storePtrVal(block, src, array_ptr_val, array_val, array_ty);
2430024313 };
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
2430224324 try sema.requireRuntimeBlock(block, src, runtime_src);
2430324325 try sema.validateRuntimeValue(block, dest_src, dest_ptr);
2430424326 try sema.validateRuntimeValue(block, value_src, elem);
......@@ -27063,6 +27085,11 @@ fn elemPtrArray(
2706327085 try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op);
2706427086 }
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
2706627093 return block.addPtrElemPtr(array_ptr, elem_index, elem_ptr_ty);
2706727094}
2706827095
src/Zcu/PerThread.zig+7-1
......@@ -2926,7 +2926,13 @@ fn analyzeFuncBodyInner(
29262926 const param_ty: Type = .fromInterned(fn_ty_info.param_types.get(ip)[runtime_param_index]);
29272927 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 }
29302936 if (try param_ty.onePossibleValue(pt)) |opv| {
29312937 gop.value_ptr.* = .fromValue(opv);
29322938 continue;
src/codegen/aarch64/abi.zig+1-1
......@@ -13,7 +13,7 @@ pub const Class = union(enum) {
1313
1414/// For `float_array` the second element will be the amount of floats.
1515pub fn classifyType(ty: Type, zcu: *Zcu) Class {
16 assert(ty.hasRuntimeBitsIgnoreComptime(zcu));
16 assert(ty.hasRuntimeBits(zcu));
1717
1818 var maybe_float_bits: ?u16 = null;
1919 switch (ty.zigTypeTag(zcu)) {
src/codegen/arm/abi.zig+13-11
......@@ -23,7 +23,7 @@ pub const Class = union(enum) {
2323pub const Context = enum { ret, arg };
2424
2525pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
26 assert(ty.hasRuntimeBitsIgnoreComptime(zcu));
26 assert(ty.hasRuntimeBits(zcu));
2727
2828 var maybe_float_bits: ?u16 = null;
2929 const max_byval_size = 512;
......@@ -39,22 +39,22 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
3939 const float_count = countFloats(ty, zcu, &maybe_float_bits);
4040 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
4246 const fields = ty.structFieldCount(zcu);
4347 var i: u32 = 0;
4448 while (i < fields) : (i += 1) {
4549 const field_ty = ty.fieldType(i, zcu);
46 const field_alignment = ty.fieldAlignment(i, zcu);
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 }
50 if (field_ty.bitSize(zcu) > 32) return Class.arrSize(bit_size, 64);
5151 }
5252 return Class.arrSize(bit_size, 32);
5353 },
5454 .@"union" => {
5555 const bit_size = ty.bitSize(zcu);
5656 const union_obj = zcu.typeToUnion(ty).?;
57 if (union_obj.flagsUnordered(ip).layout == .@"packed") {
57 if (union_obj.layout == .@"packed") {
5858 if (bit_size > 64) return .memory;
5959 return .byval;
6060 }
......@@ -62,10 +62,12 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
6262 const float_count = countFloats(ty, zcu, &maybe_float_bits);
6363 if (float_count <= byval_float_count) return .byval;
6464
65 for (union_obj.field_types.get(ip), 0..) |field_ty, field_index| {
66 if (Type.fromInterned(field_ty).bitSize(zcu) > 32 or
67 ty.fieldAlignment(field_index, zcu).compare(.gt, .@"32"))
68 {
65 if (union_obj.alignment.compareStrict(.gt, .@"32")) {
66 return Class.arrSize(bit_size, 64);
67 }
68
69 for (union_obj.field_types.get(ip)) |field_ty| {
70 if (Type.fromInterned(field_ty).bitSize(zcu) > 32) {
6971 return Class.arrSize(bit_size, 64);
7072 }
7173 }
src/codegen/llvm.zig+729-886
......@@ -23,6 +23,7 @@ const Package = @import("../Package.zig");
2323const Air = @import("../Air.zig");
2424const Value = @import("../Value.zig");
2525const Type = @import("../Type.zig");
26const DebugConstPool = link.DebugConstPool;
2627const codegen = @import("../codegen.zig");
2728const x86_64_abi = @import("x86_64/abi.zig");
2829const wasm_c_abi = @import("wasm/abi.zig");
......@@ -529,9 +530,15 @@ pub const Object = struct {
529530 debug_globals: std.ArrayList(Builder.Metadata),
530531
531532 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
536543 target: *const std.Target,
537544 /// Ideally we would use `llvm_module.getNamedFunction` to go from *Decl to LLVM function,
......@@ -657,21 +664,22 @@ pub const Object = struct {
657664 .debug_compile_unit = debug_compile_unit,
658665 .debug_enums_fwd_ref = debug_enums_fwd_ref,
659666 .debug_globals_fwd_ref = debug_globals_fwd_ref,
660 .debug_enums = .{},
661 .debug_globals = .{},
662 .debug_file_map = .{},
663 .debug_type_map = .{},
664 .debug_unresolved_namespace_scopes = .{},
667 .debug_enums = .empty,
668 .debug_globals = .empty,
669 .debug_file_map = .empty,
670 .debug_type_pool = .empty,
671 .debug_types = .empty,
672 .debug_anyerror_fwd_ref = .none,
665673 .target = target,
666 .nav_map = .{},
667 .uav_map = .{},
668 .enum_tag_name_map = .{},
669 .named_enum_map = .{},
670 .type_map = .{},
674 .nav_map = .empty,
675 .uav_map = .empty,
676 .enum_tag_name_map = .empty,
677 .named_enum_map = .empty,
678 .type_map = .empty,
671679 .error_name_table = .none,
672680 .null_opt_usize = .no_init,
673 .struct_field_map = .{},
674 .used = .{},
681 .struct_field_map = .empty,
682 .used = .empty,
675683 };
676684 return obj;
677685 }
......@@ -681,8 +689,8 @@ pub const Object = struct {
681689 self.debug_enums.deinit(gpa);
682690 self.debug_globals.deinit(gpa);
683691 self.debug_file_map.deinit(gpa);
684 self.debug_type_map.deinit(gpa);
685 self.debug_unresolved_namespace_scopes.deinit(gpa);
692 self.debug_type_pool.deinit(gpa);
693 self.debug_types.deinit(gpa);
686694 self.nav_map.deinit(gpa);
687695 self.uav_map.deinit(gpa);
688696 self.enum_tag_name_map.deinit(gpa);
......@@ -824,19 +832,13 @@ pub const Object = struct {
824832 }
825833
826834 if (!o.builder.strip) {
827 {
828 var i: usize = 0;
829 while (i < o.debug_unresolved_namespace_scopes.count()) : (i += 1) {
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 }
835 if (o.debug_anyerror_fwd_ref.unwrap()) |fwd_ref| {
836 const debug_anyerror_type = try o.lowerDebugAnyerrorType(pt);
837 o.builder.resolveDebugForwardReference(fwd_ref, debug_anyerror_type);
838838 }
839839
840 try o.flushPendingDebugTypes(pt);
841
840842 o.builder.resolveDebugForwardReference(
841843 o.debug_enums_fwd_ref.unwrap().?,
842844 try o.builder.metadataTuple(o.debug_enums.items),
......@@ -1472,7 +1474,7 @@ pub const Object = struct {
14721474
14731475 const line_number = zcu.navSrcLine(func.owner_nav) + 1;
14741476 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
14771479 const subprogram = try o.builder.debugSubprogram(
14781480 file,
......@@ -1522,7 +1524,7 @@ pub const Object = struct {
15221524
15231525 break :f .{
15241526 .counters_variable = counters_variable,
1525 .pcs = .{},
1527 .pcs = .empty,
15261528 };
15271529 };
15281530
......@@ -1538,10 +1540,10 @@ pub const Object = struct {
15381540 .args = args.items,
15391541 .arg_index = 0,
15401542 .arg_inline_index = 0,
1541 .func_inst_table = .{},
1542 .blocks = .{},
1543 .loops = .{},
1544 .switch_dispatch_info = .{},
1543 .func_inst_table = .empty,
1544 .blocks = .empty,
1545 .loops = .empty,
1546 .switch_dispatch_info = .empty,
15451547 .sync_scope = if (owner_mod.single_threaded) .singlethread else .system,
15461548 .file = file,
15471549 .scope = subprogram,
......@@ -1599,6 +1601,7 @@ pub const Object = struct {
15991601 }
16001602
16011603 try fg.wip.finish();
1604 try o.flushPendingDebugTypes(pt);
16021605 }
16031606
16041607 pub fn updateNav(self: *Object, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void {
......@@ -1615,6 +1618,14 @@ pub const Object = struct {
16151618 },
16161619 else => |e| return e,
16171620 };
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 };
16181629 }
16191630
16201631 pub fn updateExports(
......@@ -1810,6 +1821,57 @@ pub const Object = struct {
18101821 }
18111822 }
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
18131875 fn getDebugFile(o: *Object, pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator.Error!Builder.Metadata {
18141876 const gpa = o.gpa;
18151877 const gop = try o.debug_file_map.getOrPut(gpa, file_index);
......@@ -1826,10 +1888,22 @@ pub const Object = struct {
18261888 return gop.value_ptr.*;
18271889 }
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(
18301903 o: *Object,
18311904 pt: Zcu.PerThread,
18321905 ty: Type,
1906 ty_fwd_ref: Builder.Metadata,
18331907 ) Allocator.Error!Builder.Metadata {
18341908 assert(!o.builder.strip);
18351909
......@@ -1838,267 +1912,96 @@ pub const Object = struct {
18381912 const zcu = pt.zcu;
18391913 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
18431917 switch (ty.zigTypeTag(zcu)) {
18441918 .void,
18451919 .noreturn,
1846 => {
1847 const debug_void_type = try o.builder.debugSignedType(
1848 try o.builder.metadataString("void"),
1849 0,
1850 );
1851 try o.debug_type_map.put(gpa, ty.toIntern(), debug_void_type);
1852 return debug_void_type;
1853 },
1920 .comptime_int,
1921 .comptime_float,
1922 .type,
1923 .undefined,
1924 .null,
1925 .enum_literal,
1926 => return o.builder.debugSignedType(name, 0),
1927
18541928 .int => {
18551929 const info = ty.intInfo(zcu);
1856 assert(info.bits != 0);
1857 const name = try o.allocTypeName(pt, ty);
1858 defer gpa.free(name);
1859 const builder_name = try o.builder.metadataString(name);
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),
1930 const bits = ty.abiSize(zcu) * 8; // lldb cannot handle non-byte sized types
1931 return switch (info.signedness) {
1932 .signed => try o.builder.debugSignedType(name, bits),
1933 .unsigned => try o.builder.debugUnsignedType(name, bits),
18641934 };
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;
19211935 },
19221936 .float => {
1923 const bits = 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;
1937 return o.builder.debugFloatType(name, ty.floatBits(target));
19321938 },
19331939 .bool => {
1934 const debug_bool_type = try o.builder.debugBoolType(
1935 try o.builder.metadataString("bool"),
1940 return o.builder.debugBoolType(
1941 name,
19361942 8, // lldb cannot handle non-byte sized types
19371943 );
1938 try o.debug_type_map.put(gpa, ty.toIntern(), debug_bool_type);
1939 return debug_bool_type;
19401944 },
19411945 .pointer => {
1942 // Normalize everything that the debug info does not represent.
1943 const ptr_info = ty.ptrInfo(zcu);
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);
1946 const ptr_size = Type.ptrAbiSize(zcu.getTarget());
1947 const ptr_align = Type.ptrAbiAlignment(zcu.getTarget());
19781948
19791949 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
19941950 const debug_ptr_type = try o.builder.debugMemberType(
19951951 try o.builder.metadataString("ptr"),
19961952 null, // File
1997 debug_fwd_ref,
1953 ty_fwd_ref,
19981954 0, // Line
1999 try o.lowerDebugType(pt, ptr_ty),
1955 try o.getDebugType(pt, ty.slicePtrFieldType(zcu)),
20001956 ptr_size * 8,
2001 (ptr_align.toByteUnits() orelse 0) * 8,
1957 ptr_align.toByteUnits().? * 8,
20021958 0, // Offset
20031959 );
20041960
20051961 const debug_len_type = try o.builder.debugMemberType(
20061962 try o.builder.metadataString("len"),
20071963 null, // File
2008 debug_fwd_ref,
1964 ty_fwd_ref,
20091965 0, // Line
2010 try o.lowerDebugType(pt, len_ty),
2011 len_size * 8,
2012 (len_align.toByteUnits() orelse 0) * 8,
2013 len_offset * 8,
1966 try o.getDebugType(pt, .usize),
1967 ptr_size * 8,
1968 ptr_align.toByteUnits().? * 8,
1969 ptr_size * 8,
20141970 );
20151971
2016 const debug_slice_type = try o.builder.debugStructType(
2017 try o.builder.metadataString(name),
1972 return o.builder.debugStructType(
1973 name,
20181974 null, // File
20191975 o.debug_compile_unit.unwrap().?, // Scope
2020 line,
1976 0, // Line
20211977 null, // Underlying type
2022 ty.abiSize(zcu) * 8,
2023 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,
1978 ptr_size * 2 * 8,
1979 ptr_align.toByteUnits().? * 8,
20241980 try o.builder.metadataTuple(&.{
20251981 debug_ptr_type,
20261982 debug_len_type,
20271983 }),
20281984 );
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;
20371985 }
20381986
2039 const debug_elem_ty = try o.lowerDebugType(pt, Type.fromInterned(ptr_info.child));
2040
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),
1987 return o.builder.debugPointerType(
1988 name,
20461989 null, // File
20471990 null, // Scope
20481991 0, // Line
2049 debug_elem_ty,
2050 target.ptrBitWidth(),
2051 (ty.ptrAlignment(zcu).toByteUnits() orelse 0) * 8,
1992 try o.getDebugType(pt, ty.childType(zcu)),
1993 ptr_size * 8,
1994 ptr_align.toByteUnits().? * 8,
20521995 0, // Offset
20531996 );
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;
20941997 },
20951998 .array => {
2096 const debug_array_type = try o.builder.debugArrayType(
1999 return o.builder.debugArrayType(
20972000 null, // Name
20982001 null, // File
20992002 null, // Scope
21002003 0, // Line
2101 try o.lowerDebugType(pt, ty.childType(zcu)),
2004 try o.getDebugType(pt, ty.childType(zcu)),
21022005 ty.abiSize(zcu) * 8,
21032006 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,
21042007 try o.builder.metadataTuple(&.{
......@@ -2108,8 +2011,6 @@ pub const Object = struct {
21082011 ),
21092012 }),
21102013 );
2111 try o.debug_type_map.put(gpa, ty.toIntern(), debug_array_type);
2112 return debug_array_type;
21132014 },
21142015 .vector => {
21152016 const elem_ty = ty.childType(zcu);
......@@ -2120,23 +2021,17 @@ pub const Object = struct {
21202021 const debug_elem_type = switch (elem_ty.zigTypeTag(zcu)) {
21212022 .int => blk: {
21222023 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);
21272024 break :blk switch (info.signedness) {
2128 .signed => try o.builder.debugSignedType(builder_name, info.bits),
2129 .unsigned => try o.builder.debugUnsignedType(builder_name, info.bits),
2025 .signed => try o.builder.debugSignedType(name, info.bits),
2026 .unsigned => try o.builder.debugUnsignedType(name, info.bits),
21302027 };
21312028 },
2132 .bool => try o.builder.debugBoolType(
2133 try o.builder.metadataString("bool"),
2134 1,
2135 ),
2136 else => try o.lowerDebugType(pt, ty.childType(zcu)),
2029 .bool => try o.builder.debugBoolType(try o.builder.metadataString("bool"), 1),
2030 .pointer, .optional, .float => try o.getDebugType(pt, elem_ty),
2031 else => unreachable,
21372032 };
21382033
2139 const debug_vector_type = try o.builder.debugVectorType(
2034 return o.builder.debugVectorType(
21402035 null, // Name
21412036 null, // File
21422037 null, // Scope
......@@ -2151,71 +2046,64 @@ pub const Object = struct {
21512046 ),
21522047 }),
21532048 );
2154
2155 try o.debug_type_map.put(gpa, ty.toIntern(), debug_vector_type);
2156 return debug_vector_type;
21572049 },
21582050 .optional => {
2159 const name = try o.allocTypeName(pt, ty);
2160 defer gpa.free(name);
2161 const child_ty = ty.optionalChild(zcu);
2162 if (!child_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
2163 const debug_bool_type = try o.builder.debugBoolType(
2164 try o.builder.metadataString(name),
2165 8,
2051 const payload_ty = ty.optionalChild(zcu);
2052 if (ty.optionalReprIsPayload(zcu)) {
2053 // MLUGG TODO: these should use DW_TAG_typedef instead, but std.zig.llvm.Builder currently lacks support for those.
2054 const payload_member = try o.builder.debugMemberType(
2055 try o.builder.metadataString("payload"),
2056 null, // file
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}),
21662073 );
2167 try o.debug_type_map.put(gpa, ty.toIntern(), debug_bool_type);
2168 return debug_bool_type;
21692074 }
21702075
2171 const debug_fwd_ref = try o.builder.debugForwardReference();
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 }
2076 const payload_size = payload_ty.abiSize(zcu);
21872077
21882078 const non_null_ty = Type.u8;
2189 const payload_size = child_ty.abiSize(zcu);
2190 const payload_align = child_ty.abiAlignment(zcu);
21912079 const non_null_size = non_null_ty.abiSize(zcu);
21922080 const non_null_align = non_null_ty.abiAlignment(zcu);
21932081 const non_null_offset = non_null_align.forward(payload_size);
21942082
2195 const debug_data_type = try o.builder.debugMemberType(
2196 try o.builder.metadataString("data"),
2197 null, // File
2198 debug_fwd_ref,
2199 0, // Line
2200 try o.lowerDebugType(pt, child_ty),
2083 const debug_payload_type = try o.builder.debugMemberType(
2084 try o.builder.metadataString("payload"),
2085 null, // file
2086 ty_fwd_ref,
2087 0, // line
2088 try o.getDebugType(pt, payload_ty),
22012089 payload_size * 8,
2202 (payload_align.toByteUnits() orelse 0) * 8,
2203 0, // Offset
2090 payload_ty.abiAlignment(zcu).toByteUnits().? * 8,
2091 0, // offset
22042092 );
22052093
22062094 const debug_some_type = try o.builder.debugMemberType(
22072095 try o.builder.metadataString("some"),
22082096 null,
2209 debug_fwd_ref,
2097 ty_fwd_ref,
22102098 0,
2211 try o.lowerDebugType(pt, non_null_ty),
2099 try o.getDebugType(pt, non_null_ty),
22122100 non_null_size * 8,
2213 (non_null_align.toByteUnits() orelse 0) * 8,
2101 non_null_align.toByteUnits().? * 8,
22142102 non_null_offset * 8,
22152103 );
22162104
2217 const debug_optional_type = try o.builder.debugStructType(
2218 try o.builder.metadataString(name),
2105 return o.builder.debugStructType(
2106 name,
22192107 null, // File
22202108 o.debug_compile_unit.unwrap().?, // Scope
22212109 0, // Line
......@@ -2223,494 +2111,498 @@ pub const Object = struct {
22232111 ty.abiSize(zcu) * 8,
22242112 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,
22252113 try o.builder.metadataTuple(&.{
2226 debug_data_type,
2114 debug_payload_type,
22272115 debug_some_type,
22282116 }),
22292117 );
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;
22382118 },
22392119 .error_union => {
2120 const error_ty = ty.errorUnionSet(zcu);
22402121 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);
2252 const error_align = Type.anyerror.abiAlignment(zcu);
2123 const error_size = error_ty.abiSize(zcu);
2124 const error_align = error_ty.abiAlignment(zcu);
22532125 const payload_size = payload_ty.abiSize(zcu);
22542126 const payload_align = payload_ty.abiAlignment(zcu);
22552127
2256 var error_index: u32 = undefined;
2257 var payload_index: u32 = undefined;
2258 var error_offset: u64 = undefined;
2259 var payload_offset: u64 = undefined;
2260 if (error_align.compare(.gt, payload_align)) {
2261 error_index = 0;
2262 payload_index = 1;
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();
2128 const error_index: u1, const payload_index: u1, const error_offset: u64, const payload_offset: u64 = fields: {
2129 if (error_align.compare(.gt, payload_align)) {
2130 break :fields .{ 0, 1, 0, payload_align.forward(error_size) };
2131 } else {
2132 break :fields .{ 1, 0, error_align.forward(payload_size), 0 };
2133 }
2134 };
22732135
22742136 var fields: [2]Builder.Metadata = undefined;
22752137 fields[error_index] = try o.builder.debugMemberType(
2276 try o.builder.metadataString("tag"),
2138 try o.builder.metadataString("error"),
22772139 null, // File
2278 debug_fwd_ref,
2140 ty_fwd_ref,
22792141 0, // Line
2280 try o.lowerDebugType(pt, Type.anyerror),
2142 try o.getDebugType(pt, error_ty),
22812143 error_size * 8,
2282 (error_align.toByteUnits() orelse 0) * 8,
2144 error_align.toByteUnits().? * 8,
22832145 error_offset * 8,
22842146 );
22852147 fields[payload_index] = try o.builder.debugMemberType(
2286 try o.builder.metadataString("value"),
2148 try o.builder.metadataString("payload"),
22872149 null, // File
2288 debug_fwd_ref,
2150 ty_fwd_ref,
22892151 0, // Line
2290 try o.lowerDebugType(pt, payload_ty),
2152 try o.getDebugType(pt, payload_ty),
22912153 payload_size * 8,
2292 (payload_align.toByteUnits() orelse 0) * 8,
2154 payload_align.toByteUnits().? * 8,
22932155 payload_offset * 8,
22942156 );
22952157
2296 const debug_error_union_type = try o.builder.debugStructType(
2297 try o.builder.metadataString(name),
2158 return try o.builder.debugStructType(
2159 name,
22982160 null, // File
2299 o.debug_compile_unit.unwrap().?, // Sope
2161 o.debug_compile_unit.unwrap().?, // Scope
23002162 0, // Line
23012163 null, // Underlying type
23022164 ty.abiSize(zcu) * 8,
2303 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,
2165 ty.abiAlignment(zcu).toByteUnits().? * 8,
23042166 try o.builder.metadataTuple(&fields),
23052167 );
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;
23112168 },
23122169 .error_set => {
2313 const debug_error_set = try o.builder.debugUnsignedType(
2314 try o.builder.metadataString("anyerror"),
2315 16,
2170 assert(ty.toIntern() != .anyerror_type); // handled specially in `updateConst`; will be populated by `emit` instead
2171 // Error sets are just named wrappers around `anyerror`.
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}),
23162192 );
2317 try o.debug_type_map.put(gpa, ty.toIntern(), debug_error_set);
2318 return debug_error_set;
23192193 },
2320 .@"struct" => {
2321 const name = try o.allocTypeName(pt, ty);
2322 defer gpa.free(name);
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 }
2194 .@"fn" => {
2195 if (!ty.fnHasRuntimeBits(zcu)) {
2196 return o.builder.debugSignedType(name, 0);
23362197 }
23372198
2338 switch (ip.indexToKey(ty.toIntern())) {
2339 .tuple_type => |tuple| {
2340 var fields: std.ArrayList(Builder.Metadata) = .empty;
2341 defer fields.deinit(gpa);
2199 const fn_info = zcu.typeToFunc(ty).?;
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);
2346 var offset: u64 = 0;
2204 // Return type goes first.
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| {
2351 if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue;
2214 if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) {
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);
2354 const field_align = Type.fromInterned(field_ty).abiAlignment(zcu);
2355 const field_offset = field_align.forward(offset);
2356 offset = field_offset + field_size;
2219 for (fn_info.param_types.get(ip)) |param_ty_ip| {
2220 const param_ty: Type = .fromInterned(param_ty_ip);
2221 if (!param_ty.hasRuntimeBits(zcu)) continue;
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;
2359 const field_name = std.fmt.bufPrint(&name_buf, "{d}", .{i}) catch unreachable;
2230 return o.builder.debugSubroutineType(
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(
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 }
2240 try fields.ensureUnusedCapacity(gpa, tuple.types.len);
23722241
2373 const debug_struct_type = try o.builder.debugStructType(
2374 try o.builder.metadataString(name),
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);
2242 comptime assert(struct_layout_version == 2);
2243 var offset: u64 = 0;
23852244
2386 try o.debug_type_map.put(gpa, ty.toIntern(), debug_struct_type);
2387 return debug_struct_type;
2388 },
2389 .struct_type => {
2390 if (!ip.loadStructType(ty.toIntern()).haveFieldTypes(ip)) {
2391 // This can happen if a struct type makes it all the way to
2392 // flush() without ever being instantiated or referenced (even
2393 // via pointer). The only reason we are hearing about it now is
2394 // that it is being used as a namespace to put other debug types
2395 // into. Therefore we can satisfy this by making an empty namespace,
2396 // rather than changing the frontend to unnecessarily resolve the
2397 // struct field types.
2398 const debug_struct_type = try o.makeEmptyNamespaceDebugType(pt, ty);
2399 try o.debug_type_map.put(gpa, ty.toIntern(), debug_struct_type);
2400 return debug_struct_type;
2401 }
2402 },
2403 else => {},
2404 }
2245 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty_ip, field_val, i| {
2246 const field_ty: Type = .fromInterned(field_ty_ip);
2247 if (field_val != .none or !field_ty.hasRuntimeBits(zcu)) continue;
2248
2249 const field_size = field_ty.abiSize(zcu);
2250 const field_align = field_ty.abiAlignment(zcu);
2251 const field_offset = field_align.forward(offset);
2252 offset = field_offset + field_size;
2253
2254 fields.appendAssumeCapacity(try o.builder.debugMemberType(
2255 try o.builder.metadataStringFmt("{d}", .{i}),
2256 null, // file
2257 ty_fwd_ref,
2258 0, // line
2259 try o.getDebugType(pt, field_ty),
2260 field_size * 8,
2261 field_align.toByteUnits().? * 8,
2262 field_offset * 8,
2263 ));
2264 }
24052265
2406 if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) {
2407 const debug_struct_type = try o.makeEmptyNamespaceDebugType(pt, ty);
2408 try o.debug_type_map.put(gpa, ty.toIntern(), debug_struct_type);
2409 return debug_struct_type;
2266 return o.builder.debugStructType(
2267 name,
2268 null, // file
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 );
24102276 }
24112277
24122278 const struct_type = zcu.typeToStruct(ty).?;
24132279
2414 var fields: std.ArrayList(Builder.Metadata) = .empty;
2415 defer fields.deinit(gpa);
2416
2417 try fields.ensureUnusedCapacity(gpa, struct_type.field_types.len);
2280 const file = try o.getDebugFile(pt, struct_type.zir_index.resolveFile(ip));
2281 const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace|
2282 try o.namespaceToDebugScope(pt, parent_namespace)
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 itself
2422 try o.debug_type_map.put(gpa, ty.toIntern(), debug_fwd_ref);
2288 var fields: std.ArrayList(Builder.Metadata) = .empty;
2289 defer fields.deinit(gpa);
24232290
2424 comptime assert(struct_layout_version == 2);
2425 var it = struct_type.iterateRuntimeOrder(ip);
2426 while (it.next()) |field_index| {
2427 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);
2428 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
2429 const field_size = field_ty.abiSize(zcu);
2430 const field_align = ty.fieldAlignment(field_index, zcu);
2431 const field_offset = ty.structFieldOffset(field_index, zcu);
2432 const field_name = struct_type.fieldName(ip, field_index);
2433 fields.appendAssumeCapacity(try o.builder.debugMemberType(
2434 try o.builder.metadataString(field_name.toSlice(ip)),
2435 null, // File
2436 debug_fwd_ref,
2437 0, // Line
2438 try o.lowerDebugType(pt, field_ty),
2439 field_size * 8,
2440 (field_align.toByteUnits() orelse 0) * 8,
2441 field_offset * 8,
2442 ));
2291 switch (struct_type.layout) {
2292 .@"packed" => {
2293 try fields.ensureTotalCapacityPrecise(gpa, 1);
2294 fields.appendAssumeCapacity(try o.builder.debugMemberType(
2295 try o.builder.metadataString("bits"),
2296 null, // file
2297 ty_fwd_ref,
2298 0, // line
2299 try o.getDebugType(pt, .fromInterned(struct_type.packed_backing_int_type)),
2300 ty.abiSize(zcu) * 8,
2301 ty.abiAlignment(zcu).toByteUnits().? * 8,
2302 0, // offset
2303 ));
2304 },
2305 .auto, .@"extern" => {
2306 comptime assert(struct_layout_version == 2);
2307 try fields.ensureTotalCapacityPrecise(gpa, struct_type.field_types.len);
2308 var it = struct_type.iterateRuntimeOrder(ip);
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 },
24432331 }
24442332
2445 const debug_struct_type = try o.builder.debugStructType(
2446 try o.builder.metadataString(name),
2447 null, // File
2448 o.debug_compile_unit.unwrap().?, // Scope
2449 0, // Line
2450 null, // Underlying type
2333 return o.builder.debugStructType(
2334 name,
2335 file,
2336 scope,
2337 line,
2338 null, // underlying type
24512339 ty.abiSize(zcu) * 8,
2452 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,
2340 ty.abiAlignment(zcu).toByteUnits().? * 8,
24532341 try o.builder.metadataTuple(fields.items),
24542342 );
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;
24632343 },
24642344 .@"union" => {
2465 const name = try o.allocTypeName(pt, ty);
2466 defer gpa.free(name);
2467
24682345 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 itself
2483 try o.debug_type_map.put(gpa, ty.toIntern(), debug_fwd_ref);
2355 const enum_tag_ty: Type = .fromInterned(union_type.enum_tag_type);
2356 const layout = Type.getUnionLayout(union_type, zcu);
24842357
24852358 if (layout.payload_size == 0) {
2486 const debug_union_type = try o.builder.debugStructType(
2487 try o.builder.metadataString(name),
2488 null, // File
2489 o.debug_compile_unit.unwrap().?, // Scope
2490 0, // Line
2491 null, // Underlying type
2359 const tag_member = try o.builder.debugMemberType(
2360 try o.builder.metadataString("tag"),
2361 null, // file
2362 ty_fwd_ref,
2363 0, // line
2364 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
24922375 ty.abiSize(zcu) * 8,
2493 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,
2494 try o.builder.metadataTuple(
2495 &.{try o.lowerDebugType(pt, Type.fromInterned(union_type.enum_tag_ty))},
2496 ),
2376 ty.abiAlignment(zcu).toByteUnits().? * 8,
2377 try o.builder.metadataTuple(&.{tag_member}),
24972378 );
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;
25042379 }
25052380
2506 var fields: std.ArrayList(Builder.Metadata) = .empty;
2381 var fields: std.ArrayList(Builder.Metadata) = try .initCapacity(gpa, union_type.field_types.len);
25072382 defer fields.deinit(gpa);
25082383
2509 try fields.ensureUnusedCapacity(gpa, union_type.loadTagType(ip).names.len);
2510
2511 const debug_union_fwd_ref = if (layout.tag_size == 0)
2512 debug_fwd_ref
2384 const payload_fwd_ref = if (layout.tag_size == 0)
2385 ty_fwd_ref
25132386 else
25142387 try o.builder.debugForwardReference();
25152388
2516 const tag_type = union_type.loadTagType(ip);
2517
2518 for (0..tag_type.names.len) |field_index| {
2389 for (0..union_type.field_types.len) |field_index| {
25192390 const field_ty = union_type.field_types.get(ip)[field_index];
2520 if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(zcu)) continue;
25212391
25222392 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) {
25242394 .@"packed" => .none,
2525 .auto, .@"extern" => ty.fieldAlignment(field_index, zcu),
2395 .auto, .@"extern" => ty.explicitFieldAlignment(field_index, zcu),
25262396 };
25272397
2528 const field_name = tag_type.names.get(ip)[field_index];
2398 const field_name = enum_tag_ty.enumFieldName(field_index, zcu);
25292399 fields.appendAssumeCapacity(try o.builder.debugMemberType(
25302400 try o.builder.metadataString(field_name.toSlice(ip)),
2531 null, // File
2532 debug_union_fwd_ref,
2533 0, // Line
2534 try o.lowerDebugType(pt, Type.fromInterned(field_ty)),
2401 null, // file
2402 payload_fwd_ref,
2403 0, // line
2404 try o.getDebugType(pt, .fromInterned(field_ty)),
25352405 field_size * 8,
25362406 (field_align.toByteUnits() orelse 0) * 8,
2537 0, // Offset
2407 0, // offset
25382408 ));
25392409 }
25402410
2541 var union_name_buf: ?[:0]const u8 = null;
2542 defer if (union_name_buf) |buf| gpa.free(buf);
2543 const union_name = if (layout.tag_size == 0) name else name: {
2544 union_name_buf = try std.fmt.allocPrintSentinel(gpa, "{s}:Payload", .{name}, 0);
2545 break :name union_name_buf.?;
2546 };
2547
2548 const debug_union_type = try o.builder.debugUnionType(
2549 try o.builder.metadataString(union_name),
2550 null, // File
2551 o.debug_compile_unit.unwrap().?, // Scope
2552 0, // Line
2553 null, // Underlying type
2411 const debug_payload_type = try o.builder.debugUnionType(
2412 payload_name: {
2413 if (layout.tag_size == 0) break :payload_name name;
2414 break :payload_name try o.builder.metadataStringFmt("{s}:Payload", .{name.slice(&o.builder)});
2415 },
2416 file,
2417 scope,
2418 line,
2419 null, // underlying type
25542420 layout.payload_size * 8,
2555 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,
2421 ty.abiAlignment(zcu).toByteUnits().? * 8,
25562422 try o.builder.metadataTuple(fields.items),
25572423 );
25582424
2559 o.builder.resolveDebugForwardReference(debug_union_fwd_ref, debug_union_type);
2560
25612425 if (layout.tag_size == 0) {
2562 // Set to real type now that it has been lowered fully
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;
2426 return debug_payload_type;
25672427 }
25682428
2569 var tag_offset: u64 = undefined;
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 }
2429 o.builder.resolveDebugForwardReference(payload_fwd_ref, debug_payload_type);
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(
25802440 try o.builder.metadataString("tag"),
2581 null, // File
2582 debug_fwd_ref,
2583 0, // Line
2584 try o.lowerDebugType(pt, Type.fromInterned(union_type.enum_tag_ty)),
2441 null, // file
2442 ty_fwd_ref,
2443 0, // line
2444 try o.getDebugType(pt, enum_tag_ty),
25852445 layout.tag_size * 8,
2586 (layout.tag_align.toByteUnits() orelse 0) * 8,
2446 layout.tag_align.toByteUnits().? * 8,
25872447 tag_offset * 8,
25882448 );
25892449
2590 const debug_payload_type = try o.builder.debugMemberType(
2450 const payload_member_type = try o.builder.debugMemberType(
25912451 try o.builder.metadataString("payload"),
2592 null, // File
2593 debug_fwd_ref,
2594 0, // Line
2595 debug_union_type,
2452 null, // file
2453 ty_fwd_ref,
2454 0, // line
2455 debug_payload_type,
25962456 layout.payload_size * 8,
2597 (layout.payload_align.toByteUnits() orelse 0) * 8,
2457 layout.payload_align.toByteUnits().? * 8,
25982458 payload_offset * 8,
25992459 );
26002460
26012461 const full_fields: [2]Builder.Metadata =
26022462 if (layout.tag_align.compare(.gte, layout.payload_align))
2603 .{ debug_tag_type, debug_payload_type }
2463 .{ tag_member_type, payload_member_type }
26042464 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(
2608 try o.builder.metadataString(name),
2609 null, // File
2610 o.debug_compile_unit.unwrap().?, // Scope
2611 0, // Line
2612 null, // Underlying type
2467 return o.builder.debugStructType(
2468 name,
2469 file,
2470 scope,
2471 line,
2472 null, // underlying type
26132473 ty.abiSize(zcu) * 8,
2614 (ty.abiAlignment(zcu).toByteUnits() orelse 0) * 8,
2474 ty.abiAlignment(zcu).toByteUnits().? * 8,
26152475 try o.builder.metadataTuple(&full_fields),
26162476 );
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);
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;
2485 const line = ty.typeDeclSrcLine(zcu).? + 1;
26232486
2624 return debug_tagged_union_type;
2625 },
2626 .@"fn" => {
2627 const fn_info = zcu.typeToFunc(ty).?;
2487 if (!ty.hasRuntimeBits(zcu)) {
2488 return o.builder.debugStructType(
2489 name,
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);
2630 defer debug_param_types.deinit();
2500 const enum_type = ip.loadEnumType(ty.toIntern());
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.
2635 if (Type.fromInterned(fn_info.return_type).hasRuntimeBitsIgnoreComptime(zcu)) {
2636 const sret = firstParamSRet(fn_info, zcu, target);
2637 const ret_ty = if (sret) Type.void else Type.fromInterned(fn_info.return_type);
2638 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, ret_ty));
2639
2640 if (sret) {
2641 const ptr_ty = try pt.singleMutPtrType(Type.fromInterned(fn_info.return_type));
2642 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, ptr_ty));
2643 }
2644 } else {
2645 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, Type.void));
2508 for (enumerators, enum_type.field_names.get(ip), 0..) |*out, field_name, field_index| {
2509 var space: Value.BigIntSpace = undefined;
2510 const field_val: std.math.big.int.Const = switch (enum_type.field_values.len) {
2511 0 => std.math.big.int.Mutable.init(&space.limbs, field_index).toConst(),
2512 else => Value.fromInterned(enum_type.field_values.get(ip)[field_index]).toBigInt(&space, zcu),
2513 };
2514 out.* = try o.builder.debugEnumerator(
2515 try o.builder.metadataString(field_name.toSlice(ip)),
2516 int_info.signedness == .unsigned,
2517 int_info.bits,
2518 field_val,
2519 );
26462520 }
26472521
2648 if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) {
2649 // Stack trace pointer.
2650 debug_param_types.appendAssumeCapacity(try o.lowerDebugType(pt, .fromInterned(.ptr_usize_type)));
2522 const debug_enum_type = try o.builder.debugEnumerationType(
2523 name,
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);
26512538 }
26522539
2653 for (0..fn_info.param_types.len) |i| {
2654 const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[i]);
2655 if (!param_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
2540 const file = try o.getDebugFile(pt, ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip));
2541 const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace|
2542 try o.namespaceToDebugScope(pt, parent_namespace)
2543 else
2544 file;
26562545
2657 if (isByRef(param_ty, zcu)) {
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 }
2546 const line = ty.typeDeclSrcLine(zcu).? + 1;
26642547
2665 const debug_function_type = try o.builder.debugSubroutineType(
2666 try o.builder.metadataTuple(debug_param_types.items),
2548 return o.builder.debugStructType(
2549 name,
2550 file,
2551 scope,
2552 line,
2553 null, // underlying type
2554 0, // size
2555 ty.abiAlignment(zcu).toByteUnits().? * 8,
2556 null, // fields
26672557 );
2668
2669 try o.debug_type_map.put(gpa, ty.toIntern(), debug_function_type);
2670 return debug_function_type;
26712558 },
2672 .comptime_int => unreachable,
2673 .comptime_float => unreachable,
2674 .type => unreachable,
2675 .undefined => unreachable,
2676 .null => unreachable,
2677 .enum_literal => unreachable,
2678
26792559 .frame => @panic("TODO implement lowerDebugType for Frame types"),
26802560 .@"anyframe" => @panic("TODO implement lowerDebugType for AnyFrame types"),
26812561 }
26822562 }
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 {
26852566 const zcu = pt.zcu;
2686 const namespace = zcu.namespacePtr(namespace_index);
2687 if (namespace.parent == .none) return try o.getDebugFile(pt, namespace.file_scope);
2688
2689 const gop = try o.debug_unresolved_namespace_scopes.getOrPut(o.gpa, namespace_index);
2690
2691 if (!gop.found_existing) gop.value_ptr.* = try o.builder.debugForwardReference();
2567 const ip = &zcu.intern_pool;
2568 const gpa = zcu.comp.gpa;
2569
2570 const error_set_bits = zcu.errorSetBits();
2571 const error_names = ip.global_error_set.getNamesFromMainThread();
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;
26942599 }
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 {
26972602 const zcu = pt.zcu;
2698 const ip = &zcu.intern_pool;
2699 const file = try o.getDebugFile(pt, ty.typeDeclInstAllowGeneratedTag(zcu).?.resolveFile(ip));
2700 const scope = if (ty.getParentNamespace(zcu).unwrap()) |parent_namespace|
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 );
2603 const namespace = zcu.namespacePtr(namespace_index);
2604 if (namespace.parent == .none) return try o.getDebugFile(pt, namespace.file_scope);
2605 return o.getDebugType(pt, .fromInterned(namespace.owner_type));
27142606 }
27152607
27162608 fn allocTypeName(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error![:0]const u8 {
......@@ -2885,40 +2777,6 @@ pub const Object = struct {
28852777
28862778 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
29222780 function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
29232781 return function_index;
29242782 }
......@@ -3223,7 +3081,7 @@ pub const Object = struct {
32233081 ),
32243082 .opt_type => |child_ty| {
32253083 // 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
32283086 const payload_ty = try o.lowerType(pt, Type.fromInterned(child_ty));
32293087 if (t.optionalReprIsPayload(zcu)) return payload_ty;
......@@ -3245,7 +3103,7 @@ pub const Object = struct {
32453103 // Must stay in sync with `codegen.errUnionPayloadOffset`.
32463104 // See logic in `lowerPtr`.
32473105 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))
32493107 return error_type;
32503108 const payload_type = try o.lowerType(pt, Type.fromInterned(error_union_type.payload_type));
32513109
......@@ -3287,7 +3145,7 @@ pub const Object = struct {
32873145 const struct_type = ip.loadStructType(t.toIntern());
32883146
32893147 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));
32913149 try o.type_map.put(o.gpa, t.toIntern(), int_ty);
32923150 return int_ty;
32933151 }
......@@ -3301,18 +3159,16 @@ pub const Object = struct {
33013159
33023160 comptime assert(struct_layout_version == 2);
33033161 var offset: u64 = 0;
3304 var big_align: InternPool.Alignment = .@"1";
33053162 var struct_kind: Builder.Type.Structure.Kind = .normal;
33063163 // 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).
33073164 var it = struct_type.iterateRuntimeOrder(ip);
33083165 while (it.next()) |field_index| {
33093166 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);
33143167 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
33173173 const padding_len = offset - prev_offset;
33183174 if (padding_len > 0) try llvm_field_types.append(
......@@ -3320,11 +3176,11 @@ pub const Object = struct {
33203176 try o.builder.arrayType(padding_len, .i8),
33213177 );
33223178
3323 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
3179 if (!field_ty.hasRuntimeBits(zcu)) {
33243180 // This is a zero-bit field. If there are runtime bits after this field,
33253181 // map to the next LLVM field (which we know exists): otherwise, don't
33263182 // 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) {
33283184 try o.struct_field_map.put(o.gpa, .{
33293185 .struct_ty = t.toIntern(),
33303186 .field_index = field_index,
......@@ -3343,7 +3199,7 @@ pub const Object = struct {
33433199 }
33443200 {
33453201 const prev_offset = offset;
3346 offset = big_align.forward(offset);
3202 offset = struct_type.alignment.forward(offset);
33473203 const padding_len = offset - prev_offset;
33483204 if (padding_len > 0) try llvm_field_types.append(
33493205 o.gpa,
......@@ -3391,7 +3247,7 @@ pub const Object = struct {
33913247 o.gpa,
33923248 try o.builder.arrayType(padding_len, .i8),
33933249 );
3394 if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(zcu)) {
3250 if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) {
33953251 // This is a zero-bit field. If there are runtime bits after this field,
33963252 // map to the next LLVM field (which we know exists): otherwise, don't
33973253 // map the field, indicating it's at the end of the struct.
......@@ -3428,14 +3284,14 @@ pub const Object = struct {
34283284 const union_obj = ip.loadUnionType(t.toIntern());
34293285 const layout = Type.getUnionLayout(union_obj, zcu);
34303286
3431 if (union_obj.flagsUnordered(ip).layout == .@"packed") {
3432 const int_ty = try o.builder.intType(@intCast(t.bitSize(zcu)));
3287 if (union_obj.layout == .@"packed") {
3288 const int_ty = try o.lowerType(pt, .fromInterned(union_obj.packed_backing_int_type));
34333289 try o.type_map.put(o.gpa, t.toIntern(), int_ty);
34343290 return int_ty;
34353291 }
34363292
34373293 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));
34393295 try o.type_map.put(o.gpa, t.toIntern(), enum_tag_ty);
34403296 return enum_tag_ty;
34413297 }
......@@ -3467,7 +3323,7 @@ pub const Object = struct {
34673323 );
34683324 return ty;
34693325 }
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
34723328 // Put the tag before or after the payload depending on which one's
34733329 // alignment is greater.
......@@ -3502,7 +3358,7 @@ pub const Object = struct {
35023358 }
35033359 return gop.value_ptr.*;
35043360 },
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)),
35063362 .func_type => |func_type| try o.lowerTypeFn(pt, func_type),
35073363 .error_set_type, .inferred_error_set_type => try o.errorIntType(pt),
35083364 // values, not types
......@@ -3522,6 +3378,7 @@ pub const Object = struct {
35223378 .opt,
35233379 .aggregate,
35243380 .un,
3381 .bitpack,
35253382 // memoization, not types
35263383 .memoized_call,
35273384 => unreachable,
......@@ -3529,20 +3386,6 @@ pub const Object = struct {
35293386 };
35303387 }
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
35463389 fn lowerTypeFn(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type {
35473390 const zcu = pt.zcu;
35483391 const ip = &zcu.intern_pool;
......@@ -3641,7 +3484,7 @@ pub const Object = struct {
36413484 if (layout.payload_size == 0) return o.lowerValue(pt, un.tag);
36423485
36433486 const union_obj = zcu.typeToUnion(ty).?;
3644 const container_layout = union_obj.flagsUnordered(ip).layout;
3487 const container_layout = union_obj.layout;
36453488
36463489 assert(container_layout == .@"packed");
36473490
......@@ -3699,7 +3542,9 @@ pub const Object = struct {
36993542 return o.builder.undefConst(try o.lowerType(pt, Type.fromInterned(val_key.typeOf())));
37003543 }
37013544
3702 const ty = Type.fromInterned(val_key.typeOf());
3545 const ty: Type = .fromInterned(val_key.typeOf());
3546 ty.assertHasLayout(zcu);
3547
37033548 return switch (val_key) {
37043549 .int_type,
37053550 .ptr_type,
......@@ -3759,7 +3604,7 @@ pub const Object = struct {
37593604 };
37603605 const err_int_ty = try pt.errorIntType();
37613606 const payload_type = ty.errorUnionPayload(zcu);
3762 if (!payload_type.hasRuntimeBitsIgnoreComptime(zcu)) {
3607 if (!payload_type.hasRuntimeBits(zcu)) {
37633608 // We use the error type directly as the type.
37643609 return o.lowerValue(pt, err_val);
37653610 }
......@@ -3821,7 +3666,7 @@ pub const Object = struct {
38213666 const payload_ty = ty.optionalChild(zcu);
38223667
38233668 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)) {
38253670 return non_null_bit;
38263671 }
38273672 const llvm_ty = try o.lowerType(pt, ty);
......@@ -3857,6 +3702,7 @@ pub const Object = struct {
38573702 fields[0..llvm_ty_fields.len],
38583703 ), vals[0..llvm_ty_fields.len]);
38593704 },
3705 .bitpack => |bitpack| return o.lowerValue(pt, bitpack.backing_int_val),
38603706 .aggregate => |aggregate| switch (ip.indexToKey(ty.toIntern())) {
38613707 .array_type => |array_type| switch (aggregate.storage) {
38623708 .bytes => |bytes| try o.builder.stringConst(try o.builder.string(
......@@ -3988,7 +3834,7 @@ pub const Object = struct {
39883834 0..,
39893835 ) |field_ty, field_val, field_index| {
39903836 if (field_val != .none) continue;
3991 if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(zcu)) continue;
3837 if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue;
39923838
39933839 const field_align = Type.fromInterned(field_ty).abiAlignment(zcu);
39943840 big_align = big_align.max(field_align);
......@@ -4034,16 +3880,8 @@ pub const Object = struct {
40343880 },
40353881 .struct_type => {
40363882 const struct_type = ip.loadStructType(ty.toIntern());
4037 assert(struct_type.haveLayout(ip));
40383883 const struct_ty = try o.lowerType(pt, ty);
4039 if (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 }
3884 assert(struct_type.layout != .@"packed");
40473885 const llvm_len = struct_ty.aggregateLen(&o.builder);
40483886
40493887 const ExpectedContents = extern struct {
......@@ -4063,15 +3901,12 @@ pub const Object = struct {
40633901 comptime assert(struct_layout_version == 2);
40643902 var llvm_index: usize = 0;
40653903 var offset: u64 = 0;
4066 var big_align: InternPool.Alignment = .@"1";
40673904 var need_unnamed = false;
40683905 var field_it = struct_type.iterateRuntimeOrder(ip);
40693906 while (field_it.next()) |field_index| {
40703907 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);
40733908 const prev_offset = offset;
4074 offset = field_align.forward(offset);
3909 offset = struct_type.field_offsets.get(ip)[field_index];
40753910
40763911 const padding_len = offset - prev_offset;
40773912 if (padding_len > 0) {
......@@ -4084,7 +3919,7 @@ pub const Object = struct {
40843919 llvm_index += 1;
40853920 }
40863921
4087 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
3922 if (!field_ty.hasRuntimeBits(zcu)) {
40883923 // This is a zero-bit field - we only needed it for the alignment.
40893924 continue;
40903925 }
......@@ -4102,7 +3937,7 @@ pub const Object = struct {
41023937 }
41033938 {
41043939 const prev_offset = offset;
4105 offset = big_align.forward(offset);
3940 offset = struct_type.alignment.forward(offset);
41063941 const padding_len = offset - prev_offset;
41073942 if (padding_len > 0) {
41083943 fields[llvm_index] = try o.builder.arrayType(padding_len, .i8);
......@@ -4126,19 +3961,13 @@ pub const Object = struct {
41263961 if (layout.payload_size == 0) return o.lowerValue(pt, un.tag);
41273962
41283963 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
41313967 var need_unnamed = false;
41323968 const payload = if (un.tag != .none) p: {
41333969 const field_index = zcu.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?;
41343970 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
41433972 // Sometimes we must make an unnamed struct because LLVM does
41443973 // not support bitcasting our payload struct to the true union payload type.
......@@ -4146,7 +3975,7 @@ pub const Object = struct {
41463975 // must pointer cast to the expected type before accessing the union.
41473976 need_unnamed = layout.most_aligned_field != field_index;
41483977
4149 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
3978 if (!field_ty.hasRuntimeBits(zcu)) {
41503979 const padding_len = layout.payload_size;
41513980 break :p try o.builder.undefConst(try o.builder.arrayType(padding_len, .i8));
41523981 }
......@@ -4165,13 +3994,6 @@ pub const Object = struct {
41653994 );
41663995 } else p: {
41673996 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
41753997 const union_val = try o.lowerValue(pt, un.val);
41763998 need_unnamed = true;
41773999 break :p union_val;
......@@ -4273,7 +4095,14 @@ pub const Object = struct {
42734095 };
42744096 return o.lowerPtr(pt, field.base, offset + field_off);
42754097 },
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,
42774106 };
42784107 }
42794108
......@@ -4298,12 +4127,11 @@ pub const Object = struct {
42984127
42994128 const ptr_ty = Type.fromInterned(uav.orig_ty);
43004129
4301 const is_fn_body = uav_ty.zigTypeTag(zcu) == .@"fn";
4302 if ((!is_fn_body and !uav_ty.hasRuntimeBits(zcu)) or
4303 (is_fn_body and zcu.typeToFunc(uav_ty).?.is_generic)) return o.lowerPtrToVoid(pt, ptr_ty);
4130 if (!uav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
4131 return o.lowerPtrToVoid(pt, ptr_ty);
4132 }
43044133
4305 if (is_fn_body)
4306 @panic("TODO");
4134 assert(uav_ty.zigTypeTag(zcu) != .@"fn"); // should be using a Nav ref
43074135
43084136 const llvm_addr_space = toLlvmAddressSpace(ptr_ty.ptrAddressSpace(zcu), target);
43094137 const alignment = ptr_ty.ptrAlignment(zcu);
......@@ -4326,14 +4154,11 @@ pub const Object = struct {
43264154 const nav_ty = Type.fromInterned(nav.typeOf(ip));
43274155 const ptr_ty = try pt.navPtrType(nav_index);
43284156
4329 const is_fn_body = nav_ty.zigTypeTag(zcu) == .@"fn";
4330 if ((!is_fn_body and !nav_ty.hasRuntimeBits(zcu)) or
4331 (is_fn_body and zcu.typeToFunc(nav_ty).?.is_generic))
4332 {
4157 if (nav.getExtern(ip) == null and !nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) {
43334158 return o.lowerPtrToVoid(pt, ptr_ty);
43344159 }
43354160
4336 const llvm_global = if (is_fn_body)
4161 const llvm_global = if (nav_ty.zigTypeTag(zcu) == .@"fn")
43374162 (try o.resolveLlvmFunction(pt, nav_index)).ptrConst(&o.builder).global
43384163 else
43394164 (try o.resolveGlobalNav(pt, nav_index)).ptrConst(&o.builder).global;
......@@ -4376,21 +4201,18 @@ pub const Object = struct {
43764201 /// types to work around a LLVM deficiency when targeting ARM/AArch64.
43774202 fn getAtomicAbiType(o: *Object, pt: Zcu.PerThread, ty: Type, is_rmw_xchg: bool) Allocator.Error!Builder.Type {
43784203 const zcu = pt.zcu;
4379 const ip = &zcu.intern_pool;
4380 const int_ty = switch (ty.zigTypeTag(zcu)) {
4381 .int => ty,
4382 .@"enum" => ty.intTagType(zcu),
4383 .@"struct" => Type.fromInterned(ip.loadStructType(ty.toIntern()).backingIntTypeUnordered(ip)),
4204 switch (ty.zigTypeTag(zcu)) {
4205 .int, .@"enum", .@"struct", .@"union" => {},
43844206 .float => {
43854207 if (!is_rmw_xchg) return .none;
43864208 return o.builder.intType(@intCast(ty.abiSize(zcu) * 8));
43874209 },
43884210 .bool => return .i8,
43894211 else => return .none,
4390 };
4391 const bit_count = int_ty.intInfo(zcu).bits;
4212 }
4213 const bit_count = ty.bitSize(zcu);
43924214 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));
43944216 } else {
43954217 return .none;
43964218 }
......@@ -4498,7 +4320,7 @@ pub const Object = struct {
44984320 const ret_ty = try o.lowerType(pt, Type.slice_const_u8_sentinel_0);
44994321 const target = &zcu.root_mod.resolved_target.result;
45004322 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),
45024324 try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_type.name.fmt(ip)}),
45034325 toLlvmAddressSpace(.generic, target),
45044326 );
......@@ -4521,12 +4343,16 @@ pub const Object = struct {
45214343
45224344 const bad_value_block = try wip.block(1, "BadValue");
45234345 const tag_int_value = wip.arg(0);
4524 var wip_switch =
4525 try wip.@"switch"(tag_int_value, bad_value_block, @intCast(enum_type.names.len), .none);
4346 var wip_switch = try wip.@"switch"(
4347 tag_int_value,
4348 bad_value_block,
4349 @intCast(enum_type.field_names.len),
4350 .none,
4351 );
45264352 defer wip_switch.finish(&wip);
45274353
4528 for (0..enum_type.names.len) |field_index| {
4529 const name = try o.builder.stringNull(enum_type.names.get(ip)[field_index].toSlice(ip));
4354 for (0..enum_type.field_names.len) |field_index| {
4355 const name = try o.builder.stringNull(enum_type.field_names.get(ip)[field_index].toSlice(ip));
45304356 const name_init = try o.builder.stringConst(name);
45314357 const name_variable_index =
45324358 try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
......@@ -4597,7 +4423,41 @@ pub const NavGen = struct {
45974423 const ty = Type.fromInterned(nav.typeOf(ip));
45984424
45994425 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);
46014461 } else {
46024462 const variable_index = try o.resolveGlobalNav(pt, nav_index);
46034463 variable_index.setAlignment(zcu.navAlignment(nav_index).toLlvm(), &o.builder);
......@@ -4626,7 +4486,7 @@ pub const NavGen = struct {
46264486 debug_file, // File
46274487 debug_file, // Scope
46284488 line_number,
4629 try o.lowerDebugType(pt, ty),
4489 try o.getDebugType(pt, ty),
46304490 variable_index,
46314491 .{ .local = linkage == .internal },
46324492 );
......@@ -4748,7 +4608,7 @@ pub const FuncGen = struct {
47484608 /// Have we seen loads or stores involving `allowzero` pointers?
47494609 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 {
47524612 // LLVM already considers null pointers to be valid in non-generic address spaces, so avoid
47534613 // pessimizing optimization for functions with accesses to such pointers.
47544614 if (info.flags.address_space == .generic and info.flags.is_allowzero) self.allowzero_access = true;
......@@ -5216,7 +5076,7 @@ pub const FuncGen = struct {
52165076 try o.builder.metadataString(nav.fqn.toSlice(&zcu.intern_pool)),
52175077 line_number,
52185078 line_number + func.lbrace_line,
5219 try o.lowerDebugType(pt, fn_ty),
5079 try o.getDebugType(pt, fn_ty),
52205080 .{
52215081 .di_flags = .{ .StaticMember = true },
52225082 .sp_flags = .{
......@@ -5514,7 +5374,7 @@ pub const FuncGen = struct {
55145374 return .none;
55155375 }
55165376
5517 if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBitsIgnoreComptime(zcu)) {
5377 if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBits(zcu)) {
55185378 return .none;
55195379 }
55205380
......@@ -5633,7 +5493,7 @@ pub const FuncGen = struct {
56335493 return;
56345494 }
56355495 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)) {
56375497 if (Type.fromInterned(fn_info.return_type).isError(zcu)) {
56385498 // Functions with an empty error set are emitted with an error code
56395499 // return type and return zero so they can be function pointers coerced
......@@ -5698,7 +5558,7 @@ pub const FuncGen = struct {
56985558 const ptr_ty = self.typeOf(un_op);
56995559 const ret_ty = ptr_ty.childType(zcu);
57005560 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)) {
57025562 if (Type.fromInterned(fn_info.return_type).isError(zcu)) {
57035563 // Functions with an empty error set are emitted with an error code
57045564 // return type and return zero so they can be function pointers coerced
......@@ -5829,14 +5689,13 @@ pub const FuncGen = struct {
58295689 const o = self.ng.object;
58305690 const pt = self.ng.pt;
58315691 const zcu = pt.zcu;
5832 const ip = &zcu.intern_pool;
58335692 const scalar_ty = operand_ty.scalarType(zcu);
58345693 const int_ty = switch (scalar_ty.zigTypeTag(zcu)) {
58355694 .@"enum" => scalar_ty.intTagType(zcu),
58365695 .int, .bool, .pointer, .error_set => scalar_ty,
58375696 .optional => blk: {
58385697 const payload_ty = operand_ty.optionalChild(zcu);
5839 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu) or
5698 if (!payload_ty.hasRuntimeBits(zcu) or
58405699 operand_ty.optionalReprIsPayload(zcu))
58415700 {
58425701 break :blk operand_ty;
......@@ -5908,12 +5767,7 @@ pub const FuncGen = struct {
59085767 return phi.toValue();
59095768 },
59105769 .float => return self.buildFloatCmp(fast, op, operand_ty, .{ lhs, rhs }),
5911 .@"struct" => blk: {
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 },
5770 .@"struct" => scalar_ty.bitpackBackingInt(zcu),
59175771 else => unreachable,
59185772 };
59195773 const is_signed = int_ty.isSignedInt(zcu);
......@@ -6305,7 +6159,7 @@ pub const FuncGen = struct {
63056159 const pt = fg.ng.pt;
63066160 const zcu = pt.zcu;
63076161 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);
63096163 const err_union_llvm_ty = try o.lowerType(pt, err_union_ty);
63106164 const error_type = try o.errorIntType(pt);
63116165
......@@ -6641,7 +6495,7 @@ pub const FuncGen = struct {
66416495 const len = try o.builder.intValue(llvm_usize, array_ty.arrayLen(zcu));
66426496 const slice_llvm_ty = try o.lowerType(pt, self.typeOfIndex(inst));
66436497 const operand = try self.resolveInst(ty_op.operand);
6644 if (!array_ty.hasRuntimeBitsIgnoreComptime(zcu))
6498 if (!array_ty.hasRuntimeBits(zcu))
66456499 return self.wip.buildAggregate(slice_llvm_ty, &.{ operand, len }, "");
66466500 const ptr = try self.wip.gep(.inbounds, try o.lowerType(pt, array_ty), operand, &.{
66476501 try o.builder.intValue(llvm_usize, 0), try o.builder.intValue(llvm_usize, 0),
......@@ -6824,7 +6678,7 @@ pub const FuncGen = struct {
68246678 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
68256679 const slice_ptr = try self.resolveInst(ty_op.operand);
68266680 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
68296683 return self.wip.gepStruct(slice_llvm_ty, slice_ptr, index, "");
68306684 }
......@@ -6838,7 +6692,7 @@ pub const FuncGen = struct {
68386692 const slice = try self.resolveInst(bin_op.lhs);
68396693 const index = try self.resolveInst(bin_op.rhs);
68406694 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);
68426696 const base_ptr = try self.wip.extractValue(slice, &.{0}, "");
68436697 const ptr = try self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{index}, "");
68446698 if (isByRef(elem_ty, zcu)) {
......@@ -6863,7 +6717,7 @@ pub const FuncGen = struct {
68636717
68646718 const slice = try self.resolveInst(bin_op.lhs);
68656719 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));
68676721 const base_ptr = try self.wip.extractValue(slice, &.{0}, "");
68686722 return self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{index}, "");
68696723 }
......@@ -6903,7 +6757,7 @@ pub const FuncGen = struct {
69036757 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
69046758 const ptr_ty = self.typeOf(bin_op.lhs);
69056759 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);
69076761 const base_ptr = try self.resolveInst(bin_op.lhs);
69086762 const rhs = try self.resolveInst(bin_op.rhs);
69096763 // TODO: when we go fully opaque pointers in LLVM 16 we can remove this branch
......@@ -6930,8 +6784,8 @@ pub const FuncGen = struct {
69306784 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
69316785 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
69326786 const ptr_ty = self.typeOf(bin_op.lhs);
6933 const elem_ty = ptr_ty.childType(zcu);
6934 if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return self.resolveInst(bin_op.lhs);
6787 const elem_ty = ptr_ty.indexableElem(zcu);
6788 assert(elem_ty.hasRuntimeBits(zcu));
69356789
69366790 const base_ptr = try self.resolveInst(bin_op.lhs);
69376791 const rhs = try self.resolveInst(bin_op.rhs);
......@@ -6939,12 +6793,8 @@ pub const FuncGen = struct {
69396793 const elem_ptr = ty_pl.ty.toType();
69406794 if (elem_ptr.ptrInfo(zcu).flags.vector_index != .none) return base_ptr;
69416795
6942 const llvm_elem_ty = try o.lowerPtrElemTy(pt, elem_ty);
6943 return self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, if (ptr_ty.isSinglePointer(zcu))
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}, "");
6796 const llvm_elem_ty = try o.lowerType(pt, elem_ty);
6797 return self.wip.gep(.inbounds, llvm_elem_ty, base_ptr, &.{rhs}, "");
69486798 }
69496799
69506800 fn airStructFieldPtr(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
......@@ -6976,7 +6826,7 @@ pub const FuncGen = struct {
69766826 const struct_llvm_val = try self.resolveInst(struct_field.struct_operand);
69776827 const field_index = struct_field.field_index;
69786828 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
69816831 if (!isByRef(struct_ty, zcu)) {
69826832 assert(!isByRef(field_ty, zcu));
......@@ -7037,15 +6887,17 @@ pub const FuncGen = struct {
70376887 const llvm_field_index = o.llvmFieldIndex(struct_ty, field_index).?;
70386888 const field_ptr =
70396889 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);
70416891 const field_ptr_ty = try pt.ptrType(.{
70426892 .child = field_ty.toIntern(),
7043 .flags = .{ .alignment = alignment },
6893 .flags = .{ .alignment = explicit_alignment },
70446894 });
70456895 if (isByRef(field_ty, zcu)) {
7046 assert(alignment != .none);
7047 const field_alignment = alignment.toLlvm();
7048 return self.loadByRef(field_ptr, field_ty, field_alignment, .normal);
6896 const alignment = switch (explicit_alignment) {
6897 .none => field_ty.abiAlignment(zcu),
6898 else => |a| a,
6899 };
6900 return self.loadByRef(field_ptr, field_ty, alignment.toLlvm(), .normal);
70496901 } else {
70506902 return self.load(field_ptr, field_ptr_ty);
70516903 }
......@@ -7146,7 +6998,7 @@ pub const FuncGen = struct {
71466998 self.file,
71476999 self.scope,
71487000 self.prev_dbg_line,
7149 try o.lowerDebugType(pt, ptr_ty.childType(zcu)),
7001 try o.getDebugType(pt, ptr_ty.childType(zcu)),
71507002 );
71517003
71527004 _ = try self.wip.callIntrinsic(
......@@ -7179,7 +7031,7 @@ pub const FuncGen = struct {
71797031 self.file,
71807032 self.scope,
71817033 self.prev_dbg_line,
7182 try o.lowerDebugType(pt, operand_ty),
7034 try o.getDebugType(pt, operand_ty),
71837035 arg_no: {
71847036 self.arg_inline_index += 1;
71857037 break :arg_no self.arg_inline_index;
......@@ -7189,7 +7041,7 @@ pub const FuncGen = struct {
71897041 self.file,
71907042 self.scope,
71917043 self.prev_dbg_line,
7192 try o.lowerDebugType(pt, operand_ty),
7044 try o.getDebugType(pt, operand_ty),
71937045 );
71947046
71957047 const zcu = pt.zcu;
......@@ -7280,6 +7132,7 @@ pub const FuncGen = struct {
72807132 const llvm_param_attrs = try arena.alloc(Builder.Type, max_param_count);
72817133 const pt = self.ng.pt;
72827134 const zcu = pt.zcu;
7135 const ip = &zcu.intern_pool;
72837136 const target = zcu.getTarget();
72847137
72857138 var llvm_ret_i: usize = 0;
......@@ -7304,7 +7157,7 @@ pub const FuncGen = struct {
73047157 const output_inst = try self.resolveInst(output.operand);
73057158 const output_ty = self.typeOf(output.operand);
73067159 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
73097162 switch (constraint[0]) {
73107163 '=' => {},
......@@ -7422,7 +7275,7 @@ pub const FuncGen = struct {
74227275 llvm_param_attrs[llvm_param_i] = if (constraint[0] == '*') blk: {
74237276 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));
74267279 } else .none;
74277280
74287281 llvm_param_i += 1;
......@@ -7436,7 +7289,7 @@ pub const FuncGen = struct {
74367289 if (constraint[0] != '+') continue;
74377290
74387291 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));
74407293 if (llvm_ret_indirect[output.index]) {
74417294 llvm_param_values[llvm_param_i] = llvm_rw_vals[output.index];
74427295 llvm_param_types[llvm_param_i] = llvm_rw_vals[output.index].typeOfWip(&self.wip);
......@@ -7463,7 +7316,7 @@ pub const FuncGen = struct {
74637316 total_i += 1;
74647317 }
74657318
7466 const ip = &zcu.intern_pool;
7319 if (total_i != 0) try llvm_constraints.append(gpa, ',');
74677320 const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers);
74687321 const clobbers_ty = clobbers_val.typeOf(zcu);
74697322 var clobbers_bigint_buf: Value.BigIntSpace = undefined;
......@@ -7663,7 +7516,7 @@ pub const FuncGen = struct {
76637516
76647517 comptime assert(optional_layout_version == 3);
76657518
7666 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
7519 if (!payload_ty.hasRuntimeBits(zcu)) {
76677520 const loaded = if (operand_is_ptr)
76687521 try self.wip.load(access_kind, optional_llvm_ty, operand, .default, "")
76697522 else
......@@ -7706,7 +7559,7 @@ pub const FuncGen = struct {
77067559
77077560 if (operand_is_ptr) self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu));
77087561
7709 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
7562 if (!payload_ty.hasRuntimeBits(zcu)) {
77107563 const loaded = if (operand_is_ptr)
77117564 try self.wip.load(access_kind, try o.lowerType(pt, err_union_ty), operand, .default, "")
77127565 else
......@@ -7733,7 +7586,7 @@ pub const FuncGen = struct {
77337586 const operand = try self.resolveInst(ty_op.operand);
77347587 const optional_ty = self.typeOf(ty_op.operand).childType(zcu);
77357588 const payload_ty = optional_ty.optionalChild(zcu);
7736 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
7589 if (!payload_ty.hasRuntimeBits(zcu)) {
77377590 // We have a pointer to a zero-bit value and we need to return
77387591 // a pointer to a zero-bit value.
77397592 return operand;
......@@ -7761,7 +7614,7 @@ pub const FuncGen = struct {
77617614 const access_kind: Builder.MemoryAccessKind =
77627615 if (optional_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
77637616
7764 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
7617 if (!payload_ty.hasRuntimeBits(zcu)) {
77657618 self.maybeMarkAllowZeroAccess(optional_ptr_ty.ptrInfo(zcu));
77667619
77677620 // 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 {
77977650 const operand = try self.resolveInst(ty_op.operand);
77987651 const optional_ty = self.typeOf(ty_op.operand);
77997652 const payload_ty = self.typeOfIndex(inst);
7800 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return .none;
7653 if (!payload_ty.hasRuntimeBits(zcu)) return .none;
78017654
78027655 if (optional_ty.optionalReprIsPayload(zcu)) {
78037656 // Payload value is the same as the optional value.
......@@ -7819,7 +7672,7 @@ pub const FuncGen = struct {
78197672 const result_ty = self.typeOfIndex(inst);
78207673 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)) {
78237676 return if (operand_is_ptr) operand else .none;
78247677 }
78257678 const offset = try errUnionPayloadOffset(payload_ty, pt);
......@@ -7863,7 +7716,7 @@ pub const FuncGen = struct {
78637716 if (operand_is_ptr and operand_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
78647717
78657718 const payload_ty = err_union_ty.errorUnionPayload(zcu);
7866 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
7719 if (!payload_ty.hasRuntimeBits(zcu)) {
78677720 if (!operand_is_ptr) return operand;
78687721
78697722 self.maybeMarkAllowZeroAccess(operand_ty.ptrInfo(zcu));
......@@ -7899,7 +7752,7 @@ pub const FuncGen = struct {
78997752 const access_kind: Builder.MemoryAccessKind =
79007753 if (err_union_ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal;
79017754
7902 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
7755 if (!payload_ty.hasRuntimeBits(zcu)) {
79037756 self.maybeMarkAllowZeroAccess(err_union_ptr_ty.ptrInfo(zcu));
79047757
79057758 _ = try self.wip.store(access_kind, non_error_val, operand, .default);
......@@ -7946,9 +7799,8 @@ pub const FuncGen = struct {
79467799 const struct_llvm_ty = try o.lowerType(pt, struct_ty);
79477800 const llvm_field_index = o.llvmFieldIndex(struct_ty, field_index).?;
79487801 assert(self.err_ret_trace != .none);
7949 const field_ptr =
7950 try self.wip.gepStruct(struct_llvm_ty, self.err_ret_trace, llvm_field_index, "");
7951 const field_alignment = struct_ty.fieldAlignment(field_index, zcu);
7802 const field_ptr = try self.wip.gepStruct(struct_llvm_ty, self.err_ret_trace, llvm_field_index, "");
7803 const field_alignment = struct_ty.explicitFieldAlignment(field_index, zcu);
79527804 const field_ty = struct_ty.fieldType(field_index, zcu);
79537805 const field_ptr_ty = try pt.ptrType(.{
79547806 .child = field_ty.toIntern(),
......@@ -7989,7 +7841,7 @@ pub const FuncGen = struct {
79897841 const payload_ty = self.typeOf(ty_op.operand);
79907842 const non_null_bit = try o.builder.intValue(.i8, 1);
79917843 comptime assert(optional_layout_version == 3);
7992 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return non_null_bit;
7844 assert(payload_ty.hasRuntimeBits(zcu));
79937845 const operand = try self.resolveInst(ty_op.operand);
79947846 const optional_ty = self.typeOfIndex(inst);
79957847 if (optional_ty.optionalReprIsPayload(zcu)) return operand;
......@@ -8023,9 +7875,7 @@ pub const FuncGen = struct {
80237875 const err_un_ty = self.typeOfIndex(inst);
80247876 const operand = try self.resolveInst(ty_op.operand);
80257877 const payload_ty = self.typeOf(ty_op.operand);
8026 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
8027 return operand;
8028 }
7878 assert(payload_ty.hasRuntimeBits(zcu));
80297879 const ok_err_code = try o.builder.intValue(try o.errorIntType(pt), 0);
80307880 const err_un_llvm_ty = try o.lowerType(pt, err_un_ty);
80317881
......@@ -8065,7 +7915,7 @@ pub const FuncGen = struct {
80657915 const err_un_ty = self.typeOfIndex(inst);
80667916 const payload_ty = err_un_ty.errorUnionPayload(zcu);
80677917 const operand = try self.resolveInst(ty_op.operand);
8068 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return operand;
7918 if (!payload_ty.hasRuntimeBits(zcu)) return operand;
80697919 const err_un_llvm_ty = try o.lowerType(pt, err_un_ty);
80707920
80717921 const payload_offset = try errUnionPayloadOffset(payload_ty, pt);
......@@ -8517,7 +8367,7 @@ pub const FuncGen = struct {
85178367 const ptr = try self.resolveInst(bin_op.lhs);
85188368 const offset = try self.resolveInst(bin_op.rhs);
85198369 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));
85218371 switch (ptr_ty.ptrSize(zcu)) {
85228372 // It's a pointer to an array, so according to LLVM we need an extra GEP index.
85238373 .one => return self.wip.gep(.inbounds, llvm_elem_ty, ptr, &.{
......@@ -8541,7 +8391,7 @@ pub const FuncGen = struct {
85418391 const offset = try self.resolveInst(bin_op.rhs);
85428392 const negative_offset = try self.wip.neg(offset, "");
85438393 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));
85458395 switch (ptr_ty.ptrSize(zcu)) {
85468396 // It's a pointer to an array, so according to LLVM we need an extra GEP index.
85478397 .one => return self.wip.gep(.inbounds, llvm_elem_ty, ptr, &.{
......@@ -9502,7 +9352,7 @@ pub const FuncGen = struct {
95029352 self.file,
95039353 self.scope,
95049354 lbrace_line,
9505 try o.lowerDebugType(pt, inst_ty),
9355 try o.getDebugType(pt, inst_ty),
95069356 self.arg_index,
95079357 );
95089358
......@@ -9836,7 +9686,7 @@ pub const FuncGen = struct {
98369686 const ptr_ty = self.typeOf(atomic_load.ptr);
98379687 const info = ptr_ty.ptrInfo(zcu);
98389688 const elem_ty = Type.fromInterned(info.child);
9839 if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return .none;
9689 if (!elem_ty.hasRuntimeBits(zcu)) return .none;
98409690 const ordering = toLlvmAtomicOrdering(atomic_load.order);
98419691 const llvm_abi_ty = try o.getAtomicAbiType(pt, elem_ty, false);
98429692 const ptr_alignment = (if (info.flags.alignment != .none)
......@@ -10304,7 +10154,7 @@ pub const FuncGen = struct {
1030410154
1030510155 const target = &zcu.root_mod.resolved_target.result;
1030610156 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),
1030810158 try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_type.name.fmt(ip)}),
1030910159 toLlvmAddressSpace(.generic, target),
1031010160 );
......@@ -10325,13 +10175,13 @@ pub const FuncGen = struct {
1032510175 defer wip.deinit();
1032610176 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");
1032910179 const unnamed_block = try wip.block(1, "Unnamed");
1033010180 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);
1033210182 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| {
1033510185 const this_tag_int_value = try o.lowerValue(
1033610186 pt,
1033710187 (try pt.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(),
......@@ -10800,15 +10650,14 @@ pub const FuncGen = struct {
1080010650 },
1080110651 .@"struct" => {
1080210652 if (zcu.typeToPackedStruct(result_ty)) |struct_type| {
10803 const backing_int_ty = struct_type.backingIntTypeUnordered(ip);
10804 assert(backing_int_ty != .none);
10805 const big_bits = Type.fromInterned(backing_int_ty).bitSize(zcu);
10653 const backing_int_ty: Type = .fromInterned(struct_type.packed_backing_int_type);
10654 const big_bits = backing_int_ty.bitSize(zcu);
1080610655 const int_ty = try o.builder.intType(@intCast(big_bits));
1080710656 comptime assert(Type.packed_struct_layout_version == 2);
1080810657 var running_int = try o.builder.intValue(int_ty, 0);
1080910658 var running_bits: u16 = 0;
1081010659 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
1081310662 const non_int_val = try self.resolveInst(elem);
1081410663 const ty_bit_size: u16 = @intCast(Type.fromInterned(field_ty).bitSize(zcu));
......@@ -10840,12 +10689,12 @@ pub const FuncGen = struct {
1084010689
1084110690 const llvm_elem = try self.resolveInst(elem);
1084210691 const llvm_i = o.llvmFieldIndex(result_ty, i).?;
10843 const field_ptr =
10844 try self.wip.gepStruct(llvm_result_ty, alloca_inst, llvm_i, "");
10692 const field_ptr = try self.wip.gepStruct(llvm_result_ty, alloca_inst, llvm_i, "");
10693
1084510694 const field_ptr_ty = try pt.ptrType(.{
1084610695 .child = self.typeOf(elem).toIntern(),
1084710696 .flags = .{
10848 .alignment = result_ty.fieldAlignment(i, zcu),
10697 .alignment = result_ty.explicitFieldAlignment(i, zcu),
1084910698 },
1085010699 });
1085110700 try self.store(field_ptr, field_ptr_ty, llvm_elem, .none);
......@@ -10910,7 +10759,7 @@ pub const FuncGen = struct {
1091010759 const layout = union_ty.unionGetLayout(zcu);
1091110760 const union_obj = zcu.typeToUnion(union_ty).?;
1091210761
10913 if (union_obj.flagsUnordered(ip).layout == .@"packed") {
10762 if (union_obj.layout == .@"packed") {
1091410763 const big_bits = union_ty.bitSize(zcu);
1091510764 const int_llvm_ty = try o.builder.intType(@intCast(big_bits));
1091610765 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]);
......@@ -10925,10 +10774,8 @@ pub const FuncGen = struct {
1092510774
1092610775 const tag_int_val = blk: {
1092710776 const tag_ty = union_ty.unionTagTypeHypothetical(zcu);
10928 const union_field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index];
10929 const enum_field_index = tag_ty.enumFieldIndex(union_field_name, zcu).?;
10930 const tag_val = try pt.enumValueFieldIndex(tag_ty, enum_field_index);
10931 break :blk try tag_val.intFromEnum(tag_ty, pt);
10777 const tag_val = try pt.enumValueFieldIndex(tag_ty, extra.field_index);
10778 break :blk tag_val.intFromEnum(zcu);
1093210779 };
1093310780 if (layout.payload_size == 0) {
1093410781 if (layout.tag_size == 0) {
......@@ -10950,16 +10797,14 @@ pub const FuncGen = struct {
1095010797 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]);
1095110798 const field_llvm_ty = try o.lowerType(pt, field_ty);
1095210799 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);
1095410801 const llvm_usize = try o.lowerType(pt, Type.usize);
1095510802 const usize_zero = try o.builder.intValue(llvm_usize, 0);
1095610803
10804 assert(field_ty.hasRuntimeBits(zcu));
10805
1095710806 const llvm_union_ty = t: {
1095810807 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 }
1096310808 if (field_size == layout.payload_size) {
1096410809 break :p field_llvm_ty;
1096510810 }
......@@ -10969,7 +10814,7 @@ pub const FuncGen = struct {
1096910814 });
1097010815 };
1097110816 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));
1097310818 var fields: [3]Builder.Type = undefined;
1097410819 var fields_len: usize = 2;
1097510820 if (layout.tag_align.compare(.gte, layout.payload_align)) {
......@@ -11010,11 +10855,11 @@ pub const FuncGen = struct {
1101010855 const tag_index = @intFromBool(layout.tag_align.compare(.lt, layout.payload_align));
1101110856 const indices: [2]Builder.Value = .{ usize_zero, try o.builder.intValue(.i32, tag_index) };
1101210857 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));
1101410859 var big_int_space: Value.BigIntSpace = undefined;
1101510860 const tag_big_int = tag_int_val.toBigInt(&big_int_space, zcu);
1101610861 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();
1101810863 _ = try self.wip.store(.normal, llvm_tag, field_ptr, tag_alignment);
1101910864 }
1102010865
......@@ -11295,8 +11140,10 @@ pub const FuncGen = struct {
1129511140 return self.wip.gep(.inbounds, .i8, struct_ptr, &.{llvm_index}, "");
1129611141 },
1129711142 else => {
11298 const struct_llvm_ty = try o.lowerPtrElemTy(pt, struct_ty);
11299
11143 if (!struct_ty.hasRuntimeBits(zcu)) {
11144 return struct_ptr;
11145 }
11146 const struct_llvm_ty = try o.lowerType(pt, struct_ty);
1130011147 if (o.llvmFieldIndex(struct_ty, field_index)) |llvm_field_index| {
1130111148 return self.wip.gepStruct(struct_llvm_ty, struct_ptr, llvm_field_index, "");
1130211149 } else {
......@@ -11306,7 +11153,7 @@ pub const FuncGen = struct {
1130611153 // the struct.
1130711154 const llvm_index = try o.builder.intValue(
1130811155 try o.lowerType(pt, Type.usize),
11309 @intFromBool(struct_ty.hasRuntimeBitsIgnoreComptime(zcu)),
11156 @intFromBool(struct_ty.hasRuntimeBits(zcu)),
1131011157 );
1131111158 return self.wip.gep(.inbounds, struct_llvm_ty, struct_ptr, &.{llvm_index}, "");
1131211159 }
......@@ -11393,7 +11240,7 @@ pub const FuncGen = struct {
1139311240 const zcu = pt.zcu;
1139411241 const info = ptr_ty.ptrInfo(zcu);
1139511242 const elem_ty = Type.fromInterned(info.child);
11396 if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return .none;
11243 if (!elem_ty.hasRuntimeBits(zcu)) return .none;
1139711244
1139811245 const ptr_alignment = (if (info.flags.alignment != .none)
1139911246 @as(InternPool.Alignment, info.flags.alignment)
......@@ -12048,7 +11895,7 @@ fn returnTypeByRef(zcu: *Zcu, target: *const std.Target, ty: Type) bool {
1204811895
1204911896fn firstParamSRet(fn_info: InternPool.Key.FuncType, zcu: *Zcu, target: *const std.Target) bool {
1205011897 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
1205311900 return switch (fn_info.cc) {
1205411901 .auto => returnTypeByRef(zcu, target, return_type),
......@@ -12088,11 +11935,9 @@ fn firstParamSRetSystemV(ty: Type, zcu: *Zcu, target: *const std.Target) bool {
1208811935fn lowerFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type {
1208911936 const zcu = pt.zcu;
1209011937 const return_type = Type.fromInterned(fn_info.return_type);
12091 if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) {
12092 // If the return type is an error set or an error union, then we make this
12093 // anyerror return type instead, so that it can be coerced into a function
12094 // pointer type which has anyerror as the return type.
12095 return if (return_type.isError(zcu)) try o.errorIntType(pt) else .void;
11938 if (!return_type.hasRuntimeBits(zcu)) {
11939 assert(!return_type.isError(zcu));
11940 return .void;
1209611941 }
1209711942 const target = zcu.getTarget();
1209811943 switch (fn_info.cc) {
......@@ -12136,7 +11981,7 @@ fn lowerFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType)
1213611981 var types: [8]Builder.Type = undefined;
1213711982 for (0..return_type.structFieldCount(zcu)) |field_index| {
1213811983 const field_ty = return_type.fieldType(field_index, zcu);
12139 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
11984 if (!field_ty.hasRuntimeBits(zcu)) continue;
1214011985 types[types_len] = try o.lowerType(pt, field_ty);
1214111986 types_len += 1;
1214211987 }
......@@ -12174,6 +12019,7 @@ fn lowerSystemVFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.Fu
1217412019 const zcu = pt.zcu;
1217512020 const ip = &zcu.intern_pool;
1217612021 const return_type = Type.fromInterned(fn_info.return_type);
12022 return_type.assertHasLayout(zcu);
1217712023 if (isScalar(zcu, return_type)) {
1217812024 return o.lowerType(pt, return_type);
1217912025 }
......@@ -12222,9 +12068,7 @@ fn lowerSystemVFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.Fu
1222212068 assert(first_non_integer orelse classes.len == types_index);
1222312069 switch (ip.indexToKey(return_type.toIntern())) {
1222412070 .struct_type => {
12225 const struct_type = ip.loadStructType(return_type.toIntern());
12226 assert(struct_type.haveLayout(ip));
12227 const size: u64 = struct_type.sizeUnordered(ip);
12071 const size = return_type.abiSize(zcu);
1222812072 assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index);
1222912073 if (size % 8 > 0) {
1223012074 types_buffer[types_index - 1] = try o.builder.intType(@intCast(size % 8 * 8));
......@@ -12260,7 +12104,7 @@ const ParamTypeIterator = struct {
1226012104 i64_array: u8,
1226112105 };
1226212106
12263 pub fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering {
12107 fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering {
1226412108 if (it.zig_index >= it.fn_info.param_types.len) return null;
1226512109 const ip = &it.pt.zcu.intern_pool;
1226612110 const ty = it.fn_info.param_types.get(ip)[it.zig_index];
......@@ -12269,7 +12113,7 @@ const ParamTypeIterator = struct {
1226912113 }
1227012114
1227112115 /// `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 {
1227312117 assert(std.meta.eql(it.pt, fg.ng.pt));
1227412118 const ip = &it.pt.zcu.intern_pool;
1227512119 if (it.zig_index >= it.fn_info.param_types.len) {
......@@ -12288,7 +12132,7 @@ const ParamTypeIterator = struct {
1228812132 const zcu = pt.zcu;
1228912133 const target = zcu.getTarget();
1229012134
12291 if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) {
12135 if (!ty.hasRuntimeBits(zcu)) {
1229212136 it.zig_index += 1;
1229312137 return .no_bits;
1229412138 }
......@@ -12383,7 +12227,7 @@ const ParamTypeIterator = struct {
1238312227 it.types_len = 0;
1238412228 for (0..ty.structFieldCount(zcu)) |field_index| {
1238512229 const field_ty = ty.fieldType(field_index, zcu);
12386 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
12230 if (!field_ty.hasRuntimeBits(zcu)) continue;
1238712231 it.types_buffer[it.types_len] = try it.object.lowerType(pt, field_ty);
1238812232 it.types_len += 1;
1238912233 }
......@@ -12460,6 +12304,7 @@ const ParamTypeIterator = struct {
1246012304 fn nextSystemV(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering {
1246112305 const zcu = it.pt.zcu;
1246212306 const ip = &zcu.intern_pool;
12307 ty.assertHasLayout(zcu);
1246312308 const classes = x86_64_abi.classifySystemV(ty, zcu, zcu.getTarget(), .arg);
1246412309 if (classes[0] == .memory) {
1246512310 it.zig_index += 1;
......@@ -12531,9 +12376,7 @@ const ParamTypeIterator = struct {
1253112376 }
1253212377 switch (ip.indexToKey(ty.toIntern())) {
1253312378 .struct_type => {
12534 const struct_type = ip.loadStructType(ty.toIntern());
12535 assert(struct_type.haveLayout(ip));
12536 const size: u64 = struct_type.sizeUnordered(ip);
12379 const size = ty.abiSize(zcu);
1253712380 assert((std.math.divCeil(u64, size, 8) catch unreachable) == types_index);
1253812381 if (size % 8 > 0) {
1253912382 types_buffer[types_index - 1] =
......@@ -12707,14 +12550,14 @@ fn isByRef(ty: Type, zcu: *Zcu) bool {
1270712550 },
1270812551 .error_union => {
1270912552 const payload_ty = ty.errorUnionPayload(zcu);
12710 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
12553 if (!payload_ty.hasRuntimeBits(zcu)) {
1271112554 return false;
1271212555 }
1271312556 return true;
1271412557 },
1271512558 .optional => {
1271612559 const payload_ty = ty.optionalChild(zcu);
12717 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
12560 if (!payload_ty.hasRuntimeBits(zcu)) {
1271812561 return false;
1271912562 }
1272012563 if (ty.optionalReprIsPayload(zcu)) {
src/codegen/mips/abi.zig+1-1
......@@ -13,7 +13,7 @@ pub const Context = enum { ret, arg };
1313
1414pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
1515 const target = zcu.getTarget();
16 std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(zcu));
16 std.debug.assert(ty.hasRuntimeBits(zcu));
1717
1818 const max_direct_size = target.ptrBitWidth() * 2;
1919 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 };
1111
1212pub fn classifyType(ty: Type, zcu: *Zcu) Class {
1313 const target = zcu.getTarget();
14 std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(zcu));
14 std.debug.assert(ty.hasRuntimeBits(zcu));
1515
1616 const max_byval_size = target.ptrBitWidth() * 2;
1717 switch (ty.zigTypeTag(zcu)) {
......@@ -27,7 +27,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class {
2727 var field_count: usize = 0;
2828 for (0..ty.structFieldCount(zcu)) |field_index| {
2929 const field_ty = ty.fieldType(field_index, zcu);
30 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
30 if (!field_ty.hasRuntimeBits(zcu)) continue;
3131 if (field_ty.isRuntimeFloat())
3232 any_fp = true
3333 else if (!field_ty.isAbiInt(zcu))
src/codegen/wasm/abi.zig+3-3
......@@ -22,7 +22,7 @@ pub const Class = union(enum) {
2222/// or returned as value within a wasm function.
2323pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
2424 const ip = &zcu.intern_pool;
25 assert(ty.hasRuntimeBitsIgnoreComptime(zcu));
25 assert(ty.hasRuntimeBits(zcu));
2626 switch (ty.zigTypeTag(zcu)) {
2727 .int, .@"enum", .error_set => return .{ .direct = ty },
2828 .float => return .{ .direct = ty },
......@@ -47,7 +47,7 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
4747 return .indirect;
4848 }
4949 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);
5151 if (explicit_align != .none) {
5252 if (explicit_align.compareStrict(.gt, field_ty.abiAlignment(zcu)))
5353 return .indirect;
......@@ -56,7 +56,7 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
5656 },
5757 .@"union" => {
5858 const union_obj = zcu.typeToUnion(ty).?;
59 if (union_obj.flagsUnordered(ip).layout == .@"packed") {
59 if (union_obj.layout == .@"packed") {
6060 return .{ .direct = ty };
6161 }
6262 const layout = ty.unionGetLayout(zcu);
src/link.zig+4-2
......@@ -29,6 +29,7 @@ const codegen = @import("codegen.zig");
2929pub const aarch64 = @import("link/aarch64.zig");
3030pub const LdScript = @import("link/LdScript.zig");
3131pub const Queue = @import("link/Queue.zig");
32pub const DebugConstPool = @import("link/DebugConstPool.zig");
3233
3334pub const Diags = struct {
3435 /// 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
15871588 const ty_prog_node = comp.link_prog_node.start(name, 0);
15881589 defer ty_prog_node.end();
15891590 if (zcu.llvm_object) |llvm_object| {
1590 _ = llvm_object;
1591 @compileError("MLUGG TODO");
1591 llvm_object.updateContainerType(pt, container_update.ty, container_update.success) catch |err| switch (err) {
1592 error.OutOfMemory => diags.setAllocFailure(),
1593 };
15921594 } else {
15931595 if (comp.bin_file) |lf| {
15941596 lf.updateContainerType(pt, container_update.ty, container_update.success) catch |err| switch (err) {
src/link/DebugConstPool.zig+3
......@@ -13,6 +13,9 @@
1313/// * forward `updateContainerType` calls to its `DebugConstPool`
1414/// * expose some callback functions---see functions in `DebugInfo`
1515/// * 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.
1619const DebugConstPool = @This();
1720
1821values: std.AutoArrayHashMapUnmanaged(InternPool.Index, void),
src/link/Dwarf.zig+1-1
......@@ -18,7 +18,7 @@ const codegen = @import("../codegen.zig");
1818const dev = @import("../dev.zig");
1919const link = @import("../link.zig");
2020const target_info = @import("../target.zig");
21const DebugConstPool = @import("DebugConstPool.zig");
21const DebugConstPool = link.DebugConstPool;
2222
2323gpa: Allocator,
2424bin_file: *link.File,