mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-03 22:02:51 +01:00
This switches to single list storage of SemanticsNode. The driving motivation behind this is to simplify cross-references within a given IR. Types of nodes will frequently refer to other blocks. This causes a significant increase in the number of cross-references, which can become difficult to manage (and reason about). By reducing to a single list of nodes, cross-references are only needed when crossing IR boundaries. Because cross-references now only have 2 things to track (IR and index), they can be a regular SemanticsNode and don't need further indirection. This wasn't motivating, but feels like it reinforces the simplification. Note this isn't being used to deduplicate nodes, at least right now. That could lead to difficult-to-update situations, but also most nodes are associated with the underlying ParseTree::Node in order to track sources for diagnostics; as a consequence, nodes representing equal text in different source locations wouldn't be the same node. There may be future opportunities here, discussed with @zygoloid, but no action is taken at present. We may eventually want to switch the storage of NodeBlocks to have `[start, end)` ranges instead of individual numbers, but I'm leaving that alone for now. As an aside, I noticed I was accidentally overloading the copy constructor on SemanticsIR. I've added some disambiguation on that, but am not deleting the copy constructor per style advice (even though the type should never be copied due to storage size). codespell tries to change `CrossReference -> cross-reference` so disabling it there.
122 lines
4.4 KiB
C++
122 lines
4.4 KiB
C++
// 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/semantics/semantics_ir.h"
|
|
|
|
#include "common/check.h"
|
|
#include "llvm/Support/FormatVariadic.h"
|
|
#include "toolchain/lexer/tokenized_buffer.h"
|
|
#include "toolchain/semantics/semantics_builtin_kind.h"
|
|
#include "toolchain/semantics/semantics_node.h"
|
|
#include "toolchain/semantics/semantics_parse_tree_handler.h"
|
|
|
|
namespace Carbon {
|
|
|
|
auto SemanticsIR::MakeBuiltinIR() -> SemanticsIR {
|
|
SemanticsIR semantics(/*builtin_ir=*/nullptr);
|
|
auto block_id = semantics.AddNodeBlock();
|
|
semantics.nodes_.reserve(SemanticsBuiltinKind::ValidCount);
|
|
|
|
constexpr int32_t TypeOfTypeType = 0;
|
|
auto type_type = semantics.AddNode(
|
|
block_id, SemanticsNode::MakeBuiltin(SemanticsBuiltinKind::TypeType(),
|
|
SemanticsNodeId(TypeOfTypeType)));
|
|
CARBON_CHECK(type_type.index == TypeOfTypeType)
|
|
<< "TypeType's type must be self-referential.";
|
|
|
|
constexpr int32_t TypeOfInvalidType = 1;
|
|
auto invalid_type = semantics.AddNode(
|
|
block_id, SemanticsNode::MakeBuiltin(SemanticsBuiltinKind::InvalidType(),
|
|
SemanticsNodeId(TypeOfInvalidType)));
|
|
CARBON_CHECK(invalid_type.index == TypeOfInvalidType)
|
|
<< "InvalidType's type must be self-referential.";
|
|
|
|
semantics.AddNode(
|
|
block_id, SemanticsNode::MakeBuiltin(SemanticsBuiltinKind::IntegerType(),
|
|
type_type));
|
|
|
|
semantics.AddNode(block_id, SemanticsNode::MakeBuiltin(
|
|
SemanticsBuiltinKind::RealType(), type_type));
|
|
|
|
CARBON_CHECK(semantics.node_blocks_.size() == 1)
|
|
<< "BuildBuiltins should only produce 1 block, actual: "
|
|
<< semantics.node_blocks_.size();
|
|
return semantics;
|
|
}
|
|
|
|
auto SemanticsIR::MakeFromParseTree(const SemanticsIR& builtin_ir,
|
|
const TokenizedBuffer& tokens,
|
|
const ParseTree& parse_tree,
|
|
DiagnosticConsumer& consumer,
|
|
llvm::raw_ostream* vlog_stream)
|
|
-> SemanticsIR {
|
|
SemanticsIR semantics(&builtin_ir);
|
|
|
|
// Copy builtins over.
|
|
semantics.nodes_.resize_for_overwrite(SemanticsBuiltinKind::ValidCount);
|
|
static constexpr auto BuiltinIR = SemanticsCrossReferenceIRId(0);
|
|
for (int i = 0; i < SemanticsBuiltinKind::ValidCount; ++i) {
|
|
// We can reuse the type node ID because the offsets of cross-references
|
|
// will be the same in this IR.
|
|
auto type = builtin_ir.nodes_[i].type();
|
|
semantics.nodes_[i] =
|
|
SemanticsNode::MakeCrossReference(type, BuiltinIR, SemanticsNodeId(i));
|
|
}
|
|
|
|
TokenizedBuffer::TokenLocationTranslator translator(
|
|
&tokens, /*last_line_lexed_to_column=*/nullptr);
|
|
ErrorTrackingDiagnosticConsumer err_tracker(consumer);
|
|
TokenDiagnosticEmitter emitter(translator, err_tracker);
|
|
SemanticsParseTreeHandler(tokens, emitter, parse_tree, semantics, vlog_stream)
|
|
.Build();
|
|
semantics.has_errors_ = err_tracker.seen_error();
|
|
return semantics;
|
|
}
|
|
|
|
auto SemanticsIR::Print(llvm::raw_ostream& out) const -> void {
|
|
constexpr int Indent = 2;
|
|
|
|
out << "cross_reference_irs.size == " << cross_reference_irs_.size() << ",\n";
|
|
|
|
out << "integer_literals = {\n";
|
|
for (int32_t i = 0; i < static_cast<int32_t>(integer_literals_.size()); ++i) {
|
|
out.indent(Indent);
|
|
out << SemanticsIntegerLiteralId(i) << " = " << integer_literals_[i]
|
|
<< ";\n";
|
|
}
|
|
out << "},\n";
|
|
|
|
out << "strings = {\n";
|
|
for (int32_t i = 0; i < static_cast<int32_t>(strings_.size()); ++i) {
|
|
out.indent(Indent);
|
|
out << SemanticsStringId(i) << " = \"" << strings_[i] << "\";\n";
|
|
}
|
|
out << "},\n";
|
|
|
|
out << "nodes = {\n";
|
|
for (int32_t i = 0; i < static_cast<int32_t>(nodes_.size()); ++i) {
|
|
out.indent(Indent);
|
|
out << SemanticsNodeId(i) << " = " << nodes_[i] << ";\n";
|
|
}
|
|
out << "},\n";
|
|
|
|
out << "node_blocks = {\n";
|
|
for (int32_t i = 0; i < static_cast<int32_t>(node_blocks_.size()); ++i) {
|
|
out.indent(Indent);
|
|
out << SemanticsNodeBlockId(i) << " = {\n";
|
|
|
|
const auto& node_block = node_blocks_[i];
|
|
for (int32_t i = 0; i < static_cast<int32_t>(node_block.size()); ++i) {
|
|
out.indent(2 * Indent);
|
|
out << node_block[i] << ";\n";
|
|
}
|
|
|
|
out.indent(Indent);
|
|
out << "},\n";
|
|
}
|
|
out << "}\n";
|
|
}
|
|
|
|
} // namespace Carbon
|