linker.cpp 32 KB

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