aboutsummaryrefslogtreecommitdiff
path: root/src/Compilation.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/Compilation.zig')
-rw-r--r--src/Compilation.zig77
1 files changed, 58 insertions, 19 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 23f67f5b37..5b06bd6370 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -26,6 +26,8 @@ const Module = @import("Module.zig");
const Cache = @import("Cache.zig");
const stage1 = @import("stage1.zig");
const translate_c = @import("translate_c.zig");
+const c_codegen = @import("codegen/c.zig");
+const c_link = @import("link/C.zig");
const ThreadPool = @import("ThreadPool.zig");
const WaitGroup = @import("WaitGroup.zig");
@@ -131,6 +133,7 @@ emit_asm: ?EmitLoc,
emit_llvm_ir: ?EmitLoc,
emit_analysis: ?EmitLoc,
emit_docs: ?EmitLoc,
+c_header: ?c_link.Header,
pub const InnerError = Module.InnerError;
@@ -895,10 +898,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
};
};
- if (!use_llvm and options.emit_h != null) {
- fatal("TODO implement support for -femit-h in the self-hosted backend", .{});
- }
-
var system_libs: std.StringArrayHashMapUnmanaged(void) = .{};
errdefer system_libs.deinit(gpa);
try system_libs.ensureCapacity(gpa, options.system_libs.len);
@@ -975,6 +974,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
.global_cache_directory = options.global_cache_directory,
.bin_file = bin_file,
.emit_h = options.emit_h,
+ .c_header = if (!use_llvm and options.emit_h != null) c_link.Header.init(gpa) else null,
.emit_asm = options.emit_asm,
.emit_llvm_ir = options.emit_llvm_ir,
.emit_analysis = options.emit_analysis,
@@ -1286,6 +1286,20 @@ pub fn update(self: *Compilation) !void {
module.root_scope.unload(self.gpa);
}
}
+
+ // If we've chosen to emit a C header, flush the header to the disk.
+ if (self.c_header) |header| {
+ const header_path = self.emit_h.?;
+ // If a directory has been provided, write the header there. Otherwise, just write it to the
+ // cache directory.
+ const header_dir = if (header_path.directory) |dir|
+ dir.handle
+ else
+ self.local_cache_directory.handle;
+ const header_file = try header_dir.createFile(header_path.basename, .{});
+ defer header_file.close();
+ try header.flush(header_file.writer());
+ }
}
/// Having the file open for writing is problematic as far as executing the
@@ -1385,6 +1399,9 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
var c_comp_progress_node = main_progress_node.start("Compile C Objects", self.c_source_files.len);
defer c_comp_progress_node.end();
+ var arena = std.heap.ArenaAllocator.init(self.gpa);
+ defer arena.deinit();
+
var wg = WaitGroup{};
defer wg.wait();
@@ -1432,22 +1449,44 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
assert(decl.typed_value.most_recent.typed_value.ty.hasCodeGenBits());
- self.bin_file.updateDecl(module, decl) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- error.AnalysisFail => {
- decl.analysis = .dependency_failure;
- },
- else => {
- try module.failed_decls.ensureCapacity(module.gpa, module.failed_decls.items().len + 1);
- module.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(
- module.gpa,
- decl.src(),
- "unable to codegen: {}",
- .{@errorName(err)},
- ));
- decl.analysis = .codegen_failure_retryable;
- },
+ self.bin_file.updateDecl(module, decl) catch |err| {
+ switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ error.AnalysisFail => {
+ decl.analysis = .dependency_failure;
+ },
+ else => {
+ try module.failed_decls.ensureCapacity(module.gpa, module.failed_decls.items().len + 1);
+ module.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(
+ module.gpa,
+ decl.src(),
+ "unable to codegen: {}",
+ .{@errorName(err)},
+ ));
+ decl.analysis = .codegen_failure_retryable;
+ },
+ }
+ return;
};
+
+ if (self.c_header) |*header| {
+ c_codegen.generateHeader(&arena, module, &header.*, decl) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ error.AnalysisFail => {
+ decl.analysis = .dependency_failure;
+ },
+ else => {
+ try module.failed_decls.ensureCapacity(module.gpa, module.failed_decls.items().len + 1);
+ module.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create(
+ module.gpa,
+ decl.src(),
+ "unable to generate C header: {}",
+ .{@errorName(err)},
+ ));
+ decl.analysis = .codegen_failure_retryable;
+ },
+ };
+ }
},
},
.analyze_decl => |decl| {