~mmach/netext73/spirv-tools

« back to all changes in this revision

Viewing changes to source/val/validate_extensions.cpp

  • Committer: mmach
  • Date: 2020-06-26 11:46:33 UTC
  • Revision ID: netbit73@gmail.com-20200626114633-vs4gtuqb2nza47tp
2020.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
 
15
15
// Validates correctness of extension SPIR-V instructions.
16
16
 
17
 
#include "source/val/validate.h"
18
 
 
19
17
#include <sstream>
20
18
#include <string>
21
19
#include <vector>
22
20
 
 
21
#include "OpenCLDebugInfo100.h"
23
22
#include "source/diagnostic.h"
24
23
#include "source/enum_string_mapping.h"
25
24
#include "source/extensions.h"
28
27
#include "source/opcode.h"
29
28
#include "source/spirv_target_env.h"
30
29
#include "source/val/instruction.h"
 
30
#include "source/val/validate.h"
31
31
#include "source/val/validation_state.h"
32
32
 
33
33
namespace spvtools {
42
42
  return 0;
43
43
}
44
44
 
 
45
// Check that the operand of a debug info instruction |inst| at |word_index|
 
46
// is a result id of an instruction with |expected_opcode|.
 
47
spv_result_t ValidateOperandForDebugInfo(
 
48
    ValidationState_t& _, const std::string& operand_name,
 
49
    SpvOp expected_opcode, const Instruction* inst, uint32_t word_index,
 
50
    const std::function<std::string()>& ext_inst_name) {
 
51
  auto* operand = _.FindDef(inst->word(word_index));
 
52
  if (operand->opcode() != expected_opcode) {
 
53
    spv_opcode_desc desc = nullptr;
 
54
    if (_.grammar().lookupOpcode(expected_opcode, &desc) != SPV_SUCCESS ||
 
55
        !desc) {
 
56
      return _.diag(SPV_ERROR_INVALID_DATA, inst)
 
57
             << ext_inst_name() << ": "
 
58
             << "expected operand " << operand_name << " is invalid";
 
59
    }
 
60
    return _.diag(SPV_ERROR_INVALID_DATA, inst)
 
61
           << ext_inst_name() << ": "
 
62
           << "expected operand " << operand_name << " must be a result id of "
 
63
           << "Op" << desc->name;
 
64
  }
 
65
  return SPV_SUCCESS;
 
66
}
 
67
 
 
68
#define CHECK_OPERAND(NAME, opcode, index)                                  \
 
69
  do {                                                                      \
 
70
    auto result = ValidateOperandForDebugInfo(_, NAME, opcode, inst, index, \
 
71
                                              ext_inst_name);               \
 
72
    if (result != SPV_SUCCESS) return result;                               \
 
73
  } while (0)
 
74
 
 
75
// True if the operand of a debug info instruction |inst| at |word_index|
 
76
// satisifies |expectation| that is given as a function. Otherwise,
 
77
// returns false.
 
78
bool DoesDebugInfoOperandMatchExpectation(
 
79
    const ValidationState_t& _,
 
80
    const std::function<bool(OpenCLDebugInfo100Instructions)>& expectation,
 
81
    const Instruction* inst, uint32_t word_index) {
 
82
  auto* debug_inst = _.FindDef(inst->word(word_index));
 
83
  if (debug_inst->opcode() != SpvOpExtInst ||
 
84
      debug_inst->ext_inst_type() != SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 ||
 
85
      !expectation(OpenCLDebugInfo100Instructions(debug_inst->word(4)))) {
 
86
    return false;
 
87
  }
 
88
  return true;
 
89
}
 
90
 
 
91
// Check that the operand of a debug info instruction |inst| at |word_index|
 
92
// is a result id of an debug info instruction whose debug instruction type
 
93
// is |expected_debug_inst|.
 
