authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-19 21:23:09-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-10-21 21:38:41-04:00
logc4fcf0e22a0a0bab19ac9d1335b10decbfb2f137
treeab9d2b9228c6dfd927cdc5a6536811412d03c62b
parentdd402f6d83071535fffac055fabe72ebcb0db994

codegen: implement lowering aligned anon decls


7 files changed, 73 insertions(+), 57 deletions(-)

src/arch/wasm/CodeGen.zig+2-5
......@@ -3153,11 +3153,8 @@ fn lowerAnonDeclRef(
31533153 return WValue{ .imm32 = 0xaaaaaaaa };
31543154 }
31553155
3156 const alignment = mod.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment;
3157 if (alignment != .none) {
3158 @panic("TODO how to make this anon decl be aligned?");
3159 }
3160 const res = try func.bin_file.lowerAnonDecl(decl_val, 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));
31613158 switch (res) {
31623159 .ok => {},
31633160 .fail => |em| {
src/codegen.zig+2-5
......@@ -731,16 +731,13 @@ fn lowerAnonDeclRef(
731731 return Result.ok;
732732 }
733733
734 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);
735736 switch (res) {
736737 .ok => {},
737738 .fail => |em| return .{ .fail = em },
738739 }
739740
740 const alignment = mod.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment;
741 if (alignment != .none) {
742 @panic("TODO how to make this anon decl be aligned?");
743 }
744741 const vaddr = try bin_file.getAnonDeclVAddr(decl_val, .{
745742 .parent_atom_index = reloc_info.parent_atom_index,
746743 .offset = code.items.len,
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/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/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 {