]>
git.proxmox.com Git - rustc.git/blob - src/binaryen/src/ir/ExpressionManipulator.cpp
2 * Copyright 2017 WebAssembly Community Group participants
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "support/hash.h"
22 namespace ExpressionManipulator
{
24 Expression
* flexibleCopy(Expression
* original
, Module
& wasm
, CustomCopier custom
) {
25 struct Copier
: public Visitor
<Copier
, Expression
*> {
31 Copier(Module
& wasm
, CustomCopier custom
) : wasm(wasm
), custom(custom
), builder(wasm
) {}
33 Expression
* copy(Expression
* curr
) {
34 if (!curr
) return nullptr;
35 auto* ret
= custom(curr
);
37 return Visitor
<Copier
, Expression
*>::visit(curr
);
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
]));
45 return builder
.makeBlock(curr
->name
, list
, curr
->type
);
47 Expression
* visitIf(If
*curr
) {
48 return builder
.makeIf(copy(curr
->condition
), copy(curr
->ifTrue
), copy(curr
->ifFalse
), curr
->type
);
50 Expression
* visitLoop(Loop
*curr
) {
51 return builder
.makeLoop(curr
->name
, copy(curr
->body
));
53 Expression
* visitBreak(Break
*curr
) {
54 return builder
.makeBreak(curr
->name
, copy(curr
->value
), copy(curr
->condition
));
56 Expression
* visitSwitch(Switch
*curr
) {
57 return builder
.makeSwitch(curr
->targets
, curr
->default_
, copy(curr
->condition
), copy(curr
->value
));
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
]));
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
]));
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
]));
80 Expression
* visitGetLocal(GetLocal
*curr
) {
81 return builder
.makeGetLocal(curr
->index
, curr
->type
);
83 Expression
* visitSetLocal(SetLocal
*curr
) {
85 return builder
.makeTeeLocal(curr
->index
, copy(curr
->value
));
87 return builder
.makeSetLocal(curr
->index
, copy(curr
->value
));
90 Expression
* visitGetGlobal(GetGlobal
*curr
) {
91 return builder
.makeGetGlobal(curr
->name
, curr
->type
);
93 Expression
* visitSetGlobal(SetGlobal
*curr
) {
94 return builder
.makeSetGlobal(curr
->name
, copy(curr
->value
));
96 Expression
* visitLoad(Load
*curr
) {
98 return builder
.makeAtomicLoad(curr
->bytes
, curr
->offset
,
99 copy(curr
->ptr
), curr
->type
);
101 return builder
.makeLoad(curr
->bytes
, curr
->signed_
, curr
->offset
, curr
->align
, copy(curr
->ptr
), curr
->type
);
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
);
107 return builder
.makeStore(curr
->bytes
, curr
->offset
, curr
->align
, copy(curr
->ptr
), copy(curr
->value
), curr
->valueType
);
109 Expression
* visitAtomicRMW(AtomicRMW
* curr
) {
110 return builder
.makeAtomicRMW(curr
->op
, curr
->bytes
, curr
->offset
,
111 copy(curr
->ptr
), copy(curr
->value
), curr
->type
);
113 Expression
* visitAtomicCmpxchg(AtomicCmpxchg
* curr
) {
114 return builder
.makeAtomicCmpxchg(curr
->bytes
, curr
->offset
,
115 copy(curr
->ptr
), copy(curr
->expected
), copy(curr
->replacement
),
118 Expression
* visitAtomicWait(AtomicWait
* curr
) {
119 return builder
.makeAtomicWait(copy(curr
->ptr
), copy(curr
->expected
), copy(curr
->timeout
), curr
->expectedType
);
121 Expression
* visitAtomicWake(AtomicWake
* curr
) {
122 return builder
.makeAtomicWake(copy(curr
->ptr
), copy(curr
->wakeCount
));
124 Expression
* visitConst(Const
*curr
) {
125 return builder
.makeConst(curr
->value
);
127 Expression
* visitUnary(Unary
*curr
) {
128 return builder
.makeUnary(curr
->op
, copy(curr
->value
));
130 Expression
* visitBinary(Binary
*curr
) {
131 return builder
.makeBinary(curr
->op
, copy(curr
->left
), copy(curr
->right
));
133 Expression
* visitSelect(Select
*curr
) {
134 return builder
.makeSelect(copy(curr
->condition
), copy(curr
->ifTrue
), copy(curr
->ifFalse
));
136 Expression
* visitDrop(Drop
*curr
) {
137 return builder
.makeDrop(copy(curr
->value
));
139 Expression
* visitReturn(Return
*curr
) {
140 return builder
.makeReturn(copy(curr
->value
));
142 Expression
* visitHost(Host
*curr
) {
143 assert(curr
->operands
.size() == 0);
144 return builder
.makeHost(curr
->op
, curr
->nameOperand
, {});
146 Expression
* visitNop(Nop
*curr
) {
147 return builder
.makeNop();
149 Expression
* visitUnreachable(Unreachable
*curr
) {
150 return builder
.makeUnreachable();
154 Copier
copier(wasm
, custom
);
155 return copier
.copy(original
);
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
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];
172 block
->finalize(block
->type
);
175 } // namespace ExpressionManipulator