Coverage Report

Created: 2023-03-01 07:33

/src/spirv-tools/source/val/validate_extensions.cpp
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2018 Google 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
// Validates correctness of extension SPIR-V instructions.
16
#include <cstdlib>
17
#include <sstream>
18
#include <string>
19
#include <vector>
20
21
#include "spirv/unified1/NonSemanticClspvReflection.h"
22
23
#include "NonSemanticShaderDebugInfo100.h"
24
#include "OpenCLDebugInfo100.h"
25
#include "source/common_debug_info.h"
26
#include "source/diagnostic.h"
27
#include "source/enum_string_mapping.h"
28
#include "source/extensions.h"
29
#include "source/latest_version_glsl_std_450_header.h"
30
#include "source/latest_version_opencl_std_header.h"
31
#include "source/opcode.h"
32
#include "source/spirv_constant.h"
33
#include "source/spirv_target_env.h"
34
#include "source/val/instruction.h"
35
#include "source/val/validate.h"
36
#include "source/val/validation_state.h"
37
38
namespace spvtools {
39
namespace val {
40
namespace {
41
42
std::string ReflectionInstructionName(ValidationState_t& _,
43
0
                                      const Instruction* inst) {
44
0
  spv_ext_inst_desc desc = nullptr;
45
0
  if (_.grammar().lookupExtInst(SPV_EXT_INST_TYPE_NONSEMANTIC_CLSPVREFLECTION,
46
0
                                inst->word(4), &desc) != SPV_SUCCESS ||
47
0
      !desc) {
48
0
    return std::string("Unknown ExtInst");
49
0
  }
50
0
  std::ostringstream ss;
51
0
  ss << desc->name;
52
53
0
  return ss.str();
54
0
}
55
56
0
uint32_t GetSizeTBitWidth(const ValidationState_t& _) {
57
0
  if (_.addressing_model() == spv::AddressingModel::Physical32) return 32;
58
59
0
  if (_.addressing_model() == spv::AddressingModel::Physical64) return 64;
60
61
0
  return 0;
62
0
}
63
64
bool IsIntScalar(ValidationState_t& _, uint32_t id, bool must_len32,
65
0
                 bool must_unsigned) {
66
0
  auto type = _.FindDef(id);
67
0
  if (!type || type->opcode() != spv::Op::OpTypeInt) {
68
0
    return false;
69
0
  }
70
71
0
  if (must_len32 && type->GetOperandAs<uint32_t>(1) != 32) {
72
0
    return false;
73
0
  }
74
75
0
  return !must_unsigned || type->GetOperandAs<uint32_t>(2) == 0;
76
0
}
77
78
0
bool IsUint32Constant(ValidationState_t& _, uint32_t id) {
79
0
  auto inst = _.FindDef(id);
80
0
  if (!inst || inst->opcode() != spv::Op::OpConstant) {
81
0
    return false;
82
0
  }
83
84
0
  return IsIntScalar(_, inst->type_id(), true, true);
85
0
}
86
87
0
uint32_t GetUint32Constant(ValidationState_t& _, uint32_t id) {
88
0
  auto inst = _.FindDef(id);
89
0
  return inst->word(3);
90
0
}
91
92
// Check that the operand of a debug info instruction |inst| at |word_index|
93
// is a result id of an instruction with |expected_opcode|.
94
spv_result_t ValidateOperandForDebugInfo(
95
    ValidationState_t& _, const std::string& operand_name,
96
    spv::Op expected_opcode, const Instruction* inst, uint32_t word_index,
97
0
    const std::function<std::string()>& ext_inst_name) {
98
0
  auto* operand = _.FindDef(inst->word(word_index));
99
0
  if (operand->opcode() != expected_opcode) {
100
0
    spv_opcode_desc desc = nullptr;
101
0
    if (_.grammar().lookupOpcode(expected_opcode, &desc) != SPV_SUCCESS ||
102
0
        !desc) {
103
0
      return _.diag(SPV_ERROR_INVALID_DATA, inst)
104
0
             << ext_inst_name() << ": "
105
0
             << "expected operand " << operand_name << " is invalid";
106
0
    }
107
0
    return _.diag(SPV_ERROR_INVALID_DATA, inst)
108
0
           << ext_inst_name() << ": "
109
0
           << "expected operand " << operand_name << " must be a result id of "
110
0
           << "Op" << desc->name;
111
0
  }
112
0
  return SPV_SUCCESS;
113
0
}
114
115
// For NonSemantic.Shader.DebugInfo.100 check that the operand of a debug info
116
// instruction |inst| at |word_index| is a result id of a 32-bit integer
117
// OpConstant instruction. For OpenCL.DebugInfo.100 the parameter is a literal
118
// word so cannot be validated.
119
spv_result_t ValidateUint32ConstantOperandForDebugInfo(
120
    ValidationState_t& _, const std::string& operand_name,
121
    const Instruction* inst, uint32_t word_index,
122
0
    const std::function<std::string()>& ext_inst_name) {
123
0
  if (!IsUint32Constant(_, inst->word(word_index))) {
124
0
    return _.diag(SPV_ERROR_INVALID_DATA, inst)
125
0
           << ext_inst_name() << ": expected operand " << operand_name
126
0
           << " must be a result id of 32-bit unsigned OpConstant";
127
0
  }
128
0
  return SPV_SUCCESS;
129
0
}
130
131
#define CHECK_OPERAND(NAME, opcode, index)                                  \
132
0
  do {                                                                      \
133
0
    auto result = ValidateOperandForDebugInfo(_, NAME, opcode, inst, index, \
134
0
                                              ext_inst_name);               \
135
0
    if (result != SPV_SUCCESS) return result;                               \
136
0
  } while (0)
137
138
#define CHECK_CONST_UINT_OPERAND(NAME, index)                \
139
0
  if (vulkanDebugInfo) {                                     \
140
0
    auto result = ValidateUint32ConstantOperandForDebugInfo( \
141
0
        _, NAME, inst, index, ext_inst_name);                \
142
0
    if (result != SPV_SUCCESS) return result;                \
143
0
  }
144
145
// True if the operand of a debug info instruction |inst| at |word_index|
146
// satisfies |expectation| that is given as a function. Otherwise,
147
// returns false.
148
bool DoesDebugInfoOperandMatchExpectation(
149
    const ValidationState_t& _,
150
    const std::function<bool(CommonDebugInfoInstructions)>& expectation,
151
0
    const Instruction* inst, uint32_t word_index) {
152
0
  if (inst->words().size() <= word_index) return false;
153
0
  auto* debug_inst = _.FindDef(inst->word(word_index));
154
0
  if (debug_inst->opcode() != spv::Op::OpExtInst ||
155
0
      (debug_inst->ext_inst_type() != SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 &&
156
0
       debug_inst->ext_inst_type() !=
157
0
           SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) ||
158
0
      !expectation(CommonDebugInfoInstructions(debug_inst->word(4)))) {
159
0
    return false;
160
0
  }
161
0
  return true;
162
0
}
163
164
// Overload for NonSemanticShaderDebugInfo100Instructions.
165
bool DoesDebugInfoOperandMatchExpectation(
166
    const ValidationState_t& _,
167
    const std::function<bool(NonSemanticShaderDebugInfo100Instructions)>&
168
        expectation,
169
0
    const Instruction* inst, uint32_t word_index) {
170
0
  if (inst->words().size() <= word_index) return false;
171
0
  auto* debug_inst = _.FindDef(inst->word(word_index));
172
0
  if (debug_inst->opcode() != spv::Op::OpExtInst ||
173
0
      (debug_inst->ext_inst_type() !=
174
0
       SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) ||
175
0
      !expectation(
176
0
          NonSemanticShaderDebugInfo100Instructions(debug_inst->word(4)))) {
177
0
    return false;
178
0
  }
179
0
  return true;
180
0
}
181
182
// Check that the operand of a debug info instruction |inst| at |word_index|
183
// is a result id of an debug info instruction whose debug instruction type
184
// is |expected_debug_inst|.
185
spv_result_t ValidateDebugInfoOperand(
186
    ValidationState_t& _, const std::string& debug_inst_name,
187
    CommonDebugInfoInstructions expected_debug_inst, const Instruction* inst,
188
0
    uint32_t word_index, const std::function<std::string()>& ext_inst_name) {
189
0
  std::function<bool(CommonDebugInfoInstructions)> expectation =
190
0
      [expected_debug_inst](CommonDebugInfoInstructions dbg_inst) {
191
0
        return dbg_inst == expected_debug_inst;
192
0
      };
193
0
  if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index))
194
0
    return SPV_SUCCESS;
195
196
0
  spv_ext_inst_desc desc = nullptr;
197
0
  if (_.grammar().lookupExtInst(inst->ext_inst_type(), expected_debug_inst,
198
0
                                &desc) != SPV_SUCCESS ||
199
0
      !desc) {
200
0
    return _.diag(SPV_ERROR_INVALID_DATA, inst)
201
0
           << ext_inst_name() << ": "
202
0
           << "expected operand " << debug_inst_name << " is invalid";
203
0
  }
204
0
  return _.diag(SPV_ERROR_INVALID_DATA, inst)
205
0
         << ext_inst_name() << ": "
206
0
         << "expected operand " << debug_inst_name << " must be a result id of "
207
0
         << desc->name;
208
0
}
209
210
#define CHECK_DEBUG_OPERAND(NAME, debug_opcode, index)                         \
211
0
  do {                                                                         \
212
0
    auto result = ValidateDebugInfoOperand(_, NAME, debug_opcode, inst, index, \
213
0
                                           ext_inst_name);                     \
214
0
    if (result != SPV_SUCCESS) return result;                                  \
215
0
  } while (0)
216
217
// Check that the operand of a debug info instruction |inst| at |word_index|
218
// is a result id of an debug info instruction with DebugTypeBasic.
219
spv_result_t ValidateOperandBaseType(
220
    ValidationState_t& _, const Instruction* inst, uint32_t word_index,
221
0
    const std::function<std::string()>& ext_inst_name) {
222
0
  return ValidateDebugInfoOperand(_, "Base Type", CommonDebugInfoDebugTypeBasic,
223
0
                                  inst, word_index, ext_inst_name);
224
0
}
225
226
// Check that the operand of a debug info instruction |inst| at |word_index|
227
// is a result id of a debug lexical scope instruction which is one of
228
// DebugCompilationUnit, DebugFunction, DebugLexicalBlock, or
229
// DebugTypeComposite.
230
spv_result_t ValidateOperandLexicalScope(
231
    ValidationState_t& _, const std::string& debug_inst_name,
232
    const Instruction* inst, uint32_t word_index,
233
0
    const std::function<std::string()>& ext_inst_name) {
234
0
  std::function<bool(CommonDebugInfoInstructions)> expectation =
235
0
      [](CommonDebugInfoInstructions dbg_inst) {
236
0
        return dbg_inst == CommonDebugInfoDebugCompilationUnit ||
237
0
               dbg_inst == CommonDebugInfoDebugFunction ||
238
0
               dbg_inst == CommonDebugInfoDebugLexicalBlock ||
239
0
               dbg_inst == CommonDebugInfoDebugTypeComposite;
240
0
      };
241
0
  if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index))
242
0
    return SPV_SUCCESS;
243
244
0
  return _.diag(SPV_ERROR_INVALID_DATA, inst)
245
0
         << ext_inst_name() << ": "
246
0
         << "expected operand " << debug_inst_name
247
0
         << " must be a result id of a lexical scope";
248
0
}
249
250
// Check that the operand of a debug info instruction |inst| at |word_index|
251
// is a result id of a debug type instruction (See DebugTypeXXX in
252
// "4.3. Type instructions" section of OpenCL.DebugInfo.100 spec.
253
spv_result_t ValidateOperandDebugType(
254
    ValidationState_t& _, const std::string& debug_inst_name,
255
    const Instruction* inst, uint32_t word_index,
256
    const std::function<std::string()>& ext_inst_name,
257
0
    bool allow_template_param) {
258
  // Check for NonSemanticShaderDebugInfo100 specific types.
259
0
  if (inst->ext_inst_type() ==
260
0
      SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) {
261
0
    std::function<bool(NonSemanticShaderDebugInfo100Instructions)> expectation =
262
0
        [](NonSemanticShaderDebugInfo100Instructions dbg_inst) {
263
0
          return dbg_inst == NonSemanticShaderDebugInfo100DebugTypeMatrix;
264
0
        };
265
0
    if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index))
266
0
      return SPV_SUCCESS;
267
0
  }
268
269
  // Check for common types.
270
0
  std::function<bool(CommonDebugInfoInstructions)> expectation =
271
0
      [&allow_template_param](CommonDebugInfoInstructions dbg_inst) {
272
0
        if (allow_template_param &&
273
0
            (dbg_inst == CommonDebugInfoDebugTypeTemplateParameter ||
274
0
             dbg_inst == CommonDebugInfoDebugTypeTemplateTemplateParameter)) {
275
0
          return true;
276
0
        }
277
0
        return CommonDebugInfoDebugTypeBasic <= dbg_inst &&
278
0
               dbg_inst <= CommonDebugInfoDebugTypeTemplate;
279
0
      };
280
0
  if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index))
281
0
    return SPV_SUCCESS;
282
283
0
  return _.diag(SPV_ERROR_INVALID_DATA, inst)
284
0
         << ext_inst_name() << ": "
285
0
         << "expected operand " << debug_inst_name
286
0
         << " is not a valid debug type";
287
0
}
288
289
spv_result_t ValidateClspvReflectionKernel(ValidationState_t& _,
290
                                           const Instruction* inst,
291
0
                                           uint32_t version) {
292
0
  const auto inst_name = ReflectionInstructionName(_, inst);
293
0
  const auto kernel_id = inst->GetOperandAs<uint32_t>(4);
294
0
  const auto kernel = _.FindDef(kernel_id);
295
0
  if (kernel->opcode() != spv::Op::OpFunction) {
296
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
297
0
           << inst_name << " does not reference a function";
298
0
  }
299
300
0
  bool found_kernel = false;
301
0
  for (auto entry_point : _.entry_points()) {
302
0
    if (entry_point == kernel_id) {
303
0
      found_kernel = true;
304
0
      break;
305
0
    }
306
0
  }
307
0
  if (!found_kernel) {
308
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
309
0
           << inst_name << " does not reference an entry-point";
310
0
  }
311
312
0
  const auto* exec_models = _.GetExecutionModels(kernel_id);
313
0
  if (!exec_models || exec_models->empty()) {
314
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
315
0
           << inst_name << " does not reference an entry-point";
316
0
  }
317
0
  for (auto exec_model : *exec_models) {
318
0
    if (exec_model != spv::ExecutionModel::GLCompute) {
319
0
      return _.diag(SPV_ERROR_INVALID_ID, inst)
320
0
             << inst_name << " must refer only to GLCompute entry-points";
321
0
    }
322
0
  }
323
324
0
  auto name = _.FindDef(inst->GetOperandAs<uint32_t>(5));
325
0
  if (!name || name->opcode() != spv::Op::OpString) {
326
0
    return _.diag(SPV_ERROR_INVALID_ID, inst) << "Name must be an OpString";
327
0
  }
328
329
0
  const std::string name_str = name->GetOperandAs<std::string>(1);
330
0
  bool found = false;
331
0
  for (auto& desc : _.entry_point_descriptions(kernel_id)) {
332
0
    if (name_str == desc.name) {
333
0
      found = true;
334
0
      break;
335
0
    }
336
0
  }
337
0
  if (!found) {
338
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
339
0
           << "Name must match an entry-point for Kernel";
340
0
  }
341
342
0
  const auto num_operands = inst->operands().size();
343
0
  if (version < 5 && num_operands > 6) {
344
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
345
0
           << "Version " << version << " of the " << inst_name
346
0
           << " instruction can only have 2 additional operands";
347
0
  }
348
349
0
  if (num_operands > 6) {
350
0
    const auto num_args_id = inst->GetOperandAs<uint32_t>(6);
351
0
    if (!IsUint32Constant(_, num_args_id)) {
352
0
      return _.diag(SPV_ERROR_INVALID_ID, inst)
353
0
             << "NumArguments must be a 32-bit unsigned integer OpConstant";
354
0
    }
355
0
  }
356
357
0
  if (num_operands > 7) {
358
0
    const auto flags_id = inst->GetOperandAs<uint32_t>(7);
359
0
    if (!IsUint32Constant(_, flags_id)) {
360
0
      return _.diag(SPV_ERROR_INVALID_ID, inst)
361
0
             << "Flags must be a 32-bit unsigned integer OpConstant";
362
0
    }
363
0
  }
364
365
0
  if (num_operands > 8) {
366
0
    const auto atts_id = inst->GetOperandAs<uint32_t>(8);
367
0
    if (_.GetIdOpcode(atts_id) != spv::Op::OpString) {
368
0
      return _.diag(SPV_ERROR_INVALID_ID, inst)
369
0
             << "Attributes must be an OpString";
370
0
    }
371
0
  }
372
373
0
  return SPV_SUCCESS;
374
0
}
375
376
spv_result_t ValidateClspvReflectionArgumentInfo(ValidationState_t& _,
377
0
                                                 const Instruction* inst) {
378
0
  const auto num_operands = inst->operands().size();
379
0
  if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(4)) != spv::Op::OpString) {
380
0
    return _.diag(SPV_ERROR_INVALID_ID, inst) << "Name must be an OpString";
381
0
  }
382
0
  if (num_operands > 5) {
383
0
    if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(5)) != spv::Op::OpString) {
384
0
      return _.diag(SPV_ERROR_INVALID_ID, inst)
385
0
             << "TypeName must be an OpString";
386
0
    }
387
0
  }
388
0
  if (num_operands > 6) {
389
0
    if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
390
0
      return _.diag(SPV_ERROR_INVALID_ID, inst)
391
0
             << "AddressQualifier must be a 32-bit unsigned integer "
392
0
                "OpConstant";
393
0
    }
394
0
  }
395
0
  if (num_operands > 7) {
396
0
    if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(7))) {
397
0
      return _.diag(SPV_ERROR_INVALID_ID, inst)
398
0
             << "AccessQualifier must be a 32-bit unsigned integer "
399
0
                "OpConstant";
400
0
    }
401
0
  }
402
0
  if (num_operands > 8) {
403
0
    if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(8))) {
404
0
      return _.diag(SPV_ERROR_INVALID_ID, inst)
405
0
             << "TypeQualifier must be a 32-bit unsigned integer "
406
0
                "OpConstant";
407
0
    }
408
0
  }
409
410
0
  return SPV_SUCCESS;
411
0
}
412
413
0
spv_result_t ValidateKernelDecl(ValidationState_t& _, const Instruction* inst) {
414
0
  const auto decl_id = inst->GetOperandAs<uint32_t>(4);
415
0
  const auto decl = _.FindDef(decl_id);
416
0
  if (!decl || decl->opcode() != spv::Op::OpExtInst) {
417
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
418
0
           << "Kernel must be a Kernel extended instruction";
419
0
  }
420
421
0
  if (decl->GetOperandAs<uint32_t>(2) != inst->GetOperandAs<uint32_t>(2)) {
422
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
423
0
           << "Kernel must be from the same extended instruction import";
424
0
  }
425
426
0
  const auto ext_inst =
427
0
      decl->GetOperandAs<NonSemanticClspvReflectionInstructions>(3);
428
0
  if (ext_inst != NonSemanticClspvReflectionKernel) {
429
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
430
0
           << "Kernel must be a Kernel extended instruction";
431
0
  }
432
433
0
  return SPV_SUCCESS;
434
0
}
435
436
spv_result_t ValidateArgInfo(ValidationState_t& _, const Instruction* inst,
437
0
                             uint32_t info_index) {
438
0
  auto info = _.FindDef(inst->GetOperandAs<uint32_t>(info_index));
439
0
  if (!info || info->opcode() != spv::Op::OpExtInst) {
440
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
441
0
           << "ArgInfo must be an ArgumentInfo extended instruction";
442
0
  }
443
444
0
  if (info->GetOperandAs<uint32_t>(2) != inst->GetOperandAs<uint32_t>(2)) {
445
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
446
0
           << "ArgInfo must be from the same extended instruction import";
447
0
  }
448
449
0
  auto ext_inst = info->GetOperandAs<NonSemanticClspvReflectionInstructions>(3);
450
0
  if (ext_inst != NonSemanticClspvReflectionArgumentInfo) {
451
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
452
0
           << "ArgInfo must be an ArgumentInfo extended instruction";
453
0
  }
454
455
0
  return SPV_SUCCESS;
456
0
}
457
458
spv_result_t ValidateClspvReflectionArgumentBuffer(ValidationState_t& _,
459
0
                                                   const Instruction* inst) {
460
0
  const auto num_operands = inst->operands().size();
461
0
  if (auto error = ValidateKernelDecl(_, inst)) {
462
0
    return error;
463
0
  }
464
465
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
466
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
467
0
           << "Ordinal must be a 32-bit unsigned integer OpConstant";
468
0
  }
469
470
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
471
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
472
0
           << "DescriptorSet must be a 32-bit unsigned integer OpConstant";
473
0
  }
474
475
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(7))) {
476
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
477
0
           << "Binding must be a 32-bit unsigned integer OpConstant";
478
0
  }
