linker.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  1. // Copyright (c) 2017 Pierre Moreau
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "spirv-tools/linker.hpp"
  15. #include <algorithm>
  16. #include <cstdio>
  17. #include <cstring>
  18. #include <iostream>
  19. #include <memory>
  20. #include <numeric>
  21. #include <string>
  22. #include <unordered_map>
  23. #include <unordered_set>
  24. #include <utility>
  25. #include <vector>
  26. #include "source/assembly_grammar.h"
  27. #include "source/diagnostic.h"
  28. #include "source/opt/build_module.h"
  29. #include "source/opt/compact_ids_pass.h"
  30. #include "source/opt/decoration_manager.h"
  31. #include "source/opt/ir_loader.h"
  32. #include "source/opt/pass_manager.h"
  33. #include "source/opt/remove_duplicates_pass.h"
  34. #include "source/opt/remove_unused_interface_variables_pass.h"
  35. #include "source/opt/type_manager.h"
  36. #include "source/spirv_constant.h"
  37. #include "source/spirv_target_env.h"
  38. #include "source/util/make_unique.h"
  39. #include "source/util/string_utils.h"
  40. #include "spirv-tools/libspirv.hpp"
  41. namespace spvtools {
  42. namespace {
  43. using opt::Instruction;
  44. using opt::IRContext;
  45. using opt::Module;
  46. using opt::PassManager;
  47. using opt::RemoveDuplicatesPass;
  48. using opt::analysis::DecorationManager;
  49. using opt::analysis::DefUseManager;
  50. using opt::analysis::Type;
  51. using opt::analysis::TypeManager;
  52. // Stores various information about an imported or exported symbol.
  53. struct LinkageSymbolInfo {
  54. SpvId id; // ID of the symbol
  55. SpvId type_id; // ID of the type of the symbol
  56. std::string name; // unique name defining the symbol and used for matching
  57. // imports and exports together
  58. std::vector<SpvId> parameter_ids; // ID of the parameters of the symbol, if
  59. // it is a function
  60. };
  61. struct LinkageEntry {
  62. LinkageSymbolInfo imported_symbol;
  63. LinkageSymbolInfo exported_symbol;
  64. LinkageEntry(const LinkageSymbolInfo& import_info,
  65. const LinkageSymbolInfo& export_info)
  66. : imported_symbol(import_info), exported_symbol(export_info) {}
  67. };
  68. using LinkageTable = std::vector<LinkageEntry>;
  69. // Shifts the IDs used in each binary of |modules| so that they occupy a
  70. // disjoint range from the other binaries, and compute the new ID bound which
  71. // is returned in |max_id_bound|.
  72. //
  73. // Both |modules| and |max_id_bound| should not be null, and |modules| should
  74. // not be empty either. Furthermore |modules| should not contain any null
  75. // pointers.
  76. spv_result_t ShiftIdsInModules(const MessageConsumer& consumer,
  77. std::vector<opt::Module*>* modules,
  78. uint32_t* max_id_bound);
  79. // Generates the header for the linked module and returns it in |header|.
  80. //
  81. // |header| should not be null, |modules| should not be empty and pointers
  82. // should be non-null. |max_id_bound| should be strictly greater than 0.
  83. spv_result_t GenerateHeader(const MessageConsumer& consumer,
  84. const std::vector<opt::Module*>& modules,
  85. uint32_t max_id_bound, opt::ModuleHeader* header);
  86. // Merge all the modules from |in_modules| into a single module owned by
  87. // |linked_context|.
  88. //
  89. // |linked_context| should not be null.
  90. spv_result_t MergeModules(const MessageConsumer& consumer,
  91. const std::vector<Module*>& in_modules,
  92. const AssemblyGrammar& grammar,
  93. IRContext* linked_context);
  94. // Compute all pairs of import and export and return it in |linkings_to_do|.
  95. //
  96. // |linkings_to_do should not be null. Built-in symbols will be ignored.
  97. //
  98. // TODO(pierremoreau): Linkage attributes applied by a group decoration are
  99. // currently not handled. (You could have a group being
  100. // applied to a single ID.)
  101. // TODO(pierremoreau): What should be the proper behaviour with built-in
  102. // symbols?
  103. spv_result_t GetImportExportPairs(const MessageConsumer& consumer,
  104. const opt::IRContext& linked_context,
  105. const DefUseManager& def_use_manager,
  106. const DecorationManager& decoration_manager,
  107. bool allow_partial_linkage,
  108. LinkageTable* linkings_to_do);
  109. // Checks that for each pair of import and export, the import and export have
  110. // the same type as well as the same decorations.
  111. //
  112. // TODO(pierremoreau): Decorations on functions parameters are currently not
  113. // checked.
  114. spv_result_t CheckImportExportCompatibility(const MessageConsumer& consumer,
  115. const LinkageTable& linkings_to_do,
  116. opt::IRContext* context);
  117. // Remove linkage specific instructions, such as prototypes of imported
  118. // functions, declarations of imported variables, import (and export if
  119. // necessary) linkage attributes.
  120. //
  121. // |linked_context| and |decoration_manager| should not be null, and the
  122. // 'RemoveDuplicatePass' should be run first.
  123. //
  124. // TODO(pierremoreau): Linkage attributes applied by a group decoration are
  125. // currently not handled. (You could have a group being
  126. // applied to a single ID.)
  127. spv_result_t RemoveLinkageSpecificInstructions(
  128. const MessageConsumer& consumer, const LinkerOptions& options,
  129. const LinkageTable& linkings_to_do, DecorationManager* decoration_manager,
  130. opt::IRContext* linked_context);
  131. // Verify that the unique ids of each instruction in |linked_context| (i.e. the
  132. // merged module) are truly unique. Does not check the validity of other ids
  133. spv_result_t VerifyIds(const MessageConsumer& consumer,
  134. opt::IRContext* linked_context);
  135. // Verify that the universal limits are not crossed, and warn the user
  136. // otherwise.
  137. //
  138. // TODO(pierremoreau):
  139. // - Verify against the limits of the environment (e.g. Vulkan limits if
  140. // consuming vulkan1.x)
  141. spv_result_t VerifyLimits(const MessageConsumer& consumer,
  142. const opt::IRContext& linked_context);
  143. spv_result_t ShiftIdsInModules(const MessageConsumer& consumer,
  144. std::vector<opt::Module*>* modules,
  145. uint32_t* max_id_bound) {
  146. spv_position_t position = {};
  147. if (modules == nullptr)
  148. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_DATA)
  149. << "|modules| of ShiftIdsInModules should not be null.";
  150. if (modules->empty())
  151. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_DATA)
  152. << "|modules| of ShiftIdsInModules should not be empty.";
  153. if (max_id_bound == nullptr)
  154. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_DATA)
  155. << "|max_id_bound| of ShiftIdsInModules should not be null.";
  156. const size_t id_bound =
  157. std::accumulate(modules->begin(), modules->end(), static_cast<size_t>(1),
  158. [](const size_t& accumulation, opt::Module* module) {
  159. return accumulation + module->IdBound() - 1u;
  160. });
  161. if (id_bound > std::numeric_limits<uint32_t>::max())
  162. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_DATA)
  163. << "Too many IDs (" << id_bound
  164. << "): combining all modules would overflow the 32-bit word of the "
  165. "SPIR-V header.";
  166. *max_id_bound = static_cast<uint32_t>(id_bound);
  167. uint32_t id_offset = modules->front()->IdBound() - 1u;
  168. for (auto module_iter = modules->begin() + 1; module_iter != modules->end();
  169. ++module_iter) {
  170. Module* module = *module_iter;
  171. module->ForEachInst([&id_offset](Instruction* insn) {
  172. insn->ForEachId([&id_offset](uint32_t* id) { *id += id_offset; });
  173. });
  174. id_offset += module->IdBound() - 1u;
  175. // Invalidate the DefUseManager
  176. module->context()->InvalidateAnalyses(opt::IRContext::kAnalysisDefUse);
  177. }
  178. return SPV_SUCCESS;
  179. }
  180. spv_result_t GenerateHeader(const MessageConsumer& consumer,
  181. const std::vector<opt::Module*>& modules,
  182. uint32_t max_id_bound, opt::ModuleHeader* header) {
  183. spv_position_t position = {};
  184. if (modules.empty())
  185. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_DATA)
  186. << "|modules| of GenerateHeader should not be empty.";
  187. if (max_id_bound == 0u)
  188. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_DATA)
  189. << "|max_id_bound| of GenerateHeader should not be null.";
  190. const uint32_t linked_version = modules.front()->version();
  191. for (std::size_t i = 1; i < modules.size(); ++i) {
  192. const uint32_t module_version = modules[i]->version();
  193. if (module_version != linked_version)
  194. return DiagnosticStream({0, 0, 1}, consumer, "", SPV_ERROR_INTERNAL)
  195. << "Conflicting SPIR-V versions: "
  196. << SPV_SPIRV_VERSION_MAJOR_PART(linked_version) << "."
  197. << SPV_SPIRV_VERSION_MINOR_PART(linked_version)
  198. << " (input modules 1 through " << i << ") vs "
  199. << SPV_SPIRV_VERSION_MAJOR_PART(module_version) << "."
  200. << SPV_SPIRV_VERSION_MINOR_PART(module_version)
  201. << " (input module " << (i + 1) << ").";
  202. }
  203. header->magic_number = SpvMagicNumber;
  204. header->version = linked_version;
  205. header->generator = SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_LINKER, 0);
  206. header->bound = max_id_bound;
  207. header->schema = 0u;
  208. return SPV_SUCCESS;
  209. }
  210. spv_result_t MergeModules(const MessageConsumer& consumer,
  211. const std::vector<Module*>& input_modules,
  212. const AssemblyGrammar& grammar,
  213. IRContext* linked_context) {
  214. spv_position_t position = {};
  215. if (linked_context == nullptr)
  216. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_DATA)
  217. << "|linked_module| of MergeModules should not be null.";
  218. Module* linked_module = linked_context->module();
  219. if (input_modules.empty()) return SPV_SUCCESS;
  220. for (const auto& module : input_modules)
  221. for (const auto& inst : module->capabilities())
  222. linked_module->AddCapability(
  223. std::unique_ptr<Instruction>(inst.Clone(linked_context)));
  224. for (const auto& module : input_modules)
  225. for (const auto& inst : module->extensions())
  226. linked_module->AddExtension(
  227. std::unique_ptr<Instruction>(inst.Clone(linked_context)));
  228. for (const auto& module : input_modules)
  229. for (const auto& inst : module->ext_inst_imports())
  230. linked_module->AddExtInstImport(
  231. std::unique_ptr<Instruction>(inst.Clone(linked_context)));
  232. const Instruction* linked_memory_model_inst =
  233. input_modules.front()->GetMemoryModel();
  234. if (linked_memory_model_inst == nullptr) {
  235. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
  236. << "Input module 1 is lacking an OpMemoryModel instruction.";
  237. }
  238. const uint32_t linked_addressing_model =
  239. linked_memory_model_inst->GetSingleWordOperand(0u);
  240. const uint32_t linked_memory_model =
  241. linked_memory_model_inst->GetSingleWordOperand(1u);
  242. for (std::size_t i = 1; i < input_modules.size(); ++i) {
  243. const Module* module = input_modules[i];
  244. const Instruction* memory_model_inst = module->GetMemoryModel();
  245. if (memory_model_inst == nullptr)
  246. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
  247. << "Input module " << (i + 1)
  248. << " is lacking an OpMemoryModel instruction.";
  249. const uint32_t module_addressing_model =
  250. memory_model_inst->GetSingleWordOperand(0u);
  251. if (module_addressing_model != linked_addressing_model) {
  252. spv_operand_desc linked_desc = nullptr, module_desc = nullptr;
  253. grammar.lookupOperand(SPV_OPERAND_TYPE_ADDRESSING_MODEL,
  254. linked_addressing_model, &linked_desc);
  255. grammar.lookupOperand(SPV_OPERAND_TYPE_ADDRESSING_MODEL,
  256. module_addressing_model, &module_desc);
  257. return DiagnosticStream(position, consumer, "", SPV_ERROR_INTERNAL)
  258. << "Conflicting addressing models: " << linked_desc->name
  259. << " (input modules 1 through " << i << ") vs "
  260. << module_desc->name << " (input module " << (i + 1) << ").";
  261. }
  262. const uint32_t module_memory_model =
  263. memory_model_inst->GetSingleWordOperand(1u);
  264. if (module_memory_model != linked_memory_model) {
  265. spv_operand_desc linked_desc = nullptr, module_desc = nullptr;
  266. grammar.lookupOperand(SPV_OPERAND_TYPE_MEMORY_MODEL, linked_memory_model,
  267. &linked_desc);
  268. grammar.lookupOperand(SPV_OPERAND_TYPE_MEMORY_MODEL, module_memory_model,
  269. &module_desc);
  270. return DiagnosticStream(position, consumer, "", SPV_ERROR_INTERNAL)
  271. << "Conflicting memory models: " << linked_desc->name
  272. << " (input modules 1 through " << i << ") vs "
  273. << module_desc->name << " (input module " << (i + 1) << ").";
  274. }
  275. }
  276. linked_module->SetMemoryModel(std::unique_ptr<Instruction>(
  277. linked_memory_model_inst->Clone(linked_context)));
  278. std::vector<std::pair<uint32_t, std::string>> entry_points;
  279. for (const auto& module : input_modules)
  280. for (const auto& inst : module->entry_points()) {
  281. const uint32_t model = inst.GetSingleWordInOperand(0);
  282. const std::string name = inst.GetInOperand(2).AsString();
  283. const auto i = std::find_if(
  284. entry_points.begin(), entry_points.end(),
  285. [model, name](const std::pair<uint32_t, std::string>& v) {
  286. return v.first == model && v.second == name;
  287. });
  288. if (i != entry_points.end()) {
  289. spv_operand_desc desc = nullptr;
  290. grammar.lookupOperand(SPV_OPERAND_TYPE_EXECUTION_MODEL, model, &desc);
  291. return DiagnosticStream(position, consumer, "", SPV_ERROR_INTERNAL)
  292. << "The entry point \"" << name << "\", with execution model "
  293. << desc->name << ", was already defined.";
  294. }
  295. linked_module->AddEntryPoint(
  296. std::unique_ptr<Instruction>(inst.Clone(linked_context)));
  297. entry_points.emplace_back(model, name);
  298. }
  299. for (const auto& module : input_modules)
  300. for (const auto& inst : module->execution_modes())
  301. linked_module->AddExecutionMode(
  302. std::unique_ptr<Instruction>(inst.Clone(linked_context)));
  303. for (const auto& module : input_modules)
  304. for (const auto& inst : module->debugs1())
  305. linked_module->AddDebug1Inst(
  306. std::unique_ptr<Instruction>(inst.Clone(linked_context)));
  307. for (const auto& module : input_modules)
  308. for (const auto& inst : module->debugs2())
  309. linked_module->AddDebug2Inst(
  310. std::unique_ptr<Instruction>(inst.Clone(linked_context)));
  311. for (const auto& module : input_modules)
  312. for (const auto& inst : module->debugs3())
  313. linked_module->AddDebug3Inst(
  314. std::unique_ptr<Instruction>(inst.Clone(linked_context)));
  315. for (const auto& module : input_modules)
  316. for (const auto& inst : module->ext_inst_debuginfo())
  317. linked_module->AddExtInstDebugInfo(
  318. std::unique_ptr<Instruction>(inst.Clone(linked_context)));
  319. // If the generated module uses SPIR-V 1.1 or higher, add an
  320. // OpModuleProcessed instruction about the linking step.
  321. if (linked_module->version() >= SPV_SPIRV_VERSION_WORD(1, 1)) {
  322. const std::string processed_string("Linked by SPIR-V Tools Linker");
  323. std::vector<uint32_t> processed_words =
  324. spvtools::utils::MakeVector(processed_string);
  325. linked_module->AddDebug3Inst(std::unique_ptr<Instruction>(
  326. new Instruction(linked_context, SpvOpModuleProcessed, 0u, 0u,
  327. {{SPV_OPERAND_TYPE_LITERAL_STRING, processed_words}})));
  328. }
  329. for (const auto& module : input_modules)
  330. for (const auto& inst : module->annotations())
  331. linked_module->AddAnnotationInst(
  332. std::unique_ptr<Instruction>(inst.Clone(linked_context)));
  333. // TODO(pierremoreau): Since the modules have not been validate, should we
  334. // expect SpvStorageClassFunction variables outside
  335. // functions?
  336. for (const auto& module : input_modules) {
  337. for (const auto& inst : module->types_values()) {
  338. linked_module->AddType(
  339. std::unique_ptr<Instruction>(inst.Clone(linked_context)));
  340. }
  341. }
  342. // Process functions and their basic blocks
  343. for (const auto& module : input_modules) {
  344. for (const auto& func : *module) {
  345. std::unique_ptr<opt::Function> cloned_func(func.Clone(linked_context));
  346. linked_module->AddFunction(std::move(cloned_func));
  347. }
  348. }
  349. return SPV_SUCCESS;
  350. }
  351. spv_result_t GetImportExportPairs(const MessageConsumer& consumer,
  352. const opt::IRContext& linked_context,
  353. const DefUseManager& def_use_manager,
  354. const DecorationManager& decoration_manager,
  355. bool allow_partial_linkage,
  356. LinkageTable* linkings_to_do) {
  357. spv_position_t position = {};
  358. if (linkings_to_do == nullptr)
  359. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_DATA)
  360. << "|linkings_to_do| of GetImportExportPairs should not be empty.";
  361. std::vector<LinkageSymbolInfo> imports;
  362. std::unordered_map<std::string, std::vector<LinkageSymbolInfo>> exports;
  363. // Figure out the imports and exports
  364. for (const auto& decoration : linked_context.annotations()) {
  365. if (decoration.opcode() != SpvOpDecorate ||
  366. decoration.GetSingleWordInOperand(1u) != SpvDecorationLinkageAttributes)
  367. continue;
  368. const SpvId id = decoration.GetSingleWordInOperand(0u);
  369. // Ignore if the targeted symbol is a built-in
  370. bool is_built_in = false;
  371. for (const auto& id_decoration :
  372. decoration_manager.GetDecorationsFor(id, false)) {
  373. if (id_decoration->GetSingleWordInOperand(1u) == SpvDecorationBuiltIn) {
  374. is_built_in = true;
  375. break;
  376. }
  377. }
  378. if (is_built_in) {
  379. continue;
  380. }
  381. const uint32_t type = decoration.GetSingleWordInOperand(3u);
  382. LinkageSymbolInfo symbol_info;
  383. symbol_info.name = decoration.GetInOperand(2u).AsString();
  384. symbol_info.id = id;
  385. symbol_info.type_id = 0u;
  386. // Retrieve the type of the current symbol. This information will be used
  387. // when checking that the imported and exported symbols have the same
  388. // types.
  389. const Instruction* def_inst = def_use_manager.GetDef(id);
  390. if (def_inst == nullptr)
  391. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
  392. << "ID " << id << " is never defined:\n";
  393. if (def_inst->opcode() == SpvOpVariable) {
  394. symbol_info.type_id = def_inst->type_id();
  395. } else if (def_inst->opcode() == SpvOpFunction) {
  396. symbol_info.type_id = def_inst->GetSingleWordInOperand(1u);
  397. // range-based for loop calls begin()/end(), but never cbegin()/cend(),
  398. // which will not work here.
  399. for (auto func_iter = linked_context.module()->cbegin();
  400. func_iter != linked_context.module()->cend(); ++func_iter) {
  401. if (func_iter->result_id() != id) continue;
  402. func_iter->ForEachParam([&symbol_info](const Instruction* inst) {
  403. symbol_info.parameter_ids.push_back(inst->result_id());
  404. });
  405. }
  406. } else {
  407. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
  408. << "Only global variables and functions can be decorated using"
  409. << " LinkageAttributes; " << id << " is neither of them.\n";
  410. }
  411. if (type == SpvLinkageTypeImport)
  412. imports.push_back(symbol_info);
  413. else if (type == SpvLinkageTypeExport)
  414. exports[symbol_info.name].push_back(symbol_info);
  415. }
  416. // Find the import/export pairs
  417. for (const auto& import : imports) {
  418. std::vector<LinkageSymbolInfo> possible_exports;
  419. const auto& exp = exports.find(import.name);
  420. if (exp != exports.end()) possible_exports = exp->second;
  421. if (possible_exports.empty() && !allow_partial_linkage)
  422. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
  423. << "Unresolved external reference to \"" << import.name << "\".";
  424. else if (possible_exports.size() > 1u)
  425. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
  426. << "Too many external references, " << possible_exports.size()
  427. << ", were found for \"" << import.name << "\".";
  428. if (!possible_exports.empty())
  429. linkings_to_do->emplace_back(import, possible_exports.front());
  430. }
  431. return SPV_SUCCESS;
  432. }
  433. spv_result_t CheckImportExportCompatibility(const MessageConsumer& consumer,
  434. const LinkageTable& linkings_to_do,
  435. opt::IRContext* context) {
  436. spv_position_t position = {};
  437. // Ensure the import and export types are the same.
  438. const DecorationManager& decoration_manager = *context->get_decoration_mgr();
  439. const TypeManager& type_manager = *context->get_type_mgr();
  440. for (const auto& linking_entry : linkings_to_do) {
  441. Type* imported_symbol_type =
  442. type_manager.GetType(linking_entry.imported_symbol.type_id);
  443. Type* exported_symbol_type =
  444. type_manager.GetType(linking_entry.exported_symbol.type_id);
  445. if (!(*imported_symbol_type == *exported_symbol_type))
  446. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
  447. << "Type mismatch on symbol \""
  448. << linking_entry.imported_symbol.name
  449. << "\" between imported variable/function %"
  450. << linking_entry.imported_symbol.id
  451. << " and exported variable/function %"
  452. << linking_entry.exported_symbol.id << ".";
  453. }
  454. // Ensure the import and export decorations are similar
  455. for (const auto& linking_entry : linkings_to_do) {
  456. if (!decoration_manager.HaveTheSameDecorations(
  457. linking_entry.imported_symbol.id, linking_entry.exported_symbol.id))
  458. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
  459. << "Decorations mismatch on symbol \""
  460. << linking_entry.imported_symbol.name
  461. << "\" between imported variable/function %"
  462. << linking_entry.imported_symbol.id
  463. << " and exported variable/function %"
  464. << linking_entry.exported_symbol.id << ".";
  465. // TODO(pierremoreau): Decorations on function parameters should probably
  466. // match, except for FuncParamAttr if I understand the
  467. // spec correctly.
  468. // TODO(pierremoreau): Decorations on the function return type should
  469. // match, except for FuncParamAttr.
  470. }
  471. return SPV_SUCCESS;
  472. }
  473. spv_result_t RemoveLinkageSpecificInstructions(
  474. const MessageConsumer& consumer, const LinkerOptions& options,
  475. const LinkageTable& linkings_to_do, DecorationManager* decoration_manager,
  476. opt::IRContext* linked_context) {
  477. spv_position_t position = {};
  478. if (decoration_manager == nullptr)
  479. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_DATA)
  480. << "|decoration_manager| of RemoveLinkageSpecificInstructions "
  481. "should not be empty.";
  482. if (linked_context == nullptr)
  483. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_DATA)
  484. << "|linked_module| of RemoveLinkageSpecificInstructions should not "
  485. "be empty.";
  486. // TODO(pierremoreau): Remove FuncParamAttr decorations of imported
  487. // functions' return type.
  488. // Remove prototypes of imported functions
  489. for (const auto& linking_entry : linkings_to_do) {
  490. for (auto func_iter = linked_context->module()->begin();
  491. func_iter != linked_context->module()->end();) {
  492. if (func_iter->result_id() == linking_entry.imported_symbol.id)
  493. func_iter = func_iter.Erase();
  494. else
  495. ++func_iter;
  496. }
  497. }
  498. // Remove declarations of imported variables
  499. for (const auto& linking_entry : linkings_to_do) {
  500. auto next = linked_context->types_values_begin();
  501. for (auto inst = next; inst != linked_context->types_values_end();
  502. inst = next) {
  503. ++next;
  504. if (inst->result_id() == linking_entry.imported_symbol.id) {
  505. linked_context->KillInst(&*inst);
  506. }
  507. }
  508. }
  509. // If partial linkage is allowed, we need an efficient way to check whether
  510. // an imported ID had a corresponding export symbol. As uses of the imported
  511. // symbol have already been replaced by the exported symbol, use the exported
  512. // symbol ID.
  513. // TODO(pierremoreau): This will not work if the decoration is applied
  514. // through a group, but the linker does not support that
  515. // either.
  516. std::unordered_set<SpvId> imports;
  517. if (options.GetAllowPartialLinkage()) {
  518. imports.reserve(linkings_to_do.size());
  519. for (const auto& linking_entry : linkings_to_do)
  520. imports.emplace(linking_entry.exported_symbol.id);
  521. }
  522. // Remove import linkage attributes
  523. auto next = linked_context->annotation_begin();
  524. for (auto inst = next; inst != linked_context->annotation_end();
  525. inst = next) {
  526. ++next;
  527. // If this is an import annotation:
  528. // * if we do not allow partial linkage, remove all import annotations;
  529. // * otherwise, remove the annotation only if there was a corresponding
  530. // export.
  531. if (inst->opcode() == SpvOpDecorate &&
  532. inst->GetSingleWordOperand(1u) == SpvDecorationLinkageAttributes &&
  533. inst->GetSingleWordOperand(3u) == SpvLinkageTypeImport &&
  534. (!options.GetAllowPartialLinkage() ||
  535. imports.find(inst->GetSingleWordOperand(0u)) != imports.end())) {
  536. linked_context->KillInst(&*inst);
  537. }
  538. }
  539. // Remove export linkage attributes if making an executable
  540. if (!options.GetCreateLibrary()) {
  541. next = linked_context->annotation_begin();
  542. for (auto inst = next; inst != linked_context->annotation_end();
  543. inst = next) {
  544. ++next;
  545. if (inst->opcode() == SpvOpDecorate &&
  546. inst->GetSingleWordOperand(1u) == SpvDecorationLinkageAttributes &&
  547. inst->GetSingleWordOperand(3u) == SpvLinkageTypeExport) {
  548. linked_context->KillInst(&*inst);
  549. }
  550. }
  551. }
  552. // Remove Linkage capability if making an executable and partial linkage is
  553. // not allowed
  554. if (!options.GetCreateLibrary() && !options.GetAllowPartialLinkage()) {
  555. for (auto& inst : linked_context->capabilities())
  556. if (inst.GetSingleWordInOperand(0u) == SpvCapabilityLinkage) {
  557. linked_context->KillInst(&inst);
  558. // The RemoveDuplicatesPass did remove duplicated capabilities, so we
  559. // now there aren’t more SpvCapabilityLinkage further down.
  560. break;
  561. }
  562. }
  563. return SPV_SUCCESS;
  564. }
  565. spv_result_t VerifyIds(const MessageConsumer& consumer,
  566. opt::IRContext* linked_context) {
  567. std::unordered_set<uint32_t> ids;
  568. bool ok = true;
  569. linked_context->module()->ForEachInst(
  570. [&ids, &ok](const opt::Instruction* inst) {
  571. ok &= ids.insert(inst->unique_id()).second;
  572. });
  573. if (!ok) {
  574. consumer(SPV_MSG_INTERNAL_ERROR, "", {}, "Non-unique id in merged module");
  575. return SPV_ERROR_INVALID_ID;
  576. }
  577. return SPV_SUCCESS;
  578. }
  579. spv_result_t VerifyLimits(const MessageConsumer& consumer,
  580. const opt::IRContext& linked_context) {
  581. spv_position_t position = {};
  582. const uint32_t max_id_bound = linked_context.module()->id_bound();
  583. if (max_id_bound >= SPV_LIMIT_RESULT_ID_BOUND)
  584. DiagnosticStream({0u, 0u, 4u}, consumer, "", SPV_WARNING)
  585. << "The minimum limit of IDs, " << (SPV_LIMIT_RESULT_ID_BOUND - 1)
  586. << ", was exceeded:"
  587. << " " << max_id_bound << " is the current ID bound.\n"
  588. << "The resulting module might not be supported by all "
  589. "implementations.";
  590. size_t num_global_values = 0u;
  591. for (const auto& inst : linked_context.module()->types_values()) {
  592. num_global_values += inst.opcode() == SpvOpVariable;
  593. }
  594. if (num_global_values >= SPV_LIMIT_GLOBAL_VARIABLES_MAX)
  595. DiagnosticStream(position, consumer, "", SPV_WARNING)
  596. << "The minimum limit of global values, "
  597. << (SPV_LIMIT_GLOBAL_VARIABLES_MAX - 1) << ", was exceeded;"
  598. << " " << num_global_values << " global values were found.\n"
  599. << "The resulting module might not be supported by all "
  600. "implementations.";
  601. return SPV_SUCCESS;
  602. }
  603. } // namespace
  604. spv_result_t Link(const Context& context,
  605. const std::vector<std::vector<uint32_t>>& binaries,
  606. std::vector<uint32_t>* linked_binary,
  607. const LinkerOptions& options) {
  608. std::vector<const uint32_t*> binary_ptrs;
  609. binary_ptrs.reserve(binaries.size());
  610. std::vector<size_t> binary_sizes;
  611. binary_sizes.reserve(binaries.size());
  612. for (const auto& binary : binaries) {
  613. binary_ptrs.push_back(binary.data());
  614. binary_sizes.push_back(binary.size());
  615. }
  616. return Link(context, binary_ptrs.data(), binary_sizes.data(), binaries.size(),
  617. linked_binary, options);
  618. }
  619. spv_result_t Link(const Context& context, const uint32_t* const* binaries,
  620. const size_t* binary_sizes, size_t num_binaries,
  621. std::vector<uint32_t>* linked_binary,
  622. const LinkerOptions& options) {
  623. spv_position_t position = {};
  624. const spv_context& c_context = context.CContext();
  625. const MessageConsumer& consumer = c_context->consumer;
  626. linked_binary->clear();
  627. if (num_binaries == 0u)
  628. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
  629. << "No modules were given.";
  630. std::vector<std::unique_ptr<IRContext>> ir_contexts;
  631. std::vector<Module*> modules;
  632. modules.reserve(num_binaries);
  633. for (size_t i = 0u; i < num_binaries; ++i) {
  634. const uint32_t schema = binaries[i][4u];
  635. if (schema != 0u) {
  636. position.index = 4u;
  637. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
  638. << "Schema is non-zero for module " << i + 1 << ".";
  639. }
  640. std::unique_ptr<IRContext> ir_context = BuildModule(
  641. c_context->target_env, consumer, binaries[i], binary_sizes[i]);
  642. if (ir_context == nullptr)
  643. return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
  644. << "Failed to build module " << i + 1 << " out of " << num_binaries
  645. << ".";
  646. modules.push_back(ir_context->module());
  647. ir_contexts.push_back(std::move(ir_context));
  648. }
  649. // Phase 1: Shift the IDs used in each binary so that they occupy a disjoint
  650. // range from the other binaries, and compute the new ID bound.
  651. uint32_t max_id_bound = 0u;
  652. spv_result_t res = ShiftIdsInModules(consumer, &modules, &max_id_bound);
  653. if (res != SPV_SUCCESS) return res;
  654. // Phase 2: Generate the header
  655. opt::ModuleHeader header;
  656. res = GenerateHeader(consumer, modules, max_id_bound, &header);
  657. if (res != SPV_SUCCESS) return res;
  658. IRContext linked_context(c_context->target_env, consumer);
  659. linked_context.module()->SetHeader(header);
  660. // Phase 3: Merge all the binaries into a single one.
  661. AssemblyGrammar grammar(c_context);
  662. res = MergeModules(consumer, modules, grammar, &linked_context);
  663. if (res != SPV_SUCCESS) return res;
  664. if (options.GetVerifyIds()) {
  665. res = VerifyIds(consumer, &linked_context);
  666. if (res != SPV_SUCCESS) return res;
  667. }
  668. // Phase 4: Find the import/export pairs
  669. LinkageTable linkings_to_do;
  670. res = GetImportExportPairs(consumer, linked_context,
  671. *linked_context.get_def_use_mgr(),
  672. *linked_context.get_decoration_mgr(),
  673. options.GetAllowPartialLinkage(), &linkings_to_do);
  674. if (res != SPV_SUCCESS) return res;
  675. // Phase 5: Ensure the import and export have the same types and decorations.
  676. res =
  677. CheckImportExportCompatibility(consumer, linkings_to_do, &linked_context);
  678. if (res != SPV_SUCCESS) return res;
  679. // Phase 6: Remove duplicates
  680. PassManager manager;
  681. manager.SetMessageConsumer(consumer);
  682. manager.AddPass<RemoveDuplicatesPass>();
  683. opt::Pass::Status pass_res = manager.Run(&linked_context);
  684. if (pass_res == opt::Pass::Status::Failure) return SPV_ERROR_INVALID_DATA;
  685. // Phase 7: Remove all names and decorations of import variables/functions
  686. for (const auto& linking_entry : linkings_to_do) {
  687. linked_context.KillNamesAndDecorates(linking_entry.imported_symbol.id);
  688. for (const auto parameter_id :
  689. linking_entry.imported_symbol.parameter_ids) {
  690. linked_context.KillNamesAndDecorates(parameter_id);
  691. }
  692. }
  693. // Phase 8: Rematch import variables/functions to export variables/functions
  694. for (const auto& linking_entry : linkings_to_do) {
  695. linked_context.ReplaceAllUsesWith(linking_entry.imported_symbol.id,
  696. linking_entry.exported_symbol.id);
  697. }
  698. // Phase 9: Remove linkage specific instructions, such as import/export
  699. // attributes, linkage capability, etc. if applicable
  700. res = RemoveLinkageSpecificInstructions(consumer, options, linkings_to_do,
  701. linked_context.get_decoration_mgr(),
  702. &linked_context);
  703. if (res != SPV_SUCCESS) return res;
  704. // Phase 10: Compact the IDs used in the module
  705. manager.AddPass<opt::CompactIdsPass>();
  706. pass_res = manager.Run(&linked_context);
  707. if (pass_res == opt::Pass::Status::Failure) return SPV_ERROR_INVALID_DATA;
  708. // Phase 11: Recompute EntryPoint variables
  709. manager.AddPass<opt::RemoveUnusedInterfaceVariablesPass>();
  710. pass_res = manager.Run(&linked_context);
  711. if (pass_res == opt::Pass::Status::Failure) return SPV_ERROR_INVALID_DATA;
  712. // Phase 12: Warn if SPIR-V limits were exceeded
  713. res = VerifyLimits(consumer, linked_context);
  714. if (res != SPV_SUCCESS) return res;
  715. // Phase 13: Output the module
  716. linked_context.module()->ToBinary(linked_binary, true);
  717. return SPV_SUCCESS;
  718. }
  719. } // namespace spvtools