aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/llvm.zig
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2023-09-26 11:16:03 +0300
committerGitHub <noreply@github.com>2023-09-26 11:16:03 +0300
commitf4c884617f499b52eaecc0ef674609c774052f8f (patch)
treec24e4628c314d5e815f4b9796d0ff70335fa58a3 /src/codegen/llvm.zig
parent2adb932ad6ee4ff3d3c640cb8fb7bf7db0ff5d74 (diff)
parent9f4649b197b720dbc168ced25eee0805d3b678b1 (diff)
downloadzig-f4c884617f499b52eaecc0ef674609c774052f8f.tar.gz
zig-f4c884617f499b52eaecc0ef674609c774052f8f.zip
Merge pull request #17215 from kcbanner/read_from_memory_union
sema: add support for unions in readFromMemory and writeToMemory
Diffstat (limited to 'src/codegen/llvm.zig')
-rw-r--r--src/codegen/llvm.zig55
1 files changed, 36 insertions, 19 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index dc2e2f3859..bfbcac1e73 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -4108,25 +4108,28 @@ pub const Object = struct {
if (layout.payload_size == 0) return o.lowerValue(un.tag);
const union_obj = mod.typeToUnion(ty).?;
- const field_index = mod.unionTagFieldIndex(union_obj, un.tag.toValue()).?;
-
- const field_ty = union_obj.field_types.get(ip)[field_index].toType();
- if (union_obj.getLayout(ip) == .Packed) {
- if (!field_ty.hasRuntimeBits(mod)) return o.builder.intConst(union_ty, 0);
- const small_int_val = try o.builder.castConst(
- if (field_ty.isPtrAtRuntime(mod)) .ptrtoint else .bitcast,
- try o.lowerValue(un.val),
- try o.builder.intType(@intCast(field_ty.bitSize(mod))),
- );
- return o.builder.convConst(.unsigned, small_int_val, union_ty);
- }
+ const container_layout = union_obj.getLayout(ip);
+
+ var need_unnamed = false;
+ const payload = if (un.tag != .none) p: {
+ const field_index = mod.unionTagFieldIndex(union_obj, un.tag.toValue()).?;
+ const field_ty = union_obj.field_types.get(ip)[field_index].toType();
+ if (container_layout == .Packed) {
+ if (!field_ty.hasRuntimeBits(mod)) return o.builder.intConst(union_ty, 0);
+ const small_int_val = try o.builder.castConst(
+ if (field_ty.isPtrAtRuntime(mod)) .ptrtoint else .bitcast,
+ try o.lowerValue(un.val),
+ try o.builder.intType(@intCast(field_ty.bitSize(mod))),
+ );
+ return o.builder.convConst(.unsigned, small_int_val, union_ty);
+ }
+
+ // Sometimes we must make an unnamed struct because LLVM does
+ // not support bitcasting our payload struct to the true union payload type.
+ // Instead we use an unnamed struct and every reference to the global
+ // must pointer cast to the expected type before accessing the union.
+ need_unnamed = layout.most_aligned_field != field_index;
- // Sometimes we must make an unnamed struct because LLVM does
- // not support bitcasting our payload struct to the true union payload type.
- // Instead we use an unnamed struct and every reference to the global
- // must pointer cast to the expected type before accessing the union.
- var need_unnamed = layout.most_aligned_field != field_index;
- const payload = p: {
if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) {
const padding_len = layout.payload_size;
break :p try o.builder.undefConst(try o.builder.arrayType(padding_len, .i8));
@@ -4144,9 +4147,23 @@ pub const Object = struct {
try o.builder.structType(.@"packed", &.{ payload_ty, padding_ty }),
&.{ payload, try o.builder.undefConst(padding_ty) },
);
+ } else p: {
+ assert(layout.tag_size == 0);
+ const union_val = try o.lowerValue(un.val);
+ if (container_layout == .Packed) {
+ const bitcast_val = try o.builder.castConst(
+ .bitcast,
+ union_val,
+ try o.builder.intType(@intCast(ty.bitSize(mod))),
+ );
+ return o.builder.convConst(.unsigned, bitcast_val, union_ty);
+ }
+
+ need_unnamed = true;
+ break :p union_val;
};
- const payload_ty = payload.typeOf(&o.builder);
+ const payload_ty = payload.typeOf(&o.builder);
if (layout.tag_size == 0) return o.builder.structConst(if (need_unnamed)
try o.builder.structType(union_ty.structKind(&o.builder), &.{payload_ty})
else