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