aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-07-20 16:13:36 +0300
committerVeikka Tuominen <git@vexu.eu>2022-07-20 17:07:12 +0300
commitd41dd499a9fd42be3a30018dccb6a9a9fbf43f3d (patch)
treeb87a16047c8c386c3458ed12c37ea8c3dba73570
parentde62bd06472e5603fd2afb6f50d688d54f4098b4 (diff)
downloadzig-d41dd499a9fd42be3a30018dccb6a9a9fbf43f3d.tar.gz
zig-d41dd499a9fd42be3a30018dccb6a9a9fbf43f3d.zip
stage2 llvm: fix handling of pointer fields in packed structs
-rw-r--r--src/codegen/llvm.zig10
-rw-r--r--test/behavior/packed-struct.zig21
2 files changed, 30 insertions, 1 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 53c97c880f..9dc20755eb 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -5149,6 +5149,11 @@ pub const FuncGen = struct {
const same_size_int = self.context.intType(elem_bits);
const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");
return self.builder.buildBitCast(truncated_int, elem_llvm_ty, "");
+ } else if (field_ty.zigTypeTag() == .Pointer) {
+ const elem_bits = @intCast(c_uint, field_ty.bitSize(target));
+ const same_size_int = self.context.intType(elem_bits);
+ const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");
+ return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, "");
}
return self.builder.buildTrunc(shifted_value, elem_llvm_ty, "");
},
@@ -7999,7 +8004,10 @@ pub const FuncGen = struct {
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 small_int_val = if (field.ty.zigTypeTag() == .Pointer)
+ self.builder.buildPtrToInt(non_int_val, small_int_ty, "")
+ else
+ 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
diff --git a/test/behavior/packed-struct.zig b/test/behavior/packed-struct.zig
index ab5adc554a..628c2c287f 100644
--- a/test/behavior/packed-struct.zig
+++ b/test/behavior/packed-struct.zig
@@ -413,3 +413,24 @@ test "byte-aligned field pointer offsets" {
try S.doTheTest();
comptime try S.doTheTest();
}
+
+test "load pointer from packed struct" {
+ if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+
+ const Symbol = struct {
+ index: u16,
+ };
+ const Relocation = packed struct {
+ symbol: *Symbol,
+ a: u32,
+ };
+ var a: []Relocation = &.{};
+ for (a) |rela| {
+ var b = rela.symbol.index;
+ _ = b;
+ }
+}