mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
LLVM: handle aggregate_init for packed structs
This commit is contained in:
parent
052079c994
commit
6d2ec7a4e3
@ -6459,6 +6459,34 @@ pub const FuncGen = struct {
|
|||||||
return vector;
|
return vector;
|
||||||
},
|
},
|
||||||
.Struct => {
|
.Struct => {
|
||||||
|
if (result_ty.containerLayout() == .Packed) {
|
||||||
|
const struct_obj = result_ty.castTag(.@"struct").?.data;
|
||||||
|
const big_bits = struct_obj.packedIntegerBits(target);
|
||||||
|
const int_llvm_ty = self.dg.context.intType(big_bits);
|
||||||
|
const fields = struct_obj.fields.values();
|
||||||
|
comptime assert(Type.packed_struct_layout_version == 2);
|
||||||
|
var running_int: *const llvm.Value = int_llvm_ty.constNull();
|
||||||
|
var running_bits: u16 = 0;
|
||||||
|
for (elements) |elem, i| {
|
||||||
|
const field = fields[i];
|
||||||
|
if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue;
|
||||||
|
|
||||||
|
const non_int_val = try self.resolveInst(elem);
|
||||||
|
const ty_bit_size = @intCast(u16, field.ty.bitSize(target));
|
||||||
|
const small_int_ty = self.dg.context.intType(ty_bit_size);
|
||||||
|
const small_int_val = self.builder.buildBitCast(non_int_val, small_int_ty, "");
|
||||||
|
const shift_rhs = int_llvm_ty.constInt(running_bits, .False);
|
||||||
|
// If the field is as large as the entire packed struct, this
|
||||||
|
// zext would go from, e.g. i16 to i16. This is legal with
|
||||||
|
// constZExtOrBitCast but not legal with constZExt.
|
||||||
|
const extended_int_val = self.builder.buildZExtOrBitCast(small_int_val, int_llvm_ty, "");
|
||||||
|
const shifted = self.builder.buildShl(extended_int_val, shift_rhs, "");
|
||||||
|
running_int = self.builder.buildOr(running_int, shifted, "");
|
||||||
|
running_bits += ty_bit_size;
|
||||||
|
}
|
||||||
|
return running_int;
|
||||||
|
}
|
||||||
|
|
||||||
var ptr_ty_buf: Type.Payload.Pointer = undefined;
|
var ptr_ty_buf: Type.Payload.Pointer = undefined;
|
||||||
|
|
||||||
if (isByRef(result_ty)) {
|
if (isByRef(result_ty)) {
|
||||||
|
|||||||
@ -448,6 +448,14 @@ pub const Builder = opaque {
|
|||||||
Name: [*:0]const u8,
|
Name: [*:0]const u8,
|
||||||
) *const Value;
|
) *const Value;
|
||||||
|
|
||||||
|
pub const buildZExtOrBitCast = LLVMBuildZExtOrBitCast;
|
||||||
|
extern fn LLVMBuildZExtOrBitCast(
|
||||||
|
*const Builder,
|
||||||
|
Val: *const Value,
|
||||||
|
DestTy: *const Type,
|
||||||
|
Name: [*:0]const u8,
|
||||||
|
) *const Value;
|
||||||
|
|
||||||
pub const buildSExt = LLVMBuildSExt;
|
pub const buildSExt = LLVMBuildSExt;
|
||||||
extern fn LLVMBuildSExt(
|
extern fn LLVMBuildSExt(
|
||||||
*const Builder,
|
*const Builder,
|
||||||
|
|||||||
@ -1294,3 +1294,24 @@ test "loading a struct pointer perfoms a copy" {
|
|||||||
try expect(s2.b == 2);
|
try expect(s2.b == 2);
|
||||||
try expect(s2.c == 3);
|
try expect(s2.c == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "packed struct aggregate init" {
|
||||||
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
|
|
||||||
|
const S = struct {
|
||||||
|
fn foo(a: i2, b: i6) u8 {
|
||||||
|
return @bitCast(u8, P{ .a = a, .b = b });
|
||||||
|
}
|
||||||
|
|
||||||
|
const P = packed struct {
|
||||||
|
a: i2,
|
||||||
|
b: i6,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const result = @bitCast(u8, S.foo(1, 2));
|
||||||
|
try expect(result == 9);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user