1 // Copyright (c) 2020 André Perez Maselco
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
15 #include "source/fuzz/transformation_make_vector_operation_dynamic.h"
16
17 #include "source/fuzz/fuzzer_util.h"
18 #include "source/fuzz/instruction_descriptor.h"
19
20 namespace spvtools {
21 namespace fuzz {
22
23 TransformationMakeVectorOperationDynamic::
TransformationMakeVectorOperationDynamic(protobufs::TransformationMakeVectorOperationDynamic message)24 TransformationMakeVectorOperationDynamic(
25 protobufs::TransformationMakeVectorOperationDynamic message)
26 : message_(std::move(message)) {}
27
28 TransformationMakeVectorOperationDynamic::
TransformationMakeVectorOperationDynamic(uint32_t instruction_result_id,uint32_t constant_index_id)29 TransformationMakeVectorOperationDynamic(uint32_t instruction_result_id,
30 uint32_t constant_index_id) {
31 message_.set_instruction_result_id(instruction_result_id);
32 message_.set_constant_index_id(constant_index_id);
33 }
34
IsApplicable(opt::IRContext * ir_context,const TransformationContext &) const35 bool TransformationMakeVectorOperationDynamic::IsApplicable(
36 opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
37 // |instruction| must be a vector operation.
38 auto instruction =
39 ir_context->get_def_use_mgr()->GetDef(message_.instruction_result_id());
40 if (!IsVectorOperation(ir_context, instruction)) {
41 return false;
42 }
43
44 // |constant_index_instruction| must be defined as an integer instruction.
45 auto constant_index_instruction =
46 ir_context->get_def_use_mgr()->GetDef(message_.constant_index_id());
47 if (!constant_index_instruction || !constant_index_instruction->type_id() ||
48 !ir_context->get_type_mgr()
49 ->GetType(constant_index_instruction->type_id())
50 ->AsInteger()) {
51 return false;
52 }
53
54 return true;
55 }
56
Apply(opt::IRContext * ir_context,TransformationContext *) const57 void TransformationMakeVectorOperationDynamic::Apply(
58 opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
59 auto instruction =
60 ir_context->get_def_use_mgr()->GetDef(message_.instruction_result_id());
61
62 // The OpVectorInsertDynamic instruction has the vector and component operands
63 // in reverse order in relation to the OpCompositeInsert corresponding
64 // operands.
65 if (instruction->opcode() == SpvOpCompositeInsert) {
66 std::swap(instruction->GetInOperand(0), instruction->GetInOperand(1));
67 }
68
69 // Sets the literal operand to the equivalent constant.
70 instruction->SetInOperand(
71 instruction->opcode() == SpvOpCompositeExtract ? 1 : 2,
72 {message_.constant_index_id()});
73
74 // Sets the |instruction| opcode to the corresponding vector dynamic opcode.
75 instruction->SetOpcode(instruction->opcode() == SpvOpCompositeExtract
76 ? SpvOpVectorExtractDynamic
77 : SpvOpVectorInsertDynamic);
78 }
79
ToMessage() const80 protobufs::Transformation TransformationMakeVectorOperationDynamic::ToMessage()
81 const {
82 protobufs::Transformation result;
83 *result.mutable_make_vector_operation_dynamic() = message_;
84 return result;
85 }
86
IsVectorOperation(opt::IRContext * ir_context,opt::Instruction * instruction)87 bool TransformationMakeVectorOperationDynamic::IsVectorOperation(
88 opt::IRContext* ir_context, opt::Instruction* instruction) {
89 // |instruction| must be defined and must be an OpCompositeExtract/Insert
90 // instruction.
91 if (!instruction || (instruction->opcode() != SpvOpCompositeExtract &&
92 instruction->opcode() != SpvOpCompositeInsert)) {
93 return false;
94 }
95
96 // The composite must be a vector.
97 auto composite_instruction =
98 ir_context->get_def_use_mgr()->GetDef(instruction->GetSingleWordInOperand(
99 instruction->opcode() == SpvOpCompositeExtract ? 0 : 1));
100 if (!ir_context->get_type_mgr()
101 ->GetType(composite_instruction->type_id())
102 ->AsVector()) {
103 return false;
104 }
105
106 return true;
107 }
108
109 std::unordered_set<uint32_t>
GetFreshIds() const110 TransformationMakeVectorOperationDynamic::GetFreshIds() const {
111 return std::unordered_set<uint32_t>();
112 }
113
114 } // namespace fuzz
115 } // namespace spvtools
116