| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947 |
- // 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 "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/builtin_function_kind.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/type_info.h"
- #include "toolchain/sem_ir/typed_insts.h"
- namespace Carbon::SemIR {
- InstNamer::InstNamer(const File* sem_ir) : sem_ir_(sem_ir) {
- insts_.resize(sem_ir->insts().size(), {ScopeId::None, Namespace::Name()});
- labels_.resize(sem_ir->inst_blocks().size());
- scopes_.resize(static_cast<size_t>(GetScopeFor(NumberOfScopesTag())));
- generic_scopes_.resize(sem_ir->generics().size(), ScopeId::None);
- // Build the constants scope.
- CollectNamesInBlock(ScopeId::Constants, sem_ir->constants().array_ref());
- // Build the ImportRef scope.
- CollectNamesInBlock(ScopeId::ImportRefs, sem_ir->inst_blocks().Get(
- SemIR::InstBlockId::ImportRefs));
- // Build the file scope.
- CollectNamesInBlock(ScopeId::File, sem_ir->top_inst_block_id());
- // Build each function scope.
- for (auto [i, fn] : llvm::enumerate(sem_ir->functions().array_ref())) {
- FunctionId fn_id(i);
- auto fn_scope = GetScopeFor(fn_id);
- // TODO: Provide a location for the function for use as a
- // disambiguator.
- auto fn_loc = Parse::NodeId::None;
- GetScopeInfo(fn_scope).name = globals_.AllocateName(
- *this, fn_loc, sem_ir->names().GetIRBaseName(fn.name_id).str());
- CollectNamesInBlock(fn_scope, fn.implicit_param_patterns_id);
- CollectNamesInBlock(fn_scope, fn.param_patterns_id);
- if (!fn.body_block_ids.empty()) {
- AddBlockLabel(fn_scope, fn.body_block_ids.front(), "entry", fn_loc);
- }
- for (auto block_id : fn.body_block_ids) {
- CollectNamesInBlock(fn_scope, block_id);
- }
- for (auto block_id : fn.body_block_ids) {
- AddBlockLabel(fn_scope, block_id);
- }
- CollectNamesInGeneric(fn_scope, fn.generic_id);
- }
- // Build each class scope.
- for (auto [i, class_info] : llvm::enumerate(sem_ir->classes().array_ref())) {
- ClassId class_id(i);
- auto class_scope = GetScopeFor(class_id);
- // TODO: Provide a location for the class for use as a disambiguator.
- auto class_loc = Parse::NodeId::None;
- GetScopeInfo(class_scope).name = globals_.AllocateName(
- *this, class_loc,
- sem_ir->names().GetIRBaseName(class_info.name_id).str());
- AddBlockLabel(class_scope, class_info.body_block_id, "class", class_loc);
- CollectNamesInBlock(class_scope, class_info.body_block_id);
- CollectNamesInGeneric(class_scope, class_info.generic_id);
- }
- // Build each interface scope.
- for (auto [i, interface_info] :
- llvm::enumerate(sem_ir->interfaces().array_ref())) {
- InterfaceId interface_id(i);
- auto interface_scope = GetScopeFor(interface_id);
- // TODO: Provide a location for the interface for use as a disambiguator.
- auto interface_loc = Parse::NodeId::None;
- GetScopeInfo(interface_scope).name = globals_.AllocateName(
- *this, interface_loc,
- sem_ir->names().GetIRBaseName(interface_info.name_id).str());
- AddBlockLabel(interface_scope, interface_info.body_block_id, "interface",
- interface_loc);
- CollectNamesInBlock(interface_scope, interface_info.body_block_id);
- CollectNamesInGeneric(interface_scope, interface_info.generic_id);
- }
- // Build each associated constant scope.
- for (auto [i, assoc_const_info] :
- llvm::enumerate(sem_ir->associated_constants().array_ref())) {
- AssociatedConstantId assoc_const_id(i);
- auto assoc_const_scope = GetScopeFor(assoc_const_id);
- auto assoc_const_loc = sem_ir->insts().GetLocId(assoc_const_info.decl_id);
- GetScopeInfo(assoc_const_scope).name = globals_.AllocateName(
- *this, assoc_const_loc,
- sem_ir->names().GetIRBaseName(assoc_const_info.name_id).str());
- CollectNamesInGeneric(assoc_const_scope, assoc_const_info.generic_id);
- }
- // Build each impl scope.
- for (auto [i, impl_info] : llvm::enumerate(sem_ir->impls().array_ref())) {
- ImplId impl_id(i);
- auto impl_scope = GetScopeFor(impl_id);
- // TODO: Provide a location for the impl for use as a disambiguator.
- auto impl_loc = Parse::NodeId::None;
- // TODO: Invent a name based on the self and constraint types.
- GetScopeInfo(impl_scope).name =
- globals_.AllocateName(*this, impl_loc, "impl");
- AddBlockLabel(impl_scope, impl_info.body_block_id, "impl", impl_loc);
- CollectNamesInBlock(impl_scope, impl_info.body_block_id);
- CollectNamesInGeneric(impl_scope, impl_info.generic_id);
- }
- }
- 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::ImportRefs:
- return "imports";
- case ScopeId::Constants:
- return "constants";
- // For everything else, use an @ prefix.
- default:
- return ("@" + GetScopeInfo(scope).name.str()).str();
- }
- }
- auto InstNamer::GetUnscopedNameFor(InstId inst_id) const -> llvm::StringRef {
- if (!inst_id.has_value()) {
- return "";
- }
- const auto& inst_name = insts_[inst_id.index].second;
- return inst_name ? inst_name.str() : "";
- }
- auto InstNamer::GetNameFor(ScopeId scope_id, InstId inst_id) const
- -> std::string {
- if (!inst_id.has_value()) {
- return "invalid";
- }
- // Check for a builtin.
- if (SemIR::IsSingletonInstId(inst_id)) {
- return sem_ir_->insts().Get(inst_id).kind().ir_name().str();
- }
- if (inst_id == SemIR::Namespace::PackageInstId) {
- return "package";
- }
- const auto& [inst_scope, inst_name] = insts_[inst_id.index];
- if (!inst_name) {
- // This should not happen in valid IR.
- RawStringOstream out;
- out << "<unexpected>." << inst_id;
- auto loc_id = sem_ir_->insts().GetLocId(inst_id);
- // TODO: Consider handling inst_id cases.
- if (loc_id.is_node_id()) {
- 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.str()).str();
- }
- return (GetScopeName(inst_scope) + ".%" + inst_name.str()).str();
- }
- auto InstNamer::GetUnscopedLabelFor(InstBlockId block_id) const
- -> llvm::StringRef {
- if (!block_id.has_value()) {
- return "";
- }
- const auto& label_name = labels_[block_id.index].second;
- return label_name ? label_name.str() : "";
- }
- // 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_[block_id.index];
- 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.str()).str();
- }
- return (GetScopeName(label_scope) + ".!" + label_name.str()).str();
- }
- auto InstNamer::Namespace::Name::str() const -> llvm::StringRef {
- llvm::StringMapEntry<NameResult>* value = value_;
- CARBON_CHECK(value, "cannot print a null name");
- while (value->second.ambiguous && value->second.fallback) {
- value = value->second.fallback.value_;
- }
- return value->first();
- }
- auto InstNamer::Namespace::AllocateName(
- const InstNamer& inst_namer,
- std::variant<SemIR::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;
- // 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);
- 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.
- // TODO: Consider handling inst_id cases.
- if (auto* loc_id = std::get_if<LocId>(&loc_id_or_fingerprint)) {
- if (loc_id->is_node_id()) {
- 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, SemIR::LocId loc_id) -> void {
- if (!block_id.has_value() || labels_[block_id.index].second) {
- return;
- }
- if (!loc_id.has_value()) {
- if (const auto& block = sem_ir_->inst_blocks().Get(block_id);
- !block.empty()) {
- loc_id = sem_ir_->insts().GetLocId(block.front());
- }
- }
- labels_[block_id.index] = {
- scope_id, GetScopeInfo(scope_id).labels.AllocateName(*this, loc_id,
- std::move(name))};
- }
- // Finds and adds a suitable block label for the given SemIR instruction that
- // represents some kind of branch.
- auto InstNamer::AddBlockLabel(ScopeId scope_id, SemIR::LocId loc_id,
- AnyBranch branch) -> void {
- if (!loc_id.node_id().has_value()) {
- AddBlockLabel(scope_id, branch.target_id, "", loc_id);
- return;
- }
- llvm::StringRef name;
- switch (sem_ir_->parse_tree().node_kind(loc_id.node_id())) {
- case Parse::NodeKind::IfExprIf:
- switch (branch.kind) {
- case BranchIf::Kind:
- name = "if.expr.then";
- break;
- case Branch::Kind:
- name = "if.expr.else";
- break;
- case BranchWithArg::Kind:
- name = "if.expr.result";
- break;
- default:
- break;
- }
- break;
- case Parse::NodeKind::IfCondition:
- switch (branch.kind) {
- case BranchIf::Kind:
- name = "if.then";
- break;
- case Branch::Kind:
- name = "if.else";
- break;
- default:
- break;
- }
- break;
- case Parse::NodeKind::IfStatement:
- name = "if.done";
- break;
- case Parse::NodeKind::ShortCircuitOperandAnd:
- name = branch.kind == BranchIf::Kind ? "and.rhs" : "and.result";
- break;
- case Parse::NodeKind::ShortCircuitOperandOr:
- name = branch.kind == BranchIf::Kind ? "or.rhs" : "or.result";
- break;
- case Parse::NodeKind::WhileConditionStart:
- name = "while.cond";
- break;
- case Parse::NodeKind::WhileCondition:
- switch (branch.kind) {
- case BranchIf::Kind:
- name = "while.body";
- break;
- case Branch::Kind:
- name = "while.done";
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- AddBlockLabel(scope_id, branch.target_id, name.str(), loc_id);
- }
- auto InstNamer::CollectNamesInBlock(ScopeId scope_id, InstBlockId block_id)
- -> void {
- if (block_id.has_value()) {
- CollectNamesInBlock(scope_id, sem_ir_->inst_blocks().Get(block_id));
- }
- }
- auto InstNamer::CollectNamesInBlock(ScopeId top_scope_id,
- llvm::ArrayRef<InstId> block) -> void {
- llvm::SmallVector<std::pair<ScopeId, InstId>> insts;
- // Adds a scope and instructions to walk. Avoids recursion while allowing
- // the loop to below add more instructions during iteration. The new
- // instructions are queued such that they will be the next to be walked.
- // Internally that means they are reversed and added to the end of the vector,
- // since we pop from the back of the vector.
- auto queue_block_insts = [&](ScopeId scope_id,
- llvm::ArrayRef<InstId> inst_ids) {
- for (auto inst_id : llvm::reverse(inst_ids)) {
- if (inst_id.has_value()) {
- insts.push_back(std::make_pair(scope_id, inst_id));
- }
- }
- };
- auto queue_block_id = [&](ScopeId scope_id, InstBlockId block_id) {
- if (block_id.has_value()) {
- queue_block_insts(scope_id, sem_ir_->inst_blocks().Get(block_id));
- }
- };
- queue_block_insts(top_scope_id, block);
- // Use bound names where available. Otherwise, assign a backup name.
- while (!insts.empty()) {
- auto [scope_id, inst_id] = insts.pop_back_val();
- Scope& scope = GetScopeInfo(scope_id);
- auto untyped_inst = sem_ir_->insts().Get(inst_id);
- auto add_inst_name = [&](std::string name) {
- ScopeId old_scope_id = insts_[inst_id.index].first;
- if (old_scope_id == ScopeId::None) {
- std::variant<SemIR::LocId, uint64_t> loc_id_or_fingerprint =
- SemIR::LocId::None;
- if (scope_id == ScopeId::Constants || scope_id == ScopeId::ImportRefs) {
- loc_id_or_fingerprint = fingerprinter_.GetOrCompute(sem_ir_, inst_id);
- } else {
- loc_id_or_fingerprint = sem_ir_->insts().GetLocId(inst_id);
- }
- insts_[inst_id.index] = {
- scope_id,
- scope.insts.AllocateName(*this, loc_id_or_fingerprint, name)};
- } else {
- CARBON_CHECK(old_scope_id == scope_id,
- "Attempting to name inst in multiple scopes");
- }
- };
- auto add_inst_name_id = [&](NameId name_id, llvm::StringRef suffix = "") {
- add_inst_name(
- (sem_ir_->names().GetIRBaseName(name_id).str() + suffix).str());
- };
- auto add_int_or_float_type_name = [&](char type_literal_prefix,
- SemIR::InstId bit_width_id,
- llvm::StringRef suffix = "") {
- 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;
- add_inst_name(out.TakeStr());
- };
- auto facet_access_name_id = [&](InstId facet_value_inst_id) -> NameId {
- if (auto name = sem_ir_->insts().TryGetAs<NameRef>(facet_value_inst_id)) {
- return name->name_id;
- } else if (auto symbolic = sem_ir_->insts().TryGetAs<BindSymbolicName>(
- facet_value_inst_id)) {
- return sem_ir_->entity_names().Get(symbolic->entity_name_id).name_id;
- }
- return NameId::None;
- };
- if (auto branch = untyped_inst.TryAs<AnyBranch>()) {
- AddBlockLabel(scope_id, sem_ir_->insts().GetLocId(inst_id), *branch);
- }
- CARBON_KIND_SWITCH(untyped_inst) {
- case AddrOf::Kind: {
- add_inst_name("addr");
- continue;
- }
- case ArrayType::Kind: {
- // TODO: Can we figure out the name of the type this is an array of?
- add_inst_name("array_type");
- continue;
- }
- case CARBON_KIND(AssociatedConstantDecl inst): {
- add_inst_name_id(
- sem_ir_->associated_constants().Get(inst.assoc_const_id).name_id);
- queue_block_id(GetScopeFor(inst.assoc_const_id), inst.decl_block_id);
- continue;
- }
- case CARBON_KIND(AssociatedEntity inst): {
- RawStringOstream out;
- out << "assoc" << inst.index.index;
- add_inst_name(out.TakeStr());
- continue;
- }
- case CARBON_KIND(AssociatedEntityType inst): {
- auto facet_type =
- sem_ir_->types().TryGetAs<FacetType>(inst.interface_type_id);
- if (!facet_type) {
- // Should never happen, but we don't want the instruction namer to
- // crash on bad IR.
- add_inst_name("<invalid interface>");
- continue;
- }
- const auto& facet_type_info =
- sem_ir_->facet_types().Get(facet_type->facet_type_id);
- auto interface = facet_type_info.TryAsSingleInterface();
- if (!interface) {
- // Should never happen, but we don't want the instruction namer to
- // crash on bad IR.
- add_inst_name("<invalid interface>");
- continue;
- }
- const auto& interface_info =
- sem_ir_->interfaces().Get(interface->interface_id);
- add_inst_name_id(interface_info.name_id, ".assoc_type");
- continue;
- }
- case BindAlias::Kind:
- case BindName::Kind:
- case BindSymbolicName::Kind:
- case ExportDecl::Kind: {
- auto inst = untyped_inst.As<AnyBindNameOrExportDecl>();
- add_inst_name_id(
- sem_ir_->entity_names().Get(inst.entity_name_id).name_id);
- continue;
- }
- case BindingPattern::Kind:
- case SymbolicBindingPattern::Kind: {
- auto inst = untyped_inst.As<AnyBindingPattern>();
- add_inst_name_id(
- sem_ir_->entity_names().Get(inst.entity_name_id).name_id, ".patt");
- continue;
- }
- case CARBON_KIND(BoolLiteral inst): {
- if (inst.value.ToBool()) {
- add_inst_name("true");
- } else {
- add_inst_name("false");
- }
- continue;
- }
- 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)) {
- add_inst_name_id(sem_ir_->functions().Get(fn_ty->function_id).name_id,
- ".bound");
- } else {
- add_inst_name("bound_method");
- }
- continue;
- }
- case CARBON_KIND(Call inst): {
- auto callee_function =
- SemIR::GetCalleeFunction(*sem_ir_, inst.callee_id);
- if (!callee_function.function_id.has_value()) {
- break;
- }
- const auto& function =
- sem_ir_->functions().Get(callee_function.function_id);
- // Name the call's result based on the callee.
- if (function.builtin_function_kind !=
- SemIR::BuiltinFunctionKind::None) {
- // For a builtin, use the builtin name. Otherwise, we'd typically pick
- // the name `Op` below, which is probably not very useful.
- add_inst_name(function.builtin_function_kind.name().str());
- continue;
- }
- add_inst_name_id(function.name_id, ".call");
- continue;
- }
- case CARBON_KIND(ClassDecl inst): {
- const auto& class_info = sem_ir_->classes().Get(inst.class_id);
- add_inst_name_id(class_info.name_id, ".decl");
- auto class_scope_id = GetScopeFor(inst.class_id);
- queue_block_id(class_scope_id, class_info.pattern_block_id);
- queue_block_id(class_scope_id, inst.decl_block_id);
- continue;
- }
- case CARBON_KIND(ClassType inst): {
- if (auto literal_info = NumericTypeLiteralInfo::ForType(*sem_ir_, inst);
- literal_info.is_valid()) {
- add_inst_name(literal_info.GetLiteralAsString(*sem_ir_));
- break;
- }
- add_inst_name_id(sem_ir_->classes().Get(inst.class_id).name_id);
- continue;
- }
- case CompleteTypeWitness::Kind: {
- // TODO: Can we figure out the name of the type this is a witness for?
- add_inst_name("complete_type");
- continue;
- }
- case ConstType::Kind: {
- // TODO: Can we figure out the name of the type argument?
- add_inst_name("const");
- continue;
- }
- case CARBON_KIND(FacetAccessType inst): {
- auto name_id = facet_access_name_id(inst.facet_value_inst_id);
- if (name_id.has_value()) {
- add_inst_name_id(name_id, ".as_type");
- } else {
- add_inst_name("as_type");
- }
- continue;
- }
- case CARBON_KIND(FacetAccessWitness inst): {
- auto name_id = facet_access_name_id(inst.facet_value_inst_id);
- if (name_id.has_value()) {
- add_inst_name_id(name_id, ".as_wit");
- } else {
- add_inst_name("as_wit");
- }
- continue;
- }
- 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.rewrite_constraints.empty();
- if (auto interface = facet_type_info.TryAsSingleInterface()) {
- const auto& interface_info =
- sem_ir_->interfaces().Get(interface->interface_id);
- add_inst_name_id(interface_info.name_id,
- has_where ? "_where.type" : ".type");
- } else if (facet_type_info.impls_constraints.empty()) {
- add_inst_name(has_where ? "type_where" : "type");
- } else {
- add_inst_name("facet_type");
- }
- continue;
- }
- 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 interface = facet_type_info.TryAsSingleInterface()) {
- const auto& interface_info =
- sem_ir_->interfaces().Get(interface->interface_id);
- add_inst_name_id(interface_info.name_id, ".facet");
- continue;
- }
- }
- add_inst_name("facet_value");
- continue;
- }
- case FloatLiteral::Kind: {
- add_inst_name("float");
- continue;
- }
- case CARBON_KIND(FloatType inst): {
- add_int_or_float_type_name('f', inst.bit_width_id);
- continue;
- }
- case CARBON_KIND(FunctionDecl inst): {
- const auto& function_info = sem_ir_->functions().Get(inst.function_id);
- add_inst_name_id(function_info.name_id, ".decl");
- auto function_scope_id = GetScopeFor(inst.function_id);
- queue_block_id(function_scope_id, function_info.pattern_block_id);
- queue_block_id(function_scope_id, inst.decl_block_id);
- continue;
- }
- case CARBON_KIND(FunctionType inst): {
- add_inst_name_id(sem_ir_->functions().Get(inst.function_id).name_id,
- ".type");
- continue;
- }
- case CARBON_KIND(GenericClassType inst): {
- add_inst_name_id(sem_ir_->classes().Get(inst.class_id).name_id,
- ".type");
- continue;
- }
- case CARBON_KIND(GenericInterfaceType inst): {
- add_inst_name_id(sem_ir_->interfaces().Get(inst.interface_id).name_id,
- ".type");
- continue;
- }
- case CARBON_KIND(ImplDecl inst): {
- auto impl_scope_id = GetScopeFor(inst.impl_id);
- queue_block_id(impl_scope_id,
- sem_ir_->impls().Get(inst.impl_id).pattern_block_id);
- queue_block_id(impl_scope_id, inst.decl_block_id);
- break;
- }
- case ImplWitness::Kind: {
- // TODO: Include name of interface (is this available from the
- // specific?).
- add_inst_name("impl_witness");
- continue;
- }
- case CARBON_KIND(ImplWitnessAccess inst): {
- // TODO: Include information about the impl?
- RawStringOstream out;
- out << "impl.elem" << inst.index.index;
- add_inst_name(out.TakeStr());
- continue;
- }
- case CARBON_KIND(ImportDecl inst): {
- if (inst.package_id.has_value()) {
- add_inst_name_id(inst.package_id, ".import");
- } else {
- add_inst_name("default.import");
- }
- continue;
- }
- case ImportRefUnloaded::Kind:
- case ImportRefLoaded::Kind: {
- // Build the base import name: <package>.<entity-name>
- RawStringOstream out;
- auto inst = untyped_inst.As<AnyImportRef>();
- 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;
- if (import_ir.package_id().has_value()) {
- out << import_ir.identifiers().Get(import_ir.package_id());
- } else {
- out << "Main";
- }
- 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";
- }
- add_inst_name(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_template()) {
- auto const_inst_id = sem_ir_->constant_values().GetInstId(const_id);
- if (!insts_[const_inst_id.index].second) {
- queue_block_insts(ScopeId::ImportRefs,
- llvm::ArrayRef(const_inst_id));
- }
- }
- continue;
- }
- case CARBON_KIND(InterfaceDecl inst): {
- const auto& interface_info =
- sem_ir_->interfaces().Get(inst.interface_id);
- add_inst_name_id(interface_info.name_id, ".decl");
- auto interface_scope_id = GetScopeFor(inst.interface_id);
- queue_block_id(interface_scope_id, interface_info.pattern_block_id);
- queue_block_id(interface_scope_id, inst.decl_block_id);
- continue;
- }
- case CARBON_KIND(IntType inst): {
- add_int_or_float_type_name(inst.int_kind == IntKind::Signed ? 'i' : 'u',
- inst.bit_width_id, ".builtin");
- continue;
- }
- case CARBON_KIND(IntValue inst): {
- RawStringOstream out;
- out << "int_" << sem_ir_->ints().Get(inst.int_id);
- add_inst_name(out.TakeStr());
- continue;
- }
- case CARBON_KIND(NameBindingDecl inst): {
- queue_block_id(scope_id, inst.pattern_block_id);
- continue;
- }
- case CARBON_KIND(NameRef inst): {
- add_inst_name_id(inst.name_id, ".ref");
- continue;
- }
- // The namespace is specified here due to the name conflict.
- case CARBON_KIND(SemIR::Namespace inst): {
- add_inst_name_id(
- sem_ir_->name_scopes().Get(inst.name_scope_id).name_id());
- continue;
- }
- case OutParam::Kind:
- case ValueParam::Kind: {
- add_inst_name_id(untyped_inst.As<AnyParam>().pretty_name_id, ".param");
- continue;
- }
- case OutParamPattern::Kind:
- case ValueParamPattern::Kind: {
- add_inst_name_id(
- SemIR::Function::GetNameFromPatternId(*sem_ir_, inst_id),
- ".param_patt");
- continue;
- }
- case PointerType::Kind: {
- add_inst_name("ptr");
- continue;
- }
- case RequireCompleteType::Kind: {
- add_inst_name("require_complete");
- continue;
- }
- case ReturnSlotPattern::Kind: {
- add_inst_name_id(NameId::ReturnSlot, ".patt");
- continue;
- }
- case CARBON_KIND(SpecificFunction inst): {
- InstId callee_id = inst.callee_id;
- if (auto method = sem_ir_->insts().TryGetAs<BoundMethod>(callee_id)) {
- callee_id = method->function_decl_id;
- }
- auto type_id = sem_ir_->insts().Get(callee_id).type_id();
- if (auto fn_ty = sem_ir_->types().TryGetAs<FunctionType>(type_id)) {
- add_inst_name_id(sem_ir_->functions().Get(fn_ty->function_id).name_id,
- ".specific_fn");
- } else {
- add_inst_name("specific_fn");
- }
- continue;
- }
- case ReturnSlot::Kind: {
- add_inst_name_id(NameId::ReturnSlot);
- break;
- }
- case CARBON_KIND(SpliceBlock inst): {
- queue_block_id(scope_id, inst.block_id);
- break;
- }
- case StringLiteral::Kind: {
- add_inst_name("str");
- continue;
- }
- case CARBON_KIND(StructValue inst): {
- if (auto fn_ty =
- sem_ir_->types().TryGetAs<FunctionType>(inst.type_id)) {
- add_inst_name_id(
- sem_ir_->functions().Get(fn_ty->function_id).name_id);
- } else if (auto class_ty =
- sem_ir_->types().TryGetAs<ClassType>(inst.type_id)) {
- add_inst_name_id(sem_ir_->classes().Get(class_ty->class_id).name_id,
- ".val");
- } else if (auto generic_class_ty =
- sem_ir_->types().TryGetAs<GenericClassType>(
- inst.type_id)) {
- add_inst_name_id(
- sem_ir_->classes().Get(generic_class_ty->class_id).name_id,
- ".generic");
- } else if (auto generic_interface_ty =
- sem_ir_->types().TryGetAs<GenericInterfaceType>(
- inst.type_id)) {
- add_inst_name_id(sem_ir_->interfaces()
- .Get(generic_interface_ty->interface_id)
- .name_id,
- ".generic");
- } else {
- if (sem_ir_->inst_blocks().Get(inst.elements_id).empty()) {
- add_inst_name("empty_struct");
- } else {
- add_inst_name("struct");
- }
- }
- continue;
- }
- case CARBON_KIND(StructType inst): {
- const auto& fields = sem_ir_->struct_type_fields().Get(inst.fields_id);
- if (fields.empty()) {
- add_inst_name("empty_struct_type");
- continue;
- }
- std::string name = "struct_type";
- for (auto field : fields) {
- name += ".";
- name += sem_ir_->names().GetIRBaseName(field.name_id).str();
- }
- add_inst_name(std::move(name));
- continue;
- }
- case CARBON_KIND(TupleAccess inst): {
- RawStringOstream out;
- out << "tuple.elem" << inst.index.index;
- add_inst_name(out.TakeStr());
- continue;
- }
- case CARBON_KIND(TupleType inst): {
- if (inst.elements_id == TypeBlockId::Empty) {
- add_inst_name("empty_tuple.type");
- } else {
- add_inst_name("tuple.type");
- }
- continue;
- }
- case CARBON_KIND(TupleValue inst): {
- if (sem_ir_->types().Is<ArrayType>(inst.type_id)) {
- add_inst_name("array");
- } else if (inst.elements_id == InstBlockId::Empty) {
- add_inst_name("empty_tuple");
- } else {
- add_inst_name("tuple");
- }
- continue;
- }
- case CARBON_KIND(UnboundElementType inst): {
- if (auto class_ty =
- sem_ir_->types().TryGetAs<ClassType>(inst.class_type_id)) {
- add_inst_name_id(sem_ir_->classes().Get(class_ty->class_id).name_id,
- ".elem");
- } else {
- add_inst_name("elem_type");
- }
- continue;
- }
- case CARBON_KIND(VarStorage inst): {
- add_inst_name_id(inst.pretty_name_id, ".var");
- continue;
- }
- default: {
- break;
- }
- }
- // Sequentially number all remaining values.
- if (untyped_inst.kind().value_kind() != InstValueKind::None) {
- add_inst_name("");
- }
- }
- }
- auto InstNamer::CollectNamesInGeneric(ScopeId scope_id, GenericId generic_id)
- -> void {
- if (!generic_id.has_value()) {
- return;
- }
- generic_scopes_[generic_id.index] = scope_id;
- const auto& generic = sem_ir_->generics().Get(generic_id);
- CollectNamesInBlock(scope_id, generic.decl_block_id);
- CollectNamesInBlock(scope_id, generic.definition_block_id);
- }
- } // namespace Carbon::SemIR
|