| ... | ... | @@ -2312,6 +2312,8 @@ pub const Type = extern union { |
| 2312 | 2312 | } |
| 2313 | 2313 | } |
| 2314 | 2314 | |
| 2315 | const RuntimeBitsError = Module.CompileError || error{NeedLazy}; |
| 2316 | |
| 2315 | 2317 | /// true if and only if the type takes up space in memory at runtime. |
| 2316 | 2318 | /// There are two reasons a type will return false: |
| 2317 | 2319 | /// * the type is a comptime-only type. For example, the type `type` itself. |
| ... | ... | @@ -2326,8 +2328,8 @@ pub const Type = extern union { |
| 2326 | 2328 | pub fn hasRuntimeBitsAdvanced( |
| 2327 | 2329 | ty: Type, |
| 2328 | 2330 | ignore_comptime_only: bool, |
| 2329 | | opt_sema: ?*Sema, |
| 2330 | | ) Module.CompileError!bool { |
| 2331 | strat: AbiAlignmentAdvancedStrat, |
| 2332 | ) RuntimeBitsError!bool { |
| 2331 | 2333 | switch (ty.tag()) { |
| 2332 | 2334 | .u1, |
| 2333 | 2335 | .u8, |
| ... | ... | @@ -2406,8 +2408,8 @@ pub const Type = extern union { |
| 2406 | 2408 | return true; |
| 2407 | 2409 | } else if (ty.childType().zigTypeTag() == .Fn) { |
| 2408 | 2410 | return !ty.childType().fnInfo().is_generic; |
| 2409 | | } else if (opt_sema) |sema| { |
| 2410 | | return !(try sema.typeRequiresComptime(ty)); |
| 2411 | } else if (strat == .sema) { |
| 2412 | return !(try strat.sema.typeRequiresComptime(ty)); |
| 2411 | 2413 | } else { |
| 2412 | 2414 | return !comptimeOnly(ty); |
| 2413 | 2415 | } |
| ... | ... | @@ -2445,8 +2447,8 @@ pub const Type = extern union { |
| 2445 | 2447 | } |
| 2446 | 2448 | if (ignore_comptime_only) { |
| 2447 | 2449 | return true; |
| 2448 | | } else if (opt_sema) |sema| { |
| 2449 | | return !(try sema.typeRequiresComptime(child_ty)); |
| 2450 | } else if (strat == .sema) { |
| 2451 | return !(try strat.sema.typeRequiresComptime(child_ty)); |
| 2450 | 2452 | } else { |
| 2451 | 2453 | return !comptimeOnly(child_ty); |
| 2452 | 2454 | } |
| ... | ... | @@ -2459,13 +2461,14 @@ pub const Type = extern union { |
| 2459 | 2461 | // and then later if our guess was incorrect, we emit a compile error. |
| 2460 | 2462 | return true; |
| 2461 | 2463 | } |
| 2462 | | if (opt_sema) |sema| { |
| 2463 | | _ = try sema.resolveTypeFields(ty); |
| 2464 | switch (strat) { |
| 2465 | .sema => |sema| _ = try sema.resolveTypeFields(ty), |
| 2466 | .eager => assert(struct_obj.haveFieldTypes()), |
| 2467 | .lazy => if (!struct_obj.haveFieldTypes()) return error.NeedLazy, |
| 2464 | 2468 | } |
| 2465 | | assert(struct_obj.haveFieldTypes()); |
| 2466 | 2469 | for (struct_obj.fields.values()) |field| { |
| 2467 | 2470 | if (field.is_comptime) continue; |
| 2468 | | if (try field.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema)) |
| 2471 | if (try field.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat)) |
| 2469 | 2472 | return true; |
| 2470 | 2473 | } else { |
| 2471 | 2474 | return false; |
| ... | ... | @@ -2474,7 +2477,7 @@ pub const Type = extern union { |
| 2474 | 2477 | |
| 2475 | 2478 | .enum_full => { |
| 2476 | 2479 | const enum_full = ty.castTag(.enum_full).?.data; |
| 2477 | | return enum_full.tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema); |
| 2480 | return enum_full.tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat); |
| 2478 | 2481 | }, |
| 2479 | 2482 | .enum_simple => { |
| 2480 | 2483 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| ... | ... | @@ -2483,17 +2486,18 @@ pub const Type = extern union { |
| 2483 | 2486 | .enum_numbered, .enum_nonexhaustive => { |
| 2484 | 2487 | var buffer: Payload.Bits = undefined; |
| 2485 | 2488 | const int_tag_ty = ty.intTagType(&buffer); |
| 2486 | | return int_tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema); |
| 2489 | return int_tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat); |
| 2487 | 2490 | }, |
| 2488 | 2491 | |
| 2489 | 2492 | .@"union" => { |
| 2490 | 2493 | const union_obj = ty.castTag(.@"union").?.data; |
| 2491 | | if (opt_sema) |sema| { |
| 2492 | | _ = try sema.resolveTypeFields(ty); |
| 2494 | switch (strat) { |
| 2495 | .sema => |sema| _ = try sema.resolveTypeFields(ty), |
| 2496 | .eager => assert(union_obj.haveFieldTypes()), |
| 2497 | .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy, |
| 2493 | 2498 | } |
| 2494 | | assert(union_obj.haveFieldTypes()); |
| 2495 | 2499 | for (union_obj.fields.values()) |value| { |
| 2496 | | if (try value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema)) |
| 2500 | if (try value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat)) |
| 2497 | 2501 | return true; |
| 2498 | 2502 | } else { |
| 2499 | 2503 | return false; |
| ... | ... | @@ -2501,16 +2505,17 @@ pub const Type = extern union { |
| 2501 | 2505 | }, |
| 2502 | 2506 | .union_safety_tagged, .union_tagged => { |
| 2503 | 2507 | const union_obj = ty.cast(Payload.Union).?.data; |
| 2504 | | if (try union_obj.tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema)) { |
| 2508 | if (try union_obj.tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat)) { |
| 2505 | 2509 | return true; |
| 2506 | 2510 | } |
| 2507 | 2511 | |
| 2508 | | if (opt_sema) |sema| { |
| 2509 | | _ = try sema.resolveTypeFields(ty); |
| 2512 | switch (strat) { |
| 2513 | .sema => |sema| _ = try sema.resolveTypeFields(ty), |
| 2514 | .eager => assert(union_obj.haveFieldTypes()), |
| 2515 | .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy, |
| 2510 | 2516 | } |
| 2511 | | assert(union_obj.haveFieldTypes()); |
| 2512 | 2517 | for (union_obj.fields.values()) |value| { |
| 2513 | | if (try value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema)) |
| 2518 | if (try value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat)) |
| 2514 | 2519 | return true; |
| 2515 | 2520 | } else { |
| 2516 | 2521 | return false; |
| ... | ... | @@ -2518,9 +2523,9 @@ pub const Type = extern union { |
| 2518 | 2523 | }, |
| 2519 | 2524 | |
| 2520 | 2525 | .array, .vector => return ty.arrayLen() != 0 and |
| 2521 | | try ty.elemType().hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema), |
| 2526 | try ty.elemType().hasRuntimeBitsAdvanced(ignore_comptime_only, strat), |
| 2522 | 2527 | .array_u8 => return ty.arrayLen() != 0, |
| 2523 | | .array_sentinel => return ty.childType().hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema), |
| 2528 | .array_sentinel => return ty.childType().hasRuntimeBitsAdvanced(ignore_comptime_only, strat), |
| 2524 | 2529 | |
| 2525 | 2530 | .int_signed, .int_unsigned => return ty.cast(Payload.Bits).?.data != 0, |
| 2526 | 2531 | |
| ... | ... | @@ -2529,7 +2534,7 @@ pub const Type = extern union { |
| 2529 | 2534 | for (tuple.types) |field_ty, i| { |
| 2530 | 2535 | const val = tuple.values[i]; |
| 2531 | 2536 | if (val.tag() != .unreachable_value) continue; // comptime field |
| 2532 | | if (try field_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, opt_sema)) return true; |
| 2537 | if (try field_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat)) return true; |
| 2533 | 2538 | } |
| 2534 | 2539 | return false; |
| 2535 | 2540 | }, |
| ... | ... | @@ -2665,11 +2670,11 @@ pub const Type = extern union { |
| 2665 | 2670 | } |
| 2666 | 2671 | |
| 2667 | 2672 | pub fn hasRuntimeBits(ty: Type) bool { |
| 2668 | | return hasRuntimeBitsAdvanced(ty, false, null) catch unreachable; |
| 2673 | return hasRuntimeBitsAdvanced(ty, false, .eager) catch unreachable; |
| 2669 | 2674 | } |
| 2670 | 2675 | |
| 2671 | 2676 | pub fn hasRuntimeBitsIgnoreComptime(ty: Type) bool { |
| 2672 | | return hasRuntimeBitsAdvanced(ty, true, null) catch unreachable; |
| 2677 | return hasRuntimeBitsAdvanced(ty, true, .eager) catch unreachable; |
| 2673 | 2678 | } |
| 2674 | 2679 | |
| 2675 | 2680 | pub fn isFnOrHasRuntimeBits(ty: Type) bool { |
| ... | ... | @@ -2812,12 +2817,12 @@ pub const Type = extern union { |
| 2812 | 2817 | } |
| 2813 | 2818 | } |
| 2814 | 2819 | |
| 2815 | | const AbiAlignmentAdvanced = union(enum) { |
| 2820 | pub const AbiAlignmentAdvanced = union(enum) { |
| 2816 | 2821 | scalar: u32, |
| 2817 | 2822 | val: Value, |
| 2818 | 2823 | }; |
| 2819 | 2824 | |
| 2820 | | const AbiAlignmentAdvancedStrat = union(enum) { |
| 2825 | pub const AbiAlignmentAdvancedStrat = union(enum) { |
| 2821 | 2826 | eager, |
| 2822 | 2827 | lazy: Allocator, |
| 2823 | 2828 | sema: *Sema, |
| ... | ... | @@ -2971,7 +2976,10 @@ pub const Type = extern union { |
| 2971 | 2976 | |
| 2972 | 2977 | switch (strat) { |
| 2973 | 2978 | .eager, .sema => { |
| 2974 | | if (!(try child_type.hasRuntimeBitsAdvanced(false, opt_sema))) { |
| 2979 | if (!(child_type.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) { |
| 2980 | error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) }, |
| 2981 | else => |e| return e, |
| 2982 | })) { |
| 2975 | 2983 | return AbiAlignmentAdvanced{ .scalar = 1 }; |
| 2976 | 2984 | } |
| 2977 | 2985 | return child_type.abiAlignmentAdvanced(target, strat); |
| ... | ... | @@ -2990,7 +2998,10 @@ pub const Type = extern union { |
| 2990 | 2998 | const code_align = abiAlignment(Type.anyerror, target); |
| 2991 | 2999 | switch (strat) { |
| 2992 | 3000 | .eager, .sema => { |
| 2993 | | if (!(try data.payload.hasRuntimeBitsAdvanced(false, opt_sema))) { |
| 3001 | if (!(data.payload.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) { |
| 3002 | error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) }, |
| 3003 | else => |e| return e, |
| 3004 | })) { |
| 2994 | 3005 | return AbiAlignmentAdvanced{ .scalar = code_align }; |
| 2995 | 3006 | } |
| 2996 | 3007 | return AbiAlignmentAdvanced{ .scalar = @max( |
| ... | ... | @@ -3044,7 +3055,10 @@ pub const Type = extern union { |
| 3044 | 3055 | const fields = ty.structFields(); |
| 3045 | 3056 | var big_align: u32 = 0; |
| 3046 | 3057 | for (fields.values()) |field| { |
| 3047 | | if (!(try field.ty.hasRuntimeBitsAdvanced(false, opt_sema))) continue; |
| 3058 | if (!(field.ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) { |
| 3059 | error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) }, |
| 3060 | else => |e| return e, |
| 3061 | })) continue; |
| 3048 | 3062 | |
| 3049 | 3063 | const field_align = if (field.abi_align != 0) |
| 3050 | 3064 | field.abi_align |
| ... | ... | @@ -3161,7 +3175,10 @@ pub const Type = extern union { |
| 3161 | 3175 | var max_align: u32 = 0; |
| 3162 | 3176 | if (have_tag) max_align = union_obj.tag_ty.abiAlignment(target); |
| 3163 | 3177 | for (union_obj.fields.values()) |field| { |
| 3164 | | if (!(try field.ty.hasRuntimeBitsAdvanced(false, opt_sema))) continue; |
| 3178 | if (!(field.ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) { |
| 3179 | error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) }, |
| 3180 | else => |e| return e, |
| 3181 | })) continue; |
| 3165 | 3182 | |
| 3166 | 3183 | const field_align = if (field.abi_align != 0) |
| 3167 | 3184 | field.abi_align |