authorgravatar for timonkruiper@gmail.comTimon Kruiper <timonkruiper@gmail.com> 2020-12-19 12:14:17+01:00
committergravatar for timonkruiper@gmail.comTimon Kruiper <timonkruiper@gmail.com> 2020-12-28 21:20:46+01:00
logb059bb84b85ca7914d617cae7c4960a798412ea5
tree99808267690ba037765d6e8431d58f17ba71462f
parent071417161d5d7ab91c32073693590ef161017dbe

stage2: add LLVM codegen windows support to the self-hosted compiler

The following example generates a valid `main.exe`: `zig build-exe main.zig -fLLVM -target x86_64-windows-gnu --subsystem console` ``` export fn wWinMainCRTStartup() noreturn { foo(); exit(); } fn foo() void {} fn exit() noreturn { unreachable; } ```

1 files changed, 26 insertions(+), 3 deletions(-)

src/link/Coff.zig+26-3
......@@ -16,6 +16,7 @@ const link = @import("../link.zig");
1616const build_options = @import("build_options");
1717const Cache = @import("../Cache.zig");
1818const mingw = @import("../mingw.zig");
19const llvm_backend = @import("../llvm_backend.zig");
1920
2021const allocation_padding = 4 / 3;
2122const minimum_text_block_size = 64 * allocation_padding;
......@@ -32,6 +33,9 @@ pub const base_tag: link.File.Tag = .coff;
3233
3334const msdos_stub = @embedFile("msdos-stub.bin");
3435
36/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
37llvm_ir_module: ?*llvm_backend.LLVMIRModule = null,
38
3539base: link.File,
3640ptr_width: PtrWidth,
3741error_flags: link.File.ErrorFlags = .{},
......@@ -121,8 +125,13 @@ pub const SrcFn = void;
121125pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Coff {
122126 assert(options.object_format == .coff);
123127
124 if (options.use_llvm) return error.LLVM_BackendIsTODO_ForCoff; // TODO
125 if (options.use_lld) return error.LLD_LinkingIsTODO_ForCoff; // TODO
128 if (options.use_llvm) {
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 }
126135
127136 const file = try options.emit.?.directory.handle.createFile(sub_path, .{
128137 .truncate = false,
......@@ -648,6 +657,11 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
648657 const tracy = trace(@src());
649658 defer tracy.end();
650659
660 if (self.llvm_ir_module) |llvm_ir_module| {
661 try llvm_ir_module.updateDecl(module, decl);
662 return;
663 }
664
651665 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
652666 defer code_buffer.deinit();
653667
......@@ -704,6 +718,8 @@ pub fn freeDecl(self: *Coff, decl: *Module.Decl) void {
704718}
705719
706720pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl, exports: []const *Module.Export) !void {
721 if (self.llvm_ir_module) |_| return;
722
707723 for (exports) |exp| {
708724 if (exp.options.section) |section_name| {
709725 if (!mem.eql(u8, section_name, ".text")) {
......@@ -744,6 +760,11 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void {
744760 const tracy = trace(@src());
745761 defer tracy.end();
746762
763 if (self.llvm_ir_module) |llvm_ir_module| {
764 try llvm_ir_module.flushModule(comp);
765 return;
766 }
767
747768 if (self.text_section_size_dirty) {
748769 // Write the new raw size in the .text header
749770 var buf: [4]u8 = undefined;
......@@ -1124,8 +1145,9 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
11241145 try argv.append(comp.libunwind_static_lib.?.full_object_path);
11251146 }
11261147
1148 // TODO: remove when stage2 can build compiler_rt.zig, c.zig and ssp.zig
11271149 // 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) {
11291151 if (!self.base.options.link_libc) {
11301152 try argv.append(comp.libc_static_lib.?.full_object_path);
11311153 }
......@@ -1235,6 +1257,7 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !v
12351257}
12361258
12371259pub fn deinit(self: *Coff) void {
1260 if (self.llvm_ir_module) |ir_module| ir_module.deinit(self.base.allocator);
12381261 self.text_block_free_list.deinit(self.base.allocator);
12391262 self.offset_table.deinit(self.base.allocator);
12401263 self.offset_table_free_list.deinit(self.base.allocator);