| ... | @@ -16,6 +16,7 @@ const link = @import("../link.zig"); | ... | @@ -16,6 +16,7 @@ const link = @import("../link.zig"); |
| 16 | const build_options = @import("build_options"); | 16 | const build_options = @import("build_options"); |
| 17 | const Cache = @import("../Cache.zig"); | 17 | const Cache = @import("../Cache.zig"); |
| 18 | const mingw = @import("../mingw.zig"); | 18 | const mingw = @import("../mingw.zig"); |
| | 19 | const llvm_backend = @import("../llvm_backend.zig"); |
| 19 | | 20 | |
| 20 | const allocation_padding = 4 / 3; | 21 | const allocation_padding = 4 / 3; |
| 21 | const minimum_text_block_size = 64 * allocation_padding; | 22 | const minimum_text_block_size = 64 * allocation_padding; |
| ... | @@ -32,6 +33,9 @@ pub const base_tag: link.File.Tag = .coff; | ... | @@ -32,6 +33,9 @@ pub const base_tag: link.File.Tag = .coff; |
| 32 | | 33 | |
| 33 | const msdos_stub = @embedFile("msdos-stub.bin"); | 34 | const msdos_stub = @embedFile("msdos-stub.bin"); |
| 34 | | 35 | |
| | 36 | /// If this is not null, an object file is created by LLVM and linked with LLD afterwards. |
| | 37 | llvm_ir_module: ?*llvm_backend.LLVMIRModule = null, |
| | 38 | |
| 35 | base: link.File, | 39 | base: link.File, |
| 36 | ptr_width: PtrWidth, | 40 | ptr_width: PtrWidth, |
| 37 | error_flags: link.File.ErrorFlags = .{}, | 41 | error_flags: link.File.ErrorFlags = .{}, |
| ... | @@ -121,8 +125,13 @@ pub const SrcFn = void; | ... | @@ -121,8 +125,13 @@ pub const SrcFn = void; |
| 121 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Coff { | 125 | pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Coff { |
| 122 | assert(options.object_format == .coff); | 126 | assert(options.object_format == .coff); |
| 123 | | 127 | |
| 124 | if (options.use_llvm) return error.LLVM_BackendIsTODO_ForCoff; // TODO | 128 | if (options.use_llvm) { |
| 125 | if (options.use_lld) return error.LLD_LinkingIsTODO_ForCoff; // TODO | 129 | const self = try createEmpty(allocator, options); |
| | 130 | errdefer self.base.destroy(); |
| | 131 | |
| | 132 | self.llvm_ir_module = try llvm_backend.LLVMIRModule.create(allocator, sub_path, options); |
| | 133 | return self; |
| | 134 | } |
| 126 | | 135 | |
| 127 | const file = try options.emit.?.directory.handle.createFile(sub_path, .{ | 136 | const file = try options.emit.?.directory.handle.createFile(sub_path, .{ |
| 128 | .truncate = false, | 137 | .truncate = false, |
| ... | @@ -648,6 +657,11 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void { | ... | @@ -648,6 +657,11 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void { |
| 648 | const tracy = trace(@src()); | 657 | const tracy = trace(@src()); |
| 649 | defer tracy.end(); | 658 | defer tracy.end(); |
| 650 | | 659 | |
| | 660 | if (self.llvm_ir_module) |llvm_ir_module| { |
| | 661 | try llvm_ir_module.updateDecl(module, decl); |
| | 662 | return; |
| | 663 | } |
| | 664 | |
| 651 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | 665 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 652 | defer code_buffer.deinit(); | 666 | defer code_buffer.deinit(); |
| 653 | | 667 | |
| ... | @@ -704,6 +718,8 @@ pub fn freeDecl(self: *Coff, decl: *Module.Decl) void { | ... | @@ -704,6 +718,8 @@ pub fn freeDecl(self: *Coff, decl: *Module.Decl) void { |
| 704 | } | 718 | } |
| 705 | | 719 | |
| 706 | pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl, exports: []const *Module.Export) !void { | 720 | pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl, exports: []const *Module.Export) !void { |
| | 721 | if (self.llvm_ir_module) |_| return; |
| | 722 | |
| 707 | for (exports) |exp| { | 723 | for (exports) |exp| { |
| 708 | if (exp.options.section) |section_name| { | 724 | if (exp.options.section) |section_name| { |
| 709 | if (!mem.eql(u8, section_name, ".text")) { | 725 | if (!mem.eql(u8, section_name, ".text")) { |
| ... | @@ -744,6 +760,11 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void { | ... | @@ -744,6 +760,11 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void { |
| 744 | const tracy = trace(@src()); | 760 | const tracy = trace(@src()); |
| 745 | defer tracy.end(); | 761 | defer tracy.end(); |
| 746 | | 762 | |
| | 763 | if (self.llvm_ir_module) |llvm_ir_module| { |
| | 764 | try llvm_ir_module.flushModule(comp); |
| | 765 | return; |
| | 766 | } |
| | 767 | |
| 747 | if (self.text_section_size_dirty) { | 768 | if (self.text_section_size_dirty) { |
| 748 | // Write the new raw size in the .text header | 769 | // Write the new raw size in the .text header |
| 749 | var buf: [4]u8 = undefined; | 770 | var buf: [4]u8 = undefined; |
| ... | @@ -1124,8 +1145,9 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { | ... | @@ -1124,8 +1145,9 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { |
| 1124 | try argv.append(comp.libunwind_static_lib.?.full_object_path); | 1145 | try argv.append(comp.libunwind_static_lib.?.full_object_path); |
| 1125 | } | 1146 | } |
| 1126 | | 1147 | |
| | 1148 | // TODO: remove when stage2 can build compiler_rt.zig, c.zig and ssp.zig |
| 1127 | // compiler-rt, libc and libssp | 1149 | // compiler-rt, libc and libssp |
| 1128 | if (is_exe_or_dyn_lib and !self.base.options.skip_linker_dependencies) { | 1150 | if (is_exe_or_dyn_lib and !self.base.options.skip_linker_dependencies and build_options.is_stage1) { |
| 1129 | if (!self.base.options.link_libc) { | 1151 | if (!self.base.options.link_libc) { |
| 1130 | try argv.append(comp.libc_static_lib.?.full_object_path); | 1152 | try argv.append(comp.libc_static_lib.?.full_object_path); |
| 1131 | } | 1153 | } |
| ... | @@ -1235,6 +1257,7 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !v | ... | @@ -1235,6 +1257,7 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !v |
| 1235 | } | 1257 | } |
| 1236 | | 1258 | |
| 1237 | pub fn deinit(self: *Coff) void { | 1259 | pub fn deinit(self: *Coff) void { |
| | 1260 | if (self.llvm_ir_module) |ir_module| ir_module.deinit(self.base.allocator); |
| 1238 | self.text_block_free_list.deinit(self.base.allocator); | 1261 | self.text_block_free_list.deinit(self.base.allocator); |
| 1239 | self.offset_table.deinit(self.base.allocator); | 1262 | self.offset_table.deinit(self.base.allocator); |
| 1240 | self.offset_table_free_list.deinit(self.base.allocator); | 1263 | self.offset_table_free_list.deinit(self.base.allocator); |