aboutsummaryrefslogtreecommitdiff
path: root/src/Module.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-03-03 01:14:56 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-03-03 01:19:49 -0700
commitb33f3b23c98d7bb03b116fb084b35ce6b9fc1257 (patch)
tree2ae27a2c1268e4112f3f5b38feeef7e4643af2b4 /src/Module.zig
parent06b1a88a157dde8fdb9653aabda600cdeee2dd13 (diff)
downloadzig-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.zig8
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,
};
}
};