94
spv_result_t ValidateDebugInfoOperand(
 
95
    ValidationState_t& _, const std::string& debug_inst_name,
 
96
    OpenCLDebugInfo100Instructions expected_debug_inst, const Instruction* inst,
 
97
    uint32_t word_index, const std::function<std::string()>& ext_inst_name) {
 
98
  std::function<bool(OpenCLDebugInfo100Instructions)> expectation =
 
99
      [expected_debug_inst](OpenCLDebugInfo100Instructions dbg_inst) {
 
100
        return dbg_inst == expected_debug_inst;
 
101
      };
 
102
  if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index))
 
103
    return SPV_SUCCESS;
 
104
 
 
105
  spv_ext_inst_desc desc = nullptr;
 
106
  _.grammar().lookupExtInst(SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100,
 
107
                            expected_debug_inst, &desc);
 
108
  if (_.grammar().lookupExtInst(SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100,
 
109
                                expected_debug_inst, &desc) != SPV_SUCCESS ||
 
110
      !desc) {
 
111
    return _.diag(SPV_ERROR_INVALID_DATA, inst)
 
112
           << ext_inst_name() << ": "
 
113
           << "expected operand " << debug_inst_name << " is invalid";
 
114
  }
 
115
  return _.diag(SPV_ERROR_INVALID_DATA, inst)
 
116
         << ext_inst_name() << ": "
 
117
         << "expected operand " << debug_inst_name << " must be a result id of "
 
118
         << desc->name;
 
119
}
 
120
 
 
121
#define CHECK_DEBUG_OPERAND(NAME, debug_opcode, index)                         \
 
122
  do {                                                                         \
 
123
    auto result = ValidateDebugInfoOperand(_, NAME, debug_opcode, inst, index, \
 
124
                                           ext_inst_name);                     \
 
125
    if (result != SPV_SUCCESS) return result;                                  \
 
126
  } while (0)
 
127
 
 
128
// Check that the operand of a debug info instruction |inst| at |word_index|
 
129
// is a result id of an debug info instruction with DebugTypeBasic.
 
130
spv_result_t ValidateOperandBaseType(
 
131
    ValidationState_t& _, const Instruction* inst, uint32_t word_index,
 
132
    const std::function<std::string()>& ext_inst_name) {
 
133
  return ValidateDebugInfoOperand(_, "Base Type",
 
134
                                  OpenCLDebugInfo100DebugTypeBasic, inst,
 
135
                                  word_index, ext_inst_name);
 
136
}
 
137
 
 
138
// Check that the operand of a debug info instruction |inst| at |word_index|
 
139
// is a result id of a debug lexical scope instruction which is one of
 
140
// DebugCompilationUnit, DebugFunction, DebugLexicalBlock, or
 
141
// DebugTypeComposite.
 
142
spv_result_t ValidateOperandLexicalScope(
 
143
    ValidationState_t& _, const std::string& debug_inst_name,
 
144
    const Instruction* inst, uint32_t word_index,
 
145
    const std::function<std::string()>& ext_inst_name) {
 
146
  std::function<bool(OpenCLDebugInfo100Instructions)> expectation =
 
147
      [](OpenCLDebugInfo100Instructions dbg_inst) {
 
148
        return dbg_inst == OpenCLDebugInfo100DebugCompilationUnit ||
 
149
               dbg_inst == OpenCLDebugInfo100DebugFunction ||
 
150
               dbg_inst == OpenCLDebugInfo100DebugLexicalBlock ||
 
151
               dbg_inst == OpenCLDebugInfo100DebugTypeComposite;
 
152
      };
 
153
  if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index))
 
154
    return SPV_SUCCESS;
 
155
 
 
156
  return _.diag(SPV_ERROR_INVALID_DATA, inst)
 
157
         << ext_inst_name() << ": "
 
158
         << "expected operand " << debug_inst_name
 
159
         << " must be a result id of a lexical scope";
 
160
}
 
