| author | |
| committer | |
| log | 6d2ec7a4e39e3464bb5f14747937df9544e89ee7 |
| tree | 2fe3eaaef62f7cc9fb3c52aec6d7acf707786281 |
| parent | 052079c99455d01312d377d72fa1b8b5c0b22aad |
3 files changed, 57 insertions(+), 0 deletions(-)
src/codegen/llvm.zig+28| ... | @@ -6459,6 +6459,34 @@ pub const FuncGen = struct { | ... | @@ -6459,6 +6459,34 @@ pub const FuncGen = struct { |
| 6459 | return vector; | 6459 | return vector; |
| 6460 | }, | 6460 | }, |
| 6461 | .Struct => { | 6461 | .Struct => { |
| 6462 | if (result_ty.containerLayout() == .Packed) { | ||
| 6463 | const struct_obj = result_ty.castTag(.@"struct").?.data; | ||
| 6464 | const big_bits = struct_obj.packedIntegerBits(target); | ||
| 6465 | const int_llvm_ty = self.dg.context.intType(big_bits); | ||
| 6466 | const fields = struct_obj.fields.values(); | ||
| 6467 | comptime assert(Type.packed_struct_layout_version == 2); | ||
| 6468 | var running_int: *const llvm.Value = int_llvm_ty.constNull(); | ||
| 6469 | var running_bits: u16 = 0; | ||
| 6470 | for (elements) |elem, i| { | ||
| 6471 | const field = fields[i]; | ||
| 6472 | if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue; | ||
| 6473 | |||
| 6474 | const non_int_val = try self.resolveInst(elem); | ||
| 6475 | const ty_bit_size = @intCast(u16, field.ty.bitSize(target)); | ||
| 6476 | const small_int_ty = self.dg.context.intType(ty_bit_size); | ||
| 6477 | const small_int_val = self.builder.buildBitCast(non_int_val, small_int_ty, ""); | ||
| 6478 | const shift_rhs = int_llvm_ty.constInt(running_bits, .False); | ||
| 6479 | // If the field is as large as the entire packed struct, this | ||
| 6480 | // zext would go from, e.g. i16 to i16. This is legal with | ||
| 6481 | // constZExtOrBitCast but not legal with constZExt. | ||
| 6482 | const extended_int_val = self.builder.buildZExtOrBitCast(small_int_val, int_llvm_ty, ""); | ||
| 6483 | const shifted = self.builder.buildShl(extended_int_val, shift_rhs, ""); | ||
| 6484 | running_int = self.builder.buildOr(running_int, shifted, ""); | ||
| 6485 | running_bits += ty_bit_size; | ||
| 6486 | } | ||
| 6487 | return running_int; | ||
| 6488 | } | ||
| 6489 | |||
| 6462 | var ptr_ty_buf: Type.Payload.Pointer = undefined; | 6490 | var ptr_ty_buf: Type.Payload.Pointer = undefined; |
| 6463 | 6491 | ||
| 6464 | if (isByRef(result_ty)) { | 6492 | if (isByRef(result_ty)) { |
src/codegen/llvm/bindings.zig+8| ... | @@ -448,6 +448,14 @@ pub const Builder = opaque { | ... | @@ -448,6 +448,14 @@ pub const Builder = opaque { |
| 448 | Name: [*:0]const u8, | 448 | Name: [*:0]const u8, |
| 449 | ) *const Value; | 449 | ) *const Value; |
| 450 | 450 | ||
| 451 | pub const buildZExtOrBitCast = LLVMBuildZExtOrBitCast; | ||
| 452 | extern fn LLVMBuildZExtOrBitCast( | ||
| 453 | *const Builder, | ||
| 454 | Val: *const Value, | ||
| 455 | DestTy: *const Type, | ||
| 456 | Name: [*:0]const u8, | ||
| 457 | ) *const Value; | ||
| 458 | |||
| 451 | pub const buildSExt = LLVMBuildSExt; | 459 | pub const buildSExt = LLVMBuildSExt; |
| 452 | extern fn LLVMBuildSExt( | 460 | extern fn LLVMBuildSExt( |
| 453 | *const Builder, | 461 | *const Builder, |
test/behavior/struct.zig+21| ... | @@ -1294,3 +1294,24 @@ test "loading a struct pointer perfoms a copy" { | ... | @@ -1294,3 +1294,24 @@ test "loading a struct pointer perfoms a copy" { |
| 1294 | try expect(s2.b == 2); | 1294 | try expect(s2.b == 2); |
| 1295 | try expect(s2.c == 3); | 1295 | try expect(s2.c == 3); |
| 1296 | } | 1296 | } |
| 1297 | |||
| 1298 | test "packed struct aggregate init" { | ||
| 1299 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 1300 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 1301 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 1302 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 1303 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 1304 | |||
| 1305 | const S = struct { | ||
| 1306 | fn foo(a: i2, b: i6) u8 { | ||
| 1307 | return @bitCast(u8, P{ .a = a, .b = b }); | ||
| 1308 | } | ||
| 1309 | |||
| 1310 | const P = packed struct { | ||
| 1311 | a: i2, | ||
| 1312 | b: i6, | ||
| 1313 | }; | ||
| 1314 | }; | ||
| 1315 | const result = @bitCast(u8, S.foo(1, 2)); | ||
| 1316 | try expect(result == 9); | ||
| 1317 | } |