authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-10-21 21:38:55-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-10-21 21:38:55-04:00
log7d50634e0ad4355e339bc243a2e2842693e133f9
treecd6f81b82b20532d40e0944e6a814519ebf7cb41
parent3cd3052d4d303dbae7d517fa40f6d171c957afdd
parent3d7c6c803b788138aa08f51cf4ee8cf7892e315d
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #17545 from ziglang/more-anon-decls

migrate make_ptr_const to new anonymous decl mechanism

25 files changed, 336 insertions(+), 152 deletions(-)

lib/std/elf.zig+12-12
......@@ -782,10 +782,10 @@ pub const Elf32_Sym = extern struct {
782782 st_shndx: Elf32_Section,
783783
784784 pub inline fn st_type(self: @This()) u4 {
785 return @as(u4, @truncate(self.st_info));
785 return @truncate(self.st_info);
786786 }
787787 pub inline fn st_bind(self: @This()) u4 {
788 return @as(u4, @truncate(self.st_info >> 4));
788 return @truncate(self.st_info >> 4);
789789 }
790790};
791791pub const Elf64_Sym = extern struct {
......@@ -797,10 +797,10 @@ pub const Elf64_Sym = extern struct {
797797 st_size: Elf64_Xword,
798798
799799 pub inline fn st_type(self: @This()) u4 {
800 return @as(u4, @truncate(self.st_info));
800 return @truncate(self.st_info);
801801 }
802802 pub inline fn st_bind(self: @This()) u4 {
803 return @as(u4, @truncate(self.st_info >> 4));
803 return @truncate(self.st_info >> 4);
804804 }
805805};
806806pub const Elf32_Syminfo = extern struct {
......@@ -816,10 +816,10 @@ pub const Elf32_Rel = extern struct {
816816 r_info: Elf32_Word,
817817
818818 pub inline fn r_sym(self: @This()) u24 {
819 return @as(u24, @truncate(self.r_info >> 8));
819 return @truncate(self.r_info >> 8);
820820 }
821821 pub inline fn r_type(self: @This()) u8 {
822 return @as(u8, @truncate(self.r_info));
822 return @truncate(self.r_info);
823823 }
824824};
825825pub const Elf64_Rel = extern struct {
......@@ -827,10 +827,10 @@ pub const Elf64_Rel = extern struct {
827827 r_info: Elf64_Xword,
828828
829829 pub inline fn r_sym(self: @This()) u32 {
830 return @as(u32, @truncate(self.r_info >> 32));
830 return @truncate(self.r_info >> 32);
831831 }
832832 pub inline fn r_type(self: @This()) u32 {
833 return @as(u32, @truncate(self.r_info));
833 return @truncate(self.r_info);
834834 }
835835};
836836pub const Elf32_Rela = extern struct {
......@@ -839,10 +839,10 @@ pub const Elf32_Rela = extern struct {
839839 r_addend: Elf32_Sword,
840840
841841 pub inline fn r_sym(self: @This()) u24 {
842 return @as(u24, @truncate(self.r_info >> 8));
842 return @truncate(self.r_info >> 8);
843843 }
844844 pub inline fn r_type(self: @This()) u8 {
845 return @as(u8, @truncate(self.r_info));
845 return @truncate(self.r_info);
846846 }
847847};
848848pub const Elf64_Rela = extern struct {
......@@ -851,10 +851,10 @@ pub const Elf64_Rela = extern struct {
851851 r_addend: Elf64_Sxword,
852852
853853 pub inline fn r_sym(self: @This()) u32 {
854 return @as(u32, @truncate(self.r_info >> 32));
854 return @truncate(self.r_info >> 32);
855855 }
856856 pub inline fn r_type(self: @This()) u32 {
857 return @as(u32, @truncate(self.r_info));
857 return @truncate(self.r_info);
858858 }
859859};
860860pub const Elf32_Dyn = extern struct {
src/AstGen.zig+6-4
......@@ -3123,10 +3123,10 @@ fn varDecl(
31233123 if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node))
31243124 _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst });
31253125
3126 if (resolve_inferred_alloc != .none) {
3126 const const_ptr = if (resolve_inferred_alloc != .none) p: {
31273127 _ = 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);
31303130
31313131 try gz.addDbgVar(.dbg_var_ptr, ident_name, const_ptr);
31323132
......@@ -3533,7 +3533,9 @@ fn assignDestructureMaybeDecls(
35333533 else => unreachable,
35343534 };
35353535 // 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.
35373539 break :make_const try gz.addUnNode(.make_ptr_const, raw_ptr, node);
35383540 } else raw_ptr;
35393541 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
35453545 .fwd_decl = fwd_decl.toManaged(gpa),
35463546 .ctypes = .{},
35473547 .anon_decl_deps = .{},
3548 .aligned_anon_decls = .{},
35483549 };
35493550 defer {
35503551 dg.ctypes.deinit(gpa);
src/InternPool.zig+86-14
......@@ -1074,7 +1074,7 @@ pub const Key = union(enum) {
10741074
10751075 decl: Module.Decl.Index,
10761076 mut_decl: MutDecl,
1077 anon_decl: Index,
1077 anon_decl: AnonDecl,
10781078 comptime_field: Index,
10791079 int: Index,
10801080 eu_payload: Index,
......@@ -1090,6 +1090,14 @@ pub const Key = union(enum) {
10901090 base: Index,
10911091 index: u64,
10921092 };
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 };
10931101 };
10941102 };
10951103
......@@ -1231,7 +1239,8 @@ pub const Key = union(enum) {
12311239 common ++ asBytes(&x.decl) ++ asBytes(&x.runtime_index),
12321240 ),
12331241
1234 .anon_decl,
1242 .anon_decl => |x| Hash.hash(seed2, common ++ asBytes(&x)),
1243
12351244 .int,
12361245 .eu_payload,
12371246 .opt_payload,
......@@ -1500,7 +1509,8 @@ pub const Key = union(enum) {
15001509 return switch (a_info.addr) {
15011510 .decl => |a_decl| a_decl == b_info.addr.decl,
15021511 .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,
15041514 .int => |a_int| a_int == b_info.addr.int,
15051515 .eu_payload => |a_eu_payload| a_eu_payload == b_info.addr.eu_payload,
15061516 .opt_payload => |a_opt_payload| a_opt_payload == b_info.addr.opt_payload,
......@@ -2133,6 +2143,7 @@ pub const Index = enum(u32) {
21332143 ptr_decl: struct { data: *PtrDecl },
21342144 ptr_mut_decl: struct { data: *PtrMutDecl },
21352145 ptr_anon_decl: struct { data: *PtrAnonDecl },
2146 ptr_anon_decl_aligned: struct { data: *PtrAnonDeclAligned },
21362147 ptr_comptime_field: struct { data: *PtrComptimeField },
21372148 ptr_int: struct { data: *PtrBase },
21382149 ptr_eu_payload: struct { data: *PtrBase },
......@@ -2583,8 +2594,16 @@ pub const Tag = enum(u8) {
25832594 /// data is extra index of `PtrMutDecl`, which contains the type and address.
25842595 ptr_mut_decl,
25852596 /// 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.
25872599 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,
25882607 /// data is extra index of `PtrComptimeField`, which contains the pointer type and field value.
25892608 ptr_comptime_field,
25902609 /// A pointer with an integer value.
......@@ -2781,6 +2800,7 @@ pub const Tag = enum(u8) {
27812800 .ptr_decl => PtrDecl,
27822801 .ptr_mut_decl => PtrMutDecl,
27832802 .ptr_anon_decl => PtrAnonDecl,
2803 .ptr_anon_decl_aligned => PtrAnonDeclAligned,
27842804 .ptr_comptime_field => PtrComptimeField,
27852805 .ptr_int => PtrBase,
27862806 .ptr_eu_payload => PtrBase,
......@@ -3383,6 +3403,13 @@ pub const PtrAnonDecl = struct {
33833403 val: Index,
33843404};
33853405
3406pub 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
33863413pub const PtrMutDecl = struct {
33873414 ty: Index,
33883415 decl: Module.Decl.Index,
......@@ -3736,7 +3763,20 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
37363763 const info = ip.extraData(PtrAnonDecl, data);
37373764 return .{ .ptr = .{
37383765 .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 } },
37403780 } };
37413781 },
37423782 .ptr_comptime_field => {
......@@ -3817,7 +3857,17 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
38173857 } };
38183858 },
38193859 .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 } };
38213871 },
38223872 .ptr_comptime_field => .{
38233873 .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 {
45714621 .runtime_index = mut_decl.runtime_index,
45724622 }),
45734623 }),
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 ),
45814640 .comptime_field => |field_val| {
45824641 assert(field_val != .none);
45834642 ip.items.appendAssumeCapacity(.{
......@@ -7184,6 +7243,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
71847243 .ptr_decl => @sizeOf(PtrDecl),
71857244 .ptr_mut_decl => @sizeOf(PtrMutDecl),
71867245 .ptr_anon_decl => @sizeOf(PtrAnonDecl),
7246 .ptr_anon_decl_aligned => @sizeOf(PtrAnonDeclAligned),
71877247 .ptr_comptime_field => @sizeOf(PtrComptimeField),
71887248 .ptr_int => @sizeOf(PtrBase),
71897249 .ptr_eu_payload => @sizeOf(PtrBase),
......@@ -7314,6 +7374,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
73147374 .ptr_decl,
73157375 .ptr_mut_decl,
73167376 .ptr_anon_decl,
7377 .ptr_anon_decl_aligned,
73177378 .ptr_comptime_field,
73187379 .ptr_int,
73197380 .ptr_eu_payload,
......@@ -7695,6 +7756,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
76957756 inline .ptr_decl,
76967757 .ptr_mut_decl,
76977758 .ptr_anon_decl,
7759 .ptr_anon_decl_aligned,
76987760 .ptr_comptime_field,
76997761 .ptr_int,
77007762 .ptr_eu_payload,
......@@ -7855,7 +7917,7 @@ pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.Addr.Tag {
78557917 switch (ip.items.items(.tag)[base]) {
78567918 .ptr_decl => return .decl,
78577919 .ptr_mut_decl => return .mut_decl,
7858 .ptr_anon_decl => return .anon_decl,
7920 .ptr_anon_decl, .ptr_anon_decl_aligned => return .anon_decl,
78597921 .ptr_comptime_field => return .comptime_field,
78607922 .ptr_int => return .int,
78617923 inline .ptr_eu_payload,
......@@ -8032,6 +8094,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
80328094 .ptr_decl,
80338095 .ptr_mut_decl,
80348096 .ptr_anon_decl,
8097 .ptr_anon_decl_aligned,
80358098 .ptr_comptime_field,
80368099 .ptr_int,
80378100 .ptr_eu_payload,
......@@ -8281,3 +8344,12 @@ pub fn addFieldName(
82818344 ip.extra.items[names_start + field_index] = @intFromEnum(name);
82828345 return null;
82838346}
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.
8350fn 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
36573657 const elem_ty = ptr_info.child.toType();
36583658
36593659 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 } })));
36633667 return sema.makePtrConst(block, new_mut_ptr);
36643668 }
36653669
......@@ -3668,10 +3672,18 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
36683672 implicit_ct: {
36693673 const ptr_val = try sema.resolveMaybeUndefVal(alloc) orelse break :implicit_ct;
36703674 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 }
36753687 }
36763688 return sema.makePtrConst(block, alloc);
36773689 }
......@@ -3911,17 +3923,19 @@ fn finishResolveComptimeKnownAllocValue(sema: *Sema, result_val: InternPool.Inde
39113923 return result_val;
39123924}
39133925
3926fn 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
39143932fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Air.Inst.Ref {
3915 const mod = sema.mod;
39163933 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);
39213935
39223936 // Detect if a comptime value simply needs to have its type changed.
39233937 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());
39253939 }
39263940
39273941 return block.addBitCast(const_ptr_ty, alloc);
......@@ -4035,6 +4049,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
40354049 defer tracy.end();
40364050
40374051 const mod = sema.mod;
4052 const gpa = sema.gpa;
40384053 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
40394054 const src = inst_data.src();
40404055 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
41004115 if (!ia1.is_const) {
41014116 try sema.validateVarType(block, ty_src, final_elem_ty, false);
41024117 } 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 } });
41084126
41094127 // Remap the ZIR oeprand to the resolved pointer value
41104128 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
41274145
41284146 // Now we need to go back over all the store instructions, and do the logic as if
41294147 // the new result ptr type was available.
4130 const gpa = sema.gpa;
41314148
41324149 for (ia2.prongs.items) |placeholder_inst| {
41334150 var replacement_block = block.makeSubBlock();
......@@ -5539,7 +5556,10 @@ fn addStrLitNoAlias(sema: *Sema, bytes: []const u8) CompileError!Air.Inst.Ref {
55395556 });
55405557 return Air.internedToRef((try mod.intern(.{ .ptr = .{
55415558 .ty = ptr_ty.toIntern(),
5542 .addr = .{ .anon_decl = val },
5559 .addr = .{ .anon_decl = .{
5560 .val = val,
5561 .orig_ty = ptr_ty.toIntern(),
5562 } },
55435563 } })));
55445564}
55455565
......@@ -30545,7 +30565,8 @@ fn beginComptimePtrLoad(
3054530565 .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null,
3054630566 };
3054730567 },
30548 .anon_decl => |decl_val| blk: {
30568 .anon_decl => |anon_decl| blk: {
30569 const decl_val = anon_decl.val;
3054930570 if (decl_val.toValue().getVariable(mod) != null) return error.RuntimeLoad;
3055030571 const decl_ty = ip.typeOf(decl_val).toType();
3055130572 const decl_tv: TypedValue = .{ .ty = decl_ty, .val = decl_val.toValue() };
......@@ -36649,6 +36670,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3664936670 .simple_value,
3665036671 .ptr_decl,
3665136672 .ptr_anon_decl,
36673 .ptr_anon_decl_aligned,
3665236674 .ptr_mut_decl,
3665336675 .ptr_comptime_field,
3665436676 .ptr_int,
src/TypedValue.zig+2-1
......@@ -321,7 +321,8 @@ pub fn print(
321321 .val = decl.val,
322322 }, writer, level - 1, mod);
323323 },
324 .anon_decl => |decl_val| {
324 .anon_decl => |anon_decl| {
325 const decl_val = anon_decl.val;
325326 if (level == 0) return writer.print("(anon decl '{d}')", .{
326327 @intFromEnum(decl_val),
327328 });
src/Zir.zig+3-2
......@@ -997,8 +997,9 @@ pub const Inst = struct {
997997 /// is the allocation that needs to have its type inferred.
998998 /// Uses the `un_node` field. The AST node is the var decl.
999999 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.
10021003 /// Uses the `un_node` union field.
10031004 make_ptr_const,
10041005
src/arch/wasm/CodeGen.zig+10-4
......@@ -3139,16 +3139,22 @@ fn lowerParentPtrDecl(func: *CodeGen, ptr_val: Value, decl_index: Module.Decl.In
31393139 return func.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index, offset);
31403140}
31413141
3142fn lowerAnonDeclRef(func: *CodeGen, anon_decl: InternPool.Index, offset: u32) InnerError!WValue {
3142fn lowerAnonDeclRef(
3143 func: *CodeGen,
3144 anon_decl: InternPool.Key.Ptr.Addr.AnonDecl,
3145 offset: u32,
3146) InnerError!WValue {
31433147 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();
31453150
31463151 const is_fn_body = ty.zigTypeTag(mod) == .Fn;
31473152 if (!is_fn_body and !ty.hasRuntimeBitsIgnoreComptime(mod)) {
31483153 return WValue{ .imm32 = 0xaaaaaaaa };
31493154 }
31503155
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));
31523158 switch (res) {
31533159 .ok => {},
31543160 .fail => |em| {
......@@ -3156,7 +3162,7 @@ fn lowerAnonDeclRef(func: *CodeGen, anon_decl: InternPool.Index, offset: u32) In
31563162 return error.CodegenFail;
31573163 },
31583164 }
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).?;
31603166 const target_sym_index = func.bin_file.getAtom(target_atom_index).getSymbolIndex().?;
31613167 if (is_fn_body) {
31623168 return WValue{ .function_index = target_sym_index };
src/codegen.zig+4-2
......@@ -713,7 +713,7 @@ const RelocInfo = struct {
713713fn lowerAnonDeclRef(
714714 bin_file: *link.File,
715715 src_loc: Module.SrcLoc,
716 decl_val: InternPool.Index,
716 anon_decl: InternPool.Key.Ptr.Addr.AnonDecl,
717717 code: *std.ArrayList(u8),
718718 debug_output: DebugInfoOutput,
719719 reloc_info: RelocInfo,
......@@ -723,6 +723,7 @@ fn lowerAnonDeclRef(
723723 const mod = bin_file.options.module.?;
724724
725725 const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8);
726 const decl_val = anon_decl.val;
726727 const decl_ty = mod.intern_pool.typeOf(decl_val).toType();
727728 const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn;
728729 if (!is_fn_body and !decl_ty.hasRuntimeBits(mod)) {
......@@ -730,7 +731,8 @@ fn lowerAnonDeclRef(
730731 return Result.ok;
731732 }
732733
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);
734736 switch (res) {
735737 .ok => {},
736738 .fail => |em| return .{ .fail = em },
src/codegen/c.zig+19-2
......@@ -531,6 +531,7 @@ pub const DeclGen = struct {
531531 /// Keeps track of anonymous decls that need to be rendered before this
532532 /// (named) Decl in the output C code.
533533 anon_decl_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.DeclBlock),
534 aligned_anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
534535
535536 fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
536537 @setCold(true);
......@@ -548,11 +549,12 @@ pub const DeclGen = struct {
548549 writer: anytype,
549550 ty: Type,
550551 ptr_val: Value,
551 decl_val: InternPool.Index,
552 anon_decl: InternPool.Key.Ptr.Addr.AnonDecl,
552553 location: ValueRenderLocation,
553554 ) error{ OutOfMemory, AnalysisFail }!void {
554555 const mod = dg.module;
555556 const ip = &mod.intern_pool;
557 const decl_val = anon_decl.val;
556558 const decl_ty = ip.typeOf(decl_val).toType();
557559
558560 // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.
......@@ -592,8 +594,23 @@ pub const DeclGen = struct {
592594
593595 // Indicate that the anon decl should be rendered to the output so that
594596 // our reference above is not undefined.
597 const ptr_type = ip.indexToKey(anon_decl.orig_ty).ptr_type;
595598 const gop = try dg.anon_decl_deps.getOrPut(dg.gpa, decl_val);
596599 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 }
597614 }
598615
599616 fn renderDeclValue(
......@@ -651,7 +668,7 @@ pub const DeclGen = struct {
651668 switch (ptr.addr) {
652669 .decl => |d| try dg.renderDeclValue(writer, ptr_ty, ptr_val.toValue(), d, location),
653670 .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),
655672 .int => |int| {
656673 try writer.writeByte('(');
657674 try dg.renderCType(writer, ptr_cty);
src/codegen/llvm.zig+18-13
......@@ -3049,10 +3049,19 @@ pub const Object = struct {
30493049 o: *Object,
30503050 decl_val: InternPool.Index,
30513051 llvm_addr_space: Builder.AddrSpace,
3052 alignment: InternPool.Alignment,
30523053 ) Error!Builder.Variable.Index {
3054 assert(alignment != .none);
30533055 // TODO: Add address space to the anon_decl_map
30543056 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 }
30563065 errdefer assert(o.anon_decl_map.remove(decl_val));
30573066
30583067 const mod = o.module;
......@@ -3068,6 +3077,7 @@ pub const Object = struct {
30683077 try variable_index.setInitializer(try o.lowerValue(decl_val), &o.builder);
30693078 variable_index.setLinkage(.internal, &o.builder);
30703079 variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
3080 variable_index.setAlignment(alignment.toLlvm(), &o.builder);
30713081 return variable_index;
30723082 }
30733083
......@@ -4250,13 +4260,6 @@ pub const Object = struct {
42504260 return o.builder.bigIntConst(try o.builder.intType(ty.intInfo(mod).bits), bigint);
42514261 }
42524262
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
42604263 fn lowerParentPtrDecl(o: *Object, decl_index: Module.Decl.Index) Allocator.Error!Builder.Constant {
42614264 const mod = o.module;
42624265 const decl = mod.declPtr(decl_index);
......@@ -4272,7 +4275,7 @@ pub const Object = struct {
42724275 return switch (ptr.addr) {
42734276 .decl => |decl| try o.lowerParentPtrDecl(decl),
42744277 .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),
42764279 .int => |int| try o.lowerIntAsPtr(int),
42774280 .eu_payload => |eu_ptr| {
42784281 const parent_ptr = try o.lowerParentPtr(eu_ptr.toValue());
......@@ -4391,10 +4394,11 @@ pub const Object = struct {
43914394 fn lowerAnonDeclRef(
43924395 o: *Object,
43934396 ptr_ty: Type,
4394 decl_val: InternPool.Index,
4397 anon_decl: InternPool.Key.Ptr.Addr.AnonDecl,
43954398 ) Error!Builder.Constant {
43964399 const mod = o.module;
43974400 const ip = &mod.intern_pool;
4401 const decl_val = anon_decl.val;
43984402 const decl_ty = ip.typeOf(decl_val).toType();
43994403 const target = mod.getTarget();
44004404
......@@ -4413,9 +4417,10 @@ pub const Object = struct {
44134417 if (is_fn_body)
44144418 @panic("TODO");
44154419
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;
44194424
44204425 const llvm_val = try o.builder.convConst(
44214426 .unneeded,
src/codegen/llvm/Builder.zig+6
......@@ -2477,6 +2477,12 @@ pub const Variable = struct {
24772477 self.ptr(builder).alignment = alignment;
24782478 }
24792479
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
24802486 pub fn toLlvm(self: Index, builder: *const Builder) *llvm.Value {
24812487 return self.ptrConst(builder).global.toLlvm(builder);
24822488 }
src/codegen/llvm/bindings.zig+3
......@@ -273,6 +273,9 @@ pub const Value = opaque {
273273 pub const setAlignment = LLVMSetAlignment;
274274 extern fn LLVMSetAlignment(V: *Value, Bytes: c_uint) void;
275275
276 pub const getAlignment = LLVMGetAlignment;
277 extern fn LLVMGetAlignment(V: *Value) c_uint;
278
276279 pub const setFunctionCallConv = LLVMSetFunctionCallConv;
277280 extern fn LLVMSetFunctionCallConv(Fn: *Value, CC: CallConv) void;
278281
src/codegen/spirv.zig+6-1
......@@ -959,12 +959,17 @@ const DeclGen = struct {
959959 }
960960 }
961961
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 {
963967 // TODO: Merge this function with constantDeclRef.
964968
965969 const mod = self.module;
966970 const ip = &mod.intern_pool;
967971 const ty_ref = try self.resolveType(ty, .direct);
972 const decl_val = anon_decl.val;
968973 const decl_ty = ip.typeOf(decl_val).toType();
969974
970975 if (decl_val.toValue().getFunction(mod)) |func| {
src/link.zig+5-5
......@@ -940,15 +940,15 @@ pub const File = struct {
940940
941941 pub const LowerResult = @import("codegen.zig").Result;
942942
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 {
944944 if (build_options.only_c) unreachable;
945945 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),
949949 .plan9 => return @fieldParentPtr(Plan9, "base", base).lowerAnonDecl(decl_val, src_loc),
950950 .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),
952952 .spirv => unreachable,
953953 .nvptx => unreachable,
954954 }
src/link/C.zig+18-1
......@@ -7,6 +7,7 @@ const fs = std.fs;
77const C = @This();
88const Module = @import("../Module.zig");
99const InternPool = @import("../InternPool.zig");
10const Alignment = InternPool.Alignment;
1011const Compilation = @import("../Compilation.zig");
1112const codegen = @import("../codegen/c.zig");
1213const link = @import("../link.zig");
......@@ -30,6 +31,10 @@ string_bytes: std.ArrayListUnmanaged(u8) = .{},
3031/// Tracks all the anonymous decls that are used by all the decls so they can
3132/// be rendered during flush().
3233anon_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`.
37aligned_anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .{},
3338
3439/// Optimization, `updateDecl` reuses this buffer rather than creating a new
3540/// one with every call.
......@@ -125,6 +130,7 @@ pub fn deinit(self: *C) void {
125130 db.deinit(gpa);
126131 }
127132 self.anon_decls.deinit(gpa);
133 self.aligned_anon_decls.deinit(gpa);
128134
129135 self.string_bytes.deinit(gpa);
130136 self.fwd_decl_buf.deinit(gpa);
......@@ -179,6 +185,7 @@ pub fn updateFunc(
179185 .fwd_decl = fwd_decl.toManaged(gpa),
180186 .ctypes = ctypes.*,
181187 .anon_decl_deps = self.anon_decls,
188 .aligned_anon_decls = self.aligned_anon_decls,
182189 },
183190 .code = code.toManaged(gpa),
184191 .indent_writer = undefined, // set later so we can get a pointer to object.code
......@@ -189,6 +196,7 @@ pub fn updateFunc(
189196 function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() };
190197 defer {
191198 self.anon_decls = function.object.dg.anon_decl_deps;
199 self.aligned_anon_decls = function.object.dg.aligned_anon_decls;
192200 fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged();
193201 code.* = function.object.code.moveToUnmanaged();
194202 function.deinit();
......@@ -232,6 +240,7 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void {
232240 .fwd_decl = fwd_decl.toManaged(gpa),
233241 .ctypes = .{},
234242 .anon_decl_deps = self.anon_decls,
243 .aligned_anon_decls = self.aligned_anon_decls,
235244 },
236245 .code = code.toManaged(gpa),
237246 .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 {
240249
241250 defer {
242251 self.anon_decls = object.dg.anon_decl_deps;
252 self.aligned_anon_decls = object.dg.aligned_anon_decls;
243253 object.dg.ctypes.deinit(object.dg.gpa);
244254 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
245255 code.* = object.code.moveToUnmanaged();
......@@ -250,7 +260,8 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void {
250260 .val = anon_decl.toValue(),
251261 };
252262 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) {
254265 error.AnalysisFail => {
255266 @panic("TODO: C backend AnalysisFail on anonymous decl");
256267 //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
296307 .fwd_decl = fwd_decl.toManaged(gpa),
297308 .ctypes = ctypes.*,
298309 .anon_decl_deps = self.anon_decls,
310 .aligned_anon_decls = self.aligned_anon_decls,
299311 },
300312 .code = code.toManaged(gpa),
301313 .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
303315 object.indent_writer = .{ .underlying_writer = object.code.writer() };
304316 defer {
305317 self.anon_decls = object.dg.anon_decl_deps;
318 self.aligned_anon_decls = object.dg.aligned_anon_decls;
306319 object.dg.ctypes.deinit(object.dg.gpa);
307320 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
308321 code.* = object.code.moveToUnmanaged();
......@@ -602,6 +615,7 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void {
602615 .fwd_decl = fwd_decl.toManaged(gpa),
603616 .ctypes = ctypes.*,
604617 .anon_decl_deps = self.anon_decls,
618 .aligned_anon_decls = self.aligned_anon_decls,
605619 },
606620 .code = code.toManaged(gpa),
607621 .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 {
609623 object.indent_writer = .{ .underlying_writer = object.code.writer() };
610624 defer {
611625 self.anon_decls = object.dg.anon_decl_deps;
626 self.aligned_anon_decls = object.dg.aligned_anon_decls;
612627 object.dg.ctypes.deinit(gpa);
613628 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
614629 code.* = object.code.moveToUnmanaged();
......@@ -642,6 +657,7 @@ fn flushLazyFn(
642657 .fwd_decl = fwd_decl.toManaged(gpa),
643658 .ctypes = ctypes.*,
644659 .anon_decl_deps = .{},
660 .aligned_anon_decls = .{},
645661 },
646662 .code = code.toManaged(gpa),
647663 .indent_writer = undefined, // set later so we can get a pointer to object.code
......@@ -651,6 +667,7 @@ fn flushLazyFn(
651667 // If this assert trips just handle the anon_decl_deps the same as
652668 // `updateFunc()` does.
653669 assert(object.dg.anon_decl_deps.count() == 0);
670 assert(object.dg.aligned_anon_decls.count() == 0);
654671 object.dg.ctypes.deinit(gpa);
655672 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
656673 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
10911091 const index = unnamed_consts.items.len;
10921092 const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });
10931093 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))) {
10951095 .ok => |atom_index| atom_index,
10961096 .fail => |em| {
10971097 decl.analysis = .codegen_failure;
......@@ -1109,13 +1109,12 @@ const LowerConstResult = union(enum) {
11091109 fail: *Module.ErrorMsg,
11101110};
11111111
1112fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult {
1112fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, required_alignment: InternPool.Alignment, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult {
11131113 const gpa = self.base.allocator;
11141114
11151115 var code_buffer = std.ArrayList(u8).init(gpa);
11161116 defer code_buffer.deinit();
11171117
1118 const mod = self.base.options.module.?;
11191118 const atom_index = try self.createAtom();
11201119 const sym = self.getAtom(atom_index).getSymbolPtr(self);
11211120 try self.setSymbolName(sym, name);
......@@ -1129,10 +1128,13 @@ fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, sect_id: u16, src_l
11291128 .fail => |em| return .{ .fail = em },
11301129 };
11311130
1132 const required_alignment: u32 = @intCast(tv.ty.abiAlignment(mod).toByteUnits(0));
11331131 const atom = self.getAtomPtr(atom_index);
11341132 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 );
11361138 errdefer self.freeAtom(atom_index);
11371139
11381140 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
17361738 return 0;
17371739}
17381740
1739pub fn lowerAnonDecl(self: *Coff, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result {
1741pub fn lowerAnonDecl(self: *Coff, decl_val: InternPool.Index, decl_align: InternPool.Alignment, src_loc: Module.SrcLoc) !codegen.Result {
17401742 // This is basically the same as lowerUnnamedConst.
17411743 // example:
17421744 // 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
17471749 // to put it in some location.
17481750 // ...
17491751 const gpa = self.base.allocator;
1752 const mod = self.base.options.module.?;
1753 const ty = mod.intern_pool.typeOf(decl_val).toType();
17501754 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 {
17541762 const val = decl_val.toValue();
17551763 const tv = TypedValue{ .ty = ty, .val = val };
17561764 const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)});
17571765 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) {
17591767 else => {
17601768 // TODO improve error message
17611769 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 {
8787 self.exprloc_relocs.deinit(self.gpa);
8888 }
8989
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
9990 /// Adds local type relocation of the form: @offset => @this + addend
10091 /// @this signifies the offset within the .debug_abbrev section of the containing atom.
10192 fn addTypeRelocLocal(self: *DeclState, atom_index: Atom.Index, offset: u32, addend: u32) !void {
......@@ -807,11 +798,25 @@ pub const DeclState = struct {
807798 try dbg_info.append(DW.OP.deref);
808799 }
809800 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 },
815820 else => {},
816821 }
817822 },
src/link/Elf.zig+13-8
......@@ -473,7 +473,7 @@ pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link.
473473 return vaddr;
474474}
475475
476pub fn lowerAnonDecl(self: *Elf, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result {
476pub fn lowerAnonDecl(self: *Elf, decl_val: InternPool.Index, decl_align: InternPool.Alignment, src_loc: Module.SrcLoc) !codegen.Result {
477477 // This is basically the same as lowerUnnamedConst.
478478 // example:
479479 // 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
484484 // to put it in some location.
485485 // ...
486486 const gpa = self.base.allocator;
487 const mod = self.base.options.module.?;
488 const ty = mod.intern_pool.typeOf(decl_val).toType();
487489 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 {
491497 const val = decl_val.toValue();
492498 const tv = TypedValue{ .ty = ty, .val = val };
493499 const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)});
494500 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) {
496502 else => {
497503 // TODO improve error message
498504 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
34793485 const index = unnamed_consts.items.len;
34803486 const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });
34813487 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))) {
34833489 .ok => |sym_index| sym_index,
34843490 .fail => |em| {
34853491 decl.analysis = .codegen_failure;
......@@ -3502,6 +3508,7 @@ fn lowerConst(
35023508 self: *Elf,
35033509 name: []const u8,
35043510 tv: TypedValue,
3511 required_alignment: InternPool.Alignment,
35053512 output_section_index: u16,
35063513 src_loc: Module.SrcLoc,
35073514) !LowerConstResult {
......@@ -3510,7 +3517,6 @@ fn lowerConst(
35103517 var code_buffer = std.ArrayList(u8).init(gpa);
35113518 defer code_buffer.deinit();
35123519
3513 const mod = self.base.options.module.?;
35143520 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
35153521 const sym_index = try zig_module.addAtom(self);
35163522
......@@ -3524,7 +3530,6 @@ fn lowerConst(
35243530 .fail => |em| return .{ .fail = em },
35253531 };
35263532
3527 const required_alignment = tv.ty.abiAlignment(mod);
35283533 const phdr_index = self.phdr_to_shdr_table.get(output_section_index).?;
35293534 const local_sym = self.symbol(sym_index);
35303535 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
21962196 const index = unnamed_consts.items.len;
21972197 const name = try std.fmt.allocPrint(gpa, "___unnamed_{s}_{d}", .{ decl_name, index });
21982198 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))) {
22002200 .ok => |atom_index| atom_index,
22012201 .fail => |em| {
22022202 decl.analysis = .codegen_failure;
......@@ -2219,6 +2219,7 @@ fn lowerConst(
22192219 self: *MachO,
22202220 name: []const u8,
22212221 tv: TypedValue,
2222 required_alignment: InternPool.Alignment,
22222223 sect_id: u8,
22232224 src_loc: Module.SrcLoc,
22242225) !LowerConstResult {
......@@ -2227,8 +2228,6 @@ fn lowerConst(
22272228 var code_buffer = std.ArrayList(u8).init(gpa);
22282229 defer code_buffer.deinit();
22292230
2230 const mod = self.base.options.module.?;
2231
22322231 log.debug("allocating symbol indexes for {s}", .{name});
22332232
22342233 const sym_index = try self.allocateSymbol();
......@@ -2243,7 +2242,6 @@ fn lowerConst(
22432242 .fail => |em| return .{ .fail = em },
22442243 };
22452244
2246 const required_alignment = tv.ty.abiAlignment(mod);
22472245 const atom = self.getAtomPtr(atom_index);
22482246 atom.size = code.len;
22492247 // 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
28682866 return 0;
28692867}
28702868
2871pub fn lowerAnonDecl(self: *MachO, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result {
2869pub fn lowerAnonDecl(self: *MachO, decl_val: InternPool.Index, decl_align: InternPool.Alignment, src_loc: Module.SrcLoc) !codegen.Result {
28722870 // This is basically the same as lowerUnnamedConst.
28732871 // example:
28742872 // 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
28792877 // to put it in some location.
28802878 // ...
28812879 const gpa = self.base.allocator;
2880 const mod = self.base.options.module.?;
2881 const ty = mod.intern_pool.typeOf(decl_val).toType();
28822882 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 {
28862890 const val = decl_val.toValue();
28872891 const tv = TypedValue{ .ty = ty, .val = val };
28882892 const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)});
28892893 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) {
28912895 else => {
28922896 // TODO improve error message
28932897 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(
17021702 return target_symbol_index;
17031703}
17041704
1705pub fn lowerAnonDecl(wasm: *Wasm, decl_val: InternPool.Index, src_loc: Module.SrcLoc) !codegen.Result {
1705pub fn lowerAnonDecl(wasm: *Wasm, decl_val: InternPool.Index, decl_align: Alignment, src_loc: Module.SrcLoc) !codegen.Result {
17061706 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);
17101713
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 }
17161719
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),
17211726 },
1722 .fail => |em| return .{ .fail = em },
1723 }
1727 };
1728 return .ok;
17241729}
17251730
17261731pub 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 {
15711571 .none => switch (ip.indexToKey(switch (ptr.addr) {
15721572 .decl => |decl| mod.declPtr(decl).ty.toIntern(),
15731573 .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),
15751575 .comptime_field => |comptime_field| ip.typeOf(comptime_field),
15761576 else => unreachable,
15771577 })) {
......@@ -1604,7 +1604,7 @@ pub const Value = struct {
16041604 })).toValue(),
16051605 .ptr => |ptr| switch (ptr.addr) {
16061606 .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),
16081608 .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod))
16091609 .toValue().maybeElemValue(mod, index),
16101610 .int, .eu_payload => null,
test/behavior.zig-1
......@@ -37,7 +37,6 @@ test {
3737 _ = @import("behavior/bugs/1500.zig");
3838 _ = @import("behavior/bugs/1607.zig");
3939 _ = @import("behavior/bugs/1735.zig");
40 _ = @import("behavior/bugs/1741.zig");
4140 _ = @import("behavior/bugs/1851.zig");
4241 _ = @import("behavior/bugs/1914.zig");
4342 _ = @import("behavior/bugs/2006.zig");
test/behavior/align.zig+9
......@@ -15,6 +15,15 @@ test "global variable alignment" {
1515 }
1616}
1717
18test "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
1827test "slicing array of length 1 can not assume runtime index is always zero" {
1928 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2029 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/bugs/1741.zig deleted-11
......@@ -1,11 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4test "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}