summaryrefslogtreecommitdiff
path: root/source/link
diff options
context:
space:
mode:
authordan sinclair <dj2@everburning.com>2018-07-09 14:32:31 -0400
committerGitHub <noreply@github.com>2018-07-09 14:32:31 -0400
commit48326d443e434f55eb50a7cfc9acdc968daad5e3 (patch)
tree08c0754b845fc9a26a767a4e906c2b1511532615 /source/link
parente6b953361dd00181e7317eb0efa31fdf6802f79a (diff)
Move link/ code to anonymous namespace (#1679)
Most of the link code is marked as static. This CL introduces an anonymous namespace and removes the static methods. The last two methods are exposed in the public API and have been left in the spvtools namespace.
Diffstat (limited to 'source/link')
-rw-r--r--source/link/linker.cpp321
1 files changed, 162 insertions, 159 deletions
diff --git a/source/link/linker.cpp b/source/link/linker.cpp
index 16b43a28..de793765 100644
--- a/source/link/linker.cpp
+++ b/source/link/linker.cpp
@@ -36,6 +36,7 @@
#include "spirv_target_env.h"
namespace spvtools {
+namespace {
using opt::IRContext;
using opt::Instruction;
@@ -72,9 +73,9 @@ using LinkageTable = std::vector<LinkageEntry>;
// Both |modules| and |max_id_bound| should not be null, and |modules| should
// not be empty either. Furthermore |modules| should not contain any null
// pointers.
-static spv_result_t ShiftIdsInModules(const MessageConsumer& consumer,
- std::vector<opt::Module*>* modules,
- uint32_t* max_id_bound);
+spv_result_t ShiftIdsInModules(const MessageConsumer& consumer,
+ std::vector<opt::Module*>* modules,
+ uint32_t* max_id_bound);
// Generates the header for the linked module and returns it in |header|.
//
@@ -84,19 +85,18 @@ static spv_result_t ShiftIdsInModules(const MessageConsumer& consumer,
// TODO(pierremoreau): What to do when binaries use different versions of
// SPIR-V? For now, use the max of all versions found in
// the input modules.
-static spv_result_t GenerateHeader(const MessageConsumer& consumer,
- const std::vector<opt::Module*>& modules,
- uint32_t max_id_bound,
- opt::ModuleHeader* header);
+spv_result_t GenerateHeader(const MessageConsumer& consumer,
+ const std::vector<opt::Module*>& modules,
+ uint32_t max_id_bound, opt::ModuleHeader* header);
// Merge all the modules from |in_modules| into a single module owned by
// |linked_context|.
//
// |linked_context| should not be null.
-static spv_result_t MergeModules(const MessageConsumer& consumer,
- const std::vector<Module*>& in_modules,
- const AssemblyGrammar& grammar,
- IRContext* linked_context);
+spv_result_t MergeModules(const MessageConsumer& consumer,
+ const std::vector<Module*>& in_modules,
+ const AssemblyGrammar& grammar,
+ IRContext* linked_context);
// Compute all pairs of import and export and return it in |linkings_to_do|.
//
@@ -107,20 +107,21 @@ static spv_result_t MergeModules(const MessageConsumer& consumer,
// applied to a single ID.)
// TODO(pierremoreau): What should be the proper behaviour with built-in
// symbols?
-static spv_result_t GetImportExportPairs(
- const MessageConsumer& consumer, const opt::IRContext& linked_context,
- const DefUseManager& def_use_manager,
- const DecorationManager& decoration_manager, bool allow_partial_linkage,
- LinkageTable* linkings_to_do);
+spv_result_t GetImportExportPairs(const MessageConsumer& consumer,
+ const opt::IRContext& linked_context,
+ const DefUseManager& def_use_manager,
+ const DecorationManager& decoration_manager,
+ bool allow_partial_linkage,
+ LinkageTable* linkings_to_do);
// Checks that for each pair of import and export, the import and export have
// the same type as well as the same decorations.
//
// TODO(pierremoreau): Decorations on functions parameters are currently not
// checked.
-static spv_result_t CheckImportExportCompatibility(
- const MessageConsumer& consumer, const LinkageTable& linkings_to_do,
- opt::IRContext* context);
+spv_result_t CheckImportExportCompatibility(const MessageConsumer& consumer,
+ const LinkageTable& linkings_to_do,
+ opt::IRContext* context);
// Remove linkage specific instructions, such as prototypes of imported
// functions, declarations of imported variables, import (and export if
@@ -134,136 +135,19 @@ static spv_result_t CheckImportExportCompatibility(
// applied to a single ID.)
// TODO(pierremoreau): Run a pass for removing dead instructions, for example
// OpName for prototypes of imported funcions.
-static spv_result_t RemoveLinkageSpecificInstructions(
+spv_result_t RemoveLinkageSpecificInstructions(
const MessageConsumer& consumer, const LinkerOptions& options,
const LinkageTable& linkings_to_do, DecorationManager* decoration_manager,
opt::IRContext* linked_context);
// Verify that the unique ids of each instruction in |linked_context| (i.e. the
// merged module) are truly unique. Does not check the validity of other ids
-static spv_result_t VerifyIds(const MessageConsumer& consumer,
- opt::IRContext* linked_context);
-
-spv_result_t Link(const Context& context,
- const std::vector<std::vector<uint32_t>>& binaries,
- std::vector<uint32_t>* linked_binary,
- const LinkerOptions& options) {
- std::vector<const uint32_t*> binary_ptrs;
- binary_ptrs.reserve(binaries.size());
- std::vector<size_t> binary_sizes;
- binary_sizes.reserve(binaries.size());
-
- for (const auto& binary : binaries) {
- binary_ptrs.push_back(binary.data());
- binary_sizes.push_back(binary.size());
- }
-
- return Link(context, binary_ptrs.data(), binary_sizes.data(), binaries.size(),
- linked_binary, options);
-}
-
-spv_result_t Link(const Context& context, const uint32_t* const* binaries,
- const size_t* binary_sizes, size_t num_binaries,
- std::vector<uint32_t>* linked_binary,
- const LinkerOptions& options) {
- spv_position_t position = {};
- const spv_context& c_context = context.CContext();
- const MessageConsumer& consumer = c_context->consumer;
-
- linked_binary->clear();
- if (num_binaries == 0u)
- return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
- << "No modules were given.";
-
- std::vector<std::unique_ptr<IRContext>> ir_contexts;
- std::vector<Module*> modules;
- modules.reserve(num_binaries);
- for (size_t i = 0u; i < num_binaries; ++i) {
- const uint32_t schema = binaries[i][4u];
- if (schema != 0u) {
- position.index = 4u;
- return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
- << "Schema is non-zero for module " << i << ".";
- }
-
- std::unique_ptr<IRContext> ir_context = BuildModule(
- c_context->target_env, consumer, binaries[i], binary_sizes[i]);
- if (ir_context == nullptr)
- return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
- << "Failed to build a module out of " << ir_contexts.size() << ".";
- modules.push_back(ir_context->module());
- ir_contexts.push_back(std::move(ir_context));
- }
-
- // Phase 1: Shift the IDs used in each binary so that they occupy a disjoint
- // range from the other binaries, and compute the new ID bound.
- uint32_t max_id_bound = 0u;
- spv_result_t res = ShiftIdsInModules(consumer, &modules, &max_id_bound);
- if (res != SPV_SUCCESS) return res;
-
- // Phase 2: Generate the header
- opt::ModuleHeader header;
- res = GenerateHeader(consumer, modules, max_id_bound, &header);
- if (res != SPV_SUCCESS) return res;
- IRContext linked_context(c_context->target_env, consumer);
- linked_context.module()->SetHeader(header);
-
- // Phase 3: Merge all the binaries into a single one.
- AssemblyGrammar grammar(c_context);
- res = MergeModules(consumer, modules, grammar, &linked_context);
- if (res != SPV_SUCCESS) return res;
-
- if (options.GetVerifyIds()) {
- res = VerifyIds(consumer, &linked_context);
- if (res != SPV_SUCCESS) return res;
- }
-
- // Phase 4: Find the import/export pairs
- LinkageTable linkings_to_do;
- res = GetImportExportPairs(consumer, linked_context,
- *linked_context.get_def_use_mgr(),
- *linked_context.get_decoration_mgr(),
- options.GetAllowPartialLinkage(), &linkings_to_do);
- if (res != SPV_SUCCESS) return res;
-
- // Phase 5: Ensure the import and export have the same types and decorations.
- res =
- CheckImportExportCompatibility(consumer, linkings_to_do, &linked_context);
- if (res != SPV_SUCCESS) return res;
-
- // Phase 6: Remove duplicates
- PassManager manager;
- manager.SetMessageConsumer(consumer);
- manager.AddPass<RemoveDuplicatesPass>();
- opt::Pass::Status pass_res = manager.Run(&linked_context);
- if (pass_res == opt::Pass::Status::Failure) return SPV_ERROR_INVALID_DATA;
-
- // Phase 7: Rematch import variables/functions to export variables/functions
- for (const auto& linking_entry : linkings_to_do)
- linked_context.ReplaceAllUsesWith(linking_entry.imported_symbol.id,
- linking_entry.exported_symbol.id);
-
- // Phase 8: Remove linkage specific instructions, such as import/export
- // attributes, linkage capability, etc. if applicable
- res = RemoveLinkageSpecificInstructions(consumer, options, linkings_to_do,
- linked_context.get_decoration_mgr(),
- &linked_context);
- if (res != SPV_SUCCESS) return res;
-
- // Phase 9: Compact the IDs used in the module
- manager.AddPass<opt::CompactIdsPass>();
- pass_res = manager.Run(&linked_context);
- if (pass_res == opt::Pass::Status::Failure) return SPV_ERROR_INVALID_DATA;
-
- // Phase 10: Output the module
- linked_context.module()->ToBinary(linked_binary, true);
-
- return SPV_SUCCESS;
-}
+spv_result_t VerifyIds(const MessageConsumer& consumer,
+ opt::IRContext* linked_context);
-static spv_result_t ShiftIdsInModules(const MessageConsumer& consumer,
- std::vector<opt::Module*>* modules,
- uint32_t* max_id_bound) {
+spv_result_t ShiftIdsInModules(const MessageConsumer& consumer,
+ std::vector<opt::Module*>* modules,
+ uint32_t* max_id_bound) {
spv_position_t position = {};
if (modules == nullptr)
@@ -303,10 +187,9 @@ static spv_result_t ShiftIdsInModules(const MessageConsumer& consumer,
return SPV_SUCCESS;
}
-static spv_result_t GenerateHeader(const MessageConsumer& consumer,
- const std::vector<opt::Module*>& modules,
- uint32_t max_id_bound,
- opt::ModuleHeader* header) {
+spv_result_t GenerateHeader(const MessageConsumer& consumer,
+ const std::vector<opt::Module*>& modules,
+ uint32_t max_id_bound, opt::ModuleHeader* header) {
spv_position_t position = {};
if (modules.empty())
@@ -329,10 +212,10 @@ static spv_result_t GenerateHeader(const MessageConsumer& consumer,
return SPV_SUCCESS;
}
-static spv_result_t MergeModules(const MessageConsumer& consumer,
- const std::vector<Module*>& input_modules,
- const AssemblyGrammar& grammar,
- IRContext* linked_context) {
+spv_result_t MergeModules(const MessageConsumer& consumer,
+ const std::vector<Module*>& input_modules,
+ const AssemblyGrammar& grammar,
+ IRContext* linked_context) {
spv_position_t position = {};
if (linked_context == nullptr)
@@ -486,11 +369,12 @@ static spv_result_t MergeModules(const MessageConsumer& consumer,
return SPV_SUCCESS;
}
-static spv_result_t GetImportExportPairs(
- const MessageConsumer& consumer, const opt::IRContext& linked_context,
- const DefUseManager& def_use_manager,
- const DecorationManager& decoration_manager, bool allow_partial_linkage,
- LinkageTable* linkings_to_do) {
+spv_result_t GetImportExportPairs(const MessageConsumer& consumer,
+ const opt::IRContext& linked_context,
+ const DefUseManager& def_use_manager,
+ const DecorationManager& decoration_manager,
+ bool allow_partial_linkage,
+ LinkageTable* linkings_to_do) {
spv_position_t position = {};
if (linkings_to_do == nullptr)
@@ -582,9 +466,9 @@ static spv_result_t GetImportExportPairs(
return SPV_SUCCESS;
}
-static spv_result_t CheckImportExportCompatibility(
- const MessageConsumer& consumer, const LinkageTable& linkings_to_do,
- opt::IRContext* context) {
+spv_result_t CheckImportExportCompatibility(const MessageConsumer& consumer,
+ const LinkageTable& linkings_to_do,
+ opt::IRContext* context) {
spv_position_t position = {};
// Ensure th import and export types are the same.
@@ -625,7 +509,7 @@ static spv_result_t CheckImportExportCompatibility(
return SPV_SUCCESS;
}
-static spv_result_t RemoveLinkageSpecificInstructions(
+spv_result_t RemoveLinkageSpecificInstructions(
const MessageConsumer& consumer, const LinkerOptions& options,
const LinkageTable& linkings_to_do, DecorationManager* decoration_manager,
opt::IRContext* linked_context) {
@@ -762,4 +646,123 @@ spv_result_t VerifyIds(const MessageConsumer& consumer,
return SPV_SUCCESS;
}
+} // namespace
+
+spv_result_t Link(const Context& context,
+ const std::vector<std::vector<uint32_t>>& binaries,
+ std::vector<uint32_t>* linked_binary,
+ const LinkerOptions& options) {
+ std::vector<const uint32_t*> binary_ptrs;
+ binary_ptrs.reserve(binaries.size());
+ std::vector<size_t> binary_sizes;
+ binary_sizes.reserve(binaries.size());
+
+ for (const auto& binary : binaries) {
+ binary_ptrs.push_back(binary.data());
+ binary_sizes.push_back(binary.size());
+ }
+
+ return Link(context, binary_ptrs.data(), binary_sizes.data(), binaries.size(),
+ linked_binary, options);
+}
+
+spv_result_t Link(const Context& context, const uint32_t* const* binaries,
+ const size_t* binary_sizes, size_t num_binaries,
+ std::vector<uint32_t>* linked_binary,
+ const LinkerOptions& options) {
+ spv_position_t position = {};
+ const spv_context& c_context = context.CContext();
+ const MessageConsumer& consumer = c_context->consumer;
+
+ linked_binary->clear();
+ if (num_binaries == 0u)
+ return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
+ << "No modules were given.";
+
+ std::vector<std::unique_ptr<IRContext>> ir_contexts;
+ std::vector<Module*> modules;
+ modules.reserve(num_binaries);
+ for (size_t i = 0u; i < num_binaries; ++i) {
+ const uint32_t schema = binaries[i][4u];
+ if (schema != 0u) {
+ position.index = 4u;
+ return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
+ << "Schema is non-zero for module " << i << ".";
+ }
+
+ std::unique_ptr<IRContext> ir_context = BuildModule(
+ c_context->target_env, consumer, binaries[i], binary_sizes[i]);
+ if (ir_context == nullptr)
+ return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
+ << "Failed to build a module out of " << ir_contexts.size() << ".";
+ modules.push_back(ir_context->module());
+ ir_contexts.push_back(std::move(ir_context));
+ }
+
+ // Phase 1: Shift the IDs used in each binary so that they occupy a disjoint
+ // range from the other binaries, and compute the new ID bound.
+ uint32_t max_id_bound = 0u;
+ spv_result_t res = ShiftIdsInModules(consumer, &modules, &max_id_bound);
+ if (res != SPV_SUCCESS) return res;
+
+ // Phase 2: Generate the header
+ opt::ModuleHeader header;
+ res = GenerateHeader(consumer, modules, max_id_bound, &header);
+ if (res != SPV_SUCCESS) return res;
+ IRContext linked_context(c_context->target_env, consumer);
+ linked_context.module()->SetHeader(header);
+
+ // Phase 3: Merge all the binaries into a single one.
+ AssemblyGrammar grammar(c_context);
+ res = MergeModules(consumer, modules, grammar, &linked_context);
+ if (res != SPV_SUCCESS) return res;
+
+ if (options.GetVerifyIds()) {
+ res = VerifyIds(consumer, &linked_context);
+ if (res != SPV_SUCCESS) return res;
+ }
+
+ // Phase 4: Find the import/export pairs
+ LinkageTable linkings_to_do;
+ res = GetImportExportPairs(consumer, linked_context,
+ *linked_context.get_def_use_mgr(),
+ *linked_context.get_decoration_mgr(),
+ options.GetAllowPartialLinkage(), &linkings_to_do);
+ if (res != SPV_SUCCESS) return res;
+
+ // Phase 5: Ensure the import and export have the same types and decorations.
+ res =
+ CheckImportExportCompatibility(consumer, linkings_to_do, &linked_context);
+ if (res != SPV_SUCCESS) return res;
+
+ // Phase 6: Remove duplicates
+ PassManager manager;
+ manager.SetMessageConsumer(consumer);
+ manager.AddPass<RemoveDuplicatesPass>();
+ opt::Pass::Status pass_res = manager.Run(&linked_context);
+ if (pass_res == opt::Pass::Status::Failure) return SPV_ERROR_INVALID_DATA;
+
+ // Phase 7: Rematch import variables/functions to export variables/functions
+ for (const auto& linking_entry : linkings_to_do)
+ linked_context.ReplaceAllUsesWith(linking_entry.imported_symbol.id,
+ linking_entry.exported_symbol.id);
+
+ // Phase 8: Remove linkage specific instructions, such as import/export
+ // attributes, linkage capability, etc. if applicable
+ res = RemoveLinkageSpecificInstructions(consumer, options, linkings_to_do,
+ linked_context.get_decoration_mgr(),
+ &linked_context);
+ if (res != SPV_SUCCESS) return res;
+
+ // Phase 9: Compact the IDs used in the module
+ manager.AddPass<opt::CompactIdsPass>();
+ pass_res = manager.Run(&linked_context);
+ if (pass_res == opt::Pass::Status::Failure) return SPV_ERROR_INVALID_DATA;
+
+ // Phase 10: Output the module
+ linked_context.module()->ToBinary(linked_binary, true);
+
+ return SPV_SUCCESS;
+}
+
} // namespace spvtools