Coverage Report

Created: 2023-03-01 07:33

/src/spirv-tools/source/diagnostic.cpp
Line
Count
Source (jump to first uncovered line)
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 "source/diagnostic.h"
16
17
#include <cassert>
18
#include <cstring>
19
#include <iostream>
20
#include <sstream>
21
#include <utility>
22
23
#include "source/table.h"
24
25
// Diagnostic API
26
27
spv_diagnostic spvDiagnosticCreate(const spv_position position,
28
643k
                                   const char* message) {
29
643k
  spv_diagnostic diagnostic = new spv_diagnostic_t;
30
643k
  if (!diagnostic) return nullptr;
31
643k
  size_t length = strlen(message) + 1;
32
643k
  diagnostic->error = new char[length];
33
643k
  if (!diagnostic->error) {
34
0
    delete diagnostic;
35
0
    return nullptr;
36
0
  }
37
643k
  diagnostic->position = *position;
38
643k
  diagnostic->isTextSource = false;
39
643k
  memset(diagnostic->error, 0, length);
40
643k
  strcpy(diagnostic->error, message);
41
643k
  return diagnostic;
42
643k
}
43
44
1.42M
void spvDiagnosticDestroy(spv_diagnostic diagnostic) {
45
1.42M
  if (!diagnostic) return;
46
643k
  delete[] diagnostic->error;
47
643k
  delete diagnostic;
48
643k
}
49
50
9.34k
spv_result_t spvDiagnosticPrint(const spv_diagnostic diagnostic) {
51
9.34k
  if (!diagnostic) return SPV_ERROR_INVALID_DIAGNOSTIC;
52
53
9.34k
  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
9.34k
    std::cerr << "error: " << diagnostic->position.line + 1 << ": "
58
9.34k
              << diagnostic->position.column + 1 << ": " << diagnostic->error
59
9.34k
              << "\n";
60
9.34k
    return SPV_SUCCESS;
61
9.34k
  }
62
63
  // NOTE: Assume this is a binary position
64
0
  std::cerr << "error: ";
65
0
  if (diagnostic->position.index > 0)
66
0
    std::cerr << diagnostic->position.index << ": ";
67
0
  std::cerr << diagnostic->error << "\n";
68
0
  return SPV_SUCCESS;
