summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/asm2wasm.cpp128
-rw-r--r--src/wasm.h285
2 files changed, 181 insertions, 232 deletions
diff --git a/src/asm2wasm.cpp b/src/asm2wasm.cpp
index e20bbe5a1..609909ab8 100644
--- a/src/asm2wasm.cpp
+++ b/src/asm2wasm.cpp
@@ -224,14 +224,14 @@ class Asm2WasmModule : public wasm::Module {
unsigned maxGlobal; // highest address we can put a global
struct MappedGlobal {
unsigned address;
- BasicType type;
+ WasmType type;
bool import; // if true, this is an import - we should read the value, not just set a zero
MappedGlobal() : address(0), type(none), import(false) {}
- MappedGlobal(unsigned address, BasicType type, bool import) : address(address), type(type), import(import) {}
+ MappedGlobal(unsigned address, WasmType type, bool import) : address(address), type(type), import(import) {}
};
std::map<IString, MappedGlobal> mappedGlobals;
- void allocateGlobal(IString name, BasicType type, bool import) {
+ void allocateGlobal(IString name, WasmType type, bool import) {
assert(mappedGlobals.find(name) == mappedGlobals.end());
mappedGlobals.emplace(name, MappedGlobal(nextGlobal, type, import));
nextGlobal += 8;
@@ -293,7 +293,7 @@ class Asm2WasmModule : public wasm::Module {
}
}
- char getSigFromType(BasicType type) {
+ char getSigFromType(WasmType type) {
switch (type) {
case i32: return 'i';
case f64: return 'd';
@@ -304,7 +304,7 @@ class Asm2WasmModule : public wasm::Module {
FunctionType *getFunctionType(Ref parent, ExpressionList& operands) {
// generate signature
- BasicType result = detectWasmType(parent, nullptr);
+ WasmType result = detectWasmType(parent, nullptr);
std::string str = "FUNCSIG$";
str += getSigFromType(result);
for (auto operand : operands) {
@@ -332,19 +332,19 @@ public:
void optimize();
private:
- BasicType asmToWasmType(AsmType asmType) {
+ WasmType asmToWasmType(AsmType asmType) {
switch (asmType) {
- case ASM_INT: return BasicType::i32;
- case ASM_DOUBLE: return BasicType::f64;
- case ASM_NONE: return BasicType::none;
+ case ASM_INT: return WasmType::i32;
+ case ASM_DOUBLE: return WasmType::f64;
+ case ASM_NONE: return WasmType::none;
default: abort_on("confused asmType", asmType);
}
}
- AsmType wasmToAsmType(BasicType type) {
+ AsmType wasmToAsmType(WasmType type) {
switch (type) {
- case BasicType::i32: return ASM_INT;
- case BasicType::f64: return ASM_DOUBLE;
- case BasicType::none: return ASM_NONE;
+ case WasmType::i32: return ASM_INT;
+ case WasmType::f64: return ASM_DOUBLE;
+ case WasmType::none: return ASM_NONE;
default: abort_on("confused wasmType", type);
}
}
@@ -359,7 +359,7 @@ private:
return detectType(ast, data);
}
- BasicType detectWasmType(Ref ast, AsmData *data) {
+ WasmType detectWasmType(Ref ast, AsmData *data) {
return asmToWasmType(detectAsmType(ast, data));
}
@@ -381,18 +381,18 @@ private:
if (op == TRSHIFT) { binary = BinaryOp::ShrU; return true; }
if (op == EQ) { relational = RelationalOp::Eq; return false; }
if (op == NE) { relational = RelationalOp::Ne; return false; }
- BasicType leftType = detectWasmType(left, asmData);
+ WasmType leftType = detectWasmType(left, asmData);
#if 0
std::cout << "CHECK\n";
left->stringify(std::cout);
std::cout << " => ";
- printBasicType(std::cout, leftType);
+ printWasmType(std::cout, leftType);
std::cout << '\n';
right->stringify(std::cout);
std::cout << " => ";
- printBasicType(std::cout, detectWasmType(right, asmData));
+ printWasmType(std::cout, detectWasmType(right, asmData));
#endif
- bool isInteger = leftType == BasicType::i32;
+ bool isInteger = leftType == WasmType::i32;
bool isUnsigned = isUnsignedCoercion(left) || isUnsignedCoercion(right);
if (op == DIV) {
if (isInteger) {
@@ -473,7 +473,7 @@ void Asm2WasmModule::processAsm(Ref ast) {
Ref body = asmFunction[3];
assert(body[0][0] == STAT && body[0][1][0] == STRING && (body[0][1][1]->getIString() == IString("use asm") || body[0][1][1]->getIString() == IString("almost asm")));
- auto addImport = [&](IString name, Ref imported, BasicType type) {
+ auto addImport = [&](IString name, Ref imported, WasmType type) {
assert(imported[0] == DOT);
Ref module = imported[1];
if (module[0] == DOT) {
@@ -499,9 +499,9 @@ void Asm2WasmModule::processAsm(Ref ast) {
import.base = imported[2]->getIString();
// special-case some asm builtins
if (import.module == GLOBAL && (import.base == NAN_ || import.base == INFINITY_)) {
- type = BasicType::f64;
+ type = WasmType::f64;
}
- if (type != BasicType::none) {
+ if (type != WasmType::none) {
// wasm has no imported constants, so allocate a global, and we need to write the value into that
allocateGlobal(name, type, true);
} else {
@@ -522,12 +522,12 @@ void Asm2WasmModule::processAsm(Ref ast) {
if (value[0] == NUM) {
// global int
assert(value[1]->getNumber() == 0);
- allocateGlobal(name, BasicType::i32, false);
+ allocateGlobal(name, WasmType::i32, false);
} else if (value[0] == BINARY) {
// int import
assert(value[1] == OR && value[3][0] == NUM && value[3][1]->getNumber() == 0);
Ref import = value[2]; // env.what
- addImport(name, import, BasicType::i32);
+ addImport(name, import, WasmType::i32);
} else if (value[0] == UNARY_PREFIX) {
// double import or global
assert(value[1] == PLUS);
@@ -535,14 +535,14 @@ void Asm2WasmModule::processAsm(Ref ast) {
if (import[0] == NUM) {
// global
assert(import[1]->getNumber() == 0);
- allocateGlobal(name, BasicType::f64, false);
+ allocateGlobal(name, WasmType::f64, false);
} else {
// import
- addImport(name, import, BasicType::f64);
+ addImport(name, import, WasmType::f64);
}
} else if (value[0] == DOT) {
// function import
- addImport(name, value, BasicType::none);
+ addImport(name, value, WasmType::none);
} else if (value[0] == NEW) {
// ignore imports of typed arrays, but note the names of the arrays
value = value[1];
@@ -583,11 +583,11 @@ void Asm2WasmModule::processAsm(Ref ast) {
}
for (unsigned k = 0; k < contents->size(); k++) {
IString curr = contents[k][1]->getIString();
- if (table.vars.size() <= k) {
- table.vars.push_back(curr);
+ if (table.names.size() <= k) {
+ table.names.push_back(curr);
} else {
if (counts[curr] == 1) { // if just one appearance, not a null thunk
- table.vars[k] = curr;
+ table.names[k] = curr;
}
}
}
@@ -731,12 +731,12 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
assert(mappedGlobals.find(name) != mappedGlobals.end());
MappedGlobal global = mappedGlobals[name];
auto ret = allocator.alloc<Store>();
- ret->bytes = getBasicTypeSize(global.type);
+ ret->bytes = getWasmTypeSize(global.type);
ret->float_ = isFloat(global.type);
ret->offset = 0;
ret->align = ret->bytes;
auto ptr = allocator.alloc<Const>();
- ptr->value.type = BasicType::i32; // XXX for wasm64, need 64
+ ptr->value.type = WasmType::i32; // XXX for wasm64, need 64
ptr->value.i32 = global.address;
ret->ptr = ptr;
ret->value = process(ast[3]);
@@ -762,7 +762,7 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
} else if (what == BINARY) {
if (ast[1] == OR && ast[3][0] == NUM && ast[3][1]->getNumber() == 0) {
auto ret = process(ast[2]); // just look through the ()|0 coercion
- ret->type = BasicType::i32; // we add it here for e.g. call coercions
+ ret->type = WasmType::i32; // we add it here for e.g. call coercions
return ret;
}
BinaryOp binary;
@@ -786,10 +786,10 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
auto ret = allocator.alloc<Const>();
double num = ast[1]->getNumber();
if (isInteger32(num)) {
- ret->value.type = BasicType::i32;
+ ret->value.type = WasmType::i32;
ret->value.i32 = num;
} else {
- ret->value.type = BasicType::f64;
+ ret->value.type = WasmType::f64;
ret->value.f64 = num;
}
ret->type = ret->value.type;
@@ -807,13 +807,13 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
assert(mappedGlobals.find(name) != mappedGlobals.end());
MappedGlobal global = mappedGlobals[name];
auto ret = allocator.alloc<Load>();
- ret->bytes = getBasicTypeSize(global.type);
+ ret->bytes = getWasmTypeSize(global.type);
ret->signed_ = true; // but doesn't matter
ret->float_ = isFloat(global.type);
ret->offset = 0;
ret->align = ret->bytes;
auto ptr = allocator.alloc<Const>();
- ptr->value.type = BasicType::i32; // XXX for wasm64, need 64
+ ptr->value.type = WasmType::i32; // XXX for wasm64, need 64
ptr->value.i32 = global.address;
ret->ptr = ptr;
ret->type = global.type;
@@ -831,13 +831,13 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
ret->offset = 0;
ret->align = view.bytes;
ret->ptr = processUnshifted(ast[2], view.bytes);
- ret->type = getBasicType(view.bytes, !view.integer);
+ ret->type = getWasmType(view.bytes, !view.integer);
return ret;
} else if (what == UNARY_PREFIX) {
if (ast[1] == PLUS) {
if (ast[2][0] == NUM) {
auto ret = allocator.alloc<Const>();
- ret->value.type = BasicType::f64;
+ ret->value.type = WasmType::f64;
ret->value.f64 = ast[2][1]->getNumber();
ret->type = ret->value.type;
return ret;
@@ -847,12 +847,12 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
auto ret = allocator.alloc<Convert>();
ret->op = isUnsignedCoercion(ast[2]) ? ConvertUInt32 : ConvertSInt32;
ret->value = process(ast[2]);
- ret->type = BasicType::f64;
+ ret->type = WasmType::f64;
return ret;
}
assert(childType == ASM_NONE || childType == ASM_DOUBLE); // e.g. a coercion on a call or for a return
auto ret = process(ast[2]); // just look through the +() coercion
- ret->type = BasicType::f64; // we add it here for e.g. call coercions
+ ret->type = WasmType::f64; // we add it here for e.g. call coercions
return ret;
} else if (ast[1] == MINUS) {
if (ast[2][0] == NUM || (ast[2][0] == UNARY_PREFIX && ast[2][1] == PLUS && ast[2][2][0] == NUM)) {
@@ -868,14 +868,14 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
ret->op = Sub;
ret->left = allocator.alloc<Const>()->set(Literal((int32_t)0));
ret->right = process(ast[2]);
- ret->type = BasicType::i32;
+ ret->type = WasmType::i32;
return ret;
}
assert(asmType == ASM_DOUBLE);
auto ret = allocator.alloc<Unary>();
ret->op = Neg;
ret->value = process(ast[2]);
- ret->type = BasicType::f64;
+ ret->type = WasmType::f64;
return ret;
} else if (ast[1] == B_NOT) {
// ~, might be ~~ as a coercion or just a not
@@ -883,7 +883,7 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
auto ret = allocator.alloc<Convert>();
ret->op = TruncSFloat64; // equivalent to U, except for error handling, which asm.js doesn't have anyhow
ret->value = process(ast[2][2]);
- ret->type = BasicType::i32;
+ ret->type = WasmType::i32;
return ret;
}
// no bitwise unary not, so do xor with -1
@@ -891,7 +891,7 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
ret->op = Xor;
ret->left = process(ast[2]);
ret->right = allocator.alloc<Const>()->set(Literal(int32_t(-1)));
- ret->type = BasicType::i32;
+ ret->type = WasmType::i32;
return ret;
} else if (ast[1] == L_NOT) {
// no logical unary not, so do == 0
@@ -917,7 +917,7 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
ret->op = Mul;
ret->left = process(ast[2][0]);
ret->right = process(ast[2][1]);
- ret->type = BasicType::i32;
+ ret->type = WasmType::i32;
return ret;
}
if (name == Math_clz32) {
@@ -925,7 +925,7 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
auto ret = allocator.alloc<Unary>();
ret->op = Clz;
ret->value = process(ast[2][0]);
- ret->type = BasicType::i32;
+ ret->type = WasmType::i32;
return ret;
}
Call* ret;
@@ -962,7 +962,7 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
ret->type = getFunctionType(astStackHelper.getParent(), ret->operands);
return ret;
} else if (what == RETURN) {
- BasicType type = !!ast[1] ? detectWasmType(ast[1], &asmData) : none;
+ WasmType type = !!ast[1] ? detectWasmType(ast[1], &asmData) : none;
if (seenReturn) {
assert(function->result == type);
} else {
@@ -971,7 +971,7 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
// wasm has no return, so we just break on the topmost block
needTopmost = true;
auto ret = allocator.alloc<Break>();
- ret->var = TOPMOST;
+ ret->name = TOPMOST;
ret->condition = nullptr;
ret->value = !!ast[1] ? process(ast[1]) : nullptr;
return ret;
@@ -980,14 +980,14 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
} else if (what == BREAK) {
auto ret = allocator.alloc<Break>();
assert(breakStack.size() > 0);
- ret->var = !!ast[1] ? getBreakLabelName(ast[1]->getIString()) : breakStack.back();
+ ret->name = !!ast[1] ? getBreakLabelName(ast[1]->getIString()) : breakStack.back();
ret->condition = nullptr;
ret->value = nullptr;
return ret;
} else if (what == CONTINUE) {
auto ret = allocator.alloc<Break>();
assert(continueStack.size() > 0);
- ret->var = !!ast[1] ? getContinueLabelName(ast[1]->getIString()) : continueStack.back();
+ ret->name = !!ast[1] ? getContinueLabelName(ast[1]->getIString()) : continueStack.back();
ret->condition = nullptr;
ret->value = nullptr;
return ret;
@@ -1011,7 +1011,7 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
ret->body = process(ast[2]);
} else {
Break *continueWhile = allocator.alloc<Break>();
- continueWhile->var = in;
+ continueWhile->name = in;
continueWhile->condition = process(ast[1]);
continueWhile->value = nullptr;
auto body = allocator.alloc<Block>();
@@ -1033,7 +1033,7 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
} else {
stop = getNextId("do-once");
}
- block->var = stop;
+ block->name = stop;
breakStack.push_back(stop);
continueStack.push_back(IMPOSSIBLE_CONTINUE);
block->list.push_back(process(ast[2]));
@@ -1060,7 +1060,7 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
continueStack.pop_back();
breakStack.pop_back();
Break *continueIf = allocator.alloc<Break>();
- continueIf->var = in;
+ continueIf->name = in;
continueIf->condition = process(ast[1]);
continueIf->value = nullptr;
if (Block *block = dynamic_cast<Block*>(ret->body)) {
@@ -1094,7 +1094,7 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
IString name = getNextId("switch");
breakStack.push_back(name);
auto ret = allocator.alloc<Switch>();
- ret->var = name;
+ ret->name = name;
ret->value = process(ast[1]);
Ref cases = ast[2];
for (unsigned i = 0; i < cases->size(); i++) {
@@ -1130,7 +1130,7 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
unsigned addr = ptr[1]->getInteger();
unsigned shifted = addr << shifts;
auto ret = allocator.alloc<Const>();
- ret->value.type = BasicType::i32;
+ ret->value.type = WasmType::i32;
ret->value.i32 = shifted;
return (Expression*)ret;
}
@@ -1151,13 +1151,13 @@ Function* Asm2WasmModule::processFunction(Ref ast) {
function->body = processStatements(body, start);
if (needTopmost) {
Block* topmost = dynamic_cast<Block*>(function->body);
- // if there's no block there, or there is a block but it already has a var, we need a new block.
- if (!topmost || topmost->var.is()) {
+ // if there's no block there, or there is a block but it already has a name, we need a new block.
+ if (!topmost || topmost->name.is()) {
topmost = allocator.alloc<Block>();
topmost->list.push_back(function->body);
function->body = topmost;
}
- topmost->var = TOPMOST;
+ topmost->name = TOPMOST;
}
// cleanups/checks
assert(breakStack.size() == 0 && continueStack.size() == 0);
@@ -1172,10 +1172,10 @@ void Asm2WasmModule::optimize() {
Expression* walkBlock(Block *curr) override {
if (curr->list.size() != 1) return curr;
// just one element; maybe we can return just the element
- if (curr->var.isNull()) return curr->list[0];
+ if (curr->name.isNull()) return curr->list[0];
// we might be broken to, but if it's a trivial singleton child break, we can optimize here as well
Break *child = dynamic_cast<Break*>(curr->list[0]);
- if (!child || child->var != curr->var || !child->value) return curr;
+ if (!child || child->name != curr->name || !child->value) return curr;
struct BreakSeeker : public WasmWalker {
IString target; // look for this one
@@ -1184,12 +1184,12 @@ void Asm2WasmModule::optimize() {
BreakSeeker(IString target) : target(target), found(false) {}
Expression* walkBreak(Break *curr) override {
- if (curr->var == target) found++;
+ if (curr->name == target) found++;
}
};
- // look in the child's children to see if there are more uses of this var
- BreakSeeker breakSeeker(curr->var);
+ // look in the child's children to see if there are more uses of this name
+ BreakSeeker breakSeeker(curr->name);
breakSeeker.walk(child->condition);
breakSeeker.walk(child->value);
if (breakSeeker.found == 0) return child->value;
@@ -1257,7 +1257,7 @@ int main(int argc, char **argv) {
wasm.optimize();
if (debug) std::cerr << "printing...\n";
- wasm.print(std::cout);
+ std::cout << wasm;
if (debug) std::cerr << "done.\n";
}
diff --git a/src/wasm.h b/src/wasm.h
index f66f8bb8c..86bb91cc5 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -52,14 +52,15 @@ std::ostream &doIndent(std::ostream &o, unsigned indent) {
}
return o;
}
-void incIndent(std::ostream &o, unsigned& indent) {
+std::ostream &incIndent(std::ostream &o, unsigned& indent) {
o << '\n';
- indent++;
+ indent++;
+ return o;
}
-void decIndent(std::ostream &o, unsigned& indent) {
+std::ostream &decIndent(std::ostream &o, unsigned& indent) {
indent--;
doIndent(o, indent);
- o << ')';
+ return o << ')';
}
// Basics
@@ -69,16 +70,15 @@ struct Name : public cashew::IString {
Name(const char *str) : cashew::IString(str) {}
Name(cashew::IString str) : cashew::IString(str) {}
- std::ostream& print(std::ostream &o) {
- assert(str);
- o << '$' << str; // reference interpreter requires we prefix all names
- return o;
+ friend std::ostream& operator<<(std::ostream &o, Name name) {
+ assert(name.str);
+ return o << '$' << name.str; // reference interpreter requires we prefix all names
}
};
// Types
-enum BasicType {
+enum WasmType {
none,
i32,
i64,
@@ -86,28 +86,27 @@ enum BasicType {
f64
};
-std::ostream& printBasicType(std::ostream &o, BasicType type) {
+const char* printWasmType(WasmType type) {
switch (type) {
- case BasicType::none: o << "none"; break;
- case BasicType::i32: o << "i32"; break;
- case BasicType::i64: o << "i64"; break;
- case BasicType::f32: o << "f32"; break;
- case BasicType::f64: o << "f64"; break;
+ case WasmType::none: return "none";
+ case WasmType::i32: return "i32";
+ case WasmType::i64: return "i64";
+ case WasmType::f32: return "f32";
+ case WasmType::f64: return "f64";
}
- return o;
}
-unsigned getBasicTypeSize(BasicType type) {
+unsigned getWasmTypeSize(WasmType type) {
switch (type) {
- case BasicType::none: abort();
- case BasicType::i32: return 4;
- case BasicType::i64: return 8;
- case BasicType::f32: return 4;
- case BasicType::f64: return 8;
+ case WasmType::none: abort();
+ case WasmType::i32: return 4;
+ case WasmType::i64: return 8;
+ case WasmType::f32: return 4;
+ case WasmType::f64: return 8;
}
}
-bool isFloat(BasicType type) {
+bool isFloat(WasmType type) {
switch (type) {
case f32:
case f64: return true;
@@ -115,29 +114,33 @@ bool isFloat(BasicType type) {
return false;
}
-BasicType getBasicType(unsigned size, bool float_) {
- if (size < 4) return BasicType::i32;
- if (size == 4) return float_ ? BasicType::f32 : BasicType::i32;
- if (size == 8) return float_ ? BasicType::f64 : BasicType::i64;
+WasmType getWasmType(unsigned size, bool float_) {
+ if (size < 4) return WasmType::i32;
+ if (size == 4) return float_ ? WasmType::f32 : WasmType::i32;
+ if (size == 8) return float_ ? WasmType::f64 : WasmType::i64;
abort();
}
-void prepareMajorColor(std::ostream &o) {
+std::ostream &prepareMajorColor(std::ostream &o) {
Colors::red(o);
Colors::bold(o);
+ return o;
}
-void prepareColor(std::ostream &o) {
+std::ostream &prepareColor(std::ostream &o) {
Colors::magenta(o);
Colors::bold(o);
+ return o;
}
-void prepareMinorColor(std::ostream &o) {
+std::ostream &prepareMinorColor(std::ostream &o) {
Colors::orange(o);
+ return o;
}
-void restoreNormalColor(std::ostream &o) {
+std::ostream &restoreNormalColor(std::ostream &o) {
Colors::normal(o);
+ return o;
}
std::ostream& printText(std::ostream &o, const char *str) {
@@ -145,12 +148,11 @@ std::ostream& printText(std::ostream &o, const char *str) {
Colors::green(o);
o << str;
Colors::normal(o);
- o << '"';
- return o;
+ return o << '"';
}
struct Literal {
- BasicType type;
+ WasmType type;
union {
int32_t i32;
int64_t i64;
@@ -158,26 +160,24 @@ struct Literal {
double f64;
};
- Literal() : type(BasicType::none) {}
- Literal(int32_t init) : type(BasicType::i32), i32(init) {}
- Literal(int64_t init) : type(BasicType::i64), i64(init) {}
- Literal(float init) : type(BasicType::f32), f32(init) {}
- Literal(double init) : type(BasicType::f64), f64(init) {}
+ Literal() : type(WasmType::none) {}
+ Literal(int32_t init) : type(WasmType::i32), i32(init) {}
+ Literal(int64_t init) : type(WasmType::i64), i64(init) {}
+ Literal(float init) : type(WasmType::f32), f32(init) {}
+ Literal(double init) : type(WasmType::f64), f64(init) {}
- std::ostream& print(std::ostream &o) {
+ friend std::ostream& operator<<(std::ostream &o, Literal literal) {
o << '(';
- prepareMinorColor(o);
- printBasicType(o, type) << ".const ";
- switch (type) {
+ prepareMinorColor(o) << printWasmType(literal.type) << ".const ";
+ switch (literal.type) {
case none: abort();
- case BasicType::i32: o << i32; break;
- case BasicType::i64: o << i64; break;
- case BasicType::f32: o << JSPrinter::numToString(f32); break;
- case BasicType::f64: o << JSPrinter::numToString(f64); break;
+ case WasmType::i32: o << literal.i32; break;
+ case WasmType::i64: o << literal.i64; break;
+ case WasmType::f32: o << JSPrinter::numToString(literal.f32); break;
+ case WasmType::f64: o << JSPrinter::numToString(literal.f64); break;
}
restoreNormalColor(o);
- o << ')';
- return o;
+ return o << ')';
}
};
@@ -213,7 +213,7 @@ enum HostOp {
class Expression {
public:
- BasicType type;
+ WasmType type;
Expression() : type(type) {}
@@ -251,28 +251,25 @@ typedef std::vector<Expression*> ExpressionList; // TODO: optimize
class Nop : public Expression {
std::ostream& print(std::ostream &o, unsigned indent) override {
- printMinorOpening(o, "nop") << ')';
- return o;
+ return printMinorOpening(o, "nop") << ')';
}
};
class Block : public Expression {
public:
- Name var;
+ Name name;
ExpressionList list;
std::ostream& print(std::ostream &o, unsigned indent) override {
printOpening(o, "block");
- if (var.is()) {
- o << " ";
- var.print(o);
+ if (name.is()) {
+ o << ' ' << name;
}
incIndent(o, indent);
for (auto expression : list) {
printFullLine(o, indent, expression);
}
- decIndent(o, indent);
- return o;
+ return decIndent(o, indent);
}
};
@@ -286,8 +283,7 @@ public:
printFullLine(o, indent, condition);
printFullLine(o, indent, ifTrue);
if (ifFalse) printFullLine(o, indent, ifFalse);
- decIndent(o, indent);
- return o;
+ return decIndent(o, indent);
}
};
@@ -299,38 +295,33 @@ public:
std::ostream& print(std::ostream &o, unsigned indent) override {
printOpening(o, "loop");
if (out.is()) {
- o << " ";
- out.print(o);
+ o << ' ' << out;
if (in.is()) {
- o << " ";
- in.print(o);
- }
+ o << ' ' << in;
+ }
}
incIndent(o, indent);
printFullLine(o, indent, body);
- decIndent(o, indent);
- return o;
+ return decIndent(o, indent);
}
};
class Label : public Expression {
public:
- Name var;
+ Name name;
};
class Break : public Expression {
public:
- Name var;
+ Name name;
Expression *condition, *value;
std::ostream& print(std::ostream &o, unsigned indent) override {
- printOpening(o, "break ");
- var.print(o);
+ printOpening(o, "break ") << name;
incIndent(o, indent);
if (condition) printFullLine(o, indent, condition);
if (value) printFullLine(o, indent, value);
- decIndent(o, indent);
- return o;
+ return decIndent(o, indent);
}
};
@@ -342,19 +333,17 @@ public:
bool fallthru;
};
- Name var;
+ Name name;
Expression *value;
std::vector<Case> cases;
Expression *default_;
std::ostream& print(std::ostream &o, unsigned indent) override {
- printOpening(o, "switch ");
- var.print(o);
+ printOpening(o, "switch ") << name;
incIndent(o, indent);
printFullLine(o, indent, value);
o << "TODO: cases/default\n";
- decIndent(o, indent);
- return o;
+ return decIndent(o, indent);
}
};
@@ -365,7 +354,7 @@ public:
ExpressionList operands;
std::ostream& printBody(std::ostream &o, unsigned indent) {
- target.print(o);
+ o << target;
if (operands.size() > 0) {
incIndent(o, indent);
for (auto operand : operands) {
@@ -394,27 +383,24 @@ class CallImport : public Call {
class FunctionType {
public:
Name name;
- BasicType result;
- std::vector<BasicType> params;
+ WasmType result;
+ std::vector<WasmType> params;
std::ostream& print(std::ostream &o, unsigned indent, bool full=false) {
if (full) {
- printOpening(o, "type") << ' ';
- name.print(o) << " (func";
+ printOpening(o, "type") << ' ' << name << " (func";
}
if (params.size() > 0) {
o << ' ';
printMinorOpening(o, "param");
for (auto& param : params) {
- o << ' ';
- printBasicType(o, param);
+ o << ' ' << printWasmType(param);
}
o << ')';
}
if (result != none) {
o << ' ';
- printMinorOpening(o, "result ");
- printBasicType(o, result) << ')';
+ printMinorOpening(o, "result ") << printWasmType(result) << ')';
}
if (full) {
o << "))";;
@@ -443,15 +429,13 @@ public:
ExpressionList operands;
std::ostream& print(std::ostream &o, unsigned indent) override {
- printOpening(o, "call_indirect ");
- type->name.print(o);
+ printOpening(o, "call_indirect ") << type->name;
incIndent(o, indent);
printFullLine(o, indent, target);
for (auto operand : operands) {
printFullLine(o, indent, operand);
}
- decIndent(o, indent);
- return o;
+ return decIndent(o, indent);
}
};
@@ -460,9 +444,7 @@ public:
Name id;
std::ostream& print(std::ostream &o, unsigned indent) override {
- printOpening(o, "get_local ");
- id.print(o) << ')';
- return o;
+ return printOpening(o, "get_local ") << id << ')';
}
};
@@ -472,12 +454,10 @@ public:
Expression *value;
std::ostream& print(std::ostream &o, unsigned indent) override {
- printOpening(o, "set_local ");
- id.print(o);
+ printOpening(o, "set_local ") << id;
incIndent(o, indent);
printFullLine(o, indent, value);
- decIndent(o, indent);
- return o;
+ return decIndent(o, indent);
}
};
@@ -492,8 +472,7 @@ public:
std::ostream& print(std::ostream &o, unsigned indent) override {
o << '(';
- prepareColor(o);
- printBasicType(o, getBasicType(bytes, float_)) << ".load";
+ prepareColor(o) << printWasmType(getWasmType(bytes, float_)) << ".load";
if (bytes < 4) {
if (bytes == 1) {
o << '8';
@@ -509,8 +488,7 @@ public:
assert(!offset);
incIndent(o, indent);
printFullLine(o, indent, ptr);
- decIndent(o, indent);
- return o;
+ return decIndent(o, indent);
}
};
@@ -524,8 +502,7 @@ public:
std::ostream& print(std::ostream &o, unsigned indent) override {
o << '(';
- prepareColor(o);
- printBasicType(o, getBasicType(bytes, float_)) << ".store";
+ prepareColor(o) << printWasmType(getWasmType(bytes, float_)) << ".store";
if (bytes < 4) {
if (bytes == 1) {
o << '8';
@@ -541,8 +518,7 @@ public:
incIndent(o, indent);
printFullLine(o, indent, ptr);
printFullLine(o, indent, value);
- decIndent(o, indent);
- return o;
+ return decIndent(o, indent);
}
};
@@ -556,8 +532,7 @@ public:
}
std::ostream& print(std::ostream &o, unsigned indent) override {
- value.print(o);
- return o;
+ return o << value;
}
};
@@ -568,8 +543,7 @@ public:
std::ostream& print(std::ostream &o, unsigned indent) override {
o << '(';
- prepareColor(o);
- printBasicType(o, type) << '.';
+ prepareColor(o) << printWasmType(type) << '.';
switch (op) {
case Clz: o << "clz"; break;
case Neg: o << "neg"; break;
@@ -578,8 +552,7 @@ public:
}
incIndent(o, indent);
printFullLine(o, indent, value);
- decIndent(o, indent);
- return o;
+ return decIndent(o, indent);
}
};
@@ -590,8 +563,7 @@ public:
std::ostream& print(std::ostream &o, unsigned indent) override {
o << '(';
- prepareColor(o);
- printBasicType(o, type) << '.';
+ prepareColor(o) << printWasmType(type) << '.';
switch (op) {
case Add: o << "add"; break;
case Sub: o << "sub"; break;
@@ -616,8 +588,7 @@ public:
incIndent(o, indent);
printFullLine(o, indent, left);
printFullLine(o, indent, right);
- decIndent(o, indent);
- return o;
+ return decIndent(o, indent);
}
};
@@ -627,13 +598,12 @@ public:
Expression *left, *right;
Compare() {
- type = BasicType::i32;
+ type = WasmType::i32;
}
std::ostream& print(std::ostream &o, unsigned indent) override {
o << '(';
- prepareColor(o);
- printBasicType(o, type) << '.';
+ prepareColor(o) << printWasmType(type) << '.';
switch (op) {
case Eq: o << "eq"; break;
case Ne: o << "ne"; break;
@@ -655,8 +625,7 @@ public:
incIndent(o, indent);
printFullLine(o, indent, left);
printFullLine(o, indent, right);
- decIndent(o, indent);
- return o;
+ return decIndent(o, indent);
}
};
@@ -667,8 +636,7 @@ public:
std::ostream& print(std::ostream &o, unsigned indent) override {
o << '(';
- prepareColor(o);
- printBasicType(o, type) << ".convert_";
+ prepareColor(o) << printWasmType(type) << ".convert_";
switch (op) {
case ConvertUInt32: o << "u/i32"; break;
case ConvertSInt32: o << "s/i32"; break;
@@ -678,8 +646,7 @@ public:
restoreNormalColor(o);
incIndent(o, indent);
printFullLine(o, indent, value);
- decIndent(o, indent);
- return o;
+ return decIndent(o, indent);
}
};
@@ -693,45 +660,38 @@ public:
struct NameType {
Name name;
- BasicType type;
+ WasmType type;
NameType() : name(nullptr), type(none) {}
- NameType(Name name, BasicType type) : name(name), type(type) {}
+ NameType(Name name, WasmType type) : name(name), type(type) {}
};
class Function {
public:
Name name;
- BasicType result;
+ WasmType result;
std::vector<NameType> params;
std::vector<NameType> locals;
Expression *body;
std::ostream& print(std::ostream &o, unsigned indent) {
- printOpening(o, "func ", true);
- name.print(o);
+ printOpening(o, "func ", true) << name;
if (params.size() > 0) {
for (auto& param : params) {
o << ' ';
- printMinorOpening(o, "param ");
- param.name.print(o) << " ";
- printBasicType(o, param.type) << ")";
+ printMinorOpening(o, "param ") << param.name << ' ' << printWasmType(param.type) << ")";
}
}
if (result != none) {
o << ' ';
- printMinorOpening(o, "result ");
- printBasicType(o, result) << ")";
+ printMinorOpening(o, "result ") << printWasmType(result) << ")";
}
incIndent(o, indent);
for (auto& local : locals) {
doIndent(o, indent);
- printMinorOpening(o, "local ");
- local.name.print(o) << " ";
- printBasicType(o, local.type) << ")\n";
+ printMinorOpening(o, "local ") << local.name << ' ' << printWasmType(local.type) << ")\n";
}
printFullLine(o, indent, body);
- decIndent(o, indent);
- return o;
+ return decIndent(o, indent);
}
};
@@ -741,13 +701,11 @@ public:
FunctionType type;
std::ostream& print(std::ostream &o, unsigned indent) {
- printOpening(o, "import ");
- name.print(o) << ' ';
+ printOpening(o, "import ") << name << ' ';
printText(o, module.str) << ' ';
printText(o, base.str) << ' ';
type.print(o, indent);
- o << ')';
- return o;
+ return o << ')';
}
};
@@ -757,26 +715,21 @@ public:
Name value;
std::ostream& print(std::ostream &o, unsigned indent) {
- printOpening(o, "export") << ' ';
- printText(o, name.str) << ' ';
- value.print(o);
- o << ')';
- return o;
+ printOpening(o, "export ");
+ return printText(o, name.str) << ' ' << value << ')';
}
};
class Table {
public:
- std::vector<Name> vars;
+ std::vector<Name> names;
std::ostream& print(std::ostream &o, unsigned indent) {
printOpening(o, "table");
- for (auto var : vars) {
- o << ' ';
- var.print(o);
+ for (auto name : names) {
+ o << ' ' << name;
}
- o << ')';
- return o;
+ return o << ')';
}
};
@@ -789,48 +742,44 @@ protected:
Table table;
std::vector<Function*> functions;
- // internals
- std::map<Name, void*> map; // maps var ids/names to things
- unsigned nextVar;
-
public:
- Module() : nextVar(1) {}
+ Module() {}
- std::ostream& print(std::ostream &o) {
+ friend std::ostream& operator<<(std::ostream &o, Module module) {
unsigned indent = 0;
printOpening(o, "module", true);
incIndent(o, indent);
doIndent(o, indent);
printOpening(o, "memory") << " 16777216)\n"; // XXX
- for (auto& curr : functionTypes) {
+ for (auto& curr : module.functionTypes) {
doIndent(o, indent);
curr.second->print(o, indent, true);
o << '\n';
}
#if 0
- for (auto& curr : imports) {
+ for (auto& curr : module.imports) {
doIndent(o, indent);
curr.second.print(o, indent);
o << '\n';
}
#endif
- for (auto& curr : exports) {
+ for (auto& curr : module.exports) {
doIndent(o, indent);
curr.print(o, indent);
o << '\n';
}
- if (table.vars.size() > 0) {
+ if (module.table.names.size() > 0) {
doIndent(o, indent);
- table.print(o, indent);
+ module.table.print(o, indent);
o << '\n';
}
- for (auto& curr : functions) {
+ for (auto& curr : module.functions) {
doIndent(o, indent);
curr->print(o, indent);
o << '\n';
}
decIndent(o, indent);
- o << '\n';
+ return o << '\n';
}
};