479
480
0
  if (num_operands == 9) {
481
0
    if (auto error = ValidateArgInfo(_, inst, 8)) {
482
0
      return error;
483
0
    }
484
0
  }
485
486
0
  return SPV_SUCCESS;
487
0
}
488
489
spv_result_t ValidateClspvReflectionArgumentOffsetBuffer(ValidationState_t& _,
490
0
                                                         const Instruction* inst) {
491
0
  const auto num_operands = inst->operands().size();
492
0
  if (auto error = ValidateKernelDecl(_, inst)) {
493
0
    return error;
494
0
  }
495
496
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
497
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
498
0
           << "Ordinal must be a 32-bit unsigned integer OpConstant";
499
0
  }
500
501
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
502
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
503
0
           << "DescriptorSet must be a 32-bit unsigned integer OpConstant";
504
0
  }
505
506
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(7))) {
507
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
508
0
           << "Binding must be a 32-bit unsigned integer OpConstant";
509
0
  }
510
511
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(8))) {
512
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
513
0
           << "Offset must be a 32-bit unsigned integer OpConstant";
514
0
  }
515
516
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(9))) {
517
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
518
0
           << "Size must be a 32-bit unsigned integer OpConstant";
519
0
  }
520
521
0
  if (num_operands == 11) {
522
0
    if (auto error = ValidateArgInfo(_, inst, 10)) {
523
0
      return error;
524
0
    }
525
0
  }
526
527
0
  return SPV_SUCCESS;
528
0
}
529
530
spv_result_t ValidateClspvReflectionArgumentPushConstant(
531
0
    ValidationState_t& _, const Instruction* inst) {
532
0
  const auto num_operands = inst->operands().size();
533
0
  if (auto error = ValidateKernelDecl(_, inst)) {
534
0
    return error;
535
0
  }
536
537
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
538
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
539
0
           << "Ordinal must be a 32-bit unsigned integer OpConstant";
540
0
  }
541
542
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
543
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
544
0
           << "Offset must be a 32-bit unsigned integer OpConstant";
545
0
  }
546
547
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(7))) {
548
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
549
0
           << "Size must be a 32-bit unsigned integer OpConstant";
550
0
  }
551
552
0
  if (num_operands == 9) {
553
0
    if (auto error = ValidateArgInfo(_, inst, 8)) {
554
0
      return error;
555
0
    }
556
0
  }
557
558
0
  return SPV_SUCCESS;
559
0
}
560
561
spv_result_t ValidateClspvReflectionArgumentWorkgroup(ValidationState_t& _,
562
0
                                                      const Instruction* inst) {
563
0
  const auto num_operands = inst->operands().size();
564
0
  if (auto error = ValidateKernelDecl(_, inst)) {
565
0
    return error;
566
0
  }
567
568
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
569
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
570
0
           << "Ordinal must be a 32-bit unsigned integer OpConstant";
571
0
  }
572
573
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
574
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
575
0
           << "SpecId must be a 32-bit unsigned integer OpConstant";
576
0
  }
577
578
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(7))) {
579
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
580
0
           << "ElemSize must be a 32-bit unsigned integer OpConstant";
581
0
  }
582
583
0
  if (num_operands == 9) {
584
0
    if (auto error = ValidateArgInfo(_, inst, 8)) {
585
0
      return error;
586
0
    }
587
0
  }
588
589
0
  return SPV_SUCCESS;
590
0
}
591
592
spv_result_t ValidateClspvReflectionSpecConstantTriple(
593
0
    ValidationState_t& _, const Instruction* inst) {
594
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
595
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
596
0
           << "X must be a 32-bit unsigned integer OpConstant";
597
0
  }
598
599
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
600
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
601
0
           << "Y must be a 32-bit unsigned integer OpConstant";
602
0
  }
603
604
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
605
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
606
0
           << "Z must be a 32-bit unsigned integer OpConstant";
607
0
  }
608
609
0
  return SPV_SUCCESS;
610
0
}
611
612
spv_result_t ValidateClspvReflectionSpecConstantWorkDim(
613
0
    ValidationState_t& _, const Instruction* inst) {
614
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
615
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
616
0
           << "Dim must be a 32-bit unsigned integer OpConstant";
617
0
  }
618
619
0
  return SPV_SUCCESS;
620
0
}
621
622
spv_result_t ValidateClspvReflectionPushConstant(ValidationState_t& _,
623
0
                                                 const Instruction* inst) {
624
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
625
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
626
0
           << "Offset must be a 32-bit unsigned integer OpConstant";
627
0
  }
628
629
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
630
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
631
0
           << "Size must be a 32-bit unsigned integer OpConstant";
632
0
  }
633
634
0
  return SPV_SUCCESS;
635
0
}
636
637
spv_result_t ValidateClspvReflectionInitializedData(ValidationState_t& _,
638
0
                                                    const Instruction* inst) {
639
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
640
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
641
0
           << "DescriptorSet must be a 32-bit unsigned integer OpConstant";
642
0
  }
643
644
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
645
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
646
0
           << "Binding must be a 32-bit unsigned integer OpConstant";
647
0
  }
648
649
0
  if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(6)) != spv::Op::OpString) {
650
0
    return _.diag(SPV_ERROR_INVALID_ID, inst) << "Data must be an OpString";
651
0
  }
652
653
0
  return SPV_SUCCESS;
654
0
}
655
656
spv_result_t ValidateClspvReflectionSampler(ValidationState_t& _,
657
0
                                            const Instruction* inst) {
658
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
659
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
660
0
           << "DescriptorSet must be a 32-bit unsigned integer OpConstant";
661
0
  }
662
663
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
664
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
665
0
           << "Binding must be a 32-bit unsigned integer OpConstant";
666
0
  }
667
668
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
669
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
670
0
           << "Mask must be a 32-bit unsigned integer OpConstant";
671
0
  }
672
673
0
  return SPV_SUCCESS;
674
0
}
675
676
spv_result_t ValidateClspvReflectionPropertyRequiredWorkgroupSize(
677
0
    ValidationState_t& _, const Instruction* inst) {
678
0
  if (auto error = ValidateKernelDecl(_, inst)) {
679
0
    return error;
680
0
  }
681
682
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
683
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
684
0
           << "X must be a 32-bit unsigned integer OpConstant";
685
0
  }
686
687
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
688
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
689
0
           << "Y must be a 32-bit unsigned integer OpConstant";
690
0
  }
691
692
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(7))) {
693
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
694
0
           << "Z must be a 32-bit unsigned integer OpConstant";
695
0
  }
696
697
0
  return SPV_SUCCESS;
698
0
}
699
700
spv_result_t ValidateClspvReflectionSubgroupMaxSize(ValidationState_t& _,
701
0
                                                    const Instruction* inst) {
702
0
  const auto size_id = inst->GetOperandAs<uint32_t>(4);
703
0
  if (!IsUint32Constant(_, size_id)) {
704
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
705
0
           << "Size must be a 32-bit unsigned integer OpConstant";
706
0
  }
707
708
0
  return SPV_SUCCESS;
709
0
}
710
711
spv_result_t ValidateClspvReflectionPointerRelocation(ValidationState_t& _,
712
0
                                                      const Instruction* inst) {
713
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
714
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
715
0
           << "ObjectOffset must be a 32-bit unsigned integer OpConstant";
716
0
  }
717
718
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
719
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
720
0
           << "PointerOffset must be a 32-bit unsigned integer OpConstant";
721
0
  }
722
723
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
724
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
725
0
           << "PointerSize must be a 32-bit unsigned integer OpConstant";
726
0
  }
727
728
0
  return SPV_SUCCESS;
729
0
}
730
731
spv_result_t ValidateClspvReflectionImageMetadataPushConstant(
732
0
    ValidationState_t& _, const Instruction* inst) {
733
0
  if (auto error = ValidateKernelDecl(_, inst)) {
734
0
    return error;
735
0
  }
736
737
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
738
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
739
0
           << "Ordinal must be a 32-bit unsigned integer OpConstant";
740
0
  }
741
742
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
743
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
744
0
           << "Offset must be a 32-bit unsigned integer OpConstant";
745
0
  }
746
747
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(7))) {
748
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
749
0
           << "Size must be a 32-bit unsigned integer OpConstant";
750
0
  }
751
752
0
  return SPV_SUCCESS;
753
0
}
754
755
spv_result_t ValidateClspvReflectionImageMetadataUniform(
756
0
    ValidationState_t& _, const Instruction* inst) {
757
0
  if (auto error = ValidateKernelDecl(_, inst)) {
758
0
    return error;
759
0
  }
760
761
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
762
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
763
0
           << "Ordinal must be a 32-bit unsigned integer OpConstant";
764
0
  }
765
766
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
767
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
768
0
           << "DescriptorSet must be a 32-bit unsigned integer OpConstant";
769
0
  }
770
771
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(7))) {
772
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
773
0
           << "Binding must be a 32-bit unsigned integer OpConstant";
774
0
  }
775
776
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(8))) {
777
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
778
0
           << "Offset must be a 32-bit unsigned integer OpConstant";
779
0
  }
780
781
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(9))) {
782
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
783
0
           << "Size must be a 32-bit unsigned integer OpConstant";
784
0
  }
785
786
0
  return SPV_SUCCESS;
787
0
}
788
789
spv_result_t ValidateClspvReflectionPushConstantData(ValidationState_t& _,
790
0
                                                     const Instruction* inst) {
791
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
792
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
793
0
           << "Offset must be a 32-bit unsigned integer OpConstant";
794
0
  }
795
796
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
797
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
798
0
           << "Size must be a 32-bit unsigned integer OpConstant";
799
0
  }
800
801
0
  if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(6)) != spv::Op::OpString) {
802
0
    return _.diag(SPV_ERROR_INVALID_ID, inst) << "Data must be an OpString";
803
0
  }
804
805
0
  return SPV_SUCCESS;
806
0
}
807
808
spv_result_t ValidateClspvReflectionPrintfInfo(ValidationState_t& _,
809
0
                                              const Instruction* inst) {
810
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
811
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
812
0
           << "PrintfID must be a 32-bit unsigned integer OpConstant";
813
0
  }
814
815
0
  if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(5)) != spv::Op::OpString) {
816
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
817
0
           << "FormatString must be an OpString";
818
0
  }
819
820
0
  for (size_t i = 6; i < inst->operands().size(); ++i) {
821
0
    if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(i))) {
822
0
      return _.diag(SPV_ERROR_INVALID_ID, inst)
823
0
             << "ArgumentSizes must be a 32-bit unsigned integer OpConstant";
824
0
    }
825
0
  }
826
827
0
  return SPV_SUCCESS;
828
0
}
829
830
spv_result_t ValidateClspvReflectionPrintfStorageBuffer(ValidationState_t& _,
831
0
                                                        const Instruction* inst) {
832
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
833
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
834
0
           << "DescriptorSet must be a 32-bit unsigned integer OpConstant";
835
0
  }
836
837
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
838
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
839
0
           << "Binding must be a 32-bit unsigned integer OpConstant";
840
0
  }
841
842
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
843
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
844
0
           << "Size must be a 32-bit unsigned integer OpConstant";
845
0
  }
846
847
0
  return SPV_SUCCESS;
848
0
}
849
850
spv_result_t ValidateClspvReflectionPrintfPushConstant(ValidationState_t& _,
851
0
                                                       const Instruction* inst) {
852
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
853
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
854
0
           << "Offset must be a 32-bit unsigned integer OpConstant";
855
0
  }
856
857
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
858
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
859
0
           << "Size must be a 32-bit unsigned integer OpConstant";
860
0
  }
861
862
0
  if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
863
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
864
0
           << "BufferSize must be a 32-bit unsigned integer OpConstant";
865
0
  }
866
867
0
  return SPV_SUCCESS;
