| 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 | 782 | st_shndx: Elf32_Section, |
| 783 | 783 | |
| 784 | 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 | 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 | 791 | pub const Elf64_Sym = extern struct { |
| ... | ... | @@ -797,10 +797,10 @@ pub const Elf64_Sym = extern struct { |
| 797 | 797 | st_size: Elf64_Xword, |
| 798 | 798 | |
| 799 | 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 | 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 | 806 | pub const Elf32_Syminfo = extern struct { |
| ... | ... | @@ -816,10 +816,10 @@ pub const Elf32_Rel = extern struct { |
| 816 | 816 | r_info: Elf32_Word, |
| 817 | 817 | |
| 818 | 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 | 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 | 825 | pub const Elf64_Rel = extern struct { |
| ... | ... | @@ -827,10 +827,10 @@ pub const Elf64_Rel = extern struct { |
| 827 | 827 | r_info: Elf64_Xword, |
| 828 | 828 | |
| 829 | 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 | 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 | 836 | pub const Elf32_Rela = extern struct { |
| ... | ... | @@ -839,10 +839,10 @@ pub const Elf32_Rela = extern struct { |
| 839 | 839 | r_addend: Elf32_Sword, |
| 840 | 840 | |
| 841 | 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 | 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 | 848 | pub const Elf64_Rela = extern struct { |
| ... | ... | @@ -851,10 +851,10 @@ pub const Elf64_Rela = extern struct { |
| 851 | 851 | r_addend: Elf64_Sxword, |
| 852 | 852 | |
| 853 | 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 | 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 | 860 | pub const Elf32_Dyn = extern struct { |
src/AstGen.zig+6-4| ... | ... | @@ -3123,10 +3123,10 @@ fn varDecl( |
| 3123 | 3123 | if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node)) |
| 3124 | 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 | 3127 | _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node); |
| 3128 | } | |
| 3129 | const const_ptr = try gz.addUnNode(.make_ptr_const, var_ptr, node); | |
| 3128 | break :p var_ptr; | |
| 3129 | } else try gz.addUnNode(.make_ptr_const, var_ptr, node); | |
| 3130 | 3130 | |
| 3131 | 3131 | try gz.addDbgVar(.dbg_var_ptr, ident_name, const_ptr); |
| 3132 | 3132 | |
| ... | ... | @@ -3533,7 +3533,9 @@ fn assignDestructureMaybeDecls( |
| 3533 | 3533 | else => unreachable, |
| 3534 | 3534 | }; |
| 3535 | 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 | 3539 | break :make_const try gz.addUnNode(.make_ptr_const, raw_ptr, node); |
| 3538 | 3540 | } else raw_ptr; |
| 3539 | 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 | 3545 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 3546 | 3546 | .ctypes = .{}, |
| 3547 | 3547 | .anon_decl_deps = .{}, |
| 3548 | .aligned_anon_decls = .{}, | |
| 3548 | 3549 | }; |
| 3549 | 3550 | defer { |
| 3550 | 3551 | dg.ctypes.deinit(gpa); |
src/InternPool.zig+86-14| ... | ... | @@ -1074,7 +1074,7 @@ pub const Key = union(enum) { |
| 1074 | 1074 | |
| 1075 | 1075 | decl: Module.Decl.Index, |
| 1076 | 1076 | mut_decl: MutDecl, |
| 1077 | anon_decl: Index, | |
| 1077 | anon_decl: AnonDecl, | |
| 1078 | 1078 | comptime_field: Index, |
| 1079 | 1079 | int: Index, |
| 1080 | 1080 | eu_payload: Index, |
| ... | ... | @@ -1090,6 +1090,14 @@ pub const Key = union(enum) { |
| 1090 | 1090 | base: Index, |
| 1091 | 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 | 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 | 1244 | .int, |
| 1236 | 1245 | .eu_payload, |
| 1237 | 1246 | .opt_payload, |
| ... | ... | @@ -1500,7 +1509,8 @@ pub const Key = union(enum) { |
| 1500 | 1509 | return switch (a_info.addr) { |
| 1501 | 1510 | .decl => |a_decl| a_decl == b_info.addr.decl, |
| 1502 | 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 | 1514 | .int => |a_int| a_int == b_info.addr.int, |
| 1505 | 1515 | .eu_payload => |a_eu_payload| a_eu_payload == b_info.addr.eu_payload, |
| 1506 | 1516 | .opt_payload => |a_opt_payload| a_opt_payload == b_info.addr.opt_payload, |
| ... | ... | @@ -2133,6 +2143,7 @@ pub const Index = enum(u32) { |
| 2133 | 2143 | ptr_decl: struct { data: *PtrDecl }, |
| 2134 | 2144 | ptr_mut_decl: struct { data: *PtrMutDecl }, |
| 2135 | 2145 | ptr_anon_decl: struct { data: *PtrAnonDecl }, |
| 2146 | ptr_anon_decl_aligned: struct { data: *PtrAnonDeclAligned }, | |
| 2136 | 2147 | ptr_comptime_field: struct { data: *PtrComptimeField }, |
| 2137 | 2148 | ptr_int: struct { data: *PtrBase }, |
| 2138 | 2149 | ptr_eu_payload: struct { data: *PtrBase }, |
| ... | ... | @@ -2583,8 +2594,16 @@ pub const Tag = enum(u8) { |
| 2583 | 2594 | /// data is extra index of `PtrMutDecl`, which contains the type and address. |
| 2584 | 2595 | ptr_mut_decl, |
| 2585 | 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 | 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 | 2607 | /// data is extra index of `PtrComptimeField`, which contains the pointer type and field value. |
| 2589 | 2608 | ptr_comptime_field, |
| 2590 | 2609 | /// A pointer with an integer value. |
| ... | ... | @@ -2781,6 +2800,7 @@ pub const Tag = enum(u8) { |
| 2781 | 2800 | .ptr_decl => PtrDecl, |
| 2782 | 2801 | .ptr_mut_decl => PtrMutDecl, |
| 2783 | 2802 | .ptr_anon_decl => PtrAnonDecl, |
| 2803 | .ptr_anon_decl_aligned => PtrAnonDeclAligned, | |
| 2784 | 2804 | .ptr_comptime_field => PtrComptimeField, |
| 2785 | 2805 | .ptr_int => PtrBase, |
| 2786 | 2806 | .ptr_eu_payload => PtrBase, |
| ... | ... | @@ -3383,6 +3403,13 @@ pub const PtrAnonDecl = struct { |
| 3383 | 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 | 3413 | pub const PtrMutDecl = struct { |
| 3387 | 3414 | ty: Index, |
| 3388 | 3415 | decl: Module.Decl.Index, |
| ... | ... | @@ -3736,7 +3763,20 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 3736 | 3763 | const info = ip.extraData(PtrAnonDecl, data); |
| 3737 | 3764 | return .{ .ptr = .{ |
| 3738 | 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 | 3782 | .ptr_comptime_field => { |
| ... | ... | @@ -3817,7 +3857,17 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key { |
| 3817 | 3857 | } }; |
| 3818 | 3858 | }, |
| 3819 | 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 | 3872 | .ptr_comptime_field => .{ |
| 3823 | 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 | 4621 | .runtime_index = mut_decl.runtime_index, |
| 4572 | 4622 | }), |
| 4573 | 4623 | }), |
| 4574 | .anon_decl => |anon_decl| ip.items.appendAssumeCapacity(.{ | |
| 4575 | .tag = .ptr_anon_decl, | |
| 4576 | .data = try ip.addExtra(gpa, PtrAnonDecl{ | |
| 4577 | .ty = ptr.ty, | |
| 4578 | .val = anon_decl, | |
| 4579 | }), | |
| 4580 | }), | |
| 4624 | .anon_decl => |anon_decl| ip.items.appendAssumeCapacity( | |
| 4625 | if (ptrsHaveSameAlignment(ip, ptr.ty, ptr_type, anon_decl.orig_ty)) .{ | |
| 4626 | .tag = .ptr_anon_decl, | |
| 4627 | .data = try ip.addExtra(gpa, PtrAnonDecl{ | |
| 4628 | .ty = ptr.ty, | |
| 4629 | .val = anon_decl.val, | |
| 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 | 4640 | .comptime_field => |field_val| { |
| 4582 | 4641 | assert(field_val != .none); |
| 4583 | 4642 | ip.items.appendAssumeCapacity(.{ |
| ... | ... | @@ -7184,6 +7243,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void { |
| 7184 | 7243 | .ptr_decl => @sizeOf(PtrDecl), |
| 7185 | 7244 | .ptr_mut_decl => @sizeOf(PtrMutDecl), |
| 7186 | 7245 | .ptr_anon_decl => @sizeOf(PtrAnonDecl), |
| 7246 | .ptr_anon_decl_aligned => @sizeOf(PtrAnonDeclAligned), | |
| 7187 | 7247 | .ptr_comptime_field => @sizeOf(PtrComptimeField), |
| 7188 | 7248 | .ptr_int => @sizeOf(PtrBase), |
| 7189 | 7249 | .ptr_eu_payload => @sizeOf(PtrBase), |
| ... | ... | @@ -7314,6 +7374,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void { |
| 7314 | 7374 | .ptr_decl, |
| 7315 | 7375 | .ptr_mut_decl, |
| 7316 | 7376 | .ptr_anon_decl, |
| 7377 | .ptr_anon_decl_aligned, | |
| 7317 | 7378 | .ptr_comptime_field, |
| 7318 | 7379 | .ptr_int, |
| 7319 | 7380 | .ptr_eu_payload, |
| ... | ... | @@ -7695,6 +7756,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 7695 | 7756 | inline .ptr_decl, |
| 7696 | 7757 | .ptr_mut_decl, |
| 7697 | 7758 | .ptr_anon_decl, |
| 7759 | .ptr_anon_decl_aligned, | |
| 7698 | 7760 | .ptr_comptime_field, |
| 7699 | 7761 | .ptr_int, |
| 7700 | 7762 | .ptr_eu_payload, |
| ... | ... | @@ -7855,7 +7917,7 @@ pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.Addr.Tag { |
| 7855 | 7917 | switch (ip.items.items(.tag)[base]) { |
| 7856 | 7918 | .ptr_decl => return .decl, |
| 7857 | 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 | 7921 | .ptr_comptime_field => return .comptime_field, |
| 7860 | 7922 | .ptr_int => return .int, |
| 7861 | 7923 | inline .ptr_eu_payload, |
| ... | ... | @@ -8032,6 +8094,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois |
| 8032 | 8094 | .ptr_decl, |
| 8033 | 8095 | .ptr_mut_decl, |
| 8034 | 8096 | .ptr_anon_decl, |
| 8097 | .ptr_anon_decl_aligned, | |
| 8035 | 8098 | .ptr_comptime_field, |
| 8036 | 8099 | .ptr_int, |
| 8037 | 8100 | .ptr_eu_payload, |
| ... | ... | @@ -8281,3 +8344,12 @@ pub fn addFieldName( |
| 8281 | 8344 | ip.extra.items[names_start + field_index] = @intFromEnum(name); |
| 8282 | 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 | 3657 | const elem_ty = ptr_info.child.toType(); |
| 3658 | 3658 | |
| 3659 | 3659 | if (try sema.resolveComptimeKnownAllocValue(block, alloc, null)) |val| { |
| 3660 | var anon_decl = try block.startAnonDecl(); | |
| 3661 | defer anon_decl.deinit(); | |
| 3662 | const new_mut_ptr = try sema.analyzeDeclRef(try anon_decl.finish(elem_ty, val.toValue(), ptr_info.flags.alignment)); | |
| 3660 | const new_mut_ptr = Air.internedToRef((try mod.intern(.{ .ptr = .{ | |
| 3661 | .ty = alloc_ty.toIntern(), | |
| 3662 | .addr = .{ .anon_decl = .{ | |
| 3663 | .val = val, | |
| 3664 | .orig_ty = alloc_ty.toIntern(), | |
| 3665 | } }, | |
| 3666 | } }))); | |
| 3663 | 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 | 3672 | implicit_ct: { |
| 3669 | 3673 | const ptr_val = try sema.resolveMaybeUndefVal(alloc) orelse break :implicit_ct; |
| 3670 | 3674 | if (!ptr_val.isComptimeMutablePtr(mod)) { |
| 3671 | // It could still be a constant pointer to a decl | |
| 3672 | const decl_index = ptr_val.pointerDecl(mod) orelse break :implicit_ct; | |
| 3673 | const decl_val = mod.declPtr(decl_index).val.toIntern(); | |
| 3674 | if (mod.intern_pool.isRuntimeValue(decl_val)) break :implicit_ct; | |
| 3675 | // It could still be a constant pointer to a decl. | |
| 3676 | switch (mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr) { | |
| 3677 | .anon_decl => |anon_decl| { | |
| 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 | 3688 | return sema.makePtrConst(block, alloc); |
| 3677 | 3689 | } |
| ... | ... | @@ -3911,17 +3923,19 @@ fn finishResolveComptimeKnownAllocValue(sema: *Sema, result_val: InternPool.Inde |
| 3911 | 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 | 3932 | fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Air.Inst.Ref { |
| 3915 | const mod = sema.mod; | |
| 3916 | 3933 | const alloc_ty = sema.typeOf(alloc); |
| 3917 | ||
| 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); | |
| 3934 | const const_ptr_ty = try sema.makePtrTyConst(alloc_ty); | |
| 3921 | 3935 | |
| 3922 | 3936 | // Detect if a comptime value simply needs to have its type changed. |
| 3923 | 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 | 3941 | return block.addBitCast(const_ptr_ty, alloc); |
| ... | ... | @@ -4035,6 +4049,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 4035 | 4049 | defer tracy.end(); |
| 4036 | 4050 | |
| 4037 | 4051 | const mod = sema.mod; |
| 4052 | const gpa = sema.gpa; | |
| 4038 | 4053 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 4039 | 4054 | const src = inst_data.src(); |
| 4040 | 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 | 4115 | if (!ia1.is_const) { |
| 4101 | 4116 | try sema.validateVarType(block, ty_src, final_elem_ty, false); |
| 4102 | 4117 | } else if (try sema.resolveComptimeKnownAllocValue(block, ptr, final_ptr_ty)) |val| { |
| 4103 | var anon_decl = try block.startAnonDecl(); | |
| 4104 | defer anon_decl.deinit(); | |
| 4105 | const new_decl_index = try anon_decl.finish(final_elem_ty, val.toValue(), ia1.alignment); | |
| 4106 | const new_mut_ptr = Air.refToInterned(try sema.analyzeDeclRef(new_decl_index)).?.toValue(); | |
| 4107 | const new_const_ptr = (try mod.getCoerced(new_mut_ptr, final_ptr_ty)).toIntern(); | |
| 4118 | const const_ptr_ty = (try sema.makePtrTyConst(final_ptr_ty)).toIntern(); | |
| 4119 | const new_const_ptr = try mod.intern(.{ .ptr = .{ | |
| 4120 | .ty = const_ptr_ty, | |
| 4121 | .addr = .{ .anon_decl = .{ | |
| 4122 | .val = val, | |
| 4123 | .orig_ty = const_ptr_ty, | |
| 4124 | } }, | |
| 4125 | } }); | |
| 4108 | 4126 | |
| 4109 | 4127 | // Remap the ZIR oeprand to the resolved pointer value |
| 4110 | 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 | 4145 | |
| 4128 | 4146 | // Now we need to go back over all the store instructions, and do the logic as if |
| 4129 | 4147 | // the new result ptr type was available. |
| 4130 | const gpa = sema.gpa; | |
| 4131 | 4148 | |
| 4132 | 4149 | for (ia2.prongs.items) |placeholder_inst| { |
| 4133 | 4150 | var replacement_block = block.makeSubBlock(); |
| ... | ... | @@ -5539,7 +5556,10 @@ fn addStrLitNoAlias(sema: *Sema, bytes: []const u8) CompileError!Air.Inst.Ref { |
| 5539 | 5556 | }); |
| 5540 | 5557 | return Air.internedToRef((try mod.intern(.{ .ptr = .{ |
| 5541 | 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 | 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 | 30570 | if (decl_val.toValue().getVariable(mod) != null) return error.RuntimeLoad; |
| 30550 | 30571 | const decl_ty = ip.typeOf(decl_val).toType(); |
| 30551 | 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 | 36670 | .simple_value, |
| 36650 | 36671 | .ptr_decl, |
| 36651 | 36672 | .ptr_anon_decl, |
| 36673 | .ptr_anon_decl_aligned, | |
| 36652 | 36674 | .ptr_mut_decl, |
| 36653 | 36675 | .ptr_comptime_field, |
| 36654 | 36676 | .ptr_int, |
src/TypedValue.zig+2-1| ... | ... | @@ -321,7 +321,8 @@ pub fn print( |
| 321 | 321 | .val = decl.val, |
| 322 | 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 | 326 | if (level == 0) return writer.print("(anon decl '{d}')", .{ |
| 326 | 327 | @intFromEnum(decl_val), |
| 327 | 328 | }); |
src/Zir.zig+3-2| ... | ... | @@ -997,8 +997,9 @@ pub const Inst = struct { |
| 997 | 997 | /// is the allocation that needs to have its type inferred. |
| 998 | 998 | /// Uses the `un_node` field. The AST node is the var decl. |
| 999 | 999 | resolve_inferred_alloc, |
| 1000 | /// Turns a pointer coming from an `alloc`, `alloc_inferred`, `alloc_inferred_comptime` or | |
| 1001 | /// `Extended.alloc` into a constant version of the same pointer. | |
| 1000 | /// Turns a pointer coming from an `alloc` or `Extended.alloc` into a constant | |
| 1001 | /// version of the same pointer. For inferred allocations this is instead implicitly | |
| 1002 | /// handled by the `resolve_inferred_alloc` instruction. | |
| 1002 | 1003 | /// Uses the `un_node` union field. |
| 1003 | 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 | 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 | 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 | 3151 | const is_fn_body = ty.zigTypeTag(mod) == .Fn; |
| 3147 | 3152 | if (!is_fn_body and !ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 3148 | 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 | 3158 | switch (res) { |
| 3153 | 3159 | .ok => {}, |
| 3154 | 3160 | .fail => |em| { |
| ... | ... | @@ -3156,7 +3162,7 @@ fn lowerAnonDeclRef(func: *CodeGen, anon_decl: InternPool.Index, offset: u32) In |
| 3156 | 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 | 3166 | const target_sym_index = func.bin_file.getAtom(target_atom_index).getSymbolIndex().?; |
| 3161 | 3167 | if (is_fn_body) { |
| 3162 | 3168 | return WValue{ .function_index = target_sym_index }; |
src/codegen.zig+4-2| ... | ... | @@ -713,7 +713,7 @@ const RelocInfo = struct { |
| 713 | 713 | fn lowerAnonDeclRef( |
| 714 | 714 | bin_file: *link.File, |
| 715 | 715 | src_loc: Module.SrcLoc, |
| 716 | decl_val: InternPool.Index, | |
| 716 | anon_decl: InternPool.Key.Ptr.Addr.AnonDecl, | |
| 717 | 717 | code: *std.ArrayList(u8), |
| 718 | 718 | debug_output: DebugInfoOutput, |
| 719 | 719 | reloc_info: RelocInfo, |
| ... | ... | @@ -723,6 +723,7 @@ fn lowerAnonDeclRef( |
| 723 | 723 | const mod = bin_file.options.module.?; |
| 724 | 724 | |
| 725 | 725 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); |
| 726 | const decl_val = anon_decl.val; | |
| 726 | 727 | const decl_ty = mod.intern_pool.typeOf(decl_val).toType(); |
| 727 | 728 | const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn; |
| 728 | 729 | if (!is_fn_body and !decl_ty.hasRuntimeBits(mod)) { |
| ... | ... | @@ -730,7 +731,8 @@ fn lowerAnonDeclRef( |
| 730 | 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 | 736 | switch (res) { |
| 735 | 737 | .ok => {}, |
| 736 | 738 | .fail => |em| return .{ .fail = em }, |
src/codegen/c.zig+19-2| ... | ... | @@ -531,6 +531,7 @@ pub const DeclGen = struct { |
| 531 | 531 | /// Keeps track of anonymous decls that need to be rendered before this |
| 532 | 532 | /// (named) Decl in the output C code. |
| 533 | 533 | anon_decl_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.DeclBlock), |
| 534 | aligned_anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment), | |
| 534 | 535 | |
| 535 | 536 | fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { |
| 536 | 537 | @setCold(true); |
| ... | ... | @@ -548,11 +549,12 @@ pub const DeclGen = struct { |
| 548 | 549 | writer: anytype, |
| 549 | 550 | ty: Type, |
| 550 | 551 | ptr_val: Value, |
| 551 | decl_val: InternPool.Index, | |
| 552 | anon_decl: InternPool.Key.Ptr.Addr.AnonDecl, | |
| 552 | 553 | location: ValueRenderLocation, |
| 553 | 554 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 554 | 555 | const mod = dg.module; |
| 555 | 556 | const ip = &mod.intern_pool; |
| 557 | const decl_val = anon_decl.val; | |
| 556 | 558 | const decl_ty = ip.typeOf(decl_val).toType(); |
| 557 | 559 | |
| 558 | 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 | 594 | |
| 593 | 595 | // Indicate that the anon decl should be rendered to the output so that |
| 594 | 596 | // our reference above is not undefined. |
| 597 | const ptr_type = ip.indexToKey(anon_decl.orig_ty).ptr_type; | |
| 595 | 598 | const gop = try dg.anon_decl_deps.getOrPut(dg.gpa, decl_val); |
| 596 | 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 | 616 | fn renderDeclValue( |
| ... | ... | @@ -651,7 +668,7 @@ pub const DeclGen = struct { |
| 651 | 668 | switch (ptr.addr) { |
| 652 | 669 | .decl => |d| try dg.renderDeclValue(writer, ptr_ty, ptr_val.toValue(), d, location), |
| 653 | 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 | 672 | .int => |int| { |
| 656 | 673 | try writer.writeByte('('); |
| 657 | 674 | try dg.renderCType(writer, ptr_cty); |
src/codegen/llvm.zig+18-13| ... | ... | @@ -3049,10 +3049,19 @@ pub const Object = struct { |
| 3049 | 3049 | o: *Object, |
| 3050 | 3050 | decl_val: InternPool.Index, |
| 3051 | 3051 | llvm_addr_space: Builder.AddrSpace, |
| 3052 | alignment: InternPool.Alignment, | |
| 3052 | 3053 | ) Error!Builder.Variable.Index { |
| 3054 | assert(alignment != .none); | |
| 3053 | 3055 | // TODO: Add address space to the anon_decl_map |
| 3054 | 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 | 3065 | errdefer assert(o.anon_decl_map.remove(decl_val)); |
| 3057 | 3066 | |
| 3058 | 3067 | const mod = o.module; |
| ... | ... | @@ -3068,6 +3077,7 @@ pub const Object = struct { |
| 3068 | 3077 | try variable_index.setInitializer(try o.lowerValue(decl_val), &o.builder); |
| 3069 | 3078 | variable_index.setLinkage(.internal, &o.builder); |
| 3070 | 3079 | variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); |
| 3080 | variable_index.setAlignment(alignment.toLlvm(), &o.builder); | |
| 3071 | 3081 | return variable_index; |
| 3072 | 3082 | } |
| 3073 | 3083 | |
| ... | ... | @@ -4250,13 +4260,6 @@ pub const Object = struct { |
| 4250 | 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 | 4263 | fn lowerParentPtrDecl(o: *Object, decl_index: Module.Decl.Index) Allocator.Error!Builder.Constant { |
| 4261 | 4264 | const mod = o.module; |
| 4262 | 4265 | const decl = mod.declPtr(decl_index); |
| ... | ... | @@ -4272,7 +4275,7 @@ pub const Object = struct { |
| 4272 | 4275 | return switch (ptr.addr) { |
| 4273 | 4276 | .decl => |decl| try o.lowerParentPtrDecl(decl), |
| 4274 | 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 | 4279 | .int => |int| try o.lowerIntAsPtr(int), |
| 4277 | 4280 | .eu_payload => |eu_ptr| { |
| 4278 | 4281 | const parent_ptr = try o.lowerParentPtr(eu_ptr.toValue()); |
| ... | ... | @@ -4391,10 +4394,11 @@ pub const Object = struct { |
| 4391 | 4394 | fn lowerAnonDeclRef( |
| 4392 | 4395 | o: *Object, |
| 4393 | 4396 | ptr_ty: Type, |
| 4394 | decl_val: InternPool.Index, | |
| 4397 | anon_decl: InternPool.Key.Ptr.Addr.AnonDecl, | |
| 4395 | 4398 | ) Error!Builder.Constant { |
| 4396 | 4399 | const mod = o.module; |
| 4397 | 4400 | const ip = &mod.intern_pool; |
| 4401 | const decl_val = anon_decl.val; | |
| 4398 | 4402 | const decl_ty = ip.typeOf(decl_val).toType(); |
| 4399 | 4403 | const target = mod.getTarget(); |
| 4400 | 4404 | |
| ... | ... | @@ -4413,9 +4417,10 @@ pub const Object = struct { |
| 4413 | 4417 | if (is_fn_body) |
| 4414 | 4418 | @panic("TODO"); |
| 4415 | 4419 | |
| 4416 | const addr_space = target_util.defaultAddressSpace(target, .global_constant); | |
| 4417 | const llvm_addr_space = toLlvmAddressSpace(addr_space, target); | |
| 4418 | const llvm_global = (try o.resolveGlobalAnonDecl(decl_val, llvm_addr_space)).ptrConst(&o.builder).global; | |
| 4420 | const orig_ty = anon_decl.orig_ty.toType(); | |
| 4421 | const llvm_addr_space = toLlvmAddressSpace(orig_ty.ptrAddressSpace(mod), target); | |
| 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 | 4425 | const llvm_val = try o.builder.convConst( |
| 4421 | 4426 | .unneeded, |
src/codegen/llvm/Builder.zig+6| ... | ... | @@ -2477,6 +2477,12 @@ pub const Variable = struct { |
| 2477 | 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 | 2486 | pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value { |
| 2481 | 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 | 273 | pub const setAlignment = LLVMSetAlignment; |
| 274 | 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 | 279 | pub const setFunctionCallConv = LLVMSetFunctionCallConv; |
| 277 | 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 | 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 | 967 | // TODO: Merge this function with constantDeclRef. |
| 964 | 968 | |
| 965 | 969 | const mod = self.module; |
| 966 | 970 | const ip = &mod.intern_pool; |
| 967 | 971 | const ty_ref = try self.resolveType(ty, .direct); |
| 972 | const decl_val = anon_decl.val; | |
| 968 | 973 | const decl_ty = ip.typeOf(decl_val).toType(); |
| 969 | 974 | |
| 970 | 975 | if (decl_val.toValue().getFunction(mod)) |func| { |
src/link.zig+5-5| ... | ... | @@ -940,15 +940,15 @@ pub const File = struct { |
| 940 | 940 | |
| 941 | 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 | 944 | if (build_options.only_c) unreachable; |
| 945 | 945 | switch (base.tag) { |
| 946 | .coff => return @fieldParentPtr(Coff, "base", base).lowerAnonDecl(decl_val, src_loc), | |
| 947 | .elf => return @fieldParentPtr(Elf, "base", base).lowerAnonDecl(decl_val, src_loc), | |
| 948 | .macho => return @fieldParentPtr(MachO, "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, decl_align, src_loc), | |
| 948 | .macho => return @fieldParentPtr(MachO, "base", base).lowerAnonDecl(decl_val, decl_align, src_loc), | |
| 949 | 949 | .plan9 => return @fieldParentPtr(Plan9, "base", base).lowerAnonDecl(decl_val, src_loc), |
| 950 | 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 | 952 | .spirv => unreachable, |
| 953 | 953 | .nvptx => unreachable, |
| 954 | 954 | } |
src/link/C.zig+18-1| ... | ... | @@ -7,6 +7,7 @@ const fs = std.fs; |
| 7 | 7 | const C = @This(); |
| 8 | 8 | const Module = @import("../Module.zig"); |
| 9 | 9 | const InternPool = @import("../InternPool.zig"); |
| 10 | const Alignment = InternPool.Alignment; | |
| 10 | 11 | const Compilation = @import("../Compilation.zig"); |
| 11 | 12 | const codegen = @import("../codegen/c.zig"); |
| 12 | 13 | const link = @import("../link.zig"); |
| ... | ... | @@ -30,6 +31,10 @@ string_bytes: std.ArrayListUnmanaged(u8) = .{}, |
| 30 | 31 | /// Tracks all the anonymous decls that are used by all the decls so they can |
| 31 | 32 | /// be rendered during flush(). |
| 32 | 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 | 39 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new |
| 35 | 40 | /// one with every call. |
| ... | ... | @@ -125,6 +130,7 @@ pub fn deinit(self: *C) void { |
| 125 | 130 | db.deinit(gpa); |
| 126 | 131 | } |
| 127 | 132 | self.anon_decls.deinit(gpa); |
| 133 | self.aligned_anon_decls.deinit(gpa); | |
| 128 | 134 | |
| 129 | 135 | self.string_bytes.deinit(gpa); |
| 130 | 136 | self.fwd_decl_buf.deinit(gpa); |
| ... | ... | @@ -179,6 +185,7 @@ pub fn updateFunc( |
| 179 | 185 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 180 | 186 | .ctypes = ctypes.*, |
| 181 | 187 | .anon_decl_deps = self.anon_decls, |
| 188 | .aligned_anon_decls = self.aligned_anon_decls, | |
| 182 | 189 | }, |
| 183 | 190 | .code = code.toManaged(gpa), |
| 184 | 191 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| ... | ... | @@ -189,6 +196,7 @@ pub fn updateFunc( |
| 189 | 196 | function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() }; |
| 190 | 197 | defer { |
| 191 | 198 | self.anon_decls = function.object.dg.anon_decl_deps; |
| 199 | self.aligned_anon_decls = function.object.dg.aligned_anon_decls; | |
| 192 | 200 | fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged(); |
| 193 | 201 | code.* = function.object.code.moveToUnmanaged(); |
| 194 | 202 | function.deinit(); |
| ... | ... | @@ -232,6 +240,7 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { |
| 232 | 240 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 233 | 241 | .ctypes = .{}, |
| 234 | 242 | .anon_decl_deps = self.anon_decls, |
| 243 | .aligned_anon_decls = self.aligned_anon_decls, | |
| 235 | 244 | }, |
| 236 | 245 | .code = code.toManaged(gpa), |
| 237 | 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 | 249 | |
| 241 | 250 | defer { |
| 242 | 251 | self.anon_decls = object.dg.anon_decl_deps; |
| 252 | self.aligned_anon_decls = object.dg.aligned_anon_decls; | |
| 243 | 253 | object.dg.ctypes.deinit(object.dg.gpa); |
| 244 | 254 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 245 | 255 | code.* = object.code.moveToUnmanaged(); |
| ... | ... | @@ -250,7 +260,8 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { |
| 250 | 260 | .val = anon_decl.toValue(), |
| 251 | 261 | }; |
| 252 | 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 | 265 | error.AnalysisFail => { |
| 255 | 266 | @panic("TODO: C backend AnalysisFail on anonymous decl"); |
| 256 | 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 | 307 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 297 | 308 | .ctypes = ctypes.*, |
| 298 | 309 | .anon_decl_deps = self.anon_decls, |
| 310 | .aligned_anon_decls = self.aligned_anon_decls, | |
| 299 | 311 | }, |
| 300 | 312 | .code = code.toManaged(gpa), |
| 301 | 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 | 315 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; |
| 304 | 316 | defer { |
| 305 | 317 | self.anon_decls = object.dg.anon_decl_deps; |
| 318 | self.aligned_anon_decls = object.dg.aligned_anon_decls; | |
| 306 | 319 | object.dg.ctypes.deinit(object.dg.gpa); |
| 307 | 320 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 308 | 321 | code.* = object.code.moveToUnmanaged(); |
| ... | ... | @@ -602,6 +615,7 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void { |
| 602 | 615 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 603 | 616 | .ctypes = ctypes.*, |
| 604 | 617 | .anon_decl_deps = self.anon_decls, |
| 618 | .aligned_anon_decls = self.aligned_anon_decls, | |
| 605 | 619 | }, |
| 606 | 620 | .code = code.toManaged(gpa), |
| 607 | 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 | 623 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; |
| 610 | 624 | defer { |
| 611 | 625 | self.anon_decls = object.dg.anon_decl_deps; |
| 626 | self.aligned_anon_decls = object.dg.aligned_anon_decls; | |
| 612 | 627 | object.dg.ctypes.deinit(gpa); |
| 613 | 628 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 614 | 629 | code.* = object.code.moveToUnmanaged(); |
| ... | ... | @@ -642,6 +657,7 @@ fn flushLazyFn( |
| 642 | 657 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 643 | 658 | .ctypes = ctypes.*, |
| 644 | 659 | .anon_decl_deps = .{}, |
| 660 | .aligned_anon_decls = .{}, | |
| 645 | 661 | }, |
| 646 | 662 | .code = code.toManaged(gpa), |
| 647 | 663 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| ... | ... | @@ -651,6 +667,7 @@ fn flushLazyFn( |
| 651 | 667 | // If this assert trips just handle the anon_decl_deps the same as |
| 652 | 668 | // `updateFunc()` does. |
| 653 | 669 | assert(object.dg.anon_decl_deps.count() == 0); |
| 670 | assert(object.dg.aligned_anon_decls.count() == 0); | |
| 654 | 671 | object.dg.ctypes.deinit(gpa); |
| 655 | 672 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 656 | 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 | 1091 | const index = unnamed_consts.items.len; |
| 1092 | 1092 | const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); |
| 1093 | 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 | 1095 | .ok => |atom_index| atom_index, |
| 1096 | 1096 | .fail => |em| { |
| 1097 | 1097 | decl.analysis = .codegen_failure; |
| ... | ... | @@ -1109,13 +1109,12 @@ const LowerConstResult = union(enum) { |
| 1109 | 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 | 1113 | const gpa = self.base.allocator; |
| 1114 | 1114 | |
| 1115 | 1115 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 1116 | 1116 | defer code_buffer.deinit(); |
| 1117 | 1117 | |
| 1118 | const mod = self.base.options.module.?; | |
| 1119 | 1118 | const atom_index = try self.createAtom(); |
| 1120 | 1119 | const sym = self.getAtom(atom_index).getSymbolPtr(self); |
| 1121 | 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 | 1128 | .fail => |em| return .{ .fail = em }, |
| 1130 | 1129 | }; |
| 1131 | 1130 | |
| 1132 | const required_alignment: u32 = @intCast(tv.ty.abiAlignment(mod).toByteUnits(0)); | |
| 1133 | 1131 | const atom = self.getAtomPtr(atom_index); |
| 1134 | 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 | 1138 | errdefer self.freeAtom(atom_index); |
| 1137 | 1139 | |
| 1138 | 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 | 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 | 1742 | // This is basically the same as lowerUnnamedConst. |
| 1741 | 1743 | // example: |
| 1742 | 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 | 1749 | // to put it in some location. |
| 1748 | 1750 | // ... |
| 1749 | 1751 | const gpa = self.base.allocator; |
| 1752 | const mod = self.base.options.module.?; | |
| 1753 | const ty = mod.intern_pool.typeOf(decl_val).toType(); | |
| 1750 | 1754 | const gop = try self.anon_decls.getOrPut(gpa, decl_val); |
| 1751 | if (!gop.found_existing) { | |
| 1752 | const mod = self.base.options.module.?; | |
| 1753 | const ty = mod.intern_pool.typeOf(decl_val).toType(); | |
| 1755 | const required_alignment = switch (decl_align) { | |
| 1756 | .none => ty.abiAlignment(mod), | |
| 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 | 1762 | const val = decl_val.toValue(); |
| 1755 | 1763 | const tv = TypedValue{ .ty = ty, .val = val }; |
| 1756 | 1764 | const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)}); |
| 1757 | 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 | 1767 | else => { |
| 1760 | 1768 | // TODO improve error message |
| 1761 | 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 | 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 | 90 | /// Adds local type relocation of the form: @offset => @this + addend |
| 100 | 91 | /// @this signifies the offset within the .debug_abbrev section of the containing atom. |
| 101 | 92 | fn addTypeRelocLocal(self: *DeclState, atom_index: Atom.Index, offset: u32, addend: u32) !void { |
| ... | ... | @@ -807,11 +798,25 @@ pub const DeclState = struct { |
| 807 | 798 | try dbg_info.append(DW.OP.deref); |
| 808 | 799 | } |
| 809 | 800 | switch (loc) { |
| 810 | .linker_load => |load_struct| try self.addExprlocReloc( | |
| 811 | load_struct.sym_index, | |
| 812 | offset, | |
| 813 | is_ptr, | |
| 814 | ), | |
| 801 | .linker_load => |load_struct| switch (load_struct.type) { | |
| 802 | .direct => { | |
| 803 | log.debug("{x}: target sym %{d}", .{ offset, load_struct.sym_index }); | |
| 804 | try self.exprloc_relocs.append(self.gpa, .{ | |
| 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 | 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 | 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 | 477 | // This is basically the same as lowerUnnamedConst. |
| 478 | 478 | // example: |
| 479 | 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 | 484 | // to put it in some location. |
| 485 | 485 | // ... |
| 486 | 486 | const gpa = self.base.allocator; |
| 487 | const mod = self.base.options.module.?; | |
| 488 | const ty = mod.intern_pool.typeOf(decl_val).toType(); | |
| 487 | 489 | const gop = try self.anon_decls.getOrPut(gpa, decl_val); |
| 488 | if (!gop.found_existing) { | |
| 489 | const mod = self.base.options.module.?; | |
| 490 | const ty = mod.intern_pool.typeOf(decl_val).toType(); | |
| 490 | const required_alignment = switch (decl_align) { | |
| 491 | .none => ty.abiAlignment(mod), | |
| 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 | 497 | const val = decl_val.toValue(); |
| 492 | 498 | const tv = TypedValue{ .ty = ty, .val = val }; |
| 493 | 499 | const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)}); |
| 494 | 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 | 502 | else => { |
| 497 | 503 | // TODO improve error message |
| 498 | 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 | 3485 | const index = unnamed_consts.items.len; |
| 3480 | 3486 | const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); |
| 3481 | 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 | 3489 | .ok => |sym_index| sym_index, |
| 3484 | 3490 | .fail => |em| { |
| 3485 | 3491 | decl.analysis = .codegen_failure; |
| ... | ... | @@ -3502,6 +3508,7 @@ fn lowerConst( |
| 3502 | 3508 | self: *Elf, |
| 3503 | 3509 | name: []const u8, |
| 3504 | 3510 | tv: TypedValue, |
| 3511 | required_alignment: InternPool.Alignment, | |
| 3505 | 3512 | output_section_index: u16, |
| 3506 | 3513 | src_loc: Module.SrcLoc, |
| 3507 | 3514 | ) !LowerConstResult { |
| ... | ... | @@ -3510,7 +3517,6 @@ fn lowerConst( |
| 3510 | 3517 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 3511 | 3518 | defer code_buffer.deinit(); |
| 3512 | 3519 | |
| 3513 | const mod = self.base.options.module.?; | |
| 3514 | 3520 | const zig_module = self.file(self.zig_module_index.?).?.zig_module; |
| 3515 | 3521 | const sym_index = try zig_module.addAtom(self); |
| 3516 | 3522 | |
| ... | ... | @@ -3524,7 +3530,6 @@ fn lowerConst( |
| 3524 | 3530 | .fail => |em| return .{ .fail = em }, |
| 3525 | 3531 | }; |
| 3526 | 3532 | |
| 3527 | const required_alignment = tv.ty.abiAlignment(mod); | |
| 3528 | 3533 | const phdr_index = self.phdr_to_shdr_table.get(output_section_index).?; |
| 3529 | 3534 | const local_sym = self.symbol(sym_index); |
| 3530 | 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 | 2196 | const index = unnamed_consts.items.len; |
| 2197 | 2197 | const name = try std.fmt.allocPrint(gpa, "___unnamed_{s}_{d}", .{ decl_name, index }); |
| 2198 | 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 | 2200 | .ok => |atom_index| atom_index, |
| 2201 | 2201 | .fail => |em| { |
| 2202 | 2202 | decl.analysis = .codegen_failure; |
| ... | ... | @@ -2219,6 +2219,7 @@ fn lowerConst( |
| 2219 | 2219 | self: *MachO, |
| 2220 | 2220 | name: []const u8, |
| 2221 | 2221 | tv: TypedValue, |
| 2222 | required_alignment: InternPool.Alignment, | |
| 2222 | 2223 | sect_id: u8, |
| 2223 | 2224 | src_loc: Module.SrcLoc, |
| 2224 | 2225 | ) !LowerConstResult { |
| ... | ... | @@ -2227,8 +2228,6 @@ fn lowerConst( |
| 2227 | 2228 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 2228 | 2229 | defer code_buffer.deinit(); |
| 2229 | 2230 | |
| 2230 | const mod = self.base.options.module.?; | |
| 2231 | ||
| 2232 | 2231 | log.debug("allocating symbol indexes for {s}", .{name}); |
| 2233 | 2232 | |
| 2234 | 2233 | const sym_index = try self.allocateSymbol(); |
| ... | ... | @@ -2243,7 +2242,6 @@ fn lowerConst( |
| 2243 | 2242 | .fail => |em| return .{ .fail = em }, |
| 2244 | 2243 | }; |
| 2245 | 2244 | |
| 2246 | const required_alignment = tv.ty.abiAlignment(mod); | |
| 2247 | 2245 | const atom = self.getAtomPtr(atom_index); |
| 2248 | 2246 | atom.size = code.len; |
| 2249 | 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 | 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 | 2870 | // This is basically the same as lowerUnnamedConst. |
| 2873 | 2871 | // example: |
| 2874 | 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 | 2877 | // to put it in some location. |
| 2880 | 2878 | // ... |
| 2881 | 2879 | const gpa = self.base.allocator; |
| 2880 | const mod = self.base.options.module.?; | |
| 2881 | const ty = mod.intern_pool.typeOf(decl_val).toType(); | |
| 2882 | 2882 | const gop = try self.anon_decls.getOrPut(gpa, decl_val); |
| 2883 | if (!gop.found_existing) { | |
| 2884 | const mod = self.base.options.module.?; | |
| 2885 | const ty = mod.intern_pool.typeOf(decl_val).toType(); | |
| 2883 | const required_alignment = switch (decl_align) { | |
| 2884 | .none => ty.abiAlignment(mod), | |
| 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 | 2890 | const val = decl_val.toValue(); |
| 2887 | 2891 | const tv = TypedValue{ .ty = ty, .val = val }; |
| 2888 | 2892 | const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)}); |
| 2889 | 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 | 2895 | else => { |
| 2892 | 2896 | // TODO improve error message |
| 2893 | 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 | 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 | 1706 | const gop = try wasm.anon_decls.getOrPut(wasm.base.allocator, decl_val); |
| 1707 | if (gop.found_existing) { | |
| 1708 | return .ok; | |
| 1709 | } | |
| 1707 | if (!gop.found_existing) { | |
| 1708 | const mod = wasm.base.options.module.?; | |
| 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.?; | |
| 1712 | const ty = mod.intern_pool.typeOf(decl_val).toType(); | |
| 1713 | const tv: TypedValue = .{ .ty = ty, .val = decl_val.toValue() }; | |
| 1714 | const name = try std.fmt.allocPrintZ(wasm.base.allocator, "__anon_{d}", .{@intFromEnum(decl_val)}); | |
| 1715 | defer wasm.base.allocator.free(name); | |
| 1714 | switch (try wasm.lowerConst(name, tv, src_loc)) { | |
| 1715 | .ok => |atom_index| gop.value_ptr.* = atom_index, | |
| 1716 | .fail => |em| return .{ .fail = em }, | |
| 1717 | } | |
| 1718 | } | |
| 1716 | 1719 | |
| 1717 | switch (try wasm.lowerConst(name, tv, src_loc)) { | |
| 1718 | .ok => |atom_index| { | |
| 1719 | gop.value_ptr.* = atom_index; | |
| 1720 | return .ok; | |
| 1720 | const atom = wasm.getAtomPtr(gop.value_ptr.*); | |
| 1721 | atom.alignment = switch (atom.alignment) { | |
| 1722 | .none => decl_align, | |
| 1723 | else => switch (decl_align) { | |
| 1724 | .none => atom.alignment, | |
| 1725 | else => atom.alignment.maxStrict(decl_align), | |
| 1721 | 1726 | }, |
| 1722 | .fail => |em| return .{ .fail = em }, | |
| 1723 | } | |
| 1727 | }; | |
| 1728 | return .ok; | |
| 1724 | 1729 | } |
| 1725 | 1730 | |
| 1726 | 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 | 1571 | .none => switch (ip.indexToKey(switch (ptr.addr) { |
| 1572 | 1572 | .decl => |decl| mod.declPtr(decl).ty.toIntern(), |
| 1573 | 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 | 1575 | .comptime_field => |comptime_field| ip.typeOf(comptime_field), |
| 1576 | 1576 | else => unreachable, |
| 1577 | 1577 | })) { |
| ... | ... | @@ -1604,7 +1604,7 @@ pub const Value = struct { |
| 1604 | 1604 | })).toValue(), |
| 1605 | 1605 | .ptr => |ptr| switch (ptr.addr) { |
| 1606 | 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 | 1608 | .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod)) |
| 1609 | 1609 | .toValue().maybeElemValue(mod, index), |
| 1610 | 1610 | .int, .eu_payload => null, |
test/behavior.zig-1| ... | ... | @@ -37,7 +37,6 @@ test { |
| 37 | 37 | _ = @import("behavior/bugs/1500.zig"); |
| 38 | 38 | _ = @import("behavior/bugs/1607.zig"); |
| 39 | 39 | _ = @import("behavior/bugs/1735.zig"); |
| 40 | _ = @import("behavior/bugs/1741.zig"); | |
| 41 | 40 | _ = @import("behavior/bugs/1851.zig"); |
| 42 | 41 | _ = @import("behavior/bugs/1914.zig"); |
| 43 | 42 | _ = @import("behavior/bugs/2006.zig"); |
test/behavior/align.zig+9| ... | ... | @@ -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 | 27 | test "slicing array of length 1 can not assume runtime index is always zero" { |
| 19 | 28 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 20 | 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 | } |