• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2019 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_constant_scalar.h"
16 
17 #include "source/fuzz/fuzzer_util.h"
18 
19 namespace spvtools {
20 namespace fuzz {
21 
TransformationAddConstantScalar(spvtools::fuzz::protobufs::TransformationAddConstantScalar message)22 TransformationAddConstantScalar::TransformationAddConstantScalar(
23     spvtools::fuzz::protobufs::TransformationAddConstantScalar message)
24     : message_(std::move(message)) {}
25 
TransformationAddConstantScalar(uint32_t fresh_id,uint32_t type_id,const std::vector<uint32_t> & words,bool is_irrelevant)26 TransformationAddConstantScalar::TransformationAddConstantScalar(
27     uint32_t fresh_id, uint32_t type_id, const std::vector<uint32_t>& words,
28     bool is_irrelevant) {
29   message_.set_fresh_id(fresh_id);
30   message_.set_type_id(type_id);
31   message_.set_is_irrelevant(is_irrelevant);
32   for (auto word : words) {
33     message_.add_word(word);
34   }
35 }
36 
IsApplicable(opt::IRContext * ir_context,const TransformationContext &) const37 bool TransformationAddConstantScalar::IsApplicable(
38     opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
39   // The id needs to be fresh.
40   if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
41     return false;
42   }
43   // The type id for the scalar must exist and be a type.
44   auto type = ir_context->get_type_mgr()->GetType(message_.type_id());
45   if (!type) {
46     return false;
47   }
48   uint32_t width;
49   if (type->AsFloat()) {
50     width = type->AsFloat()->width();
51   } else if (type->AsInteger()) {
52     width = type->AsInteger()->width();
53   } else {
54     return false;
55   }
56   // The number of words is the integer floor of the width.
57   auto words = (width + 32 - 1) / 32;
58 
59   // The number of words provided by the transformation needs to match the
60   // width of the type.
61   return static_cast<uint32_t>(message_.word().size()) == words;
62 }
63 
Apply(opt::IRContext * ir_context,TransformationContext * transformation_context) const64 void TransformationAddConstantScalar::Apply(
65     opt::IRContext* ir_context,
66     TransformationContext* transformation_context) const {
67   auto new_instruction = MakeUnique<opt::Instruction>(
68       ir_context, SpvOpConstant, message_.type_id(), message_.fresh_id(),
69       opt::Instruction::OperandList(
70           {{SPV_OPERAND_TYPE_LITERAL_INTEGER,
71             std::vector<uint32_t>(message_.word().begin(),
72                                   message_.word().end())}}));
73   auto new_instruction_ptr = new_instruction.get();
74   ir_context->module()->AddGlobalValue(std::move(new_instruction));
75 
76   fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
77 
78   // Inform the def-use manager about the new instruction. Invalidate the
79   // constant manager as we have added a new constant.
80   ir_context->get_def_use_mgr()->AnalyzeInstDef(new_instruction_ptr);
81   ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisConstants);
82 
83   if (message_.is_irrelevant()) {
84     transformation_context->GetFactManager()->AddFactIdIsIrrelevant(
85         message_.fresh_id());
86   }
87 }
88 
ToMessage() const89 protobufs::Transformation TransformationAddConstantScalar::ToMessage() const {
90   protobufs::Transformation result;
91   *result.mutable_add_constant_scalar() = message_;
92   return result;
93 }
94 
GetFreshIds() const95 std::unordered_set<uint32_t> TransformationAddConstantScalar::GetFreshIds()
96     const {
97   return {message_.fresh_id()};
98 }
99 
100 }  // namespace fuzz
101 }  // namespace spvtools
102