semantics_node.h 11 KB

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