868
0
}
869
870
spv_result_t ValidateClspvReflectionInstruction(ValidationState_t& _,
871
                                                const Instruction* inst,
872
0
                                                uint32_t version) {
873
0
  if (!_.IsVoidType(inst->type_id())) {
874
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
875
0
           << "Return Type must be OpTypeVoid";
876
0
  }
877
878
0
  uint32_t required_version = 0;
879
0
  const auto ext_inst =
880
0
      inst->GetOperandAs<NonSemanticClspvReflectionInstructions>(3);
881
0
  switch (ext_inst) {
882
0
    case NonSemanticClspvReflectionKernel:
883
0
    case NonSemanticClspvReflectionArgumentInfo:
884
0
    case NonSemanticClspvReflectionArgumentStorageBuffer:
885
0
    case NonSemanticClspvReflectionArgumentUniform:
886
0
    case NonSemanticClspvReflectionArgumentPodStorageBuffer:
887
0
    case NonSemanticClspvReflectionArgumentPodUniform:
888
0
    case NonSemanticClspvReflectionArgumentPodPushConstant:
889
0
    case NonSemanticClspvReflectionArgumentSampledImage:
890
0
    case NonSemanticClspvReflectionArgumentStorageImage:
891
0
    case NonSemanticClspvReflectionArgumentSampler:
892
0
    case NonSemanticClspvReflectionArgumentWorkgroup:
893
0
    case NonSemanticClspvReflectionSpecConstantWorkgroupSize:
894
0
    case NonSemanticClspvReflectionSpecConstantGlobalOffset:
895
0
    case NonSemanticClspvReflectionSpecConstantWorkDim:
896
0
    case NonSemanticClspvReflectionPushConstantGlobalOffset:
897
0
    case NonSemanticClspvReflectionPushConstantEnqueuedLocalSize:
898
0
    case NonSemanticClspvReflectionPushConstantGlobalSize:
899
0
    case NonSemanticClspvReflectionPushConstantRegionOffset:
900
0
    case NonSemanticClspvReflectionPushConstantNumWorkgroups:
901
0
    case NonSemanticClspvReflectionPushConstantRegionGroupOffset:
902
0
    case NonSemanticClspvReflectionConstantDataStorageBuffer:
903
0
    case NonSemanticClspvReflectionConstantDataUniform:
904
0
    case NonSemanticClspvReflectionLiteralSampler:
905
0
    case NonSemanticClspvReflectionPropertyRequiredWorkgroupSize:
906
0
      required_version = 1;
907
0
      break;
908
0
    case NonSemanticClspvReflectionSpecConstantSubgroupMaxSize:
909
0
      required_version = 2;
910
0
      break;
911
0
    case NonSemanticClspvReflectionArgumentPointerPushConstant:
912
0
    case NonSemanticClspvReflectionArgumentPointerUniform:
913
0
    case NonSemanticClspvReflectionProgramScopeVariablesStorageBuffer:
914
0
    case NonSemanticClspvReflectionProgramScopeVariablePointerRelocation:
915
0
    case NonSemanticClspvReflectionImageArgumentInfoChannelOrderPushConstant:
916
0
    case NonSemanticClspvReflectionImageArgumentInfoChannelDataTypePushConstant:
917
0
    case NonSemanticClspvReflectionImageArgumentInfoChannelOrderUniform:
918
0
    case NonSemanticClspvReflectionImageArgumentInfoChannelDataTypeUniform:
919
0
      required_version = 3;
920
0
      break;
921
0
    case NonSemanticClspvReflectionArgumentStorageTexelBuffer:
922
0
    case NonSemanticClspvReflectionArgumentUniformTexelBuffer:
923
0
      required_version = 4;
924
0
      break;
925
0
    case NonSemanticClspvReflectionConstantDataPointerPushConstant:
926
0
    case NonSemanticClspvReflectionProgramScopeVariablePointerPushConstant:
927
0
    case NonSemanticClspvReflectionPrintfInfo:
928
0
    case NonSemanticClspvReflectionPrintfBufferStorageBuffer:
929
0
    case NonSemanticClspvReflectionPrintfBufferPointerPushConstant:
930
0
      required_version = 5;
931
0
      break;
932
0
    default:
933
0
      break;
934
0
  }
935
0
  if (version < required_version) {
936
0
    return _.diag(SPV_ERROR_INVALID_ID, inst)
937
0
           << ReflectionInstructionName(_, inst) << " requires version "
938
0
           << required_version << ", but parsed version is " << version;
939
0
  }
940
941
0
  switch (ext_inst) {
942
0
    case NonSemanticClspvReflectionKernel:
943
0
      return ValidateClspvReflectionKernel(_, inst, version);
944
0
    case NonSemanticClspvReflectionArgumentInfo:
945
0
      return ValidateClspvReflectionArgumentInfo(_, inst);
946
0
    case NonSemanticClspvReflectionArgumentStorageBuffer:
947
0
    case NonSemanticClspvReflectionArgumentUniform:
948
0
    case NonSemanticClspvReflectionArgumentSampledImage:
949
0
    case NonSemanticClspvReflectionArgumentStorageImage:
950
0
    case NonSemanticClspvReflectionArgumentSampler:
951
0
    case NonSemanticClspvReflectionArgumentStorageTexelBuffer:
952
0
    case NonSemanticClspvReflectionArgumentUniformTexelBuffer:
953
0
      return ValidateClspvReflectionArgumentBuffer(_, inst);
954
0
    case NonSemanticClspvReflectionArgumentPodStorageBuffer:
955
0
    case NonSemanticClspvReflectionArgumentPodUniform:
956
0
    case NonSemanticClspvReflectionArgumentPointerUniform:
957
0
      return ValidateClspvReflectionArgumentOffsetBuffer(_, inst);
958
0
    case NonSemanticClspvReflectionArgumentPodPushConstant:
959
0
    case NonSemanticClspvReflectionArgumentPointerPushConstant:
960
0
      return ValidateClspvReflectionArgumentPushConstant(_, inst);
961
0
    case NonSemanticClspvReflectionArgumentWorkgroup:
962
0
      return ValidateClspvReflectionArgumentWorkgroup(_, inst);
963
0
    case NonSemanticClspvReflectionSpecConstantWorkgroupSize:
964
0
    case NonSemanticClspvReflectionSpecConstantGlobalOffset:
965
0
      return ValidateClspvReflectionSpecConstantTriple(_, inst);
966
0
    case NonSemanticClspvReflectionSpecConstantWorkDim:
967
0
      return ValidateClspvReflectionSpecConstantWorkDim(_, inst);
968
0
    case NonSemanticClspvReflectionPushConstantGlobalOffset:
969
0
    case NonSemanticClspvReflectionPushConstantEnqueuedLocalSize:
970
0
    case NonSemanticClspvReflectionPushConstantGlobalSize:
971
0
    case NonSemanticClspvReflectionPushConstantRegionOffset:
972
0
    case NonSemanticClspvReflectionPushConstantNumWorkgroups:
973
0
    case NonSemanticClspvReflectionPushConstantRegionGroupOffset:
974
0
      return ValidateClspvReflectionPushConstant(_, inst);
975
0
    case NonSemanticClspvReflectionConstantDataStorageBuffer:
976
0
    case NonSemanticClspvReflectionConstantDataUniform:
977
0
    case NonSemanticClspvReflectionProgramScopeVariablesStorageBuffer:
978
0
      return ValidateClspvReflectionInitializedData(_, inst);
979
0
    case NonSemanticClspvReflectionLiteralSampler:
980
0
      return ValidateClspvReflectionSampler(_, inst);
981
0
    case NonSemanticClspvReflectionPropertyRequiredWorkgroupSize:
982
0
      return ValidateClspvReflectionPropertyRequiredWorkgroupSize(_, inst);
983
0
    case NonSemanticClspvReflectionSpecConstantSubgroupMaxSize:
984
0
      return ValidateClspvReflectionSubgroupMaxSize(_, inst);
985
0
    case NonSemanticClspvReflectionProgramScopeVariablePointerRelocation:
986
0
      return ValidateClspvReflectionPointerRelocation(_, inst);
987
0
    case NonSemanticClspvReflectionImageArgumentInfoChannelOrderPushConstant:
988
0
    case NonSemanticClspvReflectionImageArgumentInfoChannelDataTypePushConstant:
989
0
      return ValidateClspvReflectionImageMetadataPushConstant(_, inst);
990
0
    case NonSemanticClspvReflectionImageArgumentInfoChannelOrderUniform:
991
0
    case NonSemanticClspvReflectionImageArgumentInfoChannelDataTypeUniform:
992
0
      return ValidateClspvReflectionImageMetadataUniform(_, inst);
993
0
    case NonSemanticClspvReflectionConstantDataPointerPushConstant:
994
0
    case NonSemanticClspvReflectionProgramScopeVariablePointerPushConstant:
995
0
      return ValidateClspvReflectionPushConstantData(_, inst);
996
0
    case NonSemanticClspvReflectionPrintfInfo:
997
0
      return ValidateClspvReflectionPrintfInfo(_, inst);
998
0
    case NonSemanticClspvReflectionPrintfBufferStorageBuffer:
999
0
      return ValidateClspvReflectionPrintfStorageBuffer(_, inst);
1000
0
    case NonSemanticClspvReflectionPrintfBufferPointerPushConstant:
1001
0
      return ValidateClspvReflectionPrintfPushConstant(_, inst);
1002
0
    default:
1003
0
      break;
1004
0
  }
1005
1006
0
  return SPV_SUCCESS;
1007
0
}
1008
1009
bool IsConstIntScalarTypeWith32Or64Bits(ValidationState_t& _,
1010
0
                                        Instruction* instr) {
1011
0
  if (instr->opcode() != spv::Op::OpConstant) return false;
1012
0
  if (!_.IsIntScalarType(instr->type_id())) return false;
1013
0
  uint32_t size_in_bits = _.GetBitWidth(instr->type_id());
1014
0
  return size_in_bits == 32 || size_in_bits == 64;
1015
0
}
1016
1017
bool IsConstWithIntScalarType(ValidationState_t& _, const Instruction* inst,
1018
0
                              uint32_t word_index) {
1019
0
  auto* int_scalar_const = _.FindDef(inst->word(word_index));
1020
0
  if (int_scalar_const->opcode() == spv::Op::OpConstant &&
1021
0
      _.IsIntScalarType(int_scalar_const->type_id())) {
1022
0
    return true;
1023
0
  }
1024
0
  return false;
1025
0
}
1026
1027
bool IsDebugVariableWithIntScalarType(ValidationState_t& _,
1028
                                      const Instruction* inst,
1029
0
                                      uint32_t word_index) {
1030
0
  auto* dbg_int_scalar_var = _.FindDef(inst->word(word_index));
1031
0
  if (CommonDebugInfoInstructions(dbg_int_scalar_var->word(4)) ==
1032
0
          CommonDebugInfoDebugLocalVariable ||
1033
0
      CommonDebugInfoInstructions(dbg_int_scalar_var->word(4)) ==
1034
0
          CommonDebugInfoDebugGlobalVariable) {
1035
0
    auto* dbg_type = _.FindDef(dbg_int_scalar_var->word(6));
1036
0
    if (CommonDebugInfoInstructions(dbg_type->word(4)) ==
1037
0
        CommonDebugInfoDebugTypeBasic) {
1038
0
      const spv_ext_inst_type_t ext_inst_type =
1039
0
          spv_ext_inst_type_t(inst->ext_inst_type());
1040
0
      const bool vulkanDebugInfo =
1041
0
          ext_inst_type == SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100;
1042
0
      uint32_t encoding = dbg_type->word(7);
1043
0
      if (!vulkanDebugInfo || IsUint32Constant(_, encoding)) {
1044
0
        auto ocl_encoding = OpenCLDebugInfo100DebugBaseTypeAttributeEncoding(
1045
0
            vulkanDebugInfo ? GetUint32Constant(_, encoding) : encoding);
1046
0
        if (ocl_encoding == OpenCLDebugInfo100Signed ||
1047
0
            ocl_encoding == OpenCLDebugInfo100Unsigned) {
1048
0
          return true;
1049
0
        }
1050
0
      }
1051
0
    }
1052
0
  }
1053
0
  return false;
1054
0
}
1055
1056
}  // anonymous namespace
1057
1058
2.35k
spv_result_t ValidateExtension(ValidationState_t& _, const Instruction* inst) {
1059
2.35k
  if (_.version() < SPV_SPIRV_VERSION_WORD(1, 4)) {
1060
2.35k
    std::string extension = GetExtensionString(&(inst->c_inst()));
1061
2.35k
    if (extension ==
1062
2.35k
            ExtensionToString(kSPV_KHR_workgroup_memory_explicit_layout) ||
1063
2.35k
        extension == ExtensionToString(kSPV_EXT_mesh_shader) ||
1064
2.35k
        extension == ExtensionToString(kSPV_NV_shader_invocation_reorder)) {
1065
4
      return _.diag(SPV_ERROR_WRONG_VERSION, inst)
1066
4
             << extension << " extension requires SPIR-V version 1.4 or later.";
1067
4
    }
1068
2.35k
  }
1069
1070
2.35k
  return SPV_SUCCESS;
1071
2.35k
}
1072
1073
spv_result_t ValidateExtInstImport(ValidationState_t& _,
1074
8.16k
                                   const Instruction* inst) {
1075
8.16k
  const auto name_id = 1;
1076
8.16k
  if (_.version() <= SPV_SPIRV_VERSION_WORD(1, 5) &&
1077
8.16k
      !_.HasExtension(kSPV_KHR_non_semantic_info)) {
1078
8.16k
    const std::string name = inst->GetOperandAs<std::string>(name_id);
1079
8.16k
    if (name.find("NonSemantic.") == 0) {
1080
9
      return _.diag(SPV_ERROR_INVALID_DATA, inst)
1081
9
             << "NonSemantic extended instruction sets cannot be declared "
1082
9
                "without SPV_KHR_non_semantic_info.";
1083
9
    }
1084
8.16k
  }
1085
1086
8.15k
  return SPV_SUCCESS;
1087
8.16k
}
1088
1089
27.2k
spv_result_t ValidateExtInst(ValidationState_t& _, const Instruction* inst) {
1090
27.2k
  const uint32_t result_type = inst->type_id();
1091
27.2k
  const uint32_t num_operands = static_cast<uint32_t>(inst->operands().size());
1092
1093
27.2k
  const uint32_t ext_inst_set = inst->word(3);
1094
27.2k
  const uint32_t ext_inst_index = inst->word(4);
1095
27.2k
  const spv_ext_inst_type_t ext_inst_type =
1096
27.2k
      spv_ext_inst_type_t(inst->ext_inst_type());
1097
1098
27.2k
  auto ext_inst_name = [&_, ext_inst_set, ext_inst_type, ext_inst_index]() {
1099
209
    spv_ext_inst_desc desc = nullptr;
1100
209
    if (_.grammar().lookupExtInst(ext_inst_type, ext_inst_index, &desc) !=
1101
209
            SPV_SUCCESS ||
1102
209
        !desc) {
1103
0
      return std::string("Unknown ExtInst");
1104
0
    }
1105
1106
209
    auto* import_inst = _.FindDef(ext_inst_set);
1107
209
    assert(import_inst);
1108
1109
0
    std::ostringstream ss;
1110
209
    ss << import_inst->GetOperandAs<std::string>(1);
1111
209
    ss << " ";
1112
209
    ss << desc->name;
1113
1114
209
    return ss.str();
1115
209
  };
1116
1117
27.2k
  if (ext_inst_type == SPV_EXT_INST_TYPE_GLSL_STD_450) {
1118
27.2k
    const GLSLstd450 ext_inst_key = GLSLstd450(ext_inst_index);
1119
27.2k
    switch (ext_inst_key) {
1120
442
      case GLSLstd450Round:
1121
535
      case GLSLstd450RoundEven:
1122
2.09k
      case GLSLstd450FAbs:
1123
2.46k
      case GLSLstd450Trunc:
1124
2.61k
      case GLSLstd450FSign:
1125
3.26k
      case GLSLstd450Floor:
1126
3.34k
      case GLSLstd450Ceil:
1127
5.70k
      case GLSLstd450Fract:
1128
5.82k
      case GLSLstd450Sqrt:
1129
5.86k
      case GLSLstd450InverseSqrt:
1130
5.99k
      case GLSLstd450FMin:
1131
6.02k
      case GLSLstd450FMax:
1132
7.04k
      case GLSLstd450FClamp:
1133
9.99k
      case GLSLstd450FMix:
1134
12.3k
      case GLSLstd450Step:
1135
13.0k
      case GLSLstd450SmoothStep:
1136
13.3k
      case GLSLstd450Fma:
1137
13.6k
      case GLSLstd450Normalize:
1138
13.6k
      case GLSLstd450FaceForward:
1139
13.6k
      case GLSLstd450Reflect:
1140
13.6k
      case GLSLstd450NMin:
1141
13.7k
      case GLSLstd450NMax:
1142
13.7k
      case GLSLstd450NClamp: {
1143
13.7k
        if (!_.IsFloatScalarOrVectorType(result_type)) {
1144
14
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1145
14
                 << ext_inst_name() << ": "
1146
14
                 << "expected Result Type to be a float scalar or vector type";
1147
14
        }
1148
1149
39.7k
        for (uint32_t operand_index = 4; operand_index < num_operands;
1150
26.0k
             ++operand_index) {
1151
26.0k
          const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
1152
26.0k
          if (result_type != operand_type) {
1153
17
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
1154
17
                   << ext_inst_name() << ": "
1155
17
                   << "expected types of all operands to be equal to Result "
1156
17
                      "Type";
1157
17
          }
1158
26.0k
        }
1159
13.6k
        break;
1160
13.6k
      }
1161
1162
13.6k
      case GLSLstd450SAbs:
1163
10
      case GLSLstd450SSign:
1164
13
      case GLSLstd450UMin:
1165
94
      case GLSLstd450SMin:
1166
99
      case GLSLstd450UMax:
1167
101
      case GLSLstd450SMax:
1168
105
      case GLSLstd450UClamp:
1169
109
      case GLSLstd450SClamp:
1170
429
      case GLSLstd450FindILsb:
1171
469
      case GLSLstd450FindUMsb:
1172
2.87k
      case GLSLstd450FindSMsb: {
1173
2.87k
        if (!_.IsIntScalarOrVectorType(result_type)) {
1174
37
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1175
37
                 << ext_inst_name() << ": "
1176
37
                 << "expected Result Type to be an int scalar or vector type";
1177
37
        }
1178
1179
2.83k
        const uint32_t result_type_bit_width = _.GetBitWidth(result_type);
1180
2.83k
        const uint32_t result_type_dimension = _.GetDimension(result_type);
1181
1182
5.74k
        for (uint32_t operand_index = 4; operand_index < num_operands;
1183
2.91k
             ++operand_index) {
1184
2.91k
          const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
1185
2.91k
          if (!operand_type || !_.IsIntScalarOrVectorType(operand_type)) {
1186
6
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
1187
6
                   << ext_inst_name() << ": "
1188
6
                   << "expected all operands to be int scalars or vectors";
1189
6
          }
1190
1191
2.91k
          if (result_type_dimension != _.GetDimension(operand_type)) {
1192
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
1193
0
                   << ext_inst_name() << ": "
1194
0
                   << "expected all operands to have the same dimension as "
1195
0
                   << "Result Type";
1196
0
          }
1197
1198
2.91k
          if (result_type_bit_width != _.GetBitWidth(operand_type)) {
1199
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
1200
0
                   << ext_inst_name() << ": "
1201
0
                   << "expected all operands to have the same bit width as "
1202
0
                   << "Result Type";
1203
0
          }
1204
1205
2.91k
          if (ext_inst_key == GLSLstd450FindUMsb ||
1206
2.91k
              ext_inst_key == GLSLstd450FindSMsb) {
1207
2.43k
            if (result_type_bit_width != 32) {
1208
0
              return _.diag(SPV_ERROR_INVALID_DATA, inst)
1209
0
                     << ext_inst_name() << ": "
1210
0
                     << "this instruction is currently limited to 32-bit width "
1211
0
                     << "components";
1212
0
            }
1213
2.43k
          }
1214
2.91k
        }
1215
2.82k
        break;
1216
2.83k
      }
1217
1218
2.82k
      case GLSLstd450Radians:
1219
165
      case GLSLstd450Degrees:
1220
1.19k
      case GLSLstd450Sin:
1221
1.86k
      case GLSLstd450Cos:
1222
2.54k
      case GLSLstd450Tan:
1223
2.59k
      case GLSLstd450Asin:
1224
2.61k
      case GLSLstd450Acos:
1225
2.72k
      case GLSLstd450Atan:
1226
2.87k
      case GLSLstd450Sinh:
1227
3.88k
      case GLSLstd450Cosh:
1228
5.23k
      case GLSLstd450Tanh:
1229
5.32k
      case GLSLstd450Asinh:
1230
5.39k
      case GLSLstd450Acosh:
1231
5.48k
      case GLSLstd450Atanh:
1232
5.52k
      case GLSLstd450Exp:
1233
5.55k
      case GLSLstd450Exp2:
1234
5.56k
      case GLSLstd450Log:
1235
5.65k
      case GLSLstd450Log2:
1236
5.68k
      case GLSLstd450Atan2:
1237
8.71k
      case GLSLstd450Pow: {
1238
8.71k
        if (!_.IsFloatScalarOrVectorType(result_type)) {
1239
10
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1240
10
                 << ext_inst_name() << ": "
1241
10
                 << "expected Result Type to be a 16 or 32-bit scalar or "
1242
10
                    "vector float type";
1243
10
        }
1244
1245
8.70k
        const uint32_t result_type_bit_width = _.GetBitWidth(result_type);
1246
8.70k
        if (result_type_bit_width != 16 && result_type_bit_width != 32) {
1247
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1248
0
                 << ext_inst_name() << ": "
1249
0
                 << "expected Result Type to be a 16 or 32-bit scalar or "
1250
0
                    "vector float type";
1251
0
        }
1252
1253
20.4k
        for (uint32_t operand_index = 4; operand_index < num_operands;
1254
11.7k
             ++operand_index) {
1255
11.7k
          const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
1256
11.7k
          if (result_type != operand_type) {
1257
9
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
1258
9
                   << ext_inst_name() << ": "
1259
9
                   << "expected types of all operands to be equal to Result "
1260
9
                      "Type";
1261
9
          }
1262
11.7k
        }
1263
8.69k
        break;
1264
8.70k
      }
1265
1266
8.69k
      case GLSLstd450Determinant: {
1267
6
        const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1268
6
        uint32_t num_rows = 0;
1269
6
        uint32_t num_cols = 0;
1270
6
        uint32_t col_type = 0;
1271
6
        uint32_t component_type = 0;
1272
6
        if (!_.GetMatrixTypeInfo(x_type, &num_rows, &num_cols, &col_type,
1273
6
                                 &component_type) ||
1274
6
            num_rows != num_cols) {
1275
5
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1276
5
                 << ext_inst_name() << ": "
1277
5
                 << "expected operand X to be a square matrix";
1278
5
        }
1279
1280
1
        if (result_type != component_type) {
1281
1
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1282
1
                 << ext_inst_name() << ": "
1283
1
                 << "expected operand X component type to be equal to "
1284
1
                 << "Result Type";
1285
1
        }
1286
0
        break;
1287
1
      }
1288
1289
4
      case GLSLstd450MatrixInverse: {
1290
4
        uint32_t num_rows = 0;
1291
4
        uint32_t num_cols = 0;
1292
4
        uint32_t col_type = 0;
1293
4
        uint32_t component_type = 0;
1294
4
        if (!_.GetMatrixTypeInfo(result_type, &num_rows, &num_cols, &col_type,
1295
4
                                 &component_type) ||
1296
4
            num_rows != num_cols) {
1297
3
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1298
3
                 << ext_inst_name() << ": "
1299
3
                 << "expected Result Type to be a square matrix";
1300
3
        }
1301
1302
1
        const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1303
1
        if (result_type != x_type) {
1304
1
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1305
1
                 << ext_inst_name() << ": "
1306
1
                 << "expected operand X type to be equal to Result Type";
1307
1
        }
1308
0
        break;
1309
1
      }
1310
1311
6
      case GLSLstd450Modf: {
1312
6
        if (!_.IsFloatScalarOrVectorType(result_type)) {
1313
1
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1314
1
                 << ext_inst_name() << ": "
1315
1
                 << "expected Result Type to be a scalar or vector float type";
1316
1
        }
1317
1318
5
        const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1319
5
        const uint32_t i_type = _.GetOperandTypeId(inst, 5);
1320
1321
5
        if (x_type != result_type) {
1322
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1323
0
                 << ext_inst_name() << ": "
1324
0
                 << "expected operand X type to be equal to Result Type";
1325
0
        }
1326
1327
5
        spv::StorageClass i_storage_class;
1328
5
        uint32_t i_data_type = 0;
1329
5
        if (!_.GetPointerTypeInfo(i_type, &i_data_type, &i_storage_class)) {
1330
4
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1331
4
                 << ext_inst_name() << ": "
1332
4
                 << "expected operand I to be a pointer";
1333
4
        }
1334
1335
1
        if (i_data_type != result_type) {
1336
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1337
0
                 << ext_inst_name() << ": "
1338
0
                 << "expected operand I data type to be equal to Result Type";
1339
0
        }
1340
1341
1
        break;
1342
1
      }
1343
1344
3
      case GLSLstd450ModfStruct: {
1345
3
        std::vector<uint32_t> result_types;
1346
3
        if (!_.GetStructMemberTypes(result_type, &result_types) ||
1347
3
            result_types.size() != 2 ||
1348
3
            !_.IsFloatScalarOrVectorType(result_types[0]) ||
1349
3
            result_types[1] != result_types[0]) {
1350
3
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1351
3
                 << ext_inst_name() << ": "
1352
3
                 << "expected Result Type to be a struct with two identical "
1353
3
                 << "scalar or vector float type members";
1354
3
        }
1355
1356
0
        const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1357
0
        if (x_type != result_types[0]) {
1358
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1359
0
                 << ext_inst_name() << ": "
1360
0
                 << "expected operand X type to be equal to members of "
1361
0
                 << "Result Type struct";
1362
0
        }
1363
0
        break;
1364
0
      }
1365
1366
7
      case GLSLstd450Frexp: {
1367
7
        if (!_.IsFloatScalarOrVectorType(result_type)) {
1368
2
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1369
2
                 << ext_inst_name() << ": "
1370
2
                 << "expected Result Type to be a scalar or vector float type";
1371
2
        }
1372
1373
5
        const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1374
5
        const uint32_t exp_type = _.GetOperandTypeId(inst, 5);
1375
1376
5
        if (x_type != result_type) {
1377
2
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1378
2
                 << ext_inst_name() << ": "
1379
2
                 << "expected operand X type to be equal to Result Type";
1380
2
        }
1381
1382
3
        spv::StorageClass exp_storage_class;
1383
3
        uint32_t exp_data_type = 0;
1384
3
        if (!_.GetPointerTypeInfo(exp_type, &exp_data_type,
1385
3
                                  &exp_storage_class)) {
1386
3
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1387
3
                 << ext_inst_name() << ": "
1388
3
                 << "expected operand Exp to be a pointer";
1389
3
        }
1390
1391
0
        if (!_.IsIntScalarOrVectorType(exp_data_type) ||
1392
0
            (!_.HasExtension(kSPV_AMD_gpu_shader_int16) &&
1393
0
             _.GetBitWidth(exp_data_type) != 32) ||
1394
0
            (_.HasExtension(kSPV_AMD_gpu_shader_int16) &&
1395
0
             _.GetBitWidth(exp_data_type) != 16 &&
1396
0
             _.GetBitWidth(exp_data_type) != 32)) {
1397
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1398
0
                 << ext_inst_name() << ": "
1399
0
                 << "expected operand Exp data type to be a "
1400
0
                 << (_.HasExtension(kSPV_AMD_gpu_shader_int16)
1401
0
                         ? "16-bit or 32-bit "
1402
0
                         : "32-bit ")
1403
0
                 << "int scalar or vector type";
1404
0
        }
1405
1406
0
        if (_.GetDimension(result_type) != _.GetDimension(exp_data_type)) {
1407
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1408
0
                 << ext_inst_name() << ": "
1409
0
                 << "expected operand Exp data type to have the same component "
1410
0
                 << "number as Result Type";
1411
0
        }
1412
1413
0
        break;
1414
0
      }
1415
1416
1.41k
      case GLSLstd450Ldexp: {
1417
1.41k
        if (!_.IsFloatScalarOrVectorType(result_type)) {
1418
3
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1419
3
                 << ext_inst_name() << ": "
1420
3
                 << "expected Result Type to be a scalar or vector float type";
1421
3
        }
1422
1423
1.40k
        const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1424
1.40k
        const uint32_t exp_type = _.GetOperandTypeId(inst, 5);
1425
1426
1.40k
        if (x_type != result_type) {
1427
4
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1428
4
                 << ext_inst_name() << ": "
1429
4
                 << "expected operand X type to be equal to Result Type";
1430
4
        }
1431
1432
1.40k
        if (!_.IsIntScalarOrVectorType(exp_type)) {
1433
9
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1434
9
                 << ext_inst_name() << ": "
1435
9
                 << "expected operand Exp to be a 32-bit int scalar "
1436
9
                 << "or vector type";
1437
9
        }
1438
1439
1.39k
        if (_.GetDimension(result_type) != _.GetDimension(exp_type)) {
1440
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1441
0
                 << ext_inst_name() << ": "
1442
0
                 << "expected operand Exp to have the same component "
1443
0
                 << "number as Result Type";
1444
0
        }
1445
1446
1.39k
        break;
1447
1.39k
      }
1448
1449
1.39k
      case GLSLstd450FrexpStruct: {
1450
9
        std::vector<uint32_t> result_types;
1451
9
        if (!_.GetStructMemberTypes(result_type, &result_types) ||
1452
9
            result_types.size() != 2 ||
1453
9
            !_.IsFloatScalarOrVectorType(result_types[0]) ||
1454
9
            !_.IsIntScalarOrVectorType(result_types[1]) ||
1455
9
            (!_.HasExtension(kSPV_AMD_gpu_shader_int16) &&
1456
0
             _.GetBitWidth(result_types[1]) != 32) ||
1457
9
            (_.HasExtension(kSPV_AMD_gpu_shader_int16) &&
1458
0
             _.GetBitWidth(result_types[1]) != 16 &&
1459
0
             _.GetBitWidth(result_types[1]) != 32) ||
1460
9
            _.GetDimension(result_types[0]) !=
1461
9
                _.GetDimension(result_types[1])) {
1462
9
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1463
9
                 << ext_inst_name() << ": "
1464
9
                 << "expected Result Type to be a struct with two members, "
1465
9
                 << "first member a float scalar or vector, second member a "
1466
9
                 << (_.HasExtension(kSPV_AMD_gpu_shader_int16)
1467
9
                         ? "16-bit or 32-bit "
1468
9
                         : "32-bit ")
1469
9
                 << "int scalar or vector with the same number of "
1470
9
                 << "components as the first member";
1471
9
        }
1472
1473
0
        const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1474
0
        if (x_type != result_types[0]) {
1475
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1476
0
                 << ext_inst_name() << ": "
1477
0
                 << "expected operand X type to be equal to the first member "
1478
0
                 << "of Result Type struct";
1479
0
        }
1480
0
        break;
1481
0
      }
1482
1483
4
      case GLSLstd450PackSnorm4x8:
1484
8
      case GLSLstd450PackUnorm4x8: {
1485
8
        if (!_.IsIntScalarType(result_type) ||
1486
8
            _.GetBitWidth(result_type) != 32) {
1487
3
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1488
3
                 << ext_inst_name() << ": "
1489
3
                 << "expected Result Type to be 32-bit int scalar type";
1490
3
        }
1491
1492
5
        const uint32_t v_type = _.GetOperandTypeId(inst, 4);
1493
5
        if (!_.IsFloatVectorType(v_type) || _.GetDimension(v_type) != 4 ||
1494
5
            _.GetBitWidth(v_type) != 32) {
1495
5
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1496
5
                 << ext_inst_name() << ": "
1497
5
                 << "expected operand V to be a 32-bit float vector of size 4";
1498
5
        }
1499
0
        break;
1500
5
      }
1501
1502
5
      case GLSLstd450PackSnorm2x16:
1503
10
      case GLSLstd450PackUnorm2x16:
1504
13
      case GLSLstd450PackHalf2x16: {
1505
13
        if (!_.IsIntScalarType(result_type) ||
1506
13
            _.GetBitWidth(result_type) != 32) {
1507
5
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1508
5
                 << ext_inst_name() << ": "
1509
5
                 << "expected Result Type to be 32-bit int scalar type";
1510
5
        }
1511
1512
8
        const uint32_t v_type = _.GetOperandTypeId(inst, 4);
1513
8
        if (!_.IsFloatVectorType(v_type) || _.GetDimension(v_type) != 2 ||
1514
8
            _.GetBitWidth(v_type) != 32) {
1515
5
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1516
5
                 << ext_inst_name() << ": "
1517
5
                 << "expected operand V to be a 32-bit float vector of size 2";
1518
5
        }
1519
3
        break;
1520
8
      }
1521
1522
5
      case GLSLstd450PackDouble2x32: {
1523
5
        if (!_.IsFloatScalarType(result_type) ||
1524
5
            _.GetBitWidth(result_type) != 64) {
1525
5
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1526
5
                 << ext_inst_name() << ": "
1527
5
                 << "expected Result Type to be 64-bit float scalar type";
1528
5
        }
1529
1530
0
        const uint32_t v_type = _.GetOperandTypeId(inst, 4);
1531
0
        if (!_.IsIntVectorType(v_type) || _.GetDimension(v_type) != 2 ||
1532
0
            _.GetBitWidth(v_type) != 32) {
1533
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1534
0
                 << ext_inst_name() << ": "
1535
0
                 << "expected operand V to be a 32-bit int vector of size 2";
1536
0
        }
1537
0
        break;
1538
0
      }
1539
1540
11
      case GLSLstd450UnpackSnorm4x8:
1541
25
      case GLSLstd450UnpackUnorm4x8: {
1542
25
        if (!_.IsFloatVectorType(result_type) ||
1543
25
            _.GetDimension(result_type) != 4 ||
1544
25
            _.GetBitWidth(result_type) != 32) {
1545
8
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1546
8
                 << ext_inst_name() << ": "
1547
8
                 << "expected Result Type to be a 32-bit float vector of size "
1548
8
                    "4";
1549
8
        }
1550
1551
17
        const uint32_t v_type = _.GetOperandTypeId(inst, 4);
1552
17
        if (!_.IsIntScalarType(v_type) || _.GetBitWidth(v_type) != 32) {
1553
2
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1554
2
                 << ext_inst_name() << ": "
1555
2
                 << "expected operand P to be a 32-bit int scalar";
1556
2
        }
1557
15
        break;
1558
17
      }
1559
1560
15
      case GLSLstd450UnpackSnorm2x16:
1561
9
      case GLSLstd450UnpackUnorm2x16:
1562
11
      case GLSLstd450UnpackHalf2x16: {
1563
11
        if (!_.IsFloatVectorType(result_type) ||
1564
11
            _.GetDimension(result_type) != 2 ||
1565
11
            _.GetBitWidth(result_type) != 32) {
1566
8
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1567
8
                 << ext_inst_name() << ": "
1568
8
                 << "expected Result Type to be a 32-bit float vector of size "
1569
8
                    "2";
1570
8
        }
1571
1572
3
        const uint32_t v_type = _.GetOperandTypeId(inst, 4);
1573
3
        if (!_.IsIntScalarType(v_type) || _.GetBitWidth(v_type) != 32) {
1574
3
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1575
3
                 << ext_inst_name() << ": "
1576
3
                 << "expected operand P to be a 32-bit int scalar";
1577
3
        }
1578
0
        break;
1579
3
      }
1580
1581
3
      case GLSLstd450UnpackDouble2x32: {
1582
3
        if (!_.IsIntVectorType(result_type) ||
1583
3
            _.GetDimension(result_type) != 2 ||
1584
3
            _.GetBitWidth(result_type) != 32) {
1585
3
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1586
3
                 << ext_inst_name() << ": "
1587
3
                 << "expected Result Type to be a 32-bit int vector of size "
1588
3
                    "2";
1589
3
        }
1590
1591
0
        const uint32_t v_type = _.GetOperandTypeId(inst, 4);
1592
0
        if (!_.IsFloatScalarType(v_type) || _.GetBitWidth(v_type) != 64) {
1593
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1594
0
                 << ext_inst_name() << ": "
1595
0
                 << "expected operand V to be a 64-bit float scalar";
1596
0
        }
1597
0
        break;
1598
0
      }
1599
1600
450
      case GLSLstd450Length: {
1601
450
        if (!_.IsFloatScalarType(result_type)) {
1602
4
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1603
4
                 << ext_inst_name() << ": "
1604
4
                 << "expected Result Type to be a float scalar type";
1605
4
        }
1606
1607
446
        const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1608
446
        if (!_.IsFloatScalarOrVectorType(x_type)) {
1609
3
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1610
3
                 << ext_inst_name() << ": "
1611
3
                 << "expected operand X to be of float scalar or vector type";
1612
3
        }
1613
1614
443
        if (result_type != _.GetComponentType(x_type)) {
1615
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1616
0
                 << ext_inst_name() << ": "
1617
0
                 << "expected operand X component type to be equal to Result "
1618
0
                    "Type";
1619
0
        }
1620
443
        break;
1621
443
      }
1622
1623
443
      case GLSLstd450Distance: {
1624
5
        if (!_.IsFloatScalarType(result_type)) {
1625
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1626
0
                 << ext_inst_name() << ": "
1627
0
                 << "expected Result Type to be a float scalar type";
1628
0
        }
1629
1630
5
        const uint32_t p0_type = _.GetOperandTypeId(inst, 4);
1631
5
        if (!_.IsFloatScalarOrVectorType(p0_type)) {
1632
1
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1633
1
                 << ext_inst_name() << ": "
1634
1
                 << "expected operand P0 to be of float scalar or vector type";
1635
1
        }
1636
1637
4
        if (result_type != _.GetComponentType(p0_type)) {
1638
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1639
0
                 << ext_inst_name() << ": "
1640
0
                 << "expected operand P0 component type to be equal to "
1641
0
                 << "Result Type";
1642
0
        }
1643
1644
4
        const uint32_t p1_type = _.GetOperandTypeId(inst, 5);
1645
4
        if (!_.IsFloatScalarOrVectorType(p1_type)) {
1646
1
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1647
1
                 << ext_inst_name() << ": "
1648
1
                 << "expected operand P1 to be of float scalar or vector type";
1649
1
        }
1650
1651
3
        if (result_type != _.GetComponentType(p1_type)) {
1652
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1653
0
                 << ext_inst_name() << ": "
1654
0
                 << "expected operand P1 component type to be equal to "
1655
0
                 << "Result Type";
1656
0
        }
1657
1658
3
        if (_.GetDimension(p0_type) != _.GetDimension(p1_type)) {
1659
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1660
0
                 << ext_inst_name() << ": "
1661
0
                 << "expected operands P0 and P1 to have the same number of "
1662
0
                 << "components";
1663
0
        }
1664
3
        break;
1665
3
      }
1666
1667
4
      case GLSLstd450Cross: {
1668
4
        if (!_.IsFloatVectorType(result_type)) {
1669
4
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1670
4
                 << ext_inst_name() << ": "
1671
4
                 << "expected Result Type to be a float vector type";
1672
4
        }
1673
1674
0
        if (_.GetDimension(result_type) != 3) {
1675
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1676
0
                 << ext_inst_name() << ": "
1677
0
                 << "expected Result Type to have 3 components";
1678
0
        }
1679
1680
0
        const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1681
0
        const uint32_t y_type = _.GetOperandTypeId(inst, 5);
1682
1683
0
        if (x_type != result_type) {
1684
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1685
0
                 << ext_inst_name() << ": "
1686
0
                 << "expected operand X type to be equal to Result Type";
1687
0
        }
1688
1689
0
        if (y_type != result_type) {
1690
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1691
0
                 << ext_inst_name() << ": "
1692
0
                 << "expected operand Y type to be equal to Result Type";
1693
0
        }
1694
0
        break;
1695
0
      }
1696
1697
3
      case GLSLstd450Refract: {
1698
3
        if (!_.IsFloatScalarOrVectorType(result_type)) {
1699
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1700
0
                 << ext_inst_name() << ": "
1701
0
                 << "expected Result Type to be a float scalar or vector type";
1702
0
        }
1703
1704
3
        const uint32_t i_type = _.GetOperandTypeId(inst, 4);
1705
3
        const uint32_t n_type = _.GetOperandTypeId(inst, 5);
1706
3
        const uint32_t eta_type = _.GetOperandTypeId(inst, 6);
1707
1708
3
        if (result_type != i_type) {
1709
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1710
0
                 << ext_inst_name() << ": "
1711
0
                 << "expected operand I to be of type equal to Result Type";
1712
0
        }
1713
1714
3
        if (result_type != n_type) {
1715
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1716
0
                 << ext_inst_name() << ": "
1717
0
                 << "expected operand N to be of type equal to Result Type";
1718
0
        }
1719
1720
3
        if (!_.IsFloatScalarType(eta_type)) {
1721
1
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1722
1
                 << ext_inst_name() << ": "
1723
1
                 << "expected operand Eta to be a float scalar";
1724
1
        }
1725
2
        break;
1726
3
      }
1727
1728
2
      case GLSLstd450InterpolateAtCentroid:
1729
2
      case GLSLstd450InterpolateAtSample:
1730
5
      case GLSLstd450InterpolateAtOffset: {
1731
5
        if (!_.HasCapability(spv::Capability::InterpolationFunction)) {
1732
4
          return _.diag(SPV_ERROR_INVALID_CAPABILITY, inst)
1733
4
                 << ext_inst_name()
1734
4
                 << " requires capability InterpolationFunction";
1735
4
        }
1736
1737
1
        if (!_.IsFloatScalarOrVectorType(result_type) ||
1738
1
            _.GetBitWidth(result_type) != 32) {
1739
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1740
0
                 << ext_inst_name() << ": "
1741
0
                 << "expected Result Type to be a 32-bit float scalar "
1742
0
                 << "or vector type";
1743
0
        }
1744
1745
        // If HLSL legalization and first operand is an OpLoad, use load
1746
        // pointer as the interpolant lvalue. Else use interpolate first
1747
        // operand.
1748
1
        uint32_t interp_id = inst->GetOperandAs<uint32_t>(4);
1749
1
        auto* interp_inst = _.FindDef(interp_id);
1750
1
        uint32_t interpolant_type = (_.options()->before_hlsl_legalization &&
1751
1
                                     interp_inst->opcode() == spv::Op::OpLoad)
1752
1
                                        ? _.GetOperandTypeId(interp_inst, 2)
1753
1
                                        : _.GetOperandTypeId(inst, 4);
1754
1755
1
        spv::StorageClass interpolant_storage_class;
1756
1
        uint32_t interpolant_data_type = 0;
1757
1
        if (!_.GetPointerTypeInfo(interpolant_type, &interpolant_data_type,
1758
1
                                  &interpolant_storage_class)) {
1759
1
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1760
1
                 << ext_inst_name() << ": "
1761
1
                 << "expected Interpolant to be a pointer";
1762
1
        }
1763
1764
0
        if (result_type != interpolant_data_type) {
1765
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1766
0
                 << ext_inst_name() << ": "
1767
0
                 << "expected Interpolant data type to be equal to Result Type";
1768
0
        }
1769
1770
0
        if (interpolant_storage_class != spv::StorageClass::Input) {
1771
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1772
0
                 << ext_inst_name() << ": "
1773
0
                 << "expected Interpolant storage class to be Input";
1774
0
        }
1775
1776
0
        if (ext_inst_key == GLSLstd450InterpolateAtSample) {
1777
0
          const uint32_t sample_type = _.GetOperandTypeId(inst, 5);
1778
0
          if (!_.IsIntScalarType(sample_type) ||
1779
0
              _.GetBitWidth(sample_type) != 32) {
1780
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
1781
0
                   << ext_inst_name() << ": "
1782
0
                   << "expected Sample to be 32-bit integer";
1783
0
          }
1784
0
        }
1785
1786
0
        if (ext_inst_key == GLSLstd450InterpolateAtOffset) {
1787
0
          const uint32_t offset_type = _.GetOperandTypeId(inst, 5);
1788
0
          if (!_.IsFloatVectorType(offset_type) ||
1789
0
              _.GetDimension(offset_type) != 2 ||
1790
0
              _.GetBitWidth(offset_type) != 32) {
1791
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
1792
0
                   << ext_inst_name() << ": "
1793
0
                   << "expected Offset to be a vector of 2 32-bit floats";
1794
0
          }
1795
0
        }
1796
1797
0
        _.function(inst->function()->id())
1798
0
            ->RegisterExecutionModelLimitation(
1799
0
                spv::ExecutionModel::Fragment,
1800
0
                ext_inst_name() +
1801
0
                    std::string(" requires Fragment execution model"));
1802
0
        break;
1803
0
      }
1804
1805
1
      case GLSLstd450IMix: {
1806
1
        return _.diag(SPV_ERROR_INVALID_DATA, inst)
1807
1
               << "Extended instruction GLSLstd450IMix is not supported";
1808
0
      }
1809
1810
0
      case GLSLstd450Bad: {
1811
0
        return _.diag(SPV_ERROR_INVALID_DATA, inst)
1812
0
               << "Encountered extended instruction GLSLstd450Bad";
1813
0
      }
1814
1815
0
      case GLSLstd450Count: {
1816
0
        assert(0);
1817
0
        break;
1818
0
      }
1819
27.2k
    }
1820
27.2k
  } else if (ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_STD) {
1821
0
    const OpenCLLIB::Entrypoints ext_inst_key =
1822
0
        OpenCLLIB::Entrypoints(ext_inst_index);
1823
0
    switch (ext_inst_key) {
1824
0
      case OpenCLLIB::Acos:
1825
0
      case OpenCLLIB::Acosh:
1826
0
      case OpenCLLIB::Acospi:
1827
0
      case OpenCLLIB::Asin:
1828
0
      case OpenCLLIB::Asinh:
1829
0
      case OpenCLLIB::Asinpi:
1830
0
      case OpenCLLIB::Atan:
1831
0
      case OpenCLLIB::Atan2:
1832
0
      case OpenCLLIB::Atanh:
1833
0
      case OpenCLLIB::Atanpi:
1834
0
      case OpenCLLIB::Atan2pi:
1835
0
      case OpenCLLIB::Cbrt:
1836
0
      case OpenCLLIB::Ceil:
1837
0
      case OpenCLLIB::Copysign:
1838
0
      case OpenCLLIB::Cos:
1839
0
      case OpenCLLIB::Cosh:
1840
0
      case OpenCLLIB::Cospi:
1841
0
      case OpenCLLIB::Erfc:
1842
0
      case OpenCLLIB::Erf:
1843
0
      case OpenCLLIB::Exp:
1844
0
      case OpenCLLIB::Exp2:
1845
0
      case OpenCLLIB::Exp10:
1846
0
      case OpenCLLIB::Expm1:
1847
0
      case OpenCLLIB::Fabs:
1848
0
      case OpenCLLIB::Fdim:
1849
0
      case OpenCLLIB::Floor:
1850
0
      case OpenCLLIB::Fma:
1851
0
      case OpenCLLIB::Fmax:
1852
0
      case OpenCLLIB::Fmin:
1853
0
      case OpenCLLIB::Fmod:
1854
0
      case OpenCLLIB::Hypot:
1855
0
      case OpenCLLIB::Lgamma:
1856
0
      case OpenCLLIB::Log:
1857
0
      case OpenCLLIB::Log2:
1858
0
      case OpenCLLIB::Log10:
1859
0
      case OpenCLLIB::Log1p:
1860
0
      case OpenCLLIB::Logb:
1861
0
      case OpenCLLIB::Mad:
1862
0
      case OpenCLLIB::Maxmag:
1863
0
      case OpenCLLIB::Minmag:
1864
0
      case OpenCLLIB::Nextafter:
1865
0
      case OpenCLLIB::Pow:
1866
0
      case OpenCLLIB::Powr:
1867
0
      case OpenCLLIB::Remainder:
1868
0
      case OpenCLLIB::Rint:
1869
0
      case OpenCLLIB::Round:
1870
0
      case OpenCLLIB::Rsqrt:
1871
0
      case OpenCLLIB::Sin:
1872
0
      case OpenCLLIB::Sinh:
1873
0
      case OpenCLLIB::Sinpi:
1874
0
      case OpenCLLIB::Sqrt:
1875
0
      case OpenCLLIB::Tan:
1876
0
      case OpenCLLIB::Tanh:
1877
0
      case OpenCLLIB::Tanpi:
1878
0
      case OpenCLLIB::Tgamma:
1879
0
      case OpenCLLIB::Trunc:
1880
0
      case OpenCLLIB::Half_cos:
1881
0
      case OpenCLLIB::Half_divide:
1882
0
      case OpenCLLIB::Half_exp:
1883
0
      case OpenCLLIB::Half_exp2:
1884
0
      case OpenCLLIB::Half_exp10:
1885
0
      case OpenCLLIB::Half_log:
1886
0
      case OpenCLLIB::Half_log2:
1887
0
      case OpenCLLIB::Half_log10:
1888
0
      case OpenCLLIB::Half_powr:
1889
0
      case OpenCLLIB::Half_recip:
1890
0
      case OpenCLLIB::Half_rsqrt:
1891
0
      case OpenCLLIB::Half_sin:
1892
0
      case OpenCLLIB::Half_sqrt:
1893
0
      case OpenCLLIB::Half_tan:
1894
0
      case OpenCLLIB::Native_cos:
1895
0
      case OpenCLLIB::Native_divide:
1896
0
      case OpenCLLIB::Native_exp:
1897
0
      case OpenCLLIB::Native_exp2:
1898
0
      case OpenCLLIB::Native_exp10:
1899
0
      case OpenCLLIB::Native_log:
1900
0
      case OpenCLLIB::Native_log2:
1901
0
      case OpenCLLIB::Native_log10:
1902
0
      case OpenCLLIB::Native_powr:
1903
0
      case OpenCLLIB::Native_recip:
1904
0
      case OpenCLLIB::Native_rsqrt:
1905
0
      case OpenCLLIB::Native_sin:
1906
0
      case OpenCLLIB::Native_sqrt:
1907
0
      case OpenCLLIB::Native_tan:
1908
0
      case OpenCLLIB::FClamp:
1909
0
      case OpenCLLIB::Degrees:
1910
0
      case OpenCLLIB::FMax_common:
1911
0
      case OpenCLLIB::FMin_common:
1912
0
      case OpenCLLIB::Mix:
1913
0
      case OpenCLLIB::Radians:
1914
0
      case OpenCLLIB::Step:
1915
0
      case OpenCLLIB::Smoothstep:
1916
0
      case OpenCLLIB::Sign: {
1917
0
        if (!_.IsFloatScalarOrVectorType(result_type)) {
1918
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1919
0
                 << ext_inst_name() << ": "
1920
0
                 << "expected Result Type to be a float scalar or vector type";
1921
0
        }
1922
1923
0
        const uint32_t num_components = _.GetDimension(result_type);
1924
0
        if (num_components > 4 && num_components != 8 && num_components != 16) {
1925
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1926
0
                 << ext_inst_name() << ": "
1927
0
                 << "expected Result Type to be a scalar or a vector with 2, "
1928
0
                    "3, 4, 8 or 16 components";
1929
0
        }
1930
1931
0
        for (uint32_t operand_index = 4; operand_index < num_operands;
1932
0
             ++operand_index) {
1933
0
          const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
1934
0
          if (result_type != operand_type) {
1935
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
1936
0
                   << ext_inst_name() << ": "
1937
0
                   << "expected types of all operands to be equal to Result "
1938
0
                      "Type";
1939
0
          }
1940
0
        }
1941
0
        break;
1942
0
      }
1943
1944
0
      case OpenCLLIB::Fract:
1945
0
      case OpenCLLIB::Modf:
1946
0
      case OpenCLLIB::Sincos: {
1947
0
        if (!_.IsFloatScalarOrVectorType(result_type)) {
1948
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1949
0
                 << ext_inst_name() << ": "
1950
0
                 << "expected Result Type to be a float scalar or vector type";
1951
0
        }
1952
1953
0
        const uint32_t num_components = _.GetDimension(result_type);
1954
0
        if (num_components > 4 && num_components != 8 && num_components != 16) {
1955
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1956
0
                 << ext_inst_name() << ": "
1957
0
                 << "expected Result Type to be a scalar or a vector with 2, "
1958
0
                    "3, 4, 8 or 16 components";
1959
0
        }
1960
1961
0
        const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1962
0
        if (result_type != x_type) {
1963
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1964
0
                 << ext_inst_name() << ": "
1965
0
                 << "expected type of operand X to be equal to Result Type";
1966
0
        }
1967
1968
0
        const uint32_t p_type = _.GetOperandTypeId(inst, 5);
1969
0
        spv::StorageClass p_storage_class;
1970
0
        uint32_t p_data_type = 0;
1971
0
        if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
1972
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1973
0
                 << ext_inst_name() << ": "
1974
0
                 << "expected the last operand to be a pointer";
1975
0
        }
1976
1977
0
        if (p_storage_class != spv::StorageClass::Generic &&
1978
0
            p_storage_class != spv::StorageClass::CrossWorkgroup &&
1979
0
            p_storage_class != spv::StorageClass::Workgroup &&
1980
0
            p_storage_class != spv::StorageClass::Function) {
1981
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1982
0
                 << ext_inst_name() << ": "
1983
0
                 << "expected storage class of the pointer to be Generic, "
1984
0
                    "CrossWorkgroup, Workgroup or Function";
1985
0
        }
1986
1987
0
        if (result_type != p_data_type) {
1988
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
1989
0
                 << ext_inst_name() << ": "
1990
0
                 << "expected data type of the pointer to be equal to Result "
1991
0
                    "Type";
1992
0
        }
1993
0
        break;
1994
0
      }
1995
1996
0
      case OpenCLLIB::Frexp:
1997
0
      case OpenCLLIB::Lgamma_r:
1998
0
      case OpenCLLIB::Remquo: {
1999
0
        if (!_.IsFloatScalarOrVectorType(result_type)) {
2000
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2001
0
                 << ext_inst_name() << ": "
2002
0
                 << "expected Result Type to be a float scalar or vector type";
2003
0
        }
2004
2005
0
        const uint32_t num_components = _.GetDimension(result_type);
2006
0
        if (num_components > 4 && num_components != 8 && num_components != 16) {
2007
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2008
0
                 << ext_inst_name() << ": "
2009
0
                 << "expected Result Type to be a scalar or a vector with 2, "
2010
0
                    "3, 4, 8 or 16 components";
2011
0
        }
2012
2013
0
        uint32_t operand_index = 4;
2014
0
        const uint32_t x_type = _.GetOperandTypeId(inst, operand_index++);
2015
0
        if (result_type != x_type) {
2016
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2017
0
                 << ext_inst_name() << ": "
2018
0
                 << "expected type of operand X to be equal to Result Type";
2019
0
        }
2020
2021
0
        if (ext_inst_key == OpenCLLIB::Remquo) {
2022
0
          const uint32_t y_type = _.GetOperandTypeId(inst, operand_index++);
2023
0
          if (result_type != y_type) {
2024
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
2025
0
                   << ext_inst_name() << ": "
2026
0
                   << "expected type of operand Y to be equal to Result Type";
2027
0
          }
2028
0
        }
2029
2030
0
        const uint32_t p_type = _.GetOperandTypeId(inst, operand_index++);
2031
0
        spv::StorageClass p_storage_class;
2032
0
        uint32_t p_data_type = 0;
2033
0
        if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
2034
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2035
0
                 << ext_inst_name() << ": "
2036
0
                 << "expected the last operand to be a pointer";
2037
0
        }
2038
2039
0
        if (p_storage_class != spv::StorageClass::Generic &&
2040
0
            p_storage_class != spv::StorageClass::CrossWorkgroup &&
2041
0
            p_storage_class != spv::StorageClass::Workgroup &&
2042
0
            p_storage_class != spv::StorageClass::Function) {
2043
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2044
0
                 << ext_inst_name() << ": "
2045
0
                 << "expected storage class of the pointer to be Generic, "
2046
0
                    "CrossWorkgroup, Workgroup or Function";
2047
0
        }
2048
2049
0
        if (!_.IsIntScalarOrVectorType(p_data_type) ||
2050
0
            _.GetBitWidth(p_data_type) != 32) {
2051
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2052
0
                 << ext_inst_name() << ": "
2053
0
                 << "expected data type of the pointer to be a 32-bit int "
2054
0
                    "scalar or vector type";
2055
0
        }
2056
2057
0
        if (_.GetDimension(p_data_type) != num_components) {
2058
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2059
0
                 << ext_inst_name() << ": "
2060
0
                 << "expected data type of the pointer to have the same number "
2061
0
                    "of components as Result Type";
2062
0
        }
2063
0
        break;
2064
0
      }
2065
2066
0
      case OpenCLLIB::Ilogb: {
2067
0
        if (!_.IsIntScalarOrVectorType(result_type) ||
2068
0
            _.GetBitWidth(result_type) != 32) {
2069
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2070
0
                 << ext_inst_name() << ": "
2071
0
                 << "expected Result Type to be a 32-bit int scalar or vector "
2072
0
                    "type";
2073
0
        }
2074
2075
0
        const uint32_t num_components = _.GetDimension(result_type);
2076
0
        if (num_components > 4 && num_components != 8 && num_components != 16) {
2077
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2078
0
                 << ext_inst_name() << ": "
2079
0
                 << "expected Result Type to be a scalar or a vector with 2, "
2080
0
                    "3, 4, 8 or 16 components";
2081
0
        }
2082
2083
0
        const uint32_t x_type = _.GetOperandTypeId(inst, 4);
2084
0
        if (!_.IsFloatScalarOrVectorType(x_type)) {
2085
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2086
0
                 << ext_inst_name() << ": "
2087
0
                 << "expected operand X to be a float scalar or vector";
2088
0
        }
2089
2090
0
        if (_.GetDimension(x_type) != num_components) {
2091
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2092
0
                 << ext_inst_name() << ": "
2093
0
                 << "expected operand X to have the same number of components "
2094
0
                    "as Result Type";
2095
0
        }
2096
0
        break;
2097
0
      }
2098
2099
0
      case OpenCLLIB::Ldexp:
2100
0
      case OpenCLLIB::Pown:
2101
0
      case OpenCLLIB::Rootn: {
2102
0
        if (!_.IsFloatScalarOrVectorType(result_type)) {
2103
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2104
0
                 << ext_inst_name() << ": "
2105
0
                 << "expected Result Type to be a float scalar or vector type";
2106
0
        }
2107
2108
0
        const uint32_t num_components = _.GetDimension(result_type);
2109
0
        if (num_components > 4 && num_components != 8 && num_components != 16) {
2110
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2111
0
                 << ext_inst_name() << ": "
2112
0
                 << "expected Result Type to be a scalar or a vector with 2, "
2113
0
                    "3, 4, 8 or 16 components";
2114
0
        }
2115
2116
0
        const uint32_t x_type = _.GetOperandTypeId(inst, 4);
2117
0
        if (result_type != x_type) {
2118
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2119
0
                 << ext_inst_name() << ": "
2120
0
                 << "expected type of operand X to be equal to Result Type";
2121
0
        }
2122
2123
0
        const uint32_t exp_type = _.GetOperandTypeId(inst, 5);
2124
0
        if (!_.IsIntScalarOrVectorType(exp_type) ||
2125
0
            _.GetBitWidth(exp_type) != 32) {
2126
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2127
0
                 << ext_inst_name() << ": "
2128
0
                 << "expected the exponent to be a 32-bit int scalar or vector";
2129
0
        }
2130
2131
0
        if (_.GetDimension(exp_type) != num_components) {
2132
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2133
0
                 << ext_inst_name() << ": "
2134
0
                 << "expected the exponent to have the same number of "
2135
0
                    "components as Result Type";
2136
0
        }
2137
0
        break;
2138
0
      }
2139
2140
0
      case OpenCLLIB::Nan: {
2141
0
        if (!_.IsFloatScalarOrVectorType(result_type)) {
2142
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2143
0
                 << ext_inst_name() << ": "
2144
0
                 << "expected Result Type to be a float scalar or vector type";
2145
0
        }
2146
2147
0
        const uint32_t num_components = _.GetDimension(result_type);
2148
0
        if (num_components > 4 && num_components != 8 && num_components != 16) {
2149
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2150
0
                 << ext_inst_name() << ": "
2151
0
                 << "expected Result Type to be a scalar or a vector with 2, "
2152
0
                    "3, 4, 8 or 16 components";
2153
0
        }
2154
2155
0
        const uint32_t nancode_type = _.GetOperandTypeId(inst, 4);
2156
0
        if (!_.IsIntScalarOrVectorType(nancode_type)) {
2157
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2158
0
                 << ext_inst_name() << ": "
2159
0
                 << "expected Nancode to be an int scalar or vector type";
2160
0
        }
2161
2162
0
        if (_.GetDimension(nancode_type) != num_components) {
2163
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2164
0
                 << ext_inst_name() << ": "
2165
0
                 << "expected Nancode to have the same number of components as "
2166
0
                    "Result Type";
2167
0
        }
2168
2169
0
        if (_.GetBitWidth(result_type) != _.GetBitWidth(nancode_type)) {
2170
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2171
0
                 << ext_inst_name() << ": "
2172
0
                 << "expected Nancode to have the same bit width as Result "
2173
0
                    "Type";
2174
0
        }
2175
0
        break;
2176
0
      }
2177
2178
0
      case OpenCLLIB::SAbs:
2179
0
      case OpenCLLIB::SAbs_diff:
2180
0
      case OpenCLLIB::SAdd_sat:
2181
0
      case OpenCLLIB::UAdd_sat:
2182
0
      case OpenCLLIB::SHadd:
2183
0
      case OpenCLLIB::UHadd:
2184
0
      case OpenCLLIB::SRhadd:
2185
0
      case OpenCLLIB::URhadd:
2186
0
      case OpenCLLIB::SClamp:
2187
0
      case OpenCLLIB::UClamp:
2188
0
      case OpenCLLIB::Clz:
2189
0
      case OpenCLLIB::Ctz:
2190
0
      case OpenCLLIB::SMad_hi:
2191
0
      case OpenCLLIB::UMad_sat:
2192
0
      case OpenCLLIB::SMad_sat:
2193
0
      case OpenCLLIB::SMax:
2194
0
      case OpenCLLIB::UMax:
2195
0
      case OpenCLLIB::SMin:
2196
0
      case OpenCLLIB::UMin:
2197
0
      case OpenCLLIB::SMul_hi:
2198
0
      case OpenCLLIB::Rotate:
2199
0
      case OpenCLLIB::SSub_sat:
2200
0
      case OpenCLLIB::USub_sat:
2201
0
      case OpenCLLIB::Popcount:
2202
0
      case OpenCLLIB::UAbs:
2203
0
      case OpenCLLIB::UAbs_diff:
2204
0
      case OpenCLLIB::UMul_hi:
2205
0
      case OpenCLLIB::UMad_hi: {
2206
0
        if (!_.IsIntScalarOrVectorType(result_type)) {
2207
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2208
0
                 << ext_inst_name() << ": "
2209
0
                 << "expected Result Type to be an int scalar or vector type";
2210
0
        }
2211
2212
0
        const uint32_t num_components = _.GetDimension(result_type);
2213
0
        if (num_components > 4 && num_components != 8 && num_components != 16) {
2214
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2215
0
                 << ext_inst_name() << ": "
2216
0
                 << "expected Result Type to be a scalar or a vector with 2, "
2217
0
                    "3, 4, 8 or 16 components";
2218
0
        }
2219
2220
0
        for (uint32_t operand_index = 4; operand_index < num_operands;
2221
0
             ++operand_index) {
2222
0
          const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
2223
0
          if (result_type != operand_type) {
2224
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
2225
0
                   << ext_inst_name() << ": "
2226
0
                   << "expected types of all operands to be equal to Result "
2227
0
                      "Type";
2228
0
          }
2229
0
        }
2230
0
        break;
2231
0
      }
2232
2233
0
      case OpenCLLIB::U_Upsample:
2234
0
      case OpenCLLIB::S_Upsample: {
2235
0
        if (!_.IsIntScalarOrVectorType(result_type)) {
2236
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2237
0
                 << ext_inst_name() << ": "
2238
0
                 << "expected Result Type to be an int scalar or vector "
2239
0
                    "type";
2240
0
        }
2241
2242
0
        const uint32_t result_num_components = _.GetDimension(result_type);
2243
0
        if (result_num_components > 4 && result_num_components != 8 &&
2244
0
            result_num_components != 16) {
2245
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2246
0
                 << ext_inst_name() << ": "
2247
0
                 << "expected Result Type to be a scalar or a vector with 2, "
2248
0
                    "3, 4, 8 or 16 components";
2249
0
        }
2250
2251
0
        const uint32_t result_bit_width = _.GetBitWidth(result_type);
2252
0
        if (result_bit_width != 16 && result_bit_width != 32 &&
2253
0
            result_bit_width != 64) {
2254
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2255
0
                 << ext_inst_name() << ": "
2256
0
                 << "expected bit width of Result Type components to be 16, 32 "
2257
0
                    "or 64";
2258
0
        }
2259
2260
0
        const uint32_t hi_type = _.GetOperandTypeId(inst, 4);
2261
0
        const uint32_t lo_type = _.GetOperandTypeId(inst, 5);
2262
2263
0
        if (hi_type != lo_type) {
2264
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2265
0
                 << ext_inst_name() << ": "
2266
0
                 << "expected Hi and Lo operands to have the same type";
2267
0
        }
2268
2269
0
        if (result_num_components != _.GetDimension(hi_type)) {
2270
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2271
0
                 << ext_inst_name() << ": "
2272
0
                 << "expected Hi and Lo operands to have the same number of "
2273
0
                    "components as Result Type";
2274
0
        }
2275
2276
0
        if (result_bit_width != 2 * _.GetBitWidth(hi_type)) {
2277
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2278
0
                 << ext_inst_name() << ": "
2279
0
                 << "expected bit width of components of Hi and Lo operands to "
2280
0
                    "be half of the bit width of components of Result Type";
2281
0
        }
2282
0
        break;
2283
0
      }
2284
2285
0
      case OpenCLLIB::SMad24:
2286
0
      case OpenCLLIB::UMad24:
2287
0
      case OpenCLLIB::SMul24:
2288
0
      case OpenCLLIB::UMul24: {
2289
0
        if (!_.IsIntScalarOrVectorType(result_type) ||
2290
0
            _.GetBitWidth(result_type) != 32) {
2291
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2292
0
                 << ext_inst_name() << ": "
2293
0
                 << "expected Result Type to be a 32-bit int scalar or vector "
2294
0
                    "type";
2295
0
        }
2296
2297
0
        const uint32_t num_components = _.GetDimension(result_type);
2298
0
        if (num_components > 4 && num_components != 8 && num_components != 16) {
2299
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2300
0
                 << ext_inst_name() << ": "
2301
0
                 << "expected Result Type to be a scalar or a vector with 2, "
2302
0
                    "3, 4, 8 or 16 components";
2303
0
        }
2304
2305
0
        for (uint32_t operand_index = 4; operand_index < num_operands;
2306
0
             ++operand_index) {
2307
0
          const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
2308
0
          if (result_type != operand_type) {
2309
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
2310
0
                   << ext_inst_name() << ": "
2311
0
                   << "expected types of all operands to be equal to Result "
2312
0
                      "Type";
2313
0
          }
2314
0
        }
2315
0
        break;
2316
0
      }
2317
2318
0
      case OpenCLLIB::Cross: {
2319
0
        if (!_.IsFloatVectorType(result_type)) {
2320
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2321
0
                 << ext_inst_name() << ": "
2322
0
                 << "expected Result Type to be a float vector type";
2323
0
        }
2324
2325
0
        const uint32_t num_components = _.GetDimension(result_type);
2326
0
        if (num_components != 3 && num_components != 4) {
2327
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2328
0
                 << ext_inst_name() << ": "
2329
0
                 << "expected Result Type to have 3 or 4 components";
2330
0
        }
2331
2332
0
        const uint32_t x_type = _.GetOperandTypeId(inst, 4);
2333
0
        const uint32_t y_type = _.GetOperandTypeId(inst, 5);
2334
2335
0
        if (x_type != result_type) {
2336
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2337
0
                 << ext_inst_name() << ": "
2338
0
                 << "expected operand X type to be equal to Result Type";
2339
0
        }
2340
2341
0
        if (y_type != result_type) {
2342
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2343
0
                 << ext_inst_name() << ": "
2344
0
                 << "expected operand Y type to be equal to Result Type";
2345
0
        }
2346
0
        break;
2347
0
      }
2348
2349
0
      case OpenCLLIB::Distance:
2350
0
      case OpenCLLIB::Fast_distance: {
2351
0
        if (!_.IsFloatScalarType(result_type)) {
2352
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2353
0
                 << ext_inst_name() << ": "
2354
0
                 << "expected Result Type to be a float scalar type";
2355
0
        }
2356
2357
0
        const uint32_t p0_type = _.GetOperandTypeId(inst, 4);
2358
0
        if (!_.IsFloatScalarOrVectorType(p0_type)) {
2359
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2360
0
                 << ext_inst_name() << ": "
2361
0
                 << "expected operand P0 to be of float scalar or vector type";
2362
0
        }
2363
2364
0
        const uint32_t num_components = _.GetDimension(p0_type);
2365
0
        if (num_components > 4) {
2366
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2367
0
                 << ext_inst_name() << ": "
2368
0
                 << "expected operand P0 to have no more than 4 components";
2369
0
        }
2370
2371
0
        if (result_type != _.GetComponentType(p0_type)) {
2372
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2373
0
                 << ext_inst_name() << ": "
2374
0
                 << "expected operand P0 component type to be equal to "
2375
0
                 << "Result Type";
2376
0
        }
2377
2378
0
        const uint32_t p1_type = _.GetOperandTypeId(inst, 5);
2379
0
        if (p0_type != p1_type) {
2380
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2381
0
                 << ext_inst_name() << ": "
2382
0
                 << "expected operands P0 and P1 to be of the same type";
2383
0
        }
2384
0
        break;
2385
0
      }
2386
2387
0
      case OpenCLLIB::Length:
2388
0
      case OpenCLLIB::Fast_length: {
2389
0
        if (!_.IsFloatScalarType(result_type)) {
2390
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2391
0
                 << ext_inst_name() << ": "
2392
0
                 << "expected Result Type to be a float scalar type";
2393
0
        }
2394
2395
0
        const uint32_t p_type = _.GetOperandTypeId(inst, 4);
2396
0
        if (!_.IsFloatScalarOrVectorType(p_type)) {
2397
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2398
0
                 << ext_inst_name() << ": "
2399
0
                 << "expected operand P to be a float scalar or vector";
2400
0
        }
2401
2402
0
        const uint32_t num_components = _.GetDimension(p_type);
2403
0
        if (num_components > 4) {
2404
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2405
0
                 << ext_inst_name() << ": "
2406
0
                 << "expected operand P to have no more than 4 components";
2407
0
        }
2408
2409
0
        if (result_type != _.GetComponentType(p_type)) {
2410
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2411
0
                 << ext_inst_name() << ": "
2412
0
                 << "expected operand P component type to be equal to Result "
2413
0
                    "Type";
2414
0
        }
2415
0
        break;
2416
0
      }
2417
2418
0
      case OpenCLLIB::Normalize:
2419
0
      case OpenCLLIB::Fast_normalize: {
2420
0
        if (!_.IsFloatScalarOrVectorType(result_type)) {
2421
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2422
0
                 << ext_inst_name() << ": "
2423
0
                 << "expected Result Type to be a float scalar or vector type";
2424
0
        }
2425
2426
0
        const uint32_t num_components = _.GetDimension(result_type);
2427
0
        if (num_components > 4) {
2428
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2429
0
                 << ext_inst_name() << ": "
2430
0
                 << "expected Result Type to have no more than 4 components";
2431
0
        }
2432
2433
0
        const uint32_t p_type = _.GetOperandTypeId(inst, 4);
2434
0
        if (p_type != result_type) {
2435
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2436
0
                 << ext_inst_name() << ": "
2437
0
                 << "expected operand P type to be equal to Result Type";
2438
0
        }
2439
0
        break;
2440
0
      }
2441
2442
0
      case OpenCLLIB::Bitselect: {
2443
0
        if (!_.IsFloatScalarOrVectorType(result_type) &&
2444
0
            !_.IsIntScalarOrVectorType(result_type)) {
2445
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2446
0
                 << ext_inst_name() << ": "
2447
0
                 << "expected Result Type to be an int or float scalar or "
2448
0
                    "vector type";
2449
0
        }
2450
2451
0
        const uint32_t num_components = _.GetDimension(result_type);
2452
0
        if (num_components > 4 && num_components != 8 && num_components != 16) {
2453
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2454
0
                 << ext_inst_name() << ": "
2455
0
                 << "expected Result Type to be a scalar or a vector with 2, "
2456
0
                    "3, 4, 8 or 16 components";
2457
0
        }
2458
2459
0
        for (uint32_t operand_index = 4; operand_index < num_operands;
2460
0
             ++operand_index) {
2461
0
          const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
2462
0
          if (result_type != operand_type) {
2463
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
2464
0
                   << ext_inst_name() << ": "
2465
0
                   << "expected types of all operands to be equal to Result "
2466
0
                      "Type";
2467
0
          }
2468
0
        }
2469
0
        break;
2470
0
      }
2471
2472
0
      case OpenCLLIB::Select: {
2473
0
        if (!_.IsFloatScalarOrVectorType(result_type) &&
2474
0
            !_.IsIntScalarOrVectorType(result_type)) {
2475
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2476
0
                 << ext_inst_name() << ": "
2477
0
                 << "expected Result Type to be an int or float scalar or "
2478
0
                    "vector type";
2479
0
        }
2480
2481
0
        const uint32_t num_components = _.GetDimension(result_type);
2482
0
        if (num_components > 4 && num_components != 8 && num_components != 16) {
2483
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2484
0
                 << ext_inst_name() << ": "
2485
0
                 << "expected Result Type to be a scalar or a vector with 2, "
2486
0
                    "3, 4, 8 or 16 components";
2487
0
        }
2488
2489
0
        const uint32_t a_type = _.GetOperandTypeId(inst, 4);
2490
0
        const uint32_t b_type = _.GetOperandTypeId(inst, 5);
2491
0
        const uint32_t c_type = _.GetOperandTypeId(inst, 6);
2492
2493
0
        if (result_type != a_type) {
2494
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2495
0
                 << ext_inst_name() << ": "
2496
0
                 << "expected operand A type to be equal to Result Type";
2497
0
        }
2498
2499
0
        if (result_type != b_type) {
2500
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2501
0
                 << ext_inst_name() << ": "
2502
0
                 << "expected operand B type to be equal to Result Type";
2503
0
        }
2504
2505
0
        if (!_.IsIntScalarOrVectorType(c_type)) {
2506
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2507
0
                 << ext_inst_name() << ": "
2508
0
                 << "expected operand C to be an int scalar or vector";
2509
0
        }
2510
2511
0
        if (num_components != _.GetDimension(c_type)) {
2512
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2513
0
                 << ext_inst_name() << ": "
2514
0
                 << "expected operand C to have the same number of components "
2515
0
                    "as Result Type";
2516
0
        }
2517
2518
0
        if (_.GetBitWidth(result_type) != _.GetBitWidth(c_type)) {
2519
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2520
0
                 << ext_inst_name() << ": "
2521
0
                 << "expected operand C to have the same bit width as Result "
2522
0
                    "Type";
2523
0
        }
2524
0
        break;
2525
0
      }
2526
2527
0
      case OpenCLLIB::Vloadn: {
2528
0
        if (!_.IsFloatVectorType(result_type) &&
2529
0
            !_.IsIntVectorType(result_type)) {
2530
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2531
0
                 << ext_inst_name() << ": "
2532
0
                 << "expected Result Type to be an int or float vector type";
2533
0
        }
2534
2535
0
        const uint32_t num_components = _.GetDimension(result_type);
2536
0
        if (num_components > 4 && num_components != 8 && num_components != 16) {
2537
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2538
0
                 << ext_inst_name() << ": "
2539
0
                 << "expected Result Type to have 2, 3, 4, 8 or 16 components";
2540
0
        }
2541
2542
0
        const uint32_t offset_type = _.GetOperandTypeId(inst, 4);
2543
0
        const uint32_t p_type = _.GetOperandTypeId(inst, 5);
2544
2545
0
        const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
2546
0
        if (!size_t_bit_width) {
2547
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2548
0
                 << ext_inst_name()
2549
0
                 << " can only be used with physical addressing models";
2550
0
        }
2551
2552
0
        if (!_.IsIntScalarType(offset_type) ||
2553
0
            _.GetBitWidth(offset_type) != size_t_bit_width) {
2554
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2555
0
                 << ext_inst_name() << ": "
2556
0
                 << "expected operand Offset to be of type size_t ("
2557
0
                 << size_t_bit_width
2558
0
                 << "-bit integer for the addressing model used in the module)";
2559
0
        }
2560
2561
0
        spv::StorageClass p_storage_class;
2562
0
        uint32_t p_data_type = 0;
2563
0
        if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
2564
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2565
0
                 << ext_inst_name() << ": "
2566
0
                 << "expected operand P to be a pointer";
2567
0
        }
2568
2569
0
        if (p_storage_class != spv::StorageClass::UniformConstant &&
2570
0
            p_storage_class != spv::StorageClass::Generic &&
2571
0
            p_storage_class != spv::StorageClass::CrossWorkgroup &&
2572
0
            p_storage_class != spv::StorageClass::Workgroup &&
2573
0
            p_storage_class != spv::StorageClass::Function) {
2574
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2575
0
                 << ext_inst_name() << ": "
2576
0
                 << "expected operand P storage class to be UniformConstant, "
2577
0
                    "Generic, CrossWorkgroup, Workgroup or Function";
2578
0
        }
2579
2580
0
        if (_.GetComponentType(result_type) != p_data_type) {
2581
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2582
0
                 << ext_inst_name() << ": "
2583
0
                 << "expected operand P data type to be equal to component "
2584
0
                    "type of Result Type";
2585
0
        }
2586
2587
0
        const uint32_t n_value = inst->word(7);
2588
0
        if (num_components != n_value) {
2589
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2590
0
                 << ext_inst_name() << ": "
2591
0
                 << "expected literal N to be equal to the number of "
2592
0
                    "components of Result Type";
2593
0
        }
2594
0
        break;
2595
0
      }
