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