@@ -23,306 +23,91 @@ namespace ExpressionManipulator {
23
23
24
24
Expression*
25
25
flexibleCopy (Expression* original, Module& wasm, CustomCopier custom) {
26
- struct Copier : public OverriddenVisitor <Copier, Expression*> {
27
- Module& wasm;
28
- CustomCopier custom;
26
+ // Perform the copy using a stack of tasks (avoiding recusion).
27
+ struct CopyTask {
28
+ // The thing to copy.
29
+ Expression* original;
30
+ // The location of the pointer to write the copy to.
31
+ Expression** destPointer;
32
+ };
33
+ std::vector<CopyTask> tasks;
34
+ Expression* ret;
35
+ tasks.push_back ({original, &ret});
36
+ while (!tasks.empty ()) {
37
+ auto task = tasks.back ();
38
+ tasks.pop_back ();
39
+ // If the custom copier handled this one, we have nothing to do.
40
+ auto * copy = custom (task.original );
41
+ if (copy) {
42
+ *task.destPointer = copy;
43
+ continue ;
44
+ }
45
+ // If the original is a null, just copy that. (This can happen for an
46
+ // optional child.)
47
+ auto * original = task.original ;
48
+ if (original == nullptr ) {
49
+ *task.destPointer = nullptr ;
50
+ continue ;
51
+ }
52
+ // Allocate a new copy, and copy the fields.
29
53
30
- Builder builder;
54
+ # define DELEGATE_ID original->_id
31
55
32
- Copier (Module& wasm, CustomCopier custom)
33
- : wasm(wasm), custom(custom), builder(wasm) {}
56
+ // Allocate a new expression of the right type, and create cast versions of it
57
+ // for later operations.
58
+ #define DELEGATE_START (id ) \
59
+ copy = wasm.allocator .alloc <id>(); \
60
+ auto * castOriginal = original->cast <id>(); \
61
+ WASM_UNUSED (castOriginal); \
62
+ auto * castCopy = copy->cast <id>(); \
63
+ WASM_UNUSED (castCopy);
34
64
35
- Expression* copy (Expression* curr) {
36
- if (!curr) {
37
- return nullptr ;
38
- }
39
- auto * ret = custom (curr);
40
- if (ret) {
41
- return ret;
42
- }
43
- return OverriddenVisitor<Copier, Expression*>::visit (curr);
44
- }
65
+ // Handle each type of field, copying it appropriately.
66
+ #define DELEGATE_FIELD_CHILD (id, name ) \
67
+ tasks.push_back ({castOriginal->name , &castCopy->name });
45
68
46
- Expression* visitBlock (Block* curr) {
47
- ExpressionList list (wasm.allocator );
48
- for (Index i = 0 ; i < curr->list .size (); i++) {
49
- list.push_back (copy (curr->list [i]));
50
- }
51
- return builder.makeBlock (curr->name , list, curr->type );
52
- }
53
- Expression* visitIf (If* curr) {
54
- return builder.makeIf (copy (curr->condition ),
55
- copy (curr->ifTrue ),
56
- copy (curr->ifFalse ),
57
- curr->type );
58
- }
59
- Expression* visitLoop (Loop* curr) {
60
- return builder.makeLoop (curr->name , copy (curr->body ), curr->type );
61
- }
62
- Expression* visitBreak (Break* curr) {
63
- return builder.makeBreak (
64
- curr->name , copy (curr->value ), copy (curr->condition ));
65
- }
66
- Expression* visitSwitch (Switch* curr) {
67
- return builder.makeSwitch (curr->targets ,
68
- curr->default_ ,
69
- copy (curr->condition ),
70
- copy (curr->value ));
71
- }
72
- Expression* visitCall (Call* curr) {
73
- auto * ret =
74
- builder.makeCall (curr->target , {}, curr->type , curr->isReturn );
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* visitCallIndirect (CallIndirect* curr) {
81
- std::vector<Expression*> copiedOps;
82
- for (auto op : curr->operands ) {
83
- copiedOps.push_back (copy (op));
84
- }
85
- return builder.makeCallIndirect (
86
- copy (curr->target ), copiedOps, curr->sig , curr->isReturn );
87
- }
88
- Expression* visitLocalGet (LocalGet* curr) {
89
- return builder.makeLocalGet (curr->index , curr->type );
90
- }
91
- Expression* visitLocalSet (LocalSet* curr) {
92
- if (curr->isTee ()) {
93
- return builder.makeLocalTee (curr->index , copy (curr->value ), curr->type );
94
- } else {
95
- return builder.makeLocalSet (curr->index , copy (curr->value ));
96
- }
97
- }
98
- Expression* visitGlobalGet (GlobalGet* curr) {
99
- return builder.makeGlobalGet (curr->name , curr->type );
100
- }
101
- Expression* visitGlobalSet (GlobalSet* curr) {
102
- return builder.makeGlobalSet (curr->name , copy (curr->value ));
103
- }
104
- Expression* visitLoad (Load* curr) {
105
- if (curr->isAtomic ) {
106
- return builder.makeAtomicLoad (
107
- curr->bytes , curr->offset , copy (curr->ptr ), curr->type );
108
- }
109
- return builder.makeLoad (curr->bytes ,
110
- LoadUtils::isSignRelevant (curr) ? curr->signed_
111
- : false ,
112
- curr->offset ,
113
- curr->align ,
114
- copy (curr->ptr ),
115
- curr->type );
116
- }
117
- Expression* visitStore (Store* curr) {
118
- if (curr->isAtomic ) {
119
- return builder.makeAtomicStore (curr->bytes ,
120
- curr->offset ,
121
- copy (curr->ptr ),
122
- copy (curr->value ),
123
- curr->valueType );
124
- }
125
- return builder.makeStore (curr->bytes ,
126
- curr->offset ,
127
- curr->align ,
128
- copy (curr->ptr ),
129
- copy (curr->value ),
130
- curr->valueType );
131
- }
132
- Expression* visitAtomicRMW (AtomicRMW* curr) {
133
- return builder.makeAtomicRMW (curr->op ,
134
- curr->bytes ,
135
- curr->offset ,
136
- copy (curr->ptr ),
137
- copy (curr->value ),
138
- curr->type );
139
- }
140
- Expression* visitAtomicCmpxchg (AtomicCmpxchg* curr) {
141
- return builder.makeAtomicCmpxchg (curr->bytes ,
142
- curr->offset ,
143
- copy (curr->ptr ),
144
- copy (curr->expected ),
145
- copy (curr->replacement ),
146
- curr->type );
147
- }
148
- Expression* visitAtomicWait (AtomicWait* curr) {
149
- return builder.makeAtomicWait (copy (curr->ptr ),
150
- copy (curr->expected ),
151
- copy (curr->timeout ),
152
- curr->expectedType ,
153
- curr->offset );
154
- }
155
- Expression* visitAtomicNotify (AtomicNotify* curr) {
156
- return builder.makeAtomicNotify (
157
- copy (curr->ptr ), copy (curr->notifyCount ), curr->offset );
158
- }
159
- Expression* visitAtomicFence (AtomicFence* curr) {
160
- return builder.makeAtomicFence ();
161
- }
162
- Expression* visitSIMDExtract (SIMDExtract* curr) {
163
- return builder.makeSIMDExtract (curr->op , copy (curr->vec ), curr->index );
164
- }
165
- Expression* visitSIMDReplace (SIMDReplace* curr) {
166
- return builder.makeSIMDReplace (
167
- curr->op , copy (curr->vec ), curr->index , copy (curr->value ));
168
- }
169
- Expression* visitSIMDShuffle (SIMDShuffle* curr) {
170
- return builder.makeSIMDShuffle (
171
- copy (curr->left ), copy (curr->right ), curr->mask );
172
- }
173
- Expression* visitSIMDTernary (SIMDTernary* curr) {
174
- return builder.makeSIMDTernary (
175
- curr->op , copy (curr->a ), copy (curr->b ), copy (curr->c ));
176
- }
177
- Expression* visitSIMDShift (SIMDShift* curr) {
178
- return builder.makeSIMDShift (
179
- curr->op , copy (curr->vec ), copy (curr->shift ));
180
- }
181
- Expression* visitSIMDLoad (SIMDLoad* curr) {
182
- return builder.makeSIMDLoad (
183
- curr->op , curr->offset , curr->align , copy (curr->ptr ));
184
- }
185
- Expression* visitSIMDLoadStoreLane (SIMDLoadStoreLane* curr) {
186
- return builder.makeSIMDLoadStoreLane (curr->op ,
187
- curr->offset ,
188
- curr->align ,
189
- curr->index ,
190
- copy (curr->ptr ),
191
- copy (curr->vec ));
192
- }
193
- Expression* visitConst (Const* curr) {
194
- return builder.makeConst (curr->value );
195
- }
196
- Expression* visitMemoryInit (MemoryInit* curr) {
197
- return builder.makeMemoryInit (
198
- curr->segment , copy (curr->dest ), copy (curr->offset ), copy (curr->size ));
199
- }
200
- Expression* visitDataDrop (DataDrop* curr) {
201
- return builder.makeDataDrop (curr->segment );
202
- }
203
- Expression* visitMemoryCopy (MemoryCopy* curr) {
204
- return builder.makeMemoryCopy (
205
- copy (curr->dest ), copy (curr->source ), copy (curr->size ));
206
- }
207
- Expression* visitMemoryFill (MemoryFill* curr) {
208
- return builder.makeMemoryFill (
209
- copy (curr->dest ), copy (curr->value ), copy (curr->size ));
210
- }
211
- Expression* visitUnary (Unary* curr) {
212
- return builder.makeUnary (curr->op , copy (curr->value ));
213
- }
214
- Expression* visitBinary (Binary* curr) {
215
- return builder.makeBinary (curr->op , copy (curr->left ), copy (curr->right ));
216
- }
217
- Expression* visitSelect (Select* curr) {
218
- return builder.makeSelect (copy (curr->condition ),
219
- copy (curr->ifTrue ),
220
- copy (curr->ifFalse ),
221
- curr->type );
222
- }
223
- Expression* visitDrop (Drop* curr) {
224
- return builder.makeDrop (copy (curr->value ));
225
- }
226
- Expression* visitReturn (Return* curr) {
227
- return builder.makeReturn (copy (curr->value ));
228
- }
229
- Expression* visitMemorySize (MemorySize* curr) {
230
- return builder.makeMemorySize ();
231
- }
232
- Expression* visitMemoryGrow (MemoryGrow* curr) {
233
- return builder.makeMemoryGrow (copy (curr->delta ));
234
- }
235
- Expression* visitRefNull (RefNull* curr) {
236
- return builder.makeRefNull (curr->type );
237
- }
238
- Expression* visitRefIsNull (RefIsNull* curr) {
239
- return builder.makeRefIsNull (copy (curr->value ));
240
- }
241
- Expression* visitRefFunc (RefFunc* curr) {
242
- return builder.makeRefFunc (curr->func );
243
- }
244
- Expression* visitRefEq (RefEq* curr) {
245
- return builder.makeRefEq (copy (curr->left ), copy (curr->right ));
246
- }
247
- Expression* visitTry (Try* curr) {
248
- return builder.makeTry (
249
- copy (curr->body ), copy (curr->catchBody ), curr->type );
250
- }
251
- Expression* visitThrow (Throw* curr) {
252
- std::vector<Expression*> operands;
253
- for (Index i = 0 ; i < curr->operands .size (); i++) {
254
- operands.push_back (copy (curr->operands [i]));
255
- }
256
- return builder.makeThrow (curr->event , std::move (operands));
257
- }
258
- Expression* visitRethrow (Rethrow* curr) {
259
- return builder.makeRethrow (copy (curr->exnref ));
260
- }
261
- Expression* visitBrOnExn (BrOnExn* curr) {
262
- return builder.makeBrOnExn (
263
- curr->name , curr->event , copy (curr->exnref ), curr->sent );
264
- }
265
- Expression* visitNop (Nop* curr) { return builder.makeNop (); }
266
- Expression* visitUnreachable (Unreachable* curr) {
267
- return builder.makeUnreachable ();
268
- }
269
- Expression* visitPop (Pop* curr) { return builder.makePop (curr->type ); }
270
- Expression* visitTupleMake (TupleMake* curr) {
271
- std::vector<Expression*> operands;
272
- for (auto * op : curr->operands ) {
273
- operands.push_back (copy (op));
274
- }
275
- return builder.makeTupleMake (std::move (operands));
276
- }
277
- Expression* visitTupleExtract (TupleExtract* curr) {
278
- return builder.makeTupleExtract (copy (curr->tuple ), curr->index );
279
- }
280
- Expression* visitI31New (I31New* curr) {
281
- return builder.makeI31New (copy (curr->value ));
282
- }
283
- Expression* visitI31Get (I31Get* curr) {
284
- return builder.makeI31Get (copy (curr->i31 ), curr->signed_ );
285
- }
286
- Expression* visitRefTest (RefTest* curr) {
287
- WASM_UNREACHABLE (" TODO (gc): ref.test" );
288
- }
289
- Expression* visitRefCast (RefCast* curr) {
290
- WASM_UNREACHABLE (" TODO (gc): ref.cast" );
291
- }
292
- Expression* visitBrOnCast (BrOnCast* curr) {
293
- WASM_UNREACHABLE (" TODO (gc): br_on_cast" );
294
- }
295
- Expression* visitRttCanon (RttCanon* curr) {
296
- WASM_UNREACHABLE (" TODO (gc): rtt.canon" );
297
- }
298
- Expression* visitRttSub (RttSub* curr) {
299
- WASM_UNREACHABLE (" TODO (gc): rtt.sub" );
300
- }
301
- Expression* visitStructNew (StructNew* curr) {
302
- WASM_UNREACHABLE (" TODO (gc): struct.new" );
303
- }
304
- Expression* visitStructGet (StructGet* curr) {
305
- WASM_UNREACHABLE (" TODO (gc): struct.get" );
306
- }
307
- Expression* visitStructSet (StructSet* curr) {
308
- WASM_UNREACHABLE (" TODO (gc): struct.set" );
309
- }
310
- Expression* visitArrayNew (ArrayNew* curr) {
311
- WASM_UNREACHABLE (" TODO (gc): array.new" );
312
- }
313
- Expression* visitArrayGet (ArrayGet* curr) {
314
- WASM_UNREACHABLE (" TODO (gc): array.get" );
315
- }
316
- Expression* visitArraySet (ArraySet* curr) {
317
- WASM_UNREACHABLE (" TODO (gc): array.set" );
318
- }
319
- Expression* visitArrayLen (ArrayLen* curr) {
320
- WASM_UNREACHABLE (" TODO (gc): array.len" );
321
- }
322
- };
69
+ #define DELEGATE_FIELD_CHILD_VECTOR (id, name ) \
70
+ castCopy->name .resize (castOriginal->name .size ()); \
71
+ for (Index i = 0 ; i < castOriginal->name .size (); i++) { \
72
+ tasks.push_back ({castOriginal->name [i], &castCopy->name [i]}); \
73
+ }
74
+
75
+ #define COPY_FIELD (name ) castCopy->name = castOriginal->name;
76
+
77
+ #define DELEGATE_FIELD_INT (id, name ) COPY_FIELD(name)
78
+ #define DELEGATE_FIELD_LITERAL (id, name ) COPY_FIELD(name)
79
+ #define DELEGATE_FIELD_NAME (id, name ) COPY_FIELD(name)
80
+ #define DELEGATE_FIELD_SCOPE_NAME (id, name ) COPY_FIELD(name)
81
+ #define DELEGATE_FIELD_SIGNATURE (id, name ) COPY_FIELD(name)
82
+ #define DELEGATE_FIELD_TYPE (id, name ) COPY_FIELD(name)
83
+ #define DELEGATE_FIELD_ADDRESS (id, name ) COPY_FIELD(name)
323
84
324
- Copier copier (wasm, custom);
325
- return copier.copy (original);
85
+ #define COPY_FIELD_LIST (name ) \
86
+ for (Index i = 0 ; i < castOriginal->name .size (); i++) { \
87
+ castCopy->name [i] = castOriginal->name [i]; \
88
+ }
89
+
90
+ #define COPY_VECTOR (name ) \
91
+ castCopy->name .resize (castOriginal->name .size ()); \
92
+ COPY_FIELD_LIST (name)
93
+
94
+ #define COPY_ARRAY (name ) \
95
+ assert (castCopy->name .size () == castOriginal->name .size ()); \
96
+ COPY_FIELD_LIST (name)
97
+
98
+ #define DELEGATE_FIELD_SCOPE_NAME_VECTOR (id, name ) COPY_VECTOR(name)
99
+
100
+ #define DELEGATE_FIELD_INT_ARRAY (id, name ) COPY_ARRAY(name)
101
+
102
+ #include " wasm-delegations-fields.h"
103
+
104
+ // The type can be simply copied.
105
+ copy->type = original->type ;
106
+
107
+ // Write the copy to where it should be referred to.
108
+ *task.destPointer = copy;
109
+ }
110
+ return ret;
326
111
}
327
112
328
113
// Splice an item into the middle of a block's list
0 commit comments