semantics_node.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_NODE_H_
  5. #define CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_NODE_H_
  6. #include <cstdint>
  7. #include "common/check.h"
  8. #include "common/ostream.h"
  9. #include "toolchain/parser/parse_tree.h"
  10. #include "toolchain/semantics/semantics_builtin_kind.h"
  11. #include "toolchain/semantics/semantics_node_kind.h"
  12. namespace Carbon {
  13. // Type-safe storage of Node IDs.
  14. struct SemanticsNodeId : public IndexBase {
  15. // An explicitly invalid node ID.
  16. // NOLINTNEXTLINE(readability-identifier-naming)
  17. static const SemanticsNodeId Invalid;
  18. // Builtin node IDs.
  19. #define CARBON_SEMANTICS_BUILTIN_KIND_NAME(Name) \
  20. static const SemanticsNodeId Builtin##Name;
  21. #include "toolchain/semantics/semantics_builtin_kind.def"
  22. using IndexBase::IndexBase;
  23. auto Print(llvm::raw_ostream& out) const -> void {
  24. out << "node";
  25. IndexBase::Print(out);
  26. }
  27. };
  28. constexpr SemanticsNodeId SemanticsNodeId::Invalid =
  29. SemanticsNodeId(SemanticsNodeId::InvalidIndex);
  30. // Uses the cross-reference node ID for a builtin. This relies on SemanticsIR
  31. // guarantees for builtin cross-reference placement.
  32. #define CARBON_SEMANTICS_BUILTIN_KIND_NAME(Name) \
  33. constexpr SemanticsNodeId SemanticsNodeId::Builtin##Name = \
  34. SemanticsNodeId(SemanticsBuiltinKind::Name.AsInt());
  35. #include "toolchain/semantics/semantics_builtin_kind.def"
  36. // The ID of a callable, such as a function.
  37. struct SemanticsCallableId : public IndexBase {
  38. using IndexBase::IndexBase;
  39. auto Print(llvm::raw_ostream& out) const -> void {
  40. out << "callable" << index;
  41. }
  42. };
  43. // The ID of a cross-referenced IR.
  44. struct SemanticsCrossReferenceIRId : public IndexBase {
  45. using IndexBase::IndexBase;
  46. auto Print(llvm::raw_ostream& out) const -> void {
  47. out << "ir";
  48. IndexBase::Print(out);
  49. }
  50. };
  51. // Type-safe storage of integer literals.
  52. struct SemanticsIntegerLiteralId : public IndexBase {
  53. using IndexBase::IndexBase;
  54. auto Print(llvm::raw_ostream& out) const -> void {
  55. out << "int";
  56. IndexBase::Print(out);
  57. }
  58. };
  59. // Type-safe storage of node blocks.
  60. struct SemanticsNodeBlockId : public IndexBase {
  61. // All SemanticsIR instances must provide the 0th node block as empty.
  62. // NOLINTNEXTLINE(readability-identifier-naming)
  63. static const SemanticsNodeBlockId Empty;
  64. // An explicitly invalid ID.
  65. // NOLINTNEXTLINE(readability-identifier-naming)
  66. static const SemanticsNodeBlockId Invalid;
  67. using IndexBase::IndexBase;
  68. auto Print(llvm::raw_ostream& out) const -> void {
  69. out << "block";
  70. IndexBase::Print(out);
  71. }
  72. };
  73. constexpr SemanticsNodeBlockId SemanticsNodeBlockId::Empty =
  74. SemanticsNodeBlockId(0);
  75. constexpr SemanticsNodeBlockId SemanticsNodeBlockId::Invalid =
  76. SemanticsNodeBlockId(SemanticsNodeBlockId::InvalidIndex);
  77. // Type-safe storage of strings.
  78. struct SemanticsStringId : public IndexBase {
  79. using IndexBase::IndexBase;
  80. auto Print(llvm::raw_ostream& out) const -> void {
  81. out << "str";
  82. IndexBase::Print(out);
  83. }
  84. };
  85. // The standard structure for nodes.
  86. class SemanticsNode {
  87. public:
  88. struct NoArgs {};
  89. auto GetAsInvalid() const -> NoArgs { CARBON_FATAL() << "Invalid access"; }
  90. static auto MakeAssign(ParseTree::Node parse_node, SemanticsNodeId type,
  91. SemanticsNodeId lhs, SemanticsNodeId rhs)
  92. -> SemanticsNode {
  93. return SemanticsNode(parse_node, SemanticsNodeKind::Assign, type, lhs.index,
  94. rhs.index);
  95. }
  96. auto GetAsAssign() const -> std::pair<SemanticsNodeId, SemanticsNodeId> {
  97. CARBON_CHECK(kind_ == SemanticsNodeKind::Assign);
  98. return {SemanticsNodeId(arg0_), SemanticsNodeId(arg1_)};
  99. }
  100. static auto MakeBinaryOperatorAdd(ParseTree::Node parse_node,
  101. SemanticsNodeId type, SemanticsNodeId lhs,
  102. SemanticsNodeId rhs) -> SemanticsNode {
  103. return SemanticsNode(parse_node, SemanticsNodeKind::BinaryOperatorAdd, type,
  104. lhs.index, rhs.index);
  105. }
  106. auto GetAsBinaryOperatorAdd() const
  107. -> std::pair<SemanticsNodeId, SemanticsNodeId> {
  108. CARBON_CHECK(kind_ == SemanticsNodeKind::BinaryOperatorAdd);
  109. return {SemanticsNodeId(arg0_), SemanticsNodeId(arg1_)};
  110. }
  111. static auto MakeBindName(ParseTree::Node parse_node, SemanticsNodeId type,
  112. SemanticsStringId name, SemanticsNodeId node)
  113. -> SemanticsNode {
  114. return SemanticsNode(parse_node, SemanticsNodeKind::BindName, type,
  115. name.index, node.index);
  116. }
  117. auto GetAsBindName() const -> std::pair<SemanticsStringId, SemanticsNodeId> {
  118. CARBON_CHECK(kind_ == SemanticsNodeKind::BindName);
  119. return {SemanticsStringId(arg0_), SemanticsNodeId(arg1_)};
  120. }
  121. static auto MakeBuiltin(SemanticsBuiltinKind builtin_kind,
  122. SemanticsNodeId type) -> SemanticsNode {
  123. // Builtins won't have a ParseTree node associated, so we provide the
  124. // default invalid one.
  125. return SemanticsNode(ParseTree::Node::Invalid, SemanticsNodeKind::Builtin,
  126. type, builtin_kind.AsInt());
  127. }
  128. auto GetAsBuiltin() const -> SemanticsBuiltinKind {
  129. CARBON_CHECK(kind_ == SemanticsNodeKind::Builtin);
  130. return SemanticsBuiltinKind::FromInt(arg0_);
  131. }
  132. static auto MakeCodeBlock(ParseTree::Node parse_node,
  133. SemanticsNodeBlockId node_block) -> SemanticsNode {
  134. return SemanticsNode(parse_node, SemanticsNodeKind::CodeBlock,
  135. SemanticsNodeId::Invalid, node_block.index);
  136. }
  137. auto GetAsCodeBlock() const -> SemanticsNodeBlockId {
  138. CARBON_CHECK(kind_ == SemanticsNodeKind::CodeBlock);
  139. return SemanticsNodeBlockId(arg0_);
  140. }
  141. static auto MakeCrossReference(SemanticsNodeId type,
  142. SemanticsCrossReferenceIRId ir,
  143. SemanticsNodeId node) -> SemanticsNode {
  144. return SemanticsNode(ParseTree::Node::Invalid,
  145. SemanticsNodeKind::CrossReference, type, ir.index,
  146. node.index);
  147. }
  148. auto GetAsCrossReference() const
  149. -> std::pair<SemanticsCrossReferenceIRId, SemanticsNodeId> {
  150. CARBON_CHECK(kind_ == SemanticsNodeKind::CrossReference);
  151. return {SemanticsCrossReferenceIRId(arg0_), SemanticsNodeId(arg1_)};
  152. }
  153. // TODO: The signature should be added as a parameter.
  154. static auto MakeFunctionDeclaration(ParseTree::Node parse_node,
  155. SemanticsCallableId signature)
  156. -> SemanticsNode {
  157. return SemanticsNode(parse_node, SemanticsNodeKind::FunctionDeclaration,
  158. SemanticsNodeId::Invalid, signature.index);
  159. }
  160. auto GetAsFunctionDeclaration() const -> SemanticsCallableId {
  161. CARBON_CHECK(kind_ == SemanticsNodeKind::FunctionDeclaration);
  162. return {SemanticsCallableId(arg0_)};
  163. }
  164. static auto MakeFunctionDefinition(ParseTree::Node parse_node,
  165. SemanticsNodeId decl,
  166. SemanticsNodeBlockId node_block)
  167. -> SemanticsNode {
  168. return SemanticsNode(parse_node, SemanticsNodeKind::FunctionDefinition,
  169. SemanticsNodeId::Invalid, decl.index,
  170. node_block.index);
  171. }
  172. auto GetAsFunctionDefinition() const
  173. -> std::pair<SemanticsNodeId, SemanticsNodeBlockId> {
  174. CARBON_CHECK(kind_ == SemanticsNodeKind::FunctionDefinition);
  175. return {SemanticsNodeId(arg0_), SemanticsNodeBlockId(arg1_)};
  176. }
  177. static auto MakeIntegerLiteral(ParseTree::Node parse_node,
  178. SemanticsIntegerLiteralId integer)
  179. -> SemanticsNode {
  180. return SemanticsNode(parse_node, SemanticsNodeKind::IntegerLiteral,
  181. SemanticsNodeId::BuiltinIntegerType, integer.index);
  182. }
  183. auto GetAsIntegerLiteral() const -> SemanticsIntegerLiteralId {
  184. CARBON_CHECK(kind_ == SemanticsNodeKind::IntegerLiteral);
  185. return SemanticsIntegerLiteralId(arg0_);
  186. }
  187. static auto MakeRealLiteral(ParseTree::Node parse_node) -> SemanticsNode {
  188. return SemanticsNode(parse_node, SemanticsNodeKind::RealLiteral,
  189. SemanticsNodeId::BuiltinRealType);
  190. }
  191. auto GetAsRealLiteral() const -> NoArgs {
  192. CARBON_CHECK(kind_ == SemanticsNodeKind::RealLiteral);
  193. return {};
  194. }
  195. static auto MakeReturn(ParseTree::Node parse_node) -> SemanticsNode {
  196. // The actual type is `()`. However, code dealing with `return;` should
  197. // understand the type without checking, so it's not necessary but could be
  198. // specified if needed.
  199. return SemanticsNode(parse_node, SemanticsNodeKind::Return,
  200. SemanticsNodeId::Invalid);
  201. }
  202. auto GetAsReturn() const -> NoArgs {
  203. CARBON_CHECK(kind_ == SemanticsNodeKind::Return);
  204. return {};
  205. }
  206. static auto MakeReturnExpression(ParseTree::Node parse_node,
  207. SemanticsNodeId type, SemanticsNodeId expr)
  208. -> SemanticsNode {
  209. return SemanticsNode(parse_node, SemanticsNodeKind::ReturnExpression, type,
  210. expr.index);
  211. }
  212. auto GetAsReturnExpression() const -> SemanticsNodeId {
  213. CARBON_CHECK(kind_ == SemanticsNodeKind::ReturnExpression);
  214. return SemanticsNodeId(arg0_);
  215. }
  216. static auto MakeVarStorage(ParseTree::Node parse_node, SemanticsNodeId type)
  217. -> SemanticsNode {
  218. return SemanticsNode(parse_node, SemanticsNodeKind::VarStorage, type);
  219. }
  220. auto GetAsVarStorage() const -> NoArgs {
  221. CARBON_CHECK(kind_ == SemanticsNodeKind::VarStorage);
  222. return NoArgs();
  223. }
  224. SemanticsNode()
  225. : SemanticsNode(ParseTree::Node::Invalid, SemanticsNodeKind::Invalid,
  226. SemanticsNodeId::Invalid) {}
  227. auto parse_node() const -> ParseTree::Node { return parse_node_; }
  228. auto kind() const -> SemanticsNodeKind { return kind_; }
  229. auto type() const -> SemanticsNodeId { return type_; }
  230. auto Print(llvm::raw_ostream& out) const -> void;
  231. private:
  232. explicit SemanticsNode(ParseTree::Node parse_node, SemanticsNodeKind kind,
  233. SemanticsNodeId type, int32_t arg0 = -1,
  234. int32_t arg1 = -1)
  235. : parse_node_(parse_node),
  236. kind_(kind),
  237. type_(type),
  238. arg0_(arg0),
  239. arg1_(arg1) {}
  240. ParseTree::Node parse_node_;
  241. SemanticsNodeKind kind_;
  242. SemanticsNodeId type_;
  243. int32_t arg0_;
  244. int32_t arg1_;
  245. };
  246. // TODO: This is currently 20 bytes because we sometimes have 2 arguments for a
  247. // pair of SemanticsNodes. However, SemanticsNodeKind is 1 byte; if args
  248. // were 3.5 bytes, we could potentially shrink SemanticsNode by 4 bytes. This
  249. // may be worth investigating further.
  250. static_assert(sizeof(SemanticsNode) == 20, "Unexpected SemanticsNode size");
  251. } // namespace Carbon
  252. #endif // CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_NODE_H_