2596
2597
0
      case OpenCLLIB::Vstoren: {
2598
0
        if (_.GetIdOpcode(result_type) != spv::Op::OpTypeVoid) {
2599
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2600
0
                 << ext_inst_name() << ": expected Result Type to be void";
2601
0
        }
2602
2603
0
        const uint32_t data_type = _.GetOperandTypeId(inst, 4);
2604
0
        const uint32_t offset_type = _.GetOperandTypeId(inst, 5);
2605
0
        const uint32_t p_type = _.GetOperandTypeId(inst, 6);
2606
2607
0
        if (!_.IsFloatVectorType(data_type) && !_.IsIntVectorType(data_type)) {
2608
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2609
0
                 << ext_inst_name() << ": "
2610
0
                 << "expected Data to be an int or float vector";
2611
0
        }
2612
2613
0
        const uint32_t num_components = _.GetDimension(data_type);
2614
0
        if (num_components > 4 && num_components != 8 && num_components != 16) {
2615
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2616
0
                 << ext_inst_name() << ": "
2617
0
                 << "expected Data to have 2, 3, 4, 8 or 16 components";
2618
0
        }
2619
2620
0
        const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
2621
0
        if (!size_t_bit_width) {
2622
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2623
0
                 << ext_inst_name()
2624
0
                 << " can only be used with physical addressing models";
2625
0
        }
2626
2627
0
        if (!_.IsIntScalarType(offset_type) ||
2628
0
            _.GetBitWidth(offset_type) != size_t_bit_width) {
2629
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2630
0
                 << ext_inst_name() << ": "
2631
0
                 << "expected operand Offset to be of type size_t ("
2632
0
                 << size_t_bit_width
2633
0
                 << "-bit integer for the addressing model used in the module)";
2634
0
        }
2635
2636
0
        spv::StorageClass p_storage_class;
2637
0
        uint32_t p_data_type = 0;
2638
0
        if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
2639
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2640
0
                 << ext_inst_name() << ": "
2641
0
                 << "expected operand P to be a pointer";
2642
0
        }
