|
@@ -15,6 +15,7 @@
|
|
|
#include "toolchain/base/shared_value_stores.h"
|
|
#include "toolchain/base/shared_value_stores.h"
|
|
|
#include "toolchain/lex/tokenized_buffer.h"
|
|
#include "toolchain/lex/tokenized_buffer.h"
|
|
|
#include "toolchain/parse/tree.h"
|
|
#include "toolchain/parse/tree.h"
|
|
|
|
|
+#include "toolchain/parse/tree_and_subtrees.h"
|
|
|
#include "toolchain/sem_ir/builtin_function_kind.h"
|
|
#include "toolchain/sem_ir/builtin_function_kind.h"
|
|
|
#include "toolchain/sem_ir/constant.h"
|
|
#include "toolchain/sem_ir/constant.h"
|
|
|
#include "toolchain/sem_ir/entity_with_params_base.h"
|
|
#include "toolchain/sem_ir/entity_with_params_base.h"
|
|
@@ -32,10 +33,12 @@
|
|
|
namespace Carbon::SemIR {
|
|
namespace Carbon::SemIR {
|
|
|
|
|
|
|
|
Formatter::Formatter(const File* sem_ir,
|
|
Formatter::Formatter(const File* sem_ir,
|
|
|
- ShouldFormatEntityFn should_format_entity)
|
|
|
|
|
|
|
+ ShouldFormatEntityFn should_format_entity,
|
|
|
|
|
+ Parse::GetTreeAndSubtreesFn get_tree_and_subtrees)
|
|
|
: sem_ir_(sem_ir),
|
|
: sem_ir_(sem_ir),
|
|
|
inst_namer_(sem_ir_),
|
|
inst_namer_(sem_ir_),
|
|
|
- should_format_entity_(should_format_entity) {
|
|
|
|
|
|
|
+ should_format_entity_(should_format_entity),
|
|
|
|
|
+ get_tree_and_subtrees_(get_tree_and_subtrees) {
|
|
|
// Create the first chunk and assign it to all instructions that don't have
|
|
// Create the first chunk and assign it to all instructions that don't have
|
|
|
// a chunk of their own.
|
|
// a chunk of their own.
|
|
|
auto first_chunk = AddChunkNoFlush(true);
|
|
auto first_chunk = AddChunkNoFlush(true);
|
|
@@ -141,15 +144,61 @@ auto Formatter::IncludeChunkInOutput(size_t chunk) -> void {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-auto Formatter::ShouldFormatEntity(InstId decl_id) -> bool {
|
|
|
|
|
|
|
+auto Formatter::OverlapsWithDumpSemIRRange(
|
|
|
|
|
+ InstId inst_id, llvm::ArrayRef<InstBlockId> body_block_ids) -> bool {
|
|
|
|
|
+ if (!sem_ir_->parse_tree().tokens().has_dump_sem_ir_ranges()) {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ auto loc_id = sem_ir_->insts().GetCanonicalLocId(inst_id);
|
|
|
|
|
+ if (loc_id.kind() != LocId::Kind::NodeId) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // For the declaration, we use the helper for checking the full range.
|
|
|
|
|
+ auto token_range =
|
|
|
|
|
+ get_tree_and_subtrees_().GetSubtreeTokenRange(loc_id.node_id());
|
|
|
|
|
+ if (sem_ir_->parse_tree().tokens().OverlapsWithDumpSemIRRange(
|
|
|
|
|
+ token_range.begin, token_range.end)) {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // If the declaration wasn't in scope, we need to check the body.
|
|
|
|
|
+ // TODO: We currently don't track the definition end, so this checks all
|
|
|
|
|
+ // instructions in the body. Maybe we should start tracking definition end
|
|
|
|
|
+ // nodes on entities?
|
|
|
|
|
+ for (auto body_block_id : body_block_ids) {
|
|
|
|
|
+ auto block = sem_ir_->inst_blocks().GetOrEmpty(body_block_id);
|
|
|
|
|
+ for (auto inst_id : block) {
|
|
|
|
|
+ auto loc_id = sem_ir_->insts().GetCanonicalLocId(inst_id);
|
|
|
|
|
+ if (loc_id.kind() == LocId::Kind::NodeId) {
|
|
|
|
|
+ auto token = sem_ir_->parse_tree().node_token(loc_id.node_id());
|
|
|
|
|
+ if (sem_ir_->parse_tree().tokens().OverlapsWithDumpSemIRRange(token,
|
|
|
|
|
+ token)) {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return false;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+auto Formatter::ShouldFormatEntity(InstId decl_id,
|
|
|
|
|
+ llvm::ArrayRef<InstBlockId> body_block_ids)
|
|
|
|
|
+ -> bool {
|
|
|
if (!decl_id.has_value()) {
|
|
if (!decl_id.has_value()) {
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
- return should_format_entity_(decl_id);
|
|
|
|
|
|
|
+ if (!should_format_entity_(decl_id)) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ return OverlapsWithDumpSemIRRange(decl_id, body_block_ids);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-auto Formatter::ShouldFormatEntity(const EntityWithParamsBase& entity) -> bool {
|
|
|
|
|
- return ShouldFormatEntity(entity.latest_decl_id());
|
|
|
|
|
|
|
+auto Formatter::ShouldFormatEntity(const EntityWithParamsBase& entity,
|
|
|
|
|
+ llvm::ArrayRef<InstBlockId> body_block_ids)
|
|
|
|
|
+ -> bool {
|
|
|
|
|
+ return ShouldFormatEntity(entity.latest_decl_id(), body_block_ids);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
auto Formatter::OpenBrace() -> void {
|
|
auto Formatter::OpenBrace() -> void {
|
|
@@ -217,7 +266,7 @@ auto Formatter::FormatScopeIfUsed(InstNamer::ScopeId scope_id,
|
|
|
|
|
|
|
|
auto Formatter::FormatClass(ClassId id) -> void {
|
|
auto Formatter::FormatClass(ClassId id) -> void {
|
|
|
const Class& class_info = sem_ir_->classes().Get(id);
|
|
const Class& class_info = sem_ir_->classes().Get(id);
|
|
|
- if (!ShouldFormatEntity(class_info)) {
|
|
|
|
|
|
|
+ if (!ShouldFormatEntity(class_info, class_info.body_block_id)) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -246,7 +295,7 @@ auto Formatter::FormatClass(ClassId id) -> void {
|
|
|
|
|
|
|
|
auto Formatter::FormatInterface(InterfaceId id) -> void {
|
|
auto Formatter::FormatInterface(InterfaceId id) -> void {
|
|
|
const Interface& interface_info = sem_ir_->interfaces().Get(id);
|
|
const Interface& interface_info = sem_ir_->interfaces().Get(id);
|
|
|
- if (!ShouldFormatEntity(interface_info)) {
|
|
|
|
|
|
|
+ if (!ShouldFormatEntity(interface_info, interface_info.body_block_id)) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -282,7 +331,7 @@ auto Formatter::FormatInterface(InterfaceId id) -> void {
|
|
|
auto Formatter::FormatAssociatedConstant(AssociatedConstantId id) -> void {
|
|
auto Formatter::FormatAssociatedConstant(AssociatedConstantId id) -> void {
|
|
|
const AssociatedConstant& assoc_const =
|
|
const AssociatedConstant& assoc_const =
|
|
|
sem_ir_->associated_constants().Get(id);
|
|
sem_ir_->associated_constants().Get(id);
|
|
|
- if (!ShouldFormatEntity(assoc_const.decl_id)) {
|
|
|
|
|
|
|
+ if (!ShouldFormatEntity(assoc_const.decl_id, /*body_block_ids=*/{})) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -306,7 +355,7 @@ auto Formatter::FormatAssociatedConstant(AssociatedConstantId id) -> void {
|
|
|
|
|
|
|
|
auto Formatter::FormatImpl(ImplId id) -> void {
|
|
auto Formatter::FormatImpl(ImplId id) -> void {
|
|
|
const Impl& impl_info = sem_ir_->impls().Get(id);
|
|
const Impl& impl_info = sem_ir_->impls().Get(id);
|
|
|
- if (!ShouldFormatEntity(impl_info)) {
|
|
|
|
|
|
|
+ if (!ShouldFormatEntity(impl_info, impl_info.body_block_id)) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -348,7 +397,7 @@ auto Formatter::FormatImpl(ImplId id) -> void {
|
|
|
|
|
|
|
|
auto Formatter::FormatFunction(FunctionId id) -> void {
|
|
auto Formatter::FormatFunction(FunctionId id) -> void {
|
|
|
const Function& fn = sem_ir_->functions().Get(id);
|
|
const Function& fn = sem_ir_->functions().Get(id);
|
|
|
- if (!ShouldFormatEntity(fn)) {
|
|
|
|
|
|
|
+ if (!ShouldFormatEntity(fn, fn.body_block_ids)) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -649,6 +698,10 @@ auto Formatter::FormatInst(InstId inst_id, ImportRefUnloaded inst) -> void {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
auto Formatter::FormatInst(InstId inst_id) -> void {
|
|
auto Formatter::FormatInst(InstId inst_id) -> void {
|
|
|
|
|
+ if (!OverlapsWithDumpSemIRRange(inst_id, /*body_block_ids=*/{})) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (!inst_id.has_value()) {
|
|
if (!inst_id.has_value()) {
|
|
|
Indent();
|
|
Indent();
|
|
|
out_ << "none\n";
|
|
out_ << "none\n";
|