Commit 3c05c60acc

Timon Kruiper <timonkruiper@gmail.com>
2021-01-03 16:09:32
stage2: Output the LLVM object files in the cache directory
Also make sure to properly free everything.
1 parent 0008bef
Changed files (3)
src/link/Coff.zig
@@ -811,8 +811,11 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
     // If there is no Zig code to compile, then we should skip flushing the output file because it
     // will not be part of the linker line anyway.
     const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: {
-        const use_stage1 = build_options.is_stage1 and self.base.options.use_llvm;
-        if (use_stage1) {
+        // Both stage1 and stage2 LLVM backend put the object file in the cache directory.
+        if (self.base.options.use_llvm) {
+            // Stage2 has to call flushModule since that outputs the LLVM object file.
+            if (!build_options.is_stage1) try self.flushModule(comp);
+
             const obj_basename = try std.zig.binNameAlloc(arena, .{
                 .root_name = self.base.options.root_name,
                 .target = self.base.options.target,
src/link/Elf.zig
@@ -1251,8 +1251,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
     // If there is no Zig code to compile, then we should skip flushing the output file because it
     // will not be part of the linker line anyway.
     const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: {
-        const use_stage1 = build_options.is_stage1 and self.base.options.use_llvm;
-        if (use_stage1) {
+        // Both stage1 and stage2 LLVM backend put the object file in the cache directory.
+        if (self.base.options.use_llvm) {
+            // Stage2 has to call flushModule since that outputs the LLVM object file.
+            if (!build_options.is_stage1) try self.flushModule(comp);
+
             const obj_basename = try std.zig.binNameAlloc(arena, .{
                 .root_name = self.base.options.root_name,
                 .target = self.base.options.target,
src/llvm_backend.zig
@@ -142,7 +142,7 @@ pub const LLVMIRModule = struct {
     target_machine: *const llvm.TargetMachineRef,
     builder: *const llvm.BuilderRef,
 
-    output_path: []const u8,
+    object_path: []const u8,
 
     gpa: *Allocator,
     err_msg: ?*Compilation.ErrorMsg = null,
@@ -161,6 +161,17 @@ pub const LLVMIRModule = struct {
 
         const gpa = options.module.?.gpa;
 
+        const obj_basename = try std.zig.binNameAlloc(gpa, .{
+            .root_name = options.root_name,
+            .target = options.target,
+            .output_mode = .Obj,
+        });
+        defer gpa.free(obj_basename);
+
+        const o_directory = options.module.?.zig_cache_artifact_directory;
+        const object_path = try o_directory.join(gpa, &[_][]const u8{obj_basename});
+        errdefer gpa.free(object_path);
+
         initializeLLVMTargets();
 
         const root_nameZ = try gpa.dupeZ(u8, options.root_name);
@@ -212,7 +223,7 @@ pub const LLVMIRModule = struct {
             .llvm_module = llvm_module,
             .target_machine = target_machine,
             .builder = builder,
-            .output_path = sub_path,
+            .object_path = object_path,
             .gpa = gpa,
         };
         return self;
@@ -222,6 +233,10 @@ pub const LLVMIRModule = struct {
         self.builder.disposeBuilder();
         self.target_machine.disposeTargetMachine();
         self.llvm_module.disposeModule();
+
+        self.func_inst_table.deinit(self.gpa);
+        self.gpa.free(self.object_path);
+
         allocator.destroy(self);
     }
 
@@ -254,15 +269,13 @@ pub const LLVMIRModule = struct {
             }
         }
 
-        const output_pathZ = try self.gpa.dupeZ(u8, self.output_path);
-        defer self.gpa.free(output_pathZ);
+        const object_pathZ = try self.gpa.dupeZ(u8, self.object_path);
+        defer self.gpa.free(object_pathZ);
 
         var error_message: [*:0]const u8 = undefined;
-        // TODO: where to put the output object, zig-cache something?
-        // TODO: caching?
         if (self.target_machine.emitToFile(
             self.llvm_module,
-            output_pathZ.ptr,
+            object_pathZ.ptr,
             .ObjectFile,
             &error_message,
         )) {