mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 15:11:07 +01:00
By implementing these improvements, users will have the ability to choose specific parts of the trace output. Currently, when executing a file using the explorer with the --trace_file=- or --trace_file=filename.txt flag, the resulting output is an extensive and verbose log containing all the information. In this PR, I have introduced the `ProgramPhase` enum class, which have distinct phases encountered during the compilation of a program in the explorer. Each member of this enum class corresponds to a specific phase, signifying the relevant information to be included in the trace output. The phases covered by the `ProgramPhase` enum class are as follows: 1. Printing the source program 2. Name resolution 3. Control flow resolution 4. Type checking 5. Unformed variable resolution 6. Printing declarations 7. Printing the timings 8. Printing whole output. These phases can be selected by passing the following compiler flags along with `--trace_file=-`. `-trace_source_program`, `-trace_name_resolution`, `-trace_control_flow_resolution`, `-trace_type_checking`, `-trace_unformed_variables_resolution`, `-trace_declarations`, `-trace_execution`, `-trace_timing` and `-trace_all`. If none of these flags is passed only execution trace will be added to the output. Co-authored-by: Richard Smith <richard@metafoo.co.uk>
106 lines
3.8 KiB
C++
106 lines
3.8 KiB
C++
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#ifndef CARBON_EXPLORER_COMMON_TRACE_STREAM_H_
|
|
#define CARBON_EXPLORER_COMMON_TRACE_STREAM_H_
|
|
|
|
#include <bitset>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "common/check.h"
|
|
#include "common/ostream.h"
|
|
#include "explorer/common/nonnull.h"
|
|
|
|
namespace Carbon {
|
|
|
|
// Enumerates the phases of the program used for tracing and controlling which
|
|
// program phases are included for tracing.
|
|
enum class ProgramPhase {
|
|
Unknown, // Represents an unknown program phase.
|
|
SourceProgram, // Phase for the source program.
|
|
NameResolution, // Phase for name resolution.
|
|
ControlFlowResolution, // Phase for control flow resolution.
|
|
TypeChecking, // Phase for type checking.
|
|
UnformedVariableResolution, // Phase for unformed variables resolution.
|
|
Declarations, // Phase for printing declarations.
|
|
Execution, // Phase for program execution.
|
|
Timing, // Phase for timing logs.
|
|
All, // Represents all program phases.
|
|
Last = All // Last program phase indicator.
|
|
};
|
|
|
|
// Encapsulates the trace stream so that we can cleanly disable tracing while
|
|
// the prelude is being processed. The prelude is expected to take a
|
|
// disproprotionate amount of time to log, so we try to avoid it.
|
|
//
|
|
// TODO: While the prelude is combined with the provided program as a single
|
|
// AST, the AST knows which declarations came from the prelude. When the prelude
|
|
// is fully treated as a separate file, we should be able to take a different
|
|
// approach where the caller explicitly toggles tracing when switching file
|
|
// contexts.
|
|
class TraceStream {
|
|
public:
|
|
// Returns true if tracing is currently enabled.
|
|
// TODO: use current source location for file context based filtering instead
|
|
// of just checking if current code context is Prelude.
|
|
auto is_enabled() const -> bool {
|
|
return stream_.has_value() && !in_prelude_ &&
|
|
allowed_phases_[static_cast<int>(current_phase_)];
|
|
}
|
|
|
|
// Sets whether the prelude is being skipped.
|
|
auto set_in_prelude(bool in_prelude) -> void { in_prelude_ = in_prelude; }
|
|
|
|
// Sets the trace stream. This should only be called from the main.
|
|
auto set_stream(Nonnull<llvm::raw_ostream*> stream) -> void {
|
|
stream_ = stream;
|
|
}
|
|
|
|
auto set_current_phase(ProgramPhase current_phase) -> void {
|
|
current_phase_ = current_phase;
|
|
}
|
|
|
|
auto set_allowed_phases(std::vector<ProgramPhase> allowed_phases_list) {
|
|
if (allowed_phases_list.empty()) {
|
|
allowed_phases_.set(static_cast<int>(ProgramPhase::Execution));
|
|
} else {
|
|
for (auto phase : allowed_phases_list) {
|
|
if (phase == ProgramPhase::All) {
|
|
allowed_phases_.set();
|
|
} else {
|
|
allowed_phases_.set(static_cast<int>(phase));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Returns the internal stream. Requires is_enabled.
|
|
auto stream() const -> llvm::raw_ostream& {
|
|
CARBON_CHECK(is_enabled() && stream_.has_value());
|
|
return **stream_;
|
|
}
|
|
|
|
auto current_phase() const -> ProgramPhase { return current_phase_; }
|
|
|
|
// Outputs a trace message. Requires is_enabled.
|
|
template <typename T>
|
|
auto operator<<(T&& message) const -> llvm::raw_ostream& {
|
|
CARBON_CHECK(is_enabled());
|
|
**stream_ << message;
|
|
return **stream_;
|
|
}
|
|
|
|
private:
|
|
bool in_prelude_ = false;
|
|
std::optional<Nonnull<llvm::raw_ostream*>> stream_;
|
|
ProgramPhase current_phase_ = ProgramPhase::Unknown;
|
|
std::bitset<static_cast<int>(ProgramPhase::Last) + 1> allowed_phases_;
|
|
};
|
|
|
|
} // namespace Carbon
|
|
|
|
#endif // CARBON_EXPLORER_COMMON_TRACE_STREAM_H_
|