| ... | ... | @@ -2424,6 +2424,24 @@ pub const DeclGen = struct { |
| 2424 | 2424 | } |
| 2425 | 2425 | |
| 2426 | 2426 | fn lowerType(dg: *DeclGen, t: Type) Allocator.Error!*const llvm.Type { |
| 2427 | const llvm_ty = try lowerTypeInner(dg, t); |
| 2428 | if (std.debug.runtime_safety and false) 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 | } |
| 2440 | } |
| 2441 | return llvm_ty; |
| 2442 | } |
| 2443 | |
| 2444 | fn lowerTypeInner(dg: *DeclGen, t: Type) Allocator.Error!*const llvm.Type { |
| 2427 | 2445 | const gpa = dg.gpa; |
| 2428 | 2446 | const target = dg.module.getTarget(); |
| 2429 | 2447 | switch (t.zigTypeTag()) { |
| ... | ... | @@ -2519,10 +2537,18 @@ pub const DeclGen = struct { |
| 2519 | 2537 | return payload_llvm_ty; |
| 2520 | 2538 | } |
| 2521 | 2539 | |
| 2522 | | const fields: [2]*const llvm.Type = .{ |
| 2523 | | payload_llvm_ty, dg.context.intType(1), |
| 2540 | comptime assert(optional_layout_version == 2); |
| 2541 | var fields_buf: [3]*const llvm.Type = .{ |
| 2542 | payload_llvm_ty, dg.context.intType(1), undefined, |
| 2524 | 2543 | }; |
| 2525 | | return dg.context.structType(&fields, 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); |
| 2526 | 2552 | }, |
| 2527 | 2553 | .ErrorUnion => { |
| 2528 | 2554 | const payload_ty = t.errorUnionPayload(); |
| ... | ... | @@ -2534,12 +2560,37 @@ pub const DeclGen = struct { |
| 2534 | 2560 | |
| 2535 | 2561 | const payload_align = payload_ty.abiAlignment(target); |
| 2536 | 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; |
| 2537 | 2568 | if (error_align > payload_align) { |
| 2538 | | const fields: [2]*const llvm.Type = .{ llvm_error_type, llvm_payload_type }; |
| 2539 | | 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); |
| 2540 | 2581 | } else { |
| 2541 | | const fields: [2]*const llvm.Type = .{ llvm_payload_type, llvm_error_type }; |
| 2542 | | 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); |
| 2543 | 2594 | } |
| 2544 | 2595 | }, |
| 2545 | 2596 | .ErrorSet => return dg.context.intType(16), |
| ... | ... | @@ -2704,7 +2755,7 @@ pub const DeclGen = struct { |
| 2704 | 2755 | llvm_aligned_field_ty, |
| 2705 | 2756 | dg.context.intType(8).arrayType(padding_len), |
| 2706 | 2757 | }; |
| 2707 | | break :t dg.context.structType(&fields, fields.len, .False); |
| 2758 | break :t dg.context.structType(&fields, fields.len, .True); |
| 2708 | 2759 | }; |
| 2709 | 2760 | |
| 2710 | 2761 | if (layout.tag_size == 0) { |
| ... | ... | @@ -3020,7 +3071,7 @@ pub const DeclGen = struct { |
| 3020 | 3071 | return dg.context.constStruct( |
| 3021 | 3072 | llvm_elems.ptr, |
| 3022 | 3073 | @intCast(c_uint, llvm_elems.len), |
| 3023 | | .False, |
| 3074 | .True, |
| 3024 | 3075 | ); |
| 3025 | 3076 | } else { |
| 3026 | 3077 | const llvm_elem_ty = try dg.lowerType(elem_ty); |
| ... | ... | @@ -3057,7 +3108,7 @@ pub const DeclGen = struct { |
| 3057 | 3108 | return dg.context.constStruct( |
| 3058 | 3109 | llvm_elems.ptr, |
| 3059 | 3110 | @intCast(c_uint, llvm_elems.len), |
| 3060 | | .False, |
| 3111 | .True, |
| 3061 | 3112 | ); |
| 3062 | 3113 | } else { |
| 3063 | 3114 | const llvm_elem_ty = try dg.lowerType(elem_ty); |
| ... | ... | @@ -3074,7 +3125,7 @@ pub const DeclGen = struct { |
| 3074 | 3125 | const llvm_elems: [1]*const llvm.Value = .{sentinel}; |
| 3075 | 3126 | const need_unnamed = dg.isUnnamedType(elem_ty, llvm_elems[0]); |
| 3076 | 3127 | if (need_unnamed) { |
| 3077 | | return dg.context.constStruct(&llvm_elems, llvm_elems.len, .False); |
| 3128 | return dg.context.constStruct(&llvm_elems, llvm_elems.len, .True); |
| 3078 | 3129 | } else { |
| 3079 | 3130 | const llvm_elem_ty = try dg.lowerType(elem_ty); |
| 3080 | 3131 | return llvm_elem_ty.constArray(&llvm_elems, llvm_elems.len); |
| ... | ... | @@ -3083,6 +3134,7 @@ pub const DeclGen = struct { |
| 3083 | 3134 | else => unreachable, |
| 3084 | 3135 | }, |
| 3085 | 3136 | .Optional => { |
| 3137 | comptime assert(optional_layout_version == 2); |
| 3086 | 3138 | var buf: Type.Payload.ElemType = undefined; |
| 3087 | 3139 | const payload_ty = tv.ty.optionalChild(&buf); |
| 3088 | 3140 | const llvm_i1 = dg.context.intType(1); |
| ... | ... | @@ -3091,25 +3143,30 @@ pub const DeclGen = struct { |
| 3091 | 3143 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3092 | 3144 | return non_null_bit; |
| 3093 | 3145 | } |
| 3146 | const llvm_ty = try dg.lowerType(tv.ty); |
| 3094 | 3147 | if (tv.ty.optionalReprIsPayload()) { |
| 3095 | 3148 | if (tv.val.castTag(.opt_payload)) |payload| { |
| 3096 | 3149 | return dg.lowerValue(.{ .ty = payload_ty, .val = payload.data }); |
| 3097 | 3150 | } else if (is_pl) { |
| 3098 | 3151 | return dg.lowerValue(.{ .ty = payload_ty, .val = tv.val }); |
| 3099 | 3152 | } else { |
| 3100 | | const llvm_ty = try dg.lowerType(tv.ty); |
| 3101 | 3153 | return llvm_ty.constNull(); |
| 3102 | 3154 | } |
| 3103 | 3155 | } |
| 3104 | 3156 | assert(payload_ty.zigTypeTag() != .Fn); |
| 3105 | | const fields: [2]*const llvm.Value = .{ |
| 3106 | | try dg.lowerValue(.{ |
| 3107 | | .ty = payload_ty, |
| 3108 | | .val = if (tv.val.castTag(.opt_payload)) |pl| pl.data else Value.initTag(.undef), |
| 3109 | | }), |
| 3110 | | non_null_bit, |
| 3111 | | }; |
| 3112 | | return dg.context.constStruct(&fields, fields.len, .False); |
| 3157 | |
| 3158 | const llvm_field_count = llvm_ty.countStructElementTypes(); |
| 3159 | var fields_buf: [3]*const llvm.Value = undefined; |
| 3160 | fields_buf[0] = try dg.lowerValue(.{ |
| 3161 | .ty = payload_ty, |
| 3162 | .val = if (tv.val.castTag(.opt_payload)) |pl| pl.data else Value.initTag(.undef), |
| 3163 | }); |
| 3164 | fields_buf[1] = non_null_bit; |
| 3165 | if (llvm_field_count > 2) { |
| 3166 | assert(llvm_field_count == 3); |
| 3167 | fields_buf[2] = llvm_ty.structGetTypeAtIndex(2).getUndef(); |
| 3168 | } |
| 3169 | return dg.context.constStruct(&fields_buf, llvm_field_count, .False); |
| 3113 | 3170 | }, |
| 3114 | 3171 | .Fn => { |
| 3115 | 3172 | const fn_decl_index = switch (tv.val.tag()) { |
| ... | ... | @@ -3155,12 +3212,23 @@ pub const DeclGen = struct { |
| 3155 | 3212 | .ty = payload_type, |
| 3156 | 3213 | .val = if (tv.val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef), |
| 3157 | 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 | |
| 3158 | 3224 | if (error_align > payload_align) { |
| 3159 | | const fields: [2]*const llvm.Value = .{ llvm_error_value, llvm_payload_value }; |
| 3160 | | 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); |
| 3161 | 3228 | } else { |
| 3162 | | const fields: [2]*const llvm.Value = .{ llvm_payload_value, llvm_error_value }; |
| 3163 | | 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); |
| 3164 | 3232 | } |
| 3165 | 3233 | }, |
| 3166 | 3234 | .Struct => { |
| ... | ... | @@ -3361,7 +3429,7 @@ pub const DeclGen = struct { |
| 3361 | 3429 | const fields: [2]*const llvm.Value = .{ |
| 3362 | 3430 | field, dg.context.intType(8).arrayType(padding_len).getUndef(), |
| 3363 | 3431 | }; |
| 3364 | | break :p dg.context.constStruct(&fields, fields.len, .False); |
| 3432 | break :p dg.context.constStruct(&fields, fields.len, .True); |
| 3365 | 3433 | }; |
| 3366 | 3434 | |
| 3367 | 3435 | if (layout.tag_size == 0) { |
| ... | ... | @@ -5847,6 +5915,7 @@ pub const FuncGen = struct { |
| 5847 | 5915 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 5848 | 5916 | const payload_ty = self.air.typeOf(ty_op.operand); |
| 5849 | 5917 | const non_null_bit = self.context.intType(1).constAllOnes(); |
| 5918 | comptime assert(optional_layout_version == 2); |
| 5850 | 5919 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return non_null_bit; |
| 5851 | 5920 | const operand = try self.resolveInst(ty_op.operand); |
| 5852 | 5921 | const optional_ty = self.air.typeOfIndex(inst); |
| ... | ... | @@ -9300,6 +9369,7 @@ fn intrinsicsAllowed(scalar_ty: Type, target: std.Target) bool { |
| 9300 | 9369 | /// We can do this because for all types, Zig ABI alignment >= LLVM ABI |
| 9301 | 9370 | /// alignment. |
| 9302 | 9371 | const struct_layout_version = 2; |
| 9372 | const optional_layout_version = 2; |
| 9303 | 9373 | |
| 9304 | 9374 | /// We use the least significant bit of the pointer address to tell us |
| 9305 | 9375 | /// whether the type is fully resolved. Types that are only fwd declared |