diff options
author | Alon Zakai <alonzakai@gmail.com> | 2016-01-04 14:27:46 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2016-01-04 14:27:56 -0800 |
commit | c6d08d97c196e2ceae5e3b960befcd6c66916cad (patch) | |
tree | 89c27cee4f213fd66f6e60ce9b267d53a2c00b00 | |
parent | 5e82fc26d6bb0cec8863156e052250a4e441595c (diff) | |
download | binaryen-c6d08d97c196e2ceae5e3b960befcd6c66916cad.tar.gz binaryen-c6d08d97c196e2ceae5e3b960befcd6c66916cad.tar.bz2 binaryen-c6d08d97c196e2ceae5e3b960befcd6c66916cad.zip |
parse for loops in asm2wasm #60
-rw-r--r-- | src/asm2wasm-main.cpp | 5 | ||||
-rw-r--r-- | src/asm2wasm.h | 43 | ||||
-rw-r--r-- | src/emscripten-optimizer/parser.h | 21 | ||||
-rw-r--r-- | src/emscripten-optimizer/simple_ast.h | 14 | ||||
-rw-r--r-- | test/unit.asm.js | 8 | ||||
-rw-r--r-- | test/unit.fromasm | 30 |
6 files changed, 119 insertions, 2 deletions
diff --git a/src/asm2wasm-main.cpp b/src/asm2wasm-main.cpp index 0edd82c2f..6a784bd76 100644 --- a/src/asm2wasm-main.cpp +++ b/src/asm2wasm-main.cpp @@ -54,6 +54,11 @@ int main(int argc, char **argv) { if (debug) std::cerr << "parsing...\n"; cashew::Parser<Ref, DotZeroValueBuilder> builder; Ref asmjs = builder.parseToplevel(input); + if (debug) { + std::cerr << "parsed:\n"; + asmjs->stringify(std::cerr, true); + std::cerr << '\n'; + } if (debug) std::cerr << "wasming...\n"; AllocatingModule wasm; diff --git a/src/asm2wasm.h b/src/asm2wasm.h index d3d76ff83..e37751a66 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -1338,6 +1338,49 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { block->list.push_back(continuer); ret->body = block; return ret; + } else if (what == FOR) { + Ref finit = ast[1], + fcond = ast[2], + finc = ast[3], + fbody = ast[4]; + auto ret = allocator.alloc<Loop>(); + IString out, in; + if (!parentLabel.isNull()) { + out = getBreakLabelName(parentLabel); + in = getContinueLabelName(parentLabel); + parentLabel = IString(); + } else { + out = getNextId("for-out"); + in = getNextId("for-in"); + } + ret->out = out; + ret->in = in; + breakStack.push_back(out); + continueStack.push_back(in); + Break *breakOut = allocator.alloc<Break>(); + breakOut->name = out; + If *condition = allocator.alloc<If>(); + condition->condition = process(fcond); + condition->ifTrue = allocator.alloc<Nop>(); + condition->ifFalse = breakOut; + auto body = allocator.alloc<Block>(); + body->list.push_back(condition); + body->list.push_back(process(fbody)); + body->list.push_back(process(finc)); + ret->body = body; + // loops do not automatically loop, add a branch back + Block* block = blockify(ret->body); + auto continuer = allocator.alloc<Break>(); + continuer->name = ret->in; + block->list.push_back(continuer); + ret->body = block; + continueStack.pop_back(); + breakStack.pop_back(); + Block *outer = allocator.alloc<Block>(); + // add an outer block for the init as well + outer->list.push_back(process(finit)); + outer->list.push_back(ret); + return outer; } else if (what == LABEL) { assert(parentLabel.isNull()); parentLabel = ast[1]->getIString(); diff --git a/src/emscripten-optimizer/parser.h b/src/emscripten-optimizer/parser.h index 6b2fa2faa..c805ca9f6 100644 --- a/src/emscripten-optimizer/parser.h +++ b/src/emscripten-optimizer/parser.h @@ -386,6 +386,7 @@ class Parser { else if (frag.str == CONTINUE) return parseContinue(src, seps); else if (frag.str == SWITCH) return parseSwitch(src, seps); else if (frag.str == NEW) return parseNew(src, seps); + else if (frag.str == FOR) return parseFor(src, seps); dump(frag.str.str, src); abort(); return nullptr; @@ -492,6 +493,26 @@ class Parser { return Builder::makeWhile(condition, body); } + NodeRef parseFor(char*& src, const char* seps) { + skipSpace(src); + assert(*src == '('); + src++; + NodeRef init = parseElement(src, ";"); + skipSpace(src); + assert(*src == ';'); + src++; + NodeRef condition = parseElement(src, ";"); + skipSpace(src); + assert(*src == ';'); + src++; + NodeRef inc = parseElement(src, ")"); + skipSpace(src); + assert(*src == ')'); + src++; + NodeRef body = parseMaybeBracketed(src, seps); + return Builder::makeFor(init, condition, inc, body); + } + NodeRef parseBreak(char*& src, const char* seps) { skipSpace(src); Frag next(src); diff --git a/src/emscripten-optimizer/simple_ast.h b/src/emscripten-optimizer/simple_ast.h index 862e1f0bc..712845dea 100644 --- a/src/emscripten-optimizer/simple_ast.h +++ b/src/emscripten-optimizer/simple_ast.h @@ -380,7 +380,11 @@ struct Value { #define indentify() { for (int i = 0; i < indent; i++) os << " "; } switch (type) { case String: - os << '"' << str.str << '"'; + if (str.str) { + os << '"' << str.str << '"'; + } else { + os << "\"(null)\""; + } break; case Number: os << std::setprecision(17) << num; // doubles can have 17 digits of precision @@ -1561,6 +1565,14 @@ public: .push_back(body); } + static Ref makeFor(Ref init, Ref condition, Ref inc, Ref body) { + return &makeRawArray(5)->push_back(makeRawString(FOR)) + .push_back(init) + .push_back(condition) + .push_back(inc) + .push_back(body); + } + static Ref makeBreak(IString label) { return &makeRawArray(2)->push_back(makeRawString(BREAK)) .push_back(!!label ? makeRawString(label) : makeNull()); diff --git a/test/unit.asm.js b/test/unit.asm.js index a2235dd62..e539c6139 100644 --- a/test/unit.asm.js +++ b/test/unit.asm.js @@ -1,4 +1,4 @@ -function () { +function asm() { "use asm"; var t = global.NaN, u = global.Infinity; @@ -129,6 +129,12 @@ function () { function cneg_nosemicolon() { FUNCTION_TABLE_c[1 & 7](1) // no semicolon } + function forLoop() { + var i = 0; + for (i = 1; (i | 0) < 200; i = i + 1 | 0) { + h(i | 0); + } + } function z() { } diff --git a/test/unit.fromasm b/test/unit.fromasm index 5a6b78de5..4b95dfea1 100644 --- a/test/unit.fromasm +++ b/test/unit.fromasm @@ -409,6 +409,36 @@ (i32.const 1) ) ) + (func $forLoop + (local $i i32) + (block + (set_local $i + (i32.const 1) + ) + (loop $for-out$0 $for-in$1 + (block + (if_else + (i32.lt_s + (get_local $i) + (i32.const 200) + ) + (nop) + (br $for-out$0) + ) + (call $h + (get_local $i) + ) + (set_local $i + (i32.add + (get_local $i) + (i32.const 1) + ) + ) + (br $for-in$1) + ) + ) + ) + ) (func $z (nop) ) |