summaryrefslogtreecommitdiff
path: root/src/wasm.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm.h')
-rw-r--r--src/wasm.h90
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);