| 938 | } |
| 939 | |
| 940 | opt::Instruction* AddLocalVariable(opt::IRContext* context, uint32_t result_id, |
| 941 | uint32_t type_id, uint32_t function_id, |
| 942 | uint32_t initializer_id) { |
| 943 | // Check various preconditions. |
| 944 | assert(result_id != 0 && "Result id can't be 0"); |
| 945 | |
| 946 | auto* type_inst = context->get_def_use_mgr()->GetDef(type_id); |
| 947 | (void)type_inst; // Variable becomes unused in release mode. |
| 948 | assert(type_inst && type_inst->opcode() == spv::Op::OpTypePointer && |
| 949 | GetStorageClassFromPointerType(type_inst) == |
| 950 | spv::StorageClass::Function && |
| 951 | "Variable's type is invalid"); |
| 952 | |
| 953 | const auto* constant_inst = |
| 954 | context->get_def_use_mgr()->GetDef(initializer_id); |
| 955 | (void)constant_inst; // Variable becomes unused in release mode. |
| 956 | assert(constant_inst && spvOpcodeIsConstant(constant_inst->opcode()) && |
| 957 | GetPointeeTypeIdFromPointerType(type_inst) == |
| 958 | constant_inst->type_id() && |
| 959 | "Initializer is invalid"); |
| 960 | |
| 961 | auto* function = FindFunction(context, function_id); |
| 962 | assert(function && "Function id is invalid"); |
| 963 | |
| 964 | auto new_instruction = MakeUnique<opt::Instruction>( |
| 965 | context, spv::Op::OpVariable, type_id, result_id, |
| 966 | opt::Instruction::OperandList{{SPV_OPERAND_TYPE_STORAGE_CLASS, |
| 967 | {uint32_t(spv::StorageClass::Function)}}, |
| 968 | {SPV_OPERAND_TYPE_ID, {initializer_id}}}); |
| 969 | auto result = new_instruction.get(); |
| 970 | function->begin()->begin()->InsertBefore(std::move(new_instruction)); |
| 971 | |
| 972 | UpdateModuleIdBound(context, result_id); |
| 973 | |
| 974 | return result; |
| 975 | } |
| 976 | |
| 977 | bool HasDuplicates(const std::vector<uint32_t>& arr) { |
| 978 | return std::unordered_set<uint32_t>(arr.begin(), arr.end()).size() != |
no test coverage detected