mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 22:02:52 +01:00
Combine DiagnosticConverter into DiagnosticEmitter (#4878)
At present, we typically define a DiagnosticConverter, then store an instance of it and a DiagnosticEmitter that wraps it. This is relatively minor in general, but I've been trying to create more self-contained DiagnosticEmitter classes (which hold their own DiagnosticConverter, similar to NullDiagnosticEmitter), and there it just gets in the way. Since we don't reuse DiagnosticConverter instances, this combines the definition into DiagnosticEmitter. Mainly this means we don't have a separate object in play, and less to carry around. The most impact is probably to SemIRDiagnosticConverter, which was also the most complex. Now `SemIRLocDiagnosticEmitter`, this gets some different construction flow. Note in the PR I've split the file rename to its own commit, to try to help delta views. However, the most substantial parts of the refactoring are split into #4876, which this depends upon.
This commit is contained in:
@@ -333,22 +333,15 @@ class CompilationUnit {
|
||||
// Parses tokens. Returns true on success.
|
||||
auto RunParse() -> void;
|
||||
|
||||
// Prepares per-IR lazy fetch functions which may come up in cross-IR
|
||||
// diagnostics.
|
||||
auto PreCheck() -> Parse::GetTreeAndSubtreesFn;
|
||||
|
||||
// Returns information needed to check this unit.
|
||||
auto GetCheckUnit(
|
||||
SemIR::CheckIRId check_ir_id,
|
||||
llvm::ArrayRef<Parse::GetTreeAndSubtreesFn> all_trees_and_subtrees)
|
||||
-> Check::Unit;
|
||||
auto GetCheckUnit(SemIR::CheckIRId check_ir_id) -> Check::Unit;
|
||||
|
||||
// Runs post-check logic. Returns true if checking succeeded for the IR.
|
||||
auto PostCheck() -> void;
|
||||
|
||||
// Lower SemIR to LLVM IR.
|
||||
auto RunLower(std::optional<llvm::ArrayRef<Parse::GetTreeAndSubtreesFn>>
|
||||
all_trees_and_subtrees_for_debug_info) -> void;
|
||||
tree_and_subtrees_getters_for_debug_info) -> void;
|
||||
|
||||
auto RunCodeGen() -> void;
|
||||
|
||||
@@ -363,6 +356,9 @@ class CompilationUnit {
|
||||
auto input_filename() -> llvm::StringRef { return input_filename_; }
|
||||
auto success() -> bool { return success_; }
|
||||
auto has_source() -> bool { return source_.has_value(); }
|
||||
auto get_trees_and_subtrees() -> Parse::GetTreeAndSubtreesFn {
|
||||
return *tree_and_subtrees_getter_;
|
||||
}
|
||||
|
||||
private:
|
||||
// Do codegen. Returns true on success.
|
||||
@@ -414,8 +410,7 @@ class CompilationUnit {
|
||||
std::optional<Parse::Tree> parse_tree_;
|
||||
std::optional<Parse::TreeAndSubtrees> parse_tree_and_subtrees_;
|
||||
std::optional<std::function<const Parse::TreeAndSubtrees&()>>
|
||||
get_parse_tree_and_subtrees_;
|
||||
std::optional<Check::SemIRDiagnosticConverter> sem_ir_converter_;
|
||||
tree_and_subtrees_getter_;
|
||||
std::optional<SemIR::File> sem_ir_;
|
||||
std::unique_ptr<llvm::LLVMContext> llvm_context_;
|
||||
std::unique_ptr<llvm::Module> module_;
|
||||
@@ -500,36 +495,25 @@ auto CompilationUnit::RunParse() -> void {
|
||||
}
|
||||
}
|
||||
|
||||
auto CompilationUnit::PreCheck() -> Parse::GetTreeAndSubtreesFn {
|
||||
auto CompilationUnit::GetCheckUnit(SemIR::CheckIRId check_ir_id)
|
||||
-> Check::Unit {
|
||||
CARBON_CHECK(parse_tree_, "Must call RunParse first");
|
||||
CARBON_CHECK(!get_parse_tree_and_subtrees_, "Called PreCheck twice");
|
||||
CARBON_CHECK(!sem_ir_, "Called GetCheckUnit twice");
|
||||
|
||||
get_parse_tree_and_subtrees_ = [this]() -> const Parse::TreeAndSubtrees& {
|
||||
tree_and_subtrees_getter_ = [this]() -> const Parse::TreeAndSubtrees& {
|
||||
return this->GetParseTreeAndSubtrees();
|
||||
};
|
||||
return *get_parse_tree_and_subtrees_;
|
||||
}
|
||||
|
||||
auto CompilationUnit::GetCheckUnit(
|
||||
SemIR::CheckIRId check_ir_id,
|
||||
llvm::ArrayRef<Parse::GetTreeAndSubtreesFn> all_trees_and_subtrees)
|
||||
-> Check::Unit {
|
||||
CARBON_CHECK(get_parse_tree_and_subtrees_, "Must call PreCheck first");
|
||||
CARBON_CHECK(!sem_ir_converter_, "Called GetCheckUnit twice");
|
||||
|
||||
sem_ir_.emplace(&*parse_tree_, check_ir_id, parse_tree_->packaging_decl(),
|
||||
value_stores_, input_filename_);
|
||||
sem_ir_converter_.emplace(all_trees_and_subtrees, &*sem_ir_);
|
||||
return {.consumer = consumer_,
|
||||
.value_stores = &value_stores_,
|
||||
.timings = timings_ ? &*timings_ : nullptr,
|
||||
.get_parse_tree_and_subtrees = *get_parse_tree_and_subtrees_,
|
||||
.sem_ir = &*sem_ir_,
|
||||
.sem_ir_converter = &*sem_ir_converter_};
|
||||
.tree_and_subtrees_getter = *tree_and_subtrees_getter_,
|
||||
.sem_ir = &*sem_ir_};
|
||||
}
|
||||
|
||||
auto CompilationUnit::PostCheck() -> void {
|
||||
CARBON_CHECK(sem_ir_converter_, "Must call GetCheckUnit first");
|
||||
CARBON_CHECK(sem_ir_, "Must call GetCheckUnit first");
|
||||
|
||||
// We've finished all steps that can produce diagnostics. Emit the
|
||||
// diagnostics now, so that the developer sees them sooner and doesn't need
|
||||
@@ -589,15 +573,15 @@ auto CompilationUnit::PostCheck() -> void {
|
||||
|
||||
auto CompilationUnit::RunLower(
|
||||
std::optional<llvm::ArrayRef<Parse::GetTreeAndSubtreesFn>>
|
||||
all_trees_and_subtrees_for_debug_info) -> void {
|
||||
tree_and_subtrees_getters_for_debug_info) -> void {
|
||||
LogCall("Lower::LowerToLLVM", "lower", [&] {
|
||||
llvm_context_ = std::make_unique<llvm::LLVMContext>();
|
||||
// TODO: Consider disabling instruction naming by default if we're not
|
||||
// producing textual LLVM IR.
|
||||
SemIR::InstNamer inst_namer(&*sem_ir_);
|
||||
module_ = Lower::LowerToLLVM(
|
||||
*llvm_context_, all_trees_and_subtrees_for_debug_info, input_filename_,
|
||||
*sem_ir_, &inst_namer, vlog_stream_);
|
||||
*llvm_context_, tree_and_subtrees_getters_for_debug_info,
|
||||
input_filename_, *sem_ir_, &inst_namer, vlog_stream_);
|
||||
});
|
||||
if (vlog_stream_) {
|
||||
CARBON_VLOG("*** llvm::Module ***\n");
|
||||
@@ -843,25 +827,13 @@ auto CompileSubcommand::Run(DriverEnv& driver_env) -> DriverResult {
|
||||
return make_result();
|
||||
}
|
||||
|
||||
// Pre-check assigns IR IDs and constructs node converters.
|
||||
llvm::SmallVector<Parse::GetTreeAndSubtreesFn> all_trees_and_subtrees;
|
||||
// This size may not match due to units that are missing source, but that's an
|
||||
// error case and not worth extra work.
|
||||
all_trees_and_subtrees.reserve(units.size());
|
||||
for (auto& unit : units) {
|
||||
if (unit->has_source()) {
|
||||
all_trees_and_subtrees.push_back(unit->PreCheck());
|
||||
}
|
||||
}
|
||||
|
||||
// Gather Check::Units.
|
||||
llvm::SmallVector<Check::Unit> check_units;
|
||||
check_units.reserve(all_trees_and_subtrees.size());
|
||||
check_units.reserve(units.size());
|
||||
for (auto& unit : units) {
|
||||
if (unit->has_source()) {
|
||||
SemIR::CheckIRId check_ir_id(check_units.size());
|
||||
check_units.push_back(
|
||||
unit->GetCheckUnit(check_ir_id, all_trees_and_subtrees));
|
||||
check_units.push_back(unit->GetCheckUnit(check_ir_id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -888,13 +860,23 @@ auto CompileSubcommand::Run(DriverEnv& driver_env) -> DriverResult {
|
||||
}
|
||||
|
||||
// Lower.
|
||||
llvm::SmallVector<Parse::GetTreeAndSubtreesFn> tree_and_subtrees_getters;
|
||||
std::optional<llvm::ArrayRef<Parse::GetTreeAndSubtreesFn>>
|
||||
all_trees_and_subtrees_for_debug_info;
|
||||
tree_and_subtrees_getters_for_debug_info;
|
||||
if (options_.include_debug_info) {
|
||||
all_trees_and_subtrees_for_debug_info = all_trees_and_subtrees;
|
||||
// This size may not match due to units that are missing source, but that's
|
||||
// an error case and not worth extra work.
|
||||
tree_and_subtrees_getters.reserve(units.size());
|
||||
for (auto& unit : units) {
|
||||
if (unit->has_source()) {
|
||||
tree_and_subtrees_getters.push_back(unit->get_trees_and_subtrees());
|
||||
}
|
||||
}
|
||||
tree_and_subtrees_getters_for_debug_info = {};
|
||||
tree_and_subtrees_getters_for_debug_info = tree_and_subtrees_getters;
|
||||
}
|
||||
for (const auto& unit : units) {
|
||||
unit->RunLower(all_trees_and_subtrees_for_debug_info);
|
||||
unit->RunLower(tree_and_subtrees_getters_for_debug_info);
|
||||
}
|
||||
if (options_.phase == CompileOptions::Phase::Lower) {
|
||||
return make_result();
|
||||
|
||||
Reference in New Issue
Block a user