Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 3.2k
Implement emit-h#7111
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Implement emit-h #7111
Changes from all commits
40f0275aba273dc87da2f15a148d37438ddac33b1085380538d6066e58bd6c5e834d030771aac9849e89File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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"); | ||
| @@ -126,12 +128,13 @@ test_filter: ?[]const u8, | ||
| test_name_prefix: ?[]const u8, | ||
| test_evented_io: bool, | ||
| emit_h: ?EmitLoc, | ||
| emit_asm: ?EmitLoc, | ||
| emit_llvm_ir: ?EmitLoc, | ||
| emit_analysis: ?EmitLoc, | ||
| emit_docs: ?EmitLoc, | ||
| c_header: ?c_link.Header, | ||
| pub const InnerError = Module.InnerError; | ||
| pub const CRTFile = struct { | ||
| @@ -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); | ||
| @@ -974,7 +973,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ||
| .local_cache_directory = options.local_cache_directory, | ||
| .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, options.emit_h) else null, | ||
| .emit_asm = options.emit_asm, | ||
| .emit_llvm_ir = options.emit_llvm_ir, | ||
| .emit_analysis = options.emit_analysis, | ||
| @@ -1185,6 +1184,10 @@ pub fn destroy(self: *Compilation) void { | ||
| } | ||
| self.failed_c_objects.deinit(gpa); | ||
| if (self.c_header) |*header| { | ||
| header.deinit(); | ||
| } | ||
| self.cache_parent.manifest_dir.close(); | ||
| if (self.owned_link_dir) |*dir| dir.close(); | ||
| @@ -1286,6 +1289,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 = header.emit_loc.?; | ||
| // 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 +1402,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 +1452,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 => { | ||
tetsuo-cpp marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| decl.analysis = .dependency_failure; | ||
| }, | ||
| else => { | ||
| try module.failed_decls.ensureCapacity(module.gpa, module.failed_decls.items().len + 1); | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this makes sense. If | ||
| 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| { | ||
| @@ -2913,7 +2955,10 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node | ||
| man.hash.add(comp.bin_file.options.function_sections); | ||
| man.hash.add(comp.bin_file.options.is_test); | ||
| man.hash.add(comp.bin_file.options.emit != null); | ||
| man.hash.addOptionalEmitLoc(comp.emit_h); | ||
| man.hash.add(comp.c_header != null); | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There should be a ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. | ||
| if (comp.c_header) |header| { | ||
| man.hash.addEmitLoc(header.emit_loc.?); | ||
| } | ||
| man.hash.addOptionalEmitLoc(comp.emit_asm); | ||
| man.hash.addOptionalEmitLoc(comp.emit_llvm_ir); | ||
| man.hash.addOptionalEmitLoc(comp.emit_analysis); | ||
| @@ -3012,10 +3057,10 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node | ||
| }); | ||
| break :blk try directory.join(arena, &[_][]const u8{bin_basename}); | ||
| } else ""; | ||
| if (comp.emit_h != null) { | ||
| if (comp.c_header != null) { | ||
| log.warn("-femit-h is not available in the stage1 backend; no .h file will be produced", .{}); | ||
| } | ||
| const emit_h_path = try stage1LocPath(arena, comp.emit_h, directory); | ||
| const emit_h_path = try stage1LocPath(arena, if (comp.c_header) |header| header.emit_loc else null, directory); | ||
| const emit_asm_path = try stage1LocPath(arena, comp.emit_asm, directory); | ||
| const emit_llvm_ir_path = try stage1LocPath(arena, comp.emit_llvm_ir, directory); | ||
| const emit_analysis_path = try stage1LocPath(arena, comp.emit_analysis, directory); | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was the formatting change deliberate?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a
returnafter catching an error. My thinking is that there's no point in doing the header generation if the code generation for that decl didn't work.Otherwise, the same decl may even get flagged twice.