semantics_node.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  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. if (!is_valid()) {
  25. IndexBase::Print(out);
  26. } else if (index < SemanticsBuiltinKind::ValidCount) {
  27. out << SemanticsBuiltinKind::FromInt(index);
  28. } else {
  29. // Use the `+` as a small reminder that this is a delta, rather than an
  30. // absolute index.
  31. out << "+" << index - SemanticsBuiltinKind::ValidCount;
  32. }
  33. }
  34. };
  35. constexpr SemanticsNodeId SemanticsNodeId::Invalid =
  36. SemanticsNodeId(SemanticsNodeId::InvalidIndex);
  37. // Uses the cross-reference node ID for a builtin. This relies on SemanticsIR
  38. // guarantees for builtin cross-reference placement.
  39. #define CARBON_SEMANTICS_BUILTIN_KIND_NAME(Name) \
  40. constexpr SemanticsNodeId SemanticsNodeId::Builtin##Name = \
  41. SemanticsNodeId(SemanticsBuiltinKind::Name.AsInt());
  42. #include "toolchain/semantics/semantics_builtin_kind.def"
  43. // The ID of a function.
  44. struct SemanticsFunctionId : public IndexBase {
  45. using IndexBase::IndexBase;
  46. auto Print(llvm::raw_ostream& out) const -> void {
  47. out << "function";
  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 ID of a node block.
  100. struct SemanticsTypeId : public IndexBase {
  101. // The builtin TypeType.
  102. static const SemanticsTypeId TypeType;
  103. // The builtin InvalidType.
  104. static const SemanticsTypeId InvalidType;
  105. // An explicitly invalid ID.
  106. static const SemanticsTypeId Invalid;
  107. using IndexBase::IndexBase;
  108. auto Print(llvm::raw_ostream& out) const -> void {
  109. out << "type";
  110. if (index == TypeType.index) {
  111. out << "TypeType";
  112. } else if (index == InvalidType.index) {
  113. out << "InvalidType";
  114. } else {
  115. IndexBase::Print(out);
  116. }
  117. }
  118. };
  119. constexpr SemanticsTypeId SemanticsTypeId::TypeType =
  120. SemanticsTypeId(SemanticsTypeId::InvalidIndex - 2);
  121. constexpr SemanticsTypeId SemanticsTypeId::InvalidType =
  122. SemanticsTypeId(SemanticsTypeId::InvalidIndex - 1);
  123. constexpr SemanticsTypeId SemanticsTypeId::Invalid =
  124. SemanticsTypeId(SemanticsTypeId::InvalidIndex);
  125. // An index for member access.
  126. struct SemanticsMemberIndex : public IndexBase {
  127. using IndexBase::IndexBase;
  128. auto Print(llvm::raw_ostream& out) const -> void {
  129. out << "member";
  130. IndexBase::Print(out);
  131. }
  132. };
  133. // The standard structure for SemanticsNode. This is trying to provide a minimal
  134. // amount of information for a node:
  135. //
  136. // - parse_node for error placement.
  137. // - kind for run-time logic when the input Kind is unknown.
  138. // - type_id for quick type checking.
  139. // - Up to two Kind-specific members.
  140. //
  141. // For each Kind in SemanticsNodeKind, a typical flow looks like:
  142. //
  143. // - Create a `SemanticsNode` using `SemanticsNode::Kind::Make()`
  144. // - Access cross-Kind members using `node.type_id()` and similar.
  145. // - Access Kind-specific members using `node.GetAsKind()`, which depending on
  146. // the number of members will return one of NoArgs, a single value, or a
  147. // `std::pair` of values.
  148. // - Using the wrong `node.GetAsKind()` is a programming error, and should
  149. // CHECK-fail in debug modes (opt may too, but it's not an API guarantee).
  150. //
  151. // Internally, each Kind uses the `Factory*` types to provide a boilerplate
  152. // `Make` and `Get` methods.
  153. class SemanticsNode {
  154. public:
  155. struct NoArgs {};
  156. // Factory base classes are private, then used for public classes. This class
  157. // has two public and two private sections to prevent accidents.
  158. private:
  159. // Factory templates need to use the raw enum instead of the class wrapper.
  160. using KindTemplateEnum = Internal::SemanticsNodeKindRawEnum;
  161. // Provides Make and Get to support 0, 1, or 2 arguments for a SemanticsNode.
  162. // These are protected so that child factories can opt in to what pieces they
  163. // want to use.
  164. template <KindTemplateEnum Kind, typename... ArgTypes>
  165. class FactoryBase {
  166. protected:
  167. static auto Make(ParseTree::Node parse_node, SemanticsTypeId type_id,
  168. ArgTypes... arg_ids) -> SemanticsNode {
  169. return SemanticsNode(parse_node, SemanticsNodeKind::Create(Kind), type_id,
  170. arg_ids.index...);
  171. }
  172. static auto Get(SemanticsNode node) {
  173. struct Unused {};
  174. return GetImpl<ArgTypes..., Unused>(node);
  175. }
  176. private:
  177. // GetImpl handles the different return types based on ArgTypes.
  178. template <typename Arg0Type, typename Arg1Type, typename>
  179. static auto GetImpl(SemanticsNode node) -> std::pair<Arg0Type, Arg1Type> {
  180. CARBON_CHECK(node.kind() == Kind);
  181. return {Arg0Type(node.arg0_), Arg1Type(node.arg1_)};
  182. }
  183. template <typename Arg0Type, typename>
  184. static auto GetImpl(SemanticsNode node) -> Arg0Type {
  185. CARBON_CHECK(node.kind() == Kind);
  186. return Arg0Type(node.arg0_);
  187. }
  188. template <typename>
  189. static auto GetImpl(SemanticsNode node) -> NoArgs {
  190. CARBON_CHECK(node.kind() == Kind);
  191. return NoArgs();
  192. }
  193. };
  194. // Provide Get along with a Make that requires a type.
  195. template <KindTemplateEnum Kind, typename... ArgTypes>
  196. class Factory : public FactoryBase<Kind, ArgTypes...> {
  197. public:
  198. using FactoryBase<Kind, ArgTypes...>::Make;
  199. using FactoryBase<Kind, ArgTypes...>::Get;
  200. };
  201. // Provides Get along with a Make that assumes a non-changing type.
  202. template <KindTemplateEnum Kind, typename... ArgTypes>
  203. class FactoryNoType : public FactoryBase<Kind, ArgTypes...> {
  204. public:
  205. static auto Make(ParseTree::Node parse_node, ArgTypes... args) {
  206. return FactoryBase<Kind, ArgTypes...>::Make(
  207. parse_node, SemanticsTypeId::Invalid, args...);
  208. }
  209. using FactoryBase<Kind, ArgTypes...>::Get;
  210. };
  211. public:
  212. // Invalid is in the SemanticsNodeKind enum, but should never be used.
  213. class Invalid {
  214. public:
  215. static auto Get(SemanticsNode /*node*/) -> SemanticsNode::NoArgs {
  216. CARBON_FATAL() << "Invalid access";
  217. }
  218. };
  219. using Assign = SemanticsNode::Factory<SemanticsNodeKind::Assign,
  220. SemanticsNodeId /*lhs_id*/,
  221. SemanticsNodeId /*rhs_id*/>;
  222. using BinaryOperatorAdd =
  223. SemanticsNode::Factory<SemanticsNodeKind::BinaryOperatorAdd,
  224. SemanticsNodeId /*lhs_id*/,
  225. SemanticsNodeId /*rhs_id*/>;
  226. using BindName = SemanticsNode::Factory<SemanticsNodeKind::BindName,
  227. SemanticsStringId /*name_id*/,
  228. SemanticsNodeId /*node_id*/>;
  229. class Builtin {
  230. public:
  231. static auto Make(SemanticsBuiltinKind builtin_kind, SemanticsTypeId type_id)
  232. -> SemanticsNode {
  233. // Builtins won't have a ParseTree node associated, so we provide the
  234. // default invalid one.
  235. // This can't use the standard Make function because of the `AsInt()` cast
  236. // instead of `.index`.
  237. return SemanticsNode(ParseTree::Node::Invalid, SemanticsNodeKind::Builtin,
  238. type_id, builtin_kind.AsInt());
  239. }
  240. static auto Get(SemanticsNode node) -> SemanticsBuiltinKind {
  241. return SemanticsBuiltinKind::FromInt(node.arg0_);
  242. }
  243. };
  244. using Call =
  245. Factory<SemanticsNodeKind::Call, SemanticsNodeBlockId /*refs_id*/,
  246. SemanticsFunctionId /*function_id*/>;
  247. using CodeBlock = FactoryNoType<SemanticsNodeKind::CodeBlock,
  248. SemanticsNodeBlockId /*node_block_id*/>;
  249. class CrossReference
  250. : public FactoryBase<SemanticsNodeKind::CrossReference,
  251. SemanticsCrossReferenceIRId /*ir_id*/,
  252. SemanticsNodeId /*node_id*/> {
  253. public:
  254. static auto Make(SemanticsTypeId type_id, SemanticsCrossReferenceIRId ir_id,
  255. SemanticsNodeId node_id) -> SemanticsNode {
  256. // A node's parse tree node must refer to a node in the current parse
  257. // tree. This cannot use the cross-referenced node's parse tree node
  258. // because it will be in a different parse tree.
  259. return FactoryBase::Make(ParseTree::Node::Invalid, type_id, ir_id,
  260. node_id);
  261. }
  262. using FactoryBase::Get;
  263. };
  264. using FunctionDeclaration =
  265. FactoryNoType<SemanticsNodeKind::FunctionDeclaration,
  266. SemanticsFunctionId /*function_id*/>;
  267. using IntegerLiteral = Factory<SemanticsNodeKind::IntegerLiteral,
  268. SemanticsIntegerLiteralId /*integer_id*/>;
  269. using RealLiteral = Factory<SemanticsNodeKind::RealLiteral,
  270. SemanticsRealLiteralId /*real_id*/>;
  271. using Return = FactoryNoType<SemanticsNodeKind::Return>;
  272. using ReturnExpression =
  273. Factory<SemanticsNodeKind::ReturnExpression, SemanticsNodeId /*expr_id*/>;
  274. using StringLiteral = Factory<SemanticsNodeKind::StringLiteral,
  275. SemanticsStringId /*string_id*/>;
  276. using StructMemberAccess = Factory<SemanticsNodeKind::StructMemberAccess,
  277. SemanticsNodeId /*struct_id*/,
  278. SemanticsMemberIndex /*ref_index*/>;
  279. using StructType =
  280. Factory<SemanticsNodeKind::StructType, SemanticsNodeBlockId /*refs_id*/>;
  281. using StructTypeField = Factory<SemanticsNodeKind::StructTypeField,
  282. SemanticsStringId /*name_id*/>;
  283. using StructValue =
  284. Factory<SemanticsNodeKind::StructValue, SemanticsNodeBlockId /*refs_id*/>;
  285. using StubReference =
  286. Factory<SemanticsNodeKind::StubReference, SemanticsNodeId /*node_id*/>;
  287. using VarStorage = Factory<SemanticsNodeKind::VarStorage>;
  288. SemanticsNode()
  289. : SemanticsNode(ParseTree::Node::Invalid, SemanticsNodeKind::Invalid,
  290. SemanticsTypeId::Invalid) {}
  291. // Provide `node.GetAsKind()` as an instance method for all kinds, essentially
  292. // an alias for`SemanticsNode::Kind::Get(node)`.
  293. #define CARBON_SEMANTICS_NODE_KIND(Name) \
  294. auto GetAs##Name() const { return Name::Get(*this); }
  295. #include "toolchain/semantics/semantics_node_kind.def"
  296. auto parse_node() const -> ParseTree::Node { return parse_node_; }
  297. auto kind() const -> SemanticsNodeKind { return kind_; }
  298. auto type_id() const -> SemanticsTypeId { return type_id_; }
  299. auto Print(llvm::raw_ostream& out) const -> void;
  300. private:
  301. // Builtins have peculiar construction, so they are a friend rather than using
  302. // a factory base class.
  303. friend struct SemanticsNodeForBuiltin;
  304. explicit SemanticsNode(ParseTree::Node parse_node, SemanticsNodeKind kind,
  305. SemanticsTypeId type_id,
  306. int32_t arg0 = SemanticsNodeId::InvalidIndex,
  307. int32_t arg1 = SemanticsNodeId::InvalidIndex)
  308. : parse_node_(parse_node),
  309. kind_(kind),
  310. type_id_(type_id),
  311. arg0_(arg0),
  312. arg1_(arg1) {}
  313. ParseTree::Node parse_node_;
  314. SemanticsNodeKind kind_;
  315. SemanticsTypeId type_id_;
  316. // Use GetAsKind to access arg0 and arg1.
  317. int32_t arg0_;
  318. int32_t arg1_;
  319. };
  320. // TODO: This is currently 20 bytes because we sometimes have 2 arguments for a
  321. // pair of SemanticsNodes. However, SemanticsNodeKind is 1 byte; if args
  322. // were 3.5 bytes, we could potentially shrink SemanticsNode by 4 bytes. This
  323. // may be worth investigating further.
  324. static_assert(sizeof(SemanticsNode) == 20, "Unexpected SemanticsNode size");
  325. // Provides base support for use of Id types as DenseMap/DenseSet keys.
  326. // Instantiated below.
  327. template <typename Id>
  328. struct SemanticsIdMapInfo {
  329. static inline auto getEmptyKey() -> Id {
  330. return Id(llvm::DenseMapInfo<int32_t>::getEmptyKey());
  331. }
  332. static inline auto getTombstoneKey() -> Id {
  333. return Id(llvm::DenseMapInfo<int32_t>::getTombstoneKey());
  334. }
  335. static auto getHashValue(const Id& val) -> unsigned {
  336. return llvm::DenseMapInfo<int32_t>::getHashValue(val.index);
  337. }
  338. static auto isEqual(const Id& lhs, const Id& rhs) -> bool {
  339. return lhs == rhs;
  340. }
  341. };
  342. } // namespace Carbon
  343. // Support use of Id types as DenseMap/DenseSet keys.
  344. template <>
  345. struct llvm::DenseMapInfo<Carbon::SemanticsNodeId>
  346. : public Carbon::SemanticsIdMapInfo<Carbon::SemanticsNodeId> {};
  347. template <>
  348. struct llvm::DenseMapInfo<Carbon::SemanticsStringId>
  349. : public Carbon::SemanticsIdMapInfo<Carbon::SemanticsStringId> {};
  350. #endif // CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_NODE_H_