Check that if A calls B, B is defined before A for WebGPU (#2169)

Fixes #2067
This commit is contained in:
Ryan Harrison 2018-12-05 11:47:24 -05:00 committed by GitHub
parent 68d1dc66d2
commit 3e645b9d67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 1 deletions

View File

@ -279,7 +279,15 @@ spv_result_t ValidateBinaryUsingContextAndValidationState(
<< "A FunctionCall must happen within a function body.";
}
vstate->AddFunctionCallTarget(inst->GetOperandAs<uint32_t>(2));
const auto called_id = inst->GetOperandAs<uint32_t>(2);
if (spvIsWebGPUEnv(context.target_env) &&
!vstate->IsFunctionCallDefined(called_id)) {
return vstate->diag(SPV_ERROR_INVALID_LAYOUT, &instruction)
<< "For WebGPU, functions need to be defined before being "
"called.";
}
vstate->AddFunctionCallTarget(called_id);
}
if (vstate->in_function_body()) {

View File

@ -280,6 +280,9 @@ class ValidationState_t {
return (function_call_targets_.find(id) != function_call_targets_.end());
}
bool IsFunctionCallDefined(const uint32_t id) {
return (id_to_function_.find(id) != id_to_function_.end());
}
/// Registers the capability and its dependent capabilities
void RegisterCapability(SpvCapability cap);

View File

@ -648,6 +648,57 @@ TEST_F(ValidateLayout, ModuleProcessedInvalidInBasicBlock) {
HasSubstr("ModuleProcessed cannot appear in a function declaration"));
}
TEST_F(ValidateLayout, WebGPUCallerBeforeCalleeBad) {
char str[] = R"(
OpCapability Shader
OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
OpMemoryModel Logical VulkanKHR
OpEntryPoint GLCompute %main "main"
%void = OpTypeVoid
%voidfn = OpTypeFunction %void
%main = OpFunction %void None %voidfn
%1 = OpLabel
%2 = OpFunctionCall %void %callee
OpReturn
OpFunctionEnd
%callee = OpFunction %void None %voidfn
%3 = OpLabel
OpReturn
OpFunctionEnd
)";
CompileSuccessfully(str, SPV_ENV_WEBGPU_0);
ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions(SPV_ENV_WEBGPU_0));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("For WebGPU, functions need to be defined before being "
"called.\n %5 = OpFunctionCall %void %6\n"));
}
TEST_F(ValidateLayout, WebGPUCalleeBeforeCallerGood) {
char str[] = R"(
OpCapability Shader
OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
OpMemoryModel Logical VulkanKHR
OpEntryPoint GLCompute %main "main"
%void = OpTypeVoid
%voidfn = OpTypeFunction %void
%callee = OpFunction %void None %voidfn
%3 = OpLabel
OpReturn
OpFunctionEnd
%main = OpFunction %void None %voidfn
%1 = OpLabel
%2 = OpFunctionCall %void %callee
OpReturn
OpFunctionEnd
)";
CompileSuccessfully(str, SPV_ENV_WEBGPU_0);
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
}
// TODO(umar): Test optional instructions
} // namespace