diff options
Diffstat (limited to 'src/wasm.h')
-rw-r--r-- | src/wasm.h | 90 |
1 files changed, 71 insertions, 19 deletions
diff --git a/src/wasm.h b/src/wasm.h index ec2cd469e..7422dd85d 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -503,6 +503,20 @@ public: default: WASM_UNREACHABLE(); } } + Literal rotL(const Literal& other) const { + switch (type) { + case WasmType::i32: return Literal(RotateLeft(uint32_t(i32), uint32_t(other.i32))); + case WasmType::i64: return Literal(RotateLeft(uint64_t(i64), uint64_t(other.i64))); + default: WASM_UNREACHABLE(); + } + } + Literal rotR(const Literal& other) const { + switch (type) { + case WasmType::i32: return Literal(RotateRight(uint32_t(i32), uint32_t(other.i32))); + case WasmType::i64: return Literal(RotateRight(uint64_t(i64), uint64_t(other.i64))); + default: WASM_UNREACHABLE(); + } + } Literal eq(const Literal& other) const { switch (type) { @@ -669,6 +683,8 @@ public: enum UnaryOp { Clz, Ctz, Popcnt, // int Neg, Abs, Ceil, Floor, Trunc, Nearest, Sqrt, // float + // relational + EqZ, // conversions ExtendSInt32, ExtendUInt32, WrapInt64, TruncSFloat32, TruncUFloat32, TruncSFloat64, TruncUFloat64, ReinterpretFloat, // int ConvertSInt32, ConvertUInt32, ConvertSInt64, ConvertUInt64, PromoteFloat32, DemoteFloat64, ReinterpretInt // float @@ -676,7 +692,7 @@ enum UnaryOp { enum BinaryOp { Add, Sub, Mul, // int or float - DivS, DivU, RemS, RemU, And, Or, Xor, Shl, ShrU, ShrS, // int + DivS, DivU, RemS, RemU, And, Or, Xor, Shl, ShrU, ShrS, RotL, RotR, // int Div, CopySign, Min, Max, // float // relational ops Eq, Ne, // int or float @@ -794,6 +810,12 @@ public: Name name; ExpressionList list; + + void finalize() { + if (list.size() > 0) { + type = list.back()->type; + } + } }; class If : public Expression { @@ -836,20 +858,14 @@ public: class Switch : public Expression { public: - Switch() : Expression(SwitchId) {} - - struct Case { - Name name; - Expression *body; - Case() {} - Case(Name name, Expression *body) : name(name), body(body) {} - }; + Switch() : Expression(SwitchId), condition(nullptr), value(nullptr) { + type = unreachable; + } - Name name; - Expression *value; std::vector<Name> targets; Name default_; - std::vector<Case> cases; + Expression *condition; + Expression *value; }; class CallBase : public Expression { @@ -958,6 +974,11 @@ public: UnaryOp op; Expression *value; + + // the type is always the type of the operands, + // except for relationals + + bool isRelational() { return op == EqZ; } }; class Binary : public Expression { @@ -1074,6 +1095,8 @@ public: class Memory { public: + static const size_t kPageSize = 64 * 1024; + static const size_t kPageMask = ~(kPageSize - 1); struct Segment { size_t offset; const char* data; @@ -1082,8 +1105,9 @@ public: Segment(size_t offset, const char *data, size_t size) : offset(offset), data(data), size(size) {} }; - size_t initial, max; + size_t initial, max; // sizes are in pages std::vector<Segment> segments; + Name exportName; Memory() : initial(0), max((uint32_t)-1) {} }; @@ -1108,7 +1132,7 @@ public: Module() : functionTypeIndex(0), importIndex(0), exportIndex(0), functionIndex(0) {} void addFunctionType(FunctionType* curr) { - Name numericName = Name::fromInt(functionTypeIndex); + Name numericName = Name::fromInt(functionTypeIndex); // TODO: remove all these, assert on names already existing, do numeric stuff in wasm-s-parser etc. if (curr->name.isNull()) { curr->name = numericName; } @@ -1282,10 +1306,8 @@ struct ChildWalker : public WasmWalkerBase<ChildWalker<ParentType>> { parent.walk(curr->value); } void visitSwitch(Switch *curr) { - parent.walk(curr->value); - for (auto& case_ : curr->cases) { - parent.walk(case_.body); - } + parent.walk(curr->condition); + if (curr->value) parent.walk(curr->value); } void visitCall(Call *curr) { ExpressionList& list = curr->operands; @@ -1394,7 +1416,37 @@ struct WasmWalker : public WasmWalkerBase<SubType, ReturnType> { void walk(Expression*& curr) override { if (!curr) return; - ChildWalker<WasmWalker<SubType, ReturnType>>(*this).visit(curr); + // special-case Block, because Block nesting (in their first element) can be incredibly deep + if (curr->is<Block>()) { + auto* block = curr->dyn_cast<Block>(); + std::vector<Block*> stack; + stack.push_back(block); + while (block->list.size() > 0 && block->list[0]->is<Block>()) { + block = block->list[0]->cast<Block>(); + stack.push_back(block); + } + // walk all the children + for (int i = int(stack.size()) - 1; i >= 0; i--) { + auto* block = stack[i]; + auto& children = block->list; + for (size_t j = 0; j < children.size(); j++) { + if (i < int(stack.size()) - 1 && j == 0) { + // this is one of the stacked blocks, no need to walk its children, we are doing that ourselves + this->visit(children[0]); + if (replace) { + children[0] = replace; + replace = nullptr; + } + } else { + this->walk(children[j]); + } + } + } + // we walked all the children, and can rejoin later below to visit this node itself + } else { + // generic child-walking + ChildWalker<WasmWalker<SubType, ReturnType>>(*this).visit(curr); + } this->visit(curr); |