2643
2644
0
        if (p_storage_class != spv::StorageClass::Generic &&
2645
0
            p_storage_class != spv::StorageClass::CrossWorkgroup &&
2646
0
            p_storage_class != spv::StorageClass::Workgroup &&
2647
0
            p_storage_class != spv::StorageClass::Function) {
2648
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2649
0
                 << ext_inst_name() << ": "
2650
0
                 << "expected operand P storage class to be Generic, "
2651
0
                    "CrossWorkgroup, Workgroup or Function";
2652
0
        }
2653
2654
0
        if (_.GetComponentType(data_type) != p_data_type) {
2655
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2656
0
                 << ext_inst_name() << ": "
2657
0
                 << "expected operand P data type to be equal to the type of "
2658
0
                    "operand Data components";
2659
0
        }
2660
0
        break;
2661
0
      }
2662
2663
0
      case OpenCLLIB::Vload_half: {
2664
0
        if (!_.IsFloatScalarType(result_type)) {
2665
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2666
0
                 << ext_inst_name() << ": "
2667
0
                 << "expected Result Type to be a float scalar type";
2668
0
        }
2669
2670
0
        const uint32_t offset_type = _.GetOperandTypeId(inst, 4);
2671
0
        const uint32_t p_type = _.GetOperandTypeId(inst, 5);
2672
2673
0
        const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
2674
0
        if (!size_t_bit_width) {
2675
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2676
0
                 << ext_inst_name()
2677
0
                 << " can only be used with physical addressing models";
2678
0
        }
2679
2680
0
        if (!_.IsIntScalarType(offset_type) ||
2681
0
            _.GetBitWidth(offset_type) != size_t_bit_width) {
2682
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2683
0
                 << ext_inst_name() << ": "
2684
0
                 << "expected operand Offset to be of type size_t ("
2685
0
                 << size_t_bit_width
2686
0
                 << "-bit integer for the addressing model used in the module)";
2687
0
        }
2688
2689
0
        spv::StorageClass p_storage_class;
2690
0
        uint32_t p_data_type = 0;
2691
0
        if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
2692
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2693
0
                 << ext_inst_name() << ": "
2694
0
                 << "expected operand P to be a pointer";
2695
0
        }
