stage2: restructure LLVM backend

The LLVM backend is now structured into 3 different structs, namely
Object, DeclGen and FuncGen. Object represents an object that is
generated by the LLVM backend. DeclGen is responsible for generating
a decl and FuncGen is responsible for generating llvm instructions
from tzir in a function.
This commit is contained in:
Timon Kruiper 2021-03-08 00:09:03 +01:00 committed by Andrew Kelley
parent 56677f2f2d
commit a710368054
3 changed files with 408 additions and 377 deletions

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,7 @@ pub const base_tag: link.File.Tag = .coff;
const msdos_stub = @embedFile("msdos-stub.bin");
/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
llvm_ir_module: ?*llvm_backend.LLVMIRModule = null,
llvm_object: ?*llvm_backend.Object = null,
base: link.File,
ptr_width: PtrWidth,
@ -129,7 +129,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
const self = try createEmpty(allocator, options);
errdefer self.base.destroy();
self.llvm_ir_module = try llvm_backend.LLVMIRModule.create(allocator, sub_path, options);
self.llvm_object = try llvm_backend.Object.create(allocator, sub_path, options);
return self;
}
@ -413,7 +413,7 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Coff {
}
pub fn allocateDeclIndexes(self: *Coff, decl: *Module.Decl) !void {
if (self.llvm_ir_module) |_| return;
if (self.llvm_object) |_| return;
try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1);
@ -660,7 +660,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
defer tracy.end();
if (build_options.have_llvm)
if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.updateDecl(module, decl);
if (self.llvm_object) |llvm_object| return try llvm_object.updateDecl(module, decl);
const typed_value = decl.typed_value.most_recent.typed_value;
if (typed_value.val.tag() == .extern_fn) {
@ -720,7 +720,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
}
pub fn freeDecl(self: *Coff, decl: *Module.Decl) void {
if (self.llvm_ir_module) |_| return;
if (self.llvm_object) |_| return;
// Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
self.freeTextBlock(&decl.link.coff);
@ -728,7 +728,7 @@ pub fn freeDecl(self: *Coff, decl: *Module.Decl) void {
}
pub fn updateDeclExports(self: *Coff, module: *Module, decl: *Module.Decl, exports: []const *Module.Export) !void {
if (self.llvm_ir_module) |_| return;
if (self.llvm_object) |_| return;
for (exports) |exp| {
if (exp.options.section) |section_name| {
@ -771,7 +771,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void {
defer tracy.end();
if (build_options.have_llvm)
if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.flushModule(comp);
if (self.llvm_object) |llvm_object| return try llvm_object.flushModule(comp);
if (self.text_section_size_dirty) {
// Write the new raw size in the .text header
@ -1308,7 +1308,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
}
pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl) u64 {
assert(self.llvm_ir_module == null);
assert(self.llvm_object == null);
return self.text_section_virtual_address + decl.link.coff.text_offset;
}
@ -1318,7 +1318,7 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !v
pub fn deinit(self: *Coff) void {
if (build_options.have_llvm)
if (self.llvm_ir_module) |ir_module| ir_module.deinit(self.base.allocator);
if (self.llvm_object) |ir_module| ir_module.deinit(self.base.allocator);
self.text_block_free_list.deinit(self.base.allocator);
self.offset_table.deinit(self.base.allocator);

View File

@ -35,7 +35,7 @@ base: File,
ptr_width: PtrWidth,
/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
llvm_ir_module: ?*llvm_backend.LLVMIRModule = null,
llvm_object: ?*llvm_backend.Object = null,
/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
/// Same order as in the file.
@ -232,7 +232,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
const self = try createEmpty(allocator, options);
errdefer self.base.destroy();
self.llvm_ir_module = try llvm_backend.LLVMIRModule.create(allocator, sub_path, options);
self.llvm_object = try llvm_backend.Object.create(allocator, sub_path, options);
return self;
}
@ -299,7 +299,7 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Elf {
pub fn deinit(self: *Elf) void {
if (build_options.have_llvm)
if (self.llvm_ir_module) |ir_module|
if (self.llvm_object) |ir_module|
ir_module.deinit(self.base.allocator);
self.sections.deinit(self.base.allocator);
@ -318,7 +318,7 @@ pub fn deinit(self: *Elf) void {
}
pub fn getDeclVAddr(self: *Elf, decl: *const Module.Decl) u64 {
assert(self.llvm_ir_module == null);
assert(self.llvm_object == null);
assert(decl.link.elf.local_sym_index != 0);
return self.local_symbols.items[decl.link.elf.local_sym_index].st_value;
}
@ -438,7 +438,7 @@ fn updateString(self: *Elf, old_str_off: u32, new_name: []const u8) !u32 {
}
pub fn populateMissingMetadata(self: *Elf) !void {
assert(self.llvm_ir_module == null);
assert(self.llvm_object == null);
const small_ptr = switch (self.ptr_width) {
.p32 => true,
@ -745,7 +745,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
defer tracy.end();
if (build_options.have_llvm)
if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.flushModule(comp);
if (self.llvm_object) |llvm_object| return try llvm_object.flushModule(comp);
// TODO This linker code currently assumes there is only 1 compilation unit and it corresponds to the
// Zig source code.
@ -2111,7 +2111,7 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al
}
pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void {
if (self.llvm_ir_module) |_| return;
if (self.llvm_object) |_| return;
if (decl.link.elf.local_sym_index != 0) return;
@ -2149,7 +2149,7 @@ pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void {
}
pub fn freeDecl(self: *Elf, decl: *Module.Decl) void {
if (self.llvm_ir_module) |_| return;
if (self.llvm_object) |_| return;
// Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
self.freeTextBlock(&decl.link.elf);
@ -2189,7 +2189,7 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
defer tracy.end();
if (build_options.have_llvm)
if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.updateDecl(module, decl);
if (self.llvm_object) |llvm_object| return try llvm_object.updateDecl(module, decl);
const typed_value = decl.typed_value.most_recent.typed_value;
if (typed_value.val.tag() == .extern_fn) {
@ -2673,7 +2673,7 @@ pub fn updateDeclExports(
decl: *Module.Decl,
exports: []const *Module.Export,
) !void {
if (self.llvm_ir_module) |_| return;
if (self.llvm_object) |_| return;
const tracy = trace(@src());
defer tracy.end();
@ -2748,7 +2748,7 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec
const tracy = trace(@src());
defer tracy.end();
if (self.llvm_ir_module) |_| return;
if (self.llvm_object) |_| return;
const tree = decl.container.file_scope.tree;
const node_tags = tree.nodes.items(.tag);
@ -2773,7 +2773,7 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec
}
pub fn deleteExport(self: *Elf, exp: Export) void {
if (self.llvm_ir_module) |_| return;
if (self.llvm_object) |_| return;
const sym_index = exp.sym_index orelse return;
self.global_symbol_free_list.append(self.base.allocator, sym_index) catch {};