summaryrefslogtreecommitdiff
path: root/source/link/linker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/link/linker.cpp')
-rw-r--r--source/link/linker.cpp105
1 files changed, 40 insertions, 65 deletions
diff --git a/source/link/linker.cpp b/source/link/linker.cpp
index b7a57981..895c4b2f 100644
--- a/source/link/linker.cpp
+++ b/source/link/linker.cpp
@@ -37,8 +37,8 @@
namespace spvtools {
-using ir::Instruction;
using ir::IRContext;
+using ir::Instruction;
using ir::Module;
using ir::Operand;
using opt::PassManager;
@@ -89,12 +89,12 @@ static spv_result_t GenerateHeader(const MessageConsumer& consumer,
uint32_t max_id_bound,
ir::ModuleHeader* header);
-// Merge all the modules from |inModules| into a single module owned by
+// 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*>& inModules,
+ const std::vector<Module*>& in_modules,
const libspirv::AssemblyGrammar& grammar,
IRContext* linked_context);
@@ -143,29 +143,10 @@ static spv_result_t RemoveLinkageSpecificInstructions(
static spv_result_t VerifyIds(const MessageConsumer& consumer,
ir::IRContext* linked_context);
-// Structs for holding the data members for SpvLinker.
-struct Linker::Impl {
- explicit Impl(spv_target_env env) : context(spvContextCreate(env)) {
- // The default consumer in spv_context_t is a null consumer, which provides
- // equivalent functionality (from the user's perspective) as a real consumer
- // does nothing.
- }
- ~Impl() { spvContextDestroy(context); }
-
- spv_context context; // C interface context object.
-};
-
-Linker::Linker(spv_target_env env) : impl_(new Impl(env)) {}
-
-Linker::~Linker() {}
-
-void Linker::SetMessageConsumer(MessageConsumer consumer) {
- libspirv::SetContextMessageConsumer(impl_->context, std::move(consumer));
-}
-
-spv_result_t Linker::Link(const std::vector<std::vector<uint32_t>>& binaries,
- std::vector<uint32_t>& linked_binary,
- const LinkerOptions& options) const {
+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;
@@ -176,24 +157,25 @@ spv_result_t Linker::Link(const std::vector<std::vector<uint32_t>>& binaries,
binary_sizes.push_back(binary.size());
}
- return Link(binary_ptrs.data(), binary_sizes.data(), binaries.size(),
+ return Link(context, binary_ptrs.data(), binary_sizes.data(), binaries.size(),
linked_binary, options);
}
-spv_result_t Linker::Link(const uint32_t* const* binaries,
- const size_t* binary_sizes, size_t num_binaries,
- std::vector<uint32_t>& linked_binary,
- const LinkerOptions& options) const {
+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 MessageConsumer& consumer = impl_->context->consumer;
+ const spv_context& c_context = context.CContext();
+ const MessageConsumer& consumer = c_context->consumer;
- linked_binary.clear();
+ linked_binary->clear();
if (num_binaries == 0u)
return libspirv::DiagnosticStream(position, consumer,
SPV_ERROR_INVALID_BINARY)
<< "No modules were given.";
- std::vector<std::unique_ptr<IRContext>> contexts;
+ 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) {
@@ -205,14 +187,14 @@ spv_result_t Linker::Link(const uint32_t* const* binaries,
<< "Schema is non-zero for module " << i << ".";
}
- std::unique_ptr<IRContext> context = BuildModule(
- impl_->context->target_env, consumer, binaries[i], binary_sizes[i]);
- if (context == nullptr)
+ std::unique_ptr<IRContext> ir_context = BuildModule(
+ c_context->target_env, consumer, binaries[i], binary_sizes[i]);
+ if (ir_context == nullptr)
return libspirv::DiagnosticStream(position, consumer,
SPV_ERROR_INVALID_BINARY)
- << "Failed to build a module out of " << contexts.size() << ".";
- modules.push_back(context->module());
- contexts.push_back(std::move(context));
+ << "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
@@ -225,11 +207,11 @@ spv_result_t Linker::Link(const uint32_t* const* binaries,
ir::ModuleHeader header;
res = GenerateHeader(consumer, modules, max_id_bound, &header);
if (res != SPV_SUCCESS) return res;
- IRContext linked_context(impl_->context->target_env, consumer);
+ IRContext linked_context(c_context->target_env, consumer);
linked_context.module()->SetHeader(header);
// Phase 3: Merge all the binaries into a single one.
- libspirv::AssemblyGrammar grammar(impl_->context);
+ libspirv::AssemblyGrammar grammar(c_context);
res = MergeModules(consumer, modules, grammar, &linked_context);
if (res != SPV_SUCCESS) return res;
@@ -275,7 +257,7 @@ spv_result_t Linker::Link(const uint32_t* const* binaries,
if (pass_res == opt::Pass::Status::Failure) return SPV_ERROR_INVALID_DATA;
// Phase 10: Output the module
- linked_context.module()->ToBinary(&linked_binary, true);
+ linked_context.module()->ToBinary(linked_binary, true);
return SPV_SUCCESS;
}
@@ -582,11 +564,11 @@ static spv_result_t GetImportExportPairs(
if (possible_exports.empty())
return libspirv::DiagnosticStream(position, consumer,
SPV_ERROR_INVALID_BINARY)
- << "No export linkage was found for \"" << import.name << "\".";
+ << "Unresolved external reference to \"" << import.name << "\".";
else if (possible_exports.size() > 1u)
return libspirv::DiagnosticStream(position, consumer,
SPV_ERROR_INVALID_BINARY)
- << "Too many export linkages, " << possible_exports.size()
+ << "Too many external references, " << possible_exports.size()
<< ", were found for \"" << import.name << "\".";
linkings_to_do->emplace_back(import, possible_exports.front());
@@ -610,7 +592,9 @@ static spv_result_t CheckImportExportCompatibility(
context))
return libspirv::DiagnosticStream(position, consumer,
SPV_ERROR_INVALID_BINARY)
- << "Type mismatch between imported variable/function %"
+ << "Type mismatch on symbol \""
+ << linking_entry.imported_symbol.name
+ << "\" between imported variable/function %"
<< linking_entry.imported_symbol.id
<< " and exported variable/function %"
<< linking_entry.exported_symbol.id << ".";
@@ -622,27 +606,17 @@ static spv_result_t CheckImportExportCompatibility(
linking_entry.imported_symbol.id, linking_entry.exported_symbol.id))
return libspirv::DiagnosticStream(position, consumer,
SPV_ERROR_INVALID_BINARY)
- << "Decorations mismatch between imported variable/function %"
+ << "Decorations mismatch on symbol \""
+ << linking_entry.imported_symbol.name
+ << "\" between imported variable/function %"
<< linking_entry.imported_symbol.id
<< " and exported variable/function %"
<< linking_entry.exported_symbol.id << ".";
// TODO(pierremoreau): Decorations on function parameters should probably
// match, except for FuncParamAttr if I understand the
- // spec correctly, which makes the code more
- // complicated.
- // for (uint32_t i = 0u; i <
- // linking_entry.imported_symbol.parameter_ids.size(); ++i)
- // if
- // (!decoration_manager.HaveTheSameDecorations(linking_entry.imported_symbol.parameter_ids[i],
- // linking_entry.exported_symbol.parameter_ids[i]))
- // return libspirv::DiagnosticStream(position,
- // impl_->context->consumer,
- // SPV_ERROR_INVALID_BINARY)
- // << "Decorations mismatch between imported function %" <<
- // linking_entry.imported_symbol.id << "'s"
- // << " and exported function %" <<
- // linking_entry.exported_symbol.id << "'s " << (i + 1u) <<
- // "th parameter.";
+ // spec correctly.
+ // TODO(pierremoreau): Decorations on the function return type should
+ // match, except for FuncParamAttr.
}
return SPV_SUCCESS;
@@ -658,15 +632,16 @@ static spv_result_t RemoveLinkageSpecificInstructions(
return libspirv::DiagnosticStream(position, consumer,
SPV_ERROR_INVALID_DATA)
<< "|decoration_manager| of RemoveLinkageSpecificInstructions "
- "should "
- "not "
- "be empty.";
+ "should not be empty.";
if (linked_context == nullptr)
return libspirv::DiagnosticStream(position, consumer,
SPV_ERROR_INVALID_DATA)
<< "|linked_module| of RemoveLinkageSpecificInstructions should not "
"be empty.";
+ // TODO(pierremoreau): Remove FuncParamAttr decorations of imported
+ // functions' return type.
+
// Remove FuncParamAttr decorations of imported functions' parameters.
// From the SPIR-V specification, Sec. 2.13:
// When resolving imported functions, the Function Control and all Function