mirror of
https://github.com/ziglang/zig.git
synced 2024-11-27 07:32:44 +00:00
LLVM: Fix panic when using tagged union backed by enum with negative values
This commit is contained in:
parent
5571c03a5a
commit
20b9b54e6b
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user