authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-26 00:33:14-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-26 00:33:14-07:00
logaf844931b2600e50e586436dee0d607d67ed9ff2
treec76003ccb51808c017ad6401d617729847f4ffa7
parent6ef761307ce286f4c6955ce2e7627e9a0d6ec442

stage2: resolve types more lazily

This avoids unwanted "foo depends on itself" compilation errors.

4 files changed, 118 insertions(+), 94 deletions(-)

src/Module.zig+5-1
...@@ -3904,7 +3904,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {...@@ -3904,7 +3904,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
3904 // Note this resolves the type of the Decl, not the value; if this Decl3904 // Note this resolves the type of the Decl, not the value; if this Decl
3905 // is a struct, for example, this resolves `type` (which needs no resolution),3905 // is a struct, for example, this resolves `type` (which needs no resolution),
3906 // not the struct itself.3906 // not the struct itself.
3907 try sema.resolveTypeFully(&block_scope, src, decl_tv.ty);3907 try sema.resolveTypeLayout(&block_scope, src, decl_tv.ty);
39083908
3909 const decl_arena_state = try decl_arena_allocator.create(std.heap.ArenaAllocator.State);3909 const decl_arena_state = try decl_arena_allocator.create(std.heap.ArenaAllocator.State);
39103910
...@@ -4049,6 +4049,10 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {...@@ -4049,6 +4049,10 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
4049 if (has_runtime_bits) {4049 if (has_runtime_bits) {
4050 log.debug("queue linker work for {*} ({s})", .{ decl, decl.name });4050 log.debug("queue linker work for {*} ({s})", .{ decl, decl.name });
40514051
4052 // Needed for codegen_decl which will call updateDecl and then the
4053 // codegen backend wants full access to the Decl Type.
4054 try sema.resolveTypeFully(&block_scope, src, decl.ty);
4055
4052 try mod.comp.bin_file.allocateDeclIndexes(decl);4056 try mod.comp.bin_file.allocateDeclIndexes(decl);
4053 try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl });4057 try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl });
40544058
src/Sema.zig+6-10
...@@ -10880,9 +10880,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -10880,9 +10880,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
10880 .Pointer => {10880 .Pointer => {
10881 const info = ty.ptrInfo().data;10881 const info = ty.ptrInfo().data;
10882 const alignment = if (info.@"align" != 0)10882 const alignment = if (info.@"align" != 0)
10883 info.@"align"10883 try Value.Tag.int_u64.create(sema.arena, info.@"align")
10884 else10884 else
10885 try sema.typeAbiAlignment(block, src, info.pointee_type);10885 try info.pointee_type.lazyAbiAlignment(target, sema.arena);
1088610886
10887 const field_values = try sema.arena.create([8]Value);10887 const field_values = try sema.arena.create([8]Value);
10888 field_values.* = .{10888 field_values.* = .{
...@@ -10893,7 +10893,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -10893,7 +10893,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
10893 // is_volatile: bool,10893 // is_volatile: bool,
10894 Value.makeBool(info.@"volatile"),10894 Value.makeBool(info.@"volatile"),
10895 // alignment: comptime_int,10895 // alignment: comptime_int,
10896 try Value.Tag.int_u64.create(sema.arena, alignment),10896 alignment,
10897 // address_space: AddressSpace10897 // address_space: AddressSpace
10898 try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(info.@"addrspace")),10898 try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(info.@"addrspace")),
10899 // child: type,10899 // child: type,
...@@ -11322,8 +11322,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -11322,8 +11322,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
11322 const is_comptime = field_val.tag() != .unreachable_value;11322 const is_comptime = field_val.tag() != .unreachable_value;
11323 const opt_default_val = if (is_comptime) field_val else null;11323 const opt_default_val = if (is_comptime) field_val else null;
11324 const default_val_ptr = try sema.optRefValue(block, src, field_ty, opt_default_val);11324 const default_val_ptr = try sema.optRefValue(block, src, field_ty, opt_default_val);
11325 const alignment = field_ty.abiAlignment(target);
11326
11327 struct_field_fields.* = .{11325 struct_field_fields.* = .{
11328 // name: []const u8,11326 // name: []const u8,
11329 name_val,11327 name_val,
...@@ -11334,7 +11332,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -11334,7 +11332,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
11334 // is_comptime: bool,11332 // is_comptime: bool,
11335 Value.makeBool(is_comptime),11333 Value.makeBool(is_comptime),
11336 // alignment: comptime_int,11334 // alignment: comptime_int,
11337 try Value.Tag.int_u64.create(fields_anon_decl.arena(), alignment),11335 try field_ty.lazyAbiAlignment(target, fields_anon_decl.arena()),
11338 };11336 };
11339 struct_field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), struct_field_fields);11337 struct_field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), struct_field_fields);
11340 }11338 }
...@@ -22749,11 +22747,9 @@ fn typeAbiSize(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !u64 {...@@ -22749,11 +22747,9 @@ fn typeAbiSize(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !u64 {
22749 return ty.abiSize(target);22747 return ty.abiSize(target);
22750}22748}
2275122749
22752/// TODO merge with Type.abiAlignmentAdvanced22750fn typeAbiAlignment(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!u32 {
22753fn typeAbiAlignment(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !u32 {
22754 try sema.resolveTypeLayout(block, src, ty);
22755 const target = sema.mod.getTarget();22751 const target = sema.mod.getTarget();
22756 return ty.abiAlignment(target);22752 return (try ty.abiAlignmentAdvanced(target, .{ .sema_kit = sema.kit(block, src) })).scalar;
22757}22753}
2275822754
22759/// Not valid to call for packed unions.22755/// Not valid to call for packed unions.
src/type.zig+104-81
...@@ -2691,31 +2691,41 @@ pub const Type = extern union {...@@ -2691,31 +2691,41 @@ pub const Type = extern union {
26912691
2692 /// Returns 0 for 0-bit types.2692 /// Returns 0 for 0-bit types.
2693 pub fn abiAlignment(ty: Type, target: Target) u32 {2693 pub fn abiAlignment(ty: Type, target: Target) u32 {
2694 return ty.abiAlignmentAdvanced(target, .eager).scalar;2694 return (ty.abiAlignmentAdvanced(target, .eager) catch unreachable).scalar;
2695 }2695 }
26962696
2697 /// May capture a reference to `ty`.2697 /// May capture a reference to `ty`.
2698 pub fn lazyAbiAlignment(ty: Type, target: Target, arena: Allocator) !Value {2698 pub fn lazyAbiAlignment(ty: Type, target: Target, arena: Allocator) !Value {
2699 switch (ty.abiAlignmentAdvanced(target, .{ .lazy = arena })) {2699 switch (try ty.abiAlignmentAdvanced(target, .{ .lazy = arena })) {
2700 .val => |val| return try val,2700 .val => |val| return val,
2701 .scalar => |x| return Value.Tag.int_u64.create(arena, x),2701 .scalar => |x| return Value.Tag.int_u64.create(arena, x),
2702 }2702 }
2703 }2703 }
27042704
2705 const AbiAlignmentAdvanced = union(enum) {
2706 scalar: u32,
2707 val: Value,
2708 };
2709
2705 /// If you pass `eager` you will get back `scalar` and assert the type is resolved.2710 /// If you pass `eager` you will get back `scalar` and assert the type is resolved.
2711 /// In this case there will be no error, guaranteed.
2706 /// If you pass `lazy` you may get back `scalar` or `val`.2712 /// If you pass `lazy` you may get back `scalar` or `val`.
2707 /// If `val` is returned, a reference to `ty` has been captured.2713 /// If `val` is returned, a reference to `ty` has been captured.
2708 fn abiAlignmentAdvanced(2714 /// If you pass `sema_kit` you will get back `scalar` and resolve the type if
2715 /// necessary, possibly returning a CompileError.
2716 pub fn abiAlignmentAdvanced(
2709 ty: Type,2717 ty: Type,
2710 target: Target,2718 target: Target,
2711 strat: union(enum) {2719 strat: union(enum) {
2712 eager,2720 eager,
2713 lazy: Allocator,2721 lazy: Allocator,
2722 sema_kit: Module.WipAnalysis,
2714 },2723 },
2715 ) union(enum) {2724 ) Module.CompileError!AbiAlignmentAdvanced {
2716 scalar: u32,2725 const sema_kit = switch (strat) {
2717 val: Allocator.Error!Value,2726 .sema_kit => |sk| sk,
2718 } {2727 else => null,
2728 };
2719 return switch (ty.tag()) {2729 return switch (ty.tag()) {
2720 .u1,2730 .u1,
2721 .u8,2731 .u8,
...@@ -2735,25 +2745,25 @@ pub const Type = extern union {...@@ -2735,25 +2745,25 @@ pub const Type = extern union {
2735 .extern_options,2745 .extern_options,
2736 .@"opaque",2746 .@"opaque",
2737 .anyopaque,2747 .anyopaque,
2738 => return .{ .scalar = 1 },2748 => return AbiAlignmentAdvanced{ .scalar = 1 },
27392749
2740 .fn_noreturn_no_args, // represents machine code; not a pointer2750 .fn_noreturn_no_args, // represents machine code; not a pointer
2741 .fn_void_no_args, // represents machine code; not a pointer2751 .fn_void_no_args, // represents machine code; not a pointer
2742 .fn_naked_noreturn_no_args, // represents machine code; not a pointer2752 .fn_naked_noreturn_no_args, // represents machine code; not a pointer
2743 .fn_ccc_void_no_args, // represents machine code; not a pointer2753 .fn_ccc_void_no_args, // represents machine code; not a pointer
2744 => return .{ .scalar = target_util.defaultFunctionAlignment(target) },2754 => return AbiAlignmentAdvanced{ .scalar = target_util.defaultFunctionAlignment(target) },
27452755
2746 // represents machine code; not a pointer2756 // represents machine code; not a pointer
2747 .function => {2757 .function => {
2748 const alignment = ty.castTag(.function).?.data.alignment;2758 const alignment = ty.castTag(.function).?.data.alignment;
2749 if (alignment != 0) return .{ .scalar = alignment };2759 if (alignment != 0) return AbiAlignmentAdvanced{ .scalar = alignment };
2750 return .{ .scalar = target_util.defaultFunctionAlignment(target) };2760 return AbiAlignmentAdvanced{ .scalar = target_util.defaultFunctionAlignment(target) };
2751 },2761 },
27522762
2753 .i16, .u16 => return .{ .scalar = 2 },2763 .i16, .u16 => return AbiAlignmentAdvanced{ .scalar = 2 },
2754 .i32, .u32 => return .{ .scalar = 4 },2764 .i32, .u32 => return AbiAlignmentAdvanced{ .scalar = 4 },
2755 .i64, .u64 => return .{ .scalar = 8 },2765 .i64, .u64 => return AbiAlignmentAdvanced{ .scalar = 8 },
2756 .u128, .i128 => return .{ .scalar = 16 },2766 .u128, .i128 => return AbiAlignmentAdvanced{ .scalar = 16 },
27572767
2758 .isize,2768 .isize,
2759 .usize,2769 .usize,
...@@ -2776,40 +2786,40 @@ pub const Type = extern union {...@@ -2776,40 +2786,40 @@ pub const Type = extern union {
2776 .manyptr_const_u8_sentinel_0,2786 .manyptr_const_u8_sentinel_0,
2777 .@"anyframe",2787 .@"anyframe",
2778 .anyframe_T,2788 .anyframe_T,
2779 => return .{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) },2789 => return AbiAlignmentAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) },
27802790
2781 .c_short => return .{ .scalar = @divExact(CType.short.sizeInBits(target), 8) },2791 .c_short => return AbiAlignmentAdvanced{ .scalar = @divExact(CType.short.sizeInBits(target), 8) },
2782 .c_ushort => return .{ .scalar = @divExact(CType.ushort.sizeInBits(target), 8) },2792 .c_ushort => return AbiAlignmentAdvanced{ .scalar = @divExact(CType.ushort.sizeInBits(target), 8) },
2783 .c_int => return .{ .scalar = @divExact(CType.int.sizeInBits(target), 8) },2793 .c_int => return AbiAlignmentAdvanced{ .scalar = @divExact(CType.int.sizeInBits(target), 8) },
2784 .c_uint => return .{ .scalar = @divExact(CType.uint.sizeInBits(target), 8) },2794 .c_uint => return AbiAlignmentAdvanced{ .scalar = @divExact(CType.uint.sizeInBits(target), 8) },
2785 .c_long => return .{ .scalar = @divExact(CType.long.sizeInBits(target), 8) },2795 .c_long => return AbiAlignmentAdvanced{ .scalar = @divExact(CType.long.sizeInBits(target), 8) },
2786 .c_ulong => return .{ .scalar = @divExact(CType.ulong.sizeInBits(target), 8) },2796 .c_ulong => return AbiAlignmentAdvanced{ .scalar = @divExact(CType.ulong.sizeInBits(target), 8) },
2787 .c_longlong => return .{ .scalar = @divExact(CType.longlong.sizeInBits(target), 8) },2797 .c_longlong => return AbiAlignmentAdvanced{ .scalar = @divExact(CType.longlong.sizeInBits(target), 8) },
2788 .c_ulonglong => return .{ .scalar = @divExact(CType.ulonglong.sizeInBits(target), 8) },2798 .c_ulonglong => return AbiAlignmentAdvanced{ .scalar = @divExact(CType.ulonglong.sizeInBits(target), 8) },
27892799
2790 .f16 => return .{ .scalar = 2 },2800 .f16 => return AbiAlignmentAdvanced{ .scalar = 2 },
2791 .f32 => return .{ .scalar = 4 },2801 .f32 => return AbiAlignmentAdvanced{ .scalar = 4 },
2792 .f64 => return .{ .scalar = 8 },2802 .f64 => return AbiAlignmentAdvanced{ .scalar = 8 },
2793 .f128 => return .{ .scalar = 16 },2803 .f128 => return AbiAlignmentAdvanced{ .scalar = 16 },
27942804
2795 .f80 => switch (target.cpu.arch) {2805 .f80 => switch (target.cpu.arch) {
2796 .i386 => return .{ .scalar = 4 },2806 .i386 => return AbiAlignmentAdvanced{ .scalar = 4 },
2797 .x86_64 => return .{ .scalar = 16 },2807 .x86_64 => return AbiAlignmentAdvanced{ .scalar = 16 },
2798 else => {2808 else => {
2799 var payload: Payload.Bits = .{2809 var payload: Payload.Bits = .{
2800 .base = .{ .tag = .int_unsigned },2810 .base = .{ .tag = .int_unsigned },
2801 .data = 80,2811 .data = 80,
2802 };2812 };
2803 const u80_ty = initPayload(&payload.base);2813 const u80_ty = initPayload(&payload.base);
2804 return .{ .scalar = abiAlignment(u80_ty, target) };2814 return AbiAlignmentAdvanced{ .scalar = abiAlignment(u80_ty, target) };
2805 },2815 },
2806 },2816 },
2807 .c_longdouble => switch (CType.longdouble.sizeInBits(target)) {2817 .c_longdouble => switch (CType.longdouble.sizeInBits(target)) {
2808 16 => return .{ .scalar = abiAlignment(Type.f16, target) },2818 16 => return AbiAlignmentAdvanced{ .scalar = abiAlignment(Type.f16, target) },
2809 32 => return .{ .scalar = abiAlignment(Type.f32, target) },2819 32 => return AbiAlignmentAdvanced{ .scalar = abiAlignment(Type.f32, target) },
2810 64 => return .{ .scalar = abiAlignment(Type.f64, target) },2820 64 => return AbiAlignmentAdvanced{ .scalar = abiAlignment(Type.f64, target) },
2811 80 => return .{ .scalar = abiAlignment(Type.f80, target) },2821 80 => return AbiAlignmentAdvanced{ .scalar = abiAlignment(Type.f80, target) },
2812 128 => return .{ .scalar = abiAlignment(Type.f128, target) },2822 128 => return AbiAlignmentAdvanced{ .scalar = abiAlignment(Type.f128, target) },
2813 else => unreachable,2823 else => unreachable,
2814 },2824 },
28152825
...@@ -2819,22 +2829,22 @@ pub const Type = extern union {...@@ -2819,22 +2829,22 @@ pub const Type = extern union {
2819 .anyerror,2829 .anyerror,
2820 .error_set_inferred,2830 .error_set_inferred,
2821 .error_set_merged,2831 .error_set_merged,
2822 => return .{ .scalar = 2 }, // TODO revisit this when we have the concept of the error tag type2832 => return AbiAlignmentAdvanced{ .scalar = 2 }, // TODO revisit this when we have the concept of the error tag type
28232833
2824 .array, .array_sentinel => return ty.elemType().abiAlignmentAdvanced(target, strat),2834 .array, .array_sentinel => return ty.elemType().abiAlignmentAdvanced(target, strat),
28252835
2826 // TODO audit this - is there any more complicated logic to determine2836 // TODO audit this - is there any more complicated logic to determine
2827 // ABI alignment of vectors?2837 // ABI alignment of vectors?
2828 .vector => return .{ .scalar = 16 },2838 .vector => return AbiAlignmentAdvanced{ .scalar = 16 },
28292839
2830 .int_signed, .int_unsigned => {2840 .int_signed, .int_unsigned => {
2831 const bits: u16 = ty.cast(Payload.Bits).?.data;2841 const bits: u16 = ty.cast(Payload.Bits).?.data;
2832 if (bits == 0) return .{ .scalar = 0 };2842 if (bits == 0) return AbiAlignmentAdvanced{ .scalar = 0 };
2833 if (bits <= 8) return .{ .scalar = 1 };2843 if (bits <= 8) return AbiAlignmentAdvanced{ .scalar = 1 };
2834 if (bits <= 16) return .{ .scalar = 2 };2844 if (bits <= 16) return AbiAlignmentAdvanced{ .scalar = 2 };
2835 if (bits <= 32) return .{ .scalar = 4 };2845 if (bits <= 32) return AbiAlignmentAdvanced{ .scalar = 4 };
2836 if (bits <= 64) return .{ .scalar = 8 };2846 if (bits <= 64) return AbiAlignmentAdvanced{ .scalar = 8 };
2837 return .{ .scalar = 16 };2847 return AbiAlignmentAdvanced{ .scalar = 16 };
2838 },2848 },
28392849
2840 .optional => {2850 .optional => {
...@@ -2842,17 +2852,19 @@ pub const Type = extern union {...@@ -2842,17 +2852,19 @@ pub const Type = extern union {
2842 const child_type = ty.optionalChild(&buf);2852 const child_type = ty.optionalChild(&buf);
28432853
2844 if (child_type.zigTypeTag() == .Pointer and !child_type.isCPtr()) {2854 if (child_type.zigTypeTag() == .Pointer and !child_type.isCPtr()) {
2845 return .{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) };2855 return AbiAlignmentAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) };
2846 }2856 }
28472857
2848 switch (strat) {2858 switch (strat) {
2849 .eager => {2859 .eager, .sema_kit => {
2850 if (!child_type.hasRuntimeBits()) return .{ .scalar = 1 };2860 if (!(try child_type.hasRuntimeBitsAdvanced(false, sema_kit))) {
2851 return .{ .scalar = child_type.abiAlignment(target) };2861 return AbiAlignmentAdvanced{ .scalar = 1 };
2862 }
2863 return child_type.abiAlignmentAdvanced(target, strat);
2852 },2864 },
2853 .lazy => |arena| switch (child_type.abiAlignmentAdvanced(target, strat)) {2865 .lazy => |arena| switch (try child_type.abiAlignmentAdvanced(target, strat)) {
2854 .scalar => |x| return .{ .scalar = @maximum(x, 1) },2866 .scalar => |x| return AbiAlignmentAdvanced{ .scalar = @maximum(x, 1) },
2855 .val => return .{ .val = Value.Tag.lazy_align.create(arena, ty) },2867 .val => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
2856 },2868 },
2857 }2869 }
2858 },2870 },
...@@ -2860,60 +2872,64 @@ pub const Type = extern union {...@@ -2860,60 +2872,64 @@ pub const Type = extern union {
2860 .error_union => {2872 .error_union => {
2861 const data = ty.castTag(.error_union).?.data;2873 const data = ty.castTag(.error_union).?.data;
2862 switch (strat) {2874 switch (strat) {
2863 .eager => {2875 .eager, .sema_kit => {
2864 if (!data.error_set.hasRuntimeBits()) {2876 if (!(try data.error_set.hasRuntimeBitsAdvanced(false, sema_kit))) {
2865 return .{ .scalar = data.payload.abiAlignment(target) };2877 return data.payload.abiAlignmentAdvanced(target, strat);
2866 } else if (!data.payload.hasRuntimeBits()) {2878 } else if (!(try data.payload.hasRuntimeBitsAdvanced(false, sema_kit))) {
2867 return .{ .scalar = data.error_set.abiAlignment(target) };2879 return data.error_set.abiAlignmentAdvanced(target, strat);
2868 }2880 }
2869 return .{ .scalar = @maximum(2881 return AbiAlignmentAdvanced{ .scalar = @maximum(
2870 data.payload.abiAlignment(target),2882 (try data.payload.abiAlignmentAdvanced(target, strat)).scalar,
2871 data.error_set.abiAlignment(target),2883 (try data.error_set.abiAlignmentAdvanced(target, strat)).scalar,
2872 ) };2884 ) };
2873 },2885 },
2874 .lazy => |arena| {2886 .lazy => |arena| {
2875 switch (data.payload.abiAlignmentAdvanced(target, strat)) {2887 switch (try data.payload.abiAlignmentAdvanced(target, strat)) {
2876 .scalar => |payload_align| {2888 .scalar => |payload_align| {
2877 if (payload_align == 0) {2889 if (payload_align == 0) {
2878 return data.error_set.abiAlignmentAdvanced(target, strat);2890 return data.error_set.abiAlignmentAdvanced(target, strat);
2879 }2891 }
2880 switch (data.error_set.abiAlignmentAdvanced(target, strat)) {2892 switch (try data.error_set.abiAlignmentAdvanced(target, strat)) {
2881 .scalar => |err_set_align| {2893 .scalar => |err_set_align| {
2882 return .{ .scalar = @maximum(payload_align, err_set_align) };2894 return AbiAlignmentAdvanced{ .scalar = @maximum(payload_align, err_set_align) };
2883 },2895 },
2884 .val => {},2896 .val => {},
2885 }2897 }
2886 },2898 },
2887 .val => {},2899 .val => {},
2888 }2900 }
2889 return .{ .val = Value.Tag.lazy_align.create(arena, ty) };2901 return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) };
2890 },2902 },
2891 }2903 }
2892 },2904 },
28932905
2894 .@"struct" => {2906 .@"struct" => {
2907 if (sema_kit) |sk| {
2908 try sk.sema.resolveTypeLayout(sk.block, sk.src, ty);
2909 }
2895 if (ty.castTag(.@"struct")) |payload| {2910 if (ty.castTag(.@"struct")) |payload| {
2896 const struct_obj = payload.data;2911 const struct_obj = payload.data;
2897 if (!struct_obj.haveLayout()) switch (strat) {2912 if (!struct_obj.haveLayout()) switch (strat) {
2898 .eager => unreachable, // struct layout not resolved2913 .eager => unreachable, // struct layout not resolved
2899 .lazy => |arena| return .{ .val = Value.Tag.lazy_align.create(arena, ty) },2914 .sema_kit => unreachable, // handled above
2915 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
2900 };2916 };
2901 if (struct_obj.layout == .Packed) {2917 if (struct_obj.layout == .Packed) {
2902 var buf: Type.Payload.Bits = undefined;2918 var buf: Type.Payload.Bits = undefined;
2903 const int_ty = struct_obj.packedIntegerType(target, &buf);2919 const int_ty = struct_obj.packedIntegerType(target, &buf);
2904 return .{ .scalar = int_ty.abiAlignment(target) };2920 return AbiAlignmentAdvanced{ .scalar = int_ty.abiAlignment(target) };
2905 }2921 }
2906 }2922 }
29072923
2908 const fields = ty.structFields();2924 const fields = ty.structFields();
2909 var big_align: u32 = 0;2925 var big_align: u32 = 0;
2910 for (fields.values()) |field| {2926 for (fields.values()) |field| {
2911 if (!field.ty.hasRuntimeBits()) continue;2927 if (!(try field.ty.hasRuntimeBitsAdvanced(false, sema_kit))) continue;
29122928
2913 const field_align = field.normalAlignment(target);2929 const field_align = field.normalAlignment(target);
2914 big_align = @maximum(big_align, field_align);2930 big_align = @maximum(big_align, field_align);
2915 }2931 }
2916 return .{ .scalar = big_align };2932 return AbiAlignmentAdvanced{ .scalar = big_align };
2917 },2933 },
29182934
2919 .tuple, .anon_struct => {2935 .tuple, .anon_struct => {
...@@ -2923,34 +2939,41 @@ pub const Type = extern union {...@@ -2923,34 +2939,41 @@ pub const Type = extern union {
2923 const val = tuple.values[i];2939 const val = tuple.values[i];
2924 if (val.tag() != .unreachable_value) continue; // comptime field2940 if (val.tag() != .unreachable_value) continue; // comptime field
29252941
2926 switch (field_ty.abiAlignmentAdvanced(target, strat)) {2942 switch (try field_ty.abiAlignmentAdvanced(target, strat)) {
2927 .scalar => |field_align| big_align = @maximum(big_align, field_align),2943 .scalar => |field_align| big_align = @maximum(big_align, field_align),
2928 .val => switch (strat) {2944 .val => switch (strat) {
2929 .eager => unreachable, // field type alignment not resolved2945 .eager => unreachable, // field type alignment not resolved
2930 .lazy => |arena| return .{ .val = Value.Tag.lazy_align.create(arena, ty) },2946 .sema_kit => unreachable, // passed to abiAlignmentAdvanced above
2947 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
2931 },2948 },
2932 }2949 }
2933 }2950 }
2934 return .{ .scalar = big_align };2951 return AbiAlignmentAdvanced{ .scalar = big_align };
2935 },2952 },
29362953
2937 .enum_full, .enum_nonexhaustive, .enum_simple, .enum_numbered => {2954 .enum_full, .enum_nonexhaustive, .enum_simple, .enum_numbered => {
2938 var buffer: Payload.Bits = undefined;2955 var buffer: Payload.Bits = undefined;
2939 const int_tag_ty = ty.intTagType(&buffer);2956 const int_tag_ty = ty.intTagType(&buffer);
2940 return .{ .scalar = int_tag_ty.abiAlignment(target) };2957 return AbiAlignmentAdvanced{ .scalar = int_tag_ty.abiAlignment(target) };
2941 },2958 },
2942 .@"union" => switch (strat) {2959 .@"union" => switch (strat) {
2943 .eager => {2960 .eager, .sema_kit => {
2961 if (sema_kit) |sk| {
2962 try sk.sema.resolveTypeLayout(sk.block, sk.src, ty);
2963 }
2944 // TODO pass `true` for have_tag when unions have a safety tag2964 // TODO pass `true` for have_tag when unions have a safety tag
2945 return .{ .scalar = ty.castTag(.@"union").?.data.abiAlignment(target, false) };2965 return AbiAlignmentAdvanced{ .scalar = ty.castTag(.@"union").?.data.abiAlignment(target, false) };
2946 },2966 },
2947 .lazy => |arena| return .{ .val = Value.Tag.lazy_align.create(arena, ty) },2967 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
2948 },2968 },
2949 .union_tagged => switch (strat) {2969 .union_tagged => switch (strat) {
2950 .eager => {2970 .eager, .sema_kit => {
2951 return .{ .scalar = ty.castTag(.union_tagged).?.data.abiAlignment(target, true) };2971 if (sema_kit) |sk| {
2972 try sk.sema.resolveTypeLayout(sk.block, sk.src, ty);
2973 }
2974 return AbiAlignmentAdvanced{ .scalar = ty.castTag(.union_tagged).?.data.abiAlignment(target, true) };
2952 },2975 },
2953 .lazy => |arena| return .{ .val = Value.Tag.lazy_align.create(arena, ty) },2976 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
2954 },2977 },
29552978
2956 .empty_struct,2979 .empty_struct,
...@@ -2963,7 +2986,7 @@ pub const Type = extern union {...@@ -2963,7 +2986,7 @@ pub const Type = extern union {
2963 .@"undefined",2986 .@"undefined",
2964 .enum_literal,2987 .enum_literal,
2965 .type_info,2988 .type_info,
2966 => return .{ .scalar = 0 },2989 => return AbiAlignmentAdvanced{ .scalar = 0 },
29672990
2968 .noreturn,2991 .noreturn,
2969 .inferred_alloc_const,2992 .inferred_alloc_const,
src/value.zig+3-2
...@@ -1076,9 +1076,10 @@ pub const Value = extern union {...@@ -1076,9 +1076,10 @@ pub const Value = extern union {
1076 .lazy_align => {1076 .lazy_align => {
1077 const ty = val.castTag(.lazy_align).?.data;1077 const ty = val.castTag(.lazy_align).?.data;
1078 if (sema_kit) |sk| {1078 if (sema_kit) |sk| {
1079 try sk.sema.resolveTypeLayout(sk.block, sk.src, ty);1079 return (try ty.abiAlignmentAdvanced(target, .{ .sema_kit = sk })).scalar;
1080 } else {
1081 return ty.abiAlignment(target);
1080 }1082 }
1081 return ty.abiAlignment(target);
1082 },1083 },
10831084
1084 else => return null,1085 else => return null,