Skip to content

Commit c6d08d9

Browse files
committed
parse for loops in asm2wasm #60
1 parent 5e82fc2 commit c6d08d9

File tree

6 files changed

+119
-2
lines changed

6 files changed

+119
-2
lines changed

src/asm2wasm-main.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ int main(int argc, char **argv) {
5454
if (debug) std::cerr << "parsing...\n";
5555
cashew::Parser<Ref, DotZeroValueBuilder> builder;
5656
Ref asmjs = builder.parseToplevel(input);
57+
if (debug) {
58+
std::cerr << "parsed:\n";
59+
asmjs->stringify(std::cerr, true);
60+
std::cerr << '\n';
61+
}
5762

5863
if (debug) std::cerr << "wasming...\n";
5964
AllocatingModule wasm;

src/asm2wasm.h

+43
Original file line numberDiff line numberDiff line change
@@ -1338,6 +1338,49 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
13381338
block->list.push_back(continuer);
13391339
ret->body = block;
13401340
return ret;
1341+
} else if (what == FOR) {
1342+
Ref finit = ast[1],
1343+
fcond = ast[2],
1344+
finc = ast[3],
1345+
fbody = ast[4];
1346+
auto ret = allocator.alloc<Loop>();
1347+
IString out, in;
1348+
if (!parentLabel.isNull()) {
1349+
out = getBreakLabelName(parentLabel);
1350+
in = getContinueLabelName(parentLabel);
1351+
parentLabel = IString();
1352+
} else {
1353+
out = getNextId("for-out");
1354+
in = getNextId("for-in");
1355+
}
1356+
ret->out = out;
1357+
ret->in = in;
1358+
breakStack.push_back(out);
1359+
continueStack.push_back(in);
1360+
Break *breakOut = allocator.alloc<Break>();
1361+
breakOut->name = out;
1362+
If *condition = allocator.alloc<If>();
1363+
condition->condition = process(fcond);
1364+
condition->ifTrue = allocator.alloc<Nop>();
1365+
condition->ifFalse = breakOut;
1366+
auto body = allocator.alloc<Block>();
1367+
body->list.push_back(condition);
1368+
body->list.push_back(process(fbody));
1369+
body->list.push_back(process(finc));
1370+
ret->body = body;
1371+
// loops do not automatically loop, add a branch back
1372+
Block* block = blockify(ret->body);
1373+
auto continuer = allocator.alloc<Break>();
1374+
continuer->name = ret->in;
1375+
block->list.push_back(continuer);
1376+
ret->body = block;
1377+
continueStack.pop_back();
1378+
breakStack.pop_back();
1379+
Block *outer = allocator.alloc<Block>();
1380+
// add an outer block for the init as well
1381+
outer->list.push_back(process(finit));
1382+
outer->list.push_back(ret);
1383+
return outer;
13411384
} else if (what == LABEL) {
13421385
assert(parentLabel.isNull());
13431386
parentLabel = ast[1]->getIString();

src/emscripten-optimizer/parser.h

+21
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ class Parser {
386386
else if (frag.str == CONTINUE) return parseContinue(src, seps);
387387
else if (frag.str == SWITCH) return parseSwitch(src, seps);
388388
else if (frag.str == NEW) return parseNew(src, seps);
389+
else if (frag.str == FOR) return parseFor(src, seps);
389390
dump(frag.str.str, src);
390391
abort();
391392
return nullptr;
@@ -492,6 +493,26 @@ class Parser {
492493
return Builder::makeWhile(condition, body);
493494
}
494495

496+
NodeRef parseFor(char*& src, const char* seps) {
497+
skipSpace(src);
498+
assert(*src == '(');
499+
src++;
500+
NodeRef init = parseElement(src, ";");
501+
skipSpace(src);
502+
assert(*src == ';');
503+
src++;
504+
NodeRef condition = parseElement(src, ";");
505+
skipSpace(src);
506+
assert(*src == ';');
507+
src++;
508+
NodeRef inc = parseElement(src, ")");
509+
skipSpace(src);
510+
assert(*src == ')');
511+
src++;
512+
NodeRef body = parseMaybeBracketed(src, seps);
513+
return Builder::makeFor(init, condition, inc, body);
514+
}
515+
495516
NodeRef parseBreak(char*& src, const char* seps) {
496517
skipSpace(src);
497518
Frag next(src);

src/emscripten-optimizer/simple_ast.h

+13-1
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,11 @@ struct Value {
380380
#define indentify() { for (int i = 0; i < indent; i++) os << " "; }
381381
switch (type) {
382382
case String:
383-
os << '"' << str.str << '"';
383+
if (str.str) {
384+
os << '"' << str.str << '"';
385+
} else {
386+
os << "\"(null)\"";
387+
}
384388
break;
385389
case Number:
386390
os << std::setprecision(17) << num; // doubles can have 17 digits of precision
@@ -1561,6 +1565,14 @@ class ValueBuilder {
15611565
.push_back(body);
15621566
}
15631567

1568+
static Ref makeFor(Ref init, Ref condition, Ref inc, Ref body) {
1569+
return &makeRawArray(5)->push_back(makeRawString(FOR))
1570+
.push_back(init)
1571+
.push_back(condition)
1572+
.push_back(inc)
1573+
.push_back(body);
1574+
}
1575+
15641576
static Ref makeBreak(IString label) {
15651577
return &makeRawArray(2)->push_back(makeRawString(BREAK))
15661578
.push_back(!!label ? makeRawString(label) : makeNull());

test/unit.asm.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
function () {
1+
function asm() {
22
"use asm";
33

44
var t = global.NaN, u = global.Infinity;
@@ -129,6 +129,12 @@ function () {
129129
function cneg_nosemicolon() {
130130
FUNCTION_TABLE_c[1 & 7](1) // no semicolon
131131
}
132+
function forLoop() {
133+
var i = 0;
134+
for (i = 1; (i | 0) < 200; i = i + 1 | 0) {
135+
h(i | 0);
136+
}
137+
}
132138

133139
function z() {
134140
}

test/unit.fromasm

+30
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,36 @@
409409
(i32.const 1)
410410
)
411411
)
412+
(func $forLoop
413+
(local $i i32)
414+
(block
415+
(set_local $i
416+
(i32.const 1)
417+
)
418+
(loop $for-out$0 $for-in$1
419+
(block
420+
(if_else
421+
(i32.lt_s
422+
(get_local $i)
423+
(i32.const 200)
424+
)
425+
(nop)
426+
(br $for-out$0)
427+
)
428+
(call $h
429+
(get_local $i)
430+
)
431+
(set_local $i
432+
(i32.add
433+
(get_local $i)
434+
(i32.const 1)
435+
)
436+
)
437+
(br $for-in$1)
438+
)
439+
)
440+
)
441+
)
412442
(func $z
413443
(nop)
414444
)

0 commit comments

Comments
 (0)