trace_stream.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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_EXPLORER_COMMON_TRACE_STREAM_H_
  5. #define CARBON_EXPLORER_COMMON_TRACE_STREAM_H_
  6. #include <bitset>
  7. #include <optional>
  8. #include <string>
  9. #include <vector>
  10. #include "common/check.h"
  11. #include "common/ostream.h"
  12. #include "explorer/common/nonnull.h"
  13. #include "explorer/common/source_location.h"
  14. #include "llvm/ADT/ArrayRef.h"
  15. namespace Carbon {
  16. class TraceStream;
  17. // Enumerates the phases of the program used for tracing and controlling which
  18. // program phases are included for tracing.
  19. enum class ProgramPhase {
  20. Unknown, // Represents an unknown program phase.
  21. SourceProgram, // Phase for the source program.
  22. NameResolution, // Phase for name resolution.
  23. ControlFlowResolution, // Phase for control flow resolution.
  24. TypeChecking, // Phase for type checking.
  25. UnformedVariableResolution, // Phase for unformed variables resolution.
  26. Declarations, // Phase for printing declarations.
  27. Execution, // Phase for program execution.
  28. Timing, // Phase for timing logs.
  29. All, // Represents all program phases.
  30. Last = All // Last program phase indicator.
  31. };
  32. // Encapsulates the trace stream so that we can cleanly disable tracing while
  33. // the prelude is being processed. The prelude is expected to take a
  34. // disproprotionate amount of time to log, so we try to avoid it.
  35. class TraceStream {
  36. public:
  37. explicit TraceStream() {}
  38. // Returns true if tracing is currently enabled.
  39. auto is_enabled() const -> bool {
  40. return stream_.has_value() && !in_prelude_ &&
  41. allowed_phases_[static_cast<int>(current_phase_)] &&
  42. (!source_loc_ ||
  43. allowed_file_kinds_[static_cast<int>(source_loc_->file_kind())]);
  44. }
  45. // Sets whether the prelude is being skipped.
  46. auto set_in_prelude(bool in_prelude) -> void { in_prelude_ = in_prelude; }
  47. // Sets the trace stream. This should only be called from the main.
  48. auto set_stream(Nonnull<llvm::raw_ostream*> stream) -> void {
  49. stream_ = stream;
  50. }
  51. auto set_current_phase(ProgramPhase current_phase) -> void {
  52. current_phase_ = current_phase;
  53. }
  54. auto set_allowed_phases(llvm::ArrayRef<ProgramPhase> allowed_phases_list)
  55. -> void {
  56. if (allowed_phases_list.empty()) {
  57. allowed_phases_.set(static_cast<int>(ProgramPhase::Execution));
  58. } else {
  59. for (auto phase : allowed_phases_list) {
  60. if (phase == ProgramPhase::All) {
  61. allowed_phases_.set();
  62. } else {
  63. allowed_phases_.set(static_cast<int>(phase));
  64. }
  65. }
  66. }
  67. }
  68. auto set_allowed_file_kinds(llvm::ArrayRef<FileKind> kind_list) -> void {
  69. for (auto kind : kind_list) {
  70. allowed_file_kinds_.set(static_cast<int>(kind));
  71. }
  72. }
  73. auto set_source_loc(std::optional<SourceLocation> source_loc) -> void {
  74. source_loc_ = source_loc;
  75. }
  76. auto source_loc() const -> std::optional<SourceLocation> {
  77. return source_loc_;
  78. }
  79. // Returns the internal stream. Requires is_enabled.
  80. auto stream() const -> llvm::raw_ostream& {
  81. CARBON_CHECK(is_enabled() && stream_.has_value());
  82. return **stream_;
  83. }
  84. auto current_phase() const -> ProgramPhase { return current_phase_; }
  85. // Outputs a trace message. Requires is_enabled.
  86. template <typename T>
  87. auto operator<<(T&& message) const -> llvm::raw_ostream& {
  88. CARBON_CHECK(is_enabled());
  89. **stream_ << message;
  90. return **stream_;
  91. }
  92. private:
  93. bool in_prelude_ = false;
  94. ProgramPhase current_phase_ = ProgramPhase::Unknown;
  95. std::optional<SourceLocation> source_loc_ = std::nullopt;
  96. std::optional<Nonnull<llvm::raw_ostream*>> stream_;
  97. std::bitset<static_cast<int>(ProgramPhase::Last) + 1> allowed_phases_;
  98. std::bitset<static_cast<int>(FileKind::Last) + 1> allowed_file_kinds_;
  99. };
  100. // This is a RAII class to set the current program phase, destructor invocation
  101. // restores the previous phase.
  102. class SetProgramPhase {
  103. public:
  104. explicit SetProgramPhase(TraceStream& trace_stream,
  105. ProgramPhase program_phase)
  106. : trace_stream_(trace_stream),
  107. initial_phase_(trace_stream.current_phase()) {
  108. trace_stream.set_current_phase(program_phase);
  109. }
  110. ~SetProgramPhase() { trace_stream_.set_current_phase(initial_phase_); }
  111. // This can be used for cases when current phase is set multiple times within
  112. // the same scope.
  113. auto update_phase(ProgramPhase program_phase) -> void {
  114. trace_stream_.set_current_phase(program_phase);
  115. }
  116. private:
  117. TraceStream& trace_stream_;
  118. ProgramPhase initial_phase_;
  119. };
  120. // This is a RAII class to set the source location in trace stream, destructor
  121. // invocation restores the initial source location.
  122. class SetFileContext {
  123. public:
  124. explicit SetFileContext(TraceStream& trace_stream,
  125. std::optional<SourceLocation> source_loc)
  126. : trace_stream_(trace_stream),
  127. initial_source_loc_(trace_stream.source_loc()) {
  128. trace_stream_.set_source_loc(source_loc);
  129. }
  130. ~SetFileContext() { trace_stream_.set_source_loc(initial_source_loc_); }
  131. // This can be used for cases when source location needs to be updated
  132. // multiple times within the same scope.
  133. auto update_source_loc(std::optional<SourceLocation> source_loc) {
  134. trace_stream_.set_source_loc(source_loc);
  135. }
  136. private:
  137. TraceStream& trace_stream_;
  138. std::optional<SourceLocation> initial_source_loc_;
  139. };
  140. } // namespace Carbon
  141. #endif // CARBON_EXPLORER_COMMON_TRACE_STREAM_H_