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

This commit is contained in:
Anton Lilja 2024-05-02 16:15:44 +02:00 committed by GitHub
parent 5571c03a5a
commit 20b9b54e6b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 30 additions and 5 deletions

View File

@ -10091,20 +10091,21 @@ pub const FuncGen = struct {
return self.wip.conv(.unsigned, small_int_val, int_llvm_ty, "");
}
const tag_int = blk: {
const tag_int_val = blk: {
const tag_ty = union_ty.unionTagTypeHypothetical(mod);
const union_field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index];
const enum_field_index = tag_ty.enumFieldIndex(union_field_name, mod).?;
const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index);
const tag_int_val = try tag_val.intFromEnum(tag_ty, mod);
break :blk tag_int_val.toUnsignedInt(mod);
break :blk try tag_val.intFromEnum(tag_ty, mod);
};
if (layout.payload_size == 0) {
if (layout.tag_size == 0) {
return .none;
}
assert(!isByRef(union_ty, mod));
return o.builder.intValue(union_llvm_ty, tag_int);
var big_int_space: Value.BigIntSpace = undefined;
const tag_big_int = tag_int_val.toBigInt(&big_int_space, mod);
return try o.builder.bigIntValue(union_llvm_ty, tag_big_int);
}
assert(isByRef(union_ty, mod));
// The llvm type of the alloca will be the named LLVM union type, and will not
@ -10178,7 +10179,9 @@ pub const FuncGen = struct {
const indices: [2]Builder.Value = .{ usize_zero, try o.builder.intValue(.i32, tag_index) };
const field_ptr = try self.wip.gep(.inbounds, llvm_union_ty, result_ptr, &indices, "");
const tag_ty = try o.lowerType(Type.fromInterned(union_obj.enum_tag_ty));
const llvm_tag = try o.builder.intValue(tag_ty, tag_int);
var big_int_space: Value.BigIntSpace = undefined;
const tag_big_int = tag_int_val.toBigInt(&big_int_space, mod);
const llvm_tag = try o.builder.bigIntValue(tag_ty, tag_big_int);
const tag_alignment = Type.fromInterned(union_obj.enum_tag_ty).abiAlignment(mod).toLlvm();
_ = try self.wip.store(.normal, llvm_tag, field_ptr, tag_alignment);
}

View File

@ -2301,3 +2301,25 @@ test "matching captures causes union equivalence" {
comptime assert(@TypeOf(a) == @TypeOf(b));
try expect(a.u == b.u);
}
test "signed enum tag with negative value" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const Enum = enum(i8) {
a = -1,
};
const Union = union(Enum) {
a: i32,
};
var i: i32 = 0;
i = i;
const e = Union{ .a = i };
try expect(e.a == i);
}