• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Dawn 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 DAWNNODE_UTILS_DEBUG_H_
16 #define DAWNNODE_UTILS_DEBUG_H_
17 
18 #include <iostream>
19 #include <optional>
20 #include <sstream>
21 #include <unordered_map>
22 #include <variant>
23 #include <vector>
24 
25 #include "dawn/webgpu_cpp_print.h"
26 
27 namespace wgpu { namespace utils {
28 
29     // Write() is a helper for printing container types to the std::ostream.
30     // Write() is used by the LOG() macro below.
31 
32     // Forward declarations
Write(std::ostream & out)33     inline std::ostream& Write(std::ostream& out) {
34         return out;
35     }
36     template <typename T>
37     inline std::ostream& Write(std::ostream& out, const std::optional<T>& value);
38     template <typename T>
39     inline std::ostream& Write(std::ostream& out, const std::vector<T>& value);
40     template <typename K, typename V>
41     inline std::ostream& Write(std::ostream& out, const std::unordered_map<K, V>& value);
42     template <typename... TYS>
43     inline std::ostream& Write(std::ostream& out, const std::variant<TYS...>& value);
44     template <typename VALUE>
45     std::ostream& Write(std::ostream& out, VALUE&& value);
46 
47     // Write() implementations
48     template <typename T>
Write(std::ostream & out,const std::optional<T> & value)49     std::ostream& Write(std::ostream& out, const std::optional<T>& value) {
50         if (value.has_value()) {
51             return Write(out, value.value());
52         }
53         return out << "<undefined>";
54     }
55 
56     template <typename T>
Write(std::ostream & out,const std::vector<T> & value)57     std::ostream& Write(std::ostream& out, const std::vector<T>& value) {
58         out << "[";
59         bool first = true;
60         for (const auto& el : value) {
61             if (!first) {
62                 out << ", ";
63             }
64             first = false;
65             Write(out, el);
66         }
67         return out << "]";
68     }
69 
70     template <typename K, typename V>
Write(std::ostream & out,const std::unordered_map<K,V> & value)71     std::ostream& Write(std::ostream& out, const std::unordered_map<K, V>& value) {
72         out << "{";
73         bool first = true;
74         for (auto it : value) {
75             if (!first) {
76                 out << ", ";
77             }
78             first = false;
79             Write(out, it.first);
80             out << ": ";
81             Write(out, it.second);
82         }
83         return out << "}";
84     }
85 
86     template <typename... TYS>
Write(std::ostream & out,const std::variant<TYS...> & value)87     std::ostream& Write(std::ostream& out, const std::variant<TYS...>& value) {
88         std::visit([&](auto&& v) { Write(out, v); }, value);
89         return out;
90     }
91 
92     template <typename VALUE>
Write(std::ostream & out,VALUE && value)93     std::ostream& Write(std::ostream& out, VALUE&& value) {
94         return out << std::forward<VALUE>(value);
95     }
96 
97     template <typename FIRST, typename... REST>
Write(std::ostream & out,FIRST && first,REST &&...rest)98     inline std::ostream& Write(std::ostream& out, FIRST&& first, REST&&... rest) {
99         Write(out, std::forward<FIRST>(first));
100         Write(out, std::forward<REST>(rest)...);
101         return out;
102     }
103 
104     // Fatal() prints a message to stdout with the given file, line, function and optional message,
105     // then calls abort(). Fatal() is usually not called directly, but by the UNREACHABLE() and
106     // UNIMPLEMENTED() macro below.
107     template <typename... MSG_ARGS>
Fatal(const char * reason,const char * file,int line,const char * function,MSG_ARGS &&...msg_args)108     [[noreturn]] inline void Fatal(const char* reason,
109                                    const char* file,
110                                    int line,
111                                    const char* function,
112                                    MSG_ARGS&&... msg_args) {
113         std::stringstream msg;
114         msg << file << ":" << line << ": " << reason << ": " << function << "()";
115         if constexpr (sizeof...(msg_args) > 0) {
116             msg << " ";
117             Write(msg, std::forward<MSG_ARGS>(msg_args)...);
118         }
119         std::cout << msg.str() << std::endl;
120         abort();
121     }
122 
123 // LOG() prints the current file, line and function to stdout, followed by a
124 // string representation of all the variadic arguments.
125 #define LOG(...)                                                                                  \
126     ::wgpu::utils::Write(std::cout << __FILE__ << ":" << __LINE__ << " " << __FUNCTION__ << ": ", \
127                          ##__VA_ARGS__)                                                           \
128         << std::endl
129 
130 // UNIMPLEMENTED() prints 'UNIMPLEMENTED' with the current file, line and
131 // function to stdout, along with the optional message, then calls abort().
132 // The macro calls Fatal(), which is annotated with [[noreturn]].
133 // Used to stub code that has not yet been implemented.
134 #define UNIMPLEMENTED(...) \
135     ::wgpu::utils::Fatal("UNIMPLEMENTED", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)
136 
137 // UNREACHABLE() prints 'UNREACHABLE' with the current file, line and
138 // function to stdout, along with the optional message, then calls abort().
139 // The macro calls Fatal(), which is annotated with [[noreturn]].
140 // Used to stub code that has not yet been implemented.
141 #define UNREACHABLE(...) \
142     ::wgpu::utils::Fatal("UNREACHABLE", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)
143 
144 }}  // namespace wgpu::utils
145 
146 #endif  // DAWNNODE_UTILS_DEBUG_H_
147