/* * 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 { namespace 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 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(); \ auto* castOriginal = original->cast(); \ WASM_UNUSED(castOriginal); \ auto* castCopy = copy->cast(); \ WASM_UNUSED(castCopy); // Handle each type of field, copying it appropriately. #define DELEGATE_FIELD_CHILD(id, name) \ tasks.push_back({castOriginal->name, &castCopy->name}); #define DELEGATE_FIELD_CHILD_VECTOR(id, name) \ castCopy->name.resize(castOriginal->name.size()); \ for (Index i = 0; i < castOriginal->name.size(); i++) { \ tasks.push_back({castOriginal->name[i], &castCopy->name[i]}); \ } #define COPY_FIELD(name) castCopy->name = castOriginal->name; #define DELEGATE_FIELD_INT(id, name) COPY_FIELD(name) #define DELEGATE_FIELD_LITERAL(id, name) COPY_FIELD(name) #define DELEGATE_FIELD_NAME(id, name) COPY_FIELD(name) #define DELEGATE_FIELD_SCOPE_NAME_DEF(id, name) COPY_FIELD(name) #define DELEGATE_FIELD_SCOPE_NAME_USE(id, name) COPY_FIELD(name) #define DELEGATE_FIELD_SIGNATURE(id, name) COPY_FIELD(name) #define DELEGATE_FIELD_TYPE(id, name) COPY_FIELD(name) #define DELEGATE_FIELD_ADDRESS(id, name) COPY_FIELD(name) #define COPY_FIELD_LIST(name) \ for (Index i = 0; i < castOriginal->name.size(); i++) { \ castCopy->name[i] = castOriginal->name[i]; \ } #define COPY_VECTOR(name) \ castCopy->name.resize(castOriginal->name.size()); \ COPY_FIELD_LIST(name) #define COPY_ARRAY(name) \ assert(castCopy->name.size() == castOriginal->name.size()); \ COPY_FIELD_LIST(name) #define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, name) COPY_VECTOR(name) #define DELEGATE_FIELD_NAME_VECTOR(id, name) COPY_VECTOR(name) #define DELEGATE_FIELD_INT_ARRAY(id, name) COPY_ARRAY(name) #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) { auto& list = block->list; if (index == list.size()) { list.push_back(add); // simple append } else { // we need to make room list.push_back(nullptr); for (Index i = list.size() - 1; i > index; i--) { list[i] = list[i - 1]; } list[index] = add; } block->finalize(block->type); } } // namespace ExpressionManipulator } // namespace wasm