mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-12-24 16:51:06 +00:00
linker: Add --use-highest-version option (#5376)
Currently spirv-link fails if all input files don't use the same SPIR-V version. Add an option to instead use the highest input version as the output version. Note that if one of the 'old' input files uses an opcode that is deprecated in the 'new' version, the output spirv will be invalid.
This commit is contained in:
parent
bfc94f63a7
commit
6520d83eff
@ -26,11 +26,6 @@ namespace spvtools {
|
||||
|
||||
class LinkerOptions {
|
||||
public:
|
||||
LinkerOptions()
|
||||
: create_library_(false),
|
||||
verify_ids_(false),
|
||||
allow_partial_linkage_(false) {}
|
||||
|
||||
// Returns whether a library or an executable should be produced by the
|
||||
// linking phase.
|
||||
//
|
||||
@ -63,10 +58,16 @@ class LinkerOptions {
|
||||
allow_partial_linkage_ = allow_partial_linkage;
|
||||
}
|
||||
|
||||
bool GetUseHighestVersion() const { return use_highest_version_; }
|
||||
void SetUseHighestVersion(bool use_highest_vers) {
|
||||
use_highest_version_ = use_highest_vers;
|
||||
}
|
||||
|
||||
private:
|
||||
bool create_library_;
|
||||
bool verify_ids_;
|
||||
bool allow_partial_linkage_;
|
||||
bool create_library_{false};
|
||||
bool verify_ids_{false};
|
||||
bool allow_partial_linkage_{false};
|
||||
bool use_highest_version_{false};
|
||||
};
|
||||
|
||||
// Links one or more SPIR-V modules into a new SPIR-V module. That is, combine
|
||||
|
@ -91,7 +91,8 @@ spv_result_t ShiftIdsInModules(const MessageConsumer& consumer,
|
||||
// should be non-null. |max_id_bound| should be strictly greater than 0.
|
||||
spv_result_t GenerateHeader(const MessageConsumer& consumer,
|
||||
const std::vector<opt::Module*>& modules,
|
||||
uint32_t max_id_bound, opt::ModuleHeader* header);
|
||||
uint32_t max_id_bound, opt::ModuleHeader* header,
|
||||
const LinkerOptions& options);
|
||||
|
||||
// Merge all the modules from |in_modules| into a single module owned by
|
||||
// |linked_context|.
|
||||
@ -202,7 +203,8 @@ spv_result_t ShiftIdsInModules(const MessageConsumer& consumer,
|
||||
|
||||
spv_result_t GenerateHeader(const MessageConsumer& consumer,
|
||||
const std::vector<opt::Module*>& modules,
|
||||
uint32_t max_id_bound, opt::ModuleHeader* header) {
|
||||
uint32_t max_id_bound, opt::ModuleHeader* header,
|
||||
const LinkerOptions& options) {
|
||||
spv_position_t position = {};
|
||||
|
||||
if (modules.empty())
|
||||
@ -212,10 +214,12 @@ spv_result_t GenerateHeader(const MessageConsumer& consumer,
|
||||
return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_DATA)
|
||||
<< "|max_id_bound| of GenerateHeader should not be null.";
|
||||
|
||||
const uint32_t linked_version = modules.front()->version();
|
||||
uint32_t linked_version = modules.front()->version();
|
||||
for (std::size_t i = 1; i < modules.size(); ++i) {
|
||||
const uint32_t module_version = modules[i]->version();
|
||||
if (module_version != linked_version)
|
||||
if (options.GetUseHighestVersion()) {
|
||||
linked_version = std::max(linked_version, module_version);
|
||||
} else if (module_version != linked_version) {
|
||||
return DiagnosticStream({0, 0, 1}, consumer, "", SPV_ERROR_INTERNAL)
|
||||
<< "Conflicting SPIR-V versions: "
|
||||
<< SPV_SPIRV_VERSION_MAJOR_PART(linked_version) << "."
|
||||
@ -224,6 +228,7 @@ spv_result_t GenerateHeader(const MessageConsumer& consumer,
|
||||
<< SPV_SPIRV_VERSION_MAJOR_PART(module_version) << "."
|
||||
<< SPV_SPIRV_VERSION_MINOR_PART(module_version)
|
||||
<< " (input module " << (i + 1) << ").";
|
||||
}
|
||||
}
|
||||
|
||||
header->magic_number = spv::MagicNumber;
|
||||
@ -753,7 +758,7 @@ spv_result_t Link(const Context& context, const uint32_t* const* binaries,
|
||||
|
||||
// Phase 2: Generate the header
|
||||
opt::ModuleHeader header;
|
||||
res = GenerateHeader(consumer, modules, max_id_bound, &header);
|
||||
res = GenerateHeader(consumer, modules, max_id_bound, &header, options);
|
||||
if (res != SPV_SUCCESS) return res;
|
||||
IRContext linked_context(c_context->target_env, consumer);
|
||||
linked_context.module()->SetHeader(header);
|
||||
|
@ -73,5 +73,21 @@ TEST_F(BinaryVersion, Mismatch) {
|
||||
"through 1) vs 1.5 (input module 2)."));
|
||||
}
|
||||
|
||||
TEST_F(BinaryVersion, UseHighest) {
|
||||
// clang-format off
|
||||
spvtest::Binaries binaries = {
|
||||
CreateBinary(SPV_SPIRV_VERSION_WORD(1, 3)),
|
||||
CreateBinary(SPV_SPIRV_VERSION_WORD(1, 5)),
|
||||
};
|
||||
// clang-format on
|
||||
LinkerOptions options;
|
||||
options.SetUseHighestVersion(true);
|
||||
spvtest::Binary linked_binary;
|
||||
ASSERT_EQ(SPV_SUCCESS, Link(binaries, &linked_binary, options))
|
||||
<< GetErrorMessage();
|
||||
EXPECT_THAT(GetErrorMessage(), std::string());
|
||||
EXPECT_EQ(SPV_SPIRV_VERSION_WORD(1, 5), linked_binary[1]);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace spvtools
|
||||
|
@ -59,6 +59,13 @@ Options (in lexicographical order):
|
||||
NOTE: The SPIR-V version used by the linked binary module
|
||||
depends only on the version of the inputs, and is not affected
|
||||
by this option.
|
||||
--use-highest-version
|
||||
Upgrade the output SPIR-V version to the highest of the input
|
||||
files, instead of requiring all of them to have the same
|
||||
version.
|
||||
NOTE: If one of the older input files uses an instruction that
|
||||
is deprecated in the highest SPIR-V version, the output will
|
||||
be invalid.
|
||||
--verify-ids
|
||||
Verify that IDs in the resulting modules are truly unique.
|
||||
--version
|
||||
@ -78,6 +85,7 @@ FLAG_LONG_bool( create_library, /* default_value= */ false,
|
||||
FLAG_LONG_bool( allow_partial_linkage, /* default_value= */ false, /* required= */ false);
|
||||
FLAG_SHORT_string(o, /* default_value= */ "", /* required= */ false);
|
||||
FLAG_LONG_string( target_env, /* default_value= */ kDefaultEnvironment, /* required= */ false);
|
||||
FLAG_LONG_bool( use_highest_version, /* default_value= */ false, /* required= */ false);
|
||||
// clang-format on
|
||||
|
||||
int main(int, const char* argv[]) {
|
||||
@ -120,6 +128,7 @@ int main(int, const char* argv[]) {
|
||||
options.SetAllowPartialLinkage(flags::allow_partial_linkage.value());
|
||||
options.SetCreateLibrary(flags::create_library.value());
|
||||
options.SetVerifyIds(flags::verify_ids.value());
|
||||
options.SetUseHighestVersion(flags::use_highest_version.value());
|
||||
|
||||
if (inFiles.empty()) {
|
||||
fprintf(stderr, "error: No input file specified\n");
|
||||
|
Loading…
Reference in New Issue
Block a user