summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2016-03-07 17:03:23 -0800
committerAlon Zakai <alonzakai@gmail.com>2016-03-07 17:03:23 -0800
commit8efa11fbb9ff8cfd8bacc9d16642e13e2bbac9b4 (patch)
tree22050fa4bbdfa87d367030d88f5af3c4f11eb7fd /src
parentb65a994c24e83694f27cb835845b3b281207fc2f (diff)
parenta94f9938701920fe11c4f21a875ed3174ff7e9ba (diff)
downloadbinaryen-8efa11fbb9ff8cfd8bacc9d16642e13e2bbac9b4.tar.gz
binaryen-8efa11fbb9ff8cfd8bacc9d16642e13e2bbac9b4.tar.bz2
binaryen-8efa11fbb9ff8cfd8bacc9d16642e13e2bbac9b4.zip
Merge pull request #224 from WebAssembly/spec-updates
Spec updates
Diffstat (limited to 'src')
-rw-r--r--src/asm2wasm.h23
-rw-r--r--src/ast_utils.h43
-rw-r--r--src/passes/LowerCase.cpp2
-rw-r--r--src/passes/LowerIfElse.cpp2
-rw-r--r--src/passes/LowerInt64.cpp3
-rw-r--r--src/passes/Print.cpp17
-rw-r--r--src/s2wasm.h3
-rw-r--r--src/shared-constants.h2
-rw-r--r--src/wasm-binary.h4
-rw-r--r--src/wasm-s-parser.h65
-rw-r--r--src/wasm.h6
11 files changed, 141 insertions, 29 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h
index c13c847e7..be11344b2 100644
--- a/src/asm2wasm.h
+++ b/src/asm2wasm.h
@@ -28,6 +28,7 @@
#include "shared-constants.h"
#include "asm_v_wasm.h"
#include "pass.h"
+#include "ast_utils.h"
namespace wasm {
@@ -66,17 +67,6 @@ struct AstStackHelper {
std::vector<Ref> AstStackHelper::astStack;
-struct BreakSeeker : public WasmWalker<BreakSeeker> {
- IString target; // look for this one
- size_t found;
-
- BreakSeeker(IString target) : target(target), found(false) {}
-
- void visitBreak(Break *curr) {
- if (curr->name == target) found++;
- }
-};
-
//
// Asm2WasmPreProcessor - does some initial parsing/processing
// of asm.js code.
@@ -431,6 +421,7 @@ private:
if (expression->is<Block>()) return expression->dyn_cast<Block>();
auto ret = allocator.alloc<Block>();
ret->list.push_back(expression);
+ ret->finalize();
return ret;
}
@@ -1154,7 +1145,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
select->condition = isNegative;
select->type = i32;
block->list.push_back(select);
- block->type = i32;
+ block->finalize();
return block;
} else if (value->type == f32 || value->type == f64) {
auto ret = allocator.alloc<Unary>();
@@ -1237,6 +1228,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
block = allocator.alloc<Block>();
block->name = name;
block->list.push_back(ret);
+ block->finalize();
ret = block;
}
}
@@ -1279,6 +1271,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
auto body = allocator.alloc<Block>();
body->list.push_back(condition);
body->list.push_back(process(ast[2]));
+ body->finalize();
ret->body = body;
}
// loops do not automatically loop, add a branch back
@@ -1313,6 +1306,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
auto block = allocator.alloc<Block>();
block->list.push_back(child);
block->name = stop;
+ block->finalize();
return block;
} else {
auto loop = allocator.alloc<Loop>();
@@ -1376,6 +1370,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
body->list.push_back(condition);
body->list.push_back(process(fbody));
body->list.push_back(process(finc));
+ body->finalize();
ret->body = body;
// loops do not automatically loop, add a branch back
Block* block = blockify(ret->body);
@@ -1389,6 +1384,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
// add an outer block for the init as well
outer->list.push_back(process(finit));
outer->list.push_back(ret);
+ outer->finalize();
return outer;
} else if (what == LABEL) {
assert(parentLabel.isNull());
@@ -1405,7 +1401,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
auto ret = allocator.alloc<Block>();
ret->list.push_back(process(ast[1]));
ret->list.push_back(process(ast[2]));
- ret->type = ret->list[1]->type;
+ ret->finalize();
return ret;
} else if (what == SWITCH) {
IString name;
@@ -1510,6 +1506,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
for (unsigned i = from; i < ast->size(); i++) {
block->list.push_back(process(ast[i]));
}
+ block->finalize();
return block;
};
// body
diff --git a/src/ast_utils.h b/src/ast_utils.h
new file mode 100644
index 000000000..df2ffe578
--- /dev/null
+++ b/src/ast_utils.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef wasm_ast_utils_h
+#define wasm_ast_utils_h
+
+#include "wasm.h"
+
+namespace wasm {
+
+struct BreakSeeker : public WasmWalker<BreakSeeker> {
+ Name target; // look for this one
+ size_t found;
+
+ BreakSeeker(Name target) : target(target), found(false) {}
+
+ void visitBreak(Break *curr) {
+ if (curr->name == target) found++;
+ }
+
+ static bool has(Expression* tree, Name target) {
+ BreakSeeker breakSeeker(target);
+ breakSeeker.walk(tree);
+ return breakSeeker.found > 0;
+ }
+};
+
+} // namespace wasm
+
+#endif // wasm_ast_utils_h
diff --git a/src/passes/LowerCase.cpp b/src/passes/LowerCase.cpp
index f890de411..c0ab8d235 100644
--- a/src/passes/LowerCase.cpp
+++ b/src/passes/LowerCase.cpp
@@ -84,11 +84,13 @@ struct LowerCase : public WalkerPass<WasmWalker<LowerCase, void>> {
if (curr->cases.size() == 0) return;
auto top = allocator->alloc<Block>();
top->list.push_back(curr);
+ top->finalize();
for (auto& c : curr->cases) {
top->name = c.name;
auto next = allocator->alloc<Block>();
next->list.push_back(top);
next->list.push_back(c.body);
+ next->finalize();
top = next;
}
curr->cases.clear();
diff --git a/src/passes/LowerIfElse.cpp b/src/passes/LowerIfElse.cpp
index fa575d87d..922a294d2 100644
--- a/src/passes/LowerIfElse.cpp
+++ b/src/passes/LowerIfElse.cpp
@@ -49,7 +49,7 @@ struct LowerIfElse : public WalkerPass<WasmWalker<LowerIfElse, void>> {
block->name = name;
block->list.push_back(curr);
block->list.push_back(curr->ifFalse);
- block->type = curr->type;
+ block->finalize();
curr->ifFalse = nullptr;
auto break_ = allocator->alloc<Break>();
break_->name = name;
diff --git a/src/passes/LowerInt64.cpp b/src/passes/LowerInt64.cpp
index 58e56cba6..7af7443e5 100644
--- a/src/passes/LowerInt64.cpp
+++ b/src/passes/LowerInt64.cpp
@@ -112,7 +112,7 @@ struct LowerInt64 : public Pass {
ret->list.push_back(curr);
ret->list.push_back(set);
ret->list.push_back(low); // so the block returns the low bits
- ret->type = i32;
+ ret->finalize();
fixes[ret] = high;
replaceCurrent(ret);
}
@@ -132,6 +132,7 @@ struct LowerInt64 : public Pass {
set->type = value->type;
ret->list.push_back(set);
}
+ ret->finalize();
return ret;
}
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index f365db02f..e8e917a6e 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -65,11 +65,22 @@ struct PrintSExpression : public WasmVisitor<PrintSExpression, void> {
decIndent();
}
void visitIf(If *curr) {
- printOpening(o, curr->ifFalse ? "if_else" : "if");
+ printOpening(o, "if");
incIndent();
printFullLine(curr->condition);
- printFullLine(curr->ifTrue);
- if (curr->ifFalse) printFullLine(curr->ifFalse);
+ // ifTrue and False have implict blocks, avoid printing them if possible
+ if (curr->ifTrue->is<Block>() && curr->ifTrue->dyn_cast<Block>()->name.isNull() && curr->ifTrue->dyn_cast<Block>()->list.size() == 1) {
+ printFullLine(curr->ifTrue->dyn_cast<Block>()->list.back());
+ } else {
+ printFullLine(curr->ifTrue);
+ }
+ if (curr->ifFalse) {
+ if (curr->ifFalse->is<Block>() && curr->ifFalse->dyn_cast<Block>()->name.isNull() && curr->ifFalse->dyn_cast<Block>()->list.size() == 1) {
+ printFullLine(curr->ifFalse->dyn_cast<Block>()->list.back());
+ } else {
+ printFullLine(curr->ifFalse);
+ }
+ }
decIndent();
}
void visitLoop(Loop *curr) {
diff --git a/src/s2wasm.h b/src/s2wasm.h
index 0520d5c3b..2de6cd60f 100644
--- a/src/s2wasm.h
+++ b/src/s2wasm.h
@@ -528,6 +528,7 @@ class S2WasmBuilder {
last = last->cast<Loop>()->body;
}
last->cast<Block>()->list.push_back(curr);
+ last->cast<Block>()->finalize();
};
bstack.push_back(func->body);
std::vector<Expression*> estack;
@@ -1023,6 +1024,7 @@ class S2WasmBuilder {
for (auto block : loopBlocks) {
block->name = Name();
}
+ func->body->dyn_cast<Block>()->finalize();
wasm.addFunction(func);
// XXX for now, export all functions
auto exp = allocator.alloc<Export>();
@@ -1243,6 +1245,7 @@ class S2WasmBuilder {
call->operands.push_back(param);
}
block->list.push_back(call);
+ block->finalize();
}
}
}
diff --git a/src/shared-constants.h b/src/shared-constants.h
index 053aecc83..03409de6e 100644
--- a/src/shared-constants.h
+++ b/src/shared-constants.h
@@ -68,6 +68,8 @@ cashew::IString GLOBAL("global"),
CALL_IMPORT("call_import"),
CALL_INDIRECT("call_indirect"),
BR_IF("br_if"),
+ THEN("then"),
+ ELSE("else"),
NEG_INFINITY("-infinity"),
NEG_NAN("-nan"),
CASE("case"),
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 8fc6beb6c..993b4522d 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -1359,9 +1359,7 @@ public:
curr->list.push_back(expressionStack[i]);
}
expressionStack.resize(start);
- if (curr->list.size() > 0) {
- curr->type = curr->list.back()->type;
- }
+ curr->finalize();
breakStack.pop_back();
}
void visitIf(If *curr, uint8_t code) {
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index 24ca1b811..f3a28fd1a 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -29,6 +29,7 @@
#include "shared-constants.h"
#include "parsing.h"
#include "asm_v_wasm.h"
+#include "ast_utils.h"
namespace wasm {
@@ -380,6 +381,7 @@ private:
if (!autoBlock) {
autoBlock = allocator.alloc<Block>();
autoBlock->list.push_back(func->body);
+ autoBlock->finalize();
func->body = autoBlock;
}
autoBlock->list.push_back(ex);
@@ -567,6 +569,10 @@ public:
}
abort_on(str);
}
+ case 'e': {
+ if (str[1] == 'l') return makeThenOrElse(s);
+ abort_on(str);
+ }
case 'g': {
if (str[1] == 'e') return makeGetLocal(s);
if (str[1] == 'r') return makeHost(s, HostOp::GrowMemory);
@@ -607,6 +613,7 @@ public:
}
case 't': {
if (str[1] == 'a') return makeSwitch(s); // aka tableswitch
+ if (str[1] == 'h') return makeThenOrElse(s);
abort_on(str);
}
case 'u': {
@@ -688,8 +695,9 @@ private:
Expression* makeBlock(Element& s) {
auto ret = allocator.alloc<Block>();
size_t i = 1;
- if (s[1]->isStr()) {
- ret->name = s[1]->str();
+ if (i >= s.size()) return ret; // empty block
+ if (s[i]->isStr()) {
+ ret->name = s[i]->str();
i++;
} else {
ret->name = getPrefixedName("block");
@@ -699,7 +707,21 @@ private:
ret->list.push_back(parseExpression(s[i]));
}
labelStack.pop_back();
- if (ret->list.size() > 0) ret->type = ret->list.back()->type;
+ ret->finalize();
+ return ret;
+ }
+
+ // Similar to block, but the label is handled by the enclosing if (since there might not be a then or else, ick)
+ Expression* makeThenOrElse(Element& s) {
+ auto ret = allocator.alloc<Block>();
+ size_t i = 1;
+ if (s[1]->isStr()) {
+ i++;
+ }
+ for (; i < s.size(); i++) {
+ ret->list.push_back(parseExpression(s[i]));
+ }
+ ret->finalize();
return ret;
}
@@ -788,9 +810,38 @@ private:
Expression* makeIf(Element& s) {
auto ret = allocator.alloc<If>();
ret->condition = parseExpression(s[1]);
- ret->ifTrue = parseExpression(s[2]);
+
+ // ifTrue and ifFalse may get implicit blocks
+ auto handle = [&](const char* title, Element& s) {
+ Name name = getPrefixedName(title);
+ bool explicitThenElse = false;
+ if (s[0]->str() == THEN || s[0]->str() == ELSE) {
+ explicitThenElse = true;
+ if (s[1]->dollared()) {
+ name = s[1]->str();
+ }
+ }
+ labelStack.push_back(name);
+ auto* ret = parseExpression(&s);
+ labelStack.pop_back();
+ if (explicitThenElse) {
+ ret->dyn_cast<Block>()->name = name;
+ } else {
+ // add a block if we must
+ if (BreakSeeker::has(ret, name)) {
+ auto* block = allocator.alloc<Block>();
+ block->name = name;
+ block->list.push_back(ret);
+ block->finalize();
+ ret = block;
+ }
+ }
+ return ret;
+ };
+
+ ret->ifTrue = handle("if-true", *s[2]);
if (s.size() == 4) {
- ret->ifFalse = parseExpression(s[3]);
+ ret->ifFalse = handle("if-else", *s[3]);
ret->finalize();
}
return ret;
@@ -802,9 +853,7 @@ private:
for (; i < s.size() && i < stopAt; i++) {
ret->list.push_back(parseExpression(s[i]));
}
- if (ret->list.size() > 0) {
- ret->type = ret->list.back()->type;
- }
+ ret->finalize();
// Note that we do not name these implicit/synthetic blocks. They
// are the effects of syntactic sugar, and nothing can branch to
// them anyhow.
diff --git a/src/wasm.h b/src/wasm.h
index ec2cd469e..ba9d7de3d 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -794,6 +794,12 @@ public:
Name name;
ExpressionList list;
+
+ void finalize() {
+ if (list.size() > 0) {
+ type = list.back()->type;
+ }
+ }
};
class If : public Expression {