| ... | @@ -2312,6 +2312,8 @@ pub const Type = extern union { | ... | @@ -2312,6 +2312,8 @@ pub const Type = extern union { |
| 2312 | } | 2312 | } |
| 2313 | } | 2313 | } |
| 2314 | | 2314 | |
| | 2315 | const RuntimeBitsError = Module.CompileError || error{NeedLazy}; |
| | 2316 | |
| 2315 | /// true if and only if the type takes up space in memory at runtime. | 2317 | /// true if and only if the type takes up space in memory at runtime. |
| 2316 | /// There are two reasons a type will return false: | 2318 | /// There are two reasons a type will return false: |
| 2317 | /// * the type is a comptime-only type. For example, the type `type` itself. | 2319 | /// * the type is a comptime-only type. For example, the type `type` itself. |
| ... | @@ -2326,8 +2328,8 @@ pub const Type = extern union { | ... | @@ -2326,8 +2328,8 @@ pub const Type = extern union { |
| 2326 | pub fn hasRuntimeBitsAdvanced( | 2328 | pub fn hasRuntimeBitsAdvanced( |
| 2327 | ty: Type, | 2329 | ty: Type, |
| 2328 | ignore_comptime_only: bool, | 2330 | ignore_comptime_only: bool, |
| 2329 | opt_sema: ?*Sema, | 2331 | strat: AbiAlignmentAdvancedStrat, |
| 2330 | ) Module.CompileError!bool { | 2332 | ) RuntimeBitsError!bool { |
| 2331 | switch (ty.tag()) { | 2333 | switch (ty.tag()) { |
| 2332 | .u1, | 2334 | .u1, |
| 2333 | .u8, | 2335 | .u8, |
| ... | @@ -2406,8 +2408,8 @@ pub const Type = extern union { | ... | @@ -2406,8 +2408,8 @@ pub const Type = extern union { |
| 2406 | return true; | 2408 | return true; |
| 2407 | } else if (ty.childType().zigTypeTag() == .Fn) { | 2409 | } else if (ty.childType().zigTypeTag() == .Fn) { |
| 2408 | return !ty.childType().fnInfo().is_generic; | 2410 | return !ty.childType().fnInfo().is_generic; |
| 2409 | } else if (opt_sema) |sema| { | 2411 | } else if (strat == .sema) { |
| 2410 | return !(try sema.typeRequiresComptime(ty)); | 2412 | return !(try strat.sema.typeRequiresComptime(ty)); |
| 2411 | } else { | 2413 | } else { |
| 2412 | return !comptimeOnly(ty); | 2414 | return !comptimeOnly(ty); |
| 2413 | } | 2415 | } |
| ... | @@ -2445,8 +2447,8 @@ pub const Type = extern union { | ... | @@ -2445,8 +2447,8 @@ pub const Type = extern union { |
| 2445 | } | 2447 | } |
| 2446 | if (ignore_comptime_only) { | 2448 | if (ignore_comptime_only) { |
| 2447 | return true; | 2449 | return true; |
| 2448 | } else if (opt_sema) |sema| { | 2450 | } else if (strat == .sema) { |
| 2449 | return !(try sema.typeRequiresComptime(child_ty)); | 2451 | return !(try strat.sema.typeRequiresComptime(child_ty)); |
| 2450 | } else { | 2452 | } else { |
| 2451 | return !comptimeOnly(child_ty); | 2453 | return !comptimeOnly(child_ty); |
| 2452 | } | 2454 | } |
| ... | @@ -2459,13 +2461,14 @@ pub const Type = extern union { | ... | @@ -2459,13 +2461,14 @@ pub const Type = extern union { |
| 2459 | // and then later if our guess was incorrect, we emit a compile error. | 2461 | // and then later if our guess was incorrect, we emit a compile error. |
| 2460 | return true; | 2462 | return true; |
| 2461 | } | 2463 | } |
| 2462 | if (opt_sema) |sema| { | 2464 | switch (strat) { |
| 2463 | _ = try sema.resolveTypeFields(ty); | 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 | for (struct_obj.fields.values()) |field| { | 2469 | for (struct_obj.fields.values()) |field| { |
| 2467 | if (field.is_comptime) continue; | 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 | return true; | 2472 | return true; |
| 2470 | } else { | 2473 | } else { |
| 2471 | return false; | 2474 | return false; |
| ... | @@ -2474,7 +2477,7 @@ pub const Type = extern union { | ... | @@ -2474,7 +2477,7 @@ pub const Type = extern union { |
| 2474 | | 2477 | |
| 2475 | .enum_full => { | 2478 | .enum_full => { |
| 2476 | const enum_full = ty.castTag(.enum_full).?.data; | 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 | .enum_simple => { | 2482 | .enum_simple => { |
| 2480 | const enum_simple = ty.castTag(.enum_simple).?.data; | 2483 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| ... | @@ -2483,17 +2486,18 @@ pub const Type = extern union { | ... | @@ -2483,17 +2486,18 @@ pub const Type = extern union { |
| 2483 | .enum_numbered, .enum_nonexhaustive => { | 2486 | .enum_numbered, .enum_nonexhaustive => { |
| 2484 | var buffer: Payload.Bits = undefined; | 2487 | var buffer: Payload.Bits = undefined; |
| 2485 | const int_tag_ty = ty.intTagType(&buffer); | 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 | .@"union" => { | 2492 | .@"union" => { |
| 2490 | const union_obj = ty.castTag(.@"union").?.data; | 2493 | const union_obj = ty.castTag(.@"union").?.data; |
| 2491 | if (opt_sema) |sema| { | 2494 | switch (strat) { |
| 2492 | _ = try sema.resolveTypeFields(ty); | 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 | for (union_obj.fields.values()) |value| { | 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 | return true; | 2501 | return true; |
| 2498 | } else { | 2502 | } else { |
| 2499 | return false; | 2503 | return false; |
| ... | @@ -2501,16 +2505,17 @@ pub const Type = extern union { | ... | @@ -2501,16 +2505,17 @@ pub const Type = extern union { |
| 2501 | }, | 2505 | }, |
| 2502 | .union_safety_tagged, .union_tagged => { | 2506 | .union_safety_tagged, .union_tagged => { |
| 2503 | const union_obj = ty.cast(Payload.Union).?.data; | 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 | return true; | 2509 | return true; |
| 2506 | } | 2510 | } |
| 2507 | | 2511 | |
| 2508 | if (opt_sema) |sema| { | 2512 | switch (strat) { |
| 2509 | _ = try sema.resolveTypeFields(ty); | 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 | for (union_obj.fields.values()) |value| { | 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 | return true; | 2519 | return true; |
| 2515 | } else { | 2520 | } else { |
| 2516 | return false; | 2521 | return false; |
| ... | @@ -2518,9 +2523,9 @@ pub const Type = extern union { | ... | @@ -2518,9 +2523,9 @@ pub const Type = extern union { |
| 2518 | }, | 2523 | }, |
| 2519 | | 2524 | |
| 2520 | .array, .vector => return ty.arrayLen() != 0 and | 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 | .array_u8 => return ty.arrayLen() != 0, | 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 | .int_signed, .int_unsigned => return ty.cast(Payload.Bits).?.data != 0, | 2530 | .int_signed, .int_unsigned => return ty.cast(Payload.Bits).?.data != 0, |
| 2526 | | 2531 | |
| ... | @@ -2529,7 +2534,7 @@ pub const Type = extern union { | ... | @@ -2529,7 +2534,7 @@ pub const Type = extern union { |
| 2529 | for (tuple.types) |field_ty, i| { | 2534 | for (tuple.types) |field_ty, i| { |
| 2530 | const val = tuple.values[i]; | 2535 | const val = tuple.values[i]; |
| 2531 | if (val.tag() != .unreachable_value) continue; // comptime field | 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 | return false; | 2539 | return false; |
| 2535 | }, | 2540 | }, |
| ... | @@ -2665,11 +2670,11 @@ pub const Type = extern union { | ... | @@ -2665,11 +2670,11 @@ pub const Type = extern union { |
| 2665 | } | 2670 | } |
| 2666 | | 2671 | |
| 2667 | pub fn hasRuntimeBits(ty: Type) bool { | 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 | pub fn hasRuntimeBitsIgnoreComptime(ty: Type) bool { | 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 | pub fn isFnOrHasRuntimeBits(ty: Type) bool { | 2680 | pub fn isFnOrHasRuntimeBits(ty: Type) bool { |
| ... | @@ -2812,12 +2817,12 @@ pub const Type = extern union { | ... | @@ -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 | scalar: u32, | 2821 | scalar: u32, |
| 2817 | val: Value, | 2822 | val: Value, |
| 2818 | }; | 2823 | }; |
| 2819 | | 2824 | |
| 2820 | const AbiAlignmentAdvancedStrat = union(enum) { | 2825 | pub const AbiAlignmentAdvancedStrat = union(enum) { |
| 2821 | eager, | 2826 | eager, |
| 2822 | lazy: Allocator, | 2827 | lazy: Allocator, |
| 2823 | sema: *Sema, | 2828 | sema: *Sema, |
| ... | @@ -2971,7 +2976,10 @@ pub const Type = extern union { | ... | @@ -2971,7 +2976,10 @@ pub const Type = extern union { |
| 2971 | | 2976 | |
| 2972 | switch (strat) { | 2977 | switch (strat) { |
| 2973 | .eager, .sema => { | 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 | return AbiAlignmentAdvanced{ .scalar = 1 }; | 2983 | return AbiAlignmentAdvanced{ .scalar = 1 }; |
| 2976 | } | 2984 | } |
| 2977 | return child_type.abiAlignmentAdvanced(target, strat); | 2985 | return child_type.abiAlignmentAdvanced(target, strat); |
| ... | @@ -2990,7 +2998,10 @@ pub const Type = extern union { | ... | @@ -2990,7 +2998,10 @@ pub const Type = extern union { |
| 2990 | const code_align = abiAlignment(Type.anyerror, target); | 2998 | const code_align = abiAlignment(Type.anyerror, target); |
| 2991 | switch (strat) { | 2999 | switch (strat) { |
| 2992 | .eager, .sema => { | 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 | return AbiAlignmentAdvanced{ .scalar = code_align }; | 3005 | return AbiAlignmentAdvanced{ .scalar = code_align }; |
| 2995 | } | 3006 | } |
| 2996 | return AbiAlignmentAdvanced{ .scalar = @max( | 3007 | return AbiAlignmentAdvanced{ .scalar = @max( |
| ... | @@ -3044,7 +3055,10 @@ pub const Type = extern union { | ... | @@ -3044,7 +3055,10 @@ pub const Type = extern union { |
| 3044 | const fields = ty.structFields(); | 3055 | const fields = ty.structFields(); |
| 3045 | var big_align: u32 = 0; | 3056 | var big_align: u32 = 0; |
| 3046 | for (fields.values()) |field| { | 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 | const field_align = if (field.abi_align != 0) | 3063 | const field_align = if (field.abi_align != 0) |
| 3050 | field.abi_align | 3064 | field.abi_align |
| ... | @@ -3161,7 +3175,10 @@ pub const Type = extern union { | ... | @@ -3161,7 +3175,10 @@ pub const Type = extern union { |
| 3161 | var max_align: u32 = 0; | 3175 | var max_align: u32 = 0; |
| 3162 | if (have_tag) max_align = union_obj.tag_ty.abiAlignment(target); | 3176 | if (have_tag) max_align = union_obj.tag_ty.abiAlignment(target); |
| 3163 | for (union_obj.fields.values()) |field| { | 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 | const field_align = if (field.abi_align != 0) | 3183 | const field_align = if (field.abi_align != 0) |
| 3167 | field.abi_align | 3184 | field.abi_align |