2696
2697
0
        if (p_storage_class != spv::StorageClass::UniformConstant &&
2698
0
            p_storage_class != spv::StorageClass::Generic &&
2699
0
            p_storage_class != spv::StorageClass::CrossWorkgroup &&
2700
0
            p_storage_class != spv::StorageClass::Workgroup &&
2701
0
            p_storage_class != spv::StorageClass::Function) {
2702
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2703
0
                 << ext_inst_name() << ": "
2704
0
                 << "expected operand P storage class to be UniformConstant, "
2705
0
                    "Generic, CrossWorkgroup, Workgroup or Function";
2706
0
        }
2707
2708
0
        if (!_.IsFloatScalarType(p_data_type) ||
2709
0
            _.GetBitWidth(p_data_type) != 16) {
2710
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2711
0
                 << ext_inst_name() << ": "
2712
0
                 << "expected operand P data type to be 16-bit float scalar";
2713
0
        }
2714
0
        break;
2715
0
      }
2716
2717
0
      case OpenCLLIB::Vload_halfn:
2718
0
      case OpenCLLIB::Vloada_halfn: {
2719
0
        if (!_.IsFloatVectorType(result_type)) {
2720
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2721
0
                 << ext_inst_name() << ": "
2722
0
                 << "expected Result Type to be a float vector type";
2723
0
        }
2724
2725
0
        const uint32_t num_components = _.GetDimension(result_type);
2726
0
        if (num_components > 4 && num_components != 8 && num_components != 16) {
2727
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2728
0
                 << ext_inst_name() << ": "
2729
0
                 << "expected Result Type to have 2, 3, 4, 8 or 16 components";
2730
0
        }
2731
2732
0
        const uint32_t offset_type = _.GetOperandTypeId(inst, 4);
2733
0
        const uint32_t p_type = _.GetOperandTypeId(inst, 5);
2734
2735
0
        const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
2736
0
        if (!size_t_bit_width) {
2737
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2738
0
                 << ext_inst_name()
2739
0
                 << " can only be used with physical addressing models";
2740
0
        }
2741
2742
0
        if (!_.IsIntScalarType(offset_type) ||
2743
0
            _.GetBitWidth(offset_type) != size_t_bit_width) {
2744
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2745
0
                 << ext_inst_name() << ": "
2746
0
                 << "expected operand Offset to be of type size_t ("
2747
0
                 << size_t_bit_width
2748
0
                 << "-bit integer for the addressing model used in the module)";
2749
0
        }
2750
2751
0
        spv::StorageClass p_storage_class;
2752
0
        uint32_t p_data_type = 0;
2753
0
        if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
2754
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2755
0
                 << ext_inst_name() << ": "
2756
0
                 << "expected operand P to be a pointer";
2757
0
        }
2758
2759
0
        if (p_storage_class != spv::StorageClass::UniformConstant &&
2760
0
            p_storage_class != spv::StorageClass::Generic &&
2761
0
            p_storage_class != spv::StorageClass::CrossWorkgroup &&
2762
0
            p_storage_class != spv::StorageClass::Workgroup &&
2763
0
            p_storage_class != spv::StorageClass::Function) {
2764
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2765
0
                 << ext_inst_name() << ": "
2766
0
                 << "expected operand P storage class to be UniformConstant, "
2767
0
                    "Generic, CrossWorkgroup, Workgroup or Function";
2768
0
        }
2769
2770
0
        if (!_.IsFloatScalarType(p_data_type) ||
2771
0
            _.GetBitWidth(p_data_type) != 16) {
2772
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2773
0
                 << ext_inst_name() << ": "
2774
0
                 << "expected operand P data type to be 16-bit float scalar";
2775
0
        }
2776
2777
0
        const uint32_t n_value = inst->word(7);
2778
0
        if (num_components != n_value) {
2779
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2780
0
                 << ext_inst_name() << ": "
2781
0
                 << "expected literal N to be equal to the number of "
2782
0
                    "components of Result Type";
2783
0
        }
2784
0
        break;
2785
0
      }
2786
2787
0
      case OpenCLLIB::Vstore_half:
2788
0
      case OpenCLLIB::Vstore_half_r:
2789
0
      case OpenCLLIB::Vstore_halfn:
2790
0
      case OpenCLLIB::Vstore_halfn_r:
2791
0
      case OpenCLLIB::Vstorea_halfn:
2792
0
      case OpenCLLIB::Vstorea_halfn_r: {
2793
0
        if (_.GetIdOpcode(result_type) != spv::Op::OpTypeVoid) {
2794
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2795
0
                 << ext_inst_name() << ": expected Result Type to be void";
2796
0
        }
2797
2798
0
        const uint32_t data_type = _.GetOperandTypeId(inst, 4);
2799
0
        const uint32_t offset_type = _.GetOperandTypeId(inst, 5);
2800
0
        const uint32_t p_type = _.GetOperandTypeId(inst, 6);
2801
0
        const uint32_t data_type_bit_width = _.GetBitWidth(data_type);
2802
2803
0
        if (ext_inst_key == OpenCLLIB::Vstore_half ||
2804
0
            ext_inst_key == OpenCLLIB::Vstore_half_r) {
2805
0
          if (!_.IsFloatScalarType(data_type) ||
2806
0
              (data_type_bit_width != 32 && data_type_bit_width != 64)) {
2807
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
2808
0
                   << ext_inst_name() << ": "
2809
0
                   << "expected Data to be a 32 or 64-bit float scalar";
2810
0
          }
2811
0
        } else {
2812
0
          if (!_.IsFloatVectorType(data_type) ||
2813
0
              (data_type_bit_width != 32 && data_type_bit_width != 64)) {
2814
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
2815
0
                   << ext_inst_name() << ": "
2816
0
                   << "expected Data to be a 32 or 64-bit float vector";
2817
0
          }
2818
2819
0
          const uint32_t num_components = _.GetDimension(data_type);
2820
0
          if (num_components > 4 && num_components != 8 &&
2821
0
              num_components != 16) {
2822
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
2823
0
                   << ext_inst_name() << ": "
2824
0
                   << "expected Data to have 2, 3, 4, 8 or 16 components";
2825
0
          }
2826
0
        }
2827
2828
0
        const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
2829
0
        if (!size_t_bit_width) {
2830
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2831
0
                 << ext_inst_name()
2832
0
                 << " can only be used with physical addressing models";
2833
0
        }
2834
2835
0
        if (!_.IsIntScalarType(offset_type) ||
2836
0
            _.GetBitWidth(offset_type) != size_t_bit_width) {
2837
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2838
0
                 << ext_inst_name() << ": "
2839
0
                 << "expected operand Offset to be of type size_t ("
2840
0
                 << size_t_bit_width
2841
0
                 << "-bit integer for the addressing model used in the module)";
2842
0
        }
2843
2844
0
        spv::StorageClass p_storage_class;
2845
0
        uint32_t p_data_type = 0;
2846
0
        if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
2847
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2848
0
                 << ext_inst_name() << ": "
2849
0
                 << "expected operand P to be a pointer";
2850
0
        }
2851
2852
0
        if (p_storage_class != spv::StorageClass::Generic &&
2853
0
            p_storage_class != spv::StorageClass::CrossWorkgroup &&
2854
0
            p_storage_class != spv::StorageClass::Workgroup &&
2855
0
            p_storage_class != spv::StorageClass::Function) {
2856
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2857
0
                 << ext_inst_name() << ": "
2858
0
                 << "expected operand P storage class to be Generic, "
2859
0
                    "CrossWorkgroup, Workgroup or Function";
2860
0
        }
2861
2862
0
        if (!_.IsFloatScalarType(p_data_type) ||
2863
0
            _.GetBitWidth(p_data_type) != 16) {
2864
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2865
0
                 << ext_inst_name() << ": "
2866
0
                 << "expected operand P data type to be 16-bit float scalar";
2867
0
        }
2868
2869
        // Rounding mode enum is checked by assembler.
2870
0
        break;
2871
0
      }
2872
2873
0
      case OpenCLLIB::Shuffle:
2874
0
      case OpenCLLIB::Shuffle2: {
2875
0
        if (!_.IsFloatVectorType(result_type) &&
2876
0
            !_.IsIntVectorType(result_type)) {
2877
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2878
0
                 << ext_inst_name() << ": "
2879
0
                 << "expected Result Type to be an int or float vector type";
2880
0
        }
2881
2882
0
        const uint32_t result_num_components = _.GetDimension(result_type);
2883
0
        if (result_num_components != 2 && result_num_components != 4 &&
2884
0
            result_num_components != 8 && result_num_components != 16) {
2885
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2886
0
                 << ext_inst_name() << ": "
2887
0
                 << "expected Result Type to have 2, 4, 8 or 16 components";
2888
0
        }
2889
2890
0
        uint32_t operand_index = 4;
2891
0
        const uint32_t x_type = _.GetOperandTypeId(inst, operand_index++);
2892
2893
0
        if (ext_inst_key == OpenCLLIB::Shuffle2) {
2894
0
          const uint32_t y_type = _.GetOperandTypeId(inst, operand_index++);
2895
0
          if (x_type != y_type) {
2896
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
2897
0
                   << ext_inst_name() << ": "
2898
0
                   << "expected operands X and Y to be of the same type";
2899
0
          }
2900
0
        }
2901
2902
0
        const uint32_t shuffle_mask_type =
2903
0
            _.GetOperandTypeId(inst, operand_index++);
2904
2905
0
        if (!_.IsFloatVectorType(x_type) && !_.IsIntVectorType(x_type)) {
2906
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2907
0
                 << ext_inst_name() << ": "
2908
0
                 << "expected operand X to be an int or float vector";
2909
0
        }
2910
2911
0
        const uint32_t x_num_components = _.GetDimension(x_type);
2912
0
        if (x_num_components != 2 && x_num_components != 4 &&
2913
0
            x_num_components != 8 && x_num_components != 16) {
2914
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2915
0
                 << ext_inst_name() << ": "
2916
0
                 << "expected operand X to have 2, 4, 8 or 16 components";
2917
0
        }
2918
2919
0
        const uint32_t result_component_type = _.GetComponentType(result_type);
2920
2921
0
        if (result_component_type != _.GetComponentType(x_type)) {
2922
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2923
0
                 << ext_inst_name() << ": "
2924
0
                 << "expected operand X and Result Type to have equal "
2925
0
                    "component types";
2926
0
        }
2927
2928
0
        if (!_.IsIntVectorType(shuffle_mask_type)) {
2929
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2930
0
                 << ext_inst_name() << ": "
2931
0
                 << "expected operand Shuffle Mask to be an int vector";
2932
0
        }
2933
2934
0
        if (result_num_components != _.GetDimension(shuffle_mask_type)) {
2935
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2936
0
                 << ext_inst_name() << ": "
2937
0
                 << "expected operand Shuffle Mask to have the same number of "
2938
0
                    "components as Result Type";
2939
0
        }
2940
2941
0
        if (_.GetBitWidth(result_component_type) !=
2942
0
            _.GetBitWidth(shuffle_mask_type)) {
2943
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2944
0
                 << ext_inst_name() << ": "
2945
0
                 << "expected operand Shuffle Mask components to have the same "
2946
0
                    "bit width as Result Type components";
2947
0
        }
2948
0
        break;
2949
0
      }