161
 
 
162
// Check that the operand of a debug info instruction |inst| at |word_index|
 
163
// is a result id of a debug type instruction (See DebugTypeXXX in
 
164
// "4.3. Type instructions" section of OpenCL.DebugInfo.100 spec.
 
165
spv_result_t ValidateOperandDebugType(
 
166
    ValidationState_t& _, const std::string& debug_inst_name,
 
167
    const Instruction* inst, uint32_t word_index,
 
168
    const std::function<std::string()>& ext_inst_name) {
 
169
  std::function<bool(OpenCLDebugInfo100Instructions)> expectation =
 
170
      [](OpenCLDebugInfo100Instructions dbg_inst) {
 
171
        return OpenCLDebugInfo100DebugTypeBasic <= dbg_inst &&
 
172
               dbg_inst <= OpenCLDebugInfo100DebugTypePtrToMember;
 
173
      };
 
174
  if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index))
 
175
    return SPV_SUCCESS;
 
176
 
 
177
  return _.diag(SPV_ERROR_INVALID_DATA, inst)
 
178
         << ext_inst_name() << ": "
 
179
         << "expected operand " << debug_inst_name
 
180
         << " is not a valid debug type";
 
181
}
 
182
 
45
183
}  // anonymous namespace
46
184
 
47
185
spv_result_t ValidateExtension(ValidationState_t& _, const Instruction* inst) {
2028
2166
        break;
2029
2167
      }
2030
2168
    }
 
2169
  } else if (ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) {
 
2170
    if (!_.IsVoidType(result_type)) {
 
2171
      return _.diag(SPV_ERROR_INVALID_DATA, inst)
 
2172
             << ext_inst_name() << ": "
 
2173
             << "expected result type must be a result id of "
 
2174
             << "OpTypeVoid";
 
2175
    }
 
2176
 
 
2177
    auto num_words = inst->words().size();
 
2178
 
 
2179
    const OpenCLDebugInfo100Instructions ext_inst_key =
 
2180
        OpenCLDebugInfo100Instructions(ext_inst_index);
 
2181
    switch (ext_inst_key) {
 
2182
      case OpenCLDebugInfo100DebugInfoNone:
 
2183
      case OpenCLDebugInfo100DebugNoScope:
 
2184
      case OpenCLDebugInfo100DebugOperation:
 
2185
        // The binary parser validates the opcode for DebugInfoNone,
 
2186
        // DebugNoScope, DebugOperation, and the literal values don't need
 
2187
        // further checks.
 
2188
        break;
 
2189
      case OpenCLDebugInfo100DebugCompilationUnit: {
 
2190
        CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7);
 
2191
        break;
 
2192
      }
 
2193
      case OpenCLDebugInfo100DebugSource: {
 
2194
        CHECK_OPERAND("File", SpvOpString, 5);
 
2195
        if (num_words == 7) CHECK_OPERAND("Text", SpvOpString, 6);
 
2196
        break;
 
2197
      }
 
2198
      case OpenCLDebugInfo100DebugTypeBasic: {
 
2199
        CHECK_OPERAND("Name", SpvOpString, 5);
 
2200
        CHECK_OPERAND("Size", SpvOpConstant, 6);
 
2201
        // "Encoding" param is already validated by the binary parsing stage.
 
2202
        break;
 
2203
      }
 
2204
      case OpenCLDebugInfo100DebugTypePointer:
 
2205
      case OpenCLDebugInfo100DebugTypeQualifier: {
 
2206
        auto validate_base_type =
 
2207
            ValidateOperandBaseType(_, inst, 5, ext_inst_name);
 
2208
        if (validate_base_type != SPV_SUCCESS) return validate_base_type;
 
2209
        break;
 
2210
      }
 
2211
      case OpenCLDebugInfo100DebugTypeVector: {
 
2212
        auto validate_base_type =
 
2213
            ValidateOperandBaseType(_, inst, 5, ext_inst_name);
 
2214
        if (validate_base_type != SPV_SUCCESS) return validate_base_type;
 
2215
 
 
2216
        uint32_t component_count = inst->word(6);
 
2217
        if (!component_count || component_count > 4) {
 
2218
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
 
2219
                 << ext_inst_name() << ": Component Count must be positive "
 
2220
                 << "integer less than or equal to 4";
 
2221
        }
 
2222
        break;
 
2223
      }
 
2224
      case OpenCLDebugInfo100DebugTypeArray: {
 
2225
        auto validate_base_type =
 
2226
            ValidateOperandDebugType(_, "Base Type", inst, 5, ext_inst_name);
 
2227
        if (validate_base_type != SPV_SUCCESS) return validate_base_type;
 
2228
        for (uint32_t i = 6; i < num_words; ++i) {
 
2229
          CHECK_OPERAND("Component Count", SpvOpConstant, i);
 
2230
          auto* component_count = _.FindDef(inst->word(i));
 
2231
          if (!_.IsIntScalarType(component_count->type_id()) ||
 
2232
              !component_count->word(3)) {
 
2233
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
 
2234
                   << ext_inst_name() << ": Component Count must be positive "
 
2235
                   << "integer";
 
2236
          }
 
2237
        }
 
2238
        break;
 
2239
      }
 
2240
      case OpenCLDebugInfo100DebugTypedef: {
 
2241
        CHECK_OPERAND("Name", SpvOpString, 5);
 
2242
        auto validate_base_type =
 
2243
            ValidateOperandBaseType(_, inst, 6, ext_inst_name);
 
2244
        if (validate_base_type != SPV_SUCCESS) return validate_base_type;
 
2245
        CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7);
 
2246
        auto validate_parent =
 
2247
            ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
 
2248
        if (validate_parent != SPV_SUCCESS) return validate_parent;
 
2249
        break;
 
2250
      }
 
