| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- // 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
- #ifndef CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_NODE_H_
- #define CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_NODE_H_
- #include <cstdint>
- #include "common/check.h"
- #include "common/ostream.h"
- #include "toolchain/parser/parse_tree.h"
- #include "toolchain/semantics/semantics_builtin_kind.h"
- #include "toolchain/semantics/semantics_node_kind.h"
- namespace Carbon {
- // Type-safe storage of Node IDs.
- struct SemanticsNodeId : public IndexBase {
- // An explicitly invalid node ID.
- // NOLINTNEXTLINE(readability-identifier-naming)
- static const SemanticsNodeId Invalid;
- // Builtin node IDs.
- #define CARBON_SEMANTICS_BUILTIN_KIND_NAME(Name) \
- static const SemanticsNodeId Builtin##Name;
- #include "toolchain/semantics/semantics_builtin_kind.def"
- using IndexBase::IndexBase;
- auto Print(llvm::raw_ostream& out) const -> void {
- out << "node";
- IndexBase::Print(out);
- }
- };
- constexpr SemanticsNodeId SemanticsNodeId::Invalid =
- SemanticsNodeId(SemanticsNodeId::InvalidIndex);
- // Uses the cross-reference node ID for a builtin. This relies on SemanticsIR
- // guarantees for builtin cross-reference placement.
- #define CARBON_SEMANTICS_BUILTIN_KIND_NAME(Name) \
- constexpr SemanticsNodeId SemanticsNodeId::Builtin##Name = \
- SemanticsNodeId(SemanticsBuiltinKind::Name.AsInt());
- #include "toolchain/semantics/semantics_builtin_kind.def"
- // The ID of a callable, such as a function.
- struct SemanticsCallableId : public IndexBase {
- using IndexBase::IndexBase;
- auto Print(llvm::raw_ostream& out) const -> void {
- out << "callable" << index;
- }
- };
- // The ID of a cross-referenced IR.
- struct SemanticsCrossReferenceIRId : public IndexBase {
- using IndexBase::IndexBase;
- auto Print(llvm::raw_ostream& out) const -> void {
- out << "ir";
- IndexBase::Print(out);
- }
- };
- // Type-safe storage of integer literals.
- struct SemanticsIntegerLiteralId : public IndexBase {
- using IndexBase::IndexBase;
- auto Print(llvm::raw_ostream& out) const -> void {
- out << "int";
- IndexBase::Print(out);
- }
- };
- // Type-safe storage of node blocks.
- struct SemanticsNodeBlockId : public IndexBase {
- // All SemanticsIR instances must provide the 0th node block as empty.
- // NOLINTNEXTLINE(readability-identifier-naming)
- static const SemanticsNodeBlockId Empty;
- // An explicitly invalid ID.
- // NOLINTNEXTLINE(readability-identifier-naming)
- static const SemanticsNodeBlockId Invalid;
- using IndexBase::IndexBase;
- auto Print(llvm::raw_ostream& out) const -> void {
- out << "block";
- IndexBase::Print(out);
- }
- };
- constexpr SemanticsNodeBlockId SemanticsNodeBlockId::Empty =
- SemanticsNodeBlockId(0);
- constexpr SemanticsNodeBlockId SemanticsNodeBlockId::Invalid =
- SemanticsNodeBlockId(SemanticsNodeBlockId::InvalidIndex);
- // Type-safe storage of strings.
- struct SemanticsStringId : public IndexBase {
- using IndexBase::IndexBase;
- auto Print(llvm::raw_ostream& out) const -> void {
- out << "str";
- IndexBase::Print(out);
- }
- };
- // The standard structure for nodes.
- class SemanticsNode {
- public:
- struct NoArgs {};
- auto GetAsInvalid() const -> NoArgs { CARBON_FATAL() << "Invalid access"; }
- static auto MakeAssign(ParseTree::Node parse_node, SemanticsNodeId type,
- SemanticsNodeId lhs, SemanticsNodeId rhs)
- -> SemanticsNode {
- return SemanticsNode(parse_node, SemanticsNodeKind::Assign, type, lhs.index,
- rhs.index);
- }
- auto GetAsAssign() const -> std::pair<SemanticsNodeId, SemanticsNodeId> {
- CARBON_CHECK(kind_ == SemanticsNodeKind::Assign);
- return {SemanticsNodeId(arg0_), SemanticsNodeId(arg1_)};
- }
- static auto MakeBinaryOperatorAdd(ParseTree::Node parse_node,
- SemanticsNodeId type, SemanticsNodeId lhs,
- SemanticsNodeId rhs) -> SemanticsNode {
- return SemanticsNode(parse_node, SemanticsNodeKind::BinaryOperatorAdd, type,
- lhs.index, rhs.index);
- }
- auto GetAsBinaryOperatorAdd() const
- -> std::pair<SemanticsNodeId, SemanticsNodeId> {
- CARBON_CHECK(kind_ == SemanticsNodeKind::BinaryOperatorAdd);
- return {SemanticsNodeId(arg0_), SemanticsNodeId(arg1_)};
- }
- static auto MakeBindName(ParseTree::Node parse_node, SemanticsNodeId type,
- SemanticsStringId name, SemanticsNodeId node)
- -> SemanticsNode {
- return SemanticsNode(parse_node, SemanticsNodeKind::BindName, type,
- name.index, node.index);
- }
- auto GetAsBindName() const -> std::pair<SemanticsStringId, SemanticsNodeId> {
- CARBON_CHECK(kind_ == SemanticsNodeKind::BindName);
- return {SemanticsStringId(arg0_), SemanticsNodeId(arg1_)};
- }
- static auto MakeBuiltin(SemanticsBuiltinKind builtin_kind,
- SemanticsNodeId type) -> SemanticsNode {
- // Builtins won't have a ParseTree node associated, so we provide the
- // default invalid one.
- return SemanticsNode(ParseTree::Node::Invalid, SemanticsNodeKind::Builtin,
- type, builtin_kind.AsInt());
- }
- auto GetAsBuiltin() const -> SemanticsBuiltinKind {
- CARBON_CHECK(kind_ == SemanticsNodeKind::Builtin);
- return SemanticsBuiltinKind::FromInt(arg0_);
- }
- static auto MakeCodeBlock(ParseTree::Node parse_node,
- SemanticsNodeBlockId node_block) -> SemanticsNode {
- return SemanticsNode(parse_node, SemanticsNodeKind::CodeBlock,
- SemanticsNodeId::Invalid, node_block.index);
- }
- auto GetAsCodeBlock() const -> SemanticsNodeBlockId {
- CARBON_CHECK(kind_ == SemanticsNodeKind::CodeBlock);
- return SemanticsNodeBlockId(arg0_);
- }
- static auto MakeCrossReference(SemanticsNodeId type,
- SemanticsCrossReferenceIRId ir,
- SemanticsNodeId node) -> SemanticsNode {
- return SemanticsNode(ParseTree::Node::Invalid,
- SemanticsNodeKind::CrossReference, type, ir.index,
- node.index);
- }
- auto GetAsCrossReference() const
- -> std::pair<SemanticsCrossReferenceIRId, SemanticsNodeId> {
- CARBON_CHECK(kind_ == SemanticsNodeKind::CrossReference);
- return {SemanticsCrossReferenceIRId(arg0_), SemanticsNodeId(arg1_)};
- }
- // TODO: The signature should be added as a parameter.
- static auto MakeFunctionDeclaration(ParseTree::Node parse_node,
- SemanticsCallableId signature)
- -> SemanticsNode {
- return SemanticsNode(parse_node, SemanticsNodeKind::FunctionDeclaration,
- SemanticsNodeId::Invalid, signature.index);
- }
- auto GetAsFunctionDeclaration() const -> SemanticsCallableId {
- CARBON_CHECK(kind_ == SemanticsNodeKind::FunctionDeclaration);
- return {SemanticsCallableId(arg0_)};
- }
- static auto MakeFunctionDefinition(ParseTree::Node parse_node,
- SemanticsNodeId decl,
- SemanticsNodeBlockId node_block)
- -> SemanticsNode {
- return SemanticsNode(parse_node, SemanticsNodeKind::FunctionDefinition,
- SemanticsNodeId::Invalid, decl.index,
- node_block.index);
- }
- auto GetAsFunctionDefinition() const
- -> std::pair<SemanticsNodeId, SemanticsNodeBlockId> {
- CARBON_CHECK(kind_ == SemanticsNodeKind::FunctionDefinition);
- return {SemanticsNodeId(arg0_), SemanticsNodeBlockId(arg1_)};
- }
- static auto MakeIntegerLiteral(ParseTree::Node parse_node,
- SemanticsIntegerLiteralId integer)
- -> SemanticsNode {
- return SemanticsNode(parse_node, SemanticsNodeKind::IntegerLiteral,
- SemanticsNodeId::BuiltinIntegerType, integer.index);
- }
- auto GetAsIntegerLiteral() const -> SemanticsIntegerLiteralId {
- CARBON_CHECK(kind_ == SemanticsNodeKind::IntegerLiteral);
- return SemanticsIntegerLiteralId(arg0_);
- }
- static auto MakeRealLiteral(ParseTree::Node parse_node) -> SemanticsNode {
- return SemanticsNode(parse_node, SemanticsNodeKind::RealLiteral,
- SemanticsNodeId::BuiltinRealType);
- }
- auto GetAsRealLiteral() const -> NoArgs {
- CARBON_CHECK(kind_ == SemanticsNodeKind::RealLiteral);
- return {};
- }
- static auto MakeReturn(ParseTree::Node parse_node) -> SemanticsNode {
- // The actual type is `()`. However, code dealing with `return;` should
- // understand the type without checking, so it's not necessary but could be
- // specified if needed.
- return SemanticsNode(parse_node, SemanticsNodeKind::Return,
- SemanticsNodeId::Invalid);
- }
- auto GetAsReturn() const -> NoArgs {
- CARBON_CHECK(kind_ == SemanticsNodeKind::Return);
- return {};
- }
- static auto MakeReturnExpression(ParseTree::Node parse_node,
- SemanticsNodeId type, SemanticsNodeId expr)
- -> SemanticsNode {
- return SemanticsNode(parse_node, SemanticsNodeKind::ReturnExpression, type,
- expr.index);
- }
- auto GetAsReturnExpression() const -> SemanticsNodeId {
- CARBON_CHECK(kind_ == SemanticsNodeKind::ReturnExpression);
- return SemanticsNodeId(arg0_);
- }
- static auto MakeVarStorage(ParseTree::Node parse_node, SemanticsNodeId type)
- -> SemanticsNode {
- return SemanticsNode(parse_node, SemanticsNodeKind::VarStorage, type);
- }
- auto GetAsVarStorage() const -> NoArgs {
- CARBON_CHECK(kind_ == SemanticsNodeKind::VarStorage);
- return NoArgs();
- }
- SemanticsNode()
- : SemanticsNode(ParseTree::Node::Invalid, SemanticsNodeKind::Invalid,
- SemanticsNodeId::Invalid) {}
- auto parse_node() const -> ParseTree::Node { return parse_node_; }
- auto kind() const -> SemanticsNodeKind { return kind_; }
- auto type() const -> SemanticsNodeId { return type_; }
- auto Print(llvm::raw_ostream& out) const -> void;
- private:
- explicit SemanticsNode(ParseTree::Node parse_node, SemanticsNodeKind kind,
- SemanticsNodeId type, int32_t arg0 = -1,
- int32_t arg1 = -1)
- : parse_node_(parse_node),
- kind_(kind),
- type_(type),
- arg0_(arg0),
- arg1_(arg1) {}
- ParseTree::Node parse_node_;
- SemanticsNodeKind kind_;
- SemanticsNodeId type_;
- int32_t arg0_;
- int32_t arg1_;
- };
- // TODO: This is currently 20 bytes because we sometimes have 2 arguments for a
- // pair of SemanticsNodes. However, SemanticsNodeKind is 1 byte; if args
- // were 3.5 bytes, we could potentially shrink SemanticsNode by 4 bytes. This
- // may be worth investigating further.
- static_assert(sizeof(SemanticsNode) == 20, "Unexpected SemanticsNode size");
- } // namespace Carbon
- #endif // CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_NODE_H_
|