| ... | @@ -2327,16 +2327,21 @@ pub const Object = struct { | ... | @@ -2327,16 +2327,21 @@ pub const Object = struct { |
| 2327 | const layout = Type.getUnionLayout(union_type, zcu); | 2327 | const layout = Type.getUnionLayout(union_type, zcu); |
| 2328 | | 2328 | |
| 2329 | if (layout.payload_size == 0) { | 2329 | if (layout.payload_size == 0) { |
| 2330 | const tag_member = try o.builder.debugMemberType( | 2330 | const fields_tuple: ?Builder.Metadata = fields: { |
| 2331 | try o.builder.metadataString("tag"), | 2331 | if (layout.tag_size == 0) break :fields null; |
| 2332 | null, // file | 2332 | break :fields try o.builder.metadataTuple(&.{ |
| 2333 | ty_fwd_ref, | 2333 | try o.builder.debugMemberType( |
| 2334 | 0, // line | 2334 | try o.builder.metadataString("tag"), |
| 2335 | try o.getDebugType(pt, enum_tag_ty), | 2335 | null, // file |
| 2336 | layout.tag_size * 8, | 2336 | ty_fwd_ref, |
| 2337 | layout.tag_align.toByteUnits().? * 8, | 2337 | 0, // line |
| 2338 | 0, // offset | 2338 | try o.getDebugType(pt, enum_tag_ty), |
| 2339 | ); | 2339 | layout.tag_size * 8, |
| | 2340 | layout.tag_align.toByteUnits().? * 8, |
| | 2341 | 0, // offset |
| | 2342 | ), |
| | 2343 | }); |
| | 2344 | }; |
| 2340 | return o.builder.debugStructType( | 2345 | return o.builder.debugStructType( |
| 2341 | name, | 2346 | name, |
| 2342 | file, | 2347 | file, |
| ... | @@ -2345,7 +2350,7 @@ pub const Object = struct { | ... | @@ -2345,7 +2350,7 @@ pub const Object = struct { |
| 2345 | null, // underlying type | 2350 | null, // underlying type |
| 2346 | ty.abiSize(zcu) * 8, | 2351 | ty.abiSize(zcu) * 8, |
| 2347 | ty.abiAlignment(zcu).toByteUnits().? * 8, | 2352 | ty.abiAlignment(zcu).toByteUnits().? * 8, |
| 2348 | try o.builder.metadataTuple(&.{tag_member}), | 2353 | fields_tuple, |
| 2349 | ); | 2354 | ); |
| 2350 | } | 2355 | } |
| 2351 | | 2356 | |
| ... | @@ -3141,12 +3146,16 @@ pub const Object = struct { | ... | @@ -3141,12 +3146,16 @@ pub const Object = struct { |
| 3141 | var struct_kind: Builder.Type.Structure.Kind = .normal; | 3146 | var struct_kind: Builder.Type.Structure.Kind = .normal; |
| 3142 | // 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). | 3147 | // 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). |
| 3143 | var it = struct_type.iterateRuntimeOrder(ip); | 3148 | var it = struct_type.iterateRuntimeOrder(ip); |
| | 3149 | var max_field_ty_align: InternPool.Alignment = .@"1"; |
| 3144 | while (it.next()) |field_index| { | 3150 | while (it.next()) |field_index| { |
| 3145 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | 3151 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); |
| | 3152 | const field_ty_align = field_ty.abiAlignment(zcu); |
| | 3153 | max_field_ty_align = max_field_ty_align.maxStrict(field_ty_align); |
| | 3154 | |
| 3146 | const prev_offset = offset; | 3155 | const prev_offset = offset; |
| 3147 | offset = struct_type.field_offsets.get(ip)[field_index]; | 3156 | offset = struct_type.field_offsets.get(ip)[field_index]; |
| 3148 | if (@ctz(offset) < field_ty.abiAlignment(zcu).toLog2Units()) { | 3157 | if (@ctz(offset) < field_ty_align.toLog2Units()) { |
| 3149 | struct_kind = .@"packed"; | 3158 | struct_kind = .@"packed"; // prevent unexpected padding before this field |
| 3150 | } | 3159 | } |
| 3151 | | 3160 | |
| 3152 | const padding_len = offset - prev_offset; | 3161 | const padding_len = offset - prev_offset; |
| ... | @@ -3184,6 +3193,9 @@ pub const Object = struct { | ... | @@ -3184,6 +3193,9 @@ pub const Object = struct { |
| 3184 | o.gpa, | 3193 | o.gpa, |
| 3185 | try o.builder.arrayType(padding_len, .i8), | 3194 | try o.builder.arrayType(padding_len, .i8), |
| 3186 | ); | 3195 | ); |
| | 3196 | if (@ctz(offset) < max_field_ty_align.toLog2Units()) { |
| | 3197 | struct_kind = .@"packed"; // prevent unexpected trailing padding |
| | 3198 | } |
| 3187 | } | 3199 | } |
| 3188 | | 3200 | |
| 3189 | const ty = try o.builder.opaqueType(try o.builder.string(t.containerTypeName(ip).toSlice(ip))); | 3201 | const ty = try o.builder.opaqueType(try o.builder.string(t.containerTypeName(ip).toSlice(ip))); |
| ... | @@ -3883,7 +3895,7 @@ pub const Object = struct { | ... | @@ -3883,7 +3895,7 @@ pub const Object = struct { |
| 3883 | const payload = try o.lowerValue(pt, un.val); | 3895 | const payload = try o.lowerValue(pt, un.val); |
| 3884 | const payload_ty = payload.typeOf(&o.builder); | 3896 | const payload_ty = payload.typeOf(&o.builder); |
| 3885 | if (payload_ty != union_ty.structFields(&o.builder)[ | 3897 | if (payload_ty != union_ty.structFields(&o.builder)[ |
| 3886 | @intFromBool(layout.tag_align.compare(.gte, layout.payload_align)) | 3898 | @intFromBool(layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)) |
| 3887 | ]) need_unnamed = true; | 3899 | ]) need_unnamed = true; |
| 3888 | const field_size = field_ty.abiSize(zcu); | 3900 | const field_size = field_ty.abiSize(zcu); |
| 3889 | if (field_size == layout.payload_size) break :p payload; | 3901 | if (field_size == layout.payload_size) break :p payload; |
| ... | @@ -6806,7 +6818,7 @@ pub const FuncGen = struct { | ... | @@ -6806,7 +6818,7 @@ pub const FuncGen = struct { |
| 6806 | .@"union" => { | 6818 | .@"union" => { |
| 6807 | const union_llvm_ty = try o.lowerType(pt, struct_ty); | 6819 | const union_llvm_ty = try o.lowerType(pt, struct_ty); |
| 6808 | const layout = struct_ty.unionGetLayout(zcu); | 6820 | const layout = struct_ty.unionGetLayout(zcu); |
| 6809 | const payload_index = @intFromBool(layout.tag_align.compare(.gte, layout.payload_align)); | 6821 | const payload_index = @intFromBool(layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)); |
| 6810 | const field_ptr = | 6822 | const field_ptr = |
| 6811 | try self.wip.gepStruct(union_llvm_ty, struct_llvm_val, payload_index, ""); | 6823 | try self.wip.gepStruct(union_llvm_ty, struct_llvm_val, payload_index, ""); |
| 6812 | const payload_alignment = layout.payload_align.toLlvm(); | 6824 | const payload_alignment = layout.payload_align.toLlvm(); |
| ... | @@ -11063,7 +11075,7 @@ pub const FuncGen = struct { | ... | @@ -11063,7 +11075,7 @@ pub const FuncGen = struct { |
| 11063 | .@"union" => { | 11075 | .@"union" => { |
| 11064 | const layout = struct_ty.unionGetLayout(zcu); | 11076 | const layout = struct_ty.unionGetLayout(zcu); |
| 11065 | if (layout.payload_size == 0 or struct_ty.containerLayout(zcu) == .@"packed") return struct_ptr; | 11077 | if (layout.payload_size == 0 or struct_ty.containerLayout(zcu) == .@"packed") return struct_ptr; |
| 11066 | const payload_index = @intFromBool(layout.tag_align.compare(.gte, layout.payload_align)); | 11078 | const payload_index = @intFromBool(layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)); |
| 11067 | const union_llvm_ty = try o.lowerType(pt, struct_ty); | 11079 | const union_llvm_ty = try o.lowerType(pt, struct_ty); |
| 11068 | return self.wip.gepStruct(union_llvm_ty, struct_ptr, payload_index, ""); | 11080 | return self.wip.gepStruct(union_llvm_ty, struct_ptr, payload_index, ""); |
| 11069 | }, | 11081 | }, |