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 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_DEAD_BLOCK_H_
16 #define SOURCE_FUZZ_TRANSFORMATION_ADD_DEAD_BLOCK_H_
17 
18 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
19 #include "source/fuzz/transformation.h"
20 #include "source/fuzz/transformation_context.h"
21 #include "source/opt/ir_context.h"
22 
23 namespace spvtools {
24 namespace fuzz {
25 
26 class TransformationAddDeadBlock : public Transformation {
27  public:
28   explicit TransformationAddDeadBlock(
29       const protobufs::TransformationAddDeadBlock& message);
30 
31   TransformationAddDeadBlock(uint32_t fresh_id, uint32_t existing_block,
32                              bool condition_value);
33 
34   // - |message_.fresh_id| must be a fresh id
35   // - A constant with the same value as |message_.condition_value| must be
36   //   available
37   // - |message_.existing_block| must be a block that is not a loop header,
38   //   and that ends with OpBranch to a block that is not a merge block nor
39   //   continue target - this is because the successor will become the merge
40   //   block of a selection construct headed at |message_.existing_block|
41   // - |message_.existing_block| must not be a back-edge block, since in this
42   //   case the newly-added block would lead to another back-edge to the
43   //   associated loop header
44   bool IsApplicable(
45       opt::IRContext* ir_context,
46       const TransformationContext& transformation_context) const override;
47 
48   // Changes the OpBranch from |message_.existing_block| to its successor 's'
49   // to an OpBranchConditional to either 's' or a new block,
50   // |message_.fresh_id|, which itself unconditionally branches to 's'.  The
51   // conditional branch uses |message.condition_value| as its condition, and is
52   // arranged so that control will pass to 's' at runtime.
53   void Apply(opt::IRContext* ir_context,
54              TransformationContext* transformation_context) const override;
55 
56   std::unordered_set<uint32_t> GetFreshIds() const override;
57 
58   protobufs::Transformation ToMessage() const override;
59 
60  private:
61   protobufs::TransformationAddDeadBlock message_;
62 };
63 
64 }  // namespace fuzz
65 }  // namespace spvtools
66 
67 #endif  // SOURCE_FUZZ_TRANSFORMATION_ADD_DEAD_BLOCK_H_
68