]> git.proxmox.com Git - rustc.git/blob - src/binaryen/src/ir/ExpressionManipulator.cpp
New upstream version 1.23.0+dfsg1
[rustc.git] / src / binaryen / src / ir / ExpressionManipulator.cpp
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 #include "ir/utils.h"
18 #include "support/hash.h"
19
20 namespace wasm {
21
22 namespace ExpressionManipulator {
23
24 Expression* flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) {
25 struct Copier : public Visitor<Copier, Expression*> {
26 Module& wasm;
27 CustomCopier custom;
28
29 Builder builder;
30
31 Copier(Module& wasm, CustomCopier custom) : wasm(wasm), custom(custom), builder(wasm) {}
32
33 Expression* copy(Expression* curr) {
34 if (!curr) return nullptr;
35 auto* ret = custom(curr);
36 if (ret) return ret;
37 return Visitor<Copier, Expression*>::visit(curr);
38 }
39
40 Expression* visitBlock(Block *curr) {
41 ExpressionList list(wasm.allocator);
42 for (Index i = 0; i < curr->list.size(); i++) {
43 list.push_back(copy(curr->list[i]));
44 }
45 return builder.makeBlock(curr->name, list, curr->type);
46 }
47 Expression* visitIf(If *curr) {
48 return builder.makeIf(copy(curr->condition), copy(curr->ifTrue), copy(curr->ifFalse), curr->type);
49 }
50 Expression* visitLoop(Loop *curr) {
51 return builder.makeLoop(curr->name, copy(curr->body));
52 }
53 Expression* visitBreak(Break *curr) {
54 return builder.makeBreak(curr->name, copy(curr->value), copy(curr->condition));
55 }
56 Expression* visitSwitch(Switch *curr) {
57 return builder.makeSwitch(curr->targets, curr->default_, copy(curr->condition), copy(curr->value));
58 }
59 Expression* visitCall(Call *curr) {
60 auto* ret = builder.makeCall(curr->target, {}, curr->type);
61 for (Index i = 0; i < curr->operands.size(); i++) {
62 ret->operands.push_back(copy(curr->operands[i]));
63 }
64 return ret;
65 }
66 Expression* visitCallImport(CallImport *curr) {
67 auto* ret = builder.makeCallImport(curr->target, {}, curr->type);
68 for (Index i = 0; i < curr->operands.size(); i++) {
69 ret->operands.push_back(copy(curr->operands[i]));
70 }
71 return ret;
72 }
73 Expression* visitCallIndirect(CallIndirect *curr) {
74 auto* ret = builder.makeCallIndirect(curr->fullType, copy(curr->target), {}, curr->type);
75 for (Index i = 0; i < curr->operands.size(); i++) {
76 ret->operands.push_back(copy(curr->operands[i]));
77 }
78 return ret;
79 }
80 Expression* visitGetLocal(GetLocal *curr) {
81 return builder.makeGetLocal(curr->index, curr->type);
82 }
83 Expression* visitSetLocal(SetLocal *curr) {
84 if (curr->isTee()) {
85 return builder.makeTeeLocal(curr->index, copy(curr->value));
86 } else {
87 return builder.makeSetLocal(curr->index, copy(curr->value));
88 }
89 }
90 Expression* visitGetGlobal(GetGlobal *curr) {
91 return builder.makeGetGlobal(curr->name, curr->type);
92 }
93 Expression* visitSetGlobal(SetGlobal *curr) {
94 return builder.makeSetGlobal(curr->name, copy(curr->value));
95 }
96 Expression* visitLoad(Load *curr) {
97 if (curr->isAtomic) {
98 return builder.makeAtomicLoad(curr->bytes, curr->offset,
99 copy(curr->ptr), curr->type);
100 }
101 return builder.makeLoad(curr->bytes, curr->signed_, curr->offset, curr->align, copy(curr->ptr), curr->type);
102 }
103 Expression* visitStore(Store *curr) {
104 if (curr->isAtomic) {
105 return builder.makeAtomicStore(curr->bytes, curr->offset, copy(curr->ptr), copy(curr->value), curr->valueType);
106 }
107 return builder.makeStore(curr->bytes, curr->offset, curr->align, copy(curr->ptr), copy(curr->value), curr->valueType);
108 }
109 Expression* visitAtomicRMW(AtomicRMW* curr) {
110 return builder.makeAtomicRMW(curr->op, curr->bytes, curr->offset,
111 copy(curr->ptr), copy(curr->value), curr->type);
112 }
113 Expression* visitAtomicCmpxchg(AtomicCmpxchg* curr) {
114 return builder.makeAtomicCmpxchg(curr->bytes, curr->offset,
115 copy(curr->ptr), copy(curr->expected), copy(curr->replacement),
116 curr->type);
117 }
118 Expression* visitAtomicWait(AtomicWait* curr) {
119 return builder.makeAtomicWait(copy(curr->ptr), copy(curr->expected), copy(curr->timeout), curr->expectedType);
120 }
121 Expression* visitAtomicWake(AtomicWake* curr) {
122 return builder.makeAtomicWake(copy(curr->ptr), copy(curr->wakeCount));
123 }
124 Expression* visitConst(Const *curr) {
125 return builder.makeConst(curr->value);
126 }
127 Expression* visitUnary(Unary *curr) {
128 return builder.makeUnary(curr->op, copy(curr->value));
129 }
130 Expression* visitBinary(Binary *curr) {
131 return builder.makeBinary(curr->op, copy(curr->left), copy(curr->right));
132 }
133 Expression* visitSelect(Select *curr) {
134 return builder.makeSelect(copy(curr->condition), copy(curr->ifTrue), copy(curr->ifFalse));
135 }
136 Expression* visitDrop(Drop *curr) {
137 return builder.makeDrop(copy(curr->value));
138 }
139 Expression* visitReturn(Return *curr) {
140 return builder.makeReturn(copy(curr->value));
141 }
142 Expression* visitHost(Host *curr) {
143 assert(curr->operands.size() == 0);
144 return builder.makeHost(curr->op, curr->nameOperand, {});
145 }
146 Expression* visitNop(Nop *curr) {
147 return builder.makeNop();
148 }
149 Expression* visitUnreachable(Unreachable *curr) {
150 return builder.makeUnreachable();
151 }
152 };
153
154 Copier copier(wasm, custom);
155 return copier.copy(original);
156 }
157
158
159 // Splice an item into the middle of a block's list
160 void spliceIntoBlock(Block* block, Index index, Expression* add) {
161 auto& list = block->list;
162 if (index == list.size()) {
163 list.push_back(add); // simple append
164 } else {
165 // we need to make room
166 list.push_back(nullptr);
167 for (Index i = list.size() - 1; i > index; i--) {
168 list[i] = list[i - 1];
169 }
170 list[index] = add;
171 }
172 block->finalize(block->type);
173 }
174
175 } // namespace ExpressionManipulator
176
177 } // namespace wasm