Commit 2fc18b5278
Changed files (3)
src-self-hosted
src-self-hosted/codegen.zig
@@ -145,10 +145,10 @@ pub fn generateSymbol(
if (typed_value.val.cast(Value.Payload.DeclRef)) |payload| {
const decl = payload.decl;
if (decl.analysis != .complete) return error.AnalysisFail;
- assert(decl.link.local_sym_index != 0);
+ assert(decl.link.elf.local_sym_index != 0);
// TODO handle the dependency of this symbol on the decl's vaddr.
// If the decl changes vaddr, then this symbol needs to get regenerated.
- const vaddr = bin_file.local_symbols.items[decl.link.local_sym_index].st_value;
+ const vaddr = bin_file.local_symbols.items[decl.link.elf.local_sym_index].st_value;
const endian = bin_file.base.options.target.cpu.arch.endian();
switch (bin_file.base.options.target.cpu.arch.ptrBitWidth()) {
16 => {
@@ -1085,7 +1085,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
const got = &self.bin_file.program_headers.items[self.bin_file.phdr_got_index.?];
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
- const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.offset_table_index * ptr_bytes);
+ const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes);
// ff 14 25 xx xx xx xx call [addr]
try self.code.ensureCapacity(self.code.items.len + 7);
self.code.appendSliceAssumeCapacity(&[3]u8{ 0xff, 0x14, 0x25 });
@@ -1106,7 +1106,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
const got = &self.bin_file.program_headers.items[self.bin_file.phdr_got_index.?];
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
- const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.offset_table_index * ptr_bytes);
+ const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes);
try self.genSetReg(inst.base.src, .ra, .{ .memory = got_addr });
const jalr = instructions.Jalr{
@@ -1934,7 +1934,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
if (typed_value.val.cast(Value.Payload.DeclRef)) |payload| {
const got = &self.bin_file.program_headers.items[self.bin_file.phdr_got_index.?];
const decl = payload.decl;
- const got_addr = got.p_vaddr + decl.link.offset_table_index * ptr_bytes;
+ const got_addr = got.p_vaddr + decl.link.elf.offset_table_index * ptr_bytes;
return MCValue{ .memory = got_addr };
}
return self.fail(src, "TODO codegen more kinds of const pointers", .{});
src-self-hosted/link.zig
@@ -38,6 +38,16 @@ pub const Options = struct {
pub const File = struct {
+ pub const LinkBlock = union {
+ elf: Elf.TextBlock,
+ c: void,
+ };
+
+ pub const LinkFn = union {
+ elf: Elf.SrcFn,
+ c: void,
+ };
+
tag: Tag,
options: Options,
file: ?fs.File,
@@ -1720,31 +1730,31 @@ pub const File = struct {
}
pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void {
- if (decl.link.local_sym_index != 0) return;
+ if (decl.link.elf.local_sym_index != 0) return;
try self.local_symbols.ensureCapacity(self.base.allocator, self.local_symbols.items.len + 1);
try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1);
if (self.local_symbol_free_list.popOrNull()) |i| {
log.debug(.link, "reusing symbol index {} for {}\n", .{ i, decl.name });
- decl.link.local_sym_index = i;
+ decl.link.elf.local_sym_index = i;
} else {
log.debug(.link, "allocating symbol index {} for {}\n", .{ self.local_symbols.items.len, decl.name });
- decl.link.local_sym_index = @intCast(u32, self.local_symbols.items.len);
+ decl.link.elf.local_sym_index = @intCast(u32, self.local_symbols.items.len);
_ = self.local_symbols.addOneAssumeCapacity();
}
if (self.offset_table_free_list.popOrNull()) |i| {
- decl.link.offset_table_index = i;
+ decl.link.elf.offset_table_index = i;
} else {
- decl.link.offset_table_index = @intCast(u32, self.offset_table.items.len);
+ decl.link.elf.offset_table_index = @intCast(u32, self.offset_table.items.len);
_ = self.offset_table.addOneAssumeCapacity();
self.offset_table_count_dirty = true;
}
const phdr = &self.program_headers.items[self.phdr_load_re_index.?];
- self.local_symbols.items[decl.link.local_sym_index] = .{
+ self.local_symbols.items[decl.link.elf.local_sym_index] = .{
.st_name = 0,
.st_info = 0,
.st_other = 0,
@@ -1752,39 +1762,39 @@ pub const File = struct {
.st_value = phdr.p_vaddr,
.st_size = 0,
};
- self.offset_table.items[decl.link.offset_table_index] = 0;
+ self.offset_table.items[decl.link.elf.offset_table_index] = 0;
}
pub fn freeDecl(self: *Elf, decl: *Module.Decl) void {
// Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
- self.freeTextBlock(&decl.link);
- if (decl.link.local_sym_index != 0) {
- self.local_symbol_free_list.append(self.base.allocator, decl.link.local_sym_index) catch {};
- self.offset_table_free_list.append(self.base.allocator, decl.link.offset_table_index) catch {};
+ self.freeTextBlock(&decl.link.elf);
+ if (decl.link.elf.local_sym_index != 0) {
+ self.local_symbol_free_list.append(self.base.allocator, decl.link.elf.local_sym_index) catch {};
+ self.offset_table_free_list.append(self.base.allocator, decl.link.elf.offset_table_index) catch {};
- self.local_symbols.items[decl.link.local_sym_index].st_info = 0;
+ self.local_symbols.items[decl.link.elf.local_sym_index].st_info = 0;
- decl.link.local_sym_index = 0;
+ decl.link.elf.local_sym_index = 0;
}
// TODO make this logic match freeTextBlock. Maybe abstract the logic out since the same thing
// is desired for both.
- _ = self.dbg_line_fn_free_list.remove(&decl.fn_link);
- if (decl.fn_link.prev) |prev| {
+ _ = self.dbg_line_fn_free_list.remove(&decl.fn_link.elf);
+ if (decl.fn_link.elf.prev) |prev| {
_ = self.dbg_line_fn_free_list.put(self.base.allocator, prev, {}) catch {};
- prev.next = decl.fn_link.next;
- if (decl.fn_link.next) |next| {
+ prev.next = decl.fn_link.elf.next;
+ if (decl.fn_link.elf.next) |next| {
next.prev = prev;
} else {
self.dbg_line_fn_last = prev;
}
- } else if (decl.fn_link.next) |next| {
+ } else if (decl.fn_link.elf.next) |next| {
self.dbg_line_fn_first = next;
next.prev = null;
}
- if (self.dbg_line_fn_first == &decl.fn_link) {
+ if (self.dbg_line_fn_first == &decl.fn_link.elf) {
self.dbg_line_fn_first = null;
}
- if (self.dbg_line_fn_last == &decl.fn_link) {
+ if (self.dbg_line_fn_last == &decl.fn_link.elf) {
self.dbg_line_fn_last = null;
}
}
@@ -1870,24 +1880,24 @@ pub const File = struct {
const stt_bits: u8 = if (is_fn) elf.STT_FUNC else elf.STT_OBJECT;
- assert(decl.link.local_sym_index != 0); // Caller forgot to allocateDeclIndexes()
- const local_sym = &self.local_symbols.items[decl.link.local_sym_index];
+ assert(decl.link.elf.local_sym_index != 0); // Caller forgot to allocateDeclIndexes()
+ const local_sym = &self.local_symbols.items[decl.link.elf.local_sym_index];
if (local_sym.st_size != 0) {
- const capacity = decl.link.capacity(self.*);
+ const capacity = decl.link.elf.capacity(self.*);
const need_realloc = code.len > capacity or
!mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment);
if (need_realloc) {
- const vaddr = try self.growTextBlock(&decl.link, code.len, required_alignment);
+ const vaddr = try self.growTextBlock(&decl.link.elf, code.len, required_alignment);
log.debug(.link, "growing {} from 0x{x} to 0x{x}\n", .{ decl.name, local_sym.st_value, vaddr });
if (vaddr != local_sym.st_value) {
local_sym.st_value = vaddr;
log.debug(.link, " (writing new offset table entry)\n", .{});
- self.offset_table.items[decl.link.offset_table_index] = vaddr;
- try self.writeOffsetTableEntry(decl.link.offset_table_index);
+ self.offset_table.items[decl.link.elf.offset_table_index] = vaddr;
+ try self.writeOffsetTableEntry(decl.link.elf.offset_table_index);
}
} else if (code.len < local_sym.st_size) {
- self.shrinkTextBlock(&decl.link, code.len);
+ self.shrinkTextBlock(&decl.link.elf, code.len);
}
local_sym.st_size = code.len;
local_sym.st_name = try self.updateString(local_sym.st_name, mem.spanZ(decl.name));
@@ -1895,13 +1905,13 @@ pub const File = struct {
local_sym.st_other = 0;
local_sym.st_shndx = self.text_section_index.?;
// TODO this write could be avoided if no fields of the symbol were changed.
- try self.writeSymbol(decl.link.local_sym_index);
+ try self.writeSymbol(decl.link.elf.local_sym_index);
} else {
const decl_name = mem.spanZ(decl.name);
const name_str_index = try self.makeString(decl_name);
- const vaddr = try self.allocateTextBlock(&decl.link, code.len, required_alignment);
+ const vaddr = try self.allocateTextBlock(&decl.link.elf, code.len, required_alignment);
log.debug(.link, "allocated text block for {} at 0x{x}\n", .{ decl_name, vaddr });
- errdefer self.freeTextBlock(&decl.link);
+ errdefer self.freeTextBlock(&decl.link.elf);
local_sym.* = .{
.st_name = name_str_index,
@@ -1911,10 +1921,10 @@ pub const File = struct {
.st_value = vaddr,
.st_size = code.len,
};
- self.offset_table.items[decl.link.offset_table_index] = vaddr;
+ self.offset_table.items[decl.link.elf.offset_table_index] = vaddr;
- try self.writeSymbol(decl.link.local_sym_index);
- try self.writeOffsetTableEntry(decl.link.offset_table_index);
+ try self.writeSymbol(decl.link.elf.local_sym_index);
+ try self.writeOffsetTableEntry(decl.link.elf.offset_table_index);
}
const section_offset = local_sym.st_value - self.program_headers.items[self.phdr_load_re_index.?].p_vaddr;
@@ -1941,7 +1951,7 @@ pub const File = struct {
// Now we have the full contents and may allocate a region to store it.
const debug_line_sect = &self.sections.items[self.debug_line_section_index.?];
- const src_fn = &decl.fn_link;
+ const src_fn = &decl.fn_link.elf;
src_fn.len = @intCast(u32, dbg_line_buffer.items.len);
if (self.dbg_line_fn_last) |last| {
if (src_fn.next) |next| {
@@ -2026,8 +2036,8 @@ pub const File = struct {
try self.global_symbols.ensureCapacity(self.base.allocator, self.global_symbols.items.len + exports.len);
const typed_value = decl.typed_value.most_recent.typed_value;
- if (decl.link.local_sym_index == 0) return;
- const decl_sym = self.local_symbols.items[decl.link.local_sym_index];
+ if (decl.link.elf.local_sym_index == 0) return;
+ const decl_sym = self.local_symbols.items[decl.link.elf.local_sym_index];
for (exports) |exp| {
if (exp.options.section) |section_name| {
@@ -2105,7 +2115,7 @@ pub const File = struct {
const casted_line_off = @intCast(u28, line_delta);
const shdr = &self.sections.items[self.debug_line_section_index.?];
- const file_pos = shdr.sh_offset + decl.fn_link.off + self.getRelocDbgLineOff();
+ const file_pos = shdr.sh_offset + decl.fn_link.elf.off + self.getRelocDbgLineOff();
var data: [4]u8 = undefined;
leb128.writeUnsignedFixed(4, &data, casted_line_off);
try self.base.file.?.pwriteAll(&data, file_pos);
src-self-hosted/Module.zig
@@ -177,14 +177,14 @@ pub const Decl = struct {
/// Represents the position of the code in the output file.
/// This is populated regardless of semantic analysis and code generation.
- link: link.File.Elf.TextBlock = link.File.Elf.TextBlock.empty,
+ link: link.File.LinkBlock,
/// Represents the function in the linked output file, if the `Decl` is a function.
/// This is stored here and not in `Fn` because `Decl` survives across updates but
/// `Fn` does not.
/// TODO Look into making `Fn` a longer lived structure and moving this field there
/// to save on memory usage.
- fn_link: link.File.Elf.SrcFn = link.File.Elf.SrcFn.empty,
+ fn_link: link.File.LinkFn,
contents_hash: std.zig.SrcHash,
@@ -1538,10 +1538,13 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {
if (!srcHashEql(decl.contents_hash, contents_hash)) {
try self.markOutdatedDecl(decl);
decl.contents_hash = contents_hash;
- } else if (decl.fn_link.len != 0) {
- // TODO Look into detecting when this would be unnecessary by storing enough state
- // in `Decl` to notice that the line number did not change.
- self.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl });
+ } else switch (self.bin_file.tag) {
+ .elf => if (decl.fn_link.elf.len != 0) {
+ // TODO Look into detecting when this would be unnecessary by storing enough state
+ // in `Decl` to notice that the line number did not change.
+ self.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl });
+ },
+ .c => {},
}
}
} else {
@@ -1745,7 +1748,14 @@ fn allocateNewDecl(
.analysis = .unreferenced,
.deletion_flag = false,
.contents_hash = contents_hash,
- .link = link.File.Elf.TextBlock.empty,
+ .link = switch (self.bin_file.tag) {
+ .elf => .{ .elf = link.File.Elf.TextBlock.empty },
+ .c => .{ .c = {} },
+ },
+ .fn_link = switch (self.bin_file.tag) {
+ .elf => .{ .elf = link.File.Elf.SrcFn.empty },
+ .c => .{ .c = {} },
+ },
.generation = 0,
};
return new_decl;