semantics_node.h 9.6 KB

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