| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491 |
- // 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
- #include "toolchain/sem_ir/inst_namer.h"
- #include <string>
- #include <utility>
- #include <variant>
- #include "common/ostream.h"
- #include "common/raw_string_ostream.h"
- #include "llvm/ADT/STLExtras.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/ADT/StableHashing.h"
- #include "toolchain/base/kind_switch.h"
- #include "toolchain/base/shared_value_stores.h"
- #include "toolchain/base/value_ids.h"
- #include "toolchain/lex/tokenized_buffer.h"
- #include "toolchain/parse/tree.h"
- #include "toolchain/sem_ir/cpp_overload_set.h"
- #include "toolchain/sem_ir/entity_with_params_base.h"
- #include "toolchain/sem_ir/function.h"
- #include "toolchain/sem_ir/ids.h"
- #include "toolchain/sem_ir/inst_kind.h"
- #include "toolchain/sem_ir/pattern.h"
- #include "toolchain/sem_ir/singleton_insts.h"
- #include "toolchain/sem_ir/specific_interface.h"
- #include "toolchain/sem_ir/specific_named_constraint.h"
- #include "toolchain/sem_ir/type_info.h"
- #include "toolchain/sem_ir/typed_insts.h"
- namespace Carbon::SemIR {
- class InstNamer::NamingContext {
- public:
- explicit NamingContext(InstNamer* inst_namer, InstNamer::ScopeId scope_id,
- InstId inst_id);
- // Names the single instruction. Use bound names where available. Otherwise,
- // assign a backup name.
- //
- // Insts with a type_id are required to add names; other insts may
- // optionally set a name. All insts may push other insts to be named.
- auto NameInst() -> void;
- private:
- // Adds the instruction's name.
- auto AddInstName(std::string name) -> void;
- // Adds the instruction's name for a StructType, which contains the names of
- // its fields.
- auto AddStructTypeInstName(StructType struct_ty, llvm::StringRef type_suffix,
- llvm::StringRef name_suffix) -> void;
- // Adds the instruction's name by `NameId`.
- auto AddInstNameId(NameId name_id, llvm::StringRef suffix = "") -> void {
- AddInstName((sem_ir().names().GetIRBaseName(name_id) + suffix).str());
- }
- // Names an `IntType` or `FloatType`.
- auto AddIntOrFloatTypeName(char type_literal_prefix, InstId bit_width_id,
- llvm::StringRef suffix = "") -> void;
- // Names an `ImplWitnessTable` instruction.
- auto AddWitnessTableName(InstId witness_table_inst_id, std::string name)
- -> void;
- auto AddBlockLabel(ScopeId scope_id, InstBlockId block_id, std::string name,
- LocId loc_id) -> void {
- inst_namer_->AddBlockLabel(scope_id, block_id, name, loc_id);
- }
- // Pushes all instructions in a generic, by ID.
- auto PushGeneric(ScopeId scope_id, GenericId generic_id) -> void {
- inst_namer_->PushGeneric(scope_id, generic_id);
- }
- // Pushes all instructions in a block, by ID.
- auto PushBlockId(ScopeId scope_id, InstBlockId block_id) -> void {
- inst_namer_->PushBlockId(scope_id, block_id);
- }
- // Names the instruction as an entity. May push processing of the entity.
- template <typename EntityIdT>
- auto AddEntityNameAndMaybePush(EntityIdT id, llvm::StringRef suffix = "")
- -> void {
- AddInstName((inst_namer_->MaybePushEntity(id) + suffix).str());
- }
- auto sem_ir() -> const File& { return *inst_namer_->sem_ir_; }
- InstNamer* inst_namer_;
- ScopeId scope_id_;
- InstId inst_id_;
- Inst inst_;
- };
- InstNamer::InstNamer(const File* sem_ir, int total_ir_count)
- : sem_ir_(sem_ir), fingerprinter_(total_ir_count) {
- insts_.resize(sem_ir->insts().size(), {ScopeId::None, Namespace::Name()});
- labels_.resize(sem_ir->inst_blocks().size());
- scopes_.resize(GetScopeIdOffset(ScopeIdTypeEnum::None));
- generic_scopes_.resize(sem_ir->generics().size(), ScopeId::None);
- // We process the stack between each large block in order to reduce the
- // temporary size of the stack.
- auto process_stack = [&] {
- while (!inst_stack_.empty() || !inst_block_stack_.empty()) {
- if (inst_stack_.empty()) {
- auto [scope_id, block_id] = inst_block_stack_.pop_back_val();
- if (block_id != SemIR::InstBlockId::Empty) {
- PushBlockInsts(scope_id, sem_ir_->inst_blocks().Get(block_id));
- }
- }
- while (!inst_stack_.empty()) {
- auto [scope_id, inst_id] = inst_stack_.pop_back_val();
- NamingContext context(this, scope_id, inst_id);
- context.NameInst();
- }
- }
- };
- // Name each of the top-level scopes, in order. We use these as the roots of
- // walking the IR.
- PushBlockInsts(ScopeId::Constants, sem_ir->constants().array_ref());
- process_stack();
- PushBlockId(ScopeId::Imports, InstBlockId::Imports);
- process_stack();
- PushBlockId(ScopeId::Generated, InstBlockId::Generated);
- process_stack();
- PushBlockId(ScopeId::File, sem_ir->top_inst_block_id());
- process_stack();
- // Global init won't have any other references, so we add it directly.
- if (sem_ir_->global_ctor_id().has_value()) {
- MaybePushEntity(sem_ir_->global_ctor_id());
- process_stack();
- }
- }
- auto InstNamer::GetScopeIdOffset(ScopeIdTypeEnum id_enum) const -> int {
- int offset = 0;
- // For each Id type, add the number of entities *above* its case; for example,
- // the offset for functions excludes the functions themselves. The fallthrough
- // handles summing to get uniqueness; order isn't special.
- switch (id_enum) {
- case ScopeIdTypeEnum::None:
- // `None` will be getting a full count of scopes.
- offset += sem_ir_->associated_constants().size();
- [[fallthrough]];
- case ScopeIdTypeEnum::For<AssociatedConstantId>:
- offset += sem_ir_->classes().size();
- [[fallthrough]];
- case ScopeIdTypeEnum::For<ClassId>:
- offset += sem_ir_->cpp_overload_sets().size();
- [[fallthrough]];
- case ScopeIdTypeEnum::For<CppOverloadSetId>:
- offset += sem_ir_->functions().size();
- [[fallthrough]];
- case ScopeIdTypeEnum::For<FunctionId>:
- offset += sem_ir_->impls().size();
- [[fallthrough]];
- case ScopeIdTypeEnum::For<ImplId>:
- offset += sem_ir_->interfaces().size();
- [[fallthrough]];
- case ScopeIdTypeEnum::For<InterfaceId>:
- offset += sem_ir_->interfaces().size();
- [[fallthrough]];
- case ScopeIdTypeEnum::For<InterfaceWithSelfId>:
- offset += sem_ir_->named_constraints().size();
- [[fallthrough]];
- case ScopeIdTypeEnum::For<NamedConstraintId>:
- offset += sem_ir_->named_constraints().size();
- [[fallthrough]];
- case ScopeIdTypeEnum::For<NamedConstraintWithSelfId>:
- offset += sem_ir_->require_impls().size();
- [[fallthrough]];
- case ScopeIdTypeEnum::For<RequireImplsId>:
- offset += sem_ir_->specific_interfaces().size();
- [[fallthrough]];
- case ScopeIdTypeEnum::For<SpecificInterfaceId>:
- offset += sem_ir_->vtables().size();
- [[fallthrough]];
- case ScopeIdTypeEnum::For<VtableId>:
- // All type-specific scopes are offset by `FirstEntityScope`.
- offset += static_cast<int>(ScopeId::FirstEntityScope);
- return offset;
- default:
- CARBON_FATAL("Unexpected ScopeIdTypeEnum: {0}", id_enum);
- }
- }
- auto InstNamer::GetScopeName(ScopeId scope) const -> std::string {
- switch (scope) {
- case ScopeId::None:
- return "<no scope>";
- // These are treated as SemIR keywords.
- case ScopeId::File:
- return "file";
- case ScopeId::Generated:
- return "generated";
- case ScopeId::Imports:
- return "imports";
- case ScopeId::Constants:
- return "constants";
- // For everything else, use an @ prefix.
- default:
- return ("@" + GetScopeInfo(scope).name.GetFullName()).str();
- }
- }
- auto InstNamer::GetUnscopedNameFor(InstId inst_id) const -> llvm::StringRef {
- if (!inst_id.has_value()) {
- return "";
- }
- if (IsSingletonInstId(inst_id)) {
- return sem_ir_->insts().Get(inst_id).kind().ir_name();
- }
- auto index = sem_ir_->insts().GetRawIndex(inst_id);
- const auto& inst_name = insts_[index].second;
- return inst_name ? inst_name.GetFullName() : "";
- }
- auto InstNamer::GetNameFor(ScopeId scope_id, InstId inst_id) const
- -> std::string {
- if (!inst_id.has_value()) {
- return "invalid";
- }
- // Check for a builtin.
- if (IsSingletonInstId(inst_id)) {
- return sem_ir_->insts().Get(inst_id).kind().ir_name().str();
- }
- if (inst_id == SemIR::Namespace::PackageInstId) {
- return "package";
- }
- auto index = sem_ir_->insts().GetRawIndex(inst_id);
- const auto& [inst_scope, inst_name] = insts_[index];
- if (!inst_name) {
- // This should not happen in valid IR.
- RawStringOstream out;
- out << "<unexpected>." << inst_id;
- auto loc_id = sem_ir_->insts().GetCanonicalLocId(inst_id);
- // TODO: Consider handling other kinds.
- if (loc_id.kind() == LocId::Kind::NodeId) {
- const auto& tree = sem_ir_->parse_tree();
- auto token = tree.node_token(loc_id.node_id());
- out << ".loc" << tree.tokens().GetLineNumber(token) << "_"
- << tree.tokens().GetColumnNumber(token);
- }
- return out.TakeStr();
- }
- if (inst_scope == scope_id) {
- return ("%" + inst_name.GetFullName()).str();
- }
- return (GetScopeName(inst_scope) + ".%" + inst_name.GetFullName()).str();
- }
- auto InstNamer::GetUnscopedLabelFor(InstBlockId block_id) const
- -> llvm::StringRef {
- if (!block_id.has_value()) {
- return "";
- }
- const auto& label_name =
- labels_[sem_ir_->inst_blocks().GetRawIndex(block_id)].second;
- return label_name ? label_name.GetFullName() : "";
- }
- // Returns the IR name to use for a label, when referenced from a given scope.
- auto InstNamer::GetLabelFor(ScopeId scope_id, InstBlockId block_id) const
- -> std::string {
- if (!block_id.has_value()) {
- return "!invalid";
- }
- const auto& [label_scope, label_name] =
- labels_[sem_ir_->inst_blocks().GetRawIndex(block_id)];
- if (!label_name) {
- // This should not happen in valid IR.
- RawStringOstream out;
- out << "<unexpected instblockref " << block_id << ">";
- return out.TakeStr();
- }
- if (label_scope == scope_id) {
- return ("!" + label_name.GetFullName()).str();
- }
- return (GetScopeName(label_scope) + ".!" + label_name.GetFullName()).str();
- }
- auto InstNamer::Namespace::Name::GetFullName() const -> llvm::StringRef {
- if (!value_) {
- return "<null name>";
- }
- llvm::StringMapEntry<NameResult>* value = value_;
- while (value->second.ambiguous && value->second.fallback) {
- value = value->second.fallback.value_;
- }
- return value->first();
- }
- auto InstNamer::Namespace::Name::GetBaseName() const -> llvm::StringRef {
- if (!value_) {
- return "<null name>";
- }
- return value_->first().take_front(base_name_size_);
- }
- auto InstNamer::Namespace::AllocateName(
- const InstNamer& inst_namer,
- std::variant<LocId, uint64_t> loc_id_or_fingerprint, std::string name)
- -> Name {
- // The best (shortest) name for this instruction so far, and the current
- // name for it.
- Name best;
- Name current;
- const size_t base_name_size = name.size();
- // Add `name` as a name for this entity.
- auto add_name = [&](bool mark_ambiguous = true) {
- auto [it, added] = allocated_.insert({name, NameResult()});
- Name new_name = Name(it, base_name_size);
- if (!added) {
- if (mark_ambiguous) {
- // This name was allocated for a different instruction. Mark it as
- // ambiguous and keep looking for a name for this instruction.
- new_name.SetAmbiguous();
- }
- } else {
- if (!best) {
- best = new_name;
- } else {
- CARBON_CHECK(current);
- current.SetFallback(new_name);
- }
- current = new_name;
- }
- return added;
- };
- // Use the given name if it's available.
- if (!name.empty()) {
- add_name();
- }
- // Append location information to try to disambiguate.
- if (auto* loc_id = std::get_if<LocId>(&loc_id_or_fingerprint)) {
- *loc_id = inst_namer.sem_ir_->insts().GetCanonicalLocId(*loc_id);
- // TODO: Consider handling other kinds.
- if (loc_id->kind() == LocId::Kind::NodeId) {
- const auto& tree = inst_namer.sem_ir_->parse_tree();
- auto token = tree.node_token(loc_id->node_id());
- llvm::raw_string_ostream(name)
- << ".loc" << tree.tokens().GetLineNumber(token);
- add_name();
- llvm::raw_string_ostream(name)
- << "_" << tree.tokens().GetColumnNumber(token);
- add_name();
- }
- } else {
- uint64_t fingerprint = std::get<uint64_t>(loc_id_or_fingerprint);
- llvm::raw_string_ostream out(name);
- out << ".";
- // Include names with 3-6 characters from the fingerprint. Then fall back to
- // sequential numbering.
- for (int n : llvm::seq(1, 7)) {
- out.write_hex((fingerprint >> (64 - 4 * n)) & 0xF);
- if (n >= 3) {
- add_name();
- }
- }
- }
- // Append numbers until we find an available name.
- name += ".";
- auto name_size_without_counter = name.size();
- for (int counter = 1;; ++counter) {
- name.resize(name_size_without_counter);
- llvm::raw_string_ostream(name) << counter;
- if (add_name(/*mark_ambiguous=*/false)) {
- return best;
- }
- }
- }
- auto InstNamer::AddBlockLabel(
- ScopeId scope_id, InstBlockId block_id, std::string name,
- std::variant<LocId, uint64_t> loc_id_or_fingerprint) -> void {
- if (!block_id.has_value() ||
- labels_[sem_ir_->inst_blocks().GetRawIndex(block_id)].second) {
- return;
- }
- if (auto* loc_id = std::get_if<LocId>(&loc_id_or_fingerprint);
- loc_id && !loc_id->has_value()) {
- if (const auto& block = sem_ir_->inst_blocks().Get(block_id);
- !block.empty()) {
- loc_id_or_fingerprint = LocId(block.front());
- }
- }
- labels_[sem_ir_->inst_blocks().GetRawIndex(block_id)] = {
- scope_id, GetScopeInfo(scope_id).labels.AllocateName(
- *this, loc_id_or_fingerprint, std::move(name))};
- }
- // Provides names for `AddBlockLabel`.
- struct BranchNames {
- // Returns names for a branching parse node, or nullopt if not a branch.
- static auto For(Parse::NodeKind node_kind) -> std::optional<BranchNames> {
- switch (node_kind) {
- case Parse::NodeKind::ForHeaderStart:
- return {{.prefix = "for", .branch = "next"}};
- case Parse::NodeKind::ForHeader:
- return {{.prefix = "for", .branch_if = "body", .branch = "done"}};
- case Parse::NodeKind::IfExprIf:
- return {{.prefix = "if.expr",
- .branch_if = "then",
- .branch = "else",
- .branch_with_arg = "result"}};
- case Parse::NodeKind::IfCondition:
- return {{.prefix = "if", .branch_if = "then", .branch = "else"}};
- case Parse::NodeKind::IfStatement:
- return {{.prefix = "if", .branch = "done"}};
- case Parse::NodeKind::ShortCircuitOperandAnd:
- return {
- {.prefix = "and", .branch_if = "rhs", .branch_with_arg = "result"}};
- case Parse::NodeKind::ShortCircuitOperandOr:
- return {
- {.prefix = "or", .branch_if = "rhs", .branch_with_arg = "result"}};
- case Parse::NodeKind::WhileConditionStart:
- return {{.prefix = "while", .branch = "cond"}};
- case Parse::NodeKind::WhileCondition:
- return {{.prefix = "while", .branch_if = "body", .branch = "done"}};
- default:
- return std::nullopt;
- }
- }
- // Returns the provided suffix for the instruction kind, or an empty string.
- auto GetSuffix(InstKind inst_kind) -> llvm::StringLiteral {
- switch (inst_kind) {
- case BranchIf::Kind:
- return branch_if;
- case Branch::Kind:
- return branch;
- case BranchWithArg::Kind:
- return branch_with_arg;
- default:
- return "";
- }
- }
- // The kind of branch, based on the node kind.
- llvm::StringLiteral prefix;
- // For labeling branch instruction kinds. Only expected kinds need a value;
- // the empty string is for unexpected kinds.
- llvm::StringLiteral branch_if = "";
- llvm::StringLiteral branch = "";
- llvm::StringLiteral branch_with_arg = "";
- };
- // Finds and adds a suitable block label for the given SemIR instruction that
- // represents some kind of branch.
- auto InstNamer::AddBlockLabel(ScopeId scope_id, LocId loc_id, AnyBranch branch)
- -> void {
- std::string label;
- loc_id = sem_ir_->insts().GetCanonicalLocId(loc_id);
- if (loc_id.node_id().has_value()) {
- if (auto names = BranchNames::For(
- sem_ir_->parse_tree().node_kind(loc_id.node_id()))) {
- if (auto suffix = names->GetSuffix(branch.kind); !suffix.empty()) {
- label = llvm::formatv("{0}.{1}", names->prefix, suffix);
- } else {
- label =
- llvm::formatv("{0}.<unexpected {1}>", names->prefix, branch.kind);
- }
- }
- }
- AddBlockLabel(scope_id, branch.target_id, label, loc_id);
- }
- auto InstNamer::PushBlockId(ScopeId scope_id, InstBlockId block_id) -> void {
- if (block_id.has_value()) {
- inst_block_stack_.push_back({scope_id, block_id});
- }
- }
- auto InstNamer::PushBlockInsts(ScopeId scope_id,
- llvm::ArrayRef<InstId> inst_ids) -> void {
- for (auto inst_id : llvm::reverse(inst_ids)) {
- if (inst_id.has_value() && !IsSingletonInstId(inst_id)) {
- inst_stack_.push_back(std::make_pair(scope_id, inst_id));
- }
- }
- }
- auto InstNamer::PushGeneric(ScopeId scope_id, GenericId generic_id) -> void {
- if (!generic_id.has_value()) {
- return;
- }
- generic_scopes_[sem_ir_->generics().GetRawIndex(generic_id)] = scope_id;
- const auto& generic = sem_ir_->generics().Get(generic_id);
- // Push blocks in reverse order.
- PushBlockId(scope_id, generic.definition_block_id);
- PushBlockId(scope_id, generic.decl_block_id);
- }
- auto InstNamer::PushEntity(AssociatedConstantId associated_constant_id,
- [[maybe_unused]] ScopeId scope_id, Scope& scope)
- -> void {
- const auto& assoc_const =
- sem_ir_->associated_constants().Get(associated_constant_id);
- scope.name = globals_.AllocateName(
- *this, LocId(assoc_const.decl_id),
- sem_ir_->names().GetIRBaseName(assoc_const.name_id).str());
- // The `decl_block_id` is associated with this `scope_id` from the
- // AssociatedConstantDecl instruction handler.
- }
- auto InstNamer::PushEntity(ClassId class_id, ScopeId scope_id, Scope& scope)
- -> void {
- const auto& class_info = sem_ir_->classes().Get(class_id);
- LocId class_loc(class_info.latest_decl_id());
- scope.name = globals_.AllocateName(
- *this, class_loc,
- sem_ir_->names().GetIRBaseName(class_info.name_id).str());
- AddBlockLabel(scope_id, class_info.body_block_id, "class", class_loc);
- PushGeneric(scope_id, class_info.generic_id);
- // Push blocks in reverse order.
- PushBlockId(scope_id, class_info.body_block_id);
- PushBlockId(scope_id, class_info.pattern_block_id);
- }
- auto InstNamer::GetNameForParentNameScope(NameScopeId name_scope_id)
- -> llvm::StringRef {
- if (!name_scope_id.has_value()) {
- return "";
- }
- auto scope_inst =
- sem_ir_->insts().Get(sem_ir_->name_scopes().Get(name_scope_id).inst_id());
- CARBON_KIND_SWITCH(scope_inst) {
- case CARBON_KIND(ClassDecl class_decl): {
- return MaybePushEntity(class_decl.class_id);
- }
- case CARBON_KIND(ImplDecl impl): {
- return MaybePushEntity(impl.impl_id);
- }
- case CARBON_KIND(InterfaceDecl interface): {
- return MaybePushEntity(interface.interface_id);
- }
- case CARBON_KIND(InterfaceWithSelfDecl interface_with_self): {
- return MaybePushEntity(
- InterfaceWithSelfId{interface_with_self.interface_id});
- }
- case CARBON_KIND(NamedConstraintDecl named_constraint): {
- return MaybePushEntity(named_constraint.named_constraint_id);
- }
- case CARBON_KIND(NamedConstraintWithSelfDecl named_constraint_with_self): {
- return MaybePushEntity(NamedConstraintWithSelfId{
- named_constraint_with_self.named_constraint_id});
- }
- case SemIR::Namespace::Kind: {
- // Only prefix type scopes.
- return "";
- }
- default: {
- return "<unsupported scope>";
- }
- }
- }
- auto InstNamer::PushEntity(FunctionId function_id, ScopeId scope_id,
- Scope& scope) -> void {
- const auto& fn = sem_ir_->functions().Get(function_id);
- LocId fn_loc(fn.latest_decl_id());
- auto scope_prefix = GetNameForParentNameScope(fn.parent_scope_id);
- scope.name = globals_.AllocateName(
- *this, fn_loc,
- llvm::formatv("{0}{1}{2}", scope_prefix, scope_prefix.empty() ? "" : ".",
- sem_ir_->names().GetIRBaseName(fn.name_id)));
- if (!fn.body_block_ids.empty()) {
- AddBlockLabel(scope_id, fn.body_block_ids.front(), "entry", fn_loc);
- }
- // Push blocks in reverse order.
- PushGeneric(scope_id, fn.generic_id);
- for (auto block_id : llvm::reverse(fn.body_block_ids)) {
- PushBlockId(scope_id, block_id);
- }
- PushBlockId(scope_id, fn.pattern_block_id);
- PushBlockId(scope_id, fn.call_params_id);
- }
- auto InstNamer::PushEntity(RequireImplsId require_impls_id, ScopeId scope_id,
- Scope& scope) -> void {
- const auto& require = sem_ir_->require_impls().Get(require_impls_id);
- LocId require_loc(require.decl_id);
- auto scope_prefix = GetNameForParentNameScope(require.parent_scope_id);
- llvm::StringRef self_name;
- auto self_const_id =
- sem_ir_->constant_values().GetConstantInstId(require.self_id);
- auto self_index = sem_ir_->insts().GetRawIndex(self_const_id);
- if (IsSingletonInstId(self_const_id)) {
- self_name = sem_ir_->insts().Get(self_const_id).kind().ir_name();
- } else if (const auto& inst_name = insts_[self_index].second) {
- self_name = inst_name.GetBaseName();
- } else {
- self_name = "<unexpected self>";
- }
- llvm::StringRef facet_type_name;
- auto facet_type_const_id =
- sem_ir_->constant_values().GetConstantInstId(require.facet_type_inst_id);
- auto facet_type_index = sem_ir_->insts().GetRawIndex(facet_type_const_id);
- if (IsSingletonInstId(facet_type_const_id)) {
- facet_type_name =
- sem_ir_->insts().Get(facet_type_const_id).kind().ir_name();
- } else if (const auto& inst_name = insts_[facet_type_index].second) {
- facet_type_name = inst_name.GetBaseName();
- } else {
- facet_type_name = "<unexpected facet type>";
- }
- scope.name = globals_.AllocateName(
- *this, require_loc,
- llvm::formatv("{0}{1}{2}.impls.{3}.require", scope_prefix,
- scope_prefix.empty() ? "" : ".", self_name,
- facet_type_name));
- auto decl = sem_ir_->insts().GetAs<SemIR::RequireImplsDecl>(require.decl_id);
- AddBlockLabel(scope_id, decl.decl_block_id, "require", require_loc);
- // Push blocks in reverse order.
- PushGeneric(scope_id, require.generic_id);
- }
- auto InstNamer::PushEntity(CppOverloadSetId cpp_overload_set_id,
- ScopeId /*scope_id*/, Scope& scope) -> void {
- const CppOverloadSet& overload_set =
- sem_ir_->cpp_overload_sets().Get(cpp_overload_set_id);
- uint64_t fingerprint =
- fingerprinter_.GetOrCompute(sem_ir_, cpp_overload_set_id);
- auto scope_prefix = GetNameForParentNameScope(overload_set.parent_scope_id);
- scope.name = globals_.AllocateName(
- *this, fingerprint,
- llvm::formatv("{0}{1}{2}.cpp_overload_set", scope_prefix,
- scope_prefix.empty() ? "" : ".",
- sem_ir_->names().GetIRBaseName(overload_set.name_id)));
- }
- auto InstNamer::PushEntity(ImplId impl_id, ScopeId scope_id, Scope& scope)
- -> void {
- const auto& impl = sem_ir_->impls().Get(impl_id);
- auto impl_fingerprint = fingerprinter_.GetOrCompute(sem_ir_, impl_id);
- llvm::StringRef self_name;
- auto self_const_id =
- sem_ir_->constant_values().GetConstantInstId(impl.self_id);
- auto index = sem_ir_->insts().GetRawIndex(self_const_id);
- if (IsSingletonInstId(self_const_id)) {
- self_name = sem_ir_->insts().Get(self_const_id).kind().ir_name();
- } else if (const auto& inst_name = insts_[index].second) {
- self_name = inst_name.GetBaseName();
- } else {
- self_name = "<unexpected self>";
- }
- llvm::StringRef interface_name;
- if (impl.interface.interface_id.has_value()) {
- interface_name = MaybePushEntity(impl.interface.interface_id);
- } else {
- interface_name = "<error>";
- }
- scope.name = globals_.AllocateName(
- *this, impl_fingerprint,
- llvm::formatv("{0}.as.{1}.impl", self_name, interface_name));
- AddBlockLabel(scope_id, impl.body_block_id, "impl", impl_fingerprint);
- // Push blocks in reverse order.
- PushGeneric(scope_id, impl.generic_id);
- PushBlockId(scope_id, impl.witness_block_id);
- PushBlockId(scope_id, impl.body_block_id);
- PushBlockId(scope_id, impl.pattern_block_id);
- }
- auto InstNamer::PushEntity(InterfaceId interface_id, ScopeId scope_id,
- Scope& scope) -> void {
- const auto& interface = sem_ir_->interfaces().Get(interface_id);
- LocId interface_loc(interface.latest_decl_id());
- auto name = sem_ir_->names().GetIRBaseName(interface.name_id).str();
- scope.name = globals_.AllocateName(*this, interface_loc, name);
- AddBlockLabel(scope_id, interface.body_block_without_self_id, "interface",
- interface_loc);
- // Push blocks in reverse order.
- PushGeneric(scope_id, interface.generic_id);
- PushBlockId(scope_id, interface.body_block_without_self_id);
- PushBlockId(scope_id, interface.pattern_block_id);
- }
- auto InstNamer::PushEntity(InterfaceWithSelfId interface_id, ScopeId scope_id,
- Scope& scope) -> void {
- const auto& interface = sem_ir_->interfaces().Get(interface_id.id);
- LocId interface_loc(interface.latest_decl_id());
- auto name = sem_ir_->names().GetIRBaseName(interface.name_id).str();
- name += ".WithSelf";
- scope.name = globals_.AllocateName(*this, interface_loc, name);
- AddBlockLabel(scope_id, interface.body_block_with_self_id,
- "interface_with_self", interface_loc);
- // Push blocks in reverse order.
- PushGeneric(scope_id, interface.generic_with_self_id);
- PushBlockId(scope_id, interface.body_block_with_self_id);
- }
- auto InstNamer::PushEntity(NamedConstraintId named_constraint_id,
- ScopeId scope_id, Scope& scope) -> void {
- const auto& constraint =
- sem_ir_->named_constraints().Get(named_constraint_id);
- LocId constraint_loc(constraint.latest_decl_id());
- auto name = sem_ir_->names().GetIRBaseName(constraint.name_id).str();
- scope.name = globals_.AllocateName(*this, constraint_loc, name);
- AddBlockLabel(scope_id, constraint.body_block_without_self_id, "constraint",
- constraint_loc);
- // Push blocks in reverse order.
- PushGeneric(scope_id, constraint.generic_id);
- PushBlockId(scope_id, constraint.body_block_without_self_id);
- PushBlockId(scope_id, constraint.pattern_block_id);
- }
- auto InstNamer::PushEntity(NamedConstraintWithSelfId named_constraint_id,
- ScopeId scope_id, Scope& scope) -> void {
- const auto& constraint =
- sem_ir_->named_constraints().Get(named_constraint_id.id);
- LocId constraint_loc(constraint.latest_decl_id());
- auto name = sem_ir_->names().GetIRBaseName(constraint.name_id).str();
- name += ".WithSelf";
- scope.name = globals_.AllocateName(*this, constraint_loc, name);
- AddBlockLabel(scope_id, constraint.body_block_with_self_id,
- "constraint_with_self", constraint_loc);
- // Push blocks in reverse order.
- PushGeneric(scope_id, constraint.generic_with_self_id);
- PushBlockId(scope_id, constraint.body_block_with_self_id);
- }
- auto InstNamer::PushEntity(VtableId vtable_id, ScopeId /*scope_id*/,
- Scope& scope) -> void {
- const auto& vtable = sem_ir_->vtables().Get(vtable_id);
- const auto& class_info = sem_ir_->classes().Get(vtable.class_id);
- LocId vtable_loc(class_info.latest_decl_id());
- scope.name = globals_.AllocateName(
- *this, vtable_loc,
- sem_ir_->names().GetIRBaseName(class_info.name_id).str() + ".vtable");
- // TODO: Add support for generic vtables here and elsewhere.
- // PushGeneric(scope_id, vtable_info.generic_id);
- }
- InstNamer::NamingContext::NamingContext(InstNamer* inst_namer,
- InstNamer::ScopeId scope_id,
- InstId inst_id)
- : inst_namer_(inst_namer),
- scope_id_(scope_id),
- inst_id_(inst_id),
- inst_(sem_ir().insts().Get(inst_id)) {}
- auto InstNamer::NamingContext::AddInstName(std::string name) -> void {
- auto index = sem_ir().insts().GetRawIndex(inst_id_);
- ScopeId old_scope_id = inst_namer_->insts_[index].first;
- if (old_scope_id == ScopeId::None) {
- std::variant<LocId, uint64_t> loc_id_or_fingerprint = LocId::None;
- if (scope_id_ == ScopeId::Constants || scope_id_ == ScopeId::Generated ||
- scope_id_ == ScopeId::Imports) {
- loc_id_or_fingerprint =
- inst_namer_->fingerprinter_.GetOrCompute(&sem_ir(), inst_id_);
- } else {
- loc_id_or_fingerprint = LocId(inst_id_);
- }
- auto scoped_name = inst_namer_->GetScopeInfo(scope_id_).insts.AllocateName(
- *inst_namer_, loc_id_or_fingerprint, std::move(name));
- inst_namer_->insts_[index] = {scope_id_, scoped_name};
- } else {
- CARBON_CHECK(old_scope_id == scope_id_,
- "Attempting to name inst in multiple scopes");
- }
- }
- auto InstNamer::NamingContext::AddStructTypeInstName(
- StructType struct_ty, llvm::StringRef type_suffix,
- llvm::StringRef name_suffix) -> void {
- RawStringOstream out;
- const auto& fields = sem_ir().struct_type_fields().Get(struct_ty.fields_id);
- if (fields.empty()) {
- out << "empty_struct" << type_suffix;
- } else {
- RawStringOstream name;
- name << "struct" << type_suffix;
- for (auto field : fields) {
- name << ".";
- name << sem_ir().names().GetIRBaseName(field.name_id);
- }
- out << name.TakeStr();
- }
- out << name_suffix;
- AddInstName(out.TakeStr());
- }
- auto InstNamer::NamingContext::AddIntOrFloatTypeName(char type_literal_prefix,
- InstId bit_width_id,
- llvm::StringRef suffix)
- -> void {
- RawStringOstream out;
- out << type_literal_prefix;
- if (auto bit_width = sem_ir().insts().TryGetAs<IntValue>(bit_width_id)) {
- out << sem_ir().ints().Get(bit_width->int_id);
- } else {
- out << "N";
- }
- out << suffix;
- AddInstName(out.TakeStr());
- }
- auto InstNamer::NamingContext::AddWitnessTableName(InstId witness_table_inst_id,
- std::string name) -> void {
- auto witness_table =
- sem_ir().insts().TryGetAs<ImplWitnessTable>(witness_table_inst_id);
- if (!witness_table || !witness_table->impl_id.has_value()) {
- // TODO: If `impl_id` is None, the witness comes from a facet value. Can we
- // get the interface names from it? Store the facet value instruction in the
- // table?
- AddInstName(name);
- return;
- }
- const auto& impl = sem_ir().impls().Get(witness_table->impl_id);
- auto name_id = sem_ir().interfaces().Get(impl.interface.interface_id).name_id;
- std::string suffix = llvm::formatv(".{}", name);
- AddInstNameId(name_id, suffix);
- }
- auto InstNamer::NamingContext::NameInst() -> void {
- CARBON_KIND_SWITCH(inst_) {
- case AddrOf::Kind: {
- AddInstName("addr");
- return;
- }
- case ArrayType::Kind: {
- // TODO: Can we figure out the name of the type this is an array of?
- AddInstName("array_type");
- return;
- }
- case CARBON_KIND(AssociatedConstantDecl inst): {
- AddEntityNameAndMaybePush(inst.assoc_const_id);
- PushBlockId(inst_namer_->GetScopeFor(inst.assoc_const_id),
- inst.decl_block_id);
- return;
- }
- case CARBON_KIND(AssociatedEntity inst): {
- RawStringOstream out;
- out << "assoc" << inst.index.index;
- AddInstName(out.TakeStr());
- return;
- }
- case CARBON_KIND(AssociatedEntityType inst): {
- AddEntityNameAndMaybePush(inst.interface_id, ".assoc_type");
- return;
- }
- case CARBON_KIND_ANY(AnyBindingOrExportDecl, inst): {
- AddInstNameId(sem_ir().entity_names().Get(inst.entity_name_id).name_id);
- return;
- }
- case CARBON_KIND_ANY(AnyBindingPattern, inst): {
- auto name_id = NameId::Underscore;
- if (inst.entity_name_id.has_value()) {
- name_id = sem_ir().entity_names().Get(inst.entity_name_id).name_id;
- }
- AddInstNameId(name_id, ".patt");
- return;
- }
- case CARBON_KIND(BoolLiteral inst): {
- if (inst.value.ToBool()) {
- AddInstName("true");
- } else {
- AddInstName("false");
- }
- return;
- }
- case CARBON_KIND(BoundMethod inst): {
- auto type_id = sem_ir().insts().Get(inst.function_decl_id).type_id();
- if (auto fn_ty = sem_ir().types().TryGetAs<FunctionType>(type_id)) {
- AddEntityNameAndMaybePush(fn_ty->function_id, ".bound");
- } else {
- AddInstName("bound_method");
- }
- return;
- }
- case CARBON_KIND_ANY(AnyBranch, branch): {
- inst_namer_->AddBlockLabel(scope_id_, LocId(inst_id_), branch);
- return;
- }
- case CARBON_KIND(Call inst): {
- auto callee = GetCallee(sem_ir(), inst.callee_id);
- if (auto* fn = std::get_if<CalleeFunction>(&callee)) {
- AddEntityNameAndMaybePush(fn->function_id, ".call");
- return;
- }
- AddInstName("");
- return;
- }
- case CARBON_KIND(ClassDecl inst): {
- AddEntityNameAndMaybePush(inst.class_id, ".decl");
- auto class_scope_id = inst_namer_->GetScopeFor(inst.class_id);
- PushBlockId(class_scope_id, inst.decl_block_id);
- return;
- }
- case CARBON_KIND(ClassType inst): {
- if (auto type_info = RecognizedTypeInfo::ForType(sem_ir(), inst);
- type_info.is_valid()) {
- RawStringOstream out;
- if (type_info.PrintLiteral(sem_ir(), out)) {
- AddInstName(out.TakeStr());
- return;
- }
- }
- AddEntityNameAndMaybePush(inst.class_id);
- return;
- }
- case CompleteTypeWitness::Kind: {
- // TODO: Can we figure out the name of the type this is a witness for?
- AddInstName("complete_type");
- return;
- }
- case CARBON_KIND(VtableDecl inst): {
- const auto& vtable = sem_ir().vtables().Get(inst.vtable_id);
- inst_namer_->MaybePushEntity(inst.vtable_id);
- if (inst_namer_->GetScopeFor(vtable.class_id) == scope_id_) {
- inst_namer_->MaybePushEntity(vtable.class_id);
- AddInstName("vtable_decl");
- } else {
- AddEntityNameAndMaybePush(vtable.class_id, ".vtable_decl");
- }
- return;
- }
- case CARBON_KIND(VtablePtr inst): {
- const auto& vtable = sem_ir().vtables().Get(inst.vtable_id);
- inst_namer_->MaybePushEntity(inst.vtable_id);
- AddEntityNameAndMaybePush(vtable.class_id, ".vtable_ptr");
- return;
- }
- case ConstType::Kind: {
- // TODO: Can we figure out the name of the type argument?
- AddInstName("const");
- return;
- }
- case CARBON_KIND(CppTemplateNameType inst): {
- AddInstNameId(sem_ir().entity_names().Get(inst.name_id).name_id, ".type");
- return;
- }
- case CustomWitness::Kind: {
- AddInstName("custom_witness");
- return;
- }
- case CARBON_KIND(ExprPattern inst): {
- for (auto block_id :
- sem_ir().expr_regions().Get(inst.expr_region_id).block_ids) {
- PushBlockId(scope_id_, block_id);
- }
- AddInstName("expr_patt");
- return;
- }
- case CARBON_KIND(FacetAccessType inst): {
- auto name_id = SemIR::NameId::None;
- if (auto name =
- sem_ir().insts().TryGetAs<NameRef>(inst.facet_value_inst_id)) {
- name_id = name->name_id;
- } else if (auto bind = sem_ir().insts().TryGetAs<SymbolicBinding>(
- inst.facet_value_inst_id)) {
- name_id = sem_ir().entity_names().Get(bind->entity_name_id).name_id;
- }
- if (name_id.has_value()) {
- AddInstNameId(name_id, ".as_type");
- } else {
- AddInstName("as_type");
- }
- return;
- }
- case CARBON_KIND(SymbolicBindingType inst): {
- auto bind =
- sem_ir().insts().GetAs<SymbolicBinding>(inst.facet_value_inst_id);
- auto name_id = sem_ir().entity_names().Get(bind.entity_name_id).name_id;
- if (name_id.has_value()) {
- AddInstNameId(name_id, ".binding.as_type");
- } else {
- AddInstName("binding.as_type");
- }
- return;
- }
- case CARBON_KIND(FacetType inst): {
- const auto& facet_type_info =
- sem_ir().facet_types().Get(inst.facet_type_id);
- bool has_where = facet_type_info.other_requirements ||
- !facet_type_info.self_impls_constraints.empty() ||
- !facet_type_info.self_impls_named_constraints.empty() ||
- !facet_type_info.type_impls_interfaces.empty() ||
- !facet_type_info.type_impls_named_constraints.empty() ||
- !facet_type_info.rewrite_constraints.empty();
- if (facet_type_info.extend_constraints.size() == 1 &&
- facet_type_info.extend_named_constraints.empty()) {
- AddEntityNameAndMaybePush(
- facet_type_info.extend_constraints.front().interface_id,
- has_where ? "_where.type" : ".type");
- } else if (facet_type_info.extend_named_constraints.size() == 1 &&
- facet_type_info.extend_constraints.empty()) {
- AddEntityNameAndMaybePush(
- facet_type_info.extend_named_constraints.front()
- .named_constraint_id,
- has_where ? "_where.type" : ".type");
- } else if (facet_type_info.extend_constraints.empty() &&
- facet_type_info.extend_named_constraints.empty()) {
- AddInstName(has_where ? "type_where" : "type");
- } else {
- AddInstName("facet_type");
- }
- return;
- }
- case CARBON_KIND(FacetValue inst): {
- if (auto facet_type =
- sem_ir().types().TryGetAs<FacetType>(inst.type_id)) {
- const auto& facet_type_info =
- sem_ir().facet_types().Get(facet_type->facet_type_id);
- if (auto single = facet_type_info.TryAsSingleExtend()) {
- CARBON_KIND_SWITCH(*single) {
- case CARBON_KIND(SemIR::SpecificInterface interface): {
- AddEntityNameAndMaybePush(interface.interface_id, ".facet");
- break;
- }
- case CARBON_KIND(SemIR::SpecificNamedConstraint constraint): {
- AddEntityNameAndMaybePush(constraint.named_constraint_id,
- ".facet");
- break;
- }
- }
- return;
- }
- if (facet_type_info.HasNoConstraints()) {
- if (auto class_ty =
- sem_ir().insts().TryGetAs<ClassType>(inst.type_inst_id)) {
- AddEntityNameAndMaybePush(class_ty->class_id, ".type.facet");
- return;
- }
- if (auto tuple_ty = sem_ir().insts().TryGetAs<SemIR::TupleType>(
- inst.type_inst_id)) {
- if (tuple_ty->type_elements_id == InstBlockId::Empty) {
- AddInstName("empty_tuple.type.facet");
- } else {
- AddInstName("tuple.type.facet");
- }
- return;
- }
- if (auto struct_ty = sem_ir().insts().TryGetAs<SemIR::StructType>(
- inst.type_inst_id)) {
- AddStructTypeInstName(*struct_ty, "", ".type.facet");
- return;
- }
- }
- }
- AddInstName("facet_value");
- return;
- }
- case CARBON_KIND(FloatType inst): {
- AddIntOrFloatTypeName('f', inst.bit_width_id);
- return;
- }
- case FloatLiteralValue::Kind:
- case FloatValue::Kind: {
- AddInstName("float");
- return;
- }
- case CARBON_KIND(FunctionDecl inst): {
- AddEntityNameAndMaybePush(inst.function_id, ".decl");
- auto function_scope_id = inst_namer_->GetScopeFor(inst.function_id);
- PushBlockId(function_scope_id, inst.decl_block_id);
- return;
- }
- case CARBON_KIND(FunctionType inst): {
- AddEntityNameAndMaybePush(inst.function_id, ".type");
- return;
- }
- case CARBON_KIND(CppOverloadSetValue inst): {
- AddEntityNameAndMaybePush(inst.overload_set_id, ".value");
- return;
- }
- case CARBON_KIND(CppOverloadSetType inst): {
- AddEntityNameAndMaybePush(inst.overload_set_id, ".type");
- return;
- }
- case CARBON_KIND(GenericClassType inst): {
- AddEntityNameAndMaybePush(inst.class_id, ".type");
- return;
- }
- case CARBON_KIND(GenericInterfaceType inst): {
- AddEntityNameAndMaybePush(inst.interface_id, ".type");
- return;
- }
- case CARBON_KIND(GenericNamedConstraintType inst): {
- AddEntityNameAndMaybePush(inst.named_constraint_id, ".type");
- return;
- }
- case CARBON_KIND(ImplDecl inst): {
- // `impl` declarations aren't named because they aren't added to any
- // namespace, and so aren't referenced directly.
- inst_namer_->MaybePushEntity(inst.impl_id);
- PushBlockId(inst_namer_->GetScopeFor(inst.impl_id), inst.decl_block_id);
- return;
- }
- case CARBON_KIND(LookupImplWitness inst): {
- const auto& interface =
- sem_ir().specific_interfaces().Get(inst.query_specific_interface_id);
- AddEntityNameAndMaybePush(interface.interface_id, ".lookup_impl_witness");
- return;
- }
- case CARBON_KIND(ImplWitness inst): {
- AddWitnessTableName(inst.witness_table_id, "impl_witness");
- return;
- }
- case CARBON_KIND(ImplWitnessAccess inst): {
- // TODO: Include information about the impl?
- RawStringOstream out;
- out << "impl.elem" << inst.index.index;
- AddInstName(out.TakeStr());
- return;
- }
- case CARBON_KIND(ImplWitnessAccessSubstituted inst): {
- // TODO: Include information about the impl?
- RawStringOstream out;
- auto access = sem_ir().insts().GetAs<ImplWitnessAccess>(
- inst.impl_witness_access_id);
- out << "impl.elem" << access.index.index << ".subst";
- AddInstName(out.TakeStr());
- return;
- }
- case ImplWitnessAssociatedConstant::Kind: {
- AddInstName("impl_witness_assoc_constant");
- return;
- }
- case ImplWitnessTable::Kind: {
- AddWitnessTableName(inst_id_, "impl_witness_table");
- return;
- }
- case ImportCppDecl::Kind: {
- AddInstName("Cpp.import_cpp");
- return;
- }
- case CARBON_KIND(ImportDecl inst): {
- if (inst.package_id.has_value()) {
- AddInstNameId(inst.package_id, ".import");
- } else {
- AddInstName("default.import");
- }
- return;
- }
- case CARBON_KIND_ANY(AnyImportRef, inst): {
- // Build the base import name: <package>.<entity-name>
- RawStringOstream out;
- auto import_ir_inst =
- sem_ir().import_ir_insts().Get(inst.import_ir_inst_id);
- const auto& import_ir =
- *sem_ir().import_irs().Get(import_ir_inst.ir_id()).sem_ir;
- auto package_id = import_ir.package_id();
- if (auto ident_id = package_id.AsIdentifierId(); ident_id.has_value()) {
- out << import_ir.identifiers().Get(ident_id);
- } else {
- out << package_id.AsSpecialName();
- }
- out << ".";
- // Add entity name if available.
- if (inst.entity_name_id.has_value()) {
- auto name_id = sem_ir().entity_names().Get(inst.entity_name_id).name_id;
- out << sem_ir().names().GetIRBaseName(name_id);
- } else {
- out << "import_ref";
- }
- AddInstName(out.TakeStr());
- // When building import refs, we frequently add instructions without
- // a block. Constants that refer to them need to be separately
- // named.
- auto const_id = sem_ir().constant_values().Get(inst_id_);
- if (const_id.has_value() && const_id.is_concrete()) {
- auto const_inst_id = sem_ir().constant_values().GetInstId(const_id);
- auto index = sem_ir().insts().GetRawIndex(const_inst_id);
- if (!inst_namer_->insts_[index].second) {
- inst_namer_->PushBlockInsts(ScopeId::Imports, const_inst_id);
- }
- }
- return;
- }
- case CARBON_KIND(InstValue inst): {
- inst_namer_->PushBlockInsts(scope_id_, inst.inst_id);
- AddInstName(
- ("inst." + sem_ir().insts().Get(inst.inst_id).kind().ir_name())
- .str());
- return;
- }
- case CARBON_KIND(InterfaceDecl inst): {
- AddEntityNameAndMaybePush(inst.interface_id, ".decl");
- auto interface_scope_id = inst_namer_->GetScopeFor(inst.interface_id);
- PushBlockId(interface_scope_id, inst.decl_block_id);
- return;
- }
- case CARBON_KIND(InterfaceWithSelfDecl inst): {
- AddEntityNameAndMaybePush(InterfaceWithSelfId{inst.interface_id},
- ".decl");
- return;
- }
- case CARBON_KIND(IntType inst): {
- AddIntOrFloatTypeName(inst.int_kind == IntKind::Signed ? 'i' : 'u',
- inst.bit_width_id, ".builtin");
- return;
- }
- case CARBON_KIND(IntValue inst): {
- RawStringOstream out;
- out << "int_" << sem_ir().ints().Get(inst.int_id);
- AddInstName(out.TakeStr());
- return;
- }
- case CARBON_KIND(NameBindingDecl inst): {
- PushBlockId(scope_id_, inst.pattern_block_id);
- return;
- }
- case CARBON_KIND(NamedConstraintDecl inst): {
- AddEntityNameAndMaybePush(inst.named_constraint_id, ".decl");
- auto interface_scope_id =
- inst_namer_->GetScopeFor(inst.named_constraint_id);
- PushBlockId(interface_scope_id, inst.decl_block_id);
- return;
- }
- case CARBON_KIND(NamedConstraintWithSelfDecl inst): {
- AddEntityNameAndMaybePush(
- NamedConstraintWithSelfId{inst.named_constraint_id}, ".decl");
- return;
- }
- case CARBON_KIND(NameRef inst): {
- AddInstNameId(inst.name_id, ".ref");
- return;
- }
- // The namespace is specified here due to the name conflict.
- case CARBON_KIND(SemIR::Namespace inst): {
- AddInstNameId(sem_ir().name_scopes().Get(inst.name_scope_id).name_id());
- return;
- }
- case CARBON_KIND_ANY(AnyParam, inst): {
- AddInstNameId(inst.pretty_name_id, ".param");
- return;
- }
- case OutParamPattern::Kind:
- case RefParamPattern::Kind:
- case ValueParamPattern::Kind:
- case VarParamPattern::Kind: {
- AddInstNameId(GetPrettyNameFromPatternId(sem_ir(), inst_id_),
- ".param_patt");
- return;
- }
- case PatternType::Kind: {
- AddInstName("pattern_type");
- return;
- }
- case PointerType::Kind: {
- AddInstName("ptr");
- return;
- }
- case RequireCompleteType::Kind: {
- AddInstName("require_complete");
- return;
- }
- case CARBON_KIND(RequireImplsDecl inst): {
- AddEntityNameAndMaybePush(inst.require_impls_id, ".decl");
- auto require_scope_id = inst_namer_->GetScopeFor(inst.require_impls_id);
- PushBlockId(require_scope_id, inst.decl_block_id);
- return;
- }
- case ReturnSlotPattern::Kind: {
- AddInstNameId(NameId::ReturnSlot, ".patt");
- return;
- }
- case CARBON_KIND(SpecificFunction inst): {
- auto type_id = sem_ir().insts().Get(inst.callee_id).type_id();
- if (auto fn_ty = sem_ir().types().TryGetAs<FunctionType>(type_id)) {
- AddEntityNameAndMaybePush(fn_ty->function_id, ".specific_fn");
- } else {
- AddInstName("specific_fn");
- }
- return;
- }
- case CARBON_KIND(SpecificImplFunction inst): {
- auto type_id = sem_ir().insts().Get(inst.callee_id).type_id();
- if (auto fn_ty = sem_ir().types().TryGetAs<FunctionType>(type_id)) {
- AddEntityNameAndMaybePush(fn_ty->function_id, ".specific_impl_fn");
- } else {
- AddInstName("specific_impl_fn");
- }
- return;
- }
- case ReturnSlot::Kind: {
- AddInstNameId(NameId::ReturnSlot);
- return;
- }
- case CARBON_KIND(SpliceBlock inst): {
- PushBlockId(scope_id_, inst.block_id);
- AddInstName("");
- return;
- }
- case StringLiteral::Kind: {
- AddInstName("str");
- return;
- }
- case CARBON_KIND(StructType inst): {
- AddStructTypeInstName(inst, "_type", "");
- return;
- }
- case CARBON_KIND(StructValue inst): {
- if (auto fn_ty = sem_ir().types().TryGetAs<FunctionType>(inst.type_id)) {
- AddEntityNameAndMaybePush(fn_ty->function_id);
- } else if (auto class_ty =
- sem_ir().types().TryGetAs<ClassType>(inst.type_id)) {
- AddEntityNameAndMaybePush(class_ty->class_id, ".val");
- } else if (auto generic_class_ty =
- sem_ir().types().TryGetAs<GenericClassType>(
- inst.type_id)) {
- AddEntityNameAndMaybePush(generic_class_ty->class_id, ".generic");
- } else if (auto generic_interface_ty =
- sem_ir().types().TryGetAs<GenericInterfaceType>(
- inst.type_id)) {
- AddInstNameId(sem_ir()
- .interfaces()
- .Get(generic_interface_ty->interface_id)
- .name_id,
- ".generic");
- } else if (auto template_name_ty =
- sem_ir().types().TryGetAs<CppTemplateNameType>(
- inst.type_id)) {
- AddInstNameId(
- sem_ir().entity_names().Get(template_name_ty->name_id).name_id,
- ".template");
- } else {
- if (sem_ir().inst_blocks().Get(inst.elements_id).empty()) {
- AddInstName("empty_struct");
- } else {
- AddInstName("struct");
- }
- }
- return;
- }
- case CARBON_KIND(TupleAccess inst): {
- RawStringOstream out;
- out << "tuple.elem" << inst.index.index;
- AddInstName(out.TakeStr());
- return;
- }
- case CARBON_KIND(TupleType inst): {
- if (inst.type_elements_id == InstBlockId::Empty) {
- AddInstName("empty_tuple.type");
- } else {
- AddInstName("tuple.type");
- }
- return;
- }
- case CARBON_KIND(TupleValue inst): {
- if (sem_ir().types().Is<ArrayType>(inst.type_id)) {
- AddInstName("array");
- } else if (inst.elements_id == InstBlockId::Empty) {
- AddInstName("empty_tuple");
- } else {
- AddInstName("tuple");
- }
- return;
- }
- case CARBON_KIND(TypeLiteral inst): {
- if (auto value_id =
- sem_ir().constant_values().GetConstantInstId(inst.value_id);
- value_id.has_value()) {
- if (auto class_type = sem_ir().insts().TryGetAs<ClassType>(value_id)) {
- if (auto type_info =
- RecognizedTypeInfo::ForType(sem_ir(), *class_type);
- type_info.is_valid()) {
- RawStringOstream out;
- if (type_info.PrintLiteral(sem_ir(), out)) {
- AddInstName(out.TakeStr());
- return;
- }
- }
- }
- }
- AddInstName("");
- return;
- }
- case CARBON_KIND(UnboundElementType inst): {
- if (auto class_ty =
- sem_ir().insts().TryGetAs<ClassType>(inst.class_type_inst_id)) {
- AddEntityNameAndMaybePush(class_ty->class_id, ".elem");
- } else {
- AddInstName("elem_type");
- }
- return;
- }
- case UninitializedValue::Kind: {
- AddInstName("uninit");
- return;
- }
- case VarPattern::Kind: {
- AddInstNameId(GetPrettyNameFromPatternId(sem_ir(), inst_id_),
- ".var_patt");
- return;
- }
- case CARBON_KIND(VarStorage inst): {
- if (inst.pattern_id.has_value()) {
- AddInstNameId(GetPrettyNameFromPatternId(sem_ir(), inst.pattern_id),
- ".var");
- } else {
- AddInstName("var");
- }
- return;
- }
- default: {
- // Sequentially number all remaining values.
- if (inst_.kind().has_type()) {
- AddInstName("");
- }
- return;
- }
- }
- }
- auto InstNamer::has_name(InstId inst_id) const -> bool {
- return static_cast<bool>(
- insts_[sem_ir_->insts().GetRawIndex(inst_id)].second);
- }
- } // namespace Carbon::SemIR
|