meta_node.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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_META_NODE_H_
  5. #define CARBON_TOOLCHAIN_SEMANTICS_META_NODE_H_
  6. #include <cstdint>
  7. #include <tuple>
  8. #include "common/check.h"
  9. #include "llvm/ADT/SmallVector.h"
  10. namespace Carbon {
  11. class SemanticsIR;
  12. } // namespace Carbon
  13. namespace Carbon::Testing {
  14. class SemanticsIRForTest;
  15. } // namespace Carbon::Testing
  16. namespace Carbon::Semantics {
  17. // The standard structure for nodes which have multiple subtypes.
  18. //
  19. // This flyweight pattern is used so that each subtype can be stored in its own
  20. // vector, minimizing memory consumption and heap fragmentation when large
  21. // quantities are being created.
  22. template <typename KindT, typename MetaNodeStoreT>
  23. class MetaNode {
  24. public:
  25. MetaNode() : MetaNode(KindT::Invalid, -1) {}
  26. auto kind() -> KindT { return kind_; }
  27. private:
  28. friend MetaNodeStoreT;
  29. MetaNode(KindT kind, int32_t index) : kind_(kind), index_(index) {}
  30. KindT kind_;
  31. // The index of the named entity within its list.
  32. int32_t index_;
  33. };
  34. // Provides storage for nodes, indexed by MetaNodes.
  35. template <typename KindT, typename... StoredNodeT>
  36. class MetaNodeStore {
  37. public:
  38. using MetaNodeT = MetaNode<KindT, MetaNodeStore<KindT, StoredNodeT...>>;
  39. // Stores the provided node, returning a pointer to it.
  40. template <typename NodeT>
  41. auto Store(NodeT node) -> MetaNodeT {
  42. auto& node_store =
  43. std::get<static_cast<size_t>(NodeT::MetaNodeKind)>(node_stores_);
  44. int32_t index = node_store.size();
  45. node_store.push_back(node);
  46. return MetaNodeT(NodeT::MetaNodeKind, index);
  47. }
  48. // Returns the requested node. Requires that the pointer is valid for this
  49. // store.
  50. template <typename NodeT>
  51. auto Get(MetaNodeT meta_node) const -> const NodeT& {
  52. CARBON_CHECK(meta_node.index_ >= 0);
  53. CARBON_CHECK(meta_node.kind_ == NodeT::MetaNodeKind)
  54. << "Kind mismatch: " << static_cast<int>(meta_node.kind_) << " vs "
  55. << static_cast<int>(NodeT::MetaNodeKind);
  56. auto& node_store =
  57. std::get<static_cast<size_t>(NodeT::MetaNodeKind)>(node_stores_);
  58. CARBON_CHECK(static_cast<size_t>(meta_node.index_) < node_store.size());
  59. return node_store[meta_node.index_];
  60. }
  61. private:
  62. std::tuple<llvm::SmallVector<StoredNodeT, 0>...> node_stores_;
  63. };
  64. // Meta node information for declarations.
  65. enum class DeclarationKind {
  66. Function,
  67. Invalid,
  68. };
  69. class Function;
  70. using DeclarationStore = MetaNodeStore<DeclarationKind, Function>;
  71. using Declaration = MetaNode<DeclarationKind, DeclarationStore>;
  72. // Meta node information for statements.
  73. enum class StatementKind {
  74. ExpressionStatement,
  75. Return,
  76. Invalid,
  77. };
  78. class ExpressionStatement;
  79. class Return;
  80. using StatementStore =
  81. MetaNodeStore<StatementKind, ExpressionStatement, Return>;
  82. using Statement = MetaNode<StatementKind, StatementStore>;
  83. // Meta node information for declarations.
  84. enum class ExpressionKind {
  85. InfixOperator,
  86. Literal,
  87. Invalid,
  88. };
  89. class InfixOperator;
  90. class Literal;
  91. using ExpressionStore = MetaNodeStore<ExpressionKind, InfixOperator, Literal>;
  92. using Expression = MetaNode<ExpressionKind, ExpressionStore>;
  93. } // namespace Carbon::Semantics
  94. #endif // CARBON_TOOLCHAIN_SEMANTICS_META_NODE_H_