1 /*
2  * Copyright 2017 WebAssembly Community Group participants
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef wasm_ir_block_h
18 #define wasm_ir_block_h
19 
20 #include "ir/branch-utils.h"
21 #include "ir/effects.h"
22 #include "ir/manipulation.h"
23 #include "literal.h"
24 #include "wasm-builder.h"
25 #include "wasm.h"
26 
27 namespace wasm {
28 
29 namespace BlockUtils {
30 // if a block has just one element, it can often be replaced
31 // with that content
32 template<typename T>
33 inline Expression*
34 simplifyToContents(Block* block, T* parent, bool allowTypeChange = false) {
35   auto& list = block->list;
36   if (list.size() == 1 &&
37       !BranchUtils::BranchSeeker::has(list[0], block->name)) {
38     // just one element. try to replace the block
39     auto* singleton = list[0];
40     auto sideEffects = EffectAnalyzer(parent->getPassOptions(),
41                                       parent->getModule()->features,
42                                       singleton)
43                          .hasSideEffects();
44     if (!sideEffects && !singleton->type.isConcrete()) {
45       // no side effects, and singleton is not returning a value, so we can
46       // throw away the block and its contents, basically
47       return Builder(*parent->getModule()).replaceWithIdenticalType(block);
48     } else if (Type::isSubType(singleton->type, block->type) ||
49                allowTypeChange) {
50       return singleton;
51     } else {
52       // (side effects +) type change, must be block with declared value but
53       // inside is unreachable (if both concrete, must match, and since no name
54       // on block, we can't be branched to, so if singleton is unreachable, so
55       // is the block)
56       assert(block->type.isConcrete() && singleton->type == Type::unreachable);
57       // we could replace with unreachable, but would need to update all
58       // the parent's types
59     }
60   } else if (list.size() == 0) {
61     ExpressionManipulator::nop(block);
62   }
63   return block;
64 }
65 
66 // similar, but when we allow the type to change while doing so
67 template<typename T>
simplifyToContentsWithPossibleTypeChange(Block * block,T * parent)68 inline Expression* simplifyToContentsWithPossibleTypeChange(Block* block,
69                                                             T* parent) {
70   return simplifyToContents(block, parent, true);
71 }
72 } // namespace BlockUtils
73 
74 } // namespace wasm
75 
76 #endif // wasm_ir_block_h
77