Entry point validation. Based on 2.16.1 (Universal Validation Rules) of the SPIRV spec: There is at least one OpEntryPoint instruction, unless the Linkage capability is being used. No function can be targeted by both an OpEntryPoint instruction and an OpFunctionCall instruction. Additionally enforces that entry points for Vulkan should not have recursion.
| 115 | // |
| 116 | // Additionally enforces that entry points for Vulkan should not have recursion. |
| 117 | spv_result_t ValidateEntryPoints(ValidationState_t& _) { |
| 118 | _.ComputeFunctionToEntryPointMapping(); |
| 119 | _.ComputeRecursiveEntryPoints(); |
| 120 | |
| 121 | if (_.entry_points().empty() && !_.HasCapability(spv::Capability::Linkage) && |
| 122 | !_.HasCapability(spv::Capability::GraphARM)) { |
| 123 | return _.diag(SPV_ERROR_INVALID_BINARY, nullptr) |
| 124 | << "No OpEntryPoint instruction was found. This is only allowed if " |
| 125 | "the Linkage or GraphARM capability is being used."; |
| 126 | } |
| 127 | |
| 128 | for (const auto& entry_point : _.entry_points()) { |
| 129 | if (_.IsFunctionCallTarget(entry_point)) { |
| 130 | return _.diag(SPV_ERROR_INVALID_BINARY, _.FindDef(entry_point)) |
| 131 | << "A function (" << entry_point |
| 132 | << ") may not be targeted by both an OpEntryPoint instruction and " |
| 133 | "an OpFunctionCall instruction."; |
| 134 | } |
| 135 | |
| 136 | // For Vulkan, the static function-call graph for an entry point |
| 137 | // must not contain cycles. |
| 138 | if (spvIsVulkanEnv(_.context()->target_env)) { |
| 139 | if (_.recursive_entry_points().find(entry_point) != |
| 140 | _.recursive_entry_points().end()) { |
| 141 | return _.diag(SPV_ERROR_INVALID_BINARY, _.FindDef(entry_point)) |
| 142 | << _.VkErrorID(4634) |
| 143 | << "Entry points may not have a call graph with cycles."; |
| 144 | } |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | if (auto error = ValidateFloatControls2(_)) { |
| 149 | return error; |
| 150 | } |
| 151 | if (auto error = ValidateDuplicateExecutionModes(_)) { |
| 152 | return error; |
| 153 | } |
| 154 | |
| 155 | return SPV_SUCCESS; |
| 156 | } |
| 157 | |
| 158 | spv_result_t ValidateGraphEntryPoints(ValidationState_t& _) { |
| 159 | if (_.graph_entry_points().empty() && |
no test coverage detected