| 101 | } |
| 102 | |
| 103 | void TransformationPushIdThroughVariable::Apply( |
| 104 | opt::IRContext* ir_context, |
| 105 | TransformationContext* transformation_context) const { |
| 106 | auto value_instruction = |
| 107 | ir_context->get_def_use_mgr()->GetDef(message_.value_id()); |
| 108 | |
| 109 | opt::Instruction* insert_before = |
| 110 | FindInstruction(message_.instruction_descriptor(), ir_context); |
| 111 | opt::BasicBlock* enclosing_block = ir_context->get_instr_block(insert_before); |
| 112 | |
| 113 | // A pointer type instruction pointing to the value type must be defined. |
| 114 | auto pointer_type_id = fuzzerutil::MaybeGetPointerType( |
| 115 | ir_context, value_instruction->type_id(), |
| 116 | static_cast<spv::StorageClass>(message_.variable_storage_class())); |
| 117 | assert(pointer_type_id && "The required pointer type must be available."); |
| 118 | |
| 119 | // Adds whether a global or local variable. |
| 120 | if (spv::StorageClass(message_.variable_storage_class()) == |
| 121 | spv::StorageClass::Private) { |
| 122 | opt::Instruction* global_variable = fuzzerutil::AddGlobalVariable( |
| 123 | ir_context, message_.variable_id(), pointer_type_id, |
| 124 | spv::StorageClass::Private, message_.initializer_id()); |
| 125 | ir_context->get_def_use_mgr()->AnalyzeInstDefUse(global_variable); |
| 126 | } else { |
| 127 | opt::Function* function = |
| 128 | ir_context |
| 129 | ->get_instr_block( |
| 130 | FindInstruction(message_.instruction_descriptor(), ir_context)) |
| 131 | ->GetParent(); |
| 132 | opt::Instruction* local_variable = fuzzerutil::AddLocalVariable( |
| 133 | ir_context, message_.variable_id(), pointer_type_id, |
| 134 | function->result_id(), message_.initializer_id()); |
| 135 | ir_context->get_def_use_mgr()->AnalyzeInstDefUse(local_variable); |
| 136 | ir_context->set_instr_block(local_variable, &*function->entry()); |
| 137 | } |
| 138 | |
| 139 | // First, insert the OpLoad instruction before |instruction_descriptor| and |
| 140 | // then insert the OpStore instruction before the OpLoad instruction. |
| 141 | fuzzerutil::UpdateModuleIdBound(ir_context, message_.value_synonym_id()); |
| 142 | opt::Instruction* load_instruction = |
| 143 | insert_before->InsertBefore(MakeUnique<opt::Instruction>( |
| 144 | ir_context, spv::Op::OpLoad, value_instruction->type_id(), |
| 145 | message_.value_synonym_id(), |
| 146 | opt::Instruction::OperandList( |
| 147 | {{SPV_OPERAND_TYPE_ID, {message_.variable_id()}}}))); |
| 148 | opt::Instruction* store_instruction = |
| 149 | load_instruction->InsertBefore(MakeUnique<opt::Instruction>( |
| 150 | ir_context, spv::Op::OpStore, 0, 0, |
| 151 | opt::Instruction::OperandList( |
| 152 | {{SPV_OPERAND_TYPE_ID, {message_.variable_id()}}, |
| 153 | {SPV_OPERAND_TYPE_ID, {message_.value_id()}}}))); |
| 154 | ir_context->get_def_use_mgr()->AnalyzeInstDefUse(store_instruction); |
| 155 | ir_context->set_instr_block(store_instruction, enclosing_block); |
| 156 | ir_context->get_def_use_mgr()->AnalyzeInstDefUse(load_instruction); |
| 157 | ir_context->set_instr_block(load_instruction, enclosing_block); |
| 158 | |
| 159 | // We should be able to create a synonym of |value_id| if it's not irrelevant. |
| 160 | if (fuzzerutil::CanMakeSynonymOf(ir_context, *transformation_context, |
nothing calls this directly
no test coverage detected