1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
/*
* Copyright 2017 WebAssembly Community Group participants
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ir/load-utils.h"
#include "ir/utils.h"
namespace wasm::ExpressionManipulator {
Expression*
flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) {
// Perform the copy using a stack of tasks (avoiding recusion).
struct CopyTask {
// The thing to copy.
Expression* original;
// The location of the pointer to write the copy to.
Expression** destPointer;
};
std::vector<CopyTask> tasks;
Expression* ret;
tasks.push_back({original, &ret});
while (!tasks.empty()) {
auto task = tasks.back();
tasks.pop_back();
// If the custom copier handled this one, we have nothing to do.
auto* copy = custom(task.original);
if (copy) {
*task.destPointer = copy;
continue;
}
// If the original is a null, just copy that. (This can happen for an
// optional child.)
auto* original = task.original;
if (original == nullptr) {
*task.destPointer = nullptr;
continue;
}
// Allocate a new copy, and copy the fields.
#define DELEGATE_ID original->_id
// Allocate a new expression of the right type, and create cast versions of it
// for later operations.
#define DELEGATE_START(id) \
copy = wasm.allocator.alloc<id>(); \
auto* castOriginal = original->cast<id>(); \
WASM_UNUSED(castOriginal); \
auto* castCopy = copy->cast<id>(); \
WASM_UNUSED(castCopy);
// Handle each type of field, copying it appropriately.
#define DELEGATE_FIELD_CHILD(id, field) \
tasks.push_back({castOriginal->field, &castCopy->field});
#define DELEGATE_FIELD_CHILD_VECTOR(id, field) \
castCopy->field.resize(castOriginal->field.size()); \
for (Index i = 0; i < castOriginal->field.size(); i++) { \
tasks.push_back({castOriginal->field[i], &castCopy->field[i]}); \
}
#define COPY_FIELD(field) castCopy->field = castOriginal->field;
#define DELEGATE_FIELD_INT(id, field) COPY_FIELD(field)
#define DELEGATE_FIELD_LITERAL(id, field) COPY_FIELD(field)
#define DELEGATE_FIELD_NAME(id, field) COPY_FIELD(field)
#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, field) COPY_FIELD(field)
#define DELEGATE_FIELD_SCOPE_NAME_USE(id, field) COPY_FIELD(field)
#define DELEGATE_FIELD_TYPE(id, field) COPY_FIELD(field)
#define DELEGATE_FIELD_HEAPTYPE(id, field) COPY_FIELD(field)
#define DELEGATE_FIELD_ADDRESS(id, field) COPY_FIELD(field)
#define COPY_FIELD_LIST(field) \
for (Index i = 0; i < castOriginal->field.size(); i++) { \
castCopy->field[i] = castOriginal->field[i]; \
}
#define COPY_VECTOR(field) \
castCopy->field.resize(castOriginal->field.size()); \
COPY_FIELD_LIST(field)
#define COPY_ARRAY(field) \
assert(castCopy->field.size() == castOriginal->field.size()); \
COPY_FIELD_LIST(field)
#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, field) COPY_VECTOR(field)
#define DELEGATE_FIELD_NAME_VECTOR(id, field) COPY_VECTOR(field)
#define DELEGATE_FIELD_INT_ARRAY(id, field) COPY_ARRAY(field)
#include "wasm-delegations-fields.def"
// The type can be simply copied.
copy->type = original->type;
// Write the copy to where it should be referred to.
*task.destPointer = copy;
}
return ret;
}
// Splice an item into the middle of a block's list
void spliceIntoBlock(Block* block, Index index, Expression* add) {
block->list.insertAt(index, add);
block->finalize(block->type);
}
} // namespace wasm::ExpressionManipulator
|