2251
      case OpenCLDebugInfo100DebugTypeFunction: {
 
2252
        auto* return_type = _.FindDef(inst->word(6));
 
2253
        if (return_type->opcode() != SpvOpTypeVoid) {
 
2254
          auto validate_return = ValidateOperandDebugType(
 
2255
              _, "Return Type", inst, 6, ext_inst_name);
 
2256
          if (validate_return != SPV_SUCCESS) return validate_return;
 
2257
        }
 
2258
        for (uint32_t word_index = 7; word_index < num_words; ++word_index) {
 
2259
          auto validate_param = ValidateOperandDebugType(
 
2260
              _, "Parameter Types", inst, word_index, ext_inst_name);
 
2261
          if (validate_param != SPV_SUCCESS) return validate_param;
 
2262
        }
 
2263
        break;
 
2264
      }
 
2265
      case OpenCLDebugInfo100DebugTypeEnum: {
 
2266
        CHECK_OPERAND("Name", SpvOpString, 5);
 
2267
        if (!DoesDebugInfoOperandMatchExpectation(
 
2268
                _,
 
2269
                [](OpenCLDebugInfo100Instructions dbg_inst) {
 
2270
                  return dbg_inst == OpenCLDebugInfo100DebugInfoNone;
 
2271
                },
 
2272
                inst, 6)) {
 
2273
          auto validate_underlying_type = ValidateOperandDebugType(
 
2274
              _, "Underlying Types", inst, 6, ext_inst_name);
 
2275
          if (validate_underlying_type != SPV_SUCCESS)
 
2276
            return validate_underlying_type;
 
2277
        }
 
2278
        CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7);
 
2279
        auto validate_parent =
 
2280
            ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
 
2281
        if (validate_parent != SPV_SUCCESS) return validate_parent;
 
2282
        CHECK_OPERAND("Size", SpvOpConstant, 11);
 
2283
        auto* size = _.FindDef(inst->word(11));
 
