diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-03-03 01:14:56 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-03-03 01:19:49 -0700 |
| commit | b33f3b23c98d7bb03b116fb084b35ce6b9fc1257 (patch) | |
| tree | 2ae27a2c1268e4112f3f5b38feeef7e4643af2b4 /src/Module.zig | |
| parent | 06b1a88a157dde8fdb9653aabda600cdeee2dd13 (diff) | |
| download | zig-b33f3b23c98d7bb03b116fb084b35ce6b9fc1257.tar.gz zig-b33f3b23c98d7bb03b116fb084b35ce6b9fc1257.zip | |
LLVM: fix lowering of unions and switches
`Module.Union.getLayout` now additionally returns a `padding` field
which tells how many bytes are between the final field end offset and
the ending offset of the union. This is used by the LLVM backend to
explicitly insert padding.
LLVM backend: lowering of unions now inserts additional padding so that
LLVM's internals will agree on the ABI size to match what ABI size zig
wants unions to be. This is an alternative to calling LLVMABISizeOfType
and LLVMABIAlignmentOfType which end up crashing when recursive struct
definitions come into play. We no longer ever call these two functions
and the bindings are deleted to avoid future footgun firings.
LLVM backend: lowering of unions now represents untagged unions
consistently. Before it was tripping an assertion.
LLVM backend: switch cases call inttoptr on the case items and condition
if necessary. Prevents tripping an LLVM assertion.
After this commit, we are no longer tripping over any LLVM assertions.
Diffstat (limited to 'src/Module.zig')
| -rw-r--r-- | src/Module.zig | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/src/Module.zig b/src/Module.zig index c122a2e3cd..33d5bb4c4c 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -1254,6 +1254,7 @@ pub const Union = struct { payload_align: u32, tag_align: u32, tag_size: u64, + padding: u32, }; pub fn haveLayout(u: Union) bool { @@ -1309,24 +1310,30 @@ pub const Union = struct { .payload_align = payload_align, .tag_align = 0, .tag_size = 0, + .padding = 0, }; // Put the tag before or after the payload depending on which one's // alignment is greater. const tag_size = u.tag_ty.abiSize(target); const tag_align = @maximum(1, u.tag_ty.abiAlignment(target)); var size: u64 = 0; + var padding: u32 = undefined; if (tag_align >= payload_align) { // {Tag, Payload} size += tag_size; size = std.mem.alignForwardGeneric(u64, size, payload_align); size += payload_size; + const prev_size = size; size = std.mem.alignForwardGeneric(u64, size, tag_align); + padding = @intCast(u32, size - prev_size); } else { // {Payload, Tag} size += payload_size; size = std.mem.alignForwardGeneric(u64, size, tag_align); size += tag_size; + const prev_size = size; size = std.mem.alignForwardGeneric(u64, size, payload_align); + padding = @intCast(u32, size - prev_size); } return .{ .abi_size = size, @@ -1338,6 +1345,7 @@ pub const Union = struct { .payload_align = payload_align, .tag_align = tag_align, .tag_size = tag_size, + .padding = padding, }; } }; |
