| ... | ... | @@ -2425,17 +2425,17 @@ pub const DeclGen = struct { |
| 2425 | 2425 | |
| 2426 | 2426 | fn lowerType(dg: *DeclGen, t: Type) Allocator.Error!*const llvm.Type { |
| 2427 | 2427 | const llvm_ty = try lowerTypeInner(dg, t); |
| 2428 | | if (std.debug.runtime_safety) { |
| 2429 | | if (t.zigTypeTag() != .Opaque and t.hasRuntimeBits() and |
| 2430 | | !llvm_ty.isOpaqueStruct().toBool()) |
| 2431 | | { |
| 2432 | | const zig_size = t.abiSize(dg.module.getTarget()); |
| 2433 | | const llvm_size = dg.object.target_data.abiSizeOfType(llvm_ty); |
| 2434 | | if (llvm_size != zig_size) { |
| 2435 | | log.err("when lowering {}, Zig ABI size = {d} but LLVM ABI size = {d}", .{ |
| 2436 | | t.fmt(dg.module), zig_size, llvm_size, |
| 2437 | | }); |
| 2438 | | } |
| 2428 | if (std.debug.runtime_safety) check: { |
| 2429 | if (t.zigTypeTag() == .Opaque) break :check; |
| 2430 | if (!t.hasRuntimeBits()) break :check; |
| 2431 | if (!llvm_ty.isSized().toBool()) break :check; |
| 2432 | |
| 2433 | const zig_size = t.abiSize(dg.module.getTarget()); |
| 2434 | const llvm_size = dg.object.target_data.abiSizeOfType(llvm_ty); |
| 2435 | if (llvm_size != zig_size) { |
| 2436 | log.err("when lowering {}, Zig ABI size = {d} but LLVM ABI size = {d}", .{ |
| 2437 | t.fmt(dg.module), zig_size, llvm_size, |
| 2438 | }); |
| 2439 | 2439 | } |
| 2440 | 2440 | } |
| 2441 | 2441 | return llvm_ty; |
| ... | ... | @@ -2537,22 +2537,18 @@ pub const DeclGen = struct { |
| 2537 | 2537 | return payload_llvm_ty; |
| 2538 | 2538 | } |
| 2539 | 2539 | |
| 2540 | | comptime assert(optional_layout_version == 1); |
| 2541 | | const fields: [2]*const llvm.Type = .{ |
| 2542 | | payload_llvm_ty, |
| 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), |
| 2540 | comptime assert(optional_layout_version == 2); |
| 2541 | var fields_buf: [3]*const llvm.Type = .{ |
| 2542 | payload_llvm_ty, dg.context.intType(1), undefined, |
| 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 | 2553 | .ErrorUnion => { |
| 2558 | 2554 | const payload_ty = t.errorUnionPayload(); |
| ... | ... | @@ -2564,12 +2560,37 @@ pub const DeclGen = struct { |
| 2564 | 2560 | |
| 2565 | 2561 | const payload_align = payload_ty.abiAlignment(target); |
| 2566 | 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 | 2568 | if (error_align > payload_align) { |
| 2568 | | const fields: [2]*const llvm.Type = .{ llvm_error_type, llvm_payload_type }; |
| 2569 | | return dg.context.structType(&fields, fields.len, .False); |
| 2569 | fields_buf[0] = llvm_error_type; |
| 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 | 2581 | } else { |
| 2571 | | const fields: [2]*const llvm.Type = .{ llvm_payload_type, llvm_error_type }; |
| 2572 | | return dg.context.structType(&fields, fields.len, .False); |
| 2582 | fields_buf[0] = llvm_payload_type; |
| 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 | 2596 | .ErrorSet => return dg.context.intType(16), |
| ... | ... | @@ -3113,7 +3134,7 @@ pub const DeclGen = struct { |
| 3113 | 3134 | else => unreachable, |
| 3114 | 3135 | }, |
| 3115 | 3136 | .Optional => { |
| 3116 | | comptime assert(optional_layout_version == 1); |
| 3137 | comptime assert(optional_layout_version == 2); |
| 3117 | 3138 | var buf: Type.Payload.ElemType = undefined; |
| 3118 | 3139 | const payload_ty = tv.ty.optionalChild(&buf); |
| 3119 | 3140 | const llvm_i1 = dg.context.intType(1); |
| ... | ... | @@ -3191,12 +3212,23 @@ pub const DeclGen = struct { |
| 3191 | 3212 | .ty = payload_type, |
| 3192 | 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 | 3224 | if (error_align > payload_align) { |
| 3195 | | const fields: [2]*const llvm.Value = .{ llvm_error_value, llvm_payload_value }; |
| 3196 | | return dg.context.constStruct(&fields, fields.len, .False); |
| 3225 | fields_buf[0] = llvm_error_value; |
| 3226 | fields_buf[1] = llvm_payload_value; |
| 3227 | return dg.context.constStruct(&fields_buf, llvm_field_count, .False); |
| 3197 | 3228 | } else { |
| 3198 | | const fields: [2]*const llvm.Value = .{ llvm_payload_value, llvm_error_value }; |
| 3199 | | return dg.context.constStruct(&fields, fields.len, .False); |
| 3229 | fields_buf[0] = llvm_payload_value; |
| 3230 | fields_buf[1] = llvm_error_value; |
| 3231 | return dg.context.constStruct(&fields_buf, llvm_field_count, .False); |
| 3200 | 3232 | } |
| 3201 | 3233 | }, |
| 3202 | 3234 | .Struct => { |
| ... | ... | @@ -5883,7 +5915,7 @@ pub const FuncGen = struct { |
| 5883 | 5915 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 5884 | 5916 | const payload_ty = self.air.typeOf(ty_op.operand); |
| 5885 | 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 | 5919 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return non_null_bit; |
| 5888 | 5920 | const operand = try self.resolveInst(ty_op.operand); |
| 5889 | 5921 | const optional_ty = self.air.typeOfIndex(inst); |
| ... | ... | @@ -9337,7 +9369,7 @@ fn intrinsicsAllowed(scalar_ty: Type, target: std.Target) bool { |
| 9337 | 9369 | /// We can do this because for all types, Zig ABI alignment >= LLVM ABI |
| 9338 | 9370 | /// alignment. |
| 9339 | 9371 | const struct_layout_version = 2; |
| 9340 | | const optional_layout_version = 1; |
| 9372 | const optional_layout_version = 2; |
| 9341 | 9373 | |
| 9342 | 9374 | /// We use the least significant bit of the pointer address to tell us |
| 9343 | 9375 | /// whether the type is fully resolved. Types that are only fwd declared |