blob: 43bc052c04c5760f292a8fd71eedda66e899de3a [file] [log] [blame]
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001// Copyright 2021 The Tint Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef SRC_TINT_DEBUG_H_
16#define SRC_TINT_DEBUG_H_
17
18#include <utility>
19
20#include "src/tint/diagnostic/diagnostic.h"
21#include "src/tint/diagnostic/formatter.h"
22#include "src/tint/diagnostic/printer.h"
Ben Claytona1eed912023-01-13 14:46:21 +000023#include "src/tint/utils/compiler_macros.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000024
25namespace tint {
26
27/// Function type used for registering an internal compiler error reporter
28using InternalCompilerErrorReporter = void(const diag::List&);
29
30/// Sets the global error reporter to be called in case of internal compiler
31/// errors.
32/// @param reporter the error reporter
33void SetInternalCompilerErrorReporter(InternalCompilerErrorReporter* reporter);
34
35/// InternalCompilerError is a helper for reporting internal compiler errors.
36/// Construct the InternalCompilerError with the source location of the ICE
37/// fault and append any error details with the `<<` operator.
38/// When the InternalCompilerError is destructed, the concatenated error message
39/// is appended to the diagnostics list with the severity of
40/// tint::diag::Severity::InternalCompilerError, and if a
41/// InternalCompilerErrorReporter is set, then it is called with the diagnostic
42/// list.
43class InternalCompilerError {
dan sinclair41e4d9a2022-05-01 14:40:55 +000044 public:
45 /// Constructor
46 /// @param file the file containing the ICE
47 /// @param line the line containing the ICE
48 /// @param system the Tint system that has raised the ICE
49 /// @param diagnostics the list of diagnostics to append the ICE message to
50 InternalCompilerError(const char* file,
51 size_t line,
52 diag::System system,
53 diag::List& diagnostics);
Ryan Harrisondbc13af2022-02-21 15:19:07 +000054
dan sinclair41e4d9a2022-05-01 14:40:55 +000055 /// Destructor.
56 /// Adds the internal compiler error message to the diagnostics list, and then
57 /// calls the InternalCompilerErrorReporter if one is set.
58 ~InternalCompilerError();
Ryan Harrisondbc13af2022-02-21 15:19:07 +000059
dan sinclair41e4d9a2022-05-01 14:40:55 +000060 /// Appends `arg` to the ICE message.
61 /// @param arg the argument to append to the ICE message
62 /// @returns this object so calls can be chained
63 template <typename T>
64 InternalCompilerError& operator<<(T&& arg) {
65 msg_ << std::forward<T>(arg);
66 return *this;
67 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +000068
dan sinclair41e4d9a2022-05-01 14:40:55 +000069 private:
70 char const* const file_;
71 const size_t line_;
72 diag::System system_;
73 diag::List& diagnostics_;
74 std::stringstream msg_;
Ryan Harrisondbc13af2022-02-21 15:19:07 +000075};
76
77} // namespace tint
78
79/// TINT_ICE() is a macro for appending an internal compiler error message
80/// to the diagnostics list `diagnostics`, and calling the
81/// InternalCompilerErrorReporter with the full diagnostic list if a reporter is
82/// set.
83/// The ICE message contains the callsite's file and line.
84/// Use the `<<` operator to append an error message to the ICE.
dan sinclair41e4d9a2022-05-01 14:40:55 +000085#define TINT_ICE(system, diagnostics) \
86 tint::InternalCompilerError(__FILE__, __LINE__, ::tint::diag::System::system, diagnostics)
Ryan Harrisondbc13af2022-02-21 15:19:07 +000087
88/// TINT_UNREACHABLE() is a macro for appending a "TINT_UNREACHABLE"
89/// internal compiler error message to the diagnostics list `diagnostics`, and
90/// calling the InternalCompilerErrorReporter with the full diagnostic list if a
91/// reporter is set.
92/// The ICE message contains the callsite's file and line.
93/// Use the `<<` operator to append an error message to the ICE.
dan sinclair41e4d9a2022-05-01 14:40:55 +000094#define TINT_UNREACHABLE(system, diagnostics) TINT_ICE(system, diagnostics) << "TINT_UNREACHABLE "
Ryan Harrisondbc13af2022-02-21 15:19:07 +000095
96/// TINT_UNIMPLEMENTED() is a macro for appending a "TINT_UNIMPLEMENTED"
97/// internal compiler error message to the diagnostics list `diagnostics`, and
98/// calling the InternalCompilerErrorReporter with the full diagnostic list if a
99/// reporter is set.
100/// The ICE message contains the callsite's file and line.
101/// Use the `<<` operator to append an error message to the ICE.
102#define TINT_UNIMPLEMENTED(system, diagnostics) \
dan sinclair41e4d9a2022-05-01 14:40:55 +0000103 TINT_ICE(system, diagnostics) << "TINT_UNIMPLEMENTED "
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000104
105/// TINT_ASSERT() is a macro for checking the expression is true, triggering a
106/// TINT_ICE if it is not.
107/// The ICE message contains the callsite's file and line.
108/// @warning: Unlike TINT_ICE() and TINT_UNREACHABLE(), TINT_ASSERT() does not
109/// append a message to an existing tint::diag::List. As such, TINT_ASSERT()
110/// may silently fail in builds where SetInternalCompilerErrorReporter() is not
111/// called. Only use in places where there's no sensible place to put proper
112/// error handling.
dan sinclair41e4d9a2022-05-01 14:40:55 +0000113#define TINT_ASSERT(system, condition) \
114 do { \
Ben Claytona1eed912023-01-13 14:46:21 +0000115 if (TINT_UNLIKELY(!(condition))) { \
dan sinclair41e4d9a2022-05-01 14:40:55 +0000116 tint::diag::List diagnostics; \
117 TINT_ICE(system, diagnostics) << "TINT_ASSERT(" #system ", " #condition ")"; \
118 } \
119 } while (false)
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000120
121#endif // SRC_TINT_DEBUG_H_