| ... | @@ -2425,17 +2425,17 @@ pub const DeclGen = struct { | ... | @@ -2425,17 +2425,17 @@ pub const DeclGen = struct { |
| 2425 | | 2425 | |
| 2426 | fn lowerType(dg: *DeclGen, t: Type) Allocator.Error!*const llvm.Type { | 2426 | fn lowerType(dg: *DeclGen, t: Type) Allocator.Error!*const llvm.Type { |
| 2427 | const llvm_ty = try lowerTypeInner(dg, t); | 2427 | const llvm_ty = try lowerTypeInner(dg, t); |
| 2428 | if (std.debug.runtime_safety) { | 2428 | if (std.debug.runtime_safety) check: { |
| 2429 | if (t.zigTypeTag() != .Opaque and t.hasRuntimeBits() and | 2429 | if (t.zigTypeTag() == .Opaque) break :check; |
| 2430 | !llvm_ty.isOpaqueStruct().toBool()) | 2430 | if (!t.hasRuntimeBits()) break :check; |
| 2431 | { | 2431 | if (!llvm_ty.isSized().toBool()) break :check; |
| 2432 | const zig_size = t.abiSize(dg.module.getTarget()); | 2432 | |
| 2433 | const llvm_size = dg.object.target_data.abiSizeOfType(llvm_ty); | 2433 | const zig_size = t.abiSize(dg.module.getTarget()); |
| 2434 | if (llvm_size != zig_size) { | 2434 | const llvm_size = dg.object.target_data.abiSizeOfType(llvm_ty); |
| 2435 | log.err("when lowering {}, Zig ABI size = {d} but LLVM ABI size = {d}", .{ | 2435 | if (llvm_size != zig_size) { |
| 2436 | t.fmt(dg.module), zig_size, llvm_size, | 2436 | log.err("when lowering {}, Zig ABI size = {d} but LLVM ABI size = {d}", .{ |
| 2437 | }); | 2437 | t.fmt(dg.module), zig_size, llvm_size, |
| 2438 | } | 2438 | }); |
| 2439 | } | 2439 | } |
| 2440 | } | 2440 | } |
| 2441 | return llvm_ty; | 2441 | return llvm_ty; |
| ... | @@ -2537,22 +2537,18 @@ pub const DeclGen = struct { | ... | @@ -2537,22 +2537,18 @@ pub const DeclGen = struct { |
| 2537 | return payload_llvm_ty; | 2537 | return payload_llvm_ty; |
| 2538 | } | 2538 | } |
| 2539 | | 2539 | |
| 2540 | comptime assert(optional_layout_version == 1); | 2540 | comptime assert(optional_layout_version == 2); |
| 2541 | const fields: [2]*const llvm.Type = .{ | 2541 | var fields_buf: [3]*const llvm.Type = .{ |
| 2542 | payload_llvm_ty, | 2542 | payload_llvm_ty, dg.context.intType(1), undefined, |
| 2543 | dg.context.intType(1), | | |
| 2544 | }; | | |
| 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 | }; | 2543 | }; |
| 2555 | return dg.context.structType(&padded_fields, padded_fields.len, .False); | 2544 | const offset = child_ty.abiSize(target) + 1; |
| | 2545 | const abi_size = t.abiSize(target); |
| | 2546 | const padding = @intCast(c_uint, abi_size - offset); |
| | 2547 | if (padding == 0) { |
| | 2548 | return dg.context.structType(&fields_buf, 2, .False); |
| | 2549 | } |
| | 2550 | fields_buf[2] = dg.context.intType(8).arrayType(padding); |
| | 2551 | return dg.context.structType(&fields_buf, 3, .False); |
| 2556 | }, | 2552 | }, |
| 2557 | .ErrorUnion => { | 2553 | .ErrorUnion => { |
| 2558 | const payload_ty = t.errorUnionPayload(); | 2554 | const payload_ty = t.errorUnionPayload(); |
| ... | @@ -2564,12 +2560,37 @@ pub const DeclGen = struct { | ... | @@ -2564,12 +2560,37 @@ pub const DeclGen = struct { |
| 2564 | | 2560 | |
| 2565 | const payload_align = payload_ty.abiAlignment(target); | 2561 | const payload_align = payload_ty.abiAlignment(target); |
| 2566 | const error_align = Type.anyerror.abiAlignment(target); | 2562 | const error_align = Type.anyerror.abiAlignment(target); |
| | 2563 | |
| | 2564 | const payload_size = payload_ty.abiSize(target); |
| | 2565 | const error_size = Type.anyerror.abiSize(target); |
| | 2566 | |
| | 2567 | var fields_buf: [3]*const llvm.Type = undefined; |
| 2567 | if (error_align > payload_align) { | 2568 | if (error_align > payload_align) { |
| 2568 | const fields: [2]*const llvm.Type = .{ llvm_error_type, llvm_payload_type }; | 2569 | fields_buf[0] = llvm_error_type; |
| 2569 | return dg.context.structType(&fields, fields.len, .False); | 2570 | fields_buf[1] = llvm_payload_type; |
| | 2571 | const payload_end = |
| | 2572 | std.mem.alignForwardGeneric(u64, error_size, payload_align) + |
| | 2573 | payload_size; |
| | 2574 | const abi_size = std.mem.alignForwardGeneric(u64, payload_end, error_align); |
| | 2575 | const padding = @intCast(c_uint, abi_size - payload_end); |
| | 2576 | if (padding == 0) { |
| | 2577 | return dg.context.structType(&fields_buf, 2, .False); |
| | 2578 | } |
| | 2579 | fields_buf[2] = dg.context.intType(8).arrayType(padding); |
| | 2580 | return dg.context.structType(&fields_buf, 3, .False); |
| 2570 | } else { | 2581 | } else { |
| 2571 | const fields: [2]*const llvm.Type = .{ llvm_payload_type, llvm_error_type }; | 2582 | fields_buf[0] = llvm_payload_type; |
| 2572 | return dg.context.structType(&fields, fields.len, .False); | 2583 | fields_buf[1] = llvm_error_type; |
| | 2584 | const error_end = |
| | 2585 | std.mem.alignForwardGeneric(u64, payload_size, error_align) + |
| | 2586 | error_size; |
| | 2587 | const abi_size = std.mem.alignForwardGeneric(u64, error_end, payload_align); |
| | 2588 | const padding = @intCast(c_uint, abi_size - error_end); |
| | 2589 | if (padding == 0) { |
| | 2590 | return dg.context.structType(&fields_buf, 2, .False); |
| | 2591 | } |
| | 2592 | fields_buf[2] = dg.context.intType(8).arrayType(padding); |
| | 2593 | return dg.context.structType(&fields_buf, 3, .False); |
| 2573 | } | 2594 | } |
| 2574 | }, | 2595 | }, |
| 2575 | .ErrorSet => return dg.context.intType(16), | 2596 | .ErrorSet => return dg.context.intType(16), |
| ... | @@ -3113,7 +3134,7 @@ pub const DeclGen = struct { | ... | @@ -3113,7 +3134,7 @@ pub const DeclGen = struct { |
| 3113 | else => unreachable, | 3134 | else => unreachable, |
| 3114 | }, | 3135 | }, |
| 3115 | .Optional => { | 3136 | .Optional => { |
| 3116 | comptime assert(optional_layout_version == 1); | 3137 | comptime assert(optional_layout_version == 2); |
| 3117 | var buf: Type.Payload.ElemType = undefined; | 3138 | var buf: Type.Payload.ElemType = undefined; |
| 3118 | const payload_ty = tv.ty.optionalChild(&buf); | 3139 | const payload_ty = tv.ty.optionalChild(&buf); |
| 3119 | const llvm_i1 = dg.context.intType(1); | 3140 | const llvm_i1 = dg.context.intType(1); |
| ... | @@ -3191,12 +3212,23 @@ pub const DeclGen = struct { | ... | @@ -3191,12 +3212,23 @@ pub const DeclGen = struct { |
| 3191 | .ty = payload_type, | 3212 | .ty = payload_type, |
| 3192 | .val = if (tv.val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef), | 3213 | .val = if (tv.val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef), |
| 3193 | }); | 3214 | }); |
| | 3215 | var fields_buf: [3]*const llvm.Value = undefined; |
| | 3216 | |
| | 3217 | const llvm_ty = try dg.lowerType(tv.ty); |
| | 3218 | const llvm_field_count = llvm_ty.countStructElementTypes(); |
| | 3219 | if (llvm_field_count > 2) { |
| | 3220 | assert(llvm_field_count == 3); |
| | 3221 | fields_buf[2] = llvm_ty.structGetTypeAtIndex(2).getUndef(); |
| | 3222 | } |
| | 3223 | |
| 3194 | if (error_align > payload_align) { | 3224 | if (error_align > payload_align) { |
| 3195 | const fields: [2]*const llvm.Value = .{ llvm_error_value, llvm_payload_value }; | 3225 | fields_buf[0] = llvm_error_value; |
| 3196 | return dg.context.constStruct(&fields, fields.len, .False); | 3226 | fields_buf[1] = llvm_payload_value; |
| | 3227 | return dg.context.constStruct(&fields_buf, llvm_field_count, .False); |
| 3197 | } else { | 3228 | } else { |
| 3198 | const fields: [2]*const llvm.Value = .{ llvm_payload_value, llvm_error_value }; | 3229 | fields_buf[0] = llvm_payload_value; |
| 3199 | return dg.context.constStruct(&fields, fields.len, .False); | 3230 | fields_buf[1] = llvm_error_value; |
| | 3231 | return dg.context.constStruct(&fields_buf, llvm_field_count, .False); |
| 3200 | } | 3232 | } |
| 3201 | }, | 3233 | }, |
| 3202 | .Struct => { | 3234 | .Struct => { |
| ... | @@ -5883,7 +5915,7 @@ pub const FuncGen = struct { | ... | @@ -5883,7 +5915,7 @@ pub const FuncGen = struct { |
| 5883 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 5915 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 5884 | const payload_ty = self.air.typeOf(ty_op.operand); | 5916 | const payload_ty = self.air.typeOf(ty_op.operand); |
| 5885 | const non_null_bit = self.context.intType(1).constAllOnes(); | 5917 | const non_null_bit = self.context.intType(1).constAllOnes(); |
| 5886 | comptime assert(optional_layout_version == 1); | 5918 | comptime assert(optional_layout_version == 2); |
| 5887 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return non_null_bit; | 5919 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return non_null_bit; |
| 5888 | const operand = try self.resolveInst(ty_op.operand); | 5920 | const operand = try self.resolveInst(ty_op.operand); |
| 5889 | const optional_ty = self.air.typeOfIndex(inst); | 5921 | const optional_ty = self.air.typeOfIndex(inst); |
| ... | @@ -9337,7 +9369,7 @@ fn intrinsicsAllowed(scalar_ty: Type, target: std.Target) bool { | ... | @@ -9337,7 +9369,7 @@ fn intrinsicsAllowed(scalar_ty: Type, target: std.Target) bool { |
| 9337 | /// We can do this because for all types, Zig ABI alignment >= LLVM ABI | 9369 | /// We can do this because for all types, Zig ABI alignment >= LLVM ABI |
| 9338 | /// alignment. | 9370 | /// alignment. |
| 9339 | const struct_layout_version = 2; | 9371 | const struct_layout_version = 2; |
| 9340 | const optional_layout_version = 1; | 9372 | const optional_layout_version = 2; |
| 9341 | | 9373 | |
| 9342 | /// We use the least significant bit of the pointer address to tell us | 9374 | /// We use the least significant bit of the pointer address to tell us |
| 9343 | /// whether the type is fully resolved. Types that are only fwd declared | 9375 | /// whether the type is fully resolved. Types that are only fwd declared |