• 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(const spvtools::fuzz::protobufs::TransformationSetFunctionControl & message)20 TransformationSetFunctionControl::TransformationSetFunctionControl(
21     const spvtools::fuzz::protobufs::TransformationSetFunctionControl& message)
22     : message_(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 =
44       SpvFunctionControlInlineMask | SpvFunctionControlDontInlineMask |
45       SpvFunctionControlPureMask | SpvFunctionControlConstMask;
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() & SpvFunctionControlInlineMask) &&
55            (message_.function_control() & SpvFunctionControlDontInlineMask)) &&
56          "It is not OK to set both the 'Inline' and 'DontInline' bits of a "
57          "function control mask");
58 
59   // Check that Const and Pure are only present if they were present on the
60   // original function
61   for (auto mask_bit :
62        {SpvFunctionControlPureMask, SpvFunctionControlConstMask}) {
63     if ((message_.function_control() & mask_bit) &&
64         !(existing_function_control_mask & mask_bit)) {
65       return false;
66     }
67   }
68 
69   return true;
70 }
71 
Apply(opt::IRContext * ir_context,TransformationContext *) const72 void TransformationSetFunctionControl::Apply(
73     opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
74   opt::Instruction* function_def_instruction =
75       FindFunctionDefInstruction(ir_context);
76   function_def_instruction->SetInOperand(0, {message_.function_control()});
77 }
78 
ToMessage() const79 protobufs::Transformation TransformationSetFunctionControl::ToMessage() const {
80   protobufs::Transformation result;
81   *result.mutable_set_function_control() = message_;
82   return result;
83 }
84 
FindFunctionDefInstruction(opt::IRContext * ir_context) const85 opt::Instruction* TransformationSetFunctionControl ::FindFunctionDefInstruction(
86     opt::IRContext* ir_context) const {
87   // Look through all functions for a function whose defining instruction's
88   // result id matches |message_.function_id|, returning the defining
89   // instruction if found.
90   for (auto& function : *ir_context->module()) {
91     if (function.DefInst().result_id() == message_.function_id()) {
92       return &function.DefInst();
93     }
94   }
95   // A nullptr result indicates that no match was found.
96   return nullptr;
97 }
98 
99 }  // namespace fuzz
100 }  // namespace spvtools
101