2284
        if (!_.IsIntScalarType(size->type_id()) || !size->word(3)) {
 
2285
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
 
2286
                 << ext_inst_name() << ": expected operand Size is a "
 
2287
                 << "positive integer";
 
2288
        }
 
2289
        for (uint32_t word_index = 13; word_index + 1 < num_words;
 
2290
             word_index += 2) {
 
2291
          CHECK_OPERAND("Value", SpvOpConstant, word_index);
 
2292
          CHECK_OPERAND("Name", SpvOpString, word_index + 1);
 
2293
        }
 
2294
        break;
 
2295
      }
 
2296
      case OpenCLDebugInfo100DebugTypeComposite: {
 
2297
        CHECK_OPERAND("Name", SpvOpString, 5);
 
2298
        CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7);
 
2299
        auto validate_parent =
 
2300
            ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
 
2301
        if (validate_parent != SPV_SUCCESS) return validate_parent;
 
2302
        CHECK_OPERAND("Linkage Name", SpvOpString, 11);
 
2303
        if (!DoesDebugInfoOperandMatchExpectation(
 
2304
                _,
 
2305
                [](OpenCLDebugInfo100Instructions dbg_inst) {
 
2306
                  return dbg_inst == OpenCLDebugInfo100DebugInfoNone;
 
2307
                },
 
2308
                inst, 12)) {
 
2309
          CHECK_OPERAND("Size", SpvOpConstant, 12);
 
2310
        }
 
2311
        for (uint32_t word_index = 14; word_index < num_words; ++word_index) {
 
2312
          if (!DoesDebugInfoOperandMatchExpectation(
 
2313
                  _,
 
2314
                  [](OpenCLDebugInfo100Instructions dbg_inst) {
 
2315
                    return dbg_inst == OpenCLDebugInfo100DebugTypeMember ||
 
2316
                           dbg_inst == OpenCLDebugInfo100DebugFunction ||
 
2317
                           dbg_inst == OpenCLDebugInfo100DebugTypeInheritance;
 
2318
                  },
 
2319
                  inst, word_index)) {
 
2320
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
 
2321
                   << ext_inst_name() << ": "
 
2322
                   << "expected operand Members "
 
2323
                   << "must be DebugTypeMember, DebugFunction, or "
 
2324
                      "DebugTypeInheritance";
 
2325
          }
 
2326
        }
 
2327
        break;
 
2328
      }
 
2329
      case OpenCLDebugInfo100DebugTypeMember: {
 
2330
        CHECK_OPERAND("Name", SpvOpString, 5);
 
2331
        auto validate_type =
 
2332
            ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name);
 
2333
        if (validate_type != SPV_SUCCESS) return validate_type;
 
2334
        CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7);
 
2335
        CHECK_DEBUG_OPERAND("Parent", OpenCLDebugInfo100DebugTypeComposite, 10);
 
2336
        CHECK_OPERAND("Offset", SpvOpConstant, 11);
 
2337
        CHECK_OPERAND("Size", SpvOpConstant, 12);
 
2338
        if (num_words == 15) CHECK_OPERAND("Value", SpvOpConstant, 14);
 
2339
        break;
 
2340
      }
 
2341
      case OpenCLDebugInfo100DebugTypeInheritance: {
 
2342
        CHECK_DEBUG_OPERAND("Child", OpenCLDebugInfo100DebugTypeComposite, 5);
 
2343
        auto* debug_inst = _.FindDef(inst->word(5));
 
2344
        auto composite_type =
 
2345
            OpenCLDebugInfo100DebugCompositeType(debug_inst->word(6));
 
2346
        if (composite_type != OpenCLDebugInfo100Class &&
 
2347
            composite_type != OpenCLDebugInfo100Structure) {
 
2348
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
 
2349
                 << ext_inst_name() << ": "
 
2350
                 << "expected operand Child must be class or struct debug type";
 
2351
        }
 
2352
        CHECK_DEBUG_OPERAND("Parent", OpenCLDebugInfo100DebugTypeComposite, 6);
 
2353
        debug_inst = _.FindDef(inst->word(6));
 
2354
        composite_type =
 
2355
            OpenCLDebugInfo100DebugCompositeType(debug_inst->word(6));
 
2356
        if (composite_type != OpenCLDebugInfo100Class &&
 
2357
            composite_type != OpenCLDebugInfo100Structure) {
 
2358
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
 
2359
                 << ext_inst_name() << ": "
 
2360
                 << "expected operand Parent must be class or struct debug "
 
2361
                    "type";
 
2362
        }
 
2363
        CHECK_OPERAND("Offset", SpvOpConstant, 7);
 
2364
        CHECK_OPERAND("Size", SpvOpConstant, 8);
 
2365
        break;
 
2366
      }
 
