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