1 // Copyright (c) 2015-2016 The Khronos Group Inc.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 #include "source/diagnostic.h"
23 #include "source/table.h"
27 spv_diagnostic
spvDiagnosticCreate(const spv_position position
,
28 const char* message
) {
29 spv_diagnostic diagnostic
= new spv_diagnostic_t
;
30 if (!diagnostic
) return nullptr;
31 size_t length
= strlen(message
) + 1;
32 diagnostic
->error
= new char[length
];
33 if (!diagnostic
->error
) {
37 diagnostic
->position
= *position
;
38 diagnostic
->isTextSource
= false;
39 memset(diagnostic
->error
, 0, length
);
40 strcpy(diagnostic
->error
, message
);
44 void spvDiagnosticDestroy(spv_diagnostic diagnostic
) {
45 if (!diagnostic
) return;
46 delete[] diagnostic
->error
;
50 spv_result_t
spvDiagnosticPrint(const spv_diagnostic diagnostic
) {
51 if (!diagnostic
) return SPV_ERROR_INVALID_DIAGNOSTIC
;
53 if (diagnostic
->isTextSource
) {
54 // NOTE: This is a text position
55 // NOTE: add 1 to the line as editors start at line 1, we are counting new
56 // line characters to start at line 0
57 std::cerr
<< "error: " << diagnostic
->position
.line
+ 1 << ": "
58 << diagnostic
->position
.column
+ 1 << ": " << diagnostic
->error
63 // NOTE: Assume this is a binary position
64 std::cerr
<< "error: ";
65 if (diagnostic
->position
.index
> 0)
66 std::cerr
<< diagnostic
->position
.index
<< ": ";
67 std::cerr
<< diagnostic
->error
<< "\n";
73 DiagnosticStream::DiagnosticStream(DiagnosticStream
&& other
)
75 position_(other
.position_
),
76 consumer_(other
.consumer_
),
77 disassembled_instruction_(std::move(other
.disassembled_instruction_
)),
78 error_(other
.error_
) {
79 // Prevent the other object from emitting output during destruction.
80 other
.error_
= SPV_FAILED_MATCH
;
81 // Some platforms are missing support for std::ostringstream functionality,
82 // including: move constructor, swap method. Either would have been a
83 // better choice than copying the string.
84 stream_
<< other
.stream_
.str();
87 DiagnosticStream::~DiagnosticStream() {
88 if (error_
!= SPV_FAILED_MATCH
&& consumer_
!= nullptr) {
89 auto level
= SPV_MSG_ERROR
;
92 case SPV_REQUESTED_TERMINATION
: // Essentially success.
96 level
= SPV_MSG_WARNING
;
99 case SPV_ERROR_INTERNAL
:
100 case SPV_ERROR_INVALID_TABLE
:
101 level
= SPV_MSG_INTERNAL_ERROR
;
103 case SPV_ERROR_OUT_OF_MEMORY
:
104 level
= SPV_MSG_FATAL
;
109 if (disassembled_instruction_
.size() > 0)
110 stream_
<< std::endl
<< " " << disassembled_instruction_
<< std::endl
;
112 consumer_(level
, "input", position_
, stream_
.str().c_str());
116 void UseDiagnosticAsMessageConsumer(spv_context context
,
117 spv_diagnostic
* diagnostic
) {
118 assert(diagnostic
&& *diagnostic
== nullptr);
120 auto create_diagnostic
= [diagnostic
](spv_message_level_t
, const char*,
121 const spv_position_t
& position
,
122 const char* message
) {
124 spvDiagnosticDestroy(*diagnostic
); // Avoid memory leak.
125 *diagnostic
= spvDiagnosticCreate(&p
, message
);
127 SetContextMessageConsumer(context
, std::move(create_diagnostic
));
130 std::string
spvResultToString(spv_result_t res
) {
136 case SPV_UNSUPPORTED
:
137 out
= "SPV_UNSUPPORTED";
139 case SPV_END_OF_STREAM
:
140 out
= "SPV_END_OF_STREAM";
145 case SPV_FAILED_MATCH
:
146 out
= "SPV_FAILED_MATCH";
148 case SPV_REQUESTED_TERMINATION
:
149 out
= "SPV_REQUESTED_TERMINATION";
151 case SPV_ERROR_INTERNAL
:
152 out
= "SPV_ERROR_INTERNAL";
154 case SPV_ERROR_OUT_OF_MEMORY
:
155 out
= "SPV_ERROR_OUT_OF_MEMORY";
157 case SPV_ERROR_INVALID_POINTER
:
158 out
= "SPV_ERROR_INVALID_POINTER";
160 case SPV_ERROR_INVALID_BINARY
:
161 out
= "SPV_ERROR_INVALID_BINARY";
163 case SPV_ERROR_INVALID_TEXT
:
164 out
= "SPV_ERROR_INVALID_TEXT";
166 case SPV_ERROR_INVALID_TABLE
:
167 out
= "SPV_ERROR_INVALID_TABLE";
169 case SPV_ERROR_INVALID_VALUE
:
170 out
= "SPV_ERROR_INVALID_VALUE";
172 case SPV_ERROR_INVALID_DIAGNOSTIC
:
173 out
= "SPV_ERROR_INVALID_DIAGNOSTIC";
175 case SPV_ERROR_INVALID_LOOKUP
:
176 out
= "SPV_ERROR_INVALID_LOOKUP";
178 case SPV_ERROR_INVALID_ID
:
179 out
= "SPV_ERROR_INVALID_ID";
181 case SPV_ERROR_INVALID_CFG
:
182 out
= "SPV_ERROR_INVALID_CFG";
184 case SPV_ERROR_INVALID_LAYOUT
:
185 out
= "SPV_ERROR_INVALID_LAYOUT";
188 out
= "Unknown Error";
193 } // namespace spvtools