authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-03 15:23:01+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-10-03 12:49:21-07:00
logd5b9d18bf0f0eed9eb37089e4531db24b06c9f94
treea6926f62862e95ad5ed15b2dde565a03e2a02d3a
parent57eefe0533d6de517f42be4fa9ddfc9ff7ab5c53

coff: implement lowering anon decls


1 files changed, 79 insertions(+), 36 deletions(-)

src/link/Coff.zig+79-36
......@@ -82,6 +82,7 @@ atom_by_index_table: std.AutoHashMapUnmanaged(u32, Atom.Index) = .{},
8282/// value assigned to label `foo` is an unnamed constant belonging/associated
8383/// with `Decl` `main`, and lives as long as that `Decl`.
8484unnamed_const_atoms: UnnamedConstTable = .{},
85anon_decls: AnonDeclTable = .{},
8586
8687/// A table of relocations indexed by the owning them `Atom`.
8788/// Note that once we refactor `Atom`'s lifetime and ownership rules,
......@@ -107,6 +108,7 @@ const HotUpdateState = struct {
107108 loaded_base_address: ?std.os.windows.HMODULE = null,
108109};
109110
111const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, Atom.Index);
110112const RelocTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Relocation));
111113const BaseRelocationTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32));
112114const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index));
......@@ -323,6 +325,7 @@ pub fn deinit(self: *Coff) void {
323325 atoms.deinit(gpa);
324326 }
325327 self.unnamed_const_atoms.deinit(gpa);
328 self.anon_decls.deinit(gpa);
326329
327330 for (self.relocs.values()) |*relocs| {
328331 relocs.deinit(gpa);
......@@ -1077,45 +1080,53 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air:
10771080
10781081pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.Index) !u32 {
10791082 const gpa = self.base.allocator;
1080 var code_buffer = std.ArrayList(u8).init(gpa);
1081 defer code_buffer.deinit();
1082
10831083 const mod = self.base.options.module.?;
10841084 const decl = mod.declPtr(decl_index);
1085
10861085 const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index);
10871086 if (!gop.found_existing) {
10881087 gop.value_ptr.* = .{};
10891088 }
10901089 const unnamed_consts = gop.value_ptr;
1090 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
1091 const index = unnamed_consts.items.len;
1092 const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });
1093 defer gpa.free(sym_name);
1094 const atom_index = switch (try self.lowerConst(sym_name, tv, self.rdata_section_index.?, decl.srcLoc(mod))) {
1095 .ok => |atom_index| atom_index,
1096 .fail => |em| {
1097 decl.analysis = .codegen_failure;
1098 try mod.failed_decls.put(mod.gpa, decl_index, em);
1099 log.err("{s}", .{em.msg});
1100 return error.CodegenFail;
1101 },
1102 };
1103 try unnamed_consts.append(gpa, atom_index);
1104 return self.getAtom(atom_index).getSymbolIndex().?;
1105}
10911106
1092 const atom_index = try self.createAtom();
1107const LowerConstResult = union(enum) {
1108 ok: Atom.Index,
1109 fail: *Module.ErrorMsg,
1110};
10931111
1094 const sym_name = blk: {
1095 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
1112fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult {
1113 const gpa = self.base.allocator;
10961114
1097 const index = unnamed_consts.items.len;
1098 break :blk try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });
1099 };
1100 defer gpa.free(sym_name);
1101 {
1102 const atom = self.getAtom(atom_index);
1103 const sym = atom.getSymbolPtr(self);
1104 try self.setSymbolName(sym, sym_name);
1105 sym.section_number = @as(coff.SectionNumber, @enumFromInt(self.rdata_section_index.? + 1));
1106 }
1115 var code_buffer = std.ArrayList(u8).init(gpa);
1116 defer code_buffer.deinit();
1117
1118 const mod = self.base.options.module.?;
1119 const atom_index = try self.createAtom();
1120 const sym = self.getAtom(atom_index).getSymbolPtr(self);
1121 try self.setSymbolName(sym, name);
1122 sym.section_number = @as(coff.SectionNumber, @enumFromInt(sect_id + 1));
11071123
1108 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), tv, &code_buffer, .none, .{
1124 const res = try codegen.generateSymbol(&self.base, src_loc, tv, &code_buffer, .none, .{
11091125 .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?,
11101126 });
11111127 var code = switch (res) {
11121128 .ok => code_buffer.items,
1113 .fail => |em| {
1114 decl.analysis = .codegen_failure;
1115 try mod.failed_decls.put(mod.gpa, decl_index, em);
1116 log.err("{s}", .{em.msg});
1117 return error.CodegenFail;
1118 },
1129 .fail => |em| return .{ .fail = em },
11191130 };
11201131
11211132 const required_alignment: u32 = @intCast(tv.ty.abiAlignment(mod).toByteUnits(0));
......@@ -1124,14 +1135,12 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In
11241135 atom.getSymbolPtr(self).value = try self.allocateAtom(atom_index, atom.size, required_alignment);
11251136 errdefer self.freeAtom(atom_index);
11261137
1127 try unnamed_consts.append(gpa, atom_index);
1128
1129 log.debug("allocated atom for {s} at 0x{x}", .{ sym_name, atom.getSymbol(self).value });
1138 log.debug("allocated atom for {s} at 0x{x}", .{ name, atom.getSymbol(self).value });
11301139 log.debug(" (required alignment 0x{x})", .{required_alignment});
11311140
11321141 try self.writeAtom(atom_index, code);
11331142
1134 return atom.getSymbolIndex().?;
1143 return .{ .ok = atom_index };
11351144}
11361145
11371146pub fn updateDecl(
......@@ -1737,17 +1746,51 @@ pub fn lowerAnonDecl(self: *Coff, decl_val: InternPool.Index, src_loc: Module.Sr
17371746 // be used by more than one function, however, its address is being used so we need
17381747 // to put it in some location.
17391748 // ...
1740 _ = self;
1741 _ = decl_val;
1742 _ = src_loc;
1743 _ = @panic("TODO: link/Coff lowerAnonDecl");
1749 const gpa = self.base.allocator;
1750 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();
1754 const val = decl_val.toValue();
1755 const tv = TypedValue{ .ty = ty, .val = val };
1756 const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)});
1757 defer gpa.free(name);
1758 const res = self.lowerConst(name, tv, self.rdata_section_index.?, src_loc) catch |err| switch (err) {
1759 else => {
1760 // TODO improve error message
1761 const em = try Module.ErrorMsg.create(gpa, src_loc, "lowerAnonDecl failed with error: {s}", .{
1762 @errorName(err),
1763 });
1764 return .{ .fail = em };
1765 },
1766 };
1767 const atom_index = switch (res) {
1768 .ok => |atom_index| atom_index,
1769 .fail => |em| return .{ .fail = em },
1770 };
1771 gop.value_ptr.* = atom_index;
1772 }
1773 return .ok;
17441774}
17451775
17461776pub fn getAnonDeclVAddr(self: *Coff, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {
1747 _ = self;
1748 _ = decl_val;
1749 _ = reloc_info;
1750 _ = @panic("TODO: link/Coff getAnonDeclVAddr");
1777 assert(self.llvm_object == null);
1778
1779 const this_atom_index = self.anon_decls.get(decl_val).?;
1780 const sym_index = self.getAtom(this_atom_index).getSymbolIndex().?;
1781 const atom_index = self.getAtomIndexForSymbol(.{ .sym_index = reloc_info.parent_atom_index, .file = null }).?;
1782 const target = SymbolWithLoc{ .sym_index = sym_index, .file = null };
1783 try Atom.addRelocation(self, atom_index, .{
1784 .type = .direct,
1785 .target = target,
1786 .offset = @as(u32, @intCast(reloc_info.offset)),
1787 .addend = reloc_info.addend,
1788 .pcrel = false,
1789 .length = 3,
1790 });
1791 try Atom.addBaseRelocation(self, atom_index, @as(u32, @intCast(reloc_info.offset)));
1792
1793 return 0;
17511794}
17521795
17531796pub fn getGlobalSymbol(self: *Coff, name: []const u8, lib_name_name: ?[]const u8) !u32 {