Skip to content

Commit 74af79e

Browse files
zygoloidbricknerb
authored andcommitted
Support lowering specifics for an imported generic function. (carbon-language#5475)
When lowering a specific function whose generic was defined in a different file, switch to that other file's `FileContext` and lower the generic there. Also pass the `FileContext` corresponding to the specific into the `FunctionContext`, and use that `FileContext` for resolving requests for constants and types from the specific.
1 parent 3979af3 commit 74af79e

File tree

13 files changed

+742
-192
lines changed

13 files changed

+742
-192
lines changed

toolchain/lower/context.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,21 @@ auto Context::GetFileContext(const SemIR::File* file,
4141
return *insert_result.value();
4242
}
4343

44+
auto Context::LowerPendingDefinitions() -> void {
45+
// Lower function definitions for generics.
46+
// This cannot be a range-based loop, as new definitions can be added
47+
// while building other definitions.
48+
// NOLINTNEXTLINE(modernize-loop-convert)
49+
for (size_t i = 0; i != specific_function_definitions_.size(); ++i) {
50+
auto [file_context, function_id, specific_id] =
51+
specific_function_definitions_[i];
52+
file_context->BuildFunctionDefinition(function_id, specific_id);
53+
}
54+
}
55+
4456
auto Context::Finalize() && -> std::unique_ptr<llvm::Module> {
57+
LowerPendingDefinitions();
58+
4559
file_contexts_.ForEach(
4660
[](auto, auto& file_context) { file_context->Finalize(); });
4761
return std::move(llvm_module_);

toolchain/lower/context.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ class Context {
3434
int32_t column_number;
3535
};
3636

37+
// A specific function whose definition needs to be lowered.
38+
struct PendingSpecificFunctionDefinition {
39+
FileContext* context;
40+
SemIR::FunctionId function_id;
41+
SemIR::SpecificId specific_id;
42+
};
43+
3744
explicit Context(llvm::LLVMContext& llvm_context,
3845
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,
3946
std::optional<llvm::ArrayRef<Parse::GetTreeAndSubtreesFn>>
@@ -48,6 +55,12 @@ class Context {
4855
const SemIR::InstNamer* inst_namer = nullptr)
4956
-> FileContext&;
5057

58+
// Registers a specific function definition to be lowered later.
59+
auto AddPendingSpecificFunctionDefinition(
60+
PendingSpecificFunctionDefinition pending) -> void {
61+
specific_function_definitions_.push_back(pending);
62+
}
63+
5164
// Finishes lowering and takes ownership of the LLVM module. The context
5265
// cannot be used further after calling this.
5366
auto Finalize() && -> std::unique_ptr<llvm::Module>;
@@ -98,6 +111,10 @@ class Context {
98111
llvm::Module& llvm_module,
99112
llvm::DIBuilder& di_builder) -> llvm::DICompileUnit*;
100113

114+
// Lower any definitions that have been registered for later lowering.
115+
// Currently, this lowers specifics for generic functions.
116+
auto LowerPendingDefinitions() -> void;
117+
101118
// State for building the LLVM IR.
102119
llvm::LLVMContext* llvm_context_;
103120
std::unique_ptr<llvm::Module> llvm_module_;
@@ -126,6 +143,11 @@ class Context {
126143

127144
// Global format string for `printf.int.format` used by the PrintInt builtin.
128145
llvm::Value* printf_int_format_string_ = nullptr;
146+
147+
// Tracks which specific functions need to have their definitions lowered.
148+
// This list may grow while lowering generic definitions from this list.
149+
llvm::SmallVector<PendingSpecificFunctionDefinition>
150+
specific_function_definitions_;
129151
};
130152

131153
} // namespace Carbon::Lower

0 commit comments

Comments
 (0)