diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-01-05 17:33:31 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-01-05 17:41:14 -0700 |
| commit | 1a2dd85570a6439f82f7a0dd2cbf452198168c5a (patch) | |
| tree | 5731c222791af559cb26ce11dcc82b91faf30f33 /src/Compilation.zig | |
| parent | cd95444e4729761033f35d689a3b6ad6f4630552 (diff) | |
| download | zig-1a2dd85570a6439f82f7a0dd2cbf452198168c5a.tar.gz zig-1a2dd85570a6439f82f7a0dd2cbf452198168c5a.zip | |
stage2: C backend: re-implement emit-h
and also mark functions as `extern "C"` as appropriate to support c++
compilers.
Diffstat (limited to 'src/Compilation.zig')
| -rw-r--r-- | src/Compilation.zig | 96 |
1 files changed, 75 insertions, 21 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig index c654833270..552c550149 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -27,7 +27,6 @@ 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"); const libtsan = @import("libtsan.zig"); @@ -162,6 +161,8 @@ pub const CSourceFile = struct { const Job = union(enum) { /// Write the machine code for a Decl to the output file. codegen_decl: *Module.Decl, + /// Render the .h file snippet for the Decl. + emit_h_decl: *Module.Decl, /// The Decl needs to be analyzed and possibly export itself. /// It may have already be analyzed, or it may have been determined /// to be outdated; in this case perform semantic analysis again. @@ -1312,9 +1313,14 @@ pub fn update(self: *Compilation) !void { // This is needed before reading the error flags. try self.bin_file.flush(self); - self.link_error_flags = self.bin_file.errorFlags(); + if (!use_stage1) { + if (self.bin_file.options.module) |module| { + try link.File.C.flushEmitH(module); + } + } + // If there are any errors, we anticipate the source files being loaded // to report error messages. Otherwise we unload all source files to save memory. if (self.totalErrorCount() == 0 and !self.keep_source_files_loaded) { @@ -1340,7 +1346,8 @@ pub fn totalErrorCount(self: *Compilation) usize { var total: usize = self.failed_c_objects.items().len; if (self.bin_file.options.module) |module| { - total += module.failed_decls.items().len + + total += module.failed_decls.count() + + module.emit_h_failed_decls.count() + module.failed_exports.items().len + module.failed_files.items().len + @boolToInt(module.failed_root_src_file != null); @@ -1379,6 +1386,12 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { const source = try decl.scope.getSource(module); try AllErrors.add(&arena, &errors, decl.scope.subFilePath(), source, err_msg.*); } + for (module.emit_h_failed_decls.items()) |entry| { + const decl = entry.key; + const err_msg = entry.value; + const source = try decl.scope.getSource(module); + try AllErrors.add(&arena, &errors, decl.scope.subFilePath(), source, err_msg.*); + } for (module.failed_exports.items()) |entry| { const decl = entry.key.owner_decl; const err_msg = entry.value; @@ -1476,27 +1489,68 @@ 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 = .codegen_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: {s}", - .{@errorName(err)}, - )); - decl.analysis = .codegen_failure_retryable; - }, - } - return; + self.bin_file.updateDecl(module, decl) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.AnalysisFail => { + decl.analysis = .codegen_failure; + continue; + }, + 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: {s}", + .{@errorName(err)}, + )); + decl.analysis = .codegen_failure_retryable; + continue; + }, }; }, }, + .emit_h_decl => |decl| switch (decl.analysis) { + .unreferenced => unreachable, + .in_progress => unreachable, + .outdated => unreachable, + + .sema_failure, + .dependency_failure, + .sema_failure_retryable, + => continue, + + // emit-h only requires semantic analysis of the Decl to be complete, + // it does not depend on machine code generation to succeed. + .codegen_failure, .codegen_failure_retryable, .complete => { + if (build_options.omit_stage2) + @panic("sadly stage2 is omitted from this build to save memory on the CI server"); + const module = self.bin_file.options.module.?; + const emit_loc = module.emit_h.?; + const tv = decl.typed_value.most_recent.typed_value; + const emit_h = decl.getEmitH(module); + const fwd_decl = &emit_h.fwd_decl; + fwd_decl.shrinkRetainingCapacity(0); + + var dg: c_codegen.DeclGen = .{ + .module = module, + .error_msg = null, + .decl = decl, + .fwd_decl = fwd_decl.toManaged(module.gpa), + }; + defer dg.fwd_decl.deinit(); + + c_codegen.genHeader(&dg) catch |err| switch (err) { + error.AnalysisFail => { + try module.emit_h_failed_decls.put(module.gpa, decl, dg.error_msg.?); + continue; + }, + else => |e| return e, + }; + + fwd_decl.* = dg.fwd_decl.moveToUnmanaged(); + fwd_decl.shrink(module.gpa, fwd_decl.items.len); + }, + }, .analyze_decl => |decl| { if (build_options.omit_stage2) @panic("sadly stage2 is omitted from this build to save memory on the CI server"); |
