From df6a5a50dc2870f604842a7b88de38166556d572 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Sun, 26 Apr 2026 09:21:07 -0700 Subject: [PATCH] Remove the `Dump` method from `Printable` (#7118) Because this is an `__attribute__((used))` method in a templated base class it forces a _huge_ amount of template instantiation in every translation unit. Often this was just printing the members of the type, which is still useful in some cases (such as test output), but adds no value in the debugger. A more successful pattern for dumping has been namespace level functions, and particularly static ones that more transparently don't expand the non-debugger API surface. Add the few missing functions there that cover `Printable` types with more interesting contents. For several of these, it just gives us a "dump the whole thing" function as a compliment to "dump this entity in the thing". These probably aren't especially high value, but moving them here they become cheap, so I've left them in. For a couple, this expands the rich dumping support of SemIR constructs, which should be substantially more useful than the previous `Dump` behavior. This reduces `check` cumulative object file size by another 14%. Assisted-by: Antigravity with Gemini --- common/ostream.h | 8 ------ toolchain/lex/dump.cpp | 5 ++++ toolchain/parse/dump.cpp | 4 +++ toolchain/sem_ir/dump.cpp | 58 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 8 deletions(-) diff --git a/common/ostream.h b/common/ostream.h index 4ee984becdb4..d9fd397bacbc 100644 --- a/common/ostream.h +++ b/common/ostream.h @@ -22,14 +22,6 @@ namespace Carbon { template // NOLINTNEXTLINE(bugprone-crtp-constructor-accessibility) class Printable { - // Provides simple printing for debuggers. - LLVM_DUMP_METHOD auto Dump() const -> std::string { - std::string buffer; - llvm::raw_string_ostream stream(buffer); - static_cast(this)->Print(stream); - return buffer; - } - // Supports printing to llvm::raw_ostream. friend auto operator<<(llvm::raw_ostream& out, const DerivedT& obj) -> llvm::raw_ostream& { diff --git a/toolchain/lex/dump.cpp b/toolchain/lex/dump.cpp index ebb6d8616214..e386afa9263f 100644 --- a/toolchain/lex/dump.cpp +++ b/toolchain/lex/dump.cpp @@ -12,6 +12,11 @@ namespace Carbon::Lex { +static LLVM_DUMP_METHOD auto Dump(const TokenizedBuffer& tokens) + -> std::string { + return PrintToString(tokens); +} + LLVM_DUMP_METHOD auto Dump(const TokenizedBuffer& tokens, TokenIndex token) -> std::string { RawStringOstream out; diff --git a/toolchain/parse/dump.cpp b/toolchain/parse/dump.cpp index 5ddc0cf91a38..acf2537b1526 100644 --- a/toolchain/parse/dump.cpp +++ b/toolchain/parse/dump.cpp @@ -14,6 +14,10 @@ namespace Carbon::Parse { +static LLVM_DUMP_METHOD auto Dump(const Tree& tree) -> std::string { + return PrintToString(tree); +} + LLVM_DUMP_METHOD auto Dump(const Tree& tree, Lex::TokenIndex token) -> std::string { return Lex::Dump(tree.tokens(), token); diff --git a/toolchain/sem_ir/dump.cpp b/toolchain/sem_ir/dump.cpp index bbd4c8d05e96..fdf3d15c3500 100644 --- a/toolchain/sem_ir/dump.cpp +++ b/toolchain/sem_ir/dump.cpp @@ -10,11 +10,17 @@ #include "common/raw_string_ostream.h" #include "toolchain/sem_ir/ids.h" +#include "toolchain/sem_ir/inst.h" +#include "toolchain/sem_ir/name_scope.h" #include "toolchain/sem_ir/stringify.h" #include "toolchain/sem_ir/typed_insts.h" namespace Carbon::SemIR { +static LLVM_DUMP_METHOD auto Dump(const File& file) -> std::string { + return PrintToString(file); +} + static auto DumpNameIfValid(const File& file, NameId name_id) -> std::string { RawStringOstream out; if (name_id.has_value()) { @@ -540,6 +546,58 @@ LLVM_DUMP_METHOD auto Dump(const File& file, TypeId type_id) -> std::string { return DumpTypeSummary(file, type_id); } +static LLVM_DUMP_METHOD auto Dump(const File& file, const Inst& inst) + -> std::string { + RawStringOstream out; + out << inst; + + if (inst.arg0_and_kind().kind() == IdKind::For) { + auto entity_name_id = EntityNameId(inst.arg0()); + out << "\n - name:" + << DumpNameIfValid(file, + file.entity_names().Get(entity_name_id).name_id); + } + + if (inst.type_id().has_value()) { + out << "\n - type: " << DumpTypeSummary(file, inst.type_id()); + } + + return out.TakeStr(); +} + +static LLVM_DUMP_METHOD auto Dump(const File& file, const NameScope& scope) + -> std::string { + RawStringOstream out; + out << scope; + if (scope.inst_id().has_value()) { + out << " " << file.insts().Get(scope.inst_id()); + } + out << DumpNameIfValid(file, scope.name_id()); + for (const auto& entry : scope.entries()) { + out << "\n - " << entry.name_id << DumpNameIfValid(file, entry.name_id) + << ": "; + if (entry.result.is_poisoned()) { + out << ""; + } else if (entry.result.is_found()) { + switch (entry.result.access_kind()) { + case AccessKind::Public: + out << "public "; + break; + case AccessKind::Protected: + out << "protected "; + break; + case AccessKind::Private: + out << "private "; + break; + } + out << DumpInstSummary(file, entry.result.target_inst_id()); + } else { + out << ""; + } + } + return out.TakeStr(); +} + // Functions that can be used instead of the corresponding constructor, which is // unavailable during debugging. LLVM_DUMP_METHOD static auto MakeClassId(int id) -> ClassId {