Change CodeGen to use a diagnostic consumer (#5847)

We've been trying to have errors/warnings all go through the diagnostics
consumers instead of straight to stderr.
This commit is contained in:
Jon Ross-Perkins
2025-07-24 21:44:44 +00:00
committed by GitHub
parent 59619fa8eb
commit d599023c19
6 changed files with 35 additions and 16 deletions
+2
View File
@@ -17,6 +17,8 @@ cc_library(
hdrs = ["codegen.h"],
deps = [
"//common:check",
"//toolchain/diagnostics:diagnostic_emitter",
"//toolchain/diagnostics:file_diagnostics",
"@llvm-project//llvm:Core",
"@llvm-project//llvm:MC",
"@llvm-project//llvm:Support",
+8 -4
View File
@@ -13,15 +13,16 @@
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/TargetParser/Host.h"
#include "toolchain/diagnostics/diagnostic_consumer.h"
namespace Carbon {
auto CodeGen::Make(llvm::Module* module, llvm::StringRef target_triple_str,
llvm::raw_pwrite_stream* errors) -> std::optional<CodeGen> {
Diagnostics::Consumer* consumer) -> std::optional<CodeGen> {
std::string error;
const llvm::Target* target =
llvm::TargetRegistry::lookupTarget(target_triple_str, error);
CARBON_CHECK(target, "Target should be validated before codegen");
CARBON_CHECK(target, "Target should be validated before codegen: {0}", error);
llvm::Triple target_triple(target_triple_str);
module->setTargetTriple(target_triple);
@@ -30,7 +31,8 @@ auto CodeGen::Make(llvm::Module* module, llvm::StringRef target_triple_str,
constexpr llvm::StringLiteral Features = "";
llvm::TargetOptions target_opts;
CodeGen codegen(module, errors);
CodeGen codegen(module,
consumer ? consumer : &Diagnostics::ConsoleConsumer());
codegen.target_machine_.reset(target->createTargetMachine(
target_triple, CPU, Features, target_opts, llvm::Reloc::PIC_));
return codegen;
@@ -54,7 +56,9 @@ auto CodeGen::EmitCode(llvm::raw_pwrite_stream& out,
llvm::legacy::PassManager pass;
// Note that this returns true on an error.
if (target_machine_->addPassesToEmitFile(pass, out, nullptr, file_type)) {
*errors_ << "error: unable to emit to this file\n";
CARBON_DIAGNOSTIC(CodeGenUnableToEmit, Error,
"unable to emit to this file");
emitter_.Emit(module_->getName(), CodeGenUnableToEmit);
return false;
}
+15 -10
View File
@@ -7,35 +7,37 @@
#include "llvm/IR/Module.h"
#include "llvm/Target/TargetMachine.h"
#include "toolchain/diagnostics/diagnostic_consumer.h"
#include "toolchain/diagnostics/file_diagnostics.h"
namespace Carbon {
class CodeGen {
public:
// `module` and `errors` must not be null.
// `module` and `errors` must not be null. `consumer` may be null, in which
// case diagnostics go to stderr.
static auto Make(llvm::Module* module, llvm::StringRef target_triple_str,
llvm::raw_pwrite_stream* errors) -> std::optional<CodeGen>;
Diagnostics::Consumer* consumer = nullptr)
-> std::optional<CodeGen>;
// Generates the object code file.
// Returns false in case of failure, and any information about the failure is
// printed to the error stream.
//
// Note that unlike the error stream, this requires a `pwrite` stream to allow
// patching the output.
// Note this requires a `pwrite` stream to allow patching the output.
auto EmitObject(llvm::raw_pwrite_stream& out) -> bool;
// Prints the assembly to stdout.
// Returns false in case of failure, and any information about the failure is
// printed to the error stream.
//
// Note that unlike the error stream, this requires a `pwrite` stream to allow
// patching the output.
// Note this requires a `pwrite` stream to allow patching the output.
auto EmitAssembly(llvm::raw_pwrite_stream& out) -> bool;
private:
// `module` and `errors` must not be null.
explicit CodeGen(llvm::Module* module, llvm::raw_pwrite_stream* errors)
: module_(module), errors_(errors) {}
// `module` and `consumer` must not be null.
explicit CodeGen(llvm::Module* module, Diagnostics::Consumer* consumer)
: module_(module), emitter_(consumer) {}
// Using the llvm pass emits either assembly or object code to dest.
// Returns false in case of failure, and any information about the failure is
@@ -44,7 +46,10 @@ class CodeGen {
-> bool;
llvm::Module* module_;
llvm::raw_pwrite_stream* errors_;
// The emitter for diagnostics.
Diagnostics::FileEmitter emitter_;
std::unique_ptr<llvm::TargetMachine> target_machine_;
};
+3
View File
@@ -43,6 +43,9 @@ constexpr Kind UntestedKinds[] = {
// This is a little long but is tested in lex/numeric_literal_test.cpp.
Kind::TooManyDigits,
// Producing an emit failure may be infeasible.
Kind::CodeGenUnableToEmit,
// TODO: This can only fire if the first message in a diagnostic is rooted
// in a file other than the file being compiled. The language server
// currently only supports compiling one file at a time. Do one of:
@@ -499,6 +499,12 @@ CARBON_DIAGNOSTIC_KIND(GenericMissingExplicitParameters)
// Pattern matching diagnostics.
CARBON_DIAGNOSTIC_KIND(TuplePatternSizeDoesntMatchLiteral)
// ============================================================================
// CodeGen diagnostics
// ============================================================================
CARBON_DIAGNOSTIC_KIND(CodeGenUnableToEmit)
// ============================================================================
// Language server diagnostics
// ============================================================================
+1 -2
View File
@@ -741,8 +741,7 @@ auto CompilationUnit::PostCompile() -> void {
auto CompilationUnit::RunCodeGenHelper() -> bool {
std::optional<CodeGen> codegen =
CodeGen::Make(module_.get(), options_->codegen_options.target,
driver_env_->error_stream);
CodeGen::Make(module_.get(), options_->codegen_options.target, consumer_);
if (!codegen) {
return false;
}