| author | |
| committer | |
| log | ea7e34224a8c3c0551e17a60fd849efee82447f7 |
| tree | 96379f798486f191a84fac86c91cfb6cd2daf934 |
| parent | 0f3c883245f27870472978f738d6e81958e15c52 |
| signature |
4 files changed, 168 insertions(+), 172 deletions(-)
src/Type.zig+4| ... | ... | @@ -1571,6 +1571,7 @@ pub fn externUnionBackingType(ty: Type, pt: Zcu.PerThread) !Type { |
| 1571 | 1571 | } |
| 1572 | 1572 | } |
| 1573 | 1573 | |
| 1574 | /// Asserts that `ty` is a non-packed union type. | |
| 1574 | 1575 | pub fn unionGetLayout(ty: Type, zcu: *const Zcu) Zcu.UnionLayout { |
| 1575 | 1576 | assertHasLayout(ty, zcu); |
| 1576 | 1577 | const union_obj = zcu.intern_pool.loadUnionType(ty.toIntern()); |
| ... | ... | @@ -2689,7 +2690,10 @@ pub fn arrayBase(ty: Type, zcu: *const Zcu) struct { Type, u64 } { |
| 2689 | 2690 | return .{ cur_ty, cur_len }; |
| 2690 | 2691 | } |
| 2691 | 2692 | |
| 2693 | /// Asserts that `loaded_union.layout` is not `.@"packed"`. | |
| 2692 | 2694 | pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) Zcu.UnionLayout { |
| 2695 | assert(loaded_union.layout != .@"packed"); | |
| 2696 | ||
| 2693 | 2697 | const ip = &zcu.intern_pool; |
| 2694 | 2698 | var most_aligned_field: u32 = 0; |
| 2695 | 2699 | var most_aligned_field_align: InternPool.Alignment = .@"1"; |
src/codegen/llvm.zig+63-68| ... | ... | @@ -2369,6 +2369,30 @@ pub const Object = struct { |
| 2369 | 2369 | const line = ty.typeDeclSrcLine(zcu).? + 1; |
| 2370 | 2370 | |
| 2371 | 2371 | const enum_tag_ty: Type = .fromInterned(union_type.enum_tag_type); |
| 2372 | ||
| 2373 | if (union_type.layout == .@"packed") { | |
| 2374 | const bitpack_field = try o.builder.debugMemberType( | |
| 2375 | try o.builder.metadataString("bits"), | |
| 2376 | null, // file | |
| 2377 | ty_fwd_ref, | |
| 2378 | 0, // line | |
| 2379 | try o.getDebugType(pt, .fromInterned(union_type.packed_backing_int_type)), | |
| 2380 | ty.abiSize(zcu) * 8, | |
| 2381 | ty.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2382 | 0, // offset | |
| 2383 | ); | |
| 2384 | return o.builder.debugStructType( | |
| 2385 | name, | |
| 2386 | file, | |
| 2387 | scope, | |
| 2388 | line, | |
| 2389 | null, // underlying type | |
| 2390 | ty.abiSize(zcu) * 8, | |
| 2391 | ty.abiAlignment(zcu).toByteUnits().? * 8, | |
| 2392 | try o.builder.metadataTuple(&.{bitpack_field}), | |
| 2393 | ); | |
| 2394 | } | |
| 2395 | ||
| 2372 | 2396 | const layout = Type.getUnionLayout(union_type, zcu); |
| 2373 | 2397 | |
| 2374 | 2398 | if (layout.payload_size == 0) { |
| ... | ... | @@ -2411,10 +2435,7 @@ pub const Object = struct { |
| 2411 | 2435 | const field_ty = union_type.field_types.get(ip)[field_index]; |
| 2412 | 2436 | |
| 2413 | 2437 | const field_size = Type.fromInterned(field_ty).abiSize(zcu); |
| 2414 | const field_align: InternPool.Alignment = switch (union_type.layout) { | |
| 2415 | .@"packed" => .none, | |
| 2416 | .auto, .@"extern" => ty.explicitFieldAlignment(field_index, zcu), | |
| 2417 | }; | |
| 2438 | const field_align: InternPool.Alignment = ty.explicitFieldAlignment(field_index, zcu); | |
| 2418 | 2439 | |
| 2419 | 2440 | const field_name = enum_tag_ty.enumFieldName(field_index, zcu); |
| 2420 | 2441 | fields.appendAssumeCapacity(try o.builder.debugMemberType( |
| ... | ... | @@ -3318,7 +3339,6 @@ pub const Object = struct { |
| 3318 | 3339 | if (o.type_map.get(t.toIntern())) |value| return value; |
| 3319 | 3340 | |
| 3320 | 3341 | const union_obj = ip.loadUnionType(t.toIntern()); |
| 3321 | const layout = Type.getUnionLayout(union_obj, zcu); | |
| 3322 | 3342 | |
| 3323 | 3343 | if (union_obj.layout == .@"packed") { |
| 3324 | 3344 | const int_ty = try o.lowerType(pt, .fromInterned(union_obj.packed_backing_int_type)); |
| ... | ... | @@ -3326,6 +3346,8 @@ pub const Object = struct { |
| 3326 | 3346 | return int_ty; |
| 3327 | 3347 | } |
| 3328 | 3348 | |
| 3349 | const layout = Type.getUnionLayout(union_obj, zcu); | |
| 3350 | ||
| 3329 | 3351 | if (layout.payload_size == 0) { |
| 3330 | 3352 | const enum_tag_ty = try o.lowerType(pt, .fromInterned(union_obj.enum_tag_type)); |
| 3331 | 3353 | try o.type_map.put(o.gpa, t.toIntern(), enum_tag_ty); |
| ... | ... | @@ -6760,7 +6782,7 @@ pub const FuncGen = struct { |
| 6760 | 6782 | const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data; |
| 6761 | 6783 | const struct_ptr = try self.resolveInst(struct_field.struct_operand); |
| 6762 | 6784 | const struct_ptr_ty = self.typeOf(struct_field.struct_operand); |
| 6763 | return self.fieldPtr(inst, struct_ptr, struct_ptr_ty, struct_field.field_index); | |
| 6785 | return self.fieldPtr(struct_ptr, struct_ptr_ty, struct_field.field_index); | |
| 6764 | 6786 | } |
| 6765 | 6787 | |
| 6766 | 6788 | fn airStructFieldPtrIndex( |
| ... | ... | @@ -6771,7 +6793,7 @@ pub const FuncGen = struct { |
| 6771 | 6793 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6772 | 6794 | const struct_ptr = try self.resolveInst(ty_op.operand); |
| 6773 | 6795 | const struct_ptr_ty = self.typeOf(ty_op.operand); |
| 6774 | return self.fieldPtr(inst, struct_ptr, struct_ptr_ty, field_index); | |
| 6796 | return self.fieldPtr(struct_ptr, struct_ptr_ty, field_index); | |
| 6775 | 6797 | } |
| 6776 | 6798 | |
| 6777 | 6799 | fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| ... | ... | @@ -10704,18 +10726,11 @@ pub const FuncGen = struct { |
| 10704 | 10726 | const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data; |
| 10705 | 10727 | const union_ty = self.typeOfIndex(inst); |
| 10706 | 10728 | const union_llvm_ty = try o.lowerType(pt, union_ty); |
| 10707 | const layout = union_ty.unionGetLayout(zcu); | |
| 10708 | 10729 | const union_obj = zcu.typeToUnion(union_ty).?; |
| 10709 | 10730 | |
| 10710 | if (union_obj.layout == .@"packed") { | |
| 10711 | const big_bits = union_ty.bitSize(zcu); | |
| 10712 | const int_llvm_ty = try o.builder.intType(@intCast(big_bits)); | |
| 10713 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]); | |
| 10714 | const non_int_val = try self.resolveInst(extra.init); | |
| 10715 | const small_int_ty = try o.builder.intType(@intCast(field_ty.bitSize(zcu))); | |
| 10716 | const small_int_val = try self.wip.cast(.bitcast, non_int_val, small_int_ty, ""); | |
| 10717 | return self.wip.conv(.unsigned, small_int_val, int_llvm_ty, ""); | |
| 10718 | } | |
| 10731 | assert(union_obj.layout != .@"packed"); | |
| 10732 | ||
| 10733 | const layout = Type.getUnionLayout(union_obj, zcu); | |
| 10719 | 10734 | |
| 10720 | 10735 | const tag_int_val = blk: { |
| 10721 | 10736 | const tag_ty = union_ty.unionTagTypeHypothetical(zcu); |
| ... | ... | @@ -11051,65 +11066,45 @@ pub const FuncGen = struct { |
| 11051 | 11066 | |
| 11052 | 11067 | fn fieldPtr( |
| 11053 | 11068 | self: *FuncGen, |
| 11054 | inst: Air.Inst.Index, | |
| 11055 | struct_ptr: Builder.Value, | |
| 11056 | struct_ptr_ty: Type, | |
| 11069 | aggregate_ptr: Builder.Value, | |
| 11070 | aggregate_ptr_ty: Type, | |
| 11057 | 11071 | field_index: u32, |
| 11058 | 11072 | ) !Builder.Value { |
| 11059 | 11073 | const o = self.ng.object; |
| 11060 | 11074 | const pt = self.ng.pt; |
| 11061 | 11075 | const zcu = pt.zcu; |
| 11062 | const struct_ty = struct_ptr_ty.childType(zcu); | |
| 11063 | switch (struct_ty.zigTypeTag(zcu)) { | |
| 11064 | .@"struct" => switch (struct_ty.containerLayout(zcu)) { | |
| 11065 | .@"packed" => { | |
| 11066 | const result_ty = self.typeOfIndex(inst); | |
| 11067 | const result_ty_info = result_ty.ptrInfo(zcu); | |
| 11068 | const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(zcu); | |
| 11069 | const struct_type = zcu.typeToStruct(struct_ty).?; | |
| 11070 | ||
| 11071 | if (result_ty_info.packed_offset.host_size != 0) { | |
| 11072 | // From LLVM's perspective, a pointer to a packed struct and a pointer | |
| 11073 | // to a field of a packed struct are the same. The difference is in the | |
| 11074 | // Zig pointer type which provides information for how to mask and shift | |
| 11075 | // out the relevant bits when accessing the pointee. | |
| 11076 | return struct_ptr; | |
| 11077 | } | |
| 11078 | ||
| 11079 | // We have a pointer to a packed struct field that happens to be byte-aligned. | |
| 11080 | // Offset our operand pointer by the correct number of bytes. | |
| 11081 | const byte_offset = @divExact(zcu.structPackedFieldBitOffset(struct_type, field_index) + struct_ptr_ty_info.packed_offset.bit_offset, 8); | |
| 11082 | if (byte_offset == 0) return struct_ptr; | |
| 11083 | const usize_ty = try o.lowerType(pt, Type.usize); | |
| 11084 | const llvm_index = try o.builder.intValue(usize_ty, byte_offset); | |
| 11085 | return self.wip.gep(.inbounds, .i8, struct_ptr, &.{llvm_index}, ""); | |
| 11086 | }, | |
| 11087 | else => { | |
| 11088 | if (!struct_ty.hasRuntimeBits(zcu)) { | |
| 11089 | return struct_ptr; | |
| 11090 | } | |
| 11091 | const struct_llvm_ty = try o.lowerType(pt, struct_ty); | |
| 11092 | if (o.llvmFieldIndex(struct_ty, field_index)) |llvm_field_index| { | |
| 11093 | return self.wip.gepStruct(struct_llvm_ty, struct_ptr, llvm_field_index, ""); | |
| 11094 | } else { | |
| 11095 | // If we found no index then this means this is a zero sized field at the | |
| 11096 | // end of the struct. Treat our struct pointer as an array of two and get | |
| 11097 | // the index to the element at index `1` to get a pointer to the end of | |
| 11098 | // the struct. | |
| 11099 | const llvm_index = try o.builder.intValue( | |
| 11100 | try o.lowerType(pt, Type.usize), | |
| 11101 | @intFromBool(struct_ty.hasRuntimeBits(zcu)), | |
| 11102 | ); | |
| 11103 | return self.wip.gep(.inbounds, struct_llvm_ty, struct_ptr, &.{llvm_index}, ""); | |
| 11104 | } | |
| 11105 | }, | |
| 11076 | const aggregate_ty = aggregate_ptr_ty.childType(zcu); | |
| 11077 | if (aggregate_ty.containerLayout(zcu) == .@"packed") { | |
| 11078 | // A pointer to a bitpack field is equivalent to a pointer to the whole bitpack; the | |
| 11079 | // bit offset is represented in the pointer *type*. | |
| 11080 | return aggregate_ptr; | |
| 11081 | } | |
| 11082 | switch (aggregate_ty.zigTypeTag(zcu)) { | |
| 11083 | .@"struct" => { | |
| 11084 | if (!aggregate_ty.hasRuntimeBits(zcu)) { | |
| 11085 | return aggregate_ptr; | |
| 11086 | } | |
| 11087 | const struct_llvm_ty = try o.lowerType(pt, aggregate_ty); | |
| 11088 | if (o.llvmFieldIndex(aggregate_ty, field_index)) |llvm_field_index| { | |
| 11089 | return self.wip.gepStruct(struct_llvm_ty, aggregate_ptr, llvm_field_index, ""); | |
| 11090 | } else { | |
| 11091 | // If we found no index then this means this is a zero sized field at the | |
| 11092 | // end of the struct. Treat our struct pointer as an array of two and get | |
| 11093 | // the index to the element at index `1` to get a pointer to the end of | |
| 11094 | // the struct. | |
| 11095 | const llvm_index = try o.builder.intValue( | |
| 11096 | try o.lowerType(pt, Type.usize), | |
| 11097 | @intFromBool(aggregate_ty.hasRuntimeBits(zcu)), | |
| 11098 | ); | |
| 11099 | return self.wip.gep(.inbounds, struct_llvm_ty, aggregate_ptr, &.{llvm_index}, ""); | |
| 11100 | } | |
| 11106 | 11101 | }, |
| 11107 | 11102 | .@"union" => { |
| 11108 | const layout = struct_ty.unionGetLayout(zcu); | |
| 11109 | if (layout.payload_size == 0 or struct_ty.containerLayout(zcu) == .@"packed") return struct_ptr; | |
| 11103 | const layout = aggregate_ty.unionGetLayout(zcu); | |
| 11104 | if (layout.payload_size == 0) return aggregate_ptr; | |
| 11110 | 11105 | const payload_index = @intFromBool(layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)); |
| 11111 | const union_llvm_ty = try o.lowerType(pt, struct_ty); | |
| 11112 | return self.wip.gepStruct(union_llvm_ty, struct_ptr, payload_index, ""); | |
| 11106 | const union_llvm_ty = try o.lowerType(pt, aggregate_ty); | |
| 11107 | return self.wip.gepStruct(union_llvm_ty, aggregate_ptr, payload_index, ""); | |
| 11113 | 11108 | }, |
| 11114 | 11109 | else => unreachable, |
| 11115 | 11110 | } |
src/codegen/spirv/CodeGen.zig+26-46| ... | ... | @@ -4519,30 +4519,7 @@ fn unionInit( |
| 4519 | 4519 | const layout = cg.unionLayout(ty); |
| 4520 | 4520 | const payload_ty: Type = .fromInterned(union_ty.field_types.get(ip)[active_field]); |
| 4521 | 4521 | |
| 4522 | if (union_ty.layout == .@"packed") { | |
| 4523 | if (!payload_ty.hasRuntimeBits(zcu)) { | |
| 4524 | const int_ty = try pt.intType(.unsigned, @intCast(ty.bitSize(zcu))); | |
| 4525 | return cg.constInt(int_ty, 0); | |
| 4526 | } | |
| 4527 | ||
| 4528 | assert(payload != null); | |
| 4529 | if (payload_ty.isInt(zcu)) { | |
| 4530 | if (ty.bitSize(zcu) == payload_ty.bitSize(zcu)) { | |
| 4531 | return cg.bitCast(ty, payload_ty, payload.?); | |
| 4532 | } | |
| 4533 | ||
| 4534 | const trunc = try cg.buildConvert(ty, .{ .ty = payload_ty, .value = .{ .singleton = payload.? } }); | |
| 4535 | return try trunc.materialize(cg); | |
| 4536 | } | |
| 4537 | ||
| 4538 | const payload_int_ty = try pt.intType(.unsigned, @intCast(payload_ty.bitSize(zcu))); | |
| 4539 | const payload_int = if (payload_ty.ip_index == .bool_type) | |
| 4540 | try cg.convertToIndirect(payload_ty, payload.?) | |
| 4541 | else | |
| 4542 | try cg.bitCast(payload_int_ty, payload_ty, payload.?); | |
| 4543 | const trunc = try cg.buildConvert(ty, .{ .ty = payload_int_ty, .value = .{ .singleton = payload_int } }); | |
| 4544 | return try trunc.materialize(cg); | |
| 4545 | } | |
| 4522 | assert(union_ty.layout != .@"packed"); | |
| 4546 | 4523 | |
| 4547 | 4524 | const tag_int = if (layout.tag_size != 0) blk: { |
| 4548 | 4525 | const tag_val = try pt.enumValueFieldIndex(tag_ty, active_field); |
| ... | ... | @@ -4761,33 +4738,36 @@ fn structFieldPtr( |
| 4761 | 4738 | }, |
| 4762 | 4739 | .@"struct" => switch (object_ty.containerLayout(zcu)) { |
| 4763 | 4740 | .@"packed" => return cg.todo("implement field access for packed structs", .{}), |
| 4764 | else => { | |
| 4741 | .auto, .@"extern" => { | |
| 4765 | 4742 | return try cg.accessChain(result_ty_id, object_ptr, &.{field_index}); |
| 4766 | 4743 | }, |
| 4767 | 4744 | }, |
| 4768 | .@"union" => { | |
| 4769 | const layout = cg.unionLayout(object_ty); | |
| 4770 | if (!layout.has_payload) { | |
| 4771 | // Asked to get a pointer to a zero-sized field. Just lower this | |
| 4772 | // to undefined, there is no reason to make it be a valid pointer. | |
| 4773 | return try cg.module.constUndef(result_ty_id); | |
| 4774 | } | |
| 4745 | .@"union" => switch (object_ty.containerLayout(zcu)) { | |
| 4746 | .@"packed" => return cg.todo("implement field access for packed unions", .{}), | |
| 4747 | .auto, .@"extern" => { | |
| 4748 | const layout = cg.unionLayout(object_ty); | |
| 4749 | if (!layout.has_payload) { | |
| 4750 | // Asked to get a pointer to a zero-sized field. Just lower this | |
| 4751 | // to undefined, there is no reason to make it be a valid pointer. | |
| 4752 | return try cg.module.constUndef(result_ty_id); | |
| 4753 | } | |
| 4775 | 4754 | |
| 4776 | const storage_class = cg.module.storageClass(object_ptr_ty.ptrAddressSpace(zcu)); | |
| 4777 | const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect); | |
| 4778 | const pl_ptr_ty_id = try cg.module.ptrType(layout_payload_ty_id, storage_class); | |
| 4779 | const pl_ptr_id = blk: { | |
| 4780 | if (object_ty.containerLayout(zcu) == .@"packed") break :blk object_ptr; | |
| 4781 | break :blk try cg.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index}); | |
| 4782 | }; | |
| 4755 | const storage_class = cg.module.storageClass(object_ptr_ty.ptrAddressSpace(zcu)); | |
| 4756 | const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect); | |
| 4757 | const pl_ptr_ty_id = try cg.module.ptrType(layout_payload_ty_id, storage_class); | |
| 4758 | const pl_ptr_id = blk: { | |
| 4759 | if (object_ty.containerLayout(zcu) == .@"packed") break :blk object_ptr; | |
| 4760 | break :blk try cg.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index}); | |
| 4761 | }; | |
| 4783 | 4762 | |
| 4784 | const active_pl_ptr_id = cg.module.allocId(); | |
| 4785 | try cg.body.emit(cg.module.gpa, .OpBitcast, .{ | |
| 4786 | .id_result_type = result_ty_id, | |
| 4787 | .id_result = active_pl_ptr_id, | |
| 4788 | .operand = pl_ptr_id, | |
| 4789 | }); | |
| 4790 | return active_pl_ptr_id; | |
| 4763 | const active_pl_ptr_id = cg.module.allocId(); | |
| 4764 | try cg.body.emit(cg.module.gpa, .OpBitcast, .{ | |
| 4765 | .id_result_type = result_ty_id, | |
| 4766 | .id_result = active_pl_ptr_id, | |
| 4767 | .operand = pl_ptr_id, | |
| 4768 | }); | |
| 4769 | return active_pl_ptr_id; | |
| 4770 | }, | |
| 4791 | 4771 | }, |
| 4792 | 4772 | else => unreachable, |
| 4793 | 4773 | } |
src/link/Dwarf.zig+75-58| ... | ... | @@ -4009,69 +4009,86 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co |
| 4009 | 4009 | .union_type => { |
| 4010 | 4010 | const loaded_union = ip.loadUnionType(value_index); |
| 4011 | 4011 | const file = loaded_union.zir_index.resolveFile(ip); |
| 4012 | const need_terminator: bool = if (loaded_union.name_nav.unwrap()) |nav_index| t: { | |
| 4013 | const nav = ip.getNav(nav_index); | |
| 4014 | const decl_inst = nav.srcInst(ip).resolve(ip).?; | |
| 4015 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); | |
| 4016 | try wip_nav.declCommon(.{ | |
| 4017 | .decl = .decl_union, | |
| 4018 | .generic_decl = .generic_decl_const, | |
| 4019 | .decl_instance = .decl_instance_union, | |
| 4020 | }, &nav, file, &decl); | |
| 4021 | break :t true; | |
| 4022 | } else t: { | |
| 4023 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); | |
| 4024 | try wip_nav.abbrevCode(if (loaded_union.field_types.len > 0) .union_type else .empty_union_type); | |
| 4025 | try diw.writeUleb128(file_gop.index); | |
| 4026 | try wip_nav.strp(loaded_union.name.toSlice(ip)); | |
| 4027 | break :t loaded_union.field_types.len > 0; | |
| 4028 | }; | |
| 4029 | const union_layout = Type.getUnionLayout(loaded_union, zcu); | |
| 4030 | try diw.writeUleb128(union_layout.abi_size); | |
| 4031 | try diw.writeUleb128(union_layout.abi_align.toByteUnits().?); | |
| 4032 | const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); | |
| 4033 | if (loaded_union.has_runtime_tag) { | |
| 4034 | try wip_nav.abbrevCode(.tagged_union); | |
| 4035 | try wip_nav.infoSectionOffset( | |
| 4036 | .debug_info, | |
| 4037 | wip_nav.unit, | |
| 4038 | wip_nav.entry, | |
| 4039 | @intCast(diw.end + dwarf.sectionOffsetBytes()), | |
| 4040 | ); | |
| 4041 | { | |
| 4042 | try wip_nav.abbrevCode(.generated_field); | |
| 4043 | try wip_nav.strp("tag"); | |
| 4044 | try wip_nav.refType(.fromInterned(loaded_union.enum_tag_type)); | |
| 4045 | try diw.writeUleb128(union_layout.tagOffset()); | |
| 4046 | ||
| 4047 | for (0..loaded_union.field_types.len) |field_index| { | |
| 4048 | try wip_nav.enumConstValue(loaded_tag, .{ | |
| 4049 | .sdata = .signed_tagged_union_field, | |
| 4050 | .udata = .unsigned_tagged_union_field, | |
| 4051 | .block = .big_tagged_union_field, | |
| 4052 | }, field_index); | |
| 4012 | switch (loaded_union.layout) { | |
| 4013 | .auto, .@"extern" => { | |
| 4014 | const need_terminator: bool = if (loaded_union.name_nav.unwrap()) |nav_index| t: { | |
| 4015 | const nav = ip.getNav(nav_index); | |
| 4016 | const decl_inst = nav.srcInst(ip).resolve(ip).?; | |
| 4017 | const decl = zcu.fileByIndex(file).zir.?.getDeclaration(decl_inst); | |
| 4018 | try wip_nav.declCommon(.{ | |
| 4019 | .decl = .decl_union, | |
| 4020 | .generic_decl = .generic_decl_const, | |
| 4021 | .decl_instance = .decl_instance_union, | |
| 4022 | }, &nav, file, &decl); | |
| 4023 | break :t true; | |
| 4024 | } else t: { | |
| 4025 | const file_gop = try dwarf.getModInfo(unit).files.getOrPut(dwarf.gpa, file); | |
| 4026 | try wip_nav.abbrevCode(if (loaded_union.field_types.len > 0) .union_type else .empty_union_type); | |
| 4027 | try diw.writeUleb128(file_gop.index); | |
| 4028 | try wip_nav.strp(loaded_union.name.toSlice(ip)); | |
| 4029 | break :t loaded_union.field_types.len > 0; | |
| 4030 | }; | |
| 4031 | const union_layout = Type.getUnionLayout(loaded_union, zcu); | |
| 4032 | try diw.writeUleb128(union_layout.abi_size); | |
| 4033 | try diw.writeUleb128(union_layout.abi_align.toByteUnits().?); | |
| 4034 | const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); | |
| 4035 | if (loaded_union.has_runtime_tag) { | |
| 4036 | try wip_nav.abbrevCode(.tagged_union); | |
| 4037 | try wip_nav.infoSectionOffset( | |
| 4038 | .debug_info, | |
| 4039 | wip_nav.unit, | |
| 4040 | wip_nav.entry, | |
| 4041 | @intCast(diw.end + dwarf.sectionOffsetBytes()), | |
| 4042 | ); | |
| 4053 | 4043 | { |
| 4054 | try wip_nav.abbrevCode(.struct_field); | |
| 4055 | try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); | |
| 4056 | const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); | |
| 4057 | try wip_nav.refType(field_type); | |
| 4058 | try diw.writeUleb128(union_layout.payloadOffset()); | |
| 4059 | try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse | |
| 4060 | if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); | |
| 4044 | try wip_nav.abbrevCode(.generated_field); | |
| 4045 | try wip_nav.strp("tag"); | |
| 4046 | try wip_nav.refType(.fromInterned(loaded_union.enum_tag_type)); | |
| 4047 | try diw.writeUleb128(union_layout.tagOffset()); | |
| 4048 | ||
| 4049 | for (0..loaded_union.field_types.len) |field_index| { | |
| 4050 | try wip_nav.enumConstValue(loaded_tag, .{ | |
| 4051 | .sdata = .signed_tagged_union_field, | |
| 4052 | .udata = .unsigned_tagged_union_field, | |
| 4053 | .block = .big_tagged_union_field, | |
| 4054 | }, field_index); | |
| 4055 | { | |
| 4056 | try wip_nav.abbrevCode(.struct_field); | |
| 4057 | try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); | |
| 4058 | const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); | |
| 4059 | try wip_nav.refType(field_type); | |
| 4060 | try diw.writeUleb128(union_layout.payloadOffset()); | |
| 4061 | try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse | |
| 4062 | if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); | |
| 4063 | } | |
| 4064 | try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 4065 | } | |
| 4061 | 4066 | } |
| 4062 | 4067 | try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); |
| 4068 | } else for (0..loaded_union.field_types.len) |field_index| { | |
| 4069 | try wip_nav.abbrevCode(.untagged_union_field); | |
| 4070 | try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); | |
| 4071 | const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); | |
| 4072 | try wip_nav.refType(field_type); | |
| 4073 | try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse | |
| 4074 | if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); | |
| 4063 | 4075 | } |
| 4064 | } | |
| 4065 | try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 4066 | } else for (0..loaded_union.field_types.len) |field_index| { | |
| 4067 | try wip_nav.abbrevCode(.untagged_union_field); | |
| 4068 | try wip_nav.strp(loaded_tag.field_names.get(ip)[field_index].toSlice(ip)); | |
| 4069 | const field_type: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); | |
| 4070 | try wip_nav.refType(field_type); | |
| 4071 | try diw.writeUleb128(loaded_union.field_aligns.getOrNone(ip, field_index).toByteUnits() orelse | |
| 4072 | if (field_type.isNoReturn(zcu)) 1 else field_type.abiAlignment(zcu).toByteUnits().?); | |
| 4076 | if (need_terminator) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 4077 | }, | |
| 4078 | .@"packed" => { | |
| 4079 | // TODO: debug info for packed unions | |
| 4080 | try wip_nav.abbrevCode(.numeric_type); | |
| 4081 | try wip_nav.strp(loaded_union.name.toSlice(ip)); | |
| 4082 | const backing_int_ty: Type = .fromInterned(loaded_union.packed_backing_int_type); | |
| 4083 | const int_info = backing_int_ty.intInfo(zcu); | |
| 4084 | try diw.writeByte(switch (int_info.signedness) { | |
| 4085 | inline .signed, .unsigned => |signedness| @field(DW.ATE, @tagName(signedness)), | |
| 4086 | }); | |
| 4087 | try diw.writeUleb128(int_info.bits); | |
| 4088 | try diw.writeUleb128(backing_int_ty.abiSize(zcu)); | |
| 4089 | try diw.writeUleb128(backing_int_ty.abiAlignment(zcu).toByteUnits().?); | |
| 4090 | }, | |
| 4073 | 4091 | } |
| 4074 | if (need_terminator) try diw.writeUleb128(@intFromEnum(AbbrevCode.null)); | |
| 4075 | 4092 | }, |
| 4076 | 4093 | .enum_type => { |
| 4077 | 4094 | const loaded_enum = ip.loadEnumType(value_index); |