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_add_image_sample_unused_components.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 TransformationAddImageSampleUnusedComponents::
TransformationAddImageSampleUnusedComponents(const spvtools::fuzz::protobufs::TransformationAddImageSampleUnusedComponents & message)24 TransformationAddImageSampleUnusedComponents(
25 const spvtools::fuzz::protobufs::
26 TransformationAddImageSampleUnusedComponents& message)
27 : message_(message) {}
28
29 TransformationAddImageSampleUnusedComponents::
TransformationAddImageSampleUnusedComponents(uint32_t coordinate_with_unused_components_id,const protobufs::InstructionDescriptor & instruction_descriptor)30 TransformationAddImageSampleUnusedComponents(
31 uint32_t coordinate_with_unused_components_id,
32 const protobufs::InstructionDescriptor& instruction_descriptor) {
33 message_.set_coordinate_with_unused_components_id(
34 coordinate_with_unused_components_id);
35 *message_.mutable_instruction_descriptor() = instruction_descriptor;
36 }
37
IsApplicable(opt::IRContext * ir_context,const TransformationContext &) const38 bool TransformationAddImageSampleUnusedComponents::IsApplicable(
39 opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
40 auto image_sample_instruction =
41 FindInstruction(message_.instruction_descriptor(), ir_context);
42
43 // The image sample instruction must be defined.
44 if (image_sample_instruction == nullptr) {
45 return false;
46 }
47
48 // The instruction must be an image sample instruction.
49 if (!spvOpcodeIsImageSample(image_sample_instruction->opcode())) {
50 return false;
51 }
52
53 uint32_t coordinate_id = image_sample_instruction->GetSingleWordInOperand(1);
54 auto coordinate_instruction =
55 ir_context->get_def_use_mgr()->GetDef(coordinate_id);
56 auto coordinate_type =
57 ir_context->get_type_mgr()->GetType(coordinate_instruction->type_id());
58
59 // It must be possible to add unused components.
60 if (coordinate_type->AsVector() &&
61 coordinate_type->AsVector()->element_count() == 4) {
62 return false;
63 }
64
65 auto coordinate_with_unused_components_instruction =
66 ir_context->get_def_use_mgr()->GetDef(
67 message_.coordinate_with_unused_components_id());
68
69 // The coordinate with unused components instruction must be defined.
70 if (coordinate_with_unused_components_instruction == nullptr) {
71 return false;
72 }
73
74 // It must be an OpCompositeConstruct instruction such that it can be checked
75 // that the original components are present.
76 if (coordinate_with_unused_components_instruction->opcode() !=
77 SpvOpCompositeConstruct) {
78 return false;
79 }
80
81 // The first constituent must be the original coordinate.
82 if (coordinate_with_unused_components_instruction->GetSingleWordInOperand(
83 0) != coordinate_id) {
84 return false;
85 }
86
87 auto coordinate_with_unused_components_type =
88 ir_context->get_type_mgr()->GetType(
89 coordinate_with_unused_components_instruction->type_id());
90
91 // |coordinate_with_unused_components_type| must be a vector.
92 if (!coordinate_with_unused_components_type->AsVector()) {
93 return false;
94 }
95
96 return true;
97 }
98
Apply(opt::IRContext * ir_context,TransformationContext *) const99 void TransformationAddImageSampleUnusedComponents::Apply(
100 opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
101 // Sets the coordinate operand.
102 auto image_sample_instruction =
103 FindInstruction(message_.instruction_descriptor(), ir_context);
104 image_sample_instruction->SetInOperand(
105 1, {message_.coordinate_with_unused_components_id()});
106 ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
107 }
108
109 protobufs::Transformation
ToMessage() const110 TransformationAddImageSampleUnusedComponents::ToMessage() const {
111 protobufs::Transformation result;
112 *result.mutable_add_image_sample_unused_components() = message_;
113 return result;
114 }
115
116 std::unordered_set<uint32_t>
GetFreshIds() const117 TransformationAddImageSampleUnusedComponents::GetFreshIds() const {
118 return std::unordered_set<uint32_t>();
119 }
120
121 } // namespace fuzz
122 } // namespace spvtools
123