authorgravatar for liljaanton2001@gmail.comantlilja <liljaanton2001@gmail.com> 2024-05-02 16:15:44+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-22 06:56:49-07:00
log7ce03acb9db361a2313ec4fb8477a2536530bede
tree3e212841129b2aae5de0565908209eca8d290229
parentc3aa32e98408c8e6e1578e573b8e2eef47fd4c54

LLVM: Fix panic when using tagged union backed by enum with negative values


2 files changed, 30 insertions(+), 5 deletions(-)

src/codegen/llvm.zig+8-5
......@@ -9997,20 +9997,21 @@ pub const FuncGen = struct {
99979997 return self.wip.conv(.unsigned, small_int_val, int_llvm_ty, "");
99989998 }
99999999
10000 const tag_int = blk: {
10000 const tag_int_val = blk: {
1000110001 const tag_ty = union_ty.unionTagTypeHypothetical(mod);
1000210002 const union_field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index];
1000310003 const enum_field_index = tag_ty.enumFieldIndex(union_field_name, mod).?;
1000410004 const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index);
10005 const tag_int_val = try tag_val.intFromEnum(tag_ty, mod);
10006 break :blk tag_int_val.toUnsignedInt(mod);
10005 break :blk try tag_val.intFromEnum(tag_ty, mod);
1000710006 };
1000810007 if (layout.payload_size == 0) {
1000910008 if (layout.tag_size == 0) {
1001010009 return .none;
1001110010 }
1001210011 assert(!isByRef(union_ty, mod));
10013 return o.builder.intValue(union_llvm_ty, tag_int);
10012 var big_int_space: Value.BigIntSpace = undefined;
10013 const tag_big_int = tag_int_val.toBigInt(&big_int_space, mod);
10014 return try o.builder.bigIntValue(union_llvm_ty, tag_big_int);
1001410015 }
1001510016 assert(isByRef(union_ty, mod));
1001610017 // The llvm type of the alloca will be the named LLVM union type, and will not
......@@ -10084,7 +10085,9 @@ pub const FuncGen = struct {
1008410085 const indices: [2]Builder.Value = .{ usize_zero, try o.builder.intValue(.i32, tag_index) };
1008510086 const field_ptr = try self.wip.gep(.inbounds, llvm_union_ty, result_ptr, &indices, "");
1008610087 const tag_ty = try o.lowerType(Type.fromInterned(union_obj.enum_tag_ty));
10087 const llvm_tag = try o.builder.intValue(tag_ty, tag_int);
10088 var big_int_space: Value.BigIntSpace = undefined;
10089 const tag_big_int = tag_int_val.toBigInt(&big_int_space, mod);
10090 const llvm_tag = try o.builder.bigIntValue(tag_ty, tag_big_int);
1008810091 const tag_alignment = Type.fromInterned(union_obj.enum_tag_ty).abiAlignment(mod).toLlvm();
1008910092 _ = try self.wip.store(.normal, llvm_tag, field_ptr, tag_alignment);
1009010093 }
test/behavior/union.zig+22
......@@ -2301,3 +2301,25 @@ test "matching captures causes union equivalence" {
23012301 comptime assert(@TypeOf(a) == @TypeOf(b));
23022302 try expect(a.u == b.u);
23032303}
2304
2305test "signed enum tag with negative value" {
2306 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2307 if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
2308 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2309 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2310 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2311
2312 const Enum = enum(i8) {
2313 a = -1,
2314 };
2315
2316 const Union = union(Enum) {
2317 a: i32,
2318 };
2319
2320 var i: i32 = 0;
2321 i = i;
2322 const e = Union{ .a = i };
2323
2324 try expect(e.a == i);
2325}