diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-09-01 16:01:40 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2022-09-07 22:42:56 +0200 |
| commit | 49b1716064cb87b5e8ca13dcb1c9e4fc701737bc (patch) | |
| tree | 63bb6c18bfde9f04552fb22a5fa24c095cc0fe58 /src | |
| parent | a19e6adbf90771890ecdbb52d6dafab1943e4cc4 (diff) | |
| download | zig-49b1716064cb87b5e8ca13dcb1c9e4fc701737bc.tar.gz zig-49b1716064cb87b5e8ca13dcb1c9e4fc701737bc.zip | |
coff: implement lowering unnamed consts
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 2 | ||||
| -rw-r--r-- | src/link/Coff.zig | 110 |
2 files changed, 103 insertions, 9 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 5e404d00bd..1805fe7697 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -6959,7 +6959,7 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue { } else if (self.bin_file.cast(link.File.MachO)) |_| { return MCValue{ .direct_load = local_sym_index }; } else if (self.bin_file.cast(link.File.Coff)) |_| { - return self.fail("TODO lower unnamed const in COFF", .{}); + return MCValue{ .direct_load = local_sym_index }; } else if (self.bin_file.cast(link.File.Plan9)) |_| { return self.fail("TODO lower unnamed const in Plan9", .{}); } else { diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 9f3ccc069c..05ccfb7710 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -862,6 +862,11 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void { fn freeAtom(self: *Coff, atom: *Atom) void { log.debug("freeAtom {*}", .{atom}); + // TODO hashmap + for (self.managed_atoms.items) |owned| { + if (owned == atom) break; + } else atom.deinit(self.base.allocator); + const sym = atom.getSymbol(self); const sect_id = @enumToInt(sym.section_number) - 1; const free_list = &self.sections.items(.free_list)[sect_id]; @@ -955,10 +960,67 @@ pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, live } pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.Index) !u32 { - _ = self; - _ = tv; - _ = decl_index; - @panic("TODO lowerUnnamedConst"); + const gpa = self.base.allocator; + var code_buffer = std.ArrayList(u8).init(gpa); + defer code_buffer.deinit(); + + const mod = self.base.options.module.?; + const decl = mod.declPtr(decl_index); + + const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index); + if (!gop.found_existing) { + gop.value_ptr.* = .{}; + } + const unnamed_consts = gop.value_ptr; + + const atom = try gpa.create(Atom); + errdefer gpa.destroy(atom); + atom.* = Atom.empty; + + atom.sym_index = try self.allocateSymbol(); + const sym = atom.getSymbolPtr(self); + const sym_name = blk: { + const decl_name = try decl.getFullyQualifiedName(mod); + defer gpa.free(decl_name); + + const index = unnamed_consts.items.len; + break :blk try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); + }; + defer gpa.free(sym_name); + try self.setSymbolName(sym, sym_name); + sym.section_number = @intToEnum(coff.SectionNumber, self.rdata_section_index.?); + + try self.managed_atoms.append(gpa, atom); + try self.atom_by_index_table.putNoClobber(gpa, atom.sym_index, atom); + + const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), tv, &code_buffer, .none, .{ + .parent_atom_index = atom.sym_index, + }); + const code = switch (res) { + .externally_managed => |x| x, + .appended => code_buffer.items, + .fail => |em| { + decl.analysis = .codegen_failure; + try mod.failed_decls.put(mod.gpa, decl_index, em); + log.err("{s}", .{em.msg}); + return error.AnalysisFail; + }, + }; + + const required_alignment = tv.ty.abiAlignment(self.base.options.target); + atom.alignment = required_alignment; + atom.size = @intCast(u32, code.len); + sym.value = try self.allocateAtom(atom, atom.size, atom.alignment); + errdefer self.freeAtom(atom); + + try unnamed_consts.append(gpa, atom); + + log.debug("allocated atom for {s} at 0x{x}", .{ sym_name, sym.value }); + log.debug(" (required alignment 0x{x})", .{required_alignment}); + + try self.writeAtom(atom, code); + + return atom.sym_index; } pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) !void { @@ -1097,6 +1159,20 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8, try self.writeAtom(atom, code); } +fn freeUnnamedConsts(self: *Coff, decl_index: Module.Decl.Index) void { + const gpa = self.base.allocator; + const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; + for (unnamed_consts.items) |atom| { + self.freeAtom(atom); + self.locals_free_list.append(gpa, atom.sym_index) catch {}; + self.locals.items[atom.sym_index].section_number = .UNDEFINED; + _ = self.atom_by_index_table.remove(atom.sym_index); + log.debug(" adding local symbol index {d} to free list", .{atom.sym_index}); + atom.sym_index = 0; + } + unnamed_consts.clearAndFree(gpa); +} + pub fn freeDecl(self: *Coff, decl_index: Module.Decl.Index) void { if (build_options.have_llvm) { if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); @@ -1110,6 +1186,7 @@ pub fn freeDecl(self: *Coff, decl_index: Module.Decl.Index) void { const kv = self.decls.fetchRemove(decl_index); if (kv.?.value) |_| { self.freeAtom(&decl.link.coff); + self.freeUnnamedConsts(decl_index); } // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. @@ -1372,10 +1449,27 @@ pub fn getDeclVAddr( decl_index: Module.Decl.Index, reloc_info: link.File.RelocInfo, ) !u64 { - _ = self; - _ = decl_index; - _ = reloc_info; - @panic("TODO getDeclVAddr"); + const mod = self.base.options.module.?; + const decl = mod.declPtr(decl_index); + + assert(self.llvm_object == null); + assert(decl.link.coff.sym_index != 0); + + const atom = self.atom_by_index_table.get(reloc_info.parent_atom_index).?; + const target = SymbolWithLoc{ .sym_index = decl.link.coff.sym_index, .file = null }; + const target_sym = self.getSymbol(target); + try atom.addRelocation(self, .{ + .@"type" = .direct, + .target = target, + .offset = @intCast(u32, reloc_info.offset), + .addend = reloc_info.addend, + .pcrel = false, + .length = 3, + .prev_vaddr = target_sym.value, + }); + try atom.addBaseRelocation(self, @intCast(u32, reloc_info.offset)); + + return 0; } pub fn getGlobalSymbol(self: *Coff, name: []const u8) !u32 { |
