summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/asm2wasm-main.cpp5
-rw-r--r--src/asm2wasm.h43
-rw-r--r--src/emscripten-optimizer/parser.h21
-rw-r--r--src/emscripten-optimizer/simple_ast.h14
4 files changed, 82 insertions, 1 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());