2950
2951
0
      case OpenCLLIB::Printf: {
2952
0
        if (!_.IsIntScalarType(result_type) ||
2953
0
            _.GetBitWidth(result_type) != 32) {
2954
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2955
0
                 << ext_inst_name() << ": "
2956
0
                 << "expected Result Type to be a 32-bit int type";
2957
0
        }
2958
2959
0
        const uint32_t format_type = _.GetOperandTypeId(inst, 4);
2960
0
        spv::StorageClass format_storage_class;
2961
0
        uint32_t format_data_type = 0;
2962
0
        if (!_.GetPointerTypeInfo(format_type, &format_data_type,
2963
0
                                  &format_storage_class)) {
2964
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2965
0
                 << ext_inst_name() << ": "
2966
0
                 << "expected operand Format to be a pointer";
2967
0
        }
2968
2969
0
        if (format_storage_class != spv::StorageClass::UniformConstant) {
2970
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2971
0
                 << ext_inst_name() << ": "
2972
0
                 << "expected Format storage class to be UniformConstant";
2973
0
        }
2974
2975
0
        if (!_.IsIntScalarType(format_data_type) ||
2976
0
            _.GetBitWidth(format_data_type) != 8) {
2977
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2978
0
                 << ext_inst_name() << ": "
2979
0
                 << "expected Format data type to be 8-bit int";
2980
0
        }
2981
0
        break;
2982
0
      }
2983
2984
0
      case OpenCLLIB::Prefetch: {
2985
0
        if (_.GetIdOpcode(result_type) != spv::Op::OpTypeVoid) {
2986
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2987
0
                 << ext_inst_name() << ": expected Result Type to be void";
2988
0
        }
2989
2990
0
        const uint32_t p_type = _.GetOperandTypeId(inst, 4);
2991
0
        const uint32_t num_elements_type = _.GetOperandTypeId(inst, 5);
2992
2993
0
        spv::StorageClass p_storage_class;
2994
0
        uint32_t p_data_type = 0;
2995
0
        if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
2996
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
2997
0
                 << ext_inst_name() << ": "
2998
0
                 << "expected operand Ptr to be a pointer";
2999
0
        }
3000
3001
0
        if (p_storage_class != spv::StorageClass::CrossWorkgroup) {
3002
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
3003
0
                 << ext_inst_name() << ": "
3004
0
                 << "expected operand Ptr storage class to be CrossWorkgroup";
3005
0
        }
3006
3007
0
        if (!_.IsFloatScalarOrVectorType(p_data_type) &&
3008
0
            !_.IsIntScalarOrVectorType(p_data_type)) {
3009
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
3010
0
                 << ext_inst_name() << ": "
3011
0
                 << "expected Ptr data type to be int or float scalar or "
3012
0
                    "vector";
3013
0
        }
3014
3015
0
        const uint32_t num_components = _.GetDimension(p_data_type);
3016
0
        if (num_components > 4 && num_components != 8 && num_components != 16) {
3017
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
3018
0
                 << ext_inst_name() << ": "
3019
0
                 << "expected Result Type to be a scalar or a vector with 2, "
3020
0
                    "3, 4, 8 or 16 components";
3021
0
        }
3022
3023
0
        const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
3024
0
        if (!size_t_bit_width) {
3025
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
3026
0
                 << ext_inst_name()
3027
0
                 << " can only be used with physical addressing models";
3028
0
        }
3029
3030
0
        if (!_.IsIntScalarType(num_elements_type) ||
3031
0
            _.GetBitWidth(num_elements_type) != size_t_bit_width) {
3032
0
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
3033
0
                 << ext_inst_name() << ": "
3034
0
                 << "expected operand Num Elements to be of type size_t ("
3035
0
                 << size_t_bit_width
3036
0
                 << "-bit integer for the addressing model used in the module)";
3037
0
        }
3038
0
        break;
3039
0
      }
3040
0
    }
3041
0
  } else if (ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 ||
3042
0
             ext_inst_type ==
3043
0
                 SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) {
3044
0
    if (!_.IsVoidType(result_type)) {
3045
0
      return _.diag(SPV_ERROR_INVALID_DATA, inst)
3046
0
             << ext_inst_name() << ": "
3047
0
             << "expected result type must be a result id of "
3048
0
             << "OpTypeVoid";
3049
0
    }
3050
3051
0
    const bool vulkanDebugInfo =
3052
0
        ext_inst_type == SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100;
3053
3054
0
    auto num_words = inst->words().size();
3055
3056
    // Handle any non-common NonSemanticShaderDebugInfo instructions.
3057
0
    if (vulkanDebugInfo) {
3058
0
      const NonSemanticShaderDebugInfo100Instructions ext_inst_key =
3059
0
          NonSemanticShaderDebugInfo100Instructions(ext_inst_index);
3060
0
      switch (ext_inst_key) {
3061
        // The following block of instructions will be handled by the common
3062
        // validation.
3063
0
        case NonSemanticShaderDebugInfo100DebugInfoNone:
3064
0
        case NonSemanticShaderDebugInfo100DebugCompilationUnit:
3065
0
        case NonSemanticShaderDebugInfo100DebugTypeBasic:
3066
0
        case NonSemanticShaderDebugInfo100DebugTypePointer:
3067
0
        case NonSemanticShaderDebugInfo100DebugTypeQualifier:
3068
0
        case NonSemanticShaderDebugInfo100DebugTypeArray:
3069
0
        case NonSemanticShaderDebugInfo100DebugTypeVector:
3070
0
        case NonSemanticShaderDebugInfo100DebugTypedef:
3071
0
        case NonSemanticShaderDebugInfo100DebugTypeFunction:
3072
0
        case NonSemanticShaderDebugInfo100DebugTypeEnum:
3073
0
        case NonSemanticShaderDebugInfo100DebugTypeComposite:
3074
0
        case NonSemanticShaderDebugInfo100DebugTypeMember:
3075
0
        case NonSemanticShaderDebugInfo100DebugTypeInheritance:
3076
0
        case NonSemanticShaderDebugInfo100DebugTypePtrToMember:
3077
0
        case NonSemanticShaderDebugInfo100DebugTypeTemplate:
3078
0
        case NonSemanticShaderDebugInfo100DebugTypeTemplateParameter:
3079
0
        case NonSemanticShaderDebugInfo100DebugTypeTemplateTemplateParameter:
3080
0
        case NonSemanticShaderDebugInfo100DebugTypeTemplateParameterPack:
3081
0
        case NonSemanticShaderDebugInfo100DebugGlobalVariable:
3082
0
        case NonSemanticShaderDebugInfo100DebugFunctionDeclaration:
3083
0
        case NonSemanticShaderDebugInfo100DebugFunction:
3084
0
        case NonSemanticShaderDebugInfo100DebugLexicalBlock:
3085
0
        case NonSemanticShaderDebugInfo100DebugLexicalBlockDiscriminator:
3086
0
        case NonSemanticShaderDebugInfo100DebugScope:
3087
0
        case NonSemanticShaderDebugInfo100DebugNoScope:
3088
0
        case NonSemanticShaderDebugInfo100DebugInlinedAt:
3089
0
        case NonSemanticShaderDebugInfo100DebugLocalVariable:
3090
0
        case NonSemanticShaderDebugInfo100DebugInlinedVariable:
3091
0
        case NonSemanticShaderDebugInfo100DebugDeclare:
3092
0
        case NonSemanticShaderDebugInfo100DebugValue:
3093
0
        case NonSemanticShaderDebugInfo100DebugOperation:
3094
0
        case NonSemanticShaderDebugInfo100DebugExpression:
3095
0
        case NonSemanticShaderDebugInfo100DebugMacroDef:
3096
0
        case NonSemanticShaderDebugInfo100DebugMacroUndef:
3097
0
        case NonSemanticShaderDebugInfo100DebugImportedEntity:
3098
0
        case NonSemanticShaderDebugInfo100DebugSource:
3099
0
          break;
3100
0
        case NonSemanticShaderDebugInfo100DebugTypeMatrix: {
3101
0
          CHECK_DEBUG_OPERAND("Vector Type", CommonDebugInfoDebugTypeVector, 5);
3102
3103
0
          CHECK_CONST_UINT_OPERAND("Vector Count", 6);
3104
3105
0
          uint32_t vector_count = inst->word(6);
3106
0
          uint64_t const_val;
3107
0
          if (!_.GetConstantValUint64(vector_count, &const_val)) {
3108
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
3109
0
                   << ext_inst_name()
3110
0
                   << ": Vector Count must be 32-bit integer OpConstant";
3111
0
          }
3112
3113
0
          vector_count = const_val & 0xffffffff;
3114
0
          if (!vector_count || vector_count > 4) {
3115
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
3116
0
                   << ext_inst_name() << ": Vector Count must be positive "
3117
0
                   << "integer less than or equal to 4";
3118
0
          }
3119
0
          break;
3120
0
        }
3121
        // TODO: Add validation rules for remaining cases as well.
3122
0
        case NonSemanticShaderDebugInfo100DebugFunctionDefinition:
3123
0
        case NonSemanticShaderDebugInfo100DebugSourceContinued:
3124
0
        case NonSemanticShaderDebugInfo100DebugLine:
3125
0
        case NonSemanticShaderDebugInfo100DebugNoLine:
3126
0
        case NonSemanticShaderDebugInfo100DebugBuildIdentifier:
3127
0
        case NonSemanticShaderDebugInfo100DebugStoragePath:
3128
0
        case NonSemanticShaderDebugInfo100DebugEntryPoint:
3129
0
          break;
3130
0
        case NonSemanticShaderDebugInfo100InstructionsMax:
3131
0
          assert(0);
3132
0
          break;
3133
0
      }
3134
0
    }
3135
3136
    // Handle any non-common OpenCL insts, then common
3137
0
    if (ext_inst_type != SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 ||
3138
0
        OpenCLDebugInfo100Instructions(ext_inst_index) !=
3139
0
            OpenCLDebugInfo100DebugModuleINTEL) {
3140
0
      const CommonDebugInfoInstructions ext_inst_key =
3141
0
          CommonDebugInfoInstructions(ext_inst_index);
3142
0
      switch (ext_inst_key) {
3143
0
        case CommonDebugInfoDebugInfoNone:
3144
0
        case CommonDebugInfoDebugNoScope:
3145
0
          break;
3146
          // The binary parser validates the opcode for DebugInfoNone,
3147
          // DebugNoScope, DebugOperation. We just check the parameters to
3148
          // DebugOperation are properly constants for vulkan debug info.
3149
0
        case CommonDebugInfoDebugOperation: {
3150
0
          CHECK_CONST_UINT_OPERAND("Operation", 5);
3151
0
          for (uint32_t i = 6; i < num_words; ++i) {
3152
0
            CHECK_CONST_UINT_OPERAND("Operand", i);
3153
0
          }
3154
0
          break;
3155
0
        }
3156
0
        case CommonDebugInfoDebugCompilationUnit: {
3157
0
          CHECK_CONST_UINT_OPERAND("Version", 5);
3158
0
          CHECK_CONST_UINT_OPERAND("DWARF Version", 6);
3159
0
          CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3160
0
          CHECK_CONST_UINT_OPERAND("Language", 8);
3161
0
          break;
3162
0
        }
3163
0
        case CommonDebugInfoDebugSource: {
3164
0
          CHECK_OPERAND("File", spv::Op::OpString, 5);
3165
0
          if (num_words == 7) CHECK_OPERAND("Text", spv::Op::OpString, 6);
3166
0
          break;
3167
0
        }
3168
0
        case CommonDebugInfoDebugTypeBasic: {
3169
0
          CHECK_OPERAND("Name", spv::Op::OpString, 5);
3170
0
          CHECK_OPERAND("Size", spv::Op::OpConstant, 6);
3171
0
          CHECK_CONST_UINT_OPERAND("Encoding", 7);
3172
0
          break;
3173
0
        }
3174
0
        case CommonDebugInfoDebugTypePointer: {
3175
0
          auto validate_base_type =
3176
0
              ValidateOperandBaseType(_, inst, 5, ext_inst_name);
3177
0
          if (validate_base_type != SPV_SUCCESS) return validate_base_type;
3178
0
          CHECK_CONST_UINT_OPERAND("Storage Class", 6);
3179
0
          CHECK_CONST_UINT_OPERAND("Flags", 7);
3180
0
          break;
3181
0
        }
3182
0
        case CommonDebugInfoDebugTypeQualifier: {
3183
0
          auto validate_base_type =
3184
0
              ValidateOperandBaseType(_, inst, 5, ext_inst_name);
3185
0
          if (validate_base_type != SPV_SUCCESS) return validate_base_type;
3186
0
          CHECK_CONST_UINT_OPERAND("Type Qualifier", 6);
3187
0
          break;
3188
0
        }
3189
0
        case CommonDebugInfoDebugTypeVector: {
3190
0
          auto validate_base_type =
3191
0
              ValidateOperandBaseType(_, inst, 5, ext_inst_name);
3192
0
          if (validate_base_type != SPV_SUCCESS) return validate_base_type;
3193
3194
0
          CHECK_CONST_UINT_OPERAND("Component Count", 6);
3195
0
          uint32_t component_count = inst->word(6);
3196
0
          if (vulkanDebugInfo) {
3197
0
            uint64_t const_val;
3198
0
            if (!_.GetConstantValUint64(component_count, &const_val)) {
3199
0
              return _.diag(SPV_ERROR_INVALID_DATA, inst)
3200
0
                     << ext_inst_name()
3201
0
                     << ": Component Count must be 32-bit integer OpConstant";
3202
0
            }
3203
0
            component_count = const_val & 0xffffffff;
3204
0
          }
3205
3206
0
          if (!component_count || component_count > 4) {
3207
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
3208
0
                   << ext_inst_name() << ": Component Count must be positive "
3209
0
                   << "integer less than or equal to 4";
3210
0
          }
3211
0
          break;
3212
0
        }
3213
0
        case CommonDebugInfoDebugTypeArray: {
3214
0
          auto validate_base_type = ValidateOperandDebugType(
3215
0
              _, "Base Type", inst, 5, ext_inst_name, false);
3216
0
          if (validate_base_type != SPV_SUCCESS) return validate_base_type;
3217
0
          for (uint32_t i = 6; i < num_words; ++i) {
3218
0
            bool invalid = false;
3219
0
            auto* component_count = _.FindDef(inst->word(i));
3220
0
            if (IsConstIntScalarTypeWith32Or64Bits(_, component_count)) {
3221
              // TODO: We need a spec discussion for the runtime array for
3222
              // OpenCL.
3223
0
              if (!vulkanDebugInfo && !component_count->word(3)) {
3224
0
                invalid = true;
3225
0
              }
3226
0
            } else if (component_count->words().size() > 6 &&
3227
0
                       (CommonDebugInfoInstructions(component_count->word(4)) ==
3228
0
                            CommonDebugInfoDebugLocalVariable ||
3229
0
                        CommonDebugInfoInstructions(component_count->word(4)) ==
3230
0
                            CommonDebugInfoDebugGlobalVariable)) {
3231
0
              auto* component_count_type = _.FindDef(component_count->word(6));
3232
0
              if (component_count_type->words().size() > 7) {
3233
0
                uint32_t encoding = component_count_type->word(7);
3234
0
                if (CommonDebugInfoInstructions(component_count_type->word(
3235
0
                        4)) != CommonDebugInfoDebugTypeBasic ||
3236
0
                    (vulkanDebugInfo && !IsUint32Constant(_, encoding)) ||
3237
0
                    OpenCLDebugInfo100DebugBaseTypeAttributeEncoding(
3238
0
                        vulkanDebugInfo
3239
0
                            ? GetUint32Constant(_, encoding)
3240
0
                            : encoding) != OpenCLDebugInfo100Unsigned) {
3241
0
                  invalid = true;
3242
0
                } else {
3243
                  // DebugTypeBasic for DebugLocalVariable/DebugGlobalVariable
3244
                  // must have Unsigned encoding and 32 or 64 as its size in
3245
                  // bits.
3246
0
                  Instruction* size_in_bits =
3247
0
                      _.FindDef(component_count_type->word(6));
3248
0
                  if (!_.IsIntScalarType(size_in_bits->type_id()) ||
3249
0
                      (size_in_bits->word(3) != 32 &&
3250
0
                       size_in_bits->word(3) != 64)) {
3251
0
                    invalid = true;
3252
0
                  }
3253
0
                }
3254
0
              } else {
3255
0
                invalid = true;
3256
0
              }
3257
0
            } else {
3258
0
              invalid = true;
3259
0
            }
3260
0
            if (invalid) {
3261
0
              return _.diag(SPV_ERROR_INVALID_DATA, inst)
3262
0
                     << ext_inst_name() << ": Component Count must be "
3263
0
                     << "OpConstant with a 32- or 64-bits integer scalar type "
3264
0
                        "or "
3265
0
                     << "DebugGlobalVariable or DebugLocalVariable with a 32- "
3266
0
                        "or "
3267
0
                     << "64-bits unsigned integer scalar type";
3268
0
            }
3269
0
          }
3270
0
          break;
3271
0
        }
3272
0
        case CommonDebugInfoDebugTypedef: {
3273
0
          CHECK_OPERAND("Name", spv::Op::OpString, 5);
3274
0
          auto validate_base_type =
3275
0
              ValidateOperandBaseType(_, inst, 6, ext_inst_name);
3276
0
          if (validate_base_type != SPV_SUCCESS) return validate_base_type;
3277
0
          CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3278
0
          CHECK_CONST_UINT_OPERAND("Line", 8);
3279
0
          CHECK_CONST_UINT_OPERAND("Column", 9);
3280
0
          auto validate_parent =
3281
0
              ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
3282
0
          if (validate_parent != SPV_SUCCESS) return validate_parent;
3283
0
          break;
3284
0
        }
3285
0
        case CommonDebugInfoDebugTypeFunction: {
3286
0
          CHECK_CONST_UINT_OPERAND("Flags", 5);
3287
0
          auto* return_type = _.FindDef(inst->word(6));
3288
          // TODO: We need a spec discussion that we have to allow return and
3289
          // parameter types of a DebugTypeFunction to have template parameter.
3290
0
          if (return_type->opcode() != spv::Op::OpTypeVoid) {
3291
0
            auto validate_return = ValidateOperandDebugType(
3292
0
                _, "Return Type", inst, 6, ext_inst_name, true);
3293
0
            if (validate_return != SPV_SUCCESS) return validate_return;
3294
0
          }
3295
0
          for (uint32_t word_index = 7; word_index < num_words; ++word_index) {
3296
0
            auto validate_param = ValidateOperandDebugType(
3297
0
                _, "Parameter Types", inst, word_index, ext_inst_name, true);
3298
0
            if (validate_param != SPV_SUCCESS) return validate_param;
3299
0
          }
3300
0
          break;
3301
0
        }
3302
0
        case CommonDebugInfoDebugTypeEnum: {
3303
0
          CHECK_OPERAND("Name", spv::Op::OpString, 5);
3304
0
          if (!DoesDebugInfoOperandMatchExpectation(
3305
0
                  _,
3306
0
                  [](CommonDebugInfoInstructions dbg_inst) {
3307
0
                    return dbg_inst == CommonDebugInfoDebugInfoNone;
3308
0
                  },
3309
0
                  inst, 6)) {
3310
0
            auto validate_underlying_type = ValidateOperandDebugType(
3311
0
                _, "Underlying Types", inst, 6, ext_inst_name, false);
3312
0
            if (validate_underlying_type != SPV_SUCCESS)
3313
0
              return validate_underlying_type;
3314
0
          }
3315
0
          CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3316
0
          CHECK_CONST_UINT_OPERAND("Line", 8);
3317
0
          CHECK_CONST_UINT_OPERAND("Column", 9);
3318
0
          auto validate_parent =
3319
0
              ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
3320
0
          if (validate_parent != SPV_SUCCESS) return validate_parent;
3321
0
          CHECK_OPERAND("Size", spv::Op::OpConstant, 11);
3322
0
          auto* size = _.FindDef(inst->word(11));
3323
0
          if (!_.IsIntScalarType(size->type_id()) || !size->word(3)) {
3324
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
3325
0
                   << ext_inst_name() << ": expected operand Size is a "
3326
0
                   << "positive integer";
3327
0
          }
3328
0
          CHECK_CONST_UINT_OPERAND("Flags", 12);
3329
0
          for (uint32_t word_index = 13; word_index + 1 < num_words;
3330
0
               word_index += 2) {
3331
0
            CHECK_OPERAND("Value", spv::Op::OpConstant, word_index);
3332
0
            CHECK_OPERAND("Name", spv::Op::OpString, word_index + 1);
3333
0
          }
3334
0
          break;
3335
0
        }
3336
0
        case CommonDebugInfoDebugTypeComposite: {
3337
0
          CHECK_OPERAND("Name", spv::Op::OpString, 5);
3338
0
          CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3339
0
          CHECK_CONST_UINT_OPERAND("Line", 8);
3340
0
          CHECK_CONST_UINT_OPERAND("Column", 9);
3341
0
          auto validate_parent =
3342
0
              ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
3343
0
          if (validate_parent != SPV_SUCCESS) return validate_parent;
3344
0
          CHECK_OPERAND("Linkage Name", spv::Op::OpString, 11);
3345
0
          if (!DoesDebugInfoOperandMatchExpectation(
3346
0
                  _,
3347
0
                  [](CommonDebugInfoInstructions dbg_inst) {
3348
0
                    return dbg_inst == CommonDebugInfoDebugInfoNone;
3349
0
                  },
3350
0
                  inst, 12)) {
3351
0
            CHECK_OPERAND("Size", spv::Op::OpConstant, 12);
3352
0
          }
3353
0
          CHECK_CONST_UINT_OPERAND("Flags", 13);
3354
0
          for (uint32_t word_index = 14; word_index < num_words; ++word_index) {
3355
0
            if (!DoesDebugInfoOperandMatchExpectation(
3356
0
                    _,
3357
0
                    [](CommonDebugInfoInstructions dbg_inst) {
3358
0
                      return dbg_inst == CommonDebugInfoDebugTypeMember ||
3359
0
                             dbg_inst == CommonDebugInfoDebugFunction ||
3360
0
                             dbg_inst == CommonDebugInfoDebugTypeInheritance;
3361
0
                    },
3362
0
                    inst, word_index)) {
3363
0
              return _.diag(SPV_ERROR_INVALID_DATA, inst)
3364
0
                     << ext_inst_name() << ": "
3365
0
                     << "expected operand Members "
3366
0
                     << "must be DebugTypeMember, DebugFunction, or "
3367
0
                        "DebugTypeInheritance";
3368
0
            }
3369
0
          }
3370
0
          break;
3371
0
        }
3372
0
        case CommonDebugInfoDebugTypeMember: {
3373
0
          CHECK_OPERAND("Name", spv::Op::OpString, 5);
3374
          // TODO: We need a spec discussion that we have to allow member types
3375
          // to have template parameter.
3376
0
          auto validate_type =
3377
0
              ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name, true);
3378
0
          if (validate_type != SPV_SUCCESS) return validate_type;
3379
0
          CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3380
0
          CHECK_CONST_UINT_OPERAND("Line", 8);
3381
0
          CHECK_CONST_UINT_OPERAND("Column", 9);
3382
          // NonSemantic.Shader.DebugInfo doesn't have the Parent operand
3383
0
          if (vulkanDebugInfo) {
3384
0
            CHECK_OPERAND("Offset", spv::Op::OpConstant, 10);
3385
0
            CHECK_OPERAND("Size", spv::Op::OpConstant, 11);
3386
0
            CHECK_CONST_UINT_OPERAND("Flags", 12);
3387
0
            if (num_words == 14)
3388
0
              CHECK_OPERAND("Value", spv::Op::OpConstant, 13);
3389
0
          } else {
3390
0
            CHECK_DEBUG_OPERAND("Parent", CommonDebugInfoDebugTypeComposite,
3391
0
                                10);
3392
0
            CHECK_OPERAND("Offset", spv::Op::OpConstant, 11);
3393
0
            CHECK_OPERAND("Size", spv::Op::OpConstant, 12);
3394
0
            CHECK_CONST_UINT_OPERAND("Flags", 13);
3395
0
            if (num_words == 15)
3396
0
              CHECK_OPERAND("Value", spv::Op::OpConstant, 14);
3397
0
          }
3398
0
          break;
3399
0
        }
3400
0
        case CommonDebugInfoDebugTypeInheritance: {
3401
0
          CHECK_DEBUG_OPERAND("Child", CommonDebugInfoDebugTypeComposite, 5);
3402
0
          auto* debug_inst = _.FindDef(inst->word(5));
3403
0
          auto composite_type =
3404
0
              OpenCLDebugInfo100DebugCompositeType(debug_inst->word(6));
3405
0
          if (composite_type != OpenCLDebugInfo100Class &&
3406
0
              composite_type != OpenCLDebugInfo100Structure) {
3407
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
3408
0
                   << ext_inst_name() << ": "
3409
0
                   << "expected operand Child must be class or struct debug "
3410
0
                      "type";
3411
0
          }
3412
0
          CHECK_DEBUG_OPERAND("Parent", CommonDebugInfoDebugTypeComposite, 6);
3413
0
          debug_inst = _.FindDef(inst->word(6));
3414
0
          composite_type =
3415
0
              OpenCLDebugInfo100DebugCompositeType(debug_inst->word(6));
3416
0
          if (composite_type != OpenCLDebugInfo100Class &&
3417
0
              composite_type != OpenCLDebugInfo100Structure) {
3418
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
3419
0
                   << ext_inst_name() << ": "
3420
0
                   << "expected operand Parent must be class or struct debug "
3421
0
                      "type";
3422
0
          }
3423
0
          CHECK_OPERAND("Offset", spv::Op::OpConstant, 7);
3424
0
          CHECK_OPERAND("Size", spv::Op::OpConstant, 8);
3425
0
          CHECK_CONST_UINT_OPERAND("Flags", 9);
3426
0
          break;
3427
0
        }
3428
0
        case CommonDebugInfoDebugFunction: {
3429
0
          CHECK_OPERAND("Name", spv::Op::OpString, 5);
3430
0
          auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6,
3431
0
                                                        ext_inst_name, false);
3432
0
          if (validate_type != SPV_SUCCESS) return validate_type;
3433
0
          CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3434
0
          CHECK_CONST_UINT_OPERAND("Line", 8);
3435
0
          CHECK_CONST_UINT_OPERAND("Column", 9);
3436
0
          auto validate_parent =
3437
0
              ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
3438
0
          if (validate_parent != SPV_SUCCESS) return validate_parent;
3439
0
          CHECK_OPERAND("Linkage Name", spv::Op::OpString, 11);
3440
0
          CHECK_CONST_UINT_OPERAND("Flags", 12);
3441
0
          CHECK_CONST_UINT_OPERAND("Scope Line", 13);
3442
          // NonSemantic.Shader.DebugInfo.100 doesn't include a reference to the
3443
          // OpFunction
3444
0
          if (vulkanDebugInfo) {
3445
0
            if (num_words == 15) {
3446
0
              CHECK_DEBUG_OPERAND("Declaration",
3447
0
                                  CommonDebugInfoDebugFunctionDeclaration, 14);
3448
0
            }
3449
0
          } else {
3450
0
            if (!DoesDebugInfoOperandMatchExpectation(
3451
0
                    _,
3452
0
                    [](CommonDebugInfoInstructions dbg_inst) {
3453
0
                      return dbg_inst == CommonDebugInfoDebugInfoNone;
3454
0
                    },
3455
0
                    inst, 14)) {
3456
0
              CHECK_OPERAND("Function", spv::Op::OpFunction, 14);
3457
0
            }
3458
0
            if (num_words == 16) {
3459
0
              CHECK_DEBUG_OPERAND("Declaration",
3460
0
                                  CommonDebugInfoDebugFunctionDeclaration, 15);
3461
0
            }
3462
0
          }
3463
0
          break;
3464
0
        }
3465
0
        case CommonDebugInfoDebugFunctionDeclaration: {
3466
0
          CHECK_OPERAND("Name", spv::Op::OpString, 5);
3467
0
          auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6,
3468
0
                                                        ext_inst_name, false);
3469
0
          if (validate_type != SPV_SUCCESS) return validate_type;
3470
0
          CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3471
0
          CHECK_CONST_UINT_OPERAND("Line", 8);
3472
0
          CHECK_CONST_UINT_OPERAND("Column", 9);
3473
0
          auto validate_parent =
3474
0
              ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
3475
0
          if (validate_parent != SPV_SUCCESS) return validate_parent;
3476
0
          CHECK_OPERAND("Linkage Name", spv::Op::OpString, 11);
3477
0
          CHECK_CONST_UINT_OPERAND("Flags", 12);
3478
0
          break;
3479
0
        }
