| ... | @@ -82,6 +82,7 @@ atom_by_index_table: std.AutoHashMapUnmanaged(u32, Atom.Index) = .{}, | ... | @@ -82,6 +82,7 @@ atom_by_index_table: std.AutoHashMapUnmanaged(u32, Atom.Index) = .{}, |
| 82 | /// value assigned to label `foo` is an unnamed constant belonging/associated | 82 | /// value assigned to label `foo` is an unnamed constant belonging/associated |
| 83 | /// with `Decl` `main`, and lives as long as that `Decl`. | 83 | /// with `Decl` `main`, and lives as long as that `Decl`. |
| 84 | unnamed_const_atoms: UnnamedConstTable = .{}, | 84 | unnamed_const_atoms: UnnamedConstTable = .{}, |
| | 85 | anon_decls: AnonDeclTable = .{}, |
| 85 | | 86 | |
| 86 | /// A table of relocations indexed by the owning them `Atom`. | 87 | /// A table of relocations indexed by the owning them `Atom`. |
| 87 | /// Note that once we refactor `Atom`'s lifetime and ownership rules, | 88 | /// Note that once we refactor `Atom`'s lifetime and ownership rules, |
| ... | @@ -107,6 +108,7 @@ const HotUpdateState = struct { | ... | @@ -107,6 +108,7 @@ const HotUpdateState = struct { |
| 107 | loaded_base_address: ?std.os.windows.HMODULE = null, | 108 | loaded_base_address: ?std.os.windows.HMODULE = null, |
| 108 | }; | 109 | }; |
| 109 | | 110 | |
| | 111 | const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, Atom.Index); |
| 110 | const RelocTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Relocation)); | 112 | const RelocTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Relocation)); |
| 111 | const BaseRelocationTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32)); | 113 | const BaseRelocationTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32)); |
| 112 | const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index)); | 114 | const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index)); |
| ... | @@ -323,6 +325,7 @@ pub fn deinit(self: *Coff) void { | ... | @@ -323,6 +325,7 @@ pub fn deinit(self: *Coff) void { |
| 323 | atoms.deinit(gpa); | 325 | atoms.deinit(gpa); |
| 324 | } | 326 | } |
| 325 | self.unnamed_const_atoms.deinit(gpa); | 327 | self.unnamed_const_atoms.deinit(gpa); |
| | 328 | self.anon_decls.deinit(gpa); |
| 326 | | 329 | |
| 327 | for (self.relocs.values()) |*relocs| { | 330 | for (self.relocs.values()) |*relocs| { |
| 328 | relocs.deinit(gpa); | 331 | relocs.deinit(gpa); |
| ... | @@ -1077,45 +1080,53 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air: | ... | @@ -1077,45 +1080,53 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air: |
| 1077 | | 1080 | |
| 1078 | pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.Index) !u32 { | 1081 | pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.Index) !u32 { |
| 1079 | const gpa = self.base.allocator; | 1082 | const gpa = self.base.allocator; |
| 1080 | var code_buffer = std.ArrayList(u8).init(gpa); | | |
| 1081 | defer code_buffer.deinit(); | | |
| 1082 | | | |
| 1083 | const mod = self.base.options.module.?; | 1083 | const mod = self.base.options.module.?; |
| 1084 | const decl = mod.declPtr(decl_index); | 1084 | const decl = mod.declPtr(decl_index); |
| 1085 | | | |
| 1086 | const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index); | 1085 | const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index); |
| 1087 | if (!gop.found_existing) { | 1086 | if (!gop.found_existing) { |
| 1088 | gop.value_ptr.* = .{}; | 1087 | gop.value_ptr.* = .{}; |
| 1089 | } | 1088 | } |
| 1090 | const unnamed_consts = gop.value_ptr; | 1089 | 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 | } |
| 1091 | | 1106 | |
| 1092 | const atom_index = try self.createAtom(); | 1107 | const LowerConstResult = union(enum) { |
| | 1108 | ok: Atom.Index, |
| | 1109 | fail: *Module.ErrorMsg, |
| | 1110 | }; |
| 1093 | | 1111 | |
| 1094 | const sym_name = blk: { | 1112 | fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult { |
| 1095 | const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); | 1113 | const gpa = self.base.allocator; |
| 1096 | | 1114 | |
| 1097 | const index = unnamed_consts.items.len; | 1115 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 1098 | break :blk try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); | 1116 | defer code_buffer.deinit(); |
| 1099 | }; | 1117 | |
| 1100 | defer gpa.free(sym_name); | 1118 | const mod = self.base.options.module.?; |
| 1101 | { | 1119 | const atom_index = try self.createAtom(); |
| 1102 | const atom = self.getAtom(atom_index); | 1120 | const sym = self.getAtom(atom_index).getSymbolPtr(self); |
| 1103 | const sym = atom.getSymbolPtr(self); | 1121 | try self.setSymbolName(sym, name); |
| 1104 | try self.setSymbolName(sym, sym_name); | 1122 | sym.section_number = @as(coff.SectionNumber, @enumFromInt(sect_id + 1)); |
| 1105 | sym.section_number = @as(coff.SectionNumber, @enumFromInt(self.rdata_section_index.? + 1)); | | |
| 1106 | } | | |
| 1107 | | 1123 | |
| 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, .{ |
| 1109 | .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?, | 1125 | .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?, |
| 1110 | }); | 1126 | }); |
| 1111 | var code = switch (res) { | 1127 | var code = switch (res) { |
| 1112 | .ok => code_buffer.items, | 1128 | .ok => code_buffer.items, |
| 1113 | .fail => |em| { | 1129 | .fail => |em| return .{ .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 | }, | | |
| 1119 | }; | 1130 | }; |
| 1120 | | 1131 | |
| 1121 | const required_alignment: u32 = @intCast(tv.ty.abiAlignment(mod).toByteUnits(0)); | 1132 | 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 | ... | @@ -1124,14 +1135,12 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In |
| 1124 | atom.getSymbolPtr(self).value = try self.allocateAtom(atom_index, atom.size, required_alignment); | 1135 | atom.getSymbolPtr(self).value = try self.allocateAtom(atom_index, atom.size, required_alignment); |
| 1125 | errdefer self.freeAtom(atom_index); | 1136 | errdefer self.freeAtom(atom_index); |
| 1126 | | 1137 | |
| 1127 | try unnamed_consts.append(gpa, atom_index); | 1138 | log.debug("allocated atom for {s} at 0x{x}", .{ name, atom.getSymbol(self).value }); |
| 1128 | | | |
| 1129 | log.debug("allocated atom for {s} at 0x{x}", .{ sym_name, atom.getSymbol(self).value }); | | |
| 1130 | log.debug(" (required alignment 0x{x})", .{required_alignment}); | 1139 | log.debug(" (required alignment 0x{x})", .{required_alignment}); |
| 1131 | | 1140 | |
| 1132 | try self.writeAtom(atom_index, code); | 1141 | try self.writeAtom(atom_index, code); |
| 1133 | | 1142 | |
| 1134 | return atom.getSymbolIndex().?; | 1143 | return .{ .ok = atom_index }; |
| 1135 | } | 1144 | } |
| 1136 | | 1145 | |
| 1137 | pub fn updateDecl( | 1146 | pub fn updateDecl( |
| ... | @@ -1737,17 +1746,51 @@ pub fn lowerAnonDecl(self: *Coff, decl_val: InternPool.Index, src_loc: Module.Sr | ... | @@ -1737,17 +1746,51 @@ pub fn lowerAnonDecl(self: *Coff, decl_val: InternPool.Index, src_loc: Module.Sr |
| 1737 | // be used by more than one function, however, its address is being used so we need | 1746 | // be used by more than one function, however, its address is being used so we need |
| 1738 | // to put it in some location. | 1747 | // to put it in some location. |
| 1739 | // ... | 1748 | // ... |
| 1740 | _ = self; | 1749 | const gpa = self.base.allocator; |
| 1741 | _ = decl_val; | 1750 | const gop = try self.anon_decls.getOrPut(gpa, decl_val); |
| 1742 | _ = src_loc; | 1751 | if (!gop.found_existing) { |
| 1743 | _ = @panic("TODO: link/Coff lowerAnonDecl"); | 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; |
| 1744 | } | 1774 | } |
| 1745 | | 1775 | |
| 1746 | pub fn getAnonDeclVAddr(self: *Coff, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { | 1776 | pub fn getAnonDeclVAddr(self: *Coff, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 { |
| 1747 | _ = self; | 1777 | assert(self.llvm_object == null); |
| 1748 | _ = decl_val; | 1778 | |
| 1749 | _ = reloc_info; | 1779 | const this_atom_index = self.anon_decls.get(decl_val).?; |
| 1750 | _ = @panic("TODO: link/Coff getAnonDeclVAddr"); | 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; |
| 1751 | } | 1794 | } |
| 1752 | | 1795 | |
| 1753 | pub fn getGlobalSymbol(self: *Coff, name: []const u8, lib_name_name: ?[]const u8) !u32 { | 1796 | pub fn getGlobalSymbol(self: *Coff, name: []const u8, lib_name_name: ?[]const u8) !u32 { |