authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-08-22 10:17:58+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-08-22 11:16:36+03:00
logb0bcd4add29b6fbbe2bbc22719703d3c81ed594b
tree8604903fa493cc8f9f328ffcefcd2bcea2f8b8bb
parent74c7782c6083d398a4f0f126a4597c605d5223cd

Sema: allow optional pointers in packed structs

Closes #12572

3 files changed, 19 insertions(+), 4 deletions(-)

src/Sema.zig+1-1
...@@ -20565,8 +20565,8 @@ fn validatePackedType(ty: Type) bool {...@@ -20565,8 +20565,8 @@ fn validatePackedType(ty: Type) bool {
20565 .AnyFrame,20565 .AnyFrame,
20566 .Fn,20566 .Fn,
20567 .Array,20567 .Array,
20568 .Optional,
20569 => return false,20568 => return false,
20569 .Optional => return ty.isPtrLikeOptional(),
20570 .Void,20570 .Void,
20571 .Bool,20571 .Bool,
20572 .Float,20572 .Float,
src/codegen/llvm.zig+6-3
...@@ -3417,7 +3417,10 @@ pub const DeclGen = struct {...@@ -3417,7 +3417,10 @@ pub const DeclGen = struct {
3417 });3417 });
3418 const ty_bit_size = @intCast(u16, field.ty.bitSize(target));3418 const ty_bit_size = @intCast(u16, field.ty.bitSize(target));
3419 const small_int_ty = dg.context.intType(ty_bit_size);3419 const small_int_ty = dg.context.intType(ty_bit_size);
3420 const small_int_val = non_int_val.constBitCast(small_int_ty);3420 const small_int_val = if (field.ty.isPtrAtRuntime())
3421 non_int_val.constPtrToInt(small_int_ty)
3422 else
3423 non_int_val.constBitCast(small_int_ty);
3421 const shift_rhs = int_llvm_ty.constInt(running_bits, .False);3424 const shift_rhs = int_llvm_ty.constInt(running_bits, .False);
3422 // If the field is as large as the entire packed struct, this3425 // If the field is as large as the entire packed struct, this
3423 // zext would go from, e.g. i16 to i16. This is legal with3426 // zext would go from, e.g. i16 to i16. This is legal with
...@@ -5343,7 +5346,7 @@ pub const FuncGen = struct {...@@ -5343,7 +5346,7 @@ pub const FuncGen = struct {
5343 const same_size_int = self.context.intType(elem_bits);5346 const same_size_int = self.context.intType(elem_bits);
5344 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");5347 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");
5345 return self.builder.buildBitCast(truncated_int, elem_llvm_ty, "");5348 return self.builder.buildBitCast(truncated_int, elem_llvm_ty, "");
5346 } else if (field_ty.zigTypeTag() == .Pointer) {5349 } else if (field_ty.isPtrAtRuntime()) {
5347 const elem_bits = @intCast(c_uint, field_ty.bitSize(target));5350 const elem_bits = @intCast(c_uint, field_ty.bitSize(target));
5348 const same_size_int = self.context.intType(elem_bits);5351 const same_size_int = self.context.intType(elem_bits);
5349 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");5352 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");
...@@ -8408,7 +8411,7 @@ pub const FuncGen = struct {...@@ -8408,7 +8411,7 @@ pub const FuncGen = struct {
8408 const non_int_val = try self.resolveInst(elem);8411 const non_int_val = try self.resolveInst(elem);
8409 const ty_bit_size = @intCast(u16, field.ty.bitSize(target));8412 const ty_bit_size = @intCast(u16, field.ty.bitSize(target));
8410 const small_int_ty = self.dg.context.intType(ty_bit_size);8413 const small_int_ty = self.dg.context.intType(ty_bit_size);
8411 const small_int_val = if (field.ty.zigTypeTag() == .Pointer)8414 const small_int_val = if (field.ty.isPtrAtRuntime())
8412 self.builder.buildPtrToInt(non_int_val, small_int_ty, "")8415 self.builder.buildPtrToInt(non_int_val, small_int_ty, "")
8413 else8416 else
8414 self.builder.buildBitCast(non_int_val, small_int_ty, "");8417 self.builder.buildBitCast(non_int_val, small_int_ty, "");
test/behavior/packed-struct.zig+12
...@@ -434,3 +434,15 @@ test "@ptrToInt on a packed struct field" {...@@ -434,3 +434,15 @@ test "@ptrToInt on a packed struct field" {
434 };434 };
435 try expect(@ptrToInt(&S.p0.z) - @ptrToInt(&S.p0.x) == 2);435 try expect(@ptrToInt(&S.p0.z) - @ptrToInt(&S.p0.x) == 2);
436}436}
437
438test "optional pointer in packed struct" {
439 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
440 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
441 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
442 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
443
444 const T = packed struct { ptr: ?*const u8 };
445 var n: u8 = 0;
446 const x = T{ .ptr = &n };
447 try expect(x.ptr.? == &n);
448}