| 525 | } |
| 526 | |
| 527 | spv_result_t CheckImportExportCompatibility(const MessageConsumer& consumer, |
| 528 | const LinkageTable& linkings_to_do, |
| 529 | bool allow_ptr_type_mismatch, |
| 530 | opt::IRContext* context) { |
| 531 | spv_position_t position = {}; |
| 532 | |
| 533 | // Ensure the import and export types are the same. |
| 534 | const DecorationManager& decoration_manager = *context->get_decoration_mgr(); |
| 535 | const TypeManager& type_manager = *context->get_type_mgr(); |
| 536 | for (const auto& linking_entry : linkings_to_do) { |
| 537 | Type* imported_symbol_type = |
| 538 | type_manager.GetType(linking_entry.imported_symbol.type_id); |
| 539 | Type* exported_symbol_type = |
| 540 | type_manager.GetType(linking_entry.exported_symbol.type_id); |
| 541 | if (!(*imported_symbol_type == *exported_symbol_type)) { |
| 542 | Function* imported_symbol_type_func = imported_symbol_type->AsFunction(); |
| 543 | Function* exported_symbol_type_func = exported_symbol_type->AsFunction(); |
| 544 | |
| 545 | if (imported_symbol_type_func && exported_symbol_type_func) { |
| 546 | const auto& imported_params = imported_symbol_type_func->param_types(); |
| 547 | const auto& exported_params = exported_symbol_type_func->param_types(); |
| 548 | // allow_ptr_type_mismatch allows linking functions where the pointer |
| 549 | // type of arguments doesn't match. Everything else still needs to be |
| 550 | // equal. This is to workaround LLVM-17+ not having typed pointers and |
| 551 | // generated SPIR-Vs not knowing the actual pointer types in some cases. |
| 552 | if (allow_ptr_type_mismatch && |
| 553 | imported_params.size() == exported_params.size()) { |
| 554 | bool correct = true; |
| 555 | for (size_t i = 0; i < imported_params.size(); i++) { |
| 556 | const auto& imported_param = imported_params[i]; |
| 557 | const auto& exported_param = exported_params[i]; |
| 558 | |
| 559 | if (!imported_param->IsSame(exported_param) && |
| 560 | (imported_param->kind() != Type::kPointer || |
| 561 | exported_param->kind() != Type::kPointer)) { |
| 562 | correct = false; |
| 563 | break; |
| 564 | } |
| 565 | } |
| 566 | if (correct) continue; |
| 567 | } |
| 568 | } |
| 569 | return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY) |
| 570 | << "Type mismatch on symbol \"" |
| 571 | << linking_entry.imported_symbol.name |
| 572 | << "\" between imported variable/function %" |
| 573 | << linking_entry.imported_symbol.id |
| 574 | << " and exported variable/function %" |
| 575 | << linking_entry.exported_symbol.id << "."; |
| 576 | } |
| 577 | } |
| 578 | |
| 579 | // Ensure the import and export decorations are similar |
| 580 | for (const auto& linking_entry : linkings_to_do) { |
| 581 | if (!decoration_manager.HaveTheSameDecorations( |
| 582 | linking_entry.imported_symbol.id, linking_entry.exported_symbol.id)) |
| 583 | return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY) |
| 584 | << "Decorations mismatch on symbol \"" |
no test coverage detected