linker: Recalculate interface variables (#4784)

* linker: Recalculate interface variables

By resolving extern symbols Entry Points might access variables they
hadn't declared before.

* test/linker: add test to verify linked spir-vs importing functions validate

Without the fix Validate will complain about:

"ERROR: 9: Interface variable id <5> is used by entry point 'bar' id <1>, but is not listed as an interface\n  %5 = OpVariable %_ptr_Input_v3uint Input\n"
This commit is contained in:
Karol Herbst 2022-05-03 15:23:02 +02:00 committed by GitHub
parent 46492aa45a
commit edaf51038b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 2 deletions

View File

@ -34,6 +34,7 @@
#include "source/opt/ir_loader.h"
#include "source/opt/pass_manager.h"
#include "source/opt/remove_duplicates_pass.h"
#include "source/opt/remove_unused_interface_variables_pass.h"
#include "source/opt/type_manager.h"
#include "source/spirv_constant.h"
#include "source/spirv_target_env.h"
@ -807,11 +808,16 @@ spv_result_t Link(const Context& context, const uint32_t* const* binaries,
pass_res = manager.Run(&linked_context);
if (pass_res == opt::Pass::Status::Failure) return SPV_ERROR_INVALID_DATA;
// Phase 11: Warn if SPIR-V limits were exceeded
// Phase 11: Recompute EntryPoint variables
manager.AddPass<opt::RemoveUnusedInterfaceVariablesPass>();
pass_res = manager.Run(&linked_context);
if (pass_res == opt::Pass::Status::Failure) return SPV_ERROR_INVALID_DATA;
// Phase 12: Warn if SPIR-V limits were exceeded
res = VerifyLimits(consumer, linked_context);
if (res != SPV_SUCCESS) return res;
// Phase 12: Output the module
// Phase 13: Output the module
linked_context.module()->ToBinary(linked_binary, true);
return SPV_SUCCESS;

View File

@ -104,5 +104,48 @@ OpFunctionEnd
"GLCompute, was already defined."));
}
TEST_F(EntryPoints, LinkedVariables) {
const std::string body1 = R"(
OpCapability Addresses
OpCapability Linkage
OpCapability Kernel
OpMemoryModel Physical64 OpenCL
OpDecorate %7 LinkageAttributes "foo" Export
%1 = OpTypeInt 32 0
%2 = OpTypeVector %1 3
%3 = OpTypePointer Input %2
%4 = OpVariable %3 Input
%5 = OpTypeVoid
%6 = OpTypeFunction %5
%7 = OpFunction %5 None %6
%8 = OpLabel
%9 = OpLoad %2 %4 Aligned 32
OpReturn
OpFunctionEnd
)";
const std::string body2 = R"(
OpCapability Linkage
OpCapability Kernel
OpMemoryModel Physical64 OpenCL
OpEntryPoint Kernel %4 "bar"
OpDecorate %3 LinkageAttributes "foo" Import
%1 = OpTypeVoid
%2 = OpTypeFunction %1
%3 = OpFunction %1 None %2
OpFunctionEnd
%4 = OpFunction %1 None %2
%5 = OpLabel
%6 = OpFunctionCall %1 %3
OpReturn
OpFunctionEnd
)";
spvtest::Binary linked_binary;
EXPECT_EQ(SPV_SUCCESS, AssembleAndLink({body1, body2}, &linked_binary));
EXPECT_THAT(GetErrorMessage(), std::string());
EXPECT_TRUE(Validate(linked_binary));
EXPECT_THAT(GetErrorMessage(), std::string());
}
} // namespace
} // namespace spvtools

View File

@ -208,6 +208,10 @@ class LinkerTest : public ::testing::Test {
// Returns the accumulated error messages for the test.
std::string GetErrorMessage() const { return error_message_; }
bool Validate(const spvtest::Binary& binary) {
return tools_.Validate(binary);
}
private:
spvtools::Context context_;
spvtools::SpirvTools