semantics_node.h 12 KB

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