aboutsummaryrefslogtreecommitdiff
path: root/src/link/Coff.zig
diff options
context:
space:
mode:
authorTimon Kruiper <timonkruiper@gmail.com>2020-12-19 12:14:17 +0100
committerTimon Kruiper <timonkruiper@gmail.com>2020-12-28 21:20:46 +0100
commitb059bb84b85ca7914d617cae7c4960a798412ea5 (patch)
tree99808267690ba037765d6e8431d58f17ba71462f /src/link/Coff.zig
parent071417161d5d7ab91c32073693590ef161017dbe (diff)
downloadzig-b059bb84b85ca7914d617cae7c4960a798412ea5.tar.gz
zig-b059bb84b85ca7914d617cae7c4960a798412ea5.zip
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; } ```
Diffstat (limited to 'src/link/Coff.zig')
-rw-r--r--src/link/Coff.zig29
1 files changed, 26 insertions, 3 deletions
diff --git a/src/link/Coff.zig b/src/link/Coff.zig
index bea3033f88..161a4092f4 100644
--- a/src/link/Coff.zig
+++ b/src/link/Coff.zig
@@ -16,6 +16,7 @@ const link = @import("../link.zig");
const build_options = @import("build_options");
const Cache = @import("../Cache.zig");
const mingw = @import("../mingw.zig");
+const llvm_backend = @import("../llvm_backend.zig");
const allocation_padding = 4 / 3;
const minimum_text_block_size = 64 * allocation_padding;
@@ -32,6 +33,9 @@ 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,
+
base: link.File,
ptr_width: PtrWidth,
error_flags: link.File.ErrorFlags = .{},
@@ -121,8 +125,13 @@ pub const SrcFn = void;
pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Coff {
assert(options.object_format == .coff);
- if (options.use_llvm) return error.LLVM_BackendIsTODO_ForCoff; // TODO
- if (options.use_lld) return error.LLD_LinkingIsTODO_ForCoff; // TODO
+ if (options.use_llvm) {
+ const self = try createEmpty(allocator, options);
+ errdefer self.base.destroy();
+
+ self.llvm_ir_module = try llvm_backend.LLVMIRModule.create(allocator, sub_path, options);
+ return self;
+ }
const file = try options.emit.?.directory.handle.createFile(sub_path, .{
.truncate = false,
@@ -648,6 +657,11 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
const tracy = trace(@src());
defer tracy.end();
+ if (self.llvm_ir_module) |llvm_ir_module| {
+ try llvm_ir_module.updateDecl(module, decl);
+ return;
+ }
+
var code_buffer = std.ArrayList(u8).init(self.base.allocator);
defer code_buffer.deinit();
@@ -704,6 +718,8 @@ pub fn freeDecl(self: *Coff, decl: *Module.Decl) void {
}
pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl, exports: []const *Module.Export) !void {
+ if (self.llvm_ir_module) |_| return;
+
for (exports) |exp| {
if (exp.options.section) |section_name| {
if (!mem.eql(u8, section_name, ".text")) {
@@ -744,6 +760,11 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void {
const tracy = trace(@src());
defer tracy.end();
+ if (self.llvm_ir_module) |llvm_ir_module| {
+ try llvm_ir_module.flushModule(comp);
+ return;
+ }
+
if (self.text_section_size_dirty) {
// Write the new raw size in the .text header
var buf: [4]u8 = undefined;
@@ -1124,8 +1145,9 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
try argv.append(comp.libunwind_static_lib.?.full_object_path);
}
+ // TODO: remove when stage2 can build compiler_rt.zig, c.zig and ssp.zig
// compiler-rt, libc and libssp
- if (is_exe_or_dyn_lib and !self.base.options.skip_linker_dependencies) {
+ if (is_exe_or_dyn_lib and !self.base.options.skip_linker_dependencies and build_options.is_stage1) {
if (!self.base.options.link_libc) {
try argv.append(comp.libc_static_lib.?.full_object_path);
}
@@ -1235,6 +1257,7 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !v
}
pub fn deinit(self: *Coff) void {
+ if (self.llvm_ir_module) |ir_module| ir_module.deinit(self.base.allocator);
self.text_block_free_list.deinit(self.base.allocator);
self.offset_table.deinit(self.base.allocator);
self.offset_table_free_list.deinit(self.base.allocator);