semantics_node_block_stack.h 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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_BLOCK_STACK_H_
  5. #define CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_NODE_BLOCK_STACK_H_
  6. #include <type_traits>
  7. #include "llvm/ADT/SmallVector.h"
  8. #include "toolchain/semantics/semantics_ir.h"
  9. #include "toolchain/semantics/semantics_node.h"
  10. namespace Carbon::Check {
  11. // Wraps the stack of node blocks for Context.
  12. //
  13. // All pushes and pops will be vlogged.
  14. class NodeBlockStack {
  15. public:
  16. explicit NodeBlockStack(llvm::StringLiteral name, SemIR::File& semantics_ir,
  17. llvm::raw_ostream* vlog_stream)
  18. : name_(name), semantics_ir_(&semantics_ir), vlog_stream_(vlog_stream) {}
  19. // Pushes an existing node block.
  20. auto Push(SemIR::NodeBlockId id) -> void;
  21. // Pushes a new node block. It will be invalid unless PeekForAdd is called in
  22. // order to support lazy allocation.
  23. auto Push() -> void { Push(SemIR::NodeBlockId::Invalid); }
  24. // Pushes a new unreachable code block.
  25. auto PushUnreachable() -> void { Push(SemIR::NodeBlockId::Unreachable); }
  26. // Allocates and pushes a new node block.
  27. auto PushForAdd() -> SemIR::NodeBlockId {
  28. Push();
  29. return PeekForAdd();
  30. }
  31. // Peeks at the top node block. This does not trigger lazy allocation, so the
  32. // returned node block may be invalid.
  33. auto Peek() -> SemIR::NodeBlockId {
  34. CARBON_CHECK(!stack_.empty()) << "no current block";
  35. return stack_.back();
  36. }
  37. // Returns the top node block, allocating one if it's still invalid.
  38. auto PeekForAdd() -> SemIR::NodeBlockId;
  39. // Pops the top node block. This will always return a valid node block;
  40. // SemIR::NodeBlockId::Empty is returned if one wasn't allocated.
  41. auto Pop() -> SemIR::NodeBlockId;
  42. // Pops the top node block, ensuring that it is lazily allocated if it's
  43. // empty. For use when more nodes will be added to the block later.
  44. auto PopForAdd() -> SemIR::NodeBlockId {
  45. PeekForAdd();
  46. return Pop();
  47. }
  48. // Returns whether the current block is statically reachable.
  49. auto is_current_block_reachable() -> bool {
  50. return Peek() != SemIR::NodeBlockId::Unreachable;
  51. }
  52. // Prints the stack for a stack dump.
  53. auto PrintForStackDump(llvm::raw_ostream& output) const -> void;
  54. auto empty() const -> bool { return stack_.empty(); }
  55. auto size() const -> size_t { return stack_.size(); }
  56. private:
  57. // A name for debugging.
  58. llvm::StringLiteral name_;
  59. // The underlying SemIR::File instance. Always non-null.
  60. SemIR::File* semantics_ir_;
  61. // Whether to print verbose output.
  62. llvm::raw_ostream* vlog_stream_;
  63. // The actual stack.
  64. // PushEntry and PopEntry control modification in order to centralize
  65. // vlogging.
  66. llvm::SmallVector<SemIR::NodeBlockId> stack_;
  67. };
  68. } // namespace Carbon::Check
  69. #endif // CARBON_TOOLCHAIN_SEMANTICS_SEMANTICS_NODE_BLOCK_STACK_H_