• 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_set_function_control.h"
16 
17 namespace spvtools {
18 namespace fuzz {
19 
TransformationSetFunctionControl(protobufs::TransformationSetFunctionControl message)20 TransformationSetFunctionControl::TransformationSetFunctionControl(
21     protobufs::TransformationSetFunctionControl message)
22     : message_(std::move(message)) {}
23 
TransformationSetFunctionControl(uint32_t function_id,uint32_t function_control)24 TransformationSetFunctionControl::TransformationSetFunctionControl(
25     uint32_t function_id, uint32_t function_control) {
26   message_.set_function_id(function_id);
27   message_.set_function_control(function_control);
28 }
29 
IsApplicable(opt::IRContext * ir_context,const TransformationContext &) const30 bool TransformationSetFunctionControl::IsApplicable(
31     opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
32   opt::Instruction* function_def_instruction =
33       FindFunctionDefInstruction(ir_context);
34   if (!function_def_instruction) {
35     // The given function id does not correspond to any function.
36     return false;
37   }
38   uint32_t existing_function_control_mask =
39       function_def_instruction->GetSingleWordInOperand(0);
40 
41   // Check (via an assertion) that function control mask doesn't have any bad
42   // bits set.
43   uint32_t acceptable_function_control_bits = uint32_t(
44       spv::FunctionControlMask::Inline | spv::FunctionControlMask::DontInline |
45       spv::FunctionControlMask::Pure | spv::FunctionControlMask::Const);
46   // The following is to keep release-mode compilers happy as this variable is
47   // only used in an assertion.
48   (void)(acceptable_function_control_bits);
49   assert(!(message_.function_control() & ~acceptable_function_control_bits) &&
50          "Nonsensical loop control bits were found.");
51 
52   // Check (via an assertion) that function control mask does not have both
53   // Inline and DontInline bits set.
54   assert(!((message_.function_control() &
55             (uint32_t)spv::FunctionControlMask::Inline) &&
56            (message_.function_control() &
57             (uint32_t)spv::FunctionControlMask::DontInline)) &&
58          "It is not OK to set both the 'Inline' and 'DontInline' bits of a "
59          "function control mask");
60 
61   // Check that Const and Pure are only present if they were present on the
62   // original function
63   for (auto mask_bit :
64        {spv::FunctionControlMask::Pure, spv::FunctionControlMask::Const}) {
65     if ((message_.function_control() & uint32_t(mask_bit)) &&
66         !(existing_function_control_mask & uint32_t(mask_bit))) {
67       return false;
68     }
69   }
70 
71   return true;
72 }
73 
Apply(opt::IRContext * ir_context,TransformationContext *) const74 void TransformationSetFunctionControl::Apply(
75     opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
76   opt::Instruction* function_def_instruction =
77       FindFunctionDefInstruction(ir_context);
78   function_def_instruction->SetInOperand(0, {message_.function_control()});
79 }
80 
ToMessage() const81 protobufs::Transformation TransformationSetFunctionControl::ToMessage() const {
82   protobufs::Transformation result;
83   *result.mutable_set_function_control() = message_;
84   return result;
85 }
86 
FindFunctionDefInstruction(opt::IRContext * ir_context) const87 opt::Instruction* TransformationSetFunctionControl ::FindFunctionDefInstruction(
88     opt::IRContext* ir_context) const {
89   // Look through all functions for a function whose defining instruction's
90   // result id matches |message_.function_id|, returning the defining
91   // instruction if found.
92   for (auto& function : *ir_context->module()) {
93     if (function.DefInst().result_id() == message_.function_id()) {
94       return &function.DefInst();
95     }
96   }
97   // A nullptr result indicates that no match was found.
98   return nullptr;
99 }
100 
GetFreshIds() const101 std::unordered_set<uint32_t> TransformationSetFunctionControl::GetFreshIds()
102     const {
103   return std::unordered_set<uint32_t>();
104 }
105 
106 }  // namespace fuzz
107 }  // namespace spvtools
108