| ... | ... | @@ -82,6 +82,7 @@ atom_by_index_table: std.AutoHashMapUnmanaged(u32, Atom.Index) = .{}, |
| 82 | 82 | /// value assigned to label `foo` is an unnamed constant belonging/associated |
| 83 | 83 | /// with `Decl` `main`, and lives as long as that `Decl`. |
| 84 | 84 | unnamed_const_atoms: UnnamedConstTable = .{}, |
| 85 | anon_decls: AnonDeclTable = .{}, |
| 85 | 86 | |
| 86 | 87 | /// A table of relocations indexed by the owning them `Atom`. |
| 87 | 88 | /// Note that once we refactor `Atom`'s lifetime and ownership rules, |
| ... | ... | @@ -107,6 +108,7 @@ const HotUpdateState = struct { |
| 107 | 108 | loaded_base_address: ?std.os.windows.HMODULE = null, |
| 108 | 109 | }; |
| 109 | 110 | |
| 111 | const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, Atom.Index); |
| 110 | 112 | const RelocTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Relocation)); |
| 111 | 113 | const BaseRelocationTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32)); |
| 112 | 114 | const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index)); |
| ... | ... | @@ -323,6 +325,7 @@ pub fn deinit(self: *Coff) void { |
| 323 | 325 | atoms.deinit(gpa); |
| 324 | 326 | } |
| 325 | 327 | self.unnamed_const_atoms.deinit(gpa); |
| 328 | self.anon_decls.deinit(gpa); |
| 326 | 329 | |
| 327 | 330 | for (self.relocs.values()) |*relocs| { |
| 328 | 331 | relocs.deinit(gpa); |
| ... | ... | @@ -1077,45 +1080,53 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air: |
| 1077 | 1080 | |
| 1078 | 1081 | pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.Index) !u32 { |
| 1079 | 1082 | const gpa = self.base.allocator; |
| 1080 | | var code_buffer = std.ArrayList(u8).init(gpa); |
| 1081 | | defer code_buffer.deinit(); |
| 1082 | | |
| 1083 | 1083 | const mod = self.base.options.module.?; |
| 1084 | 1084 | const decl = mod.declPtr(decl_index); |
| 1085 | | |
| 1086 | 1085 | const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index); |
| 1087 | 1086 | if (!gop.found_existing) { |
| 1088 | 1087 | gop.value_ptr.* = .{}; |
| 1089 | 1088 | } |
| 1090 | 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: { |
| 1095 | | const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod)); |
| 1112 | fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult { |
| 1113 | const gpa = self.base.allocator; |
| 1096 | 1114 | |
| 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)); |
| 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 | 1125 | .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?, |
| 1110 | 1126 | }); |
| 1111 | 1127 | var code = switch (res) { |
| 1112 | 1128 | .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 }, |
| 1119 | 1130 | }; |
| 1120 | 1131 | |
| 1121 | 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 | 1135 | atom.getSymbolPtr(self).value = try self.allocateAtom(atom_index, atom.size, required_alignment); |
| 1125 | 1136 | errdefer self.freeAtom(atom_index); |
| 1126 | 1137 | |
| 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 }); |
| 1130 | 1139 | log.debug(" (required alignment 0x{x})", .{required_alignment}); |
| 1131 | 1140 | |
| 1132 | 1141 | try self.writeAtom(atom_index, code); |
| 1133 | 1142 | |
| 1134 | | return atom.getSymbolIndex().?; |
| 1143 | return .{ .ok = atom_index }; |
| 1135 | 1144 | } |
| 1136 | 1145 | |
| 1137 | 1146 | pub fn updateDecl( |
| ... | ... | @@ -1737,17 +1746,51 @@ pub fn lowerAnonDecl(self: *Coff, decl_val: InternPool.Index, src_loc: Module.Sr |
| 1737 | 1746 | // be used by more than one function, however, its address is being used so we need |
| 1738 | 1747 | // to put it in some location. |
| 1739 | 1748 | // ... |
| 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; |
| 1744 | 1774 | } |
| 1745 | 1775 | |
| 1746 | 1776 | pub 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; |
| 1751 | 1794 | } |
| 1752 | 1795 | |
| 1753 | 1796 | pub fn getGlobalSymbol(self: *Coff, name: []const u8, lib_name_name: ?[]const u8) !u32 { |