blob: 57048b9bd495b033b71982e08c755732cbc16eaf [file] [log] [blame] [edit]
/*
* 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) {
struct Copier : public OverriddenVisitor<Copier, Expression*> {
Module& wasm;
CustomCopier custom;
Builder builder;
Copier(Module& wasm, CustomCopier custom)
: wasm(wasm), custom(custom), builder(wasm) {}
Expression* copy(Expression* curr) {
if (!curr) {
return nullptr;
}
auto* ret = custom(curr);
if (ret) {
return ret;
}
return OverriddenVisitor<Copier, Expression*>::visit(curr);
}
Expression* visitBlock(Block* curr) {
ExpressionList list(wasm.allocator);
for (Index i = 0; i < curr->list.size(); i++) {
list.push_back(copy(curr->list[i]));
}
return builder.makeBlock(curr->name, list, curr->type);
}
Expression* visitIf(If* curr) {
return builder.makeIf(copy(curr->condition),
copy(curr->ifTrue),
copy(curr->ifFalse),
curr->type);
}
Expression* visitLoop(Loop* curr) {
return builder.makeLoop(curr->name, copy(curr->body), curr->type);
}
Expression* visitBreak(Break* curr) {
return builder.makeBreak(
curr->name, copy(curr->value), copy(curr->condition));
}
Expression* visitSwitch(Switch* curr) {
return builder.makeSwitch(curr->targets,
curr->default_,
copy(curr->condition),
copy(curr->value));
}
Expression* visitCall(Call* curr) {
auto* ret =
builder.makeCall(curr->target, {}, curr->type, curr->isReturn);
for (Index i = 0; i < curr->operands.size(); i++) {
ret->operands.push_back(copy(curr->operands[i]));
}
return ret;
}
Expression* visitCallIndirect(CallIndirect* curr) {
std::vector<Expression*> copiedOps;
for (auto op : curr->operands) {
copiedOps.push_back(copy(op));
}
return builder.makeCallIndirect(
copy(curr->target), copiedOps, curr->sig, curr->isReturn);
}
Expression* visitLocalGet(LocalGet* curr) {
return builder.makeLocalGet(curr->index, curr->type);
}
Expression* visitLocalSet(LocalSet* curr) {
if (curr->isTee()) {
return builder.makeLocalTee(curr->index, copy(curr->value), curr->type);
} else {
return builder.makeLocalSet(curr->index, copy(curr->value));
}
}
Expression* visitGlobalGet(GlobalGet* curr) {
return builder.makeGlobalGet(curr->name, curr->type);
}
Expression* visitGlobalSet(GlobalSet* curr) {
return builder.makeGlobalSet(curr->name, copy(curr->value));
}
Expression* visitLoad(Load* curr) {
if (curr->isAtomic) {
return builder.makeAtomicLoad(
curr->bytes, curr->offset, copy(curr->ptr), curr->type);
}
return builder.makeLoad(curr->bytes,
LoadUtils::isSignRelevant(curr) ? curr->signed_
: false,
curr->offset,
curr->align,
copy(curr->ptr),
curr->type);
}
Expression* visitStore(Store* curr) {
if (curr->isAtomic) {
return builder.makeAtomicStore(curr->bytes,
curr->offset,
copy(curr->ptr),
copy(curr->value),
curr->valueType);
}
return builder.makeStore(curr->bytes,
curr->offset,
curr->align,
copy(curr->ptr),
copy(curr->value),
curr->valueType);
}
Expression* visitAtomicRMW(AtomicRMW* curr) {
return builder.makeAtomicRMW(curr->op,
curr->bytes,
curr->offset,
copy(curr->ptr),
copy(curr->value),
curr->type);
}
Expression* visitAtomicCmpxchg(AtomicCmpxchg* curr) {
return builder.makeAtomicCmpxchg(curr->bytes,
curr->offset,
copy(curr->ptr),
copy(curr->expected),
copy(curr->replacement),
curr->type);
}
Expression* visitAtomicWait(AtomicWait* curr) {
return builder.makeAtomicWait(copy(curr->ptr),
copy(curr->expected),
copy(curr->timeout),
curr->expectedType,
curr->offset);
}
Expression* visitAtomicNotify(AtomicNotify* curr) {
return builder.makeAtomicNotify(
copy(curr->ptr), copy(curr->notifyCount), curr->offset);
}
Expression* visitAtomicFence(AtomicFence* curr) {
return builder.makeAtomicFence();
}
Expression* visitSIMDExtract(SIMDExtract* curr) {
return builder.makeSIMDExtract(curr->op, copy(curr->vec), curr->index);
}
Expression* visitSIMDReplace(SIMDReplace* curr) {
return builder.makeSIMDReplace(
curr->op, copy(curr->vec), curr->index, copy(curr->value));
}
Expression* visitSIMDShuffle(SIMDShuffle* curr) {
return builder.makeSIMDShuffle(
copy(curr->left), copy(curr->right), curr->mask);
}
Expression* visitSIMDTernary(SIMDTernary* curr) {
return builder.makeSIMDTernary(
curr->op, copy(curr->a), copy(curr->b), copy(curr->c));
}
Expression* visitSIMDShift(SIMDShift* curr) {
return builder.makeSIMDShift(
curr->op, copy(curr->vec), copy(curr->shift));
}
Expression* visitSIMDLoad(SIMDLoad* curr) {
return builder.makeSIMDLoad(
curr->op, curr->offset, curr->align, copy(curr->ptr));
}
Expression* visitConst(Const* curr) {
return builder.makeConst(curr->value);
}
Expression* visitMemoryInit(MemoryInit* curr) {
return builder.makeMemoryInit(
curr->segment, copy(curr->dest), copy(curr->offset), copy(curr->size));
}
Expression* visitDataDrop(DataDrop* curr) {
return builder.makeDataDrop(curr->segment);
}
Expression* visitMemoryCopy(MemoryCopy* curr) {
return builder.makeMemoryCopy(
copy(curr->dest), copy(curr->source), copy(curr->size));
}
Expression* visitMemoryFill(MemoryFill* curr) {
return builder.makeMemoryFill(
copy(curr->dest), copy(curr->value), copy(curr->size));
}
Expression* visitUnary(Unary* curr) {
return builder.makeUnary(curr->op, copy(curr->value));
}
Expression* visitBinary(Binary* curr) {
return builder.makeBinary(curr->op, copy(curr->left), copy(curr->right));
}
Expression* visitSelect(Select* curr) {
return builder.makeSelect(copy(curr->condition),
copy(curr->ifTrue),
copy(curr->ifFalse),
curr->type);
}
Expression* visitDrop(Drop* curr) {
return builder.makeDrop(copy(curr->value));
}
Expression* visitReturn(Return* curr) {
return builder.makeReturn(copy(curr->value));
}
Expression* visitHost(Host* curr) {
std::vector<Expression*> operands;
for (Index i = 0; i < curr->operands.size(); i++) {
operands.push_back(copy(curr->operands[i]));
}
auto* ret =
builder.makeHost(curr->op, curr->nameOperand, std::move(operands));
return ret;
}
Expression* visitRefNull(RefNull* curr) { return builder.makeRefNull(); }
Expression* visitRefIsNull(RefIsNull* curr) {
return builder.makeRefIsNull(copy(curr->value));
}
Expression* visitRefFunc(RefFunc* curr) {
return builder.makeRefFunc(curr->func);
}
Expression* visitTry(Try* curr) {
return builder.makeTry(
copy(curr->body), copy(curr->catchBody), curr->type);
}
Expression* visitThrow(Throw* curr) {
std::vector<Expression*> operands;
for (Index i = 0; i < curr->operands.size(); i++) {
operands.push_back(copy(curr->operands[i]));
}
return builder.makeThrow(curr->event, std::move(operands));
}
Expression* visitRethrow(Rethrow* curr) {
return builder.makeRethrow(copy(curr->exnref));
}
Expression* visitBrOnExn(BrOnExn* curr) {
return builder.makeBrOnExn(
curr->name, curr->event, copy(curr->exnref), curr->sent);
}
Expression* visitNop(Nop* curr) { return builder.makeNop(); }
Expression* visitUnreachable(Unreachable* curr) {
return builder.makeUnreachable();
}
Expression* visitPop(Pop* curr) { return builder.makePop(curr->type); }
Expression* visitTupleMake(TupleMake* curr) {
std::vector<Expression*> operands;
for (auto* op : curr->operands) {
operands.push_back(copy(op));
}
return builder.makeTupleMake(std::move(operands));
}
Expression* visitTupleExtract(TupleExtract* curr) {
return builder.makeTupleExtract(copy(curr->tuple), curr->index);
}
};
Copier copier(wasm, custom);
return copier.copy(original);
}
// 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