Perform Clang IRGen during check (#6569)

Background:
https://docs.google.com/document/d/1wi85FRiWh4X9A-gCYMVGKR40-q5fM6-3JaSpePk-XCY/edit?usp=sharing
And specifically this work is essentially an alternative to #5543

Clang's code generation is implemented through an ASTListener
(clang::CodeGenerator) that is attached throughout Clang's
parsing/sema/code
generation phases and acts on Clang AST incrementally throughout that
process.

Prior to this patch, Carbon has only created the CodeGenerator during
Carbon's
`lower` phase, missing out on key callbacks that would be made by Clang
during
`check`. Some of these issues were addressed by #6237 and #6483 - but
there were
still remaining cases where the delayed processing lead to missing
functionality.

With #6483 much of the Clang code that made multithreaded complexity of
#5543 is
no longer present, and we have access to the point of ASTListener
registration
so we can register the CodeGenerator there and consume its resulting
llvm::Module during lower.

Examples of some of the bugs this addresses are seen in the linked doc,
and
checked in as tests in this change in
`clang_code_generator_callbacks.carbon`

An indicental bug that's also fixed, and caused all the other test case
churn,
is that the `CodeGenerator` created during `lower` wasn't getting passed
the
Clang `CodeGenOpts` and was creating its own default - so, most notably,
optimization flags were not respected. This meant that the LLVM IR from
Clang
was always -O0 style IR (optnone, no inlinehint, no TBAA, etc). With
this
change, now the Clang IRGen gets the real `CodeGenOpts` and respects
optimization/other flags specified there.

This is only meant to be a rough proof of concept - I'm totally open to
reworking this in any way (even quite substantially) if folks have ideas
about
how this should be implemented most generally/elegantly/etc.
This commit is contained in:
David Blaikie
2026-01-14 00:54:37 +00:00
committed by GitHub
parent c64117d0e0
commit f1f6005d4a
36 changed files with 3059 additions and 2363 deletions
+8 -2
View File
@@ -580,8 +580,8 @@ class CompilationUnit {
std::optional<Parse::TreeAndSubtrees> parse_tree_and_subtrees_;
std::optional<std::function<auto()->const Parse::TreeAndSubtrees&>>
tree_and_subtrees_getter_;
std::optional<SemIR::File> sem_ir_;
std::unique_ptr<llvm::LLVMContext> llvm_context_;
std::optional<SemIR::File> sem_ir_;
std::unique_ptr<llvm::Module> module_;
std::unique_ptr<llvm::TargetMachine> target_machine_;
};
@@ -769,10 +769,14 @@ auto CompilationUnit::GetCheckUnit() -> Check::Unit {
};
sem_ir_.emplace(&*parse_tree_, check_ir_id_, parse_tree_->packaging_decl(),
value_stores_, input_filename_);
if (!llvm_context_) {
llvm_context_ = std::make_unique<llvm::LLVMContext>();
}
return {.consumer = consumer_,
.value_stores = &value_stores_,
.timings = timings_ ? &*timings_ : nullptr,
.sem_ir = &*sem_ir_,
.llvm_context = llvm_context_.get(),
.total_ir_count = total_ir_count_};
}
@@ -795,7 +799,9 @@ auto CompilationUnit::PostCheck() -> void {
auto CompilationUnit::RunLower() -> void {
LogCall("Lower::LowerToLLVM", "lower", [&] {
llvm_context_ = std::make_unique<llvm::LLVMContext>();
if (!llvm_context_) {
llvm_context_ = std::make_unique<llvm::LLVMContext>();
}
Lower::LowerToLLVMOptions options;
options.llvm_verifier_stream =
options_->run_llvm_verifier ? driver_env_->error_stream : nullptr;