authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-27 15:37:48+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-29 15:47:02+02:00
log6f9c7e33b956686ebfd4690c7f85a602d0ac9ffe
tree879c716f577683a11a8e36a029c515160ca81532
parent34be5784a3f19658d15d1fb24bb07800cdb025c4

llvm: implement `union_init` for packed unions

Closes #13664

3 files changed, 43 insertions(+), 0 deletions(-)

src/codegen/llvm.zig+15
...@@ -9228,6 +9228,21 @@ pub const FuncGen = struct {...@@ -9228,6 +9228,21 @@ pub const FuncGen = struct {
9228 const target = self.dg.module.getTarget();9228 const target = self.dg.module.getTarget();
9229 const layout = union_ty.unionGetLayout(target);9229 const layout = union_ty.unionGetLayout(target);
9230 const union_obj = union_ty.cast(Type.Payload.Union).?.data;9230 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
9231
9232 if (union_obj.layout == .Packed) {
9233 const big_bits = union_ty.bitSize(target);
9234 const int_llvm_ty = self.dg.context.intType(@intCast(c_uint, big_bits));
9235 const field = union_obj.fields.values()[extra.field_index];
9236 const non_int_val = try self.resolveInst(extra.init);
9237 const ty_bit_size = @intCast(u16, field.ty.bitSize(target));
9238 const small_int_ty = self.dg.context.intType(ty_bit_size);
9239 const small_int_val = if (field.ty.isPtrAtRuntime())
9240 self.builder.buildPtrToInt(non_int_val, small_int_ty, "")
9241 else
9242 self.builder.buildBitCast(non_int_val, small_int_ty, "");
9243 return self.builder.buildZExtOrBitCast(small_int_val, int_llvm_ty, "");
9244 }
9245
9231 const tag_int = blk: {9246 const tag_int = blk: {
9232 const tag_ty = union_ty.unionTagTypeHypothetical();9247 const tag_ty = union_ty.unionTagTypeHypothetical();
9233 const union_field_name = union_obj.fields.keys()[extra.field_index];9248 const union_field_name = union_obj.fields.keys()[extra.field_index];
test/behavior.zig+1
...@@ -116,6 +116,7 @@ test {...@@ -116,6 +116,7 @@ test {
116 _ = @import("behavior/bugs/13171.zig");116 _ = @import("behavior/bugs/13171.zig");
117 _ = @import("behavior/bugs/13285.zig");117 _ = @import("behavior/bugs/13285.zig");
118 _ = @import("behavior/bugs/13435.zig");118 _ = @import("behavior/bugs/13435.zig");
119 _ = @import("behavior/bugs/13664.zig");
119 _ = @import("behavior/byteswap.zig");120 _ = @import("behavior/byteswap.zig");
120 _ = @import("behavior/byval_arg_var.zig");121 _ = @import("behavior/byval_arg_var.zig");
121 _ = @import("behavior/call.zig");122 _ = @import("behavior/call.zig");
test/behavior/bugs/13664.zig created+27
...@@ -0,0 +1,27 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4const Fields = packed struct {
5 timestamp: u50,
6 random_bits: u13,
7};
8const ID = packed union {
9 value: u63,
10 fields: Fields,
11};
12fn value() i64 {
13 return 1341;
14}
15test {
16 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
17 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
18 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
20
21 const timestamp: i64 = value();
22 const id = ID{ .fields = Fields{
23 .timestamp = @intCast(u50, timestamp),
24 .random_bits = 420,
25 } };
26 try std.testing.expect((ID{ .value = id.value }).fields.timestamp == timestamp);
27}