authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-14 20:05:55-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-14 22:26:11-07:00
log9c136be78fcc44d4dd4902605de6af14358c67a3
tree5861223079650e79cd5015fc1f616b86be2b763f
parent070e3ea37dd51c2a2080941a056c455f70232148

LLVM: add padding to optional types when lowering

If the LLVM ABI size does not agree with the Zig ABI size.

1 files changed, 31 insertions(+), 11 deletions(-)

src/codegen/llvm.zig+31-11
......@@ -2537,10 +2537,22 @@ pub const DeclGen = struct {
25372537 return payload_llvm_ty;
25382538 }
25392539
2540 comptime assert(optional_layout_version == 1);
25402541 const fields: [2]*const llvm.Type = .{
2541 payload_llvm_ty, dg.context.intType(1),
2542 payload_llvm_ty,
2543 dg.context.intType(1),
25422544 };
2543 return dg.context.structType(&fields, fields.len, .False);
2545 const llvm_ty = dg.context.structType(&fields, fields.len, .False);
2546 const llvm_size = dg.object.target_data.abiSizeOfType(llvm_ty);
2547 const zig_size = t.abiSize(target);
2548 const padding = @intCast(c_uint, zig_size - llvm_size);
2549 if (padding == 0) return llvm_ty;
2550 const padded_fields: [3]*const llvm.Type = .{
2551 payload_llvm_ty,
2552 dg.context.intType(1),
2553 dg.context.intType(8).arrayType(padding),
2554 };
2555 return dg.context.structType(&padded_fields, padded_fields.len, .False);
25442556 },
25452557 .ErrorUnion => {
25462558 const payload_ty = t.errorUnionPayload();
......@@ -3101,6 +3113,7 @@ pub const DeclGen = struct {
31013113 else => unreachable,
31023114 },
31033115 .Optional => {
3116 comptime assert(optional_layout_version == 1);
31043117 var buf: Type.Payload.ElemType = undefined;
31053118 const payload_ty = tv.ty.optionalChild(&buf);
31063119 const llvm_i1 = dg.context.intType(1);
......@@ -3109,25 +3122,30 @@ pub const DeclGen = struct {
31093122 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
31103123 return non_null_bit;
31113124 }
3125 const llvm_ty = try dg.lowerType(tv.ty);
31123126 if (tv.ty.optionalReprIsPayload()) {
31133127 if (tv.val.castTag(.opt_payload)) |payload| {
31143128 return dg.lowerValue(.{ .ty = payload_ty, .val = payload.data });
31153129 } else if (is_pl) {
31163130 return dg.lowerValue(.{ .ty = payload_ty, .val = tv.val });
31173131 } else {
3118 const llvm_ty = try dg.lowerType(tv.ty);
31193132 return llvm_ty.constNull();
31203133 }
31213134 }
31223135 assert(payload_ty.zigTypeTag() != .Fn);
3123 const fields: [2]*const llvm.Value = .{
3124 try dg.lowerValue(.{
3125 .ty = payload_ty,
3126 .val = if (tv.val.castTag(.opt_payload)) |pl| pl.data else Value.initTag(.undef),
3127 }),
3128 non_null_bit,
3129 };
3130 return dg.context.constStruct(&fields, fields.len, .False);
3136
3137 const llvm_field_count = llvm_ty.countStructElementTypes();
3138 var fields_buf: [3]*const llvm.Value = undefined;
3139 fields_buf[0] = try dg.lowerValue(.{
3140 .ty = payload_ty,
3141 .val = if (tv.val.castTag(.opt_payload)) |pl| pl.data else Value.initTag(.undef),
3142 });
3143 fields_buf[1] = non_null_bit;
3144 if (llvm_field_count > 2) {
3145 assert(llvm_field_count == 3);
3146 fields_buf[2] = llvm_ty.structGetTypeAtIndex(2).getUndef();
3147 }
3148 return dg.context.constStruct(&fields_buf, llvm_field_count, .False);
31313149 },
31323150 .Fn => {
31333151 const fn_decl_index = switch (tv.val.tag()) {
......@@ -5865,6 +5883,7 @@ pub const FuncGen = struct {
58655883 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
58665884 const payload_ty = self.air.typeOf(ty_op.operand);
58675885 const non_null_bit = self.context.intType(1).constAllOnes();
5886 comptime assert(optional_layout_version == 1);
58685887 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return non_null_bit;
58695888 const operand = try self.resolveInst(ty_op.operand);
58705889 const optional_ty = self.air.typeOfIndex(inst);
......@@ -9318,6 +9337,7 @@ fn intrinsicsAllowed(scalar_ty: Type, target: std.Target) bool {
93189337/// We can do this because for all types, Zig ABI alignment >= LLVM ABI
93199338/// alignment.
93209339const struct_layout_version = 2;
9340const optional_layout_version = 1;
93219341
93229342/// We use the least significant bit of the pointer address to tell us
93239343/// whether the type is fully resolved. Types that are only fwd declared