| ... | ... | @@ -26698,21 +26698,25 @@ fn structFieldPtrByIndex( |
| 26698 | 26698 | } |
| 26699 | 26699 | } |
| 26700 | 26700 | } else if (struct_type.layout == .Extern) { |
| 26701 | | // For extern structs, field aligment might be bigger than type's natural alignment. Eg, in |
| 26702 | | // `extern struct { x: u32, y: u16 }` the second field is aligned as u32. |
| 26701 | // For extern structs, field alignment might be bigger than type's |
| 26702 | // natural alignment. Eg, in `extern struct { x: u32, y: u16 }` the |
| 26703 | // second field is aligned as u32. |
| 26703 | 26704 | const field_offset = struct_ty.structFieldOffset(field_index, mod); |
| 26704 | 26705 | ptr_ty_data.flags.alignment = if (parent_align == .none) |
| 26705 | 26706 | .none |
| 26706 | 26707 | else |
| 26707 | 26708 | @enumFromInt(@min(@intFromEnum(parent_align), @ctz(field_offset))); |
| 26708 | 26709 | } else { |
| 26709 | | // Our alignment is capped at the field alignment |
| 26710 | // Our alignment is capped at the field alignment. |
| 26710 | 26711 | const field_align = try sema.structFieldAlignment( |
| 26711 | 26712 | struct_type.fieldAlign(ip, field_index), |
| 26712 | 26713 | field_ty.toType(), |
| 26713 | 26714 | struct_type.layout, |
| 26714 | 26715 | ); |
| 26715 | | ptr_ty_data.flags.alignment = field_align.min(parent_align); |
| 26716 | ptr_ty_data.flags.alignment = if (struct_ptr_ty_info.flags.alignment == .none) |
| 26717 | field_align |
| 26718 | else |
| 26719 | field_align.min(parent_align); |
| 26716 | 26720 | } |
| 26717 | 26721 | |
| 26718 | 26722 | const ptr_field_ty = try sema.ptrType(ptr_ty_data); |
| ... | ... | @@ -28635,8 +28639,8 @@ const InMemoryCoercionResult = union(enum) { |
| 28635 | 28639 | break; |
| 28636 | 28640 | }, |
| 28637 | 28641 | .ptr_alignment => |pair| { |
| 28638 | | try sema.errNote(block, src, msg, "pointer alignment '{}' cannot cast into pointer alignment '{}'", .{ |
| 28639 | | pair.actual, pair.wanted, |
| 28642 | try sema.errNote(block, src, msg, "pointer alignment '{d}' cannot cast into pointer alignment '{d}'", .{ |
| 28643 | pair.actual.toByteUnits(0), pair.wanted.toByteUnits(0), |
| 28640 | 28644 | }); |
| 28641 | 28645 | break; |
| 28642 | 28646 | }, |
| ... | ... | @@ -34307,20 +34311,29 @@ pub fn resolveStructAlignment( |
| 34307 | 34311 | |
| 34308 | 34312 | try sema.resolveTypeFieldsStruct(ty, struct_type); |
| 34309 | 34313 | |
| 34314 | if (struct_type.setAlignmentWip(ip)) { |
| 34315 | // We'll guess "pointer-aligned", if the struct has an |
| 34316 | // underaligned pointer field then some allocations |
| 34317 | // might require explicit alignment. |
| 34318 | //TODO write this bit and emit an error later if incorrect |
| 34319 | //struct_type.flagsPtr(ip).assumed_pointer_aligned = true; |
| 34320 | const result = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)); |
| 34321 | struct_type.flagsPtr(ip).alignment = result; |
| 34322 | return result; |
| 34323 | } |
| 34324 | |
| 34310 | 34325 | var result: Alignment = .@"1"; |
| 34311 | 34326 | |
| 34312 | 34327 | for (0..struct_type.field_types.len) |i| { |
| 34313 | | if (struct_type.fieldIsComptime(ip, i)) continue; |
| 34314 | 34328 | const field_ty = struct_type.field_types.get(ip)[i].toType(); |
| 34315 | | if (try sema.typeRequiresComptime(field_ty)) continue; |
| 34316 | | if (try sema.typeHasRuntimeBits(field_ty)) { |
| 34317 | | const field_align = try sema.structFieldAlignment( |
| 34318 | | struct_type.fieldAlign(ip, i), |
| 34319 | | field_ty, |
| 34320 | | struct_type.layout, |
| 34321 | | ); |
| 34322 | | result = result.max(field_align); |
| 34323 | | } |
| 34329 | if (struct_type.fieldIsComptime(ip, i) or try sema.typeRequiresComptime(field_ty)) |
| 34330 | continue; |
| 34331 | const field_align = try sema.structFieldAlignment( |
| 34332 | struct_type.fieldAlign(ip, i), |
| 34333 | field_ty, |
| 34334 | struct_type.layout, |
| 34335 | ); |
| 34336 | result = result.max(field_align); |
| 34324 | 34337 | } |
| 34325 | 34338 | |
| 34326 | 34339 | struct_type.flagsPtr(ip).alignment = result; |
| ... | ... | @@ -34358,7 +34371,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 34358 | 34371 | |
| 34359 | 34372 | for (aligns, sizes, 0..) |*field_align, *field_size, i| { |
| 34360 | 34373 | const field_ty = struct_type.field_types.get(ip)[i].toType(); |
| 34361 | | if (struct_type.fieldIsComptime(ip, i) or !(try sema.typeHasRuntimeBits(field_ty))) { |
| 34374 | if (struct_type.fieldIsComptime(ip, i) or try sema.typeRequiresComptime(field_ty)) { |
| 34362 | 34375 | struct_type.offsets.get(ip)[i] = 0; |
| 34363 | 34376 | field_size.* = 0; |
| 34364 | 34377 | field_align.* = .none; |
| ... | ... | @@ -34439,10 +34452,8 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 34439 | 34452 | var offset: u64 = 0; |
| 34440 | 34453 | var big_align: Alignment = .@"1"; |
| 34441 | 34454 | while (it.next()) |i| { |
| 34442 | | const field_ty = struct_type.field_types.get(ip)[i].toType(); |
| 34443 | | // Type query definitely valid as we performed it earlier |
| 34444 | | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue; |
| 34445 | | big_align = big_align.max(aligns[i]); |
| 34455 | if (aligns[i] == .none) continue; |
| 34456 | big_align = big_align.maxStrict(aligns[i]); |
| 34446 | 34457 | offsets[i] = @intCast(aligns[i].forward(offset)); |
| 34447 | 34458 | offset = offsets[i] + sizes[i]; |
| 34448 | 34459 | } |
| ... | ... | @@ -36870,7 +36881,7 @@ fn structFieldAlignment( |
| 36870 | 36881 | // extern |
| 36871 | 36882 | const ty_abi_align = try sema.typeAbiAlignment(field_ty); |
| 36872 | 36883 | if (field_ty.isAbiInt(mod) and field_ty.intInfo(mod).bits >= 128) { |
| 36873 | | return ty_abi_align.max(.@"16"); |
| 36884 | return ty_abi_align.maxStrict(.@"16"); |
| 36874 | 36885 | } |
| 36875 | 36886 | return ty_abi_align; |
| 36876 | 36887 | } |