3480
0
        case CommonDebugInfoDebugLexicalBlock: {
3481
0
          CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 5);
3482
0
          CHECK_CONST_UINT_OPERAND("Line", 6);
3483
0
          CHECK_CONST_UINT_OPERAND("Column", 7);
3484
0
          auto validate_parent =
3485
0
              ValidateOperandLexicalScope(_, "Parent", inst, 8, ext_inst_name);
3486
0
          if (validate_parent != SPV_SUCCESS) return validate_parent;
3487
0
          if (num_words == 10) CHECK_OPERAND("Name", spv::Op::OpString, 9);
3488
0
          break;
3489
0
        }
3490
0
        case CommonDebugInfoDebugScope: {
3491
0
          auto validate_scope =
3492
0
              ValidateOperandLexicalScope(_, "Scope", inst, 5, ext_inst_name);
3493
0
          if (validate_scope != SPV_SUCCESS) return validate_scope;
3494
0
          if (num_words == 7) {
3495
0
            CHECK_DEBUG_OPERAND("Inlined At", CommonDebugInfoDebugInlinedAt, 6);
3496
0
          }
3497
0
          break;
3498
0
        }
3499
0
        case CommonDebugInfoDebugLocalVariable: {
3500
0
          CHECK_OPERAND("Name", spv::Op::OpString, 5);
3501
          // TODO: We need a spec discussion that we have to allow local
3502
          // variable types to have template parameter.
3503
0
          auto validate_type =
3504
0
              ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name, true);
3505
0
          if (validate_type != SPV_SUCCESS) return validate_type;
3506
0
          CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3507
0
          CHECK_CONST_UINT_OPERAND("Line", 8);
3508
0
          CHECK_CONST_UINT_OPERAND("Column", 9);
3509
0
          auto validate_parent =
3510
0
              ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
3511
0
          if (validate_parent != SPV_SUCCESS) return validate_parent;
3512
0
          CHECK_CONST_UINT_OPERAND("Flags", 11);
3513
0
          if (num_words == 13) {
3514
0
            CHECK_CONST_UINT_OPERAND("ArgNumber", 12);
3515
0
          }
3516
0
          break;
3517
0
        }
3518
0
        case CommonDebugInfoDebugDeclare: {
3519
0
          CHECK_DEBUG_OPERAND("Local Variable",
3520
0
                              CommonDebugInfoDebugLocalVariable, 5);
3521
0
          auto* operand = _.FindDef(inst->word(6));
3522
0
          if (operand->opcode() != spv::Op::OpVariable &&
3523
0
              operand->opcode() != spv::Op::OpFunctionParameter) {
3524
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
3525
0
                   << ext_inst_name() << ": "
3526
0
                   << "expected operand Variable must be a result id of "
3527
0
                      "OpVariable or OpFunctionParameter";
3528
0
          }
3529
3530
0
          CHECK_DEBUG_OPERAND("Expression", CommonDebugInfoDebugExpression, 7);
3531
3532
0
          if (vulkanDebugInfo) {
3533
0
            for (uint32_t word_index = 8; word_index < num_words;
3534
0
                 ++word_index) {
3535
0
              auto index_inst = _.FindDef(inst->word(word_index));
3536
0
              auto type_id = index_inst != nullptr ? index_inst->type_id() : 0;
3537
0
              if (type_id == 0 || !IsIntScalar(_, type_id, false, false))
3538
0
                return _.diag(SPV_ERROR_INVALID_DATA, inst)
3539
0
                       << ext_inst_name() << ": "
3540
0
                       << "expected index must be scalar integer";
3541
0
            }
3542
0
          }
3543
0
          break;
3544
0
        }
3545
0
        case CommonDebugInfoDebugExpression: {
3546
0
          for (uint32_t word_index = 5; word_index < num_words; ++word_index) {
3547
0
            CHECK_DEBUG_OPERAND("Operation", CommonDebugInfoDebugOperation,
3548
0
                                word_index);
3549
0
          }
3550
0
          break;
3551
0
        }
3552
0
        case CommonDebugInfoDebugTypeTemplate: {
3553
0
          if (!DoesDebugInfoOperandMatchExpectation(
3554
0
                  _,
3555
0
                  [](CommonDebugInfoInstructions dbg_inst) {
3556
0
                    return dbg_inst == CommonDebugInfoDebugTypeComposite ||
3557
0
                           dbg_inst == CommonDebugInfoDebugFunction;
3558
0
                  },
3559
0
                  inst, 5)) {
3560
0
            return _.diag(SPV_ERROR_INVALID_DATA, inst)
3561
0
                   << ext_inst_name() << ": "
3562
0
                   << "expected operand Target must be DebugTypeComposite "
3563
0
                   << "or DebugFunction";
3564
0
          }
3565
0
          for (uint32_t word_index = 6; word_index < num_words; ++word_index) {
3566
0
            if (!DoesDebugInfoOperandMatchExpectation(
3567
0
                    _,
3568
0
                    [](CommonDebugInfoInstructions dbg_inst) {
3569
0
                      return dbg_inst ==
3570
0
                                 CommonDebugInfoDebugTypeTemplateParameter ||
3571
0
                             dbg_inst ==
3572
0
                                 CommonDebugInfoDebugTypeTemplateTemplateParameter;
3573
0
                    },
3574
0
                    inst, word_index)) {
3575
0
              return _.diag(SPV_ERROR_INVALID_DATA, inst)
3576
0
                     << ext_inst_name() << ": "
3577
0
                     << "expected operand Parameters must be "
3578
0
                     << "DebugTypeTemplateParameter or "
3579
0
                     << "DebugTypeTemplateTemplateParameter";
3580
0
            }
3581
0
          }
3582
0
          break;
3583
0
        }
3584
0
        case CommonDebugInfoDebugTypeTemplateParameter: {
3585
0
          CHECK_OPERAND("Name", spv::Op::OpString, 5);
3586
0
          auto validate_actual_type = ValidateOperandDebugType(
3587
0
              _, "Actual Type", inst, 6, ext_inst_name, false);
3588
0
          if (validate_actual_type != SPV_SUCCESS) return validate_actual_type;
3589
0
          if (!DoesDebugInfoOperandMatchExpectation(
3590
0
                  _,
3591
0
                  [](CommonDebugInfoInstructions dbg_inst) {
3592
0
                    return dbg_inst == CommonDebugInfoDebugInfoNone;
3593
0
                  },
3594
0
                  inst, 7)) {
3595
0
            CHECK_OPERAND("Value", spv::Op::OpConstant, 7);
3596
0
          }
3597
0
          CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 8);
3598
0
          CHECK_CONST_UINT_OPERAND("Line", 9);
3599
0
          CHECK_CONST_UINT_OPERAND("Column", 10);
3600
0
          break;
3601
0
        }
3602
0
        case CommonDebugInfoDebugGlobalVariable: {
3603
0
          CHECK_OPERAND("Name", spv::Op::OpString, 5);
3604
0
          auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6,
3605
0
                                                        ext_inst_name, false);
3606
0
          if (validate_type != SPV_SUCCESS) return validate_type;
3607
0
          CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3608
0
          CHECK_CONST_UINT_OPERAND("Line", 8);
3609
0
          CHECK_CONST_UINT_OPERAND("Column", 9);
3610
0
          auto validate_scope =
3611
0
              ValidateOperandLexicalScope(_, "Scope", inst, 10, ext_inst_name);
3612
0
          if (validate_scope != SPV_SUCCESS) return validate_scope;
3613
0
          CHECK_OPERAND("Linkage Name", spv::Op::OpString, 11);
3614
0
          if (!DoesDebugInfoOperandMatchExpectation(
3615
0
                  _,
3616
0
                  [](CommonDebugInfoInstructions dbg_inst) {
3617
0
                    return dbg_inst == CommonDebugInfoDebugInfoNone;
3618
0
                  },
3619
0
                  inst, 12)) {
3620
0
            auto* operand = _.FindDef(inst->word(12));
3621
0
            if (operand->opcode() != spv::Op::OpVariable &&
3622
0
                operand->opcode() != spv::Op::OpConstant) {
3623
0
              return _.diag(SPV_ERROR_INVALID_DATA, inst)
3624
0
                     << ext_inst_name() << ": "
3625
0
                     << "expected operand Variable must be a result id of "
3626
0
                        "OpVariable or OpConstant or DebugInfoNone";
3627
0
            }
3628
0
          }
3629
0
          if (num_words == 15) {
3630
0
            CHECK_DEBUG_OPERAND("Static Member Declaration",
3631
0
                                CommonDebugInfoDebugTypeMember, 14);
3632
0
          }
3633
0
          break;
3634
0
        }
3635
0
        case CommonDebugInfoDebugInlinedAt: {
3636
0
          CHECK_CONST_UINT_OPERAND("Line", 5);
3637
0
          auto validate_scope =
3638
0
              ValidateOperandLexicalScope(_, "Scope", inst, 6, ext_inst_name);
3639
0
          if (validate_scope != SPV_SUCCESS) return validate_scope;
3640
0
          if (num_words == 8) {
3641
0
            CHECK_DEBUG_OPERAND("Inlined", CommonDebugInfoDebugInlinedAt, 7);
3642
0
          }
3643
0
          break;
3644
0
        }
3645
0
        case CommonDebugInfoDebugValue: {
3646
0
          CHECK_DEBUG_OPERAND("Local Variable",
3647
0
                              CommonDebugInfoDebugLocalVariable, 5);
3648
0
          CHECK_DEBUG_OPERAND("Expression", CommonDebugInfoDebugExpression, 7);
3649
3650
0
          for (uint32_t word_index = 8; word_index < num_words; ++word_index) {
3651
            // TODO: The following code simply checks if it is a const int
3652
            // scalar or a DebugLocalVariable or DebugGlobalVariable, but we
3653
            // have to check it using the same validation for Indexes of
3654
            // OpAccessChain.
3655
0
            if (!IsConstWithIntScalarType(_, inst, word_index) &&
3656
0
                !IsDebugVariableWithIntScalarType(_, inst, word_index)) {
3657
0
              return _.diag(SPV_ERROR_INVALID_DATA, inst)
3658
0
                     << ext_inst_name() << ": expected operand Indexes is "
3659
0
                     << "OpConstant, DebugGlobalVariable, or "
3660
0
                     << "type is OpConstant with an integer scalar type";
3661
0
            }
3662
0
          }
3663
0
          break;
3664
0
        }
3665
3666
        // TODO: Add validation rules for remaining cases as well.
3667
0
        case CommonDebugInfoDebugTypePtrToMember:
3668
0
        case CommonDebugInfoDebugTypeTemplateTemplateParameter:
3669
0
        case CommonDebugInfoDebugTypeTemplateParameterPack:
3670
0
        case CommonDebugInfoDebugLexicalBlockDiscriminator:
3671
0
        case CommonDebugInfoDebugInlinedVariable:
3672
0
        case CommonDebugInfoDebugMacroDef:
3673
0
        case CommonDebugInfoDebugMacroUndef:
3674
0
        case CommonDebugInfoDebugImportedEntity:
3675
0
          break;
3676
0
        case CommonDebugInfoInstructionsMax:
3677
0
          assert(0);
3678
0
          break;
3679
0
      }
3680
0
    }
3681
0
  } else if (ext_inst_type == SPV_EXT_INST_TYPE_NONSEMANTIC_CLSPVREFLECTION) {
3682
0
    auto import_inst = _.FindDef(inst->GetOperandAs<uint32_t>(2));
3683
0
    const std::string name = import_inst->GetOperandAs<std::string>(1);
3684
0
    const std::string reflection = "NonSemantic.ClspvReflection.";
3685
0
    char* end_ptr;
3686
0
    auto version_string = name.substr(reflection.size());
3687
0
    if (version_string.empty()) {
3688
0
      return _.diag(SPV_ERROR_INVALID_DATA, import_inst)
3689
0
             << "Missing NonSemantic.ClspvReflection import version";
3690
0
    }
3691
0
    uint32_t version = static_cast<uint32_t>(
3692
0
        std::strtoul(version_string.c_str(), &end_ptr, 10));
3693
0
    if (end_ptr && *end_ptr != '\0') {
3694
0
      return _.diag(SPV_ERROR_INVALID_DATA, import_inst)
3695
0
             << "NonSemantic.ClspvReflection import does not encode the "
3696
0
                "version correctly";
3697
0
    }
3698
0
    if (version == 0 || version > NonSemanticClspvReflectionRevision) {
3699
0
      return _.diag(SPV_ERROR_INVALID_DATA, import_inst)
3700
0
             << "Unknown NonSemantic.ClspvReflection import version";
3701
0
    }
3702
3703
0
    return ValidateClspvReflectionInstruction(_, inst, version);
3704
0
  }
3705
3706
27.0k
  return SPV_SUCCESS;
3707
27.2k
}
3708
3709
2.69M
spv_result_t ExtensionPass(ValidationState_t& _, const Instruction* inst) {
3710
2.69M
  const spv::Op opcode = inst->opcode();
3711
2.69M
  if (opcode == spv::Op::OpExtension) return ValidateExtension(_, inst);
3712
2.69M
  if (opcode == spv::Op::OpExtInstImport) return ValidateExtInstImport(_, inst);
3713
2.68M
  if (opcode == spv::Op::OpExtInst) return ValidateExtInst(_, inst);
3714
3715
2.66M
  return SPV_SUCCESS;
3716
2.68M
}
3717
3718
}  // namespace val
3719
}  // namespace spvtools