semantics_node.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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/ostream.h"
  8. #include "toolchain/semantics/semantics_node_kind.h"
  9. namespace Carbon {
  10. // Type-safe storage of Node IDs.
  11. struct SemanticsNodeId {
  12. SemanticsNodeId() : id(-1) {}
  13. explicit SemanticsNodeId(int32_t id) : id(id) {}
  14. SemanticsNodeId(SemanticsNodeId const&) = default;
  15. auto operator=(const SemanticsNodeId& other) -> SemanticsNodeId& = default;
  16. void Print(llvm::raw_ostream& out) const { out << "%" << id; }
  17. int32_t id;
  18. };
  19. // Type-safe storage of identifiers.
  20. struct SemanticsIdentifierId {
  21. SemanticsIdentifierId() : id(-1) {}
  22. explicit SemanticsIdentifierId(int32_t id) : id(id) {}
  23. void Print(llvm::raw_ostream& out) const { out << "%s" << id; }
  24. int32_t id;
  25. };
  26. // Type-safe storage of integer literals.
  27. struct SemanticsIntegerLiteralId {
  28. SemanticsIntegerLiteralId() : id(-1) {}
  29. explicit SemanticsIntegerLiteralId(int32_t id) : id(id) {}
  30. void Print(llvm::raw_ostream& out) const { out << "%s" << id; }
  31. int32_t id;
  32. };
  33. struct SemanticsTwoNodeIds {
  34. SemanticsNodeId nodes[2];
  35. };
  36. union SemanticsNodeArgs {
  37. struct None {};
  38. SemanticsNodeArgs() : no_args() {}
  39. explicit SemanticsNodeArgs(SemanticsNodeId one_node) : one_node(one_node) {}
  40. explicit SemanticsNodeArgs(SemanticsTwoNodeIds two_nodes)
  41. : two_nodes(two_nodes) {}
  42. explicit SemanticsNodeArgs(SemanticsIdentifierId identifier)
  43. : identifier(identifier) {}
  44. explicit SemanticsNodeArgs(SemanticsIntegerLiteralId integer_literal)
  45. : integer_literal(integer_literal) {}
  46. None no_args;
  47. SemanticsNodeId one_node;
  48. SemanticsTwoNodeIds two_nodes;
  49. SemanticsIdentifierId identifier;
  50. SemanticsIntegerLiteralId integer_literal;
  51. };
  52. // TODO: This is currently 8 bytes only because of two_nodes; others are only 4
  53. // bytes. The NodeKind is 1 byte; if we reduced this structure to 7 bytes (3.5
  54. // bytes per node), we could potentially change SemanticsNode from 12 bytes to 8
  55. // bytes. This may be worth investigating further.
  56. static_assert(sizeof(SemanticsNodeArgs) == 8, "Unexpected OneOfArgs size");
  57. // The standard structure for nodes.
  58. class SemanticsNode {
  59. public:
  60. // Define factory functions for each node kind. These should improve type
  61. // safety by enforcing argument counts.
  62. // `clang-format` has a bug with spacing around `->` returns here. See
  63. // https://bugs.llvm.org/show_bug.cgi?id=48320 for details.
  64. #define CARBON_SEMANTICS_MAKE_no_args(Name) \
  65. static auto Make##Name()->SemanticsNode { \
  66. return SemanticsNode(SemanticsNodeKind::Name(), SemanticsNodeArgs()); \
  67. }
  68. #define CARBON_SEMANTICS_MAKE_one_node(Name) \
  69. static auto Make##Name(SemanticsNodeId one_node)->SemanticsNode { \
  70. return SemanticsNode(SemanticsNodeKind::Name(), \
  71. SemanticsNodeArgs(one_node)); \
  72. }
  73. #define CARBON_SEMANTICS_MAKE_two_nodes(Name) \
  74. static auto Make##Name(SemanticsNodeId node1, SemanticsNodeId node2) \
  75. ->SemanticsNode { \
  76. return SemanticsNode( \
  77. SemanticsNodeKind::Name(), \
  78. SemanticsNodeArgs(SemanticsTwoNodeIds{node1, node2})); \
  79. }
  80. #define CARBON_SEMANTICS_MAKE_identifier(Name) \
  81. static auto Make##Name(SemanticsIdentifierId identifier)->SemanticsNode { \
  82. return SemanticsNode(SemanticsNodeKind::Name(), \
  83. SemanticsNodeArgs(identifier)); \
  84. }
  85. #define CARBON_SEMANTICS_MAKE_integer_literal(Name) \
  86. static auto Make##Name(SemanticsIntegerLiteralId integer_literal) \
  87. ->SemanticsNode { \
  88. return SemanticsNode(SemanticsNodeKind::Name(), \
  89. SemanticsNodeArgs(integer_literal)); \
  90. }
  91. #define CARBON_SEMANTICS_NODE_KIND(Name, ArgsType) \
  92. CARBON_SEMANTICS_MAKE_##ArgsType(Name)
  93. #include "toolchain/semantics/semantics_node_kind.def"
  94. #undef CARBON_SEMANTICS_MAKE_no_args
  95. #undef CARBON_SEMANTICS_MAKE_one_node
  96. #undef CARBON_SEMANTICS_MAKE_two_nodes
  97. #undef CARBON_SEMANTICS_MAKE_identifier
  98. #undef CARBON_SEMANTICS_MAKE_integer_literal
  99. SemanticsNode() : kind_(SemanticsNodeKind::Invalid()) {}
  100. auto kind() -> SemanticsNodeKind { return kind_; }
  101. void Print(llvm::raw_ostream& out) const;
  102. private:
  103. SemanticsNode(SemanticsNodeKind kind, SemanticsNodeArgs one_of_args)
  104. : kind_(kind), one_of_args_(one_of_args) {}
  105. SemanticsNodeKind kind_;
  106. SemanticsNodeArgs one_of_args_;
  107. };
  108. } // namespace Carbon
  109. #endif // CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_NODE_H_