2367
      case OpenCLDebugInfo100DebugFunction: {
 
2368
        CHECK_OPERAND("Name", SpvOpString, 5);
 
2369
        auto validate_type =
 
2370
            ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name);
 
2371
        if (validate_type != SPV_SUCCESS) return validate_type;
 
2372
        CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7);
 
2373
        auto validate_parent =
 
2374
            ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
 
2375
        if (validate_parent != SPV_SUCCESS) return validate_parent;
 
2376
        CHECK_OPERAND("Linkage Name", SpvOpString, 11);
 
2377
        // TODO: The current OpenCL.100.DebugInfo spec says "Function
 
2378
        // is an OpFunction which is described by this instruction.".
 
2379
        // However, the function definition can be opted-out e.g.,
 
2380
        // inlining. We assume that Function operand can be a
 
2381
        // DebugInfoNone, but we must discuss it and update the spec.
 
2382
        if (!DoesDebugInfoOperandMatchExpectation(
 
2383
                _,
 
2384
                [](OpenCLDebugInfo100Instructions dbg_inst) {
 
2385
                  return dbg_inst == OpenCLDebugInfo100DebugInfoNone;
 
2386
                },
 
2387
                inst, 14)) {
 
2388
          CHECK_OPERAND("Function", SpvOpFunction, 14);
 
2389
        }
 
2390
        if (num_words == 16) {
 
2391
          CHECK_DEBUG_OPERAND("Declaration",
 
2392
                              OpenCLDebugInfo100DebugFunctionDeclaration, 15);
 
2393
        }
 
2394
        break;
 
2395
      }
 
2396
      case OpenCLDebugInfo100DebugFunctionDeclaration: {
 
2397
        CHECK_OPERAND("Name", SpvOpString, 5);
 
2398
        auto validate_type =
 
2399
            ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name);
 
2400
        if (validate_type != SPV_SUCCESS) return validate_type;
 
2401
        CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7);
 
2402
        auto validate_parent =
 
2403
            ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
 
2404
        if (validate_parent != SPV_SUCCESS) return validate_parent;
 
2405
        CHECK_OPERAND("Linkage Name", SpvOpString, 11);
 
2406
        break;
 
2407
      }
 
2408
      case OpenCLDebugInfo100DebugLexicalBlock: {
 
2409
        CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 5);
 
2410
        auto validate_parent =
 
2411
            ValidateOperandLexicalScope(_, "Parent", inst, 8, ext_inst_name);
 
2412
        if (validate_parent != SPV_SUCCESS) return validate_parent;
 
2413
        if (num_words == 10) CHECK_OPERAND("Name", SpvOpString, 9);
 
2414
        break;
 
2415
      }
 
2416
      case OpenCLDebugInfo100DebugScope: {
 
2417
        // TODO(https://gitlab.khronos.org/spirv/SPIR-V/issues/533): We are
 
2418
        // still in spec discussion about what must be "Scope" operand of
 
2419
        // DebugScope. Update this code if the conclusion is different.
 
2420
        auto validate_scope =
 
2421
            ValidateOperandLexicalScope(_, "Scope", inst, 5, ext_inst_name);
 
2422
        if (validate_scope != SPV_SUCCESS) return validate_scope;
 
2423
        if (num_words == 7) {
 
2424
          CHECK_DEBUG_OPERAND("Inlined At", OpenCLDebugInfo100DebugInlinedAt,
 
2425
                              6);
 
2426
        }
 
2427
        break;
 
2428
      }
 
