mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 22:02:52 +01:00
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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user