| author | |
| committer | |
| log | 7d50634e0ad4355e339bc243a2e2842693e133f9 |
| tree | cd6f81b82b20532d40e0944e6a814519ebf7cb41 |
| parent | 3cd3052d4d303dbae7d517fa40f6d171c957afdd |
| parent | 3d7c6c803b788138aa08f51cf4ee8cf7892e315d |
| signature |
migrate make_ptr_const to new anonymous decl mechanism25 files changed, 336 insertions(+), 152 deletions(-)
lib/std/elf.zig+12-12| ... | @@ -782,10 +782,10 @@ pub const Elf32_Sym = extern struct { | ... | @@ -782,10 +782,10 @@ pub const Elf32_Sym = extern struct { |
| 782 | st_shndx: Elf32_Section, | 782 | st_shndx: Elf32_Section, |
| 783 | 783 | ||
| 784 | pub inline fn st_type(self: @This()) u4 { | 784 | pub inline fn st_type(self: @This()) u4 { |
| 785 | return @as(u4, @truncate(self.st_info)); | 785 | return @truncate(self.st_info); |
| 786 | } | 786 | } |
| 787 | pub inline fn st_bind(self: @This()) u4 { | 787 | pub inline fn st_bind(self: @This()) u4 { |
| 788 | return @as(u4, @truncate(self.st_info >> 4)); | 788 | return @truncate(self.st_info >> 4); |
| 789 | } | 789 | } |
| 790 | }; | 790 | }; |
| 791 | pub const Elf64_Sym = extern struct { | 791 | pub const Elf64_Sym = extern struct { |
| ... | @@ -797,10 +797,10 @@ pub const Elf64_Sym = extern struct { | ... | @@ -797,10 +797,10 @@ pub const Elf64_Sym = extern struct { |
| 797 | st_size: Elf64_Xword, | 797 | st_size: Elf64_Xword, |
| 798 | 798 | ||
| 799 | pub inline fn st_type(self: @This()) u4 { | 799 | pub inline fn st_type(self: @This()) u4 { |
| 800 | return @as(u4, @truncate(self.st_info)); | 800 | return @truncate(self.st_info); |
| 801 | } | 801 | } |
| 802 | pub inline fn st_bind(self: @This()) u4 { | 802 | pub inline fn st_bind(self: @This()) u4 { |
| 803 | return @as(u4, @truncate(self.st_info >> 4)); | 803 | return @truncate(self.st_info >> 4); |
| 804 | } | 804 | } |
| 805 | }; | 805 | }; |
| 806 | pub const Elf32_Syminfo = extern struct { | 806 | pub const Elf32_Syminfo = extern struct { |
| ... | @@ -816,10 +816,10 @@ pub const Elf32_Rel = extern struct { | ... | @@ -816,10 +816,10 @@ pub const Elf32_Rel = extern struct { |
| 816 | r_info: Elf32_Word, | 816 | r_info: Elf32_Word, |
| 817 | 817 | ||
| 818 | pub inline fn r_sym(self: @This()) u24 { | 818 | pub inline fn r_sym(self: @This()) u24 { |
| 819 | return @as(u24, @truncate(self.r_info >> 8)); | 819 | return @truncate(self.r_info >> 8); |
| 820 | } | 820 | } |
| 821 | pub inline fn r_type(self: @This()) u8 { | 821 | pub inline fn r_type(self: @This()) u8 { |
| 822 | return @as(u8, @truncate(self.r_info)); | 822 | return @truncate(self.r_info); |
| 823 | } | 823 | } |
| 824 | }; | 824 | }; |
| 825 | pub const Elf64_Rel = extern struct { | 825 | pub const Elf64_Rel = extern struct { |
| ... | @@ -827,10 +827,10 @@ pub const Elf64_Rel = extern struct { | ... | @@ -827,10 +827,10 @@ pub const Elf64_Rel = extern struct { |
| 827 | r_info: Elf64_Xword, | 827 | r_info: Elf64_Xword, |
| 828 | 828 | ||
| 829 | pub inline fn r_sym(self: @This()) u32 { | 829 | pub inline fn r_sym(self: @This()) u32 { |
| 830 | return @as(u32, @truncate(self.r_info >> 32)); | 830 | return @truncate(self.r_info >> 32); |
| 831 | } | 831 | } |
| 832 | pub inline fn r_type(self: @This()) u32 { | 832 | pub inline fn r_type(self: @This()) u32 { |
| 833 | return @as(u32, @truncate(self.r_info)); | 833 | return @truncate(self.r_info); |
| 834 | } | 834 | } |
| 835 | }; | 835 | }; |
| 836 | pub const Elf32_Rela = extern struct { | 836 | pub const Elf32_Rela = extern struct { |
| ... | @@ -839,10 +839,10 @@ pub const Elf32_Rela = extern struct { | ... | @@ -839,10 +839,10 @@ pub const Elf32_Rela = extern struct { |
| 839 | r_addend: Elf32_Sword, | 839 | r_addend: Elf32_Sword, |
| 840 | 840 | ||
| 841 | pub inline fn r_sym(self: @This()) u24 { | 841 | pub inline fn r_sym(self: @This()) u24 { |
| 842 | return @as(u24, @truncate(self.r_info >> 8)); | 842 | return @truncate(self.r_info >> 8); |
| 843 | } | 843 | } |
| 844 | pub inline fn r_type(self: @This()) u8 { | 844 | pub inline fn r_type(self: @This()) u8 { |
| 845 | return @as(u8, @truncate(self.r_info)); | 845 | return @truncate(self.r_info); |
| 846 | } | 846 | } |
| 847 | }; | 847 | }; |
| 848 | pub const Elf64_Rela = extern struct { | 848 | pub const Elf64_Rela = extern struct { |
| ... | @@ -851,10 +851,10 @@ pub const Elf64_Rela = extern struct { | ... | @@ -851,10 +851,10 @@ pub const Elf64_Rela = extern struct { |
| 851 | r_addend: Elf64_Sxword, | 851 | r_addend: Elf64_Sxword, |
| 852 | 852 | ||
| 853 | pub inline fn r_sym(self: @This()) u32 { | 853 | pub inline fn r_sym(self: @This()) u32 { |
| 854 | return @as(u32, @truncate(self.r_info >> 32)); | 854 | return @truncate(self.r_info >> 32); |
| 855 | } | 855 | } |
| 856 | pub inline fn r_type(self: @This()) u32 { | 856 | pub inline fn r_type(self: @This()) u32 { |
| 857 | return @as(u32, @truncate(self.r_info)); | 857 | return @truncate(self.r_info); |
| 858 | } | 858 | } |
| 859 | }; | 859 | }; |
| 860 | pub const Elf32_Dyn = extern struct { | 860 | pub const Elf32_Dyn = extern struct { |
src/AstGen.zig+6-4| ... | @@ -3123,10 +3123,10 @@ fn varDecl( | ... | @@ -3123,10 +3123,10 @@ fn varDecl( |
| 3123 | if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node)) | 3123 | if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node)) |
| 3124 | _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst }); | 3124 | _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst }); |
| 3125 | 3125 | ||
| 3126 | if (resolve_inferred_alloc != .none) { | 3126 | const const_ptr = if (resolve_inferred_alloc != .none) p: { |
| 3127 | _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node); | 3127 | _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node); |
| 3128 | } | 3128 | break :p var_ptr; |
| 3129 | const const_ptr = try gz.addUnNode(.make_ptr_const, var_ptr, node); | 3129 | } else try gz.addUnNode(.make_ptr_const, var_ptr, node); |
| 3130 | 3130 | ||
| 3131 | try gz.addDbgVar(.dbg_var_ptr, ident_name, const_ptr); | 3131 | try gz.addDbgVar(.dbg_var_ptr, ident_name, const_ptr); |
| 3132 | 3132 | ||
| ... | @@ -3533,7 +3533,9 @@ fn assignDestructureMaybeDecls( | ... | @@ -3533,7 +3533,9 @@ fn assignDestructureMaybeDecls( |
| 3533 | else => unreachable, | 3533 | else => unreachable, |
| 3534 | }; | 3534 | }; |
| 3535 | // If the alloc was const, make it const. | 3535 | // If the alloc was const, make it const. |
| 3536 | const var_ptr = if (is_const) make_const: { | 3536 | const var_ptr = if (is_const and full.ast.type_node != 0) make_const: { |
| 3537 | // Note that we don't do this if type_node == 0 since `resolve_inferred_alloc` | ||
| 3538 | // handles it for us. | ||
| 3537 | break :make_const try gz.addUnNode(.make_ptr_const, raw_ptr, node); | 3539 | break :make_const try gz.addUnNode(.make_ptr_const, raw_ptr, node); |
| 3538 | } else raw_ptr; | 3540 | } else raw_ptr; |
| 3539 | const name_token = full.ast.mut_token + 1; | 3541 | const name_token = full.ast.mut_token + 1; |
src/Compilation.zig+1| ... | @@ -3545,6 +3545,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v | ... | @@ -3545,6 +3545,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v |
| 3545 | .fwd_decl = fwd_decl.toManaged(gpa), | 3545 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 3546 | .ctypes = .{}, | 3546 | .ctypes = .{}, |
| 3547 | .anon_decl_deps = .{}, | 3547 | .anon_decl_deps = .{}, |
| 3548 | .aligned_anon_decls = .{}, | ||
| 3548 | }; | 3549 | }; |
| 3549 | defer { | 3550 | defer { |
| 3550 | dg.ctypes.deinit(gpa); | 3551 | dg.ctypes.deinit(gpa); |
src/InternPool.zig+86-14| ... | @@ -1074,7 +1074,7 @@ pub const Key = union(enum) { | ... | @@ -1074,7 +1074,7 @@ pub const Key = union(enum) { |
| 1074 | 1074 | ||
| 1075 | decl: Module.Decl.Index, | 1075 | decl: Module.Decl.Index, |
| 1076 | mut_decl: MutDecl, | 1076 | mut_decl: MutDecl, |
| 1077 | anon_decl: Index, | 1077 | anon_decl: AnonDecl, |
| 1078 | comptime_field: Index, | 1078 | comptime_field: Index, |
| 1079 | int: Index, | 1079 | int: Index, |
| 1080 | eu_payload: Index, | 1080 | eu_payload: Index, |
| ... | @@ -1090,6 +1090,14 @@ pub const Key = union(enum) { | ... | @@ -1090,6 +1090,14 @@ pub const Key = union(enum) { |
| 1090 | base: Index, | 1090 | base: Index, |
| 1091 | index: u64, | 1091 | index: u64, |
| 1092 | }; | 1092 | }; |
| 1093 | pub const AnonDecl = extern struct { | ||
| 1094 | val: Index, | ||
| 1095 | /// Contains the canonical pointer type of the anonymous | ||
| 1096 | /// declaration. This may equal `ty` of the `Ptr` or it may be | ||
| 1097 | /// different. Importantly, when lowering the anonymous decl, | ||
| 1098 | /// the original pointer type alignment must be used. | ||
| 1099 | orig_ty: Index, | ||
| 1100 | }; | ||
| 1093 | }; | 1101 | }; |
| 1094 | }; | 1102 | }; |
| 1095 | 1103 | ||
| ... | @@ -1231,7 +1239,8 @@ pub const Key = union(enum) { | ... | @@ -1231,7 +1239,8 @@ pub const Key = union(enum) { |
| 1231 | common ++ asBytes(&x.decl) ++ asBytes(&x.runtime_index), | 1239 | common ++ asBytes(&x.decl) ++ asBytes(&x.runtime_index), |
| 1232 | ), | 1240 | ), |
| 1233 | 1241 | ||
| 1234 | .anon_decl, | 1242 | .anon_decl => |x| Hash.hash(seed2, common ++ asBytes(&x)), |
| 1243 | |||
| 1235 | .int, | 1244 | .int, |
| 1236 | .eu_payload, | 1245 | .eu_payload, |
| 1237 | .opt_payload, | 1246 | .opt_payload, |
| ... | @@ -1500,7 +1509,8 @@ pub const Key = union(enum) { | ... | @@ -1500,7 +1509,8 @@ pub const Key = union(enum) { |
| 1500 | return switch (a_info.addr) { | 1509 | return switch (a_info.addr) { |
| 1501 | .decl => |a_decl| a_decl == b_info.addr.decl, | 1510 | .decl => |a_decl| a_decl == b_info.addr.decl, |
| 1502 | .mut_decl => |a_mut_decl| std.meta.eql(a_mut_decl, b_info.addr.mut_decl), | 1511 | .mut_decl => |a_mut_decl| std.meta.eql(a_mut_decl, b_info.addr.mut_decl), |
| 1503 | .anon_decl => |a_decl| a_decl == b_info.addr.anon_decl, | 1512 | .anon_decl => |ad| ad.val == b_info.addr.anon_decl.val and |
| 1513 | ad.orig_ty == b_info.addr.anon_decl.orig_ty, | ||
| 1504 | .int => |a_int| a_int == b_info.addr.int, | 1514 | .int => |a_int| a_int == b_info.addr.int, |
| 1505 | .eu_payload => |a_eu_payload| a_eu_payload == b_info.addr.eu_payload, | 1515 | .eu_payload => |a_eu_payload| a_eu_payload == b_info.addr.eu_payload, |
| 1506 | .opt_payload => |a_opt_payload| a_opt_payload == b_info.addr.opt_payload, | 1516 | .opt_payload => |a_opt_payload| a_opt_payload == b_info.addr.opt_payload, |
| ... | @@ -2133,6 +2143,7 @@ pub const Index = enum(u32) { | ... | @@ -2133,6 +2143,7 @@ pub const Index = enum(u32) { |
| 2133 | ptr_decl: struct { data: *PtrDecl }, | 2143 | ptr_decl: struct { data: *PtrDecl }, |
| 2134 | ptr_mut_decl: struct { data: *PtrMutDecl }, | 2144 | ptr_mut_decl: struct { data: *PtrMutDecl }, |
| 2135 | ptr_anon_decl: struct { data: *PtrAnonDecl }, | 2145 | ptr_anon_decl: struct { data: *PtrAnonDecl }, |
| 2146 | ptr_anon_decl_aligned: struct { data: *PtrAnonDeclAligned }, | ||
| 2136 | ptr_comptime_field: struct { data: *PtrComptimeField }, | 2147 | ptr_comptime_field: struct { data: *PtrComptimeField }, |
| 2137 | ptr_int: struct { data: *PtrBase }, | 2148 | ptr_int: struct { data: *PtrBase }, |
| 2138 | ptr_eu_payload: struct { data: *PtrBase }, | 2149 | ptr_eu_payload: struct { data: *PtrBase }, |
| ... | @@ -2583,8 +2594,16 @@ pub const Tag = enum(u8) { | ... | @@ -2583,8 +2594,16 @@ pub const Tag = enum(u8) { |
| 2583 | /// data is extra index of `PtrMutDecl`, which contains the type and address. | 2594 | /// data is extra index of `PtrMutDecl`, which contains the type and address. |
| 2584 | ptr_mut_decl, | 2595 | ptr_mut_decl, |
| 2585 | /// A pointer to an anonymous decl. | 2596 | /// A pointer to an anonymous decl. |
| 2586 | /// data is extra index of `PtrAnonDecl`, which contains the type and decl value. | 2597 | /// data is extra index of `PtrAnonDecl`, which contains the pointer type and decl value. |
| 2598 | /// The alignment of the anonymous decl is communicated via the pointer type. | ||
| 2587 | ptr_anon_decl, | 2599 | ptr_anon_decl, |
| 2600 | /// A pointer to an anonymous decl. | ||
| 2601 | /// data is extra index of `PtrAnonDeclAligned`, which contains the pointer | ||
| 2602 | /// type and decl value. | ||
| 2603 | /// The original pointer type is also provided, which will be different than `ty`. | ||
| 2604 | /// This encoding is only used when a pointer to an anonymous decl is | ||
| 2605 | /// coerced to a different pointer type with a different alignment. | ||
| 2606 | ptr_anon_decl_aligned, | ||
| 2588 | /// data is extra index of `PtrComptimeField`, which contains the pointer type and field value. | 2607 | /// data is extra index of `PtrComptimeField`, which contains the pointer type and field value. |
| 2589 | ptr_comptime_field, | 2608 | ptr_comptime_field, |
| 2590 | /// A pointer with an integer value. | 2609 | /// A pointer with an integer value. |
| ... | @@ -2781,6 +2800,7 @@ pub const Tag = enum(u8) { | ... | @@ -2781,6 +2800,7 @@ pub const Tag = enum(u8) { |
| 2781 | .ptr_decl => PtrDecl, | 2800 | .ptr_decl => PtrDecl, |
| 2782 | .ptr_mut_decl => PtrMutDecl, | 2801 | .ptr_mut_decl => PtrMutDecl, |
| 2783 | .ptr_anon_decl => PtrAnonDecl, | 2802 | .ptr_anon_decl => PtrAnonDecl, |
| 2803 | .ptr_anon_decl_aligned => PtrAnonDeclAligned, | ||
| 2784 | .ptr_comptime_field => PtrComptimeField, | 2804 | .ptr_comptime_field => PtrComptimeField, |
| 2785 | .ptr_int => PtrBase, | 2805 | .ptr_int => PtrBase, |
| 2786 | .ptr_eu_payload => PtrBase, | 2806 | .ptr_eu_payload => PtrBase, |
| ... | @@ -3383,6 +3403,13 @@ pub const PtrAnonDecl = struct { | ... | @@ -3383,6 +3403,13 @@ pub const PtrAnonDecl = struct { |
| 3383 | val: Index, | 3403 | val: Index, |
| 3384 | }; | 3404 | }; |
| 3385 | 3405 | ||
| 3406 | pub const PtrAnonDeclAligned = struct { | ||
| 3407 | ty: Index, | ||
| 3408 | val: Index, | ||
| 3409 | /// Must be nonequal to `ty`. Only the alignment from this value is important. | ||
| 3410 | orig_ty: Index, | ||
| 3411 | }; | ||
| 3412 | |||
| 3386 | pub const PtrMutDecl = struct { | 3413 | pub const PtrMutDecl = struct { |
| 3387 | ty: Index, | 3414 | ty: Index, |
| 3388 | decl: Module.Decl.Index, | 3415 | decl: Module.Decl.Index, |
| ... | @@ -3736,7 +3763,20 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -3736,7 +3763,20 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 3736 | const info = ip.extraData(PtrAnonDecl, data); | 3763 | const info = ip.extraData(PtrAnonDecl, data); |
| 3737 | return .{ .ptr = .{ | 3764 | return .{ .ptr = .{ |
| 3738 | .ty = info.ty, | 3765 | .ty = info.ty, |
| 3739 | .addr = .{ .anon_decl = info.val }, | 3766 | .addr = .{ .anon_decl = .{ |
| 3767 | .val = info.val, | ||
| 3768 | .orig_ty = info.ty, | ||
| 3769 | } }, | ||
| 3770 | } }; | ||
| 3771 | }, | ||
| 3772 | .ptr_anon_decl_aligned => { | ||
| 3773 | const info = ip.extraData(PtrAnonDeclAligned, data); | ||
| 3774 | return .{ .ptr = .{ | ||
| 3775 | .ty = info.ty, | ||
| 3776 | .addr = .{ .anon_decl = .{ | ||
| 3777 | .val = info.val, | ||
| 3778 | .orig_ty = info.orig_ty, | ||
| 3779 | } }, | ||
| 3740 | } }; | 3780 | } }; |
| 3741 | }, | 3781 | }, |
| 3742 | .ptr_comptime_field => { | 3782 | .ptr_comptime_field => { |
| ... | @@ -3817,7 +3857,17 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { | ... | @@ -3817,7 +3857,17 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 3817 | } }; | 3857 | } }; |
| 3818 | }, | 3858 | }, |
| 3819 | .ptr_anon_decl => .{ | 3859 | .ptr_anon_decl => .{ |
| 3820 | .anon_decl = ip.extraData(PtrAnonDecl, ptr_item.data).val, | 3860 | .anon_decl = .{ |
| 3861 | .val = ip.extraData(PtrAnonDecl, ptr_item.data).val, | ||
| 3862 | .orig_ty = info.ty, | ||
| 3863 | }, | ||
| 3864 | }, | ||
| 3865 | .ptr_anon_decl_aligned => b: { | ||
| 3866 | const sub_info = ip.extraData(PtrAnonDeclAligned, ptr_item.data); | ||
| 3867 | break :b .{ .anon_decl = .{ | ||
| 3868 | .val = sub_info.val, | ||
| 3869 | .orig_ty = sub_info.orig_ty, | ||
| 3870 | } }; | ||
| 3821 | }, | 3871 | }, |
| 3822 | .ptr_comptime_field => .{ | 3872 | .ptr_comptime_field => .{ |
| 3823 | .comptime_field = ip.extraData(PtrComptimeField, ptr_item.data).field_val, | 3873 | .comptime_field = ip.extraData(PtrComptimeField, ptr_item.data).field_val, |
| ... | @@ -4571,13 +4621,22 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { | ... | @@ -4571,13 +4621,22 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { |
| 4571 | .runtime_index = mut_decl.runtime_index, | 4621 | .runtime_index = mut_decl.runtime_index, |
| 4572 | }), | 4622 | }), |
| 4573 | }), | 4623 | }), |
| 4574 | .anon_decl => |anon_decl| ip.items.appendAssumeCapacity(.{ | 4624 | .anon_decl => |anon_decl| ip.items.appendAssumeCapacity( |
| 4575 | .tag = .ptr_anon_decl, | 4625 | if (ptrsHaveSameAlignment(ip, ptr.ty, ptr_type, anon_decl.orig_ty)) .{ |
| 4576 | .data = try ip.addExtra(gpa, PtrAnonDecl{ | 4626 | .tag = .ptr_anon_decl, |
| 4577 | .ty = ptr.ty, | 4627 | .data = try ip.addExtra(gpa, PtrAnonDecl{ |
| 4578 | .val = anon_decl, | 4628 | .ty = ptr.ty, |
| 4579 | }), | 4629 | .val = anon_decl.val, |
| 4580 | }), | 4630 | }), |
| 4631 | } else .{ | ||
| 4632 | .tag = .ptr_anon_decl_aligned, | ||
| 4633 | .data = try ip.addExtra(gpa, PtrAnonDeclAligned{ | ||
| 4634 | .ty = ptr.ty, | ||
| 4635 | .val = anon_decl.val, | ||
| 4636 | .orig_ty = anon_decl.orig_ty, | ||
| 4637 | }), | ||
| 4638 | }, | ||
| 4639 | ), | ||
| 4581 | .comptime_field => |field_val| { | 4640 | .comptime_field => |field_val| { |
| 4582 | assert(field_val != .none); | 4641 | assert(field_val != .none); |
| 4583 | ip.items.appendAssumeCapacity(.{ | 4642 | ip.items.appendAssumeCapacity(.{ |
| ... | @@ -7184,6 +7243,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { | ... | @@ -7184,6 +7243,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 7184 | .ptr_decl => @sizeOf(PtrDecl), | 7243 | .ptr_decl => @sizeOf(PtrDecl), |
| 7185 | .ptr_mut_decl => @sizeOf(PtrMutDecl), | 7244 | .ptr_mut_decl => @sizeOf(PtrMutDecl), |
| 7186 | .ptr_anon_decl => @sizeOf(PtrAnonDecl), | 7245 | .ptr_anon_decl => @sizeOf(PtrAnonDecl), |
| 7246 | .ptr_anon_decl_aligned => @sizeOf(PtrAnonDeclAligned), | ||
| 7187 | .ptr_comptime_field => @sizeOf(PtrComptimeField), | 7247 | .ptr_comptime_field => @sizeOf(PtrComptimeField), |
| 7188 | .ptr_int => @sizeOf(PtrBase), | 7248 | .ptr_int => @sizeOf(PtrBase), |
| 7189 | .ptr_eu_payload => @sizeOf(PtrBase), | 7249 | .ptr_eu_payload => @sizeOf(PtrBase), |
| ... | @@ -7314,6 +7374,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { | ... | @@ -7314,6 +7374,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { |
| 7314 | .ptr_decl, | 7374 | .ptr_decl, |
| 7315 | .ptr_mut_decl, | 7375 | .ptr_mut_decl, |
| 7316 | .ptr_anon_decl, | 7376 | .ptr_anon_decl, |
| 7377 | .ptr_anon_decl_aligned, | ||
| 7317 | .ptr_comptime_field, | 7378 | .ptr_comptime_field, |
| 7318 | .ptr_int, | 7379 | .ptr_int, |
| 7319 | .ptr_eu_payload, | 7380 | .ptr_eu_payload, |
| ... | @@ -7695,6 +7756,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { | ... | @@ -7695,6 +7756,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 7695 | inline .ptr_decl, | 7756 | inline .ptr_decl, |
| 7696 | .ptr_mut_decl, | 7757 | .ptr_mut_decl, |
| 7697 | .ptr_anon_decl, | 7758 | .ptr_anon_decl, |
| 7759 | .ptr_anon_decl_aligned, | ||
| 7698 | .ptr_comptime_field, | 7760 | .ptr_comptime_field, |
| 7699 | .ptr_int, | 7761 | .ptr_int, |
| 7700 | .ptr_eu_payload, | 7762 | .ptr_eu_payload, |
| ... | @@ -7855,7 +7917,7 @@ pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.Addr.Tag { | ... | @@ -7855,7 +7917,7 @@ pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.Addr.Tag { |
| 7855 | switch (ip.items.items(.tag)[base]) { | 7917 | switch (ip.items.items(.tag)[base]) { |
| 7856 | .ptr_decl => return .decl, | 7918 | .ptr_decl => return .decl, |
| 7857 | .ptr_mut_decl => return .mut_decl, | 7919 | .ptr_mut_decl => return .mut_decl, |
| 7858 | .ptr_anon_decl => return .anon_decl, | 7920 | .ptr_anon_decl, .ptr_anon_decl_aligned => return .anon_decl, |
| 7859 | .ptr_comptime_field => return .comptime_field, | 7921 | .ptr_comptime_field => return .comptime_field, |
| 7860 | .ptr_int => return .int, | 7922 | .ptr_int => return .int, |
| 7861 | inline .ptr_eu_payload, | 7923 | inline .ptr_eu_payload, |
| ... | @@ -8032,6 +8094,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois | ... | @@ -8032,6 +8094,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois |
| 8032 | .ptr_decl, | 8094 | .ptr_decl, |
| 8033 | .ptr_mut_decl, | 8095 | .ptr_mut_decl, |
| 8034 | .ptr_anon_decl, | 8096 | .ptr_anon_decl, |
| 8097 | .ptr_anon_decl_aligned, | ||
| 8035 | .ptr_comptime_field, | 8098 | .ptr_comptime_field, |
| 8036 | .ptr_int, | 8099 | .ptr_int, |
| 8037 | .ptr_eu_payload, | 8100 | .ptr_eu_payload, |
| ... | @@ -8281,3 +8344,12 @@ pub fn addFieldName( | ... | @@ -8281,3 +8344,12 @@ pub fn addFieldName( |
| 8281 | ip.extra.items[names_start + field_index] = @intFromEnum(name); | 8344 | ip.extra.items[names_start + field_index] = @intFromEnum(name); |
| 8282 | return null; | 8345 | return null; |
| 8283 | } | 8346 | } |
| 8347 | |||
| 8348 | /// Used only by `get` for pointer values, and mainly intended to use `Tag.ptr_anon_decl` | ||
| 8349 | /// encoding instead of `Tag.ptr_anon_decl_aligned` when possible. | ||
| 8350 | fn ptrsHaveSameAlignment(ip: *InternPool, a_ty: Index, a_info: Key.PtrType, b_ty: Index) bool { | ||
| 8351 | if (a_ty == b_ty) return true; | ||
| 8352 | const b_info = ip.indexToKey(b_ty).ptr_type; | ||
| 8353 | return a_info.flags.alignment == b_info.flags.alignment and | ||
| 8354 | (a_info.child == b_info.child or a_info.flags.alignment != .none); | ||
| 8355 | } |
src/Sema.zig+43-21| ... | @@ -3657,9 +3657,13 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro | ... | @@ -3657,9 +3657,13 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 3657 | const elem_ty = ptr_info.child.toType(); | 3657 | const elem_ty = ptr_info.child.toType(); |
| 3658 | 3658 | ||
| 3659 | if (try sema.resolveComptimeKnownAllocValue(block, alloc, null)) |val| { | 3659 | if (try sema.resolveComptimeKnownAllocValue(block, alloc, null)) |val| { |
| 3660 | var anon_decl = try block.startAnonDecl(); | 3660 | const new_mut_ptr = Air.internedToRef((try mod.intern(.{ .ptr = .{ |
| 3661 | defer anon_decl.deinit(); | 3661 | .ty = alloc_ty.toIntern(), |
| 3662 | const new_mut_ptr = try sema.analyzeDeclRef(try anon_decl.finish(elem_ty, val.toValue(), ptr_info.flags.alignment)); | 3662 | .addr = .{ .anon_decl = .{ |
| 3663 | .val = val, | ||
| 3664 | .orig_ty = alloc_ty.toIntern(), | ||
| 3665 | } }, | ||
| 3666 | } }))); | ||
| 3663 | return sema.makePtrConst(block, new_mut_ptr); | 3667 | return sema.makePtrConst(block, new_mut_ptr); |
| 3664 | } | 3668 | } |
| 3665 | 3669 | ||
| ... | @@ -3668,10 +3672,18 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro | ... | @@ -3668,10 +3672,18 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 3668 | implicit_ct: { | 3672 | implicit_ct: { |
| 3669 | const ptr_val = try sema.resolveMaybeUndefVal(alloc) orelse break :implicit_ct; | 3673 | const ptr_val = try sema.resolveMaybeUndefVal(alloc) orelse break :implicit_ct; |
| 3670 | if (!ptr_val.isComptimeMutablePtr(mod)) { | 3674 | if (!ptr_val.isComptimeMutablePtr(mod)) { |
| 3671 | // It could still be a constant pointer to a decl | 3675 | // It could still be a constant pointer to a decl. |
| 3672 | const decl_index = ptr_val.pointerDecl(mod) orelse break :implicit_ct; | 3676 | switch (mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr) { |
| 3673 | const decl_val = mod.declPtr(decl_index).val.toIntern(); | 3677 | .anon_decl => |anon_decl| { |
| 3674 | if (mod.intern_pool.isRuntimeValue(decl_val)) break :implicit_ct; | 3678 | if (mod.intern_pool.isVariable(anon_decl.val)) |
| 3679 | break :implicit_ct; | ||
| 3680 | }, | ||
| 3681 | else => { | ||
| 3682 | const decl_index = ptr_val.pointerDecl(mod) orelse break :implicit_ct; | ||
| 3683 | const decl_val = mod.declPtr(decl_index).val.toIntern(); | ||
| 3684 | if (mod.intern_pool.isRuntimeValue(decl_val)) break :implicit_ct; | ||
| 3685 | }, | ||
| 3686 | } | ||
| 3675 | } | 3687 | } |
| 3676 | return sema.makePtrConst(block, alloc); | 3688 | return sema.makePtrConst(block, alloc); |
| 3677 | } | 3689 | } |
| ... | @@ -3911,17 +3923,19 @@ fn finishResolveComptimeKnownAllocValue(sema: *Sema, result_val: InternPool.Inde | ... | @@ -3911,17 +3923,19 @@ fn finishResolveComptimeKnownAllocValue(sema: *Sema, result_val: InternPool.Inde |
| 3911 | return result_val; | 3923 | return result_val; |
| 3912 | } | 3924 | } |
| 3913 | 3925 | ||
| 3926 | fn makePtrTyConst(sema: *Sema, ptr_ty: Type) CompileError!Type { | ||
| 3927 | var ptr_info = ptr_ty.ptrInfo(sema.mod); | ||
| 3928 | ptr_info.flags.is_const = true; | ||
| 3929 | return sema.ptrType(ptr_info); | ||
| 3930 | } | ||
| 3931 | |||
| 3914 | fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Air.Inst.Ref { | 3932 | fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Air.Inst.Ref { |
| 3915 | const mod = sema.mod; | ||
| 3916 | const alloc_ty = sema.typeOf(alloc); | 3933 | const alloc_ty = sema.typeOf(alloc); |
| 3917 | 3934 | const const_ptr_ty = try sema.makePtrTyConst(alloc_ty); | |
| 3918 | var ptr_info = alloc_ty.ptrInfo(mod); | ||
| 3919 | ptr_info.flags.is_const = true; | ||
| 3920 | const const_ptr_ty = try sema.ptrType(ptr_info); | ||
| 3921 | 3935 | ||
| 3922 | // Detect if a comptime value simply needs to have its type changed. | 3936 | // Detect if a comptime value simply needs to have its type changed. |
| 3923 | if (try sema.resolveMaybeUndefVal(alloc)) |val| { | 3937 | if (try sema.resolveMaybeUndefVal(alloc)) |val| { |
| 3924 | return Air.internedToRef((try mod.getCoerced(val, const_ptr_ty)).toIntern()); | 3938 | return Air.internedToRef((try sema.mod.getCoerced(val, const_ptr_ty)).toIntern()); |
| 3925 | } | 3939 | } |
| 3926 | 3940 | ||
| 3927 | return block.addBitCast(const_ptr_ty, alloc); | 3941 | return block.addBitCast(const_ptr_ty, alloc); |
| ... | @@ -4035,6 +4049,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com | ... | @@ -4035,6 +4049,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 4035 | defer tracy.end(); | 4049 | defer tracy.end(); |
| 4036 | 4050 | ||
| 4037 | const mod = sema.mod; | 4051 | const mod = sema.mod; |
| 4052 | const gpa = sema.gpa; | ||
| 4038 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 4053 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 4039 | const src = inst_data.src(); | 4054 | const src = inst_data.src(); |
| 4040 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; | 4055 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; |
| ... | @@ -4100,11 +4115,14 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com | ... | @@ -4100,11 +4115,14 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 4100 | if (!ia1.is_const) { | 4115 | if (!ia1.is_const) { |
| 4101 | try sema.validateVarType(block, ty_src, final_elem_ty, false); | 4116 | try sema.validateVarType(block, ty_src, final_elem_ty, false); |
| 4102 | } else if (try sema.resolveComptimeKnownAllocValue(block, ptr, final_ptr_ty)) |val| { | 4117 | } else if (try sema.resolveComptimeKnownAllocValue(block, ptr, final_ptr_ty)) |val| { |
| 4103 | var anon_decl = try block.startAnonDecl(); | 4118 | const const_ptr_ty = (try sema.makePtrTyConst(final_ptr_ty)).toIntern(); |
| 4104 | defer anon_decl.deinit(); | 4119 | const new_const_ptr = try mod.intern(.{ .ptr = .{ |
| 4105 | const new_decl_index = try anon_decl.finish(final_elem_ty, val.toValue(), ia1.alignment); | 4120 | .ty = const_ptr_ty, |
| 4106 | const new_mut_ptr = Air.refToInterned(try sema.analyzeDeclRef(new_decl_index)).?.toValue(); | 4121 | .addr = .{ .anon_decl = .{ |
| 4107 | const new_const_ptr = (try mod.getCoerced(new_mut_ptr, final_ptr_ty)).toIntern(); | 4122 | .val = val, |
| 4123 | .orig_ty = const_ptr_ty, | ||
| 4124 | } }, | ||
| 4125 | } }); | ||
| 4108 | 4126 | ||
| 4109 | // Remap the ZIR oeprand to the resolved pointer value | 4127 | // Remap the ZIR oeprand to the resolved pointer value |
| 4110 | sema.inst_map.putAssumeCapacity(Zir.refToIndex(inst_data.operand).?, Air.internedToRef(new_const_ptr)); | 4128 | sema.inst_map.putAssumeCapacity(Zir.refToIndex(inst_data.operand).?, Air.internedToRef(new_const_ptr)); |
| ... | @@ -4127,7 +4145,6 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com | ... | @@ -4127,7 +4145,6 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 4127 | 4145 | ||
| 4128 | // Now we need to go back over all the store instructions, and do the logic as if | 4146 | // Now we need to go back over all the store instructions, and do the logic as if |
| 4129 | // the new result ptr type was available. | 4147 | // the new result ptr type was available. |
| 4130 | const gpa = sema.gpa; | ||
| 4131 | 4148 | ||
| 4132 | for (ia2.prongs.items) |placeholder_inst| { | 4149 | for (ia2.prongs.items) |placeholder_inst| { |
| 4133 | var replacement_block = block.makeSubBlock(); | 4150 | var replacement_block = block.makeSubBlock(); |
| ... | @@ -5539,7 +5556,10 @@ fn addStrLitNoAlias(sema: *Sema, bytes: []const u8) CompileError!Air.Inst.Ref { | ... | @@ -5539,7 +5556,10 @@ fn addStrLitNoAlias(sema: *Sema, bytes: []const u8) CompileError!Air.Inst.Ref { |
| 5539 | }); | 5556 | }); |
| 5540 | return Air.internedToRef((try mod.intern(.{ .ptr = .{ | 5557 | return Air.internedToRef((try mod.intern(.{ .ptr = .{ |
| 5541 | .ty = ptr_ty.toIntern(), | 5558 | .ty = ptr_ty.toIntern(), |
| 5542 | .addr = .{ .anon_decl = val }, | 5559 | .addr = .{ .anon_decl = .{ |
| 5560 | .val = val, | ||
| 5561 | .orig_ty = ptr_ty.toIntern(), | ||
| 5562 | } }, | ||
| 5543 | } }))); | 5563 | } }))); |
| 5544 | } | 5564 | } |
| 5545 | 5565 | ||
| ... | @@ -30545,7 +30565,8 @@ fn beginComptimePtrLoad( | ... | @@ -30545,7 +30565,8 @@ fn beginComptimePtrLoad( |
| 30545 | .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null, | 30565 | .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null, |
| 30546 | }; | 30566 | }; |
| 30547 | }, | 30567 | }, |
| 30548 | .anon_decl => |decl_val| blk: { | 30568 | .anon_decl => |anon_decl| blk: { |
| 30569 | const decl_val = anon_decl.val; | ||
| 30549 | if (decl_val.toValue().getVariable(mod) != null) return error.RuntimeLoad; | 30570 | if (decl_val.toValue().getVariable(mod) != null) return error.RuntimeLoad; |
| 30550 | const decl_ty = ip.typeOf(decl_val).toType(); | 30571 | const decl_ty = ip.typeOf(decl_val).toType(); |
| 30551 | const decl_tv: TypedValue = .{ .ty = decl_ty, .val = decl_val.toValue() }; | 30572 | const decl_tv: TypedValue = .{ .ty = decl_ty, .val = decl_val.toValue() }; |
| ... | @@ -36649,6 +36670,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -36649,6 +36670,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 36649 | .simple_value, | 36670 | .simple_value, |
| 36650 | .ptr_decl, | 36671 | .ptr_decl, |
| 36651 | .ptr_anon_decl, | 36672 | .ptr_anon_decl, |
| 36673 | .ptr_anon_decl_aligned, | ||
| 36652 | .ptr_mut_decl, | 36674 | .ptr_mut_decl, |
| 36653 | .ptr_comptime_field, | 36675 | .ptr_comptime_field, |
| 36654 | .ptr_int, | 36676 | .ptr_int, |
src/TypedValue.zig+2-1| ... | @@ -321,7 +321,8 @@ pub fn print( | ... | @@ -321,7 +321,8 @@ pub fn print( |
| 321 | .val = decl.val, | 321 | .val = decl.val, |
| 322 | }, writer, level - 1, mod); | 322 | }, writer, level - 1, mod); |
| 323 | }, | 323 | }, |
| 324 | .anon_decl => |decl_val| { | 324 | .anon_decl => |anon_decl| { |
| 325 | const decl_val = anon_decl.val; | ||
| 325 | if (level == 0) return writer.print("(anon decl '{d}')", .{ | 326 | if (level == 0) return writer.print("(anon decl '{d}')", .{ |
| 326 | @intFromEnum(decl_val), | 327 | @intFromEnum(decl_val), |
| 327 | }); | 328 | }); |
src/Zir.zig+3-2| ... | @@ -997,8 +997,9 @@ pub const Inst = struct { | ... | @@ -997,8 +997,9 @@ pub const Inst = struct { |
| 997 | /// is the allocation that needs to have its type inferred. | 997 | /// is the allocation that needs to have its type inferred. |
| 998 | /// Uses the `un_node` field. The AST node is the var decl. | 998 | /// Uses the `un_node` field. The AST node is the var decl. |
| 999 | resolve_inferred_alloc, | 999 | resolve_inferred_alloc, |
| 1000 | /// Turns a pointer coming from an `alloc`, `alloc_inferred`, `alloc_inferred_comptime` or | 1000 | /// Turns a pointer coming from an `alloc` or `Extended.alloc` into a constant |
| 1001 | /// `Extended.alloc` into a constant version of the same pointer. | 1001 | /// version of the same pointer. For inferred allocations this is instead implicitly |
| 1002 | /// handled by the `resolve_inferred_alloc` instruction. | ||
| 1002 | /// Uses the `un_node` union field. | 1003 | /// Uses the `un_node` union field. |
| 1003 | make_ptr_const, | 1004 | make_ptr_const, |
| 1004 | 1005 |
src/arch/wasm/CodeGen.zig+10-4| ... | @@ -3139,16 +3139,22 @@ fn lowerParentPtrDecl(func: *CodeGen, ptr_val: Value, decl_index: Module.Decl.In | ... | @@ -3139,16 +3139,22 @@ fn lowerParentPtrDecl(func: *CodeGen, ptr_val: Value, decl_index: Module.Decl.In |
| 3139 | return func.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index, offset); | 3139 | return func.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index, offset); |
| 3140 | } | 3140 | } |
| 3141 | 3141 | ||
| 3142 | fn lowerAnonDeclRef(func: *CodeGen, anon_decl: InternPool.Index, offset: u32) InnerError!WValue { | 3142 | fn lowerAnonDeclRef( |
| 3143 | func: *CodeGen, | ||
| 3144 | anon_decl: InternPool.Key.Ptr.Addr.AnonDecl, | ||
| 3145 | offset: u32, | ||
| 3146 | ) InnerError!WValue { | ||
| 3143 | const mod = func.bin_file.base.options.module.?; | 3147 | const mod = func.bin_file.base.options.module.?; |
| 3144 | const ty = mod.intern_pool.typeOf(anon_decl).toType(); | 3148 | const decl_val = anon_decl.val; |
| 3149 | const ty = mod.intern_pool.typeOf(decl_val).toType(); | ||
| 3145 | 3150 | ||
| 3146 | const is_fn_body = ty.zigTypeTag(mod) == .Fn; | 3151 | const is_fn_body = ty.zigTypeTag(mod) == .Fn; |
| 3147 | if (!is_fn_body and !ty.hasRuntimeBitsIgnoreComptime(mod)) { | 3152 | if (!is_fn_body and !ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3148 | return WValue{ .imm32 = 0xaaaaaaaa }; | 3153 | return WValue{ .imm32 = 0xaaaaaaaa }; |
| 3149 | } | 3154 | } |
| 3150 | 3155 | ||
| 3151 | const res = try func.bin_file.lowerAnonDecl(anon_decl, func.decl.srcLoc(mod)); | 3156 | const decl_align = mod.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment; |
| 3157 | const res = try func.bin_file.lowerAnonDecl(decl_val, decl_align, func.decl.srcLoc(mod)); | ||
| 3152 | switch (res) { | 3158 | switch (res) { |
| 3153 | .ok => {}, | 3159 | .ok => {}, |
| 3154 | .fail => |em| { | 3160 | .fail => |em| { |
| ... | @@ -3156,7 +3162,7 @@ fn lowerAnonDeclRef(func: *CodeGen, anon_decl: InternPool.Index, offset: u32) In | ... | @@ -3156,7 +3162,7 @@ fn lowerAnonDeclRef(func: *CodeGen, anon_decl: InternPool.Index, offset: u32) In |
| 3156 | return error.CodegenFail; | 3162 | return error.CodegenFail; |
| 3157 | }, | 3163 | }, |
| 3158 | } | 3164 | } |
| 3159 | const target_atom_index = func.bin_file.anon_decls.get(anon_decl).?; | 3165 | const target_atom_index = func.bin_file.anon_decls.get(decl_val).?; |
| 3160 | const target_sym_index = func.bin_file.getAtom(target_atom_index).getSymbolIndex().?; | 3166 | const target_sym_index = func.bin_file.getAtom(target_atom_index).getSymbolIndex().?; |
| 3161 | if (is_fn_body) { | 3167 | if (is_fn_body) { |
| 3162 | return WValue{ .function_index = target_sym_index }; | 3168 | return WValue{ .function_index = target_sym_index }; |
src/codegen.zig+4-2| ... | @@ -713,7 +713,7 @@ const RelocInfo = struct { | ... | @@ -713,7 +713,7 @@ const RelocInfo = struct { |
| 713 | fn lowerAnonDeclRef( | 713 | fn lowerAnonDeclRef( |
| 714 | bin_file: *link.File, | 714 | bin_file: *link.File, |
| 715 | src_loc: Module.SrcLoc, | 715 | src_loc: Module.SrcLoc, |
| 716 | decl_val: InternPool.Index, | 716 | anon_decl: InternPool.Key.Ptr.Addr.AnonDecl, |
| 717 | code: *std.ArrayList(u8), | 717 | code: *std.ArrayList(u8), |
| 718 | debug_output: DebugInfoOutput, | 718 | debug_output: DebugInfoOutput, |
| 719 | reloc_info: RelocInfo, | 719 | reloc_info: RelocInfo, |
| ... | @@ -723,6 +723,7 @@ fn lowerAnonDeclRef( | ... | @@ -723,6 +723,7 @@ fn lowerAnonDeclRef( |
| 723 | const mod = bin_file.options.module.?; | 723 | const mod = bin_file.options.module.?; |
| 724 | 724 | ||
| 725 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); | 725 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); |
| 726 | const decl_val = anon_decl.val; | ||
| 726 | const decl_ty = mod.intern_pool.typeOf(decl_val).toType(); | 727 | const decl_ty = mod.intern_pool.typeOf(decl_val).toType(); |
| 727 | const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn; | 728 | const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn; |
| 728 | if (!is_fn_body and !decl_ty.hasRuntimeBits(mod)) { | 729 | if (!is_fn_body and !decl_ty.hasRuntimeBits(mod)) { |
| ... | @@ -730,7 +731,8 @@ fn lowerAnonDeclRef( | ... | @@ -730,7 +731,8 @@ fn lowerAnonDeclRef( |
| 730 | return Result.ok; | 731 | return Result.ok; |
| 731 | } | 732 | } |
| 732 | 733 | ||
| 733 | const res = try bin_file.lowerAnonDecl(decl_val, src_loc); | 734 | const decl_align = mod.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment; |
| 735 | const res = try bin_file.lowerAnonDecl(decl_val, decl_align, src_loc); | ||
| 734 | switch (res) { | 736 | switch (res) { |
| 735 | .ok => {}, | 737 | .ok => {}, |
| 736 | .fail => |em| return .{ .fail = em }, | 738 | .fail => |em| return .{ .fail = em }, |
src/codegen/c.zig+19-2| ... | @@ -531,6 +531,7 @@ pub const DeclGen = struct { | ... | @@ -531,6 +531,7 @@ pub const DeclGen = struct { |
| 531 | /// Keeps track of anonymous decls that need to be rendered before this | 531 | /// Keeps track of anonymous decls that need to be rendered before this |
| 532 | /// (named) Decl in the output C code. | 532 | /// (named) Decl in the output C code. |
| 533 | anon_decl_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.DeclBlock), | 533 | anon_decl_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.DeclBlock), |
| 534 | aligned_anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), | ||
| 534 | 535 | ||
| 535 | fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { | 536 | fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { |
| 536 | @setCold(true); | 537 | @setCold(true); |
| ... | @@ -548,11 +549,12 @@ pub const DeclGen = struct { | ... | @@ -548,11 +549,12 @@ pub const DeclGen = struct { |
| 548 | writer: anytype, | 549 | writer: anytype, |
| 549 | ty: Type, | 550 | ty: Type, |
| 550 | ptr_val: Value, | 551 | ptr_val: Value, |
| 551 | decl_val: InternPool.Index, | 552 | anon_decl: InternPool.Key.Ptr.Addr.AnonDecl, |
| 552 | location: ValueRenderLocation, | 553 | location: ValueRenderLocation, |
| 553 | ) error{ OutOfMemory, AnalysisFail }!void { | 554 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 554 | const mod = dg.module; | 555 | const mod = dg.module; |
| 555 | const ip = &mod.intern_pool; | 556 | const ip = &mod.intern_pool; |
| 557 | const decl_val = anon_decl.val; | ||
| 556 | const decl_ty = ip.typeOf(decl_val).toType(); | 558 | const decl_ty = ip.typeOf(decl_val).toType(); |
| 557 | 559 | ||
| 558 | // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. | 560 | // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. |
| ... | @@ -592,8 +594,23 @@ pub const DeclGen = struct { | ... | @@ -592,8 +594,23 @@ pub const DeclGen = struct { |
| 592 | 594 | ||
| 593 | // Indicate that the anon decl should be rendered to the output so that | 595 | // Indicate that the anon decl should be rendered to the output so that |
| 594 | // our reference above is not undefined. | 596 | // our reference above is not undefined. |
| 597 | const ptr_type = ip.indexToKey(anon_decl.orig_ty).ptr_type; | ||
| 595 | const gop = try dg.anon_decl_deps.getOrPut(dg.gpa, decl_val); | 598 | const gop = try dg.anon_decl_deps.getOrPut(dg.gpa, decl_val); |
| 596 | if (!gop.found_existing) gop.value_ptr.* = .{}; | 599 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 600 | |||
| 601 | // Only insert an alignment entry if the alignment is greater than ABI | ||
| 602 | // alignment. If there is already an entry, keep the greater alignment. | ||
| 603 | const explicit_alignment = ptr_type.flags.alignment; | ||
| 604 | if (explicit_alignment != .none) { | ||
| 605 | const abi_alignment = ptr_type.child.toType().abiAlignment(mod); | ||
| 606 | if (explicit_alignment.compareStrict(.gt, abi_alignment)) { | ||
| 607 | const aligned_gop = try dg.aligned_anon_decls.getOrPut(dg.gpa, decl_val); | ||
| 608 | aligned_gop.value_ptr.* = if (aligned_gop.found_existing) | ||
| 609 | aligned_gop.value_ptr.maxStrict(explicit_alignment) | ||
| 610 | else | ||
| 611 | explicit_alignment; | ||
| 612 | } | ||
| 613 | } | ||
| 597 | } | 614 | } |
| 598 | 615 | ||
| 599 | fn renderDeclValue( | 616 | fn renderDeclValue( |
| ... | @@ -651,7 +668,7 @@ pub const DeclGen = struct { | ... | @@ -651,7 +668,7 @@ pub const DeclGen = struct { |
| 651 | switch (ptr.addr) { | 668 | switch (ptr.addr) { |
| 652 | .decl => |d| try dg.renderDeclValue(writer, ptr_ty, ptr_val.toValue(), d, location), | 669 | .decl => |d| try dg.renderDeclValue(writer, ptr_ty, ptr_val.toValue(), d, location), |
| 653 | .mut_decl => |md| try dg.renderDeclValue(writer, ptr_ty, ptr_val.toValue(), md.decl, location), | 670 | .mut_decl => |md| try dg.renderDeclValue(writer, ptr_ty, ptr_val.toValue(), md.decl, location), |
| 654 | .anon_decl => |decl_val| try dg.renderAnonDeclValue(writer, ptr_ty, ptr_val.toValue(), decl_val, location), | 671 | .anon_decl => |anon_decl| try dg.renderAnonDeclValue(writer, ptr_ty, ptr_val.toValue(), anon_decl, location), |
| 655 | .int => |int| { | 672 | .int => |int| { |
| 656 | try writer.writeByte('('); | 673 | try writer.writeByte('('); |
| 657 | try dg.renderCType(writer, ptr_cty); | 674 | try dg.renderCType(writer, ptr_cty); |
src/codegen/llvm.zig+18-13| ... | @@ -3049,10 +3049,19 @@ pub const Object = struct { | ... | @@ -3049,10 +3049,19 @@ pub const Object = struct { |
| 3049 | o: *Object, | 3049 | o: *Object, |
| 3050 | decl_val: InternPool.Index, | 3050 | decl_val: InternPool.Index, |
| 3051 | llvm_addr_space: Builder.AddrSpace, | 3051 | llvm_addr_space: Builder.AddrSpace, |
| 3052 | alignment: InternPool.Alignment, | ||
| 3052 | ) Error!Builder.Variable.Index { | 3053 | ) Error!Builder.Variable.Index { |
| 3054 | assert(alignment != .none); | ||
| 3053 | // TODO: Add address space to the anon_decl_map | 3055 | // TODO: Add address space to the anon_decl_map |
| 3054 | const gop = try o.anon_decl_map.getOrPut(o.gpa, decl_val); | 3056 | const gop = try o.anon_decl_map.getOrPut(o.gpa, decl_val); |
| 3055 | if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.variable; | 3057 | if (gop.found_existing) { |
| 3058 | // Keep the greater of the two alignments. | ||
| 3059 | const variable_index = gop.value_ptr.ptr(&o.builder).kind.variable; | ||
| 3060 | const old_alignment = InternPool.Alignment.fromLlvm(variable_index.getAlignment(&o.builder)); | ||
| 3061 | const max_alignment = old_alignment.maxStrict(alignment); | ||
| 3062 | variable_index.setAlignment(max_alignment.toLlvm(), &o.builder); | ||
| 3063 | return variable_index; | ||
| 3064 | } | ||
| 3056 | errdefer assert(o.anon_decl_map.remove(decl_val)); | 3065 | errdefer assert(o.anon_decl_map.remove(decl_val)); |
| 3057 | 3066 | ||
| 3058 | const mod = o.module; | 3067 | const mod = o.module; |
| ... | @@ -3068,6 +3077,7 @@ pub const Object = struct { | ... | @@ -3068,6 +3077,7 @@ pub const Object = struct { |
| 3068 | try variable_index.setInitializer(try o.lowerValue(decl_val), &o.builder); | 3077 | try variable_index.setInitializer(try o.lowerValue(decl_val), &o.builder); |
| 3069 | variable_index.setLinkage(.internal, &o.builder); | 3078 | variable_index.setLinkage(.internal, &o.builder); |
| 3070 | variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); | 3079 | variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); |
| 3080 | variable_index.setAlignment(alignment.toLlvm(), &o.builder); | ||
| 3071 | return variable_index; | 3081 | return variable_index; |
| 3072 | } | 3082 | } |
| 3073 | 3083 | ||
| ... | @@ -4250,13 +4260,6 @@ pub const Object = struct { | ... | @@ -4250,13 +4260,6 @@ pub const Object = struct { |
| 4250 | return o.builder.bigIntConst(try o.builder.intType(ty.intInfo(mod).bits), bigint); | 4260 | return o.builder.bigIntConst(try o.builder.intType(ty.intInfo(mod).bits), bigint); |
| 4251 | } | 4261 | } |
| 4252 | 4262 | ||
| 4253 | fn lowerParentPtrAnonDecl(o: *Object, decl_val: InternPool.Index) Error!Builder.Constant { | ||
| 4254 | const mod = o.module; | ||
| 4255 | const decl_ty = mod.intern_pool.typeOf(decl_val).toType(); | ||
| 4256 | const ptr_ty = try mod.singleMutPtrType(decl_ty); | ||
| 4257 | return o.lowerAnonDeclRef(ptr_ty, decl_val); | ||
| 4258 | } | ||
| 4259 | |||
| 4260 | fn lowerParentPtrDecl(o: *Object, decl_index: Module.Decl.Index) Allocator.Error!Builder.Constant { | 4263 | fn lowerParentPtrDecl(o: *Object, decl_index: Module.Decl.Index) Allocator.Error!Builder.Constant { |
| 4261 | const mod = o.module; | 4264 | const mod = o.module; |
| 4262 | const decl = mod.declPtr(decl_index); | 4265 | const decl = mod.declPtr(decl_index); |
| ... | @@ -4272,7 +4275,7 @@ pub const Object = struct { | ... | @@ -4272,7 +4275,7 @@ pub const Object = struct { |
| 4272 | return switch (ptr.addr) { | 4275 | return switch (ptr.addr) { |
| 4273 | .decl => |decl| try o.lowerParentPtrDecl(decl), | 4276 | .decl => |decl| try o.lowerParentPtrDecl(decl), |
| 4274 | .mut_decl => |mut_decl| try o.lowerParentPtrDecl(mut_decl.decl), | 4277 | .mut_decl => |mut_decl| try o.lowerParentPtrDecl(mut_decl.decl), |
| 4275 | .anon_decl => |anon_decl| try o.lowerParentPtrAnonDecl(anon_decl), | 4278 | .anon_decl => |ad| try o.lowerAnonDeclRef(ad.orig_ty.toType(), ad), |
| 4276 | .int => |int| try o.lowerIntAsPtr(int), | 4279 | .int => |int| try o.lowerIntAsPtr(int), |
| 4277 | .eu_payload => |eu_ptr| { | 4280 | .eu_payload => |eu_ptr| { |
| 4278 | const parent_ptr = try o.lowerParentPtr(eu_ptr.toValue()); | 4281 | const parent_ptr = try o.lowerParentPtr(eu_ptr.toValue()); |
| ... | @@ -4391,10 +4394,11 @@ pub const Object = struct { | ... | @@ -4391,10 +4394,11 @@ pub const Object = struct { |
| 4391 | fn lowerAnonDeclRef( | 4394 | fn lowerAnonDeclRef( |
| 4392 | o: *Object, | 4395 | o: *Object, |
| 4393 | ptr_ty: Type, | 4396 | ptr_ty: Type, |
| 4394 | decl_val: InternPool.Index, | 4397 | anon_decl: InternPool.Key.Ptr.Addr.AnonDecl, |
| 4395 | ) Error!Builder.Constant { | 4398 | ) Error!Builder.Constant { |
| 4396 | const mod = o.module; | 4399 | const mod = o.module; |
| 4397 | const ip = &mod.intern_pool; | 4400 | const ip = &mod.intern_pool; |
| 4401 | const decl_val = anon_decl.val; | ||
| 4398 | const decl_ty = ip.typeOf(decl_val).toType(); | 4402 | const decl_ty = ip.typeOf(decl_val).toType(); |
| 4399 | const target = mod.getTarget(); | 4403 | const target = mod.getTarget(); |
| 4400 | 4404 | ||
| ... | @@ -4413,9 +4417,10 @@ pub const Object = struct { | ... | @@ -4413,9 +4417,10 @@ pub const Object = struct { |
| 4413 | if (is_fn_body) | 4417 | if (is_fn_body) |
| 4414 | @panic("TODO"); | 4418 | @panic("TODO"); |
| 4415 | 4419 | ||
| 4416 | const addr_space = target_util.defaultAddressSpace(target, .global_constant); | 4420 | const orig_ty = anon_decl.orig_ty.toType(); |
| 4417 | const llvm_addr_space = toLlvmAddressSpace(addr_space, target); | 4421 | const llvm_addr_space = toLlvmAddressSpace(orig_ty.ptrAddressSpace(mod), target); |
| 4418 | const llvm_global = (try o.resolveGlobalAnonDecl(decl_val, llvm_addr_space)).ptrConst(&o.builder).global; | 4422 | const alignment = orig_ty.ptrAlignment(mod); |
| 4423 | const llvm_global = (try o.resolveGlobalAnonDecl(decl_val, llvm_addr_space, alignment)).ptrConst(&o.builder).global; | ||
| 4419 | 4424 | ||
| 4420 | const llvm_val = try o.builder.convConst( | 4425 | const llvm_val = try o.builder.convConst( |
| 4421 | .unneeded, | 4426 | .unneeded, |
src/codegen/llvm/Builder.zig+6| ... | @@ -2477,6 +2477,12 @@ pub const Variable = struct { | ... | @@ -2477,6 +2477,12 @@ pub const Variable = struct { |
| 2477 | self.ptr(builder).alignment = alignment; | 2477 | self.ptr(builder).alignment = alignment; |
| 2478 | } | 2478 | } |
| 2479 | 2479 | ||
| 2480 | pub fn getAlignment(self: Index, builder: *Builder) Alignment { | ||
| 2481 | if (builder.useLibLlvm()) | ||
| 2482 | return Alignment.fromByteUnits(self.toLlvm(builder).getAlignment()); | ||
| 2483 | return self.ptr(builder).alignment; | ||
| 2484 | } | ||
| 2485 | |||
| 2480 | pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value { | 2486 | pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value { |
| 2481 | return self.ptrConst(builder).global.toLlvm(builder); | 2487 | return self.ptrConst(builder).global.toLlvm(builder); |
| 2482 | } | 2488 | } |
src/codegen/llvm/bindings.zig+3| ... | @@ -273,6 +273,9 @@ pub const Value = opaque { | ... | @@ -273,6 +273,9 @@ pub const Value = opaque { |
| 273 | pub const setAlignment = LLVMSetAlignment; | 273 | pub const setAlignment = LLVMSetAlignment; |
| 274 | extern fn LLVMSetAlignment(V: *Value, Bytes: c_uint) void; | 274 | extern fn LLVMSetAlignment(V: *Value, Bytes: c_uint) void; |
| 275 | 275 | ||
| 276 | pub const getAlignment = LLVMGetAlignment; | ||
| 277 | extern fn LLVMGetAlignment(V: *Value) c_uint; | ||
| 278 | |||
| 276 | pub const setFunctionCallConv = LLVMSetFunctionCallConv; | 279 | pub const setFunctionCallConv = LLVMSetFunctionCallConv; |
| 277 | extern fn LLVMSetFunctionCallConv(Fn: *Value, CC: CallConv) void; | 280 | extern fn LLVMSetFunctionCallConv(Fn: *Value, CC: CallConv) void; |
| 278 | 281 |
src/codegen/spirv.zig+6-1| ... | @@ -959,12 +959,17 @@ const DeclGen = struct { | ... | @@ -959,12 +959,17 @@ const DeclGen = struct { |
| 959 | } | 959 | } |
| 960 | } | 960 | } |
| 961 | 961 | ||
| 962 | fn constantAnonDeclRef(self: *DeclGen, ty: Type, decl_val: InternPool.Index) !IdRef { | 962 | fn constantAnonDeclRef( |
| 963 | self: *DeclGen, | ||
| 964 | ty: Type, | ||
| 965 | anon_decl: InternPool.Key.Ptr.Addr.AnonDecl, | ||
| 966 | ) !IdRef { | ||
| 963 | // TODO: Merge this function with constantDeclRef. | 967 | // TODO: Merge this function with constantDeclRef. |
| 964 | 968 | ||
| 965 | const mod = self.module; | 969 | const mod = self.module; |
| 966 | const ip = &mod.intern_pool; | 970 | const ip = &mod.intern_pool; |
| 967 | const ty_ref = try self.resolveType(ty, .direct); | 971 | const ty_ref = try self.resolveType(ty, .direct); |
| 972 | const decl_val = anon_decl.val; | ||
| 968 | const decl_ty = ip.typeOf(decl_val).toType(); | 973 | const decl_ty = ip.typeOf(decl_val).toType(); |
| 969 | 974 | ||
| 970 | if (decl_val.toValue().getFunction(mod)) |func| { | 975 | if (decl_val.toValue().getFunction(mod)) |func| { |
src/link.zig+5-5| ... | @@ -940,15 +940,15 @@ pub const File = struct { | ... | @@ -940,15 +940,15 @@ pub const File = struct { |
| 940 | 940 | ||
| 941 | pub const LowerResult = @import("codegen.zig").Result; | 941 | pub const LowerResult = @import("codegen.zig").Result; |
| 942 | 942 | ||
| 943 | pub fn lowerAnonDecl(base: *File, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !LowerResult { | 943 | pub fn lowerAnonDecl(base: *File, decl_val: InternPool.Index, decl_align: InternPool.Alignment, src_loc: Module.SrcLoc) !LowerResult { |
| 944 | if (build_options.only_c) unreachable; | 944 | if (build_options.only_c) unreachable; |
| 945 | switch (base.tag) { | 945 | switch (base.tag) { |
| 946 | .coff => return @fieldParentPtr(Coff, "base", base).lowerAnonDecl(decl_val, src_loc), | 946 | .coff => return @fieldParentPtr(Coff, "base", base).lowerAnonDecl(decl_val, decl_align, src_loc), |
| 947 | .elf => return @fieldParentPtr(Elf, "base", base).lowerAnonDecl(decl_val, src_loc), | 947 | .elf => return @fieldParentPtr(Elf, "base", base).lowerAnonDecl(decl_val, decl_align, src_loc), |
| 948 | .macho => return @fieldParentPtr(MachO, "base", base).lowerAnonDecl(decl_val, src_loc), | 948 | .macho => return @fieldParentPtr(MachO, "base", base).lowerAnonDecl(decl_val, decl_align, src_loc), |
| 949 | .plan9 => return @fieldParentPtr(Plan9, "base", base).lowerAnonDecl(decl_val, src_loc), | 949 | .plan9 => return @fieldParentPtr(Plan9, "base", base).lowerAnonDecl(decl_val, src_loc), |
| 950 | .c => unreachable, | 950 | .c => unreachable, |
| 951 | .wasm => return @fieldParentPtr(Wasm, "base", base).lowerAnonDecl(decl_val, src_loc), | 951 | .wasm => return @fieldParentPtr(Wasm, "base", base).lowerAnonDecl(decl_val, decl_align, src_loc), |
| 952 | .spirv => unreachable, | 952 | .spirv => unreachable, |
| 953 | .nvptx => unreachable, | 953 | .nvptx => unreachable, |
| 954 | } | 954 | } |
src/link/C.zig+18-1| ... | @@ -7,6 +7,7 @@ const fs = std.fs; | ... | @@ -7,6 +7,7 @@ const fs = std.fs; |
| 7 | const C = @This(); | 7 | const C = @This(); |
| 8 | const Module = @import("../Module.zig"); | 8 | const Module = @import("../Module.zig"); |
| 9 | const InternPool = @import("../InternPool.zig"); | 9 | const InternPool = @import("../InternPool.zig"); |
| 10 | const Alignment = InternPool.Alignment; | ||
| 10 | const Compilation = @import("../Compilation.zig"); | 11 | const Compilation = @import("../Compilation.zig"); |
| 11 | const codegen = @import("../codegen/c.zig"); | 12 | const codegen = @import("../codegen/c.zig"); |
| 12 | const link = @import("../link.zig"); | 13 | const link = @import("../link.zig"); |
| ... | @@ -30,6 +31,10 @@ string_bytes: std.ArrayListUnmanaged(u8) = .{}, | ... | @@ -30,6 +31,10 @@ string_bytes: std.ArrayListUnmanaged(u8) = .{}, |
| 30 | /// Tracks all the anonymous decls that are used by all the decls so they can | 31 | /// Tracks all the anonymous decls that are used by all the decls so they can |
| 31 | /// be rendered during flush(). | 32 | /// be rendered during flush(). |
| 32 | anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, DeclBlock) = .{}, | 33 | anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, DeclBlock) = .{}, |
| 34 | /// Sparse set of anon decls that are overaligned. Underaligned anon decls are | ||
| 35 | /// lowered the same as ABI-aligned anon decls. The keys here are a subset of | ||
| 36 | /// the keys of `anon_decls`. | ||
| 37 | aligned_anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .{}, | ||
| 33 | 38 | ||
| 34 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new | 39 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new |
| 35 | /// one with every call. | 40 | /// one with every call. |
| ... | @@ -125,6 +130,7 @@ pub fn deinit(self: *C) void { | ... | @@ -125,6 +130,7 @@ pub fn deinit(self: *C) void { |
| 125 | db.deinit(gpa); | 130 | db.deinit(gpa); |
| 126 | } | 131 | } |
| 127 | self.anon_decls.deinit(gpa); | 132 | self.anon_decls.deinit(gpa); |
| 133 | self.aligned_anon_decls.deinit(gpa); | ||
| 128 | 134 | ||
| 129 | self.string_bytes.deinit(gpa); | 135 | self.string_bytes.deinit(gpa); |
| 130 | self.fwd_decl_buf.deinit(gpa); | 136 | self.fwd_decl_buf.deinit(gpa); |
| ... | @@ -179,6 +185,7 @@ pub fn updateFunc( | ... | @@ -179,6 +185,7 @@ pub fn updateFunc( |
| 179 | .fwd_decl = fwd_decl.toManaged(gpa), | 185 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 180 | .ctypes = ctypes.*, | 186 | .ctypes = ctypes.*, |
| 181 | .anon_decl_deps = self.anon_decls, | 187 | .anon_decl_deps = self.anon_decls, |
| 188 | .aligned_anon_decls = self.aligned_anon_decls, | ||
| 182 | }, | 189 | }, |
| 183 | .code = code.toManaged(gpa), | 190 | .code = code.toManaged(gpa), |
| 184 | .indent_writer = undefined, // set later so we can get a pointer to object.code | 191 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| ... | @@ -189,6 +196,7 @@ pub fn updateFunc( | ... | @@ -189,6 +196,7 @@ pub fn updateFunc( |
| 189 | function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() }; | 196 | function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() }; |
| 190 | defer { | 197 | defer { |
| 191 | self.anon_decls = function.object.dg.anon_decl_deps; | 198 | self.anon_decls = function.object.dg.anon_decl_deps; |
| 199 | self.aligned_anon_decls = function.object.dg.aligned_anon_decls; | ||
| 192 | fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged(); | 200 | fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged(); |
| 193 | code.* = function.object.code.moveToUnmanaged(); | 201 | code.* = function.object.code.moveToUnmanaged(); |
| 194 | function.deinit(); | 202 | function.deinit(); |
| ... | @@ -232,6 +240,7 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { | ... | @@ -232,6 +240,7 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { |
| 232 | .fwd_decl = fwd_decl.toManaged(gpa), | 240 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 233 | .ctypes = .{}, | 241 | .ctypes = .{}, |
| 234 | .anon_decl_deps = self.anon_decls, | 242 | .anon_decl_deps = self.anon_decls, |
| 243 | .aligned_anon_decls = self.aligned_anon_decls, | ||
| 235 | }, | 244 | }, |
| 236 | .code = code.toManaged(gpa), | 245 | .code = code.toManaged(gpa), |
| 237 | .indent_writer = undefined, // set later so we can get a pointer to object.code | 246 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| ... | @@ -240,6 +249,7 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { | ... | @@ -240,6 +249,7 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { |
| 240 | 249 | ||
| 241 | defer { | 250 | defer { |
| 242 | self.anon_decls = object.dg.anon_decl_deps; | 251 | self.anon_decls = object.dg.anon_decl_deps; |
| 252 | self.aligned_anon_decls = object.dg.aligned_anon_decls; | ||
| 243 | object.dg.ctypes.deinit(object.dg.gpa); | 253 | object.dg.ctypes.deinit(object.dg.gpa); |
| 244 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | 254 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 245 | code.* = object.code.moveToUnmanaged(); | 255 | code.* = object.code.moveToUnmanaged(); |
| ... | @@ -250,7 +260,8 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { | ... | @@ -250,7 +260,8 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { |
| 250 | .val = anon_decl.toValue(), | 260 | .val = anon_decl.toValue(), |
| 251 | }; | 261 | }; |
| 252 | const c_value: codegen.CValue = .{ .constant = anon_decl }; | 262 | const c_value: codegen.CValue = .{ .constant = anon_decl }; |
| 253 | codegen.genDeclValue(&object, tv, false, c_value, .none, .none) catch |err| switch (err) { | 263 | const alignment: Alignment = self.aligned_anon_decls.get(anon_decl) orelse .none; |
| 264 | codegen.genDeclValue(&object, tv, false, c_value, alignment, .none) catch |err| switch (err) { | ||
| 254 | error.AnalysisFail => { | 265 | error.AnalysisFail => { |
| 255 | @panic("TODO: C backend AnalysisFail on anonymous decl"); | 266 | @panic("TODO: C backend AnalysisFail on anonymous decl"); |
| 256 | //try module.failed_decls.put(gpa, decl_index, object.dg.error_msg.?); | 267 | //try module.failed_decls.put(gpa, decl_index, object.dg.error_msg.?); |
| ... | @@ -296,6 +307,7 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi | ... | @@ -296,6 +307,7 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi |
| 296 | .fwd_decl = fwd_decl.toManaged(gpa), | 307 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 297 | .ctypes = ctypes.*, | 308 | .ctypes = ctypes.*, |
| 298 | .anon_decl_deps = self.anon_decls, | 309 | .anon_decl_deps = self.anon_decls, |
| 310 | .aligned_anon_decls = self.aligned_anon_decls, | ||
| 299 | }, | 311 | }, |
| 300 | .code = code.toManaged(gpa), | 312 | .code = code.toManaged(gpa), |
| 301 | .indent_writer = undefined, // set later so we can get a pointer to object.code | 313 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| ... | @@ -303,6 +315,7 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi | ... | @@ -303,6 +315,7 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi |
| 303 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; | 315 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; |
| 304 | defer { | 316 | defer { |
| 305 | self.anon_decls = object.dg.anon_decl_deps; | 317 | self.anon_decls = object.dg.anon_decl_deps; |
| 318 | self.aligned_anon_decls = object.dg.aligned_anon_decls; | ||
| 306 | object.dg.ctypes.deinit(object.dg.gpa); | 319 | object.dg.ctypes.deinit(object.dg.gpa); |
| 307 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | 320 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 308 | code.* = object.code.moveToUnmanaged(); | 321 | code.* = object.code.moveToUnmanaged(); |
| ... | @@ -602,6 +615,7 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { | ... | @@ -602,6 +615,7 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { |
| 602 | .fwd_decl = fwd_decl.toManaged(gpa), | 615 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 603 | .ctypes = ctypes.*, | 616 | .ctypes = ctypes.*, |
| 604 | .anon_decl_deps = self.anon_decls, | 617 | .anon_decl_deps = self.anon_decls, |
| 618 | .aligned_anon_decls = self.aligned_anon_decls, | ||
| 605 | }, | 619 | }, |
| 606 | .code = code.toManaged(gpa), | 620 | .code = code.toManaged(gpa), |
| 607 | .indent_writer = undefined, // set later so we can get a pointer to object.code | 621 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| ... | @@ -609,6 +623,7 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { | ... | @@ -609,6 +623,7 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { |
| 609 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; | 623 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; |
| 610 | defer { | 624 | defer { |
| 611 | self.anon_decls = object.dg.anon_decl_deps; | 625 | self.anon_decls = object.dg.anon_decl_deps; |
| 626 | self.aligned_anon_decls = object.dg.aligned_anon_decls; | ||
| 612 | object.dg.ctypes.deinit(gpa); | 627 | object.dg.ctypes.deinit(gpa); |
| 613 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | 628 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 614 | code.* = object.code.moveToUnmanaged(); | 629 | code.* = object.code.moveToUnmanaged(); |
| ... | @@ -642,6 +657,7 @@ fn flushLazyFn( | ... | @@ -642,6 +657,7 @@ fn flushLazyFn( |
| 642 | .fwd_decl = fwd_decl.toManaged(gpa), | 657 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 643 | .ctypes = ctypes.*, | 658 | .ctypes = ctypes.*, |
| 644 | .anon_decl_deps = .{}, | 659 | .anon_decl_deps = .{}, |
| 660 | .aligned_anon_decls = .{}, | ||
| 645 | }, | 661 | }, |
| 646 | .code = code.toManaged(gpa), | 662 | .code = code.toManaged(gpa), |
| 647 | .indent_writer = undefined, // set later so we can get a pointer to object.code | 663 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| ... | @@ -651,6 +667,7 @@ fn flushLazyFn( | ... | @@ -651,6 +667,7 @@ fn flushLazyFn( |
| 651 | // If this assert trips just handle the anon_decl_deps the same as | 667 | // If this assert trips just handle the anon_decl_deps the same as |
| 652 | // `updateFunc()` does. | 668 | // `updateFunc()` does. |
| 653 | assert(object.dg.anon_decl_deps.count() == 0); | 669 | assert(object.dg.anon_decl_deps.count() == 0); |
| 670 | assert(object.dg.aligned_anon_decls.count() == 0); | ||
| 654 | object.dg.ctypes.deinit(gpa); | 671 | object.dg.ctypes.deinit(gpa); |
| 655 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | 672 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 656 | code.* = object.code.moveToUnmanaged(); | 673 | code.* = object.code.moveToUnmanaged(); |
src/link/Coff.zig+18-10| ... | @@ -1091,7 +1091,7 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In | ... | @@ -1091,7 +1091,7 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In |
| 1091 | const index = unnamed_consts.items.len; | 1091 | const index = unnamed_consts.items.len; |
| 1092 | const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); | 1092 | const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); |
| 1093 | defer gpa.free(sym_name); | 1093 | defer gpa.free(sym_name); |
| 1094 | const atom_index = switch (try self.lowerConst(sym_name, tv, self.rdata_section_index.?, decl.srcLoc(mod))) { | 1094 | const atom_index = switch (try self.lowerConst(sym_name, tv, tv.ty.abiAlignment(mod), self.rdata_section_index.?, decl.srcLoc(mod))) { |
| 1095 | .ok => |atom_index| atom_index, | 1095 | .ok => |atom_index| atom_index, |
| 1096 | .fail => |em| { | 1096 | .fail => |em| { |
| 1097 | decl.analysis = .codegen_failure; | 1097 | decl.analysis = .codegen_failure; |
| ... | @@ -1109,13 +1109,12 @@ const LowerConstResult = union(enum) { | ... | @@ -1109,13 +1109,12 @@ const LowerConstResult = union(enum) { |
| 1109 | fail: *Module.ErrorMsg, | 1109 | fail: *Module.ErrorMsg, |
| 1110 | }; | 1110 | }; |
| 1111 | 1111 | ||
| 1112 | fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult { | 1112 | fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, required_alignment: InternPool.Alignment, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult { |
| 1113 | const gpa = self.base.allocator; | 1113 | const gpa = self.base.allocator; |
| 1114 | 1114 | ||
| 1115 | var code_buffer = std.ArrayList(u8).init(gpa); | 1115 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 1116 | defer code_buffer.deinit(); | 1116 | defer code_buffer.deinit(); |
| 1117 | 1117 | ||
| 1118 | const mod = self.base.options.module.?; | ||
| 1119 | const atom_index = try self.createAtom(); | 1118 | const atom_index = try self.createAtom(); |
| 1120 | const sym = self.getAtom(atom_index).getSymbolPtr(self); | 1119 | const sym = self.getAtom(atom_index).getSymbolPtr(self); |
| 1121 | try self.setSymbolName(sym, name); | 1120 | try self.setSymbolName(sym, name); |
| ... | @@ -1129,10 +1128,13 @@ fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, sect_id: u16, src_l | ... | @@ -1129,10 +1128,13 @@ fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, sect_id: u16, src_l |
| 1129 | .fail => |em| return .{ .fail = em }, | 1128 | .fail => |em| return .{ .fail = em }, |
| 1130 | }; | 1129 | }; |
| 1131 | 1130 | ||
| 1132 | const required_alignment: u32 = @intCast(tv.ty.abiAlignment(mod).toByteUnits(0)); | ||
| 1133 | const atom = self.getAtomPtr(atom_index); | 1131 | const atom = self.getAtomPtr(atom_index); |
| 1134 | atom.size = @as(u32, @intCast(code.len)); | 1132 | atom.size = @as(u32, @intCast(code.len)); |
| 1135 | atom.getSymbolPtr(self).value = try self.allocateAtom(atom_index, atom.size, required_alignment); | 1133 | atom.getSymbolPtr(self).value = try self.allocateAtom( |
| 1134 | atom_index, | ||
| 1135 | atom.size, | ||
| 1136 | @intCast(required_alignment.toByteUnitsOptional().?), | ||
| 1137 | ); | ||
| 1136 | errdefer self.freeAtom(atom_index); | 1138 | errdefer self.freeAtom(atom_index); |
| 1137 | 1139 | ||
| 1138 | log.debug("allocated atom for {s} at 0x{x}", .{ name, atom.getSymbol(self).value }); | 1140 | log.debug("allocated atom for {s} at 0x{x}", .{ name, atom.getSymbol(self).value }); |
| ... | @@ -1736,7 +1738,7 @@ pub fn getDeclVAddr(self: *Coff, decl_index: Module.Decl.Index, reloc_info: link | ... | @@ -1736,7 +1738,7 @@ pub fn getDeclVAddr(self: *Coff, decl_index: Module.Decl.Index, reloc_info: link |
| 1736 | return 0; | 1738 | return 0; |
| 1737 | } | 1739 | } |
| 1738 | 1740 | ||
| 1739 | pub fn lowerAnonDecl(self: *Coff, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result { | 1741 | pub fn lowerAnonDecl(self: *Coff, decl_val: InternPool.Index, decl_align: InternPool.Alignment, src_loc: Module.SrcLoc) !codegen.Result { |
| 1740 | // This is basically the same as lowerUnnamedConst. | 1742 | // This is basically the same as lowerUnnamedConst. |
| 1741 | // example: | 1743 | // example: |
| 1742 | // const ty = mod.intern_pool.typeOf(decl_val).toType(); | 1744 | // const ty = mod.intern_pool.typeOf(decl_val).toType(); |
| ... | @@ -1747,15 +1749,21 @@ pub fn lowerAnonDecl(self: *Coff, decl_val: InternPool.Index, src_loc: Module.Sr | ... | @@ -1747,15 +1749,21 @@ pub fn lowerAnonDecl(self: *Coff, decl_val: InternPool.Index, src_loc: Module.Sr |
| 1747 | // to put it in some location. | 1749 | // to put it in some location. |
| 1748 | // ... | 1750 | // ... |
| 1749 | const gpa = self.base.allocator; | 1751 | const gpa = self.base.allocator; |
| 1752 | const mod = self.base.options.module.?; | ||
| 1753 | const ty = mod.intern_pool.typeOf(decl_val).toType(); | ||
| 1750 | const gop = try self.anon_decls.getOrPut(gpa, decl_val); | 1754 | const gop = try self.anon_decls.getOrPut(gpa, decl_val); |
| 1751 | if (!gop.found_existing) { | 1755 | const required_alignment = switch (decl_align) { |
| 1752 | const mod = self.base.options.module.?; | 1756 | .none => ty.abiAlignment(mod), |
| 1753 | const ty = mod.intern_pool.typeOf(decl_val).toType(); | 1757 | else => decl_align, |
| 1758 | }; | ||
| 1759 | if (!gop.found_existing or | ||
| 1760 | !required_alignment.check(self.getAtom(gop.value_ptr.*).getSymbol(self).value)) | ||
| 1761 | { | ||
| 1754 | const val = decl_val.toValue(); | 1762 | const val = decl_val.toValue(); |
| 1755 | const tv = TypedValue{ .ty = ty, .val = val }; | 1763 | const tv = TypedValue{ .ty = ty, .val = val }; |
| 1756 | const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)}); | 1764 | const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)}); |
| 1757 | defer gpa.free(name); | 1765 | defer gpa.free(name); |
| 1758 | const res = self.lowerConst(name, tv, self.rdata_section_index.?, src_loc) catch |err| switch (err) { | 1766 | const res = self.lowerConst(name, tv, required_alignment, self.rdata_section_index.?, src_loc) catch |err| switch (err) { |
| 1759 | else => { | 1767 | else => { |
| 1760 | // TODO improve error message | 1768 | // TODO improve error message |
| 1761 | const em = try Module.ErrorMsg.create(gpa, src_loc, "lowerAnonDecl failed with error: {s}", .{ | 1769 | const em = try Module.ErrorMsg.create(gpa, src_loc, "lowerAnonDecl failed with error: {s}", .{ |
src/link/Dwarf.zig+19-14| ... | @@ -87,15 +87,6 @@ pub const DeclState = struct { | ... | @@ -87,15 +87,6 @@ pub const DeclState = struct { |
| 87 | self.exprloc_relocs.deinit(self.gpa); | 87 | self.exprloc_relocs.deinit(self.gpa); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | fn addExprlocReloc(self: *DeclState, target: u32, offset: u32, is_ptr: bool) !void { | ||
| 91 | log.debug("{x}: target sym %{d}, via GOT {}", .{ offset, target, is_ptr }); | ||
| 92 | try self.exprloc_relocs.append(self.gpa, .{ | ||
| 93 | .type = if (is_ptr) .got_load else .direct_load, | ||
| 94 | .target = target, | ||
| 95 | .offset = offset, | ||
| 96 | }); | ||
| 97 | } | ||
| 98 | |||
| 99 | /// Adds local type relocation of the form: @offset => @this + addend | 90 | /// Adds local type relocation of the form: @offset => @this + addend |
| 100 | /// @this signifies the offset within the .debug_abbrev section of the containing atom. | 91 | /// @this signifies the offset within the .debug_abbrev section of the containing atom. |
| 101 | fn addTypeRelocLocal(self: *DeclState, atom_index: Atom.Index, offset: u32, addend: u32) !void { | 92 | fn addTypeRelocLocal(self: *DeclState, atom_index: Atom.Index, offset: u32, addend: u32) !void { |
| ... | @@ -807,11 +798,25 @@ pub const DeclState = struct { | ... | @@ -807,11 +798,25 @@ pub const DeclState = struct { |
| 807 | try dbg_info.append(DW.OP.deref); | 798 | try dbg_info.append(DW.OP.deref); |
| 808 | } | 799 | } |
| 809 | switch (loc) { | 800 | switch (loc) { |
| 810 | .linker_load => |load_struct| try self.addExprlocReloc( | 801 | .linker_load => |load_struct| switch (load_struct.type) { |
| 811 | load_struct.sym_index, | 802 | .direct => { |
| 812 | offset, | 803 | log.debug("{x}: target sym %{d}", .{ offset, load_struct.sym_index }); |
| 813 | is_ptr, | 804 | try self.exprloc_relocs.append(self.gpa, .{ |
| 814 | ), | 805 | .type = .direct_load, |
| 806 | .target = load_struct.sym_index, | ||
| 807 | .offset = offset, | ||
| 808 | }); | ||
| 809 | }, | ||
| 810 | .got => { | ||
| 811 | log.debug("{x}: target sym %{d} via GOT", .{ offset, load_struct.sym_index }); | ||
| 812 | try self.exprloc_relocs.append(self.gpa, .{ | ||
| 813 | .type = .got_load, | ||
| 814 | .target = load_struct.sym_index, | ||
| 815 | .offset = offset, | ||
| 816 | }); | ||
| 817 | }, | ||
| 818 | else => {}, // TODO | ||
| 819 | }, | ||
| 815 | else => {}, | 820 | else => {}, |
| 816 | } | 821 | } |
| 817 | }, | 822 | }, |
src/link/Elf.zig+13-8| ... | @@ -473,7 +473,7 @@ pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link. | ... | @@ -473,7 +473,7 @@ pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link. |
| 473 | return vaddr; | 473 | return vaddr; |
| 474 | } | 474 | } |
| 475 | 475 | ||
| 476 | pub fn lowerAnonDecl(self: *Elf, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result { | 476 | pub fn lowerAnonDecl(self: *Elf, decl_val: InternPool.Index, decl_align: InternPool.Alignment, src_loc: Module.SrcLoc) !codegen.Result { |
| 477 | // This is basically the same as lowerUnnamedConst. | 477 | // This is basically the same as lowerUnnamedConst. |
| 478 | // example: | 478 | // example: |
| 479 | // const ty = mod.intern_pool.typeOf(decl_val).toType(); | 479 | // const ty = mod.intern_pool.typeOf(decl_val).toType(); |
| ... | @@ -484,15 +484,21 @@ pub fn lowerAnonDecl(self: *Elf, decl_val: InternPool.Index, src_loc: Module.Src | ... | @@ -484,15 +484,21 @@ pub fn lowerAnonDecl(self: *Elf, decl_val: InternPool.Index, src_loc: Module.Src |
| 484 | // to put it in some location. | 484 | // to put it in some location. |
| 485 | // ... | 485 | // ... |
| 486 | const gpa = self.base.allocator; | 486 | const gpa = self.base.allocator; |
| 487 | const mod = self.base.options.module.?; | ||
| 488 | const ty = mod.intern_pool.typeOf(decl_val).toType(); | ||
| 487 | const gop = try self.anon_decls.getOrPut(gpa, decl_val); | 489 | const gop = try self.anon_decls.getOrPut(gpa, decl_val); |
| 488 | if (!gop.found_existing) { | 490 | const required_alignment = switch (decl_align) { |
| 489 | const mod = self.base.options.module.?; | 491 | .none => ty.abiAlignment(mod), |
| 490 | const ty = mod.intern_pool.typeOf(decl_val).toType(); | 492 | else => decl_align, |
| 493 | }; | ||
| 494 | if (!gop.found_existing or | ||
| 495 | required_alignment.order(self.symbol(gop.value_ptr.*).atom(self).?.alignment).compare(.gt)) | ||
| 496 | { | ||
| 491 | const val = decl_val.toValue(); | 497 | const val = decl_val.toValue(); |
| 492 | const tv = TypedValue{ .ty = ty, .val = val }; | 498 | const tv = TypedValue{ .ty = ty, .val = val }; |
| 493 | const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)}); | 499 | const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)}); |
| 494 | defer gpa.free(name); | 500 | defer gpa.free(name); |
| 495 | const res = self.lowerConst(name, tv, self.zig_rodata_section_index.?, src_loc) catch |err| switch (err) { | 501 | const res = self.lowerConst(name, tv, required_alignment, self.zig_rodata_section_index.?, src_loc) catch |err| switch (err) { |
| 496 | else => { | 502 | else => { |
| 497 | // TODO improve error message | 503 | // TODO improve error message |
| 498 | const em = try Module.ErrorMsg.create(gpa, src_loc, "lowerAnonDecl failed with error: {s}", .{ | 504 | const em = try Module.ErrorMsg.create(gpa, src_loc, "lowerAnonDecl failed with error: {s}", .{ |
| ... | @@ -3479,7 +3485,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module | ... | @@ -3479,7 +3485,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module |
| 3479 | const index = unnamed_consts.items.len; | 3485 | const index = unnamed_consts.items.len; |
| 3480 | const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); | 3486 | const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); |
| 3481 | defer gpa.free(name); | 3487 | defer gpa.free(name); |
| 3482 | const sym_index = switch (try self.lowerConst(name, typed_value, self.zig_rodata_section_index.?, decl.srcLoc(mod))) { | 3488 | const sym_index = switch (try self.lowerConst(name, typed_value, typed_value.ty.abiAlignment(mod), self.zig_rodata_section_index.?, decl.srcLoc(mod))) { |
| 3483 | .ok => |sym_index| sym_index, | 3489 | .ok => |sym_index| sym_index, |
| 3484 | .fail => |em| { | 3490 | .fail => |em| { |
| 3485 | decl.analysis = .codegen_failure; | 3491 | decl.analysis = .codegen_failure; |
| ... | @@ -3502,6 +3508,7 @@ fn lowerConst( | ... | @@ -3502,6 +3508,7 @@ fn lowerConst( |
| 3502 | self: *Elf, | 3508 | self: *Elf, |
| 3503 | name: []const u8, | 3509 | name: []const u8, |
| 3504 | tv: TypedValue, | 3510 | tv: TypedValue, |
| 3511 | required_alignment: InternPool.Alignment, | ||
| 3505 | output_section_index: u16, | 3512 | output_section_index: u16, |
| 3506 | src_loc: Module.SrcLoc, | 3513 | src_loc: Module.SrcLoc, |
| 3507 | ) !LowerConstResult { | 3514 | ) !LowerConstResult { |
| ... | @@ -3510,7 +3517,6 @@ fn lowerConst( | ... | @@ -3510,7 +3517,6 @@ fn lowerConst( |
| 3510 | var code_buffer = std.ArrayList(u8).init(gpa); | 3517 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 3511 | defer code_buffer.deinit(); | 3518 | defer code_buffer.deinit(); |
| 3512 | 3519 | ||
| 3513 | const mod = self.base.options.module.?; | ||
| 3514 | const zig_module = self.file(self.zig_module_index.?).?.zig_module; | 3520 | const zig_module = self.file(self.zig_module_index.?).?.zig_module; |
| 3515 | const sym_index = try zig_module.addAtom(self); | 3521 | const sym_index = try zig_module.addAtom(self); |
| 3516 | 3522 | ||
| ... | @@ -3524,7 +3530,6 @@ fn lowerConst( | ... | @@ -3524,7 +3530,6 @@ fn lowerConst( |
| 3524 | .fail => |em| return .{ .fail = em }, | 3530 | .fail => |em| return .{ .fail = em }, |
| 3525 | }; | 3531 | }; |
| 3526 | 3532 | ||
| 3527 | const required_alignment = tv.ty.abiAlignment(mod); | ||
| 3528 | const phdr_index = self.phdr_to_shdr_table.get(output_section_index).?; | 3533 | const phdr_index = self.phdr_to_shdr_table.get(output_section_index).?; |
| 3529 | const local_sym = self.symbol(sym_index); | 3534 | const local_sym = self.symbol(sym_index); |
| 3530 | const name_str_index = try self.strtab.insert(gpa, name); | 3535 | const name_str_index = try self.strtab.insert(gpa, name); |
src/link/MachO.zig+13-9| ... | @@ -2196,7 +2196,7 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu | ... | @@ -2196,7 +2196,7 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu |
| 2196 | const index = unnamed_consts.items.len; | 2196 | const index = unnamed_consts.items.len; |
| 2197 | const name = try std.fmt.allocPrint(gpa, "___unnamed_{s}_{d}", .{ decl_name, index }); | 2197 | const name = try std.fmt.allocPrint(gpa, "___unnamed_{s}_{d}", .{ decl_name, index }); |
| 2198 | defer gpa.free(name); | 2198 | defer gpa.free(name); |
| 2199 | const atom_index = switch (try self.lowerConst(name, typed_value, self.data_const_section_index.?, decl.srcLoc(mod))) { | 2199 | const atom_index = switch (try self.lowerConst(name, typed_value, typed_value.ty.abiAlignment(mod), self.data_const_section_index.?, decl.srcLoc(mod))) { |
| 2200 | .ok => |atom_index| atom_index, | 2200 | .ok => |atom_index| atom_index, |
| 2201 | .fail => |em| { | 2201 | .fail => |em| { |
| 2202 | decl.analysis = .codegen_failure; | 2202 | decl.analysis = .codegen_failure; |
| ... | @@ -2219,6 +2219,7 @@ fn lowerConst( | ... | @@ -2219,6 +2219,7 @@ fn lowerConst( |
| 2219 | self: *MachO, | 2219 | self: *MachO, |
| 2220 | name: []const u8, | 2220 | name: []const u8, |
| 2221 | tv: TypedValue, | 2221 | tv: TypedValue, |
| 2222 | required_alignment: InternPool.Alignment, | ||
| 2222 | sect_id: u8, | 2223 | sect_id: u8, |
| 2223 | src_loc: Module.SrcLoc, | 2224 | src_loc: Module.SrcLoc, |
| 2224 | ) !LowerConstResult { | 2225 | ) !LowerConstResult { |
| ... | @@ -2227,8 +2228,6 @@ fn lowerConst( | ... | @@ -2227,8 +2228,6 @@ fn lowerConst( |
| 2227 | var code_buffer = std.ArrayList(u8).init(gpa); | 2228 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 2228 | defer code_buffer.deinit(); | 2229 | defer code_buffer.deinit(); |
| 2229 | 2230 | ||
| 2230 | const mod = self.base.options.module.?; | ||
| 2231 | |||
| 2232 | log.debug("allocating symbol indexes for {s}", .{name}); | 2231 | log.debug("allocating symbol indexes for {s}", .{name}); |
| 2233 | 2232 | ||
| 2234 | const sym_index = try self.allocateSymbol(); | 2233 | const sym_index = try self.allocateSymbol(); |
| ... | @@ -2243,7 +2242,6 @@ fn lowerConst( | ... | @@ -2243,7 +2242,6 @@ fn lowerConst( |
| 2243 | .fail => |em| return .{ .fail = em }, | 2242 | .fail => |em| return .{ .fail = em }, |
| 2244 | }; | 2243 | }; |
| 2245 | 2244 | ||
| 2246 | const required_alignment = tv.ty.abiAlignment(mod); | ||
| 2247 | const atom = self.getAtomPtr(atom_index); | 2245 | const atom = self.getAtomPtr(atom_index); |
| 2248 | atom.size = code.len; | 2246 | atom.size = code.len; |
| 2249 | // TODO: work out logic for disambiguating functions from function pointers | 2247 | // TODO: work out logic for disambiguating functions from function pointers |
| ... | @@ -2868,7 +2866,7 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil | ... | @@ -2868,7 +2866,7 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil |
| 2868 | return 0; | 2866 | return 0; |
| 2869 | } | 2867 | } |
| 2870 | 2868 | ||
| 2871 | pub fn lowerAnonDecl(self: *MachO, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result { | 2869 | pub fn lowerAnonDecl(self: *MachO, decl_val: InternPool.Index, decl_align: InternPool.Alignment, src_loc: Module.SrcLoc) !codegen.Result { |
| 2872 | // This is basically the same as lowerUnnamedConst. | 2870 | // This is basically the same as lowerUnnamedConst. |
| 2873 | // example: | 2871 | // example: |
| 2874 | // const ty = mod.intern_pool.typeOf(decl_val).toType(); | 2872 | // const ty = mod.intern_pool.typeOf(decl_val).toType(); |
| ... | @@ -2879,15 +2877,21 @@ pub fn lowerAnonDecl(self: *MachO, decl_val: InternPool.Index, src_loc: Module.S | ... | @@ -2879,15 +2877,21 @@ pub fn lowerAnonDecl(self: *MachO, decl_val: InternPool.Index, src_loc: Module.S |
| 2879 | // to put it in some location. | 2877 | // to put it in some location. |
| 2880 | // ... | 2878 | // ... |
| 2881 | const gpa = self.base.allocator; | 2879 | const gpa = self.base.allocator; |
| 2880 | const mod = self.base.options.module.?; | ||
| 2881 | const ty = mod.intern_pool.typeOf(decl_val).toType(); | ||
| 2882 | const gop = try self.anon_decls.getOrPut(gpa, decl_val); | 2882 | const gop = try self.anon_decls.getOrPut(gpa, decl_val); |
| 2883 | if (!gop.found_existing) { | 2883 | const required_alignment = switch (decl_align) { |
| 2884 | const mod = self.base.options.module.?; | 2884 | .none => ty.abiAlignment(mod), |
| 2885 | const ty = mod.intern_pool.typeOf(decl_val).toType(); | 2885 | else => decl_align, |
| 2886 | }; | ||
| 2887 | if (!gop.found_existing or | ||
| 2888 | !required_alignment.check(self.getAtom(gop.value_ptr.*).getSymbol(self).n_value)) | ||
| 2889 | { | ||
| 2886 | const val = decl_val.toValue(); | 2890 | const val = decl_val.toValue(); |
| 2887 | const tv = TypedValue{ .ty = ty, .val = val }; | 2891 | const tv = TypedValue{ .ty = ty, .val = val }; |
| 2888 | const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)}); | 2892 | const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)}); |
| 2889 | defer gpa.free(name); | 2893 | defer gpa.free(name); |
| 2890 | const res = self.lowerConst(name, tv, self.data_const_section_index.?, src_loc) catch |err| switch (err) { | 2894 | const res = self.lowerConst(name, tv, required_alignment, self.data_const_section_index.?, src_loc) catch |err| switch (err) { |
| 2891 | else => { | 2895 | else => { |
| 2892 | // TODO improve error message | 2896 | // TODO improve error message |
| 2893 | const em = try Module.ErrorMsg.create(gpa, src_loc, "lowerAnonDecl failed with error: {s}", .{ | 2897 | const em = try Module.ErrorMsg.create(gpa, src_loc, "lowerAnonDecl failed with error: {s}", .{ |
src/link/Wasm.zig+20-15| ... | @@ -1702,25 +1702,30 @@ pub fn getDeclVAddr( | ... | @@ -1702,25 +1702,30 @@ pub fn getDeclVAddr( |
| 1702 | return target_symbol_index; | 1702 | return target_symbol_index; |
| 1703 | } | 1703 | } |
| 1704 | 1704 | ||
| 1705 | pub fn lowerAnonDecl(wasm: *Wasm, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result { | 1705 | pub fn lowerAnonDecl(wasm: *Wasm, decl_val: InternPool.Index, decl_align: Alignment, src_loc: Module.SrcLoc) !codegen.Result { |
| 1706 | const gop = try wasm.anon_decls.getOrPut(wasm.base.allocator, decl_val); | 1706 | const gop = try wasm.anon_decls.getOrPut(wasm.base.allocator, decl_val); |
| 1707 | if (gop.found_existing) { | 1707 | if (!gop.found_existing) { |
| 1708 | return .ok; | 1708 | const mod = wasm.base.options.module.?; |
| 1709 | } | 1709 | const ty = mod.intern_pool.typeOf(decl_val).toType(); |
| 1710 | const tv: TypedValue = .{ .ty = ty, .val = decl_val.toValue() }; | ||
| 1711 | const name = try std.fmt.allocPrintZ(wasm.base.allocator, "__anon_{d}", .{@intFromEnum(decl_val)}); | ||
| 1712 | defer wasm.base.allocator.free(name); | ||
| 1710 | 1713 | ||
| 1711 | const mod = wasm.base.options.module.?; | 1714 | switch (try wasm.lowerConst(name, tv, src_loc)) { |
| 1712 | const ty = mod.intern_pool.typeOf(decl_val).toType(); | 1715 | .ok => |atom_index| gop.value_ptr.* = atom_index, |
| 1713 | const tv: TypedValue = .{ .ty = ty, .val = decl_val.toValue() }; | 1716 | .fail => |em| return .{ .fail = em }, |
| 1714 | const name = try std.fmt.allocPrintZ(wasm.base.allocator, "__anon_{d}", .{@intFromEnum(decl_val)}); | 1717 | } |
| 1715 | defer wasm.base.allocator.free(name); | 1718 | } |
| 1716 | 1719 | ||
| 1717 | switch (try wasm.lowerConst(name, tv, src_loc)) { | 1720 | const atom = wasm.getAtomPtr(gop.value_ptr.*); |
| 1718 | .ok => |atom_index| { | 1721 | atom.alignment = switch (atom.alignment) { |
| 1719 | gop.value_ptr.* = atom_index; | 1722 | .none => decl_align, |
| 1720 | return .ok; | 1723 | else => switch (decl_align) { |
| 1724 | .none => atom.alignment, | ||
| 1725 | else => atom.alignment.maxStrict(decl_align), | ||
| 1721 | }, | 1726 | }, |
| 1722 | .fail => |em| return .{ .fail = em }, | 1727 | }; |
| 1723 | } | 1728 | return .ok; |
| 1724 | } | 1729 | } |
| 1725 | 1730 | ||
| 1726 | pub fn getAnonDeclVAddr(wasm: *Wasm, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { | 1731 | pub fn getAnonDeclVAddr(wasm: *Wasm, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { |
src/value.zig+2-2| ... | @@ -1571,7 +1571,7 @@ pub const Value = struct { | ... | @@ -1571,7 +1571,7 @@ pub const Value = struct { |
| 1571 | .none => switch (ip.indexToKey(switch (ptr.addr) { | 1571 | .none => switch (ip.indexToKey(switch (ptr.addr) { |
| 1572 | .decl => |decl| mod.declPtr(decl).ty.toIntern(), | 1572 | .decl => |decl| mod.declPtr(decl).ty.toIntern(), |
| 1573 | .mut_decl => |mut_decl| mod.declPtr(mut_decl.decl).ty.toIntern(), | 1573 | .mut_decl => |mut_decl| mod.declPtr(mut_decl.decl).ty.toIntern(), |
| 1574 | .anon_decl => |anon_decl| ip.typeOf(anon_decl), | 1574 | .anon_decl => |anon_decl| ip.typeOf(anon_decl.val), |
| 1575 | .comptime_field => |comptime_field| ip.typeOf(comptime_field), | 1575 | .comptime_field => |comptime_field| ip.typeOf(comptime_field), |
| 1576 | else => unreachable, | 1576 | else => unreachable, |
| 1577 | })) { | 1577 | })) { |
| ... | @@ -1604,7 +1604,7 @@ pub const Value = struct { | ... | @@ -1604,7 +1604,7 @@ pub const Value = struct { |
| 1604 | })).toValue(), | 1604 | })).toValue(), |
| 1605 | .ptr => |ptr| switch (ptr.addr) { | 1605 | .ptr => |ptr| switch (ptr.addr) { |
| 1606 | .decl => |decl| mod.declPtr(decl).val.maybeElemValue(mod, index), | 1606 | .decl => |decl| mod.declPtr(decl).val.maybeElemValue(mod, index), |
| 1607 | .anon_decl => |anon_decl| anon_decl.toValue().maybeElemValue(mod, index), | 1607 | .anon_decl => |anon_decl| anon_decl.val.toValue().maybeElemValue(mod, index), |
| 1608 | .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod)) | 1608 | .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod)) |
| 1609 | .toValue().maybeElemValue(mod, index), | 1609 | .toValue().maybeElemValue(mod, index), |
| 1610 | .int, .eu_payload => null, | 1610 | .int, .eu_payload => null, |
test/behavior.zig-1| ... | @@ -37,7 +37,6 @@ test { | ... | @@ -37,7 +37,6 @@ test { |
| 37 | _ = @import("behavior/bugs/1500.zig"); | 37 | _ = @import("behavior/bugs/1500.zig"); |
| 38 | _ = @import("behavior/bugs/1607.zig"); | 38 | _ = @import("behavior/bugs/1607.zig"); |
| 39 | _ = @import("behavior/bugs/1735.zig"); | 39 | _ = @import("behavior/bugs/1735.zig"); |
| 40 | _ = @import("behavior/bugs/1741.zig"); | ||
| 41 | _ = @import("behavior/bugs/1851.zig"); | 40 | _ = @import("behavior/bugs/1851.zig"); |
| 42 | _ = @import("behavior/bugs/1914.zig"); | 41 | _ = @import("behavior/bugs/1914.zig"); |
| 43 | _ = @import("behavior/bugs/2006.zig"); | 42 | _ = @import("behavior/bugs/2006.zig"); |
test/behavior/align.zig+9| ... | @@ -15,6 +15,15 @@ test "global variable alignment" { | ... | @@ -15,6 +15,15 @@ test "global variable alignment" { |
| 15 | } | 15 | } |
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | test "large alignment of local constant" { | ||
| 19 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 20 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 21 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky | ||
| 22 | |||
| 23 | const x: f32 align(128) = 12.34; | ||
| 24 | try std.testing.expect(@intFromPtr(&x) % 128 == 0); | ||
| 25 | } | ||
| 26 | |||
| 18 | test "slicing array of length 1 can not assume runtime index is always zero" { | 27 | test "slicing array of length 1 can not assume runtime index is always zero" { |
| 19 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 28 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 20 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 29 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
test/behavior/bugs/1741.zig deleted-11| ... | @@ -1,11 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | test "fixed" { | ||
| 5 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 6 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 7 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky | ||
| 8 | |||
| 9 | const x: f32 align(128) = 12.34; | ||
| 10 | try std.testing.expect(@intFromPtr(&x) % 128 == 0); | ||
| 11 | } | ||