2429
      case OpenCLDebugInfo100DebugLocalVariable: {
 
2430
        CHECK_OPERAND("Name", SpvOpString, 5);
 
2431
        auto validate_type =
 
2432
            ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name);
 
2433
        if (validate_type != SPV_SUCCESS) return validate_type;
 
2434
        CHECK_DEBUG_OPERAND("Source", OpenCLDebugInfo100DebugSource, 7);
 
2435
        auto validate_parent =
 
2436
            ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
 
2437
        if (validate_parent != SPV_SUCCESS) return validate_parent;
 
2438
        break;
 
2439
      }
 
2440
      case OpenCLDebugInfo100DebugDeclare: {
 
2441
        CHECK_DEBUG_OPERAND("Local Variable",
 
2442
                            OpenCLDebugInfo100DebugLocalVariable, 5);
 
2443
 
 
2444
        // TODO: We must discuss DebugDeclare.Variable of OpenCL.100.DebugInfo.
 
2445
        // Currently, it says "Variable must be an id of OpVariable instruction
 
2446
        // which defines the local variable.", but we want to allow
 
2447
        // OpFunctionParameter as well.
 
2448
        auto* operand = _.FindDef(inst->word(6));
 
2449
        if (operand->opcode() != SpvOpVariable &&
 
2450
            operand->opcode() != SpvOpFunctionParameter) {
 
2451
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
 
2452
                 << ext_inst_name() << ": "
 
2453
                 << "expected operand Variable must be a result id of "
 
2454
                    "OpVariable or OpFunctionParameter";
 
2455
        }
 
2456
 
 
2457
        CHECK_DEBUG_OPERAND("Expression", OpenCLDebugInfo100DebugExpression, 7);
 
2458
        break;
 
2459
      }
 
2460
      case OpenCLDebugInfo100DebugExpression: {
 
2461
        for (uint32_t word_index = 5; word_index < num_words; ++word_index) {
 
2462
          CHECK_DEBUG_OPERAND("Operation", OpenCLDebugInfo100DebugOperation,
 
2463
                              word_index);
 
2464
        }
 
2465
        break;
 
2466
      }
 
2467
 
 
2468
      // TODO: Add validation rules for remaining cases as well.
 
2469
      case OpenCLDebugInfo100DebugTypePtrToMember:
 
2470
      case OpenCLDebugInfo100DebugTypeTemplate:
 
2471
      case OpenCLDebugInfo100DebugTypeTemplateParameter:
 
2472
      case OpenCLDebugInfo100DebugTypeTemplateTemplateParameter:
 
2473
      case OpenCLDebugInfo100DebugTypeTemplateParameterPack:
 
2474
      case OpenCLDebugInfo100DebugGlobalVariable:
 
2475
      case OpenCLDebugInfo100DebugLexicalBlockDiscriminator:
 
2476
      case OpenCLDebugInfo100DebugInlinedAt:
 
2477
      case OpenCLDebugInfo100DebugInlinedVariable:
 
2478
      case OpenCLDebugInfo100DebugValue:
 
2479
      case OpenCLDebugInfo100DebugMacroDef:
 
2480
      case OpenCLDebugInfo100DebugMacroUndef:
 
2481
      case OpenCLDebugInfo100DebugImportedEntity:
 
2482
        break;
 
2483
      case OpenCLDebugInfo100InstructionsMax:
 
2484
        assert(0);
 
2485
        break;
 
2486
    }
2031
2487
  }
2032
2488
 
2033
2489
  return SPV_SUCCESS;