authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-02 13:17:42+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-02 17:57:10+03:00
log7a8d9af4a94caeb74361c9462cd44a1e4356150b
treec1496557509bcd1aa9581e6541bfecd1374160dc
parent4462d082240d71e671a8d3d5fb3da81e70c4760e

stage2 llvm: correct handling of zero-bit types in unionFieldPtr

Pointers to zero-bit types are not zero-bit types so the function should return something. Closes #12716

2 files changed, 32 insertions(+), 7 deletions(-)

src/codegen/llvm.zig+4-7
......@@ -9051,7 +9051,7 @@ pub const FuncGen = struct {
90519051 }
90529052 },
90539053 },
9054 .Union => return self.unionFieldPtr(inst, struct_ptr, struct_ty, field_index),
9054 .Union => return self.unionFieldPtr(inst, struct_ptr, struct_ty),
90559055 else => unreachable,
90569056 }
90579057 }
......@@ -9061,16 +9061,13 @@ pub const FuncGen = struct {
90619061 inst: Air.Inst.Index,
90629062 union_ptr: *const llvm.Value,
90639063 union_ty: Type,
9064 field_index: c_uint,
90659064 ) !?*const llvm.Value {
9066 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
9067 const field = &union_obj.fields.values()[field_index];
90689065 const result_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst));
9069 if (!field.ty.hasRuntimeBitsIgnoreComptime()) {
9070 return null;
9071 }
90729066 const target = self.dg.module.getTarget();
90739067 const layout = union_ty.unionGetLayout(target);
9068 if (layout.payload_size == 0) {
9069 return self.builder.buildBitCast(union_ptr, result_llvm_ty, "");
9070 }
90749071 const payload_index = @boolToInt(layout.tag_align >= layout.payload_align);
90759072 const union_field_ptr = self.builder.buildStructGEP(union_ptr, payload_index, "");
90769073 return self.builder.buildBitCast(union_field_ptr, result_llvm_ty, "");
test/behavior/union.zig+28
......@@ -1352,3 +1352,31 @@ test "@unionInit uses tag value instead of field index" {
13521352 }
13531353 try expect(@enumToInt(u) == 255);
13541354}
1355
1356test "union field ptr - zero sized payload" {
1357 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1358 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1359 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1360
1361 const U = union {
1362 foo: void,
1363 bar: void,
1364 fn bar(_: *void) void {}
1365 };
1366 var u: U = .{ .foo = {} };
1367 U.bar(&u.foo);
1368}
1369
1370test "union field ptr - zero sized field" {
1371 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1372 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1373 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1374
1375 const U = union {
1376 foo: void,
1377 bar: u32,
1378 fn bar(_: *void) void {}
1379 };
1380 var u: U = .{ .foo = {} };
1381 U.bar(&u.foo);
1382}