mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 08:33:06 +00:00
stage2: LLVM backend: fix const packed structs
When doing LLVM const bit shifting we must make sure the integer bit sizes are wide enough or else LLVM gives us a poison result.
This commit is contained in:
parent
3abe464b06
commit
886df772f0
@ -1361,10 +1361,12 @@ pub const DeclGen = struct {
|
||||
.val = field_val,
|
||||
});
|
||||
const ty_bit_size = @intCast(u16, field.ty.bitSize(target));
|
||||
const llvm_int_ty = dg.context.intType(ty_bit_size);
|
||||
const int_val = non_int_val.constBitCast(llvm_int_ty);
|
||||
const shift_rhs = llvm_int_ty.constInt(running_bits, .False);
|
||||
const shifted = int_val.constShl(shift_rhs);
|
||||
const small_int_ty = dg.context.intType(ty_bit_size);
|
||||
const small_int_val = non_int_val.constBitCast(small_int_ty);
|
||||
const big_int_ty = running_int.typeOf();
|
||||
const shift_rhs = big_int_ty.constInt(running_bits, .False);
|
||||
const extended_int_val = small_int_val.constZExt(big_int_ty);
|
||||
const shifted = extended_int_val.constShl(shift_rhs);
|
||||
running_int = running_int.constOr(shifted);
|
||||
running_bits += ty_bit_size;
|
||||
} else {
|
||||
|
@ -201,6 +201,11 @@ pub const Value = opaque {
|
||||
|
||||
pub const addCase = LLVMAddCase;
|
||||
extern fn LLVMAddCase(Switch: *const Value, OnVal: *const Value, Dest: *const BasicBlock) void;
|
||||
|
||||
pub inline fn isPoison(Val: *const Value) bool {
|
||||
return LLVMIsPoison(Val).toBool();
|
||||
}
|
||||
extern fn LLVMIsPoison(Val: *const Value) Bool;
|
||||
};
|
||||
|
||||
pub const Type = opaque {
|
||||
|
@ -21,7 +21,7 @@ test {
|
||||
_ = @import("behavior/usingnamespace.zig");
|
||||
|
||||
// Tests that pass for stage1, stage2 and the C backend, but not for the wasm backend
|
||||
if (!builtin.zig_is_stage2 or (builtin.zig_is_stage2 and builtin.stage2_arch != .wasm32)) {
|
||||
if (!builtin.zig_is_stage2 or builtin.stage2_arch != .wasm32) {
|
||||
_ = @import("behavior/align.zig");
|
||||
_ = @import("behavior/bool.zig");
|
||||
_ = @import("behavior/bugs/704.zig");
|
||||
|
@ -47,3 +47,46 @@ test "enum literal casting to optional" {
|
||||
|
||||
try expect(bar.? == Bar.B);
|
||||
}
|
||||
|
||||
const A = enum(u3) { One, Two, Three, Four, One2, Two2, Three2, Four2 };
|
||||
const B = enum(u3) { One3, Two3, Three3, Four3, One23, Two23, Three23, Four23 };
|
||||
const C = enum(u2) { One4, Two4, Three4, Four4 };
|
||||
|
||||
const BitFieldOfEnums = packed struct {
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
};
|
||||
|
||||
const bit_field_1 = BitFieldOfEnums{
|
||||
.a = A.Two,
|
||||
.b = B.Three3,
|
||||
.c = C.Four4,
|
||||
};
|
||||
|
||||
test "bit field access with enum fields" {
|
||||
var data = bit_field_1;
|
||||
try expect(getA(&data) == A.Two);
|
||||
try expect(getB(&data) == B.Three3);
|
||||
try expect(getC(&data) == C.Four4);
|
||||
comptime try expect(@sizeOf(BitFieldOfEnums) == 1);
|
||||
|
||||
data.b = B.Four3;
|
||||
try expect(data.b == B.Four3);
|
||||
|
||||
data.a = A.Three;
|
||||
try expect(data.a == A.Three);
|
||||
try expect(data.b == B.Four3);
|
||||
}
|
||||
|
||||
fn getA(data: *const BitFieldOfEnums) A {
|
||||
return data.a;
|
||||
}
|
||||
|
||||
fn getB(data: *const BitFieldOfEnums) B {
|
||||
return data.b;
|
||||
}
|
||||
|
||||
fn getC(data: *const BitFieldOfEnums) C {
|
||||
return data.c;
|
||||
}
|
||||
|
@ -2,63 +2,6 @@ const expect = @import("std").testing.expect;
|
||||
const mem = @import("std").mem;
|
||||
const Tag = @import("std").meta.Tag;
|
||||
|
||||
const Small2 = enum(u2) { One, Two };
|
||||
|
||||
const A = enum(u3) { One, Two, Three, Four, One2, Two2, Three2, Four2 };
|
||||
const B = enum(u3) { One3, Two3, Three3, Four3, One23, Two23, Three23, Four23 };
|
||||
const C = enum(u2) { One4, Two4, Three4, Four4 };
|
||||
|
||||
const BitFieldOfEnums = packed struct {
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
};
|
||||
|
||||
const bit_field_1 = BitFieldOfEnums{
|
||||
.a = A.Two,
|
||||
.b = B.Three3,
|
||||
.c = C.Four4,
|
||||
};
|
||||
|
||||
test "bit field access with enum fields" {
|
||||
var data = bit_field_1;
|
||||
try expect(getA(&data) == A.Two);
|
||||
try expect(getB(&data) == B.Three3);
|
||||
try expect(getC(&data) == C.Four4);
|
||||
comptime try expect(@sizeOf(BitFieldOfEnums) == 1);
|
||||
|
||||
data.b = B.Four3;
|
||||
try expect(data.b == B.Four3);
|
||||
|
||||
data.a = A.Three;
|
||||
try expect(data.a == A.Three);
|
||||
try expect(data.b == B.Four3);
|
||||
}
|
||||
|
||||
fn getA(data: *const BitFieldOfEnums) A {
|
||||
return data.a;
|
||||
}
|
||||
|
||||
fn getB(data: *const BitFieldOfEnums) B {
|
||||
return data.b;
|
||||
}
|
||||
|
||||
fn getC(data: *const BitFieldOfEnums) C {
|
||||
return data.c;
|
||||
}
|
||||
|
||||
const MultipleChoice2 = enum(u32) {
|
||||
Unspecified1,
|
||||
A = 20,
|
||||
Unspecified2,
|
||||
B = 40,
|
||||
Unspecified3,
|
||||
C = 60,
|
||||
Unspecified4,
|
||||
D = 1000,
|
||||
Unspecified5,
|
||||
};
|
||||
|
||||
const EnumWithOneMember = enum { Eof };
|
||||
|
||||
fn doALoopThing(id: EnumWithOneMember) void {
|
||||
|
Loading…
Reference in New Issue
Block a user