semantics_ir.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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_IR_H_
  5. #define CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_IR_H_
  6. #include "llvm/ADT/SmallVector.h"
  7. #include "llvm/ADT/StringMap.h"
  8. #include "toolchain/parser/parse_tree.h"
  9. #include "toolchain/semantics/semantics_node.h"
  10. namespace Carbon::Testing {
  11. class SemanticsIRForTest;
  12. } // namespace Carbon::Testing
  13. namespace Carbon {
  14. // A callable object.
  15. struct SemanticsCallable {
  16. auto Print(llvm::raw_ostream& out) const -> void {
  17. out << "{param_ir: " << param_ir_id << ", param_refs: " << param_refs_id
  18. << "}";
  19. }
  20. // The full IR for parameters.
  21. SemanticsNodeBlockId param_ir_id;
  22. // A block containing a single reference node per parameter.
  23. SemanticsNodeBlockId param_refs_id;
  24. };
  25. // Provides semantic analysis on a ParseTree.
  26. class SemanticsIR {
  27. public:
  28. // Produces the builtins.
  29. static auto MakeBuiltinIR() -> SemanticsIR;
  30. // Adds the IR for the provided ParseTree.
  31. static auto MakeFromParseTree(const SemanticsIR& builtin_ir,
  32. const TokenizedBuffer& tokens,
  33. const ParseTree& parse_tree,
  34. DiagnosticConsumer& consumer,
  35. llvm::raw_ostream* vlog_stream) -> SemanticsIR;
  36. // Prints the full IR.
  37. auto Print(llvm::raw_ostream& out) const -> void;
  38. // Returns true if there were errors creating the semantics IR.
  39. auto has_errors() const -> bool { return has_errors_; }
  40. private:
  41. friend class SemanticsParseTreeHandler;
  42. explicit SemanticsIR(const SemanticsIR* builtin_ir)
  43. : cross_reference_irs_({builtin_ir == nullptr ? this : builtin_ir}) {
  44. // For SemanticsNodeBlockId::Empty.
  45. node_blocks_.resize(1);
  46. }
  47. // Returns the requested node.
  48. auto GetNode(SemanticsNodeId node_id) const -> const SemanticsNode& {
  49. return nodes_[node_id.index];
  50. }
  51. // Returns the type of the requested node.
  52. auto GetType(SemanticsNodeId node_id) -> SemanticsNodeId {
  53. return GetNode(node_id).type();
  54. }
  55. auto AddCallable(SemanticsCallable callable) -> SemanticsCallableId {
  56. SemanticsCallableId id(callables_.size());
  57. callables_.push_back(callable);
  58. return id;
  59. }
  60. // Adds an integer literal, returning an ID to reference it.
  61. auto AddIntegerLiteral(llvm::APInt integer_literal)
  62. -> SemanticsIntegerLiteralId {
  63. SemanticsIntegerLiteralId id(integer_literals_.size());
  64. integer_literals_.push_back(integer_literal);
  65. return id;
  66. }
  67. // Adds a node to a specified block, returning an ID to reference the node.
  68. auto AddNode(SemanticsNodeBlockId block_id, SemanticsNode node)
  69. -> SemanticsNodeId {
  70. SemanticsNodeId node_id(nodes_.size());
  71. nodes_.push_back(node);
  72. node_blocks_[block_id.index].push_back(node_id);
  73. return node_id;
  74. }
  75. // Adds an empty new node block, returning an ID to reference it and add
  76. // items.
  77. auto AddNodeBlock() -> SemanticsNodeBlockId {
  78. SemanticsNodeBlockId id(node_blocks_.size());
  79. node_blocks_.resize(node_blocks_.size() + 1);
  80. return id;
  81. }
  82. auto GetNodeBlock(SemanticsNodeBlockId block_id)
  83. -> llvm::SmallVector<SemanticsNodeId>& {
  84. return node_blocks_[block_id.index];
  85. }
  86. // Adds an string, returning an ID to reference it.
  87. auto AddString(llvm::StringRef str) -> SemanticsStringId {
  88. // If the string has already been stored, return the corresponding ID.
  89. if (auto existing_id = GetString(str)) {
  90. return *existing_id;
  91. }
  92. // Allocate the string and store it in the map.
  93. SemanticsStringId id(strings_.size());
  94. strings_.push_back(str);
  95. CARBON_CHECK(string_to_id_.insert({str, id}).second);
  96. return id;
  97. }
  98. // Returns an ID for the string if it's previously been stored.
  99. auto GetString(llvm::StringRef str) -> std::optional<SemanticsStringId> {
  100. auto str_find = string_to_id_.find(str);
  101. if (str_find != string_to_id_.end()) {
  102. return str_find->second;
  103. }
  104. return std::nullopt;
  105. }
  106. bool has_errors_ = false;
  107. // Storage for callable objects.
  108. llvm::SmallVector<SemanticsCallable> callables_;
  109. // Related IRs. There will always be at least 2 entries, the builtin IR (used
  110. // for references of builtins) followed by the current IR (used for references
  111. // crossing node blocks).
  112. llvm::SmallVector<const SemanticsIR*> cross_reference_irs_;
  113. // Storage for integer literals.
  114. llvm::SmallVector<llvm::APInt> integer_literals_;
  115. // Storage for strings. strings_ provides a list of allocated strings, while
  116. // string_to_id_ provides a mapping to identify strings.
  117. llvm::StringMap<SemanticsStringId> string_to_id_;
  118. llvm::SmallVector<llvm::StringRef> strings_;
  119. // All nodes. The first entries will always be cross-references to builtins,
  120. // at indices matching SemanticsBuiltinKind ordering.
  121. llvm::SmallVector<SemanticsNode> nodes_;
  122. // Storage for blocks within the IR. These reference entries in nodes_.
  123. llvm::SmallVector<llvm::SmallVector<SemanticsNodeId>> node_blocks_;
  124. };
  125. } // namespace Carbon
  126. #endif // CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_IR_H_