1*03ce13f7SAndroid Build Coastguard Worker // Copyright (c) 2015-2016 The Khronos Group Inc.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker
15*03ce13f7SAndroid Build Coastguard Worker #include "source/diagnostic.h"
16*03ce13f7SAndroid Build Coastguard Worker
17*03ce13f7SAndroid Build Coastguard Worker #include <cassert>
18*03ce13f7SAndroid Build Coastguard Worker #include <cstring>
19*03ce13f7SAndroid Build Coastguard Worker #include <iostream>
20*03ce13f7SAndroid Build Coastguard Worker #include <sstream>
21*03ce13f7SAndroid Build Coastguard Worker #include <utility>
22*03ce13f7SAndroid Build Coastguard Worker
23*03ce13f7SAndroid Build Coastguard Worker #include "source/table.h"
24*03ce13f7SAndroid Build Coastguard Worker
25*03ce13f7SAndroid Build Coastguard Worker // Diagnostic API
26*03ce13f7SAndroid Build Coastguard Worker
spvDiagnosticCreate(const spv_position position,const char * message)27*03ce13f7SAndroid Build Coastguard Worker spv_diagnostic spvDiagnosticCreate(const spv_position position,
28*03ce13f7SAndroid Build Coastguard Worker const char* message) {
29*03ce13f7SAndroid Build Coastguard Worker spv_diagnostic diagnostic = new spv_diagnostic_t;
30*03ce13f7SAndroid Build Coastguard Worker if (!diagnostic) return nullptr;
31*03ce13f7SAndroid Build Coastguard Worker size_t length = strlen(message) + 1;
32*03ce13f7SAndroid Build Coastguard Worker diagnostic->error = new char[length];
33*03ce13f7SAndroid Build Coastguard Worker if (!diagnostic->error) {
34*03ce13f7SAndroid Build Coastguard Worker delete diagnostic;
35*03ce13f7SAndroid Build Coastguard Worker return nullptr;
36*03ce13f7SAndroid Build Coastguard Worker }
37*03ce13f7SAndroid Build Coastguard Worker diagnostic->position = *position;
38*03ce13f7SAndroid Build Coastguard Worker diagnostic->isTextSource = false;
39*03ce13f7SAndroid Build Coastguard Worker memset(diagnostic->error, 0, length);
40*03ce13f7SAndroid Build Coastguard Worker strcpy(diagnostic->error, message);
41*03ce13f7SAndroid Build Coastguard Worker return diagnostic;
42*03ce13f7SAndroid Build Coastguard Worker }
43*03ce13f7SAndroid Build Coastguard Worker
spvDiagnosticDestroy(spv_diagnostic diagnostic)44*03ce13f7SAndroid Build Coastguard Worker void spvDiagnosticDestroy(spv_diagnostic diagnostic) {
45*03ce13f7SAndroid Build Coastguard Worker if (!diagnostic) return;
46*03ce13f7SAndroid Build Coastguard Worker delete[] diagnostic->error;
47*03ce13f7SAndroid Build Coastguard Worker delete diagnostic;
48*03ce13f7SAndroid Build Coastguard Worker }
49*03ce13f7SAndroid Build Coastguard Worker
spvDiagnosticPrint(const spv_diagnostic diagnostic)50*03ce13f7SAndroid Build Coastguard Worker spv_result_t spvDiagnosticPrint(const spv_diagnostic diagnostic) {
51*03ce13f7SAndroid Build Coastguard Worker if (!diagnostic) return SPV_ERROR_INVALID_DIAGNOSTIC;
52*03ce13f7SAndroid Build Coastguard Worker
53*03ce13f7SAndroid Build Coastguard Worker if (diagnostic->isTextSource) {
54*03ce13f7SAndroid Build Coastguard Worker // NOTE: This is a text position
55*03ce13f7SAndroid Build Coastguard Worker // NOTE: add 1 to the line as editors start at line 1, we are counting new
56*03ce13f7SAndroid Build Coastguard Worker // line characters to start at line 0
57*03ce13f7SAndroid Build Coastguard Worker std::cerr << "error: " << diagnostic->position.line + 1 << ": "
58*03ce13f7SAndroid Build Coastguard Worker << diagnostic->position.column + 1 << ": " << diagnostic->error
59*03ce13f7SAndroid Build Coastguard Worker << "\n";
60*03ce13f7SAndroid Build Coastguard Worker return SPV_SUCCESS;
61*03ce13f7SAndroid Build Coastguard Worker }
62*03ce13f7SAndroid Build Coastguard Worker
63*03ce13f7SAndroid Build Coastguard Worker // NOTE: Assume this is a binary position
64*03ce13f7SAndroid Build Coastguard Worker std::cerr << "error: ";
65*03ce13f7SAndroid Build Coastguard Worker if (diagnostic->position.index > 0)
66*03ce13f7SAndroid Build Coastguard Worker std::cerr << diagnostic->position.index << ": ";
67*03ce13f7SAndroid Build Coastguard Worker std::cerr << diagnostic->error << "\n";
68*03ce13f7SAndroid Build Coastguard Worker return SPV_SUCCESS;
69*03ce13f7SAndroid Build Coastguard Worker }
70*03ce13f7SAndroid Build Coastguard Worker
71*03ce13f7SAndroid Build Coastguard Worker namespace spvtools {
72*03ce13f7SAndroid Build Coastguard Worker
DiagnosticStream(DiagnosticStream && other)73*03ce13f7SAndroid Build Coastguard Worker DiagnosticStream::DiagnosticStream(DiagnosticStream&& other)
74*03ce13f7SAndroid Build Coastguard Worker : stream_(),
75*03ce13f7SAndroid Build Coastguard Worker position_(other.position_),
76*03ce13f7SAndroid Build Coastguard Worker consumer_(other.consumer_),
77*03ce13f7SAndroid Build Coastguard Worker disassembled_instruction_(std::move(other.disassembled_instruction_)),
78*03ce13f7SAndroid Build Coastguard Worker error_(other.error_) {
79*03ce13f7SAndroid Build Coastguard Worker // Prevent the other object from emitting output during destruction.
80*03ce13f7SAndroid Build Coastguard Worker other.error_ = SPV_FAILED_MATCH;
81*03ce13f7SAndroid Build Coastguard Worker // Some platforms are missing support for std::ostringstream functionality,
82*03ce13f7SAndroid Build Coastguard Worker // including: move constructor, swap method. Either would have been a
83*03ce13f7SAndroid Build Coastguard Worker // better choice than copying the string.
84*03ce13f7SAndroid Build Coastguard Worker stream_ << other.stream_.str();
85*03ce13f7SAndroid Build Coastguard Worker }
86*03ce13f7SAndroid Build Coastguard Worker
~DiagnosticStream()87*03ce13f7SAndroid Build Coastguard Worker DiagnosticStream::~DiagnosticStream() {
88*03ce13f7SAndroid Build Coastguard Worker if (error_ != SPV_FAILED_MATCH && consumer_ != nullptr) {
89*03ce13f7SAndroid Build Coastguard Worker auto level = SPV_MSG_ERROR;
90*03ce13f7SAndroid Build Coastguard Worker switch (error_) {
91*03ce13f7SAndroid Build Coastguard Worker case SPV_SUCCESS:
92*03ce13f7SAndroid Build Coastguard Worker case SPV_REQUESTED_TERMINATION: // Essentially success.
93*03ce13f7SAndroid Build Coastguard Worker level = SPV_MSG_INFO;
94*03ce13f7SAndroid Build Coastguard Worker break;
95*03ce13f7SAndroid Build Coastguard Worker case SPV_WARNING:
96*03ce13f7SAndroid Build Coastguard Worker level = SPV_MSG_WARNING;
97*03ce13f7SAndroid Build Coastguard Worker break;
98*03ce13f7SAndroid Build Coastguard Worker case SPV_UNSUPPORTED:
99*03ce13f7SAndroid Build Coastguard Worker case SPV_ERROR_INTERNAL:
100*03ce13f7SAndroid Build Coastguard Worker case SPV_ERROR_INVALID_TABLE:
101*03ce13f7SAndroid Build Coastguard Worker level = SPV_MSG_INTERNAL_ERROR;
102*03ce13f7SAndroid Build Coastguard Worker break;
103*03ce13f7SAndroid Build Coastguard Worker case SPV_ERROR_OUT_OF_MEMORY:
104*03ce13f7SAndroid Build Coastguard Worker level = SPV_MSG_FATAL;
105*03ce13f7SAndroid Build Coastguard Worker break;
106*03ce13f7SAndroid Build Coastguard Worker default:
107*03ce13f7SAndroid Build Coastguard Worker break;
108*03ce13f7SAndroid Build Coastguard Worker }
109*03ce13f7SAndroid Build Coastguard Worker if (disassembled_instruction_.size() > 0)
110*03ce13f7SAndroid Build Coastguard Worker stream_ << std::endl << " " << disassembled_instruction_ << std::endl;
111*03ce13f7SAndroid Build Coastguard Worker
112*03ce13f7SAndroid Build Coastguard Worker consumer_(level, "input", position_, stream_.str().c_str());
113*03ce13f7SAndroid Build Coastguard Worker }
114*03ce13f7SAndroid Build Coastguard Worker }
115*03ce13f7SAndroid Build Coastguard Worker
UseDiagnosticAsMessageConsumer(spv_context context,spv_diagnostic * diagnostic)116*03ce13f7SAndroid Build Coastguard Worker void UseDiagnosticAsMessageConsumer(spv_context context,
117*03ce13f7SAndroid Build Coastguard Worker spv_diagnostic* diagnostic) {
118*03ce13f7SAndroid Build Coastguard Worker assert(diagnostic && *diagnostic == nullptr);
119*03ce13f7SAndroid Build Coastguard Worker
120*03ce13f7SAndroid Build Coastguard Worker auto create_diagnostic = [diagnostic](spv_message_level_t, const char*,
121*03ce13f7SAndroid Build Coastguard Worker const spv_position_t& position,
122*03ce13f7SAndroid Build Coastguard Worker const char* message) {
123*03ce13f7SAndroid Build Coastguard Worker auto p = position;
124*03ce13f7SAndroid Build Coastguard Worker spvDiagnosticDestroy(*diagnostic); // Avoid memory leak.
125*03ce13f7SAndroid Build Coastguard Worker *diagnostic = spvDiagnosticCreate(&p, message);
126*03ce13f7SAndroid Build Coastguard Worker };
127*03ce13f7SAndroid Build Coastguard Worker SetContextMessageConsumer(context, std::move(create_diagnostic));
128*03ce13f7SAndroid Build Coastguard Worker }
129*03ce13f7SAndroid Build Coastguard Worker
spvResultToString(spv_result_t res)130*03ce13f7SAndroid Build Coastguard Worker std::string spvResultToString(spv_result_t res) {
131*03ce13f7SAndroid Build Coastguard Worker std::string out;
132*03ce13f7SAndroid Build Coastguard Worker switch (res) {
133*03ce13f7SAndroid Build Coastguard Worker case SPV_SUCCESS:
134*03ce13f7SAndroid Build Coastguard Worker out = "SPV_SUCCESS";
135*03ce13f7SAndroid Build Coastguard Worker break;
136*03ce13f7SAndroid Build Coastguard Worker case SPV_UNSUPPORTED:
137*03ce13f7SAndroid Build Coastguard Worker out = "SPV_UNSUPPORTED";
138*03ce13f7SAndroid Build Coastguard Worker break;
139*03ce13f7SAndroid Build Coastguard Worker case SPV_END_OF_STREAM:
140*03ce13f7SAndroid Build Coastguard Worker out = "SPV_END_OF_STREAM";
141*03ce13f7SAndroid Build Coastguard Worker break;
142*03ce13f7SAndroid Build Coastguard Worker case SPV_WARNING:
143*03ce13f7SAndroid Build Coastguard Worker out = "SPV_WARNING";
144*03ce13f7SAndroid Build Coastguard Worker break;
145*03ce13f7SAndroid Build Coastguard Worker case SPV_FAILED_MATCH:
146*03ce13f7SAndroid Build Coastguard Worker out = "SPV_FAILED_MATCH";
147*03ce13f7SAndroid Build Coastguard Worker break;
148*03ce13f7SAndroid Build Coastguard Worker case SPV_REQUESTED_TERMINATION:
149*03ce13f7SAndroid Build Coastguard Worker out = "SPV_REQUESTED_TERMINATION";
150*03ce13f7SAndroid Build Coastguard Worker break;
151*03ce13f7SAndroid Build Coastguard Worker case SPV_ERROR_INTERNAL:
152*03ce13f7SAndroid Build Coastguard Worker out = "SPV_ERROR_INTERNAL";
153*03ce13f7SAndroid Build Coastguard Worker break;
154*03ce13f7SAndroid Build Coastguard Worker case SPV_ERROR_OUT_OF_MEMORY:
155*03ce13f7SAndroid Build Coastguard Worker out = "SPV_ERROR_OUT_OF_MEMORY";
156*03ce13f7SAndroid Build Coastguard Worker break;
157*03ce13f7SAndroid Build Coastguard Worker case SPV_ERROR_INVALID_POINTER:
158*03ce13f7SAndroid Build Coastguard Worker out = "SPV_ERROR_INVALID_POINTER";
159*03ce13f7SAndroid Build Coastguard Worker break;
160*03ce13f7SAndroid Build Coastguard Worker case SPV_ERROR_INVALID_BINARY:
161*03ce13f7SAndroid Build Coastguard Worker out = "SPV_ERROR_INVALID_BINARY";
162*03ce13f7SAndroid Build Coastguard Worker break;
163*03ce13f7SAndroid Build Coastguard Worker case SPV_ERROR_INVALID_TEXT:
164*03ce13f7SAndroid Build Coastguard Worker out = "SPV_ERROR_INVALID_TEXT";
165*03ce13f7SAndroid Build Coastguard Worker break;
166*03ce13f7SAndroid Build Coastguard Worker case SPV_ERROR_INVALID_TABLE:
167*03ce13f7SAndroid Build Coastguard Worker out = "SPV_ERROR_INVALID_TABLE";
168*03ce13f7SAndroid Build Coastguard Worker break;
169*03ce13f7SAndroid Build Coastguard Worker case SPV_ERROR_INVALID_VALUE:
170*03ce13f7SAndroid Build Coastguard Worker out = "SPV_ERROR_INVALID_VALUE";
171*03ce13f7SAndroid Build Coastguard Worker break;
172*03ce13f7SAndroid Build Coastguard Worker case SPV_ERROR_INVALID_DIAGNOSTIC:
173*03ce13f7SAndroid Build Coastguard Worker out = "SPV_ERROR_INVALID_DIAGNOSTIC";
174*03ce13f7SAndroid Build Coastguard Worker break;
175*03ce13f7SAndroid Build Coastguard Worker case SPV_ERROR_INVALID_LOOKUP:
176*03ce13f7SAndroid Build Coastguard Worker out = "SPV_ERROR_INVALID_LOOKUP";
177*03ce13f7SAndroid Build Coastguard Worker break;
178*03ce13f7SAndroid Build Coastguard Worker case SPV_ERROR_INVALID_ID:
179*03ce13f7SAndroid Build Coastguard Worker out = "SPV_ERROR_INVALID_ID";
180*03ce13f7SAndroid Build Coastguard Worker break;
181*03ce13f7SAndroid Build Coastguard Worker case SPV_ERROR_INVALID_CFG:
182*03ce13f7SAndroid Build Coastguard Worker out = "SPV_ERROR_INVALID_CFG";
183*03ce13f7SAndroid Build Coastguard Worker break;
184*03ce13f7SAndroid Build Coastguard Worker case SPV_ERROR_INVALID_LAYOUT:
185*03ce13f7SAndroid Build Coastguard Worker out = "SPV_ERROR_INVALID_LAYOUT";
186*03ce13f7SAndroid Build Coastguard Worker break;
187*03ce13f7SAndroid Build Coastguard Worker default:
188*03ce13f7SAndroid Build Coastguard Worker out = "Unknown Error";
189*03ce13f7SAndroid Build Coastguard Worker }
190*03ce13f7SAndroid Build Coastguard Worker return out;
191*03ce13f7SAndroid Build Coastguard Worker }
192*03ce13f7SAndroid Build Coastguard Worker
193*03ce13f7SAndroid Build Coastguard Worker } // namespace spvtools
194