• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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