• 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 #include "dawn_native/CompilationMessages.h"
16 
17 #include "common/Assert.h"
18 #include "dawn_native/dawn_platform.h"
19 
20 #include <tint/tint.h>
21 
22 namespace dawn_native {
23 
24     namespace {
25 
tintSeverityToMessageType(tint::diag::Severity severity)26         WGPUCompilationMessageType tintSeverityToMessageType(tint::diag::Severity severity) {
27             switch (severity) {
28                 case tint::diag::Severity::Note:
29                     return WGPUCompilationMessageType_Info;
30                 case tint::diag::Severity::Warning:
31                     return WGPUCompilationMessageType_Warning;
32                 default:
33                     return WGPUCompilationMessageType_Error;
34             }
35         }
36 
37     }  // anonymous namespace
38 
OwnedCompilationMessages()39     OwnedCompilationMessages::OwnedCompilationMessages() {
40         mCompilationInfo.nextInChain = 0;
41         mCompilationInfo.messageCount = 0;
42         mCompilationInfo.messages = nullptr;
43     }
44 
AddMessageForTesting(std::string message,wgpu::CompilationMessageType type,uint64_t lineNum,uint64_t linePos,uint64_t offset,uint64_t length)45     void OwnedCompilationMessages::AddMessageForTesting(std::string message,
46                                                         wgpu::CompilationMessageType type,
47                                                         uint64_t lineNum,
48                                                         uint64_t linePos,
49                                                         uint64_t offset,
50                                                         uint64_t length) {
51         // Cannot add messages after GetCompilationInfo has been called.
52         ASSERT(mCompilationInfo.messages == nullptr);
53 
54         mMessageStrings.push_back(message);
55         mMessages.push_back({nullptr, nullptr, static_cast<WGPUCompilationMessageType>(type),
56                              lineNum, linePos, offset, length});
57     }
58 
AddMessage(const tint::diag::Diagnostic & diagnostic)59     void OwnedCompilationMessages::AddMessage(const tint::diag::Diagnostic& diagnostic) {
60         // Cannot add messages after GetCompilationInfo has been called.
61         ASSERT(mCompilationInfo.messages == nullptr);
62 
63         // Tint line and column values are 1-based.
64         uint64_t lineNum = diagnostic.source.range.begin.line;
65         uint64_t linePos = diagnostic.source.range.begin.column;
66         // The offset is 0-based.
67         uint64_t offset = 0;
68         uint64_t length = 0;
69 
70         if (lineNum && linePos && diagnostic.source.file_content) {
71             const std::vector<std::string>& lines = diagnostic.source.file_content->lines;
72             size_t i = 0;
73             // To find the offset of the message position, loop through each of the first lineNum-1
74             // lines and add it's length (+1 to account for the line break) to the offset.
75             for (; i < lineNum - 1; ++i) {
76                 offset += lines[i].length() + 1;
77             }
78 
79             // If the end line is on a different line from the beginning line, add the length of the
80             // lines in between to the ending offset.
81             uint64_t endLineNum = diagnostic.source.range.end.line;
82             uint64_t endLinePos = diagnostic.source.range.end.column;
83             uint64_t endOffset = offset;
84             for (; i < endLineNum - 1; ++i) {
85                 endOffset += lines[i].length() + 1;
86             }
87 
88             // Add the line positions to the offset and endOffset to get their final positions
89             // within the code string.
90             offset += linePos - 1;
91             endOffset += endLinePos - 1;
92 
93             // The length of the message is the difference between the starting offset and the
94             // ending offset.
95             length = endOffset - offset;
96         }
97 
98         if (diagnostic.code) {
99             mMessageStrings.push_back(std::string(diagnostic.code) + ": " + diagnostic.message);
100         } else {
101             mMessageStrings.push_back(diagnostic.message);
102         }
103 
104         mMessages.push_back({nullptr, nullptr, tintSeverityToMessageType(diagnostic.severity),
105                              lineNum, linePos, offset, length});
106     }
107 
AddMessages(const tint::diag::List & diagnostics)108     void OwnedCompilationMessages::AddMessages(const tint::diag::List& diagnostics) {
109         // Cannot add messages after GetCompilationInfo has been called.
110         ASSERT(mCompilationInfo.messages == nullptr);
111 
112         for (const auto& diag : diagnostics) {
113             AddMessage(diag);
114         }
115 
116         AddFormattedTintMessages(diagnostics);
117     }
118 
ClearMessages()119     void OwnedCompilationMessages::ClearMessages() {
120         // Cannot clear messages after GetCompilationInfo has been called.
121         ASSERT(mCompilationInfo.messages == nullptr);
122 
123         mMessageStrings.clear();
124         mMessages.clear();
125     }
126 
GetCompilationInfo()127     const WGPUCompilationInfo* OwnedCompilationMessages::GetCompilationInfo() {
128         mCompilationInfo.messageCount = mMessages.size();
129         mCompilationInfo.messages = mMessages.data();
130 
131         // Ensure every message points at the correct message string. Cannot do this earlier, since
132         // vector reallocations may move the pointers around.
133         for (size_t i = 0; i < mCompilationInfo.messageCount; ++i) {
134             WGPUCompilationMessage& message = mMessages[i];
135             std::string& messageString = mMessageStrings[i];
136             message.message = messageString.c_str();
137         }
138 
139         return &mCompilationInfo;
140     }
141 
GetFormattedTintMessages()142     const std::vector<std::string>& OwnedCompilationMessages::GetFormattedTintMessages() {
143         return mFormattedTintMessages;
144     }
145 
AddFormattedTintMessages(const tint::diag::List & diagnostics)146     void OwnedCompilationMessages::AddFormattedTintMessages(const tint::diag::List& diagnostics) {
147         tint::diag::List messageList;
148         size_t warningCount = 0;
149         size_t errorCount = 0;
150         for (auto& diag : diagnostics) {
151             switch (diag.severity) {
152                 case (tint::diag::Severity::Fatal):
153                 case (tint::diag::Severity::Error):
154                 case (tint::diag::Severity::InternalCompilerError): {
155                     errorCount++;
156                     messageList.add(tint::diag::Diagnostic(diag));
157                     break;
158                 }
159                 case (tint::diag::Severity::Warning): {
160                     warningCount++;
161                     messageList.add(tint::diag::Diagnostic(diag));
162                     break;
163                 }
164                 default:
165                     break;
166             }
167         }
168         if (errorCount == 0 && warningCount == 0) {
169             return;
170         }
171         tint::diag::Formatter::Style style;
172         style.print_newline_at_end = false;
173         std::ostringstream t;
174         if (errorCount > 0) {
175             t << errorCount << " error(s) ";
176             if (warningCount > 0) {
177                 t << "and ";
178             }
179         }
180         if (warningCount > 0) {
181             t << warningCount << " warning(s) ";
182         }
183         t << "generated while compiling the shader:" << std::endl
184           << tint::diag::Formatter{style}.format(messageList);
185         mFormattedTintMessages.push_back(t.str());
186     }
187 
188 }  // namespace dawn_native
189