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