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