| 751 | } |
| 752 | |
| 753 | spv_result_t FixFunctionCallTypes(opt::IRContext& context, |
| 754 | const LinkageTable& linkings) { |
| 755 | auto mod = context.module(); |
| 756 | const auto type_manager = context.get_type_mgr(); |
| 757 | const auto def_use_mgr = context.get_def_use_mgr(); |
| 758 | |
| 759 | for (auto& func : *mod) { |
| 760 | func.ForEachInst([&](Instruction* inst) { |
| 761 | if (inst->opcode() != spv::Op::OpFunctionCall) return; |
| 762 | opt::Operand& target = inst->GetInOperand(0); |
| 763 | |
| 764 | // only fix calls to imported functions |
| 765 | auto linking = std::find_if( |
| 766 | linkings.begin(), linkings.end(), [&](const auto& entry) { |
| 767 | return entry.exported_symbol.id == target.AsId(); |
| 768 | }); |
| 769 | if (linking == linkings.end()) return; |
| 770 | |
| 771 | auto builder = InstructionBuilder(&context, inst); |
| 772 | for (uint32_t i = 1; i < inst->NumInOperands(); ++i) { |
| 773 | auto exported_func_param = |
| 774 | def_use_mgr->GetDef(linking->exported_symbol.parameter_ids[i - 1]); |
| 775 | const Type* target_type = |
| 776 | type_manager->GetType(exported_func_param->type_id()); |
| 777 | if (target_type->kind() != Type::kPointer) continue; |
| 778 | |
| 779 | opt::Operand& arg = inst->GetInOperand(i); |
| 780 | const Type* param_type = |
| 781 | type_manager->GetType(def_use_mgr->GetDef(arg.AsId())->type_id()); |
| 782 | |
| 783 | // No need to cast if it already matches |
| 784 | if (*param_type == *target_type) continue; |
| 785 | |
| 786 | auto new_id = context.TakeNextId(); |
| 787 | |
| 788 | // cast to the expected pointer type |
| 789 | builder.AddInstruction(MakeUnique<opt::Instruction>( |
| 790 | &context, spv::Op::OpBitcast, exported_func_param->type_id(), |
| 791 | new_id, |
| 792 | opt::Instruction::OperandList( |
| 793 | {{SPV_OPERAND_TYPE_ID, {arg.AsId()}}}))); |
| 794 | |
| 795 | inst->SetInOperand(i, {new_id}); |
| 796 | } |
| 797 | }); |
| 798 | } |
| 799 | context.InvalidateAnalyses(opt::IRContext::kAnalysisDefUse | |
| 800 | opt::IRContext::kAnalysisInstrToBlockMapping); |
| 801 | return SPV_SUCCESS; |
| 802 | } |
| 803 | |
| 804 | } // namespace |
| 805 |
no test coverage detected