MCPcopy Create free account
hub / github.com/KhronosGroup/SPIRV-Tools / ValidatePhi

Function ValidatePhi

source/val/validate_cfg.cpp:40–138  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

38namespace {
39
40spv_result_t ValidatePhi(ValidationState_t& _, const Instruction* inst) {
41 auto block = inst->block();
42 size_t num_in_ops = inst->words().size() - 3;
43 if (num_in_ops % 2 != 0) {
44 return _.diag(SPV_ERROR_INVALID_ID, inst)
45 << "OpPhi does not have an equal number of incoming values and "
46 "basic blocks.";
47 }
48
49 if (_.IsVoidType(inst->type_id())) {
50 return _.diag(SPV_ERROR_INVALID_DATA, inst)
51 << "OpPhi must not have void result type";
52 }
53 if (_.IsPointerType(inst->type_id()) &&
54 _.addressing_model() == spv::AddressingModel::Logical) {
55 if (!_.features().variable_pointers) {
56 return _.diag(SPV_ERROR_INVALID_DATA, inst)
57 << "Using pointers with OpPhi requires capability "
58 << "VariablePointers or VariablePointersStorageBuffer";
59 }
60 }
61
62 const Instruction* type_inst = _.FindDef(inst->type_id());
63 assert(type_inst);
64 const spv::Op type_opcode = type_inst->opcode();
65
66 if (!_.options()->before_hlsl_legalization &&
67 !_.HasCapability(spv::Capability::BindlessTextureNV)) {
68 if (type_opcode == spv::Op::OpTypeSampledImage ||
69 (_.HasCapability(spv::Capability::Shader) &&
70 (type_opcode == spv::Op::OpTypeImage ||
71 type_opcode == spv::Op::OpTypeSampler))) {
72 return _.diag(SPV_ERROR_INVALID_ID, inst)
73 << "Result type cannot be Op" << spvOpcodeString(type_opcode);
74 }
75 }
76
77 // Create a uniqued vector of predecessor ids for comparison against
78 // incoming values. OpBranchConditional %cond %label %label produces two
79 // predecessors in the CFG.
80 std::vector<uint32_t> pred_ids;
81 std::transform(block->predecessors()->begin(), block->predecessors()->end(),
82 std::back_inserter(pred_ids),
83 [](const BasicBlock* b) { return b->id(); });
84 std::sort(pred_ids.begin(), pred_ids.end());
85 pred_ids.erase(std::unique(pred_ids.begin(), pred_ids.end()), pred_ids.end());
86
87 size_t num_edges = num_in_ops / 2;
88 if (num_edges != pred_ids.size()) {
89 return _.diag(SPV_ERROR_INVALID_ID, inst)
90 << "OpPhi's number of incoming blocks (" << num_edges
91 << ") does not match block's predecessor count ("
92 << block->predecessors()->size() << ").";
93 }
94
95 std::unordered_set<uint32_t> observed_predecessors;
96
97 for (size_t i = 3; i < inst->words().size(); ++i) {

Callers 1

ControlFlowPassFunction · 0.85

Calls 15

spvOpcodeStringFunction · 0.85
diagMethod · 0.80
IsVoidTypeMethod · 0.80
IsPointerTypeMethod · 0.80
addressing_modelMethod · 0.80
FindDefMethod · 0.80
optionsMethod · 0.80
predecessorsMethod · 0.80
wordMethod · 0.80
GetTypeIdMethod · 0.80
getIdNameMethod · 0.80
GetIdOpcodeMethod · 0.80

Tested by

no test coverage detected