mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 21:30:12 +01:00
This is trying to make it clearer when vectors are being indexed with `CheckIRId`. The only one that I still kind of want to change is the `SmallVector<std::unique_ptr<CompilationUnit>>`, but because it's a `unique_ptr` that's a little more complex. I may not bother. Note, some of the changes around nuanced `SmallVector` interactions were based on trying to copy the way `SmallVector` itself takes arguments, like with range passing.
160 lines
5.8 KiB
C++
160 lines
5.8 KiB
C++
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#ifndef CARBON_TOOLCHAIN_LOWER_CONTEXT_H_
|
|
#define CARBON_TOOLCHAIN_LOWER_CONTEXT_H_
|
|
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <utility>
|
|
|
|
#include "llvm/IR/Constants.h"
|
|
#include "llvm/IR/DIBuilder.h"
|
|
#include "llvm/IR/LLVMContext.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "toolchain/parse/tree_and_subtrees.h"
|
|
#include "toolchain/sem_ir/absolute_node_id.h"
|
|
#include "toolchain/sem_ir/ids.h"
|
|
#include "toolchain/sem_ir/inst_namer.h"
|
|
|
|
namespace Carbon::Lower {
|
|
|
|
class FileContext;
|
|
|
|
// Context for lowering to an LLVM module.
|
|
class Context {
|
|
public:
|
|
// Location information for use with DebugInfo. The line_number and
|
|
// column_number are >= 0, with 0 as unknown, so that they can be passed
|
|
// directly to DebugInfo.
|
|
struct LocForDI {
|
|
llvm::StringRef filename;
|
|
int32_t line_number;
|
|
int32_t column_number;
|
|
};
|
|
|
|
// A specific function whose definition needs to be lowered.
|
|
struct PendingSpecificFunctionDefinition {
|
|
FileContext* context;
|
|
SemIR::FunctionId function_id;
|
|
SemIR::SpecificId specific_id;
|
|
};
|
|
|
|
// `llvm_context` and `tree_and_subtrees_getters` must be non-null.
|
|
// `vlog_stream` is optional.
|
|
explicit Context(
|
|
llvm::LLVMContext* llvm_context,
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs, bool want_debug_info,
|
|
const Parse::GetTreeAndSubtreesStore* tree_and_subtrees_getters,
|
|
llvm::StringRef module_name, llvm::raw_ostream* vlog_stream);
|
|
|
|
// Gets or creates the `FileContext` for a given SemIR file. If an
|
|
// `inst_namer` is specified the first time this is called for a file, it will
|
|
// be used for that file. Otherwise, no instruction namer will be used.
|
|
// TODO: Consider building an InstNamer if we're not given one.
|
|
auto GetFileContext(const SemIR::File* file,
|
|
const SemIR::InstNamer* inst_namer = nullptr)
|
|
-> FileContext&;
|
|
|
|
// Registers a specific function definition to be lowered later.
|
|
auto AddPendingSpecificFunctionDefinition(
|
|
PendingSpecificFunctionDefinition pending) -> void {
|
|
specific_function_definitions_.push_back(pending);
|
|
}
|
|
|
|
// Finishes lowering and takes ownership of the LLVM module. The context
|
|
// cannot be used further after calling this.
|
|
auto Finalize() && -> std::unique_ptr<llvm::Module>;
|
|
|
|
// Returns location information for use with DebugInfo.
|
|
auto GetLocForDI(SemIR::AbsoluteNodeId abs_node_id) -> LocForDI;
|
|
|
|
// Returns a lowered value to use for a value of type `type`.
|
|
auto GetTypeAsValue() -> llvm::Constant* {
|
|
return llvm::ConstantStruct::get(GetTypeType());
|
|
}
|
|
|
|
// Returns a lowered value to use for a value of int literal type.
|
|
auto GetIntLiteralAsValue() -> llvm::Constant* {
|
|
// TODO: Consider adding a named struct type for integer literals.
|
|
return llvm::ConstantStruct::get(llvm::StructType::get(llvm_context()));
|
|
}
|
|
|
|
// Returns the empty LLVM struct type used to represent the type `type`.
|
|
auto GetTypeType() -> llvm::StructType* {
|
|
if (!type_type_) {
|
|
// `type` is lowered to an empty LLVM StructType.
|
|
type_type_ = llvm::StructType::create(*llvm_context_, {}, "type");
|
|
}
|
|
return type_type_;
|
|
}
|
|
|
|
auto llvm_context() -> llvm::LLVMContext& { return *llvm_context_; }
|
|
auto llvm_module() -> llvm::Module& { return *llvm_module_; }
|
|
auto file_system() -> llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>& {
|
|
return file_system_;
|
|
}
|
|
auto di_builder() -> llvm::DIBuilder& { return di_builder_; }
|
|
auto di_compile_unit() -> llvm::DICompileUnit* { return di_compile_unit_; }
|
|
auto tree_and_subtrees_getters() -> const Parse::GetTreeAndSubtreesStore& {
|
|
return *tree_and_subtrees_getters_;
|
|
}
|
|
|
|
auto printf_int_format_string() -> llvm::Value* {
|
|
return printf_int_format_string_;
|
|
}
|
|
auto SetPrintfIntFormatString(llvm::Value* printf_int_format_string) {
|
|
CARBON_CHECK(!printf_int_format_string_,
|
|
"PrintInt formatting string already generated");
|
|
printf_int_format_string_ = printf_int_format_string;
|
|
}
|
|
|
|
private:
|
|
// Create the DICompileUnit metadata for this compilation.
|
|
auto BuildDICompileUnit(llvm::StringRef module_name,
|
|
llvm::Module& llvm_module,
|
|
llvm::DIBuilder& di_builder) -> llvm::DICompileUnit*;
|
|
|
|
// Lower any definitions that have been registered for later lowering.
|
|
// Currently, this lowers specifics for generic functions.
|
|
auto LowerPendingDefinitions() -> void;
|
|
|
|
// State for building the LLVM IR.
|
|
llvm::LLVMContext* llvm_context_;
|
|
std::unique_ptr<llvm::Module> llvm_module_;
|
|
|
|
// The filesystem for source code.
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> file_system_;
|
|
|
|
// State for building the LLVM IR debug info metadata.
|
|
llvm::DIBuilder di_builder_;
|
|
|
|
// The DICompileUnit, if any - null implies debug info is not being emitted.
|
|
llvm::DICompileUnit* di_compile_unit_;
|
|
|
|
// Parse trees. Used for debug information and crash diagnostics.
|
|
const Parse::GetTreeAndSubtreesStore* tree_and_subtrees_getters_;
|
|
|
|
// The optional vlog stream.
|
|
llvm::raw_ostream* vlog_stream_;
|
|
|
|
// The `FileContext`s for each IR that is involved in this lowering action.
|
|
Map<SemIR::CheckIRId, std::unique_ptr<FileContext>> file_contexts_;
|
|
|
|
// Lowered version of the builtin type `type`.
|
|
llvm::StructType* type_type_ = nullptr;
|
|
|
|
// Global format string for `printf.int.format` used by the PrintInt builtin.
|
|
llvm::Value* printf_int_format_string_ = nullptr;
|
|
|
|
// Tracks which specific functions need to have their definitions lowered.
|
|
// This list may grow while lowering generic definitions from this list.
|
|
llvm::SmallVector<PendingSpecificFunctionDefinition>
|
|
specific_function_definitions_;
|
|
};
|
|
|
|
} // namespace Carbon::Lower
|
|
|
|
#endif // CARBON_TOOLCHAIN_LOWER_CONTEXT_H_
|