diagnostic.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // Copyright (c) 2015-2016 The Khronos Group Inc.
  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. #include "source/diagnostic.h"
  15. #include <cassert>
  16. #include <cstring>
  17. #include <iostream>
  18. #include <sstream>
  19. #include <utility>
  20. #include "source/table.h"
  21. // Diagnostic API
  22. spv_diagnostic spvDiagnosticCreate(const spv_position position,
  23. const char* message) {
  24. spv_diagnostic diagnostic = new spv_diagnostic_t;
  25. if (!diagnostic) return nullptr;
  26. size_t length = strlen(message) + 1;
  27. diagnostic->error = new char[length];
  28. if (!diagnostic->error) {
  29. delete diagnostic;
  30. return nullptr;
  31. }
  32. diagnostic->position = *position;
  33. diagnostic->isTextSource = false;
  34. memset(diagnostic->error, 0, length);
  35. strncpy(diagnostic->error, message, length);
  36. return diagnostic;
  37. }
  38. void spvDiagnosticDestroy(spv_diagnostic diagnostic) {
  39. if (!diagnostic) return;
  40. delete[] diagnostic->error;
  41. delete diagnostic;
  42. }
  43. spv_result_t spvDiagnosticPrint(const spv_diagnostic diagnostic) {
  44. if (!diagnostic) return SPV_ERROR_INVALID_DIAGNOSTIC;
  45. if (diagnostic->isTextSource) {
  46. // NOTE: This is a text position
  47. // NOTE: add 1 to the line as editors start at line 1, we are counting new
  48. // line characters to start at line 0
  49. std::cerr << "error: " << diagnostic->position.line + 1 << ": "
  50. << diagnostic->position.column + 1 << ": " << diagnostic->error
  51. << "\n";
  52. return SPV_SUCCESS;
  53. }
  54. // NOTE: Assume this is a binary position
  55. std::cerr << "error: ";
  56. if (diagnostic->position.index > 0)
  57. std::cerr << diagnostic->position.index << ": ";
  58. std::cerr << diagnostic->error << "\n";
  59. return SPV_SUCCESS;
  60. }
  61. namespace spvtools {
  62. DiagnosticStream::DiagnosticStream(DiagnosticStream&& other)
  63. : stream_(),
  64. position_(other.position_),
  65. consumer_(other.consumer_),
  66. disassembled_instruction_(std::move(other.disassembled_instruction_)),
  67. error_(other.error_) {
  68. // Prevent the other object from emitting output during destruction.
  69. other.error_ = SPV_FAILED_MATCH;
  70. // Some platforms are missing support for std::ostringstream functionality,
  71. // including: move constructor, swap method. Either would have been a
  72. // better choice than copying the string.
  73. stream_ << other.stream_.str();
  74. }
  75. DiagnosticStream::~DiagnosticStream() {
  76. if (error_ != SPV_FAILED_MATCH && consumer_ != nullptr) {
  77. auto level = SPV_MSG_ERROR;
  78. switch (error_) {
  79. case SPV_SUCCESS:
  80. case SPV_REQUESTED_TERMINATION: // Essentially success.
  81. level = SPV_MSG_INFO;
  82. break;
  83. case SPV_WARNING:
  84. level = SPV_MSG_WARNING;
  85. break;
  86. case SPV_UNSUPPORTED:
  87. case SPV_ERROR_INTERNAL:
  88. case SPV_ERROR_INVALID_TABLE:
  89. level = SPV_MSG_INTERNAL_ERROR;
  90. break;
  91. case SPV_ERROR_OUT_OF_MEMORY:
  92. level = SPV_MSG_FATAL;
  93. break;
  94. default:
  95. break;
  96. }
  97. if (disassembled_instruction_.size() > 0)
  98. stream_ << std::endl << " " << disassembled_instruction_ << std::endl;
  99. consumer_(level, "input", position_, stream_.str().c_str());
  100. }
  101. }
  102. void UseDiagnosticAsMessageConsumer(spv_context context,
  103. spv_diagnostic* diagnostic) {
  104. assert(diagnostic && *diagnostic == nullptr);
  105. auto create_diagnostic = [diagnostic](spv_message_level_t, const char*,
  106. const spv_position_t& position,
  107. const char* message) {
  108. auto p = position;
  109. spvDiagnosticDestroy(*diagnostic); // Avoid memory leak.
  110. *diagnostic = spvDiagnosticCreate(&p, message);
  111. };
  112. SetContextMessageConsumer(context, std::move(create_diagnostic));
  113. }
  114. std::string spvResultToString(spv_result_t res) {
  115. std::string out;
  116. switch (res) {
  117. case SPV_SUCCESS:
  118. out = "SPV_SUCCESS";
  119. break;
  120. case SPV_UNSUPPORTED:
  121. out = "SPV_UNSUPPORTED";
  122. break;
  123. case SPV_END_OF_STREAM:
  124. out = "SPV_END_OF_STREAM";
  125. break;
  126. case SPV_WARNING:
  127. out = "SPV_WARNING";
  128. break;
  129. case SPV_FAILED_MATCH:
  130. out = "SPV_FAILED_MATCH";
  131. break;
  132. case SPV_REQUESTED_TERMINATION:
  133. out = "SPV_REQUESTED_TERMINATION";
  134. break;
  135. case SPV_ERROR_INTERNAL:
  136. out = "SPV_ERROR_INTERNAL";
  137. break;
  138. case SPV_ERROR_OUT_OF_MEMORY:
  139. out = "SPV_ERROR_OUT_OF_MEMORY";
  140. break;
  141. case SPV_ERROR_INVALID_POINTER:
  142. out = "SPV_ERROR_INVALID_POINTER";
  143. break;
  144. case SPV_ERROR_INVALID_BINARY:
  145. out = "SPV_ERROR_INVALID_BINARY";
  146. break;
  147. case SPV_ERROR_INVALID_TEXT:
  148. out = "SPV_ERROR_INVALID_TEXT";
  149. break;
  150. case SPV_ERROR_INVALID_TABLE:
  151. out = "SPV_ERROR_INVALID_TABLE";
  152. break;
  153. case SPV_ERROR_INVALID_VALUE:
  154. out = "SPV_ERROR_INVALID_VALUE";
  155. break;
  156. case SPV_ERROR_INVALID_DIAGNOSTIC:
  157. out = "SPV_ERROR_INVALID_DIAGNOSTIC";
  158. break;
  159. case SPV_ERROR_INVALID_LOOKUP:
  160. out = "SPV_ERROR_INVALID_LOOKUP";
  161. break;
  162. case SPV_ERROR_INVALID_ID:
  163. out = "SPV_ERROR_INVALID_ID";
  164. break;
  165. case SPV_ERROR_INVALID_CFG:
  166. out = "SPV_ERROR_INVALID_CFG";
  167. break;
  168. case SPV_ERROR_INVALID_LAYOUT:
  169. out = "SPV_ERROR_INVALID_LAYOUT";
  170. break;
  171. default:
  172. out = "Unknown Error";
  173. }
  174. return out;
  175. }
  176. } // namespace spvtools