macho: implement lowering anon decls
This commit is contained in:
committed by
Andrew Kelley
parent
0134e5d2a1
commit
57eefe0533
@@ -109,6 +109,7 @@ atom_by_index_table: std.AutoHashMapUnmanaged(u32, Atom.Index) = .{},
|
||||
/// value assigned to label `foo` is an unnamed constant belonging/associated
|
||||
/// with `Decl` `main`, and lives as long as that `Decl`.
|
||||
unnamed_const_atoms: UnnamedConstTable = .{},
|
||||
anon_decls: AnonDeclTable = .{},
|
||||
|
||||
/// A table of relocations indexed by the owning them `Atom`.
|
||||
/// Note that once we refactor `Atom`'s lifetime and ownership rules,
|
||||
@@ -1899,6 +1900,7 @@ pub fn deinit(self: *MachO) void {
|
||||
atoms.deinit(gpa);
|
||||
}
|
||||
self.unnamed_const_atoms.deinit(gpa);
|
||||
self.anon_decls.deinit(gpa);
|
||||
|
||||
self.atom_by_index_table.deinit(gpa);
|
||||
|
||||
@@ -2172,39 +2174,19 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: InternPool.Index, air:
|
||||
|
||||
pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Module.Decl.Index) !u32 {
|
||||
const gpa = self.base.allocator;
|
||||
|
||||
var code_buffer = std.ArrayList(u8).init(gpa);
|
||||
defer code_buffer.deinit();
|
||||
|
||||
const mod = self.base.options.module.?;
|
||||
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 decl = mod.declPtr(decl_index);
|
||||
const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
|
||||
|
||||
const name_str_index = blk: {
|
||||
const index = unnamed_consts.items.len;
|
||||
const name = try std.fmt.allocPrint(gpa, "___unnamed_{s}_{d}", .{ decl_name, index });
|
||||
defer gpa.free(name);
|
||||
break :blk try self.strtab.insert(gpa, name);
|
||||
};
|
||||
const name = self.strtab.get(name_str_index).?;
|
||||
|
||||
log.debug("allocating symbol indexes for {s}", .{name});
|
||||
|
||||
const sym_index = try self.allocateSymbol();
|
||||
const atom_index = try self.createAtom(sym_index, .{});
|
||||
try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom_index);
|
||||
|
||||
const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), typed_value, &code_buffer, .none, .{
|
||||
.parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?,
|
||||
});
|
||||
var code = switch (res) {
|
||||
.ok => code_buffer.items,
|
||||
const index = unnamed_consts.items.len;
|
||||
const name = try std.fmt.allocPrint(gpa, "___unnamed_{s}_{d}", .{ decl_name, index });
|
||||
defer gpa.free(name);
|
||||
const atom_index = switch (try self.lowerConst(name, typed_value, self.data_const_section_index.?, decl.srcLoc(mod))) {
|
||||
.ok => |atom_index| atom_index,
|
||||
.fail => |em| {
|
||||
decl.analysis = .codegen_failure;
|
||||
try mod.failed_decls.put(mod.gpa, decl_index, em);
|
||||
@@ -2212,28 +2194,63 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu
|
||||
return error.CodegenFail;
|
||||
},
|
||||
};
|
||||
try unnamed_consts.append(gpa, atom_index);
|
||||
const atom = self.getAtomPtr(atom_index);
|
||||
return atom.getSymbolIndex().?;
|
||||
}
|
||||
|
||||
const required_alignment = typed_value.ty.abiAlignment(mod);
|
||||
const LowerConstResult = union(enum) {
|
||||
ok: Atom.Index,
|
||||
fail: *Module.ErrorMsg,
|
||||
};
|
||||
|
||||
fn lowerConst(
|
||||
self: *MachO,
|
||||
name: []const u8,
|
||||
tv: TypedValue,
|
||||
sect_id: u8,
|
||||
src_loc: Module.SrcLoc,
|
||||
) !LowerConstResult {
|
||||
const gpa = self.base.allocator;
|
||||
|
||||
var code_buffer = std.ArrayList(u8).init(gpa);
|
||||
defer code_buffer.deinit();
|
||||
|
||||
const mod = self.base.options.module.?;
|
||||
|
||||
log.debug("allocating symbol indexes for {s}", .{name});
|
||||
|
||||
const sym_index = try self.allocateSymbol();
|
||||
const atom_index = try self.createAtom(sym_index, .{});
|
||||
try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom_index);
|
||||
|
||||
const res = try codegen.generateSymbol(&self.base, src_loc, tv, &code_buffer, .none, .{
|
||||
.parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?,
|
||||
});
|
||||
var code = switch (res) {
|
||||
.ok => code_buffer.items,
|
||||
.fail => |em| return .{ .fail = em },
|
||||
};
|
||||
|
||||
const required_alignment = tv.ty.abiAlignment(mod);
|
||||
const atom = self.getAtomPtr(atom_index);
|
||||
atom.size = code.len;
|
||||
// TODO: work out logic for disambiguating functions from function pointers
|
||||
// const sect_id = self.getDeclOutputSection(decl_index);
|
||||
const sect_id = self.data_const_section_index.?;
|
||||
const symbol = atom.getSymbolPtr(self);
|
||||
const name_str_index = try self.strtab.insert(gpa, name);
|
||||
symbol.n_strx = name_str_index;
|
||||
symbol.n_type = macho.N_SECT;
|
||||
symbol.n_sect = sect_id + 1;
|
||||
symbol.n_value = try self.allocateAtom(atom_index, code.len, required_alignment);
|
||||
errdefer self.freeAtom(atom_index);
|
||||
|
||||
try unnamed_consts.append(gpa, atom_index);
|
||||
|
||||
log.debug("allocated atom for {s} at 0x{x}", .{ name, symbol.n_value });
|
||||
log.debug(" (required alignment 0x{x})", .{required_alignment});
|
||||
|
||||
try self.writeAtom(atom_index, code);
|
||||
|
||||
return atom.getSymbolIndex().?;
|
||||
return .{ .ok = atom_index };
|
||||
}
|
||||
|
||||
pub fn updateDecl(self: *MachO, mod: *Module, decl_index: Module.Decl.Index) !void {
|
||||
@@ -2850,17 +2867,50 @@ pub fn lowerAnonDecl(self: *MachO, decl_val: InternPool.Index, src_loc: Module.S
|
||||
// be used by more than one function, however, its address is being used so we need
|
||||
// to put it in some location.
|
||||
// ...
|
||||
_ = self;
|
||||
_ = decl_val;
|
||||
_ = src_loc;
|
||||
_ = @panic("TODO: link/MachO lowerAnonDecl");
|
||||
const gpa = self.base.allocator;
|
||||
const gop = try self.anon_decls.getOrPut(gpa, decl_val);
|
||||
if (!gop.found_existing) {
|
||||
const mod = self.base.options.module.?;
|
||||
const ty = mod.intern_pool.typeOf(decl_val).toType();
|
||||
const val = decl_val.toValue();
|
||||
const tv = TypedValue{ .ty = ty, .val = val };
|
||||
const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)});
|
||||
defer gpa.free(name);
|
||||
const res = self.lowerConst(name, tv, self.data_const_section_index.?, src_loc) catch |err| switch (err) {
|
||||
else => {
|
||||
// TODO improve error message
|
||||
const em = try Module.ErrorMsg.create(gpa, src_loc, "lowerAnonDecl failed with error: {s}", .{
|
||||
@errorName(err),
|
||||
});
|
||||
return .{ .fail = em };
|
||||
},
|
||||
};
|
||||
const atom_index = switch (res) {
|
||||
.ok => |atom_index| atom_index,
|
||||
.fail => |em| return .{ .fail = em },
|
||||
};
|
||||
gop.value_ptr.* = atom_index;
|
||||
}
|
||||
return .ok;
|
||||
}
|
||||
|
||||
pub fn getAnonDeclVAddr(self: *MachO, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {
|
||||
_ = self;
|
||||
_ = decl_val;
|
||||
_ = reloc_info;
|
||||
_ = @panic("TODO: link/MachO getAnonDeclVAddr");
|
||||
assert(self.llvm_object == null);
|
||||
|
||||
const this_atom_index = self.anon_decls.get(decl_val).?;
|
||||
const sym_index = self.getAtom(this_atom_index).getSymbolIndex().?;
|
||||
const atom_index = self.getAtomIndexForSymbol(.{ .sym_index = reloc_info.parent_atom_index }).?;
|
||||
try Atom.addRelocation(self, atom_index, .{
|
||||
.type = .unsigned,
|
||||
.target = .{ .sym_index = sym_index },
|
||||
.offset = @as(u32, @intCast(reloc_info.offset)),
|
||||
.addend = reloc_info.addend,
|
||||
.pcrel = false,
|
||||
.length = 3,
|
||||
});
|
||||
try Atom.addRebase(self, atom_index, @as(u32, @intCast(reloc_info.offset)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn populateMissingMetadata(self: *MachO) !void {
|
||||
@@ -5412,6 +5462,7 @@ const DeclMetadata = struct {
|
||||
}
|
||||
};
|
||||
|
||||
const AnonDeclTable = std.AutoHashMapUnmanaged(InternPool.Index, Atom.Index);
|
||||
const BindingTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Atom.Binding));
|
||||
const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index));
|
||||
const RebaseTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32));
|
||||
|
||||
Reference in New Issue
Block a user