1 // Copyright (c) 2020 Google LLC
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_relaxed_decoration.h"
16 
17 #include "source/fuzz/fuzzer_util.h"
18 
19 namespace spvtools {
20 namespace fuzz {
21 
TransformationAddRelaxedDecoration(protobufs::TransformationAddRelaxedDecoration message)22 TransformationAddRelaxedDecoration::TransformationAddRelaxedDecoration(
23     protobufs::TransformationAddRelaxedDecoration message)
24     : message_(std::move(message)) {}
25 
TransformationAddRelaxedDecoration(uint32_t result_id)26 TransformationAddRelaxedDecoration::TransformationAddRelaxedDecoration(
27     uint32_t result_id) {
28   message_.set_result_id(result_id);
29 }
30 
IsApplicable(opt::IRContext * ir_context,const TransformationContext & transformation_context) const31 bool TransformationAddRelaxedDecoration::IsApplicable(
32     opt::IRContext* ir_context,
33     const TransformationContext& transformation_context) const {
34   // |message_.result_id| must be the id of an instruction.
35   auto instr = ir_context->get_def_use_mgr()->GetDef(message_.result_id());
36   if (!instr) {
37     return false;
38   }
39   opt::BasicBlock* cur_block = ir_context->get_instr_block(instr);
40   // The instruction must have a block.
41   if (cur_block == nullptr) {
42     return false;
43   }
44   // |cur_block| must be a dead block.
45   if (!(transformation_context.GetFactManager()->BlockIsDead(
46           cur_block->id()))) {
47     return false;
48   }
49   // The instruction must be numeric.
50   return IsNumeric(instr->opcode());
51 }
52 
Apply(opt::IRContext * ir_context,TransformationContext *) const53 void TransformationAddRelaxedDecoration::Apply(
54     opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
55   // Add a RelaxedPrecision decoration targeting |message_.result_id|.
56   ir_context->get_decoration_mgr()->AddDecoration(
57       message_.result_id(), SpvDecorationRelaxedPrecision);
58 }
59 
ToMessage() const60 protobufs::Transformation TransformationAddRelaxedDecoration::ToMessage()
61     const {
62   protobufs::Transformation result;
63   *result.mutable_add_relaxed_decoration() = message_;
64   return result;
65 }
66 
IsNumeric(uint32_t opcode)67 bool TransformationAddRelaxedDecoration::IsNumeric(uint32_t opcode) {
68   switch (opcode) {
69     case SpvOpConvertFToU:
70     case SpvOpConvertFToS:
71     case SpvOpConvertSToF:
72     case SpvOpConvertUToF:
73     case SpvOpUConvert:
74     case SpvOpSConvert:
75     case SpvOpFConvert:
76     case SpvOpConvertPtrToU:
77     case SpvOpSatConvertSToU:
78     case SpvOpSatConvertUToS:
79     case SpvOpVectorExtractDynamic:
80     case SpvOpVectorInsertDynamic:
81     case SpvOpVectorShuffle:
82     case SpvOpTranspose:
83     case SpvOpSNegate:
84     case SpvOpFNegate:
85     case SpvOpIAdd:
86     case SpvOpFAdd:
87     case SpvOpISub:
88     case SpvOpFSub:
89     case SpvOpIMul:
90     case SpvOpFMul:
91     case SpvOpUDiv:
92     case SpvOpSDiv:
93     case SpvOpFDiv:
94     case SpvOpUMod:
95     case SpvOpSRem:
96     case SpvOpSMod:
97     case SpvOpFRem:
98     case SpvOpFMod:
99     case SpvOpVectorTimesScalar:
100     case SpvOpMatrixTimesScalar:
101     case SpvOpVectorTimesMatrix:
102     case SpvOpMatrixTimesVector:
103     case SpvOpMatrixTimesMatrix:
104     case SpvOpOuterProduct:
105     case SpvOpDot:
106     case SpvOpIAddCarry:
107     case SpvOpISubBorrow:
108     case SpvOpUMulExtended:
109     case SpvOpSMulExtended:
110     case SpvOpShiftRightLogical:
111     case SpvOpShiftRightArithmetic:
112     case SpvOpShiftLeftLogical:
113     case SpvOpBitwiseOr:
114     case SpvOpBitwiseXor:
115     case SpvOpBitwiseAnd:
116     case SpvOpNot:
117     case SpvOpBitFieldInsert:
118     case SpvOpBitFieldSExtract:
119     case SpvOpBitFieldUExtract:
120     case SpvOpBitReverse:
121     case SpvOpBitCount:
122     case SpvOpAtomicLoad:
123     case SpvOpAtomicStore:
124     case SpvOpAtomicExchange:
125     case SpvOpAtomicCompareExchange:
126     case SpvOpAtomicCompareExchangeWeak:
127     case SpvOpAtomicIIncrement:
128     case SpvOpAtomicIDecrement:
129     case SpvOpAtomicIAdd:
130     case SpvOpAtomicISub:
131     case SpvOpAtomicSMin:
132     case SpvOpAtomicUMin:
133     case SpvOpAtomicSMax:
134     case SpvOpAtomicUMax:
135     case SpvOpAtomicAnd:
136     case SpvOpAtomicOr:
137     case SpvOpAtomicXor:
138       return true;
139     default:
140       return false;
141   }
142 }
143 
GetFreshIds() const144 std::unordered_set<uint32_t> TransformationAddRelaxedDecoration::GetFreshIds()
145     const {
146   return std::unordered_set<uint32_t>();
147 }
148 
149 }  // namespace fuzz
150 }  // namespace spvtools