69
9.34k
}
70
71
namespace spvtools {
72
73
DiagnosticStream::DiagnosticStream(DiagnosticStream&& other)
74
    : stream_(),
75
      position_(other.position_),
76
      consumer_(other.consumer_),
77
      disassembled_instruction_(std::move(other.disassembled_instruction_)),
78
64
      error_(other.error_) {
79
  // Prevent the other object from emitting output during destruction.
80
64
  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
64
  stream_ << other.stream_.str();
85
64
}
86
87
1.02M
DiagnosticStream::~DiagnosticStream() {
88
1.02M
  if (error_ != SPV_FAILED_MATCH && consumer_ != nullptr) {
89
654k
    auto level = SPV_MSG_ERROR;
90
654k
    switch (error_) {
91
0
      case SPV_SUCCESS:
92
0
      case SPV_REQUESTED_TERMINATION:  // Essentially success.
93
0
        level = SPV_MSG_INFO;
94
0
        break;
95
5.38k
      case SPV_WARNING:
96
5.38k
        level = SPV_MSG_WARNING;
97
5.38k
        break;
98
0
      case SPV_UNSUPPORTED:
99
11.4k
      case SPV_ERROR_INTERNAL:
100
11.4k
      case SPV_ERROR_INVALID_TABLE:
101
11.4k
        level = SPV_MSG_INTERNAL_ERROR;
102
11.4k
        break;
103
12
      case SPV_ERROR_OUT_OF_MEMORY:
104
12
        level = SPV_MSG_FATAL;
105
12
        break;
106
637k
      default:
107
637k
        break;
108
654k
    }
109
654k
    if (disassembled_instruction_.size() > 0)
110
13.0k
      stream_ << std::endl << "  " << disassembled_instruction_ << std::endl;
111
112
654k
    consumer_(level, "input", position_, stream_.str().c_str());
113
654k
  }
114
1.02M
}
115
116
void UseDiagnosticAsMessageConsumer(spv_context context,
117
1.82M
                                    spv_diagnostic* diagnostic) {
118
1.82M
  assert(diagnostic && *diagnostic == nullptr);
119
120
0
  auto create_diagnostic = [diagnostic](spv_message_level_t, const char*,
121
1.82M
                                        const spv_position_t& position,
122
1.82M
                                        const char* message) {
123
643k
    auto p = position;
124
643k
    spvDiagnosticDestroy(*diagnostic);  // Avoid memory leak.
125
643k
    *diagnostic = spvDiagnosticCreate(&p, message);
126
643k
  };
127
1.82M
  SetContextMessageConsumer(context, std::move(create_diagnostic));
128
1.82M
}
129
130
0
std::string spvResultToString(spv_result_t res) {
131
0
  std::string out;
132
0
  switch (res) {
133
0
    case SPV_SUCCESS:
134
0
      out = "SPV_SUCCESS";
135
0
      break;
136
0
    case SPV_UNSUPPORTED:
137
0
      out = "SPV_UNSUPPORTED";
138
0
      break;
139
0
    case SPV_END_OF_STREAM:
140
0
      out = "SPV_END_OF_STREAM";
141
0
      break;
142
0
    case SPV_WARNING:
143
0
      out = "SPV_WARNING";
144
0
      break;
145
0
    case SPV_FAILED_MATCH:
146
0
      out = "SPV_FAILED_MATCH";
147
0
      break;
148
0
    case SPV_REQUESTED_TERMINATION:
149
0
      out = "SPV_REQUESTED_TERMINATION";
150
0
      break;
151
0
    case SPV_ERROR_INTERNAL:
152
0
      out = "SPV_ERROR_INTERNAL";
153
0
      break;
154
0
    case SPV_ERROR_OUT_OF_MEMORY:
155
0
      out = "SPV_ERROR_OUT_OF_MEMORY";
156
0
      break;
157
0
    case SPV_ERROR_INVALID_POINTER:
158
0
      out = "SPV_ERROR_INVALID_POINTER";
159
0
      break;
160
0
    case SPV_ERROR_INVALID_BINARY:
161
0
      out = "SPV_ERROR_INVALID_BINARY";
162
0
      break;
163
0
    case SPV_ERROR_INVALID_TEXT:
164
0
      out = "SPV_ERROR_INVALID_TEXT";
165
0
      break;
166
0
    case SPV_ERROR_INVALID_TABLE:
167
0
      out = "SPV_ERROR_INVALID_TABLE";
168
0
      break;
169
0
    case SPV_ERROR_INVALID_VALUE:
170
0
      out = "SPV_ERROR_INVALID_VALUE";
171
0
      break;
172
0
    case SPV_ERROR_INVALID_DIAGNOSTIC:
173
0
      out = "SPV_ERROR_INVALID_DIAGNOSTIC";
174
0
      break;
175
0
    case SPV_ERROR_INVALID_LOOKUP:
176
0
      out = "SPV_ERROR_INVALID_LOOKUP";
177
0
      break;
178
0
    case SPV_ERROR_INVALID_ID:
179
0
      out = "SPV_ERROR_INVALID_ID";
180
0
      break;
181
0
    case SPV_ERROR_INVALID_CFG:
182
0
      out = "SPV_ERROR_INVALID_CFG";
183
0
      break;
184
0
    case SPV_ERROR_INVALID_LAYOUT:
185
0
      out = "SPV_ERROR_INVALID_LAYOUT";
186
0
      break;
187
0
    default:
188
0
      out = "Unknown Error";
189
0
  }
190
0
  return out;
191
0
}
192
193
}  // namespace spvtools