mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 09:01:04 +01:00
Refactor SemIR::InstNamer (#3690)
- Rename `ScopeIndex` to `ScopeId`, because the order is not meaningful. This avoids collisions with `SemIR::ScopeIndex`. - Change `GetScopeFor` to use an `if constexpr` chain rather than duplicating the numbering logic across multiple functions. - Simplify `GetNameFor`, avoiding multiple identical overloads. As requested in review of #3683.
This commit is contained in:
@@ -29,13 +29,15 @@ class InstNamer {
|
||||
public:
|
||||
// int32_t matches the input value size.
|
||||
// NOLINTNEXTLINE(performance-enum-size)
|
||||
enum class ScopeIndex : int32_t {
|
||||
enum class ScopeId : int32_t {
|
||||
None = -1,
|
||||
File = 0,
|
||||
Constants = 1,
|
||||
FirstFunction = 2,
|
||||
};
|
||||
static_assert(sizeof(ScopeIndex) == sizeof(FunctionId));
|
||||
static_assert(sizeof(ScopeId) == sizeof(FunctionId));
|
||||
|
||||
struct NumberOfScopesTag {};
|
||||
|
||||
InstNamer(const Lex::TokenizedBuffer& tokenized_buffer,
|
||||
const Parse::Tree& parse_tree, const File& sem_ir)
|
||||
@@ -44,19 +46,16 @@ class InstNamer {
|
||||
sem_ir_(sem_ir) {
|
||||
insts.resize(sem_ir.insts().size());
|
||||
labels.resize(sem_ir.inst_blocks().size());
|
||||
scopes.resize(static_cast<int32_t>(ScopeIndex::FirstFunction) +
|
||||
sem_ir.functions().size() + sem_ir.classes().size() +
|
||||
sem_ir.interfaces().size());
|
||||
scopes.resize(static_cast<size_t>(GetScopeFor(NumberOfScopesTag())));
|
||||
|
||||
// Build the constants scope.
|
||||
GetScopeInfo(ScopeIndex::Constants).name =
|
||||
GetScopeInfo(ScopeId::Constants).name =
|
||||
globals.AddNameUnchecked("constants");
|
||||
CollectNamesInBlock(ScopeIndex::Constants,
|
||||
sem_ir.constants().GetAsVector());
|
||||
CollectNamesInBlock(ScopeId::Constants, sem_ir.constants().GetAsVector());
|
||||
|
||||
// Build the file scope.
|
||||
GetScopeInfo(ScopeIndex::File).name = globals.AddNameUnchecked("file");
|
||||
CollectNamesInBlock(ScopeIndex::File, sem_ir.top_inst_block_id());
|
||||
GetScopeInfo(ScopeId::File).name = globals.AddNameUnchecked("file");
|
||||
CollectNamesInBlock(ScopeId::File, sem_ir.top_inst_block_id());
|
||||
|
||||
// Build each function scope.
|
||||
for (auto [i, fn] : llvm::enumerate(sem_ir.functions().array_ref())) {
|
||||
@@ -117,54 +116,41 @@ class InstNamer {
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the scope index corresponding to a function.
|
||||
auto GetScopeFor(FunctionId fn_id) -> ScopeIndex {
|
||||
return static_cast<ScopeIndex>(
|
||||
static_cast<int32_t>(ScopeIndex::FirstFunction) + fn_id.index);
|
||||
// Returns the scope index corresponding to an ID of a function, class, or
|
||||
// interface.
|
||||
template <typename IdT>
|
||||
auto GetScopeFor(IdT id) -> ScopeId {
|
||||
auto index = static_cast<int32_t>(ScopeId::FirstFunction);
|
||||
|
||||
if constexpr (!std::same_as<FunctionId, IdT>) {
|
||||
index += sem_ir_.functions().size();
|
||||
if constexpr (!std::same_as<ClassId, IdT>) {
|
||||
index += sem_ir_.classes().size();
|
||||
if constexpr (!std::same_as<InterfaceId, IdT>) {
|
||||
index += sem_ir_.interfaces().size();
|
||||
static_assert(std::same_as<NumberOfScopesTag, IdT>,
|
||||
"Unknown ID kind for scope");
|
||||
}
|
||||
}
|
||||
}
|
||||
if constexpr (!std::same_as<NumberOfScopesTag, IdT>) {
|
||||
index += id.index;
|
||||
}
|
||||
return static_cast<ScopeId>(index);
|
||||
}
|
||||
|
||||
// Returns the scope index corresponding to a class.
|
||||
auto GetScopeFor(ClassId class_id) -> ScopeIndex {
|
||||
return static_cast<ScopeIndex>(
|
||||
static_cast<int32_t>(ScopeIndex::FirstFunction) +
|
||||
sem_ir_.functions().size() + class_id.index);
|
||||
}
|
||||
|
||||
// Returns the scope index corresponding to an interface.
|
||||
auto GetScopeFor(InterfaceId interface_id) -> ScopeIndex {
|
||||
return static_cast<ScopeIndex>(
|
||||
static_cast<int32_t>(ScopeIndex::FirstFunction) +
|
||||
sem_ir_.functions().size() + sem_ir_.classes().size() +
|
||||
interface_id.index);
|
||||
}
|
||||
|
||||
// Returns the IR name to use for a function.
|
||||
auto GetNameFor(FunctionId fn_id) -> llvm::StringRef {
|
||||
if (!fn_id.is_valid()) {
|
||||
// Returns the IR name to use for a function, class, or interface.
|
||||
template <typename IdT>
|
||||
auto GetNameFor(IdT id) -> llvm::StringRef {
|
||||
if (!id.is_valid()) {
|
||||
return "invalid";
|
||||
}
|
||||
return GetScopeInfo(GetScopeFor(fn_id)).name.str();
|
||||
}
|
||||
|
||||
// Returns the IR name to use for a class.
|
||||
auto GetNameFor(ClassId class_id) -> llvm::StringRef {
|
||||
if (!class_id.is_valid()) {
|
||||
return "invalid";
|
||||
}
|
||||
return GetScopeInfo(GetScopeFor(class_id)).name.str();
|
||||
}
|
||||
|
||||
// Returns the IR name to use for an interface.
|
||||
auto GetNameFor(InterfaceId interface_id) -> llvm::StringRef {
|
||||
if (!interface_id.is_valid()) {
|
||||
return "invalid";
|
||||
}
|
||||
return GetScopeInfo(GetScopeFor(interface_id)).name.str();
|
||||
return GetScopeInfo(GetScopeFor(id)).name.str();
|
||||
}
|
||||
|
||||
// Returns the IR name to use for an instruction, when referenced from a given
|
||||
// scope.
|
||||
auto GetNameFor(ScopeIndex scope_idx, InstId inst_id) -> std::string {
|
||||
auto GetNameFor(ScopeId scope_id, InstId inst_id) -> std::string {
|
||||
if (!inst_id.is_valid()) {
|
||||
return "invalid";
|
||||
}
|
||||
@@ -185,14 +171,14 @@ class InstNamer {
|
||||
llvm::raw_string_ostream(str) << "<unexpected instref " << inst_id << ">";
|
||||
return str;
|
||||
}
|
||||
if (inst_scope == scope_idx) {
|
||||
if (inst_scope == scope_id) {
|
||||
return inst_name.str().str();
|
||||
}
|
||||
return (GetScopeInfo(inst_scope).name.str() + "." + inst_name.str()).str();
|
||||
}
|
||||
|
||||
// Returns the IR name to use for a label, when referenced from a given scope.
|
||||
auto GetLabelFor(ScopeIndex scope_idx, InstBlockId block_id) -> std::string {
|
||||
auto GetLabelFor(ScopeId scope_id, InstBlockId block_id) -> std::string {
|
||||
if (!block_id.is_valid()) {
|
||||
return "!invalid";
|
||||
}
|
||||
@@ -205,7 +191,7 @@ class InstNamer {
|
||||
<< "<unexpected instblockref " << block_id << ">";
|
||||
return str;
|
||||
}
|
||||
if (label_scope == scope_idx) {
|
||||
if (label_scope == scope_id) {
|
||||
return label_name.str().str();
|
||||
}
|
||||
return (GetScopeInfo(label_scope).name.str() + "." + label_name.str())
|
||||
@@ -327,11 +313,11 @@ class InstNamer {
|
||||
Namespace labels = {.prefix = "!"};
|
||||
};
|
||||
|
||||
auto GetScopeInfo(ScopeIndex scope_idx) -> Scope& {
|
||||
return scopes[static_cast<int>(scope_idx)];
|
||||
auto GetScopeInfo(ScopeId scope_id) -> Scope& {
|
||||
return scopes[static_cast<int>(scope_id)];
|
||||
}
|
||||
|
||||
auto AddBlockLabel(ScopeIndex scope_idx, InstBlockId block_id,
|
||||
auto AddBlockLabel(ScopeId scope_id, InstBlockId block_id,
|
||||
std::string name = "",
|
||||
Parse::NodeId parse_node = Parse::NodeId::Invalid)
|
||||
-> void {
|
||||
@@ -346,14 +332,14 @@ class InstNamer {
|
||||
}
|
||||
}
|
||||
|
||||
labels[block_id.index] = {scope_idx,
|
||||
GetScopeInfo(scope_idx).labels.AllocateName(
|
||||
*this, parse_node, std::move(name))};
|
||||
labels[block_id.index] = {
|
||||
scope_id, GetScopeInfo(scope_id).labels.AllocateName(*this, parse_node,
|
||||
std::move(name))};
|
||||
}
|
||||
|
||||
// Finds and adds a suitable block label for the given SemIR instruction that
|
||||
// represents some kind of branch.
|
||||
auto AddBlockLabel(ScopeIndex scope_idx, Parse::NodeId parse_node,
|
||||
auto AddBlockLabel(ScopeId scope_id, Parse::NodeId parse_node,
|
||||
AnyBranch branch) -> void {
|
||||
llvm::StringRef name;
|
||||
switch (parse_tree_.node_kind(parse_node)) {
|
||||
@@ -418,18 +404,18 @@ class InstNamer {
|
||||
break;
|
||||
}
|
||||
|
||||
AddBlockLabel(scope_idx, branch.target_id, name.str(), parse_node);
|
||||
AddBlockLabel(scope_id, branch.target_id, name.str(), parse_node);
|
||||
}
|
||||
|
||||
auto CollectNamesInBlock(ScopeIndex scope_idx, InstBlockId block_id) -> void {
|
||||
auto CollectNamesInBlock(ScopeId scope_id, InstBlockId block_id) -> void {
|
||||
if (block_id.is_valid()) {
|
||||
CollectNamesInBlock(scope_idx, sem_ir_.inst_blocks().Get(block_id));
|
||||
CollectNamesInBlock(scope_id, sem_ir_.inst_blocks().Get(block_id));
|
||||
}
|
||||
}
|
||||
|
||||
auto CollectNamesInBlock(ScopeIndex scope_idx, llvm::ArrayRef<InstId> block)
|
||||
auto CollectNamesInBlock(ScopeId scope_id, llvm::ArrayRef<InstId> block)
|
||||
-> void {
|
||||
Scope& scope = GetScopeInfo(scope_idx);
|
||||
Scope& scope = GetScopeInfo(scope_id);
|
||||
|
||||
// Use bound names where available. Otherwise, assign a backup name.
|
||||
for (auto inst_id : block) {
|
||||
@@ -440,8 +426,8 @@ class InstNamer {
|
||||
auto inst = sem_ir_.insts().Get(inst_id);
|
||||
auto add_inst_name = [&](std::string name) {
|
||||
insts[inst_id.index] = {
|
||||
scope_idx, scope.insts.AllocateName(
|
||||
*this, sem_ir_.insts().GetParseNode(inst_id), name)};
|
||||
scope_id, scope.insts.AllocateName(
|
||||
*this, sem_ir_.insts().GetParseNode(inst_id), name)};
|
||||
};
|
||||
auto add_inst_name_id = [&](NameId name_id, llvm::StringRef suffix = "") {
|
||||
add_inst_name(
|
||||
@@ -449,8 +435,7 @@ class InstNamer {
|
||||
};
|
||||
|
||||
if (auto branch = inst.TryAs<AnyBranch>()) {
|
||||
AddBlockLabel(scope_idx, sem_ir_.insts().GetParseNode(inst_id),
|
||||
*branch);
|
||||
AddBlockLabel(scope_id, sem_ir_.insts().GetParseNode(inst_id), *branch);
|
||||
}
|
||||
|
||||
switch (inst.kind()) {
|
||||
@@ -459,11 +444,11 @@ class InstNamer {
|
||||
// function declarations, which may be nested within a pattern. For
|
||||
// now, just look through `addr`, but we should find a better way to
|
||||
// visit parameters.
|
||||
CollectNamesInBlock(scope_idx, inst.As<AddrPattern>().inner_id);
|
||||
CollectNamesInBlock(scope_id, inst.As<AddrPattern>().inner_id);
|
||||
break;
|
||||
}
|
||||
case SpliceBlock::Kind: {
|
||||
CollectNamesInBlock(scope_idx, inst.As<SpliceBlock>().block_id);
|
||||
CollectNamesInBlock(scope_id, inst.As<SpliceBlock>().block_id);
|
||||
break;
|
||||
}
|
||||
case BindName::Kind:
|
||||
@@ -535,8 +520,8 @@ class InstNamer {
|
||||
const File& sem_ir_;
|
||||
|
||||
Namespace globals = {.prefix = "@"};
|
||||
std::vector<std::pair<ScopeIndex, Namespace::Name>> insts;
|
||||
std::vector<std::pair<ScopeIndex, Namespace::Name>> labels;
|
||||
std::vector<std::pair<ScopeId, Namespace::Name>> insts;
|
||||
std::vector<std::pair<ScopeId, Namespace::Name>> labels;
|
||||
std::vector<Scope> scopes;
|
||||
};
|
||||
} // namespace
|
||||
@@ -566,7 +551,7 @@ class Formatter {
|
||||
// blocks. For example, there may be branching in the initializer of a
|
||||
// global or a type expression.
|
||||
if (auto block_id = sem_ir_.top_inst_block_id(); block_id.is_valid()) {
|
||||
llvm::SaveAndRestore file_scope(scope_, InstNamer::ScopeIndex::File);
|
||||
llvm::SaveAndRestore file_scope(scope_, InstNamer::ScopeId::File);
|
||||
FormatCodeBlock(block_id);
|
||||
}
|
||||
out_ << "}\n";
|
||||
@@ -592,8 +577,7 @@ class Formatter {
|
||||
return;
|
||||
}
|
||||
|
||||
llvm::SaveAndRestore constants_scope(scope_,
|
||||
InstNamer::ScopeIndex::Constants);
|
||||
llvm::SaveAndRestore constants_scope(scope_, InstNamer::ScopeId::Constants);
|
||||
out_ << "constants {\n";
|
||||
FormatCodeBlock(sem_ir_.constants().GetAsVector());
|
||||
out_ << "}\n\n";
|
||||
@@ -1115,7 +1099,7 @@ class Formatter {
|
||||
const File& sem_ir_;
|
||||
llvm::raw_ostream& out_;
|
||||
InstNamer inst_namer_;
|
||||
InstNamer::ScopeIndex scope_ = InstNamer::ScopeIndex::None;
|
||||
InstNamer::ScopeId scope_ = InstNamer::ScopeId::None;
|
||||
bool in_terminator_sequence_ = false;
|
||||
int indent_ = 2;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user