summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2016-04-21 19:01:47 -0700
committerAlon Zakai <alonzakai@gmail.com>2016-04-21 19:01:47 -0700
commita180c863ac4b6882f47e5e05ceeebe94b1208a7d (patch)
treed1e5591a6075f67359f792438f848cd15e834bc9 /src
parent7b180b286a3df1a231454399869516ae8571d9bb (diff)
parent171668684ad91dc8d397ef411ce5fd337bc7a976 (diff)
downloadbinaryen-a180c863ac4b6882f47e5e05ceeebe94b1208a7d.tar.gz
binaryen-a180c863ac4b6882f47e5e05ceeebe94b1208a7d.tar.bz2
binaryen-a180c863ac4b6882f47e5e05ceeebe94b1208a7d.zip
Merge pull request #377 from WebAssembly/zero_x_b
More 0xb work
Diffstat (limited to 'src')
-rw-r--r--src/passes/Print.cpp4
-rw-r--r--src/support/file.cpp2
-rw-r--r--src/wasm-binary.h130
-rw-r--r--src/wasm-builder.h15
4 files changed, 91 insertions, 60 deletions
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 59ade1c76..bb89b2720 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -181,9 +181,7 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
}
o << " " << curr->default_;
incIndent();
- if (curr->value) {
- printFullLine(curr->value);
- }
+ if (curr->value && !curr->value->is<Nop>()) printFullLine(curr->value);
printFullLine(curr->condition);
decIndent();
}
diff --git a/src/support/file.cpp b/src/support/file.cpp
index b71361d99..ef014e59a 100644
--- a/src/support/file.cpp
+++ b/src/support/file.cpp
@@ -37,7 +37,7 @@ T wasm::read_file(const std::string &filename, Flags::BinaryOption binary, Flags
std::cerr << "Failed opening '" << filename << "': Input file too large: " << insize << " bytes. Try rebuilding in 64-bit mode." << std::endl;
exit(EXIT_FAILURE);
}
- T input(size_t(insize) + 1, '\0');
+ T input(size_t(insize) + (binary == Flags::Binary ? 0 : 1), '\0');
infile.seekg(0);
infile.read(&input[0], insize);
return input;
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 8fed9f6d9..01ccfdd3c 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -230,7 +230,6 @@ namespace Section {
auto DataSegments = "data";
auto FunctionTable = "table";
auto Names = "name";
- auto End = "end";
auto Start = "start";
};
@@ -270,8 +269,7 @@ enum ASTNodes {
I32Clz = 0x57,
I32Ctz = 0x58,
I32Popcnt = 0x59,
- I32EqZ = 0xc0, // XXX
- BoolNot = 0x5a,
+ I32EqZ = 0x5a,
I64Add = 0x5b,
I64Sub = 0x5c,
I64Mul = 0x5d,
@@ -298,7 +296,7 @@ enum ASTNodes {
I64Clz = 0x72,
I64Ctz = 0x73,
I64Popcnt = 0x74,
- I64EqZ = 0xc1, // XXX
+ I64EqZ = 0xba,
F32Add = 0x75,
F32Sub = 0x76,
F32Mul = 0x77,
@@ -363,12 +361,12 @@ enum ASTNodes {
F64UConvertI64 = 0xb1,
F64ConvertF32 = 0xb2,
F64ReinterpretI64 = 0xb3,
+ I32ReinterpretF32 = 0xb4,
I64ReinterpretF64 = 0xb5,
I32RotR = 0xb6,
I32RotL = 0xb7,
I64RotR = 0xb8,
I64RotL = 0xb9,
- I32ReinterpretF32 = 0xfe, // XXX not in v8 spec doc
I32LoadMem8S = 0x20,
I32LoadMem8U = 0x21,
@@ -476,7 +474,6 @@ public:
writeDataSegments();
writeFunctionTable();
writeNames();
- writeEnd();
finishUp();
}
@@ -518,7 +515,7 @@ public:
auto start = startSection(BinaryConsts::Section::Memory);
o << U32LEB(wasm->memory.initial)
<< U32LEB(wasm->memory.max)
- << int8_t(1); // export memory
+ << int8_t(wasm->memory.exportName.is()); // export memory
finishSection(start);
}
@@ -644,7 +641,6 @@ public:
if (numLocalsByType[f64]) o << U32LEB(numLocalsByType[f64]) << binaryWasmType(f64);
depth = 0;
recurse(function->body);
- o << int8_t(BinaryConsts::End);
assert(depth == 0);
size_t size = o.size() - start;
assert(size <= std::numeric_limits<uint32_t>::max());
@@ -732,11 +728,6 @@ public:
finishSection(start);
}
- void writeEnd() {
- auto start = startSection(BinaryConsts::Section::End);
- finishSection(start);
- }
-
// helpers
void writeInlineString(const char* name) {
@@ -812,19 +803,23 @@ public:
}
void visitIf(If *curr) {
if (debug) std::cerr << "zz node: If" << std::endl;
- o << int8_t(BinaryConsts::If);
recurse(curr->condition);
- recurse(curr->ifTrue); // TODO: emit block contents directly, if block with no name
+ o << int8_t(BinaryConsts::If);
+ breakStack.push_back(IMPOSSIBLE_CONTINUE); // the binary format requires this; we have a block if we need one; TODO: optimize
+ recurse(curr->ifTrue); // TODO: emit block contents directly, if possible
+ breakStack.pop_back();
if (curr->ifFalse) {
o << int8_t(BinaryConsts::Else);
+ breakStack.push_back(IMPOSSIBLE_CONTINUE); // TODO ditto
recurse(curr->ifFalse);
+ breakStack.pop_back();
}
o << int8_t(BinaryConsts::End);
}
void visitLoop(Loop *curr) {
if (debug) std::cerr << "zz node: Loop" << std::endl;
// TODO: optimize, as we usually have a block as our singleton child
- o << int8_t(BinaryConsts::Loop) << int8_t(1);
+ o << int8_t(BinaryConsts::Loop);
breakStack.push_back(curr->out);
breakStack.push_back(curr->in);
recurse(curr->body);
@@ -856,19 +851,17 @@ public:
}
void visitSwitch(Switch *curr) {
if (debug) std::cerr << "zz node: Switch" << std::endl;
- o << int8_t(BinaryConsts::TableSwitch) << U32LEB(curr->targets.size());
- for (auto target : curr->targets) {
- o << U32LEB(getBreakIndex(target));
- }
- o << U32LEB(getBreakIndex(curr->default_));
- recurse(curr->condition);
- o << int8_t(BinaryConsts::End);
if (curr->value) {
recurse(curr->value);
} else {
visitNop(nullptr);
}
- o << int8_t(BinaryConsts::End);
+ recurse(curr->condition);
+ o << int8_t(BinaryConsts::TableSwitch) << U32LEB(curr->targets.size());
+ for (auto target : curr->targets) {
+ o << U32LEB(getBreakIndex(target));
+ }
+ o << U32LEB(getBreakIndex(curr->default_));
}
void visitCall(Call *curr) {
if (debug) std::cerr << "zz node: Call" << std::endl;
@@ -1178,10 +1171,10 @@ public:
else if (match(BinaryConsts::Section::DataSegments)) readDataSegments();
else if (match(BinaryConsts::Section::FunctionTable)) readFunctionTable();
else if (match(BinaryConsts::Section::Names)) readNames();
- else if (match(BinaryConsts::Section::End)) {
- if (debug) std::cerr << "== readEnd" << std::endl;
- break;
- } else {
+ else {
+ std::cerr << "unfamiliar section: ";
+ for (size_t i = 0; i < nameSize; i++) std::cerr << input[pos + i];
+ std::cerr << std::endl;
abort();
}
assert(pos == before + sectionSize);
@@ -1343,7 +1336,10 @@ public:
if (debug) std::cerr << "== readMemory" << std::endl;
wasm.memory.initial = getU32LEB();
wasm.memory.max = getU32LEB();
- verifyInt8(1); // export memory
+ auto exportMemory = getInt8();
+ if (exportMemory) {
+ wasm.memory.exportName = Name("memory");
+ }
}
void readSignatures() {
@@ -1414,6 +1410,7 @@ public:
std::vector<Function*> functions; // we store functions here before wasm.addFunction after we know their names
std::map<size_t, std::vector<Call*>> functionCalls; // at index i we have all calls to i
Function* currFunction = nullptr;
+ size_t endOfFunction;
void readFunctions() {
if (debug) std::cerr << "== readFunctions" << std::endl;
@@ -1421,7 +1418,8 @@ public:
for (size_t i = 0; i < total; i++) {
if (debug) std::cerr << "read one at " << pos << std::endl;
size_t size = getU32LEB();
- assert(size > 0); // we could also check it matches the seen size
+ assert(size > 0);
+ endOfFunction = pos + size;
auto type = functionTypes[i];
if (debug) std::cerr << "reading" << i << std::endl;
size_t nextVar = 0;
@@ -1443,7 +1441,7 @@ public:
}
}
auto func = Builder(wasm).makeFunction(
- Name("TODO"),
+ Name::fromInt(i),
std::move(params),
type->result,
std::move(vars)
@@ -1458,12 +1456,11 @@ public:
assert(breakStack.empty());
assert(expressionStack.empty());
depth = 0;
- processExpressions();
- assert(expressionStack.size() == 1);
- func->body = popExpression();
+ func->body = getMaybeBlock();
assert(depth == 0);
assert(breakStack.empty());
assert(expressionStack.empty());
+ assert(pos == endOfFunction);
}
currFunction = nullptr;
functions.push_back(func);
@@ -1490,11 +1487,16 @@ public:
std::vector<Expression*> expressionStack;
- BinaryConsts::ASTNodes processExpressions() { // until an end or else marker
+ BinaryConsts::ASTNodes lastSeparator = BinaryConsts::End;
+
+ void processExpressions() { // until an end or else marker, or the end of the function
while (1) {
Expression* curr;
auto ret = readExpression(curr);
- if (!curr) return ret;
+ if (!curr) {
+ lastSeparator = ret;
+ return;
+ }
expressionStack.push_back(curr);
}
}
@@ -1579,6 +1581,10 @@ public:
int depth; // only for debugging
BinaryConsts::ASTNodes readExpression(Expression*& curr) {
+ if (pos == endOfFunction) {
+ curr = nullptr;
+ return BinaryConsts::End;
+ }
if (debug) std::cerr << "zz recurse into " << ++depth << " at " << pos << std::endl;
uint8_t code = getInt8();
if (debug) std::cerr << "readExpression seeing " << (int)code << std::endl;
@@ -1669,32 +1675,49 @@ public:
breakStack.pop_back();
}
}
+
+ Expression* getMaybeBlock() {
+ auto start = expressionStack.size();
+ processExpressions();
+ size_t end = expressionStack.size();
+ if (start - end == 1) {
+ return popExpression();
+ }
+ auto* block = allocator.alloc<Block>();
+ for (size_t i = start; i < end; i++) {
+ block->list.push_back(expressionStack[i]);
+ }
+ block->finalize();
+ expressionStack.resize(start);
+ return block;
+ }
+
+ Expression* getBlock() {
+ Name label = getNextLabel();
+ breakStack.push_back(label);
+ auto* block = Builder(wasm).blockify(getMaybeBlock());
+ breakStack.pop_back();
+ block->cast<Block>()->name = label;
+ return block;
+ }
+
void visitIf(If *curr) {
if (debug) std::cerr << "zz node: If" << std::endl;
- size_t start = expressionStack.size();
- auto next = processExpressions();
- size_t end = expressionStack.size();
- assert(end - start == 2);
- curr->ifTrue = popExpression();
curr->condition = popExpression();
- if (next == BinaryConsts::Else) {
- size_t start = expressionStack.size();
- processExpressions();
- size_t end = expressionStack.size();
- assert(end - start == 1);
- curr->ifFalse = popExpression();
+ curr->ifTrue = getBlock();
+ if (lastSeparator == BinaryConsts::Else) {
+ curr->ifFalse = getBlock();
curr->finalize();
}
+ assert(lastSeparator == BinaryConsts::End);
}
void visitLoop(Loop *curr) {
if (debug) std::cerr << "zz node: Loop" << std::endl;
- verifyInt8(1); // size TODO: generalize
curr->out = getNextLabel();
curr->in = getNextLabel();
breakStack.push_back(curr->out);
breakStack.push_back(curr->in);
- processExpressions();
- curr->body = popExpression();
+ curr->body = getMaybeBlock();
breakStack.pop_back();
breakStack.pop_back();
curr->finalize();
@@ -1713,16 +1736,13 @@ public:
}
void visitSwitch(Switch *curr) {
if (debug) std::cerr << "zz node: Switch" << std::endl;
+ curr->condition = popExpression();
+ curr->value = popExpression();
auto numTargets = getU32LEB();
for (size_t i = 0; i < numTargets; i++) {
curr->targets.push_back(getBreakName(getU32LEB()));
}
curr->default_ = getBreakName(getU32LEB());
- processExpressions();
- curr->condition = popExpression();
- processExpressions();
- curr->value = popExpression();
- if (curr->value->is<Nop>()) curr->value = nullptr;
}
void visitCall(Call *curr) {
if (debug) std::cerr << "zz node: Call" << std::endl;
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index 336a90e0d..6e342771b 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -65,7 +65,14 @@ public:
}
// Nop TODO: add all the rest
- // Block
+ Block* makeBlock(Expression* first = nullptr) {
+ auto* ret = allocator.alloc<Block>();
+ if (first) {
+ ret->list.push_back(first);
+ ret->finalize();
+ }
+ return ret;
+ }
If* makeIf(Expression* condition, Expression* ifTrue, Expression* ifFalse=nullptr) {
auto* ret = allocator.alloc<If>();
ret->condition = condition; ret->ifTrue = ifTrue; ret->ifFalse = ifFalse;
@@ -192,6 +199,12 @@ public:
func->localNames.clear();
func->localIndices.clear();
}
+
+ // ensure a node is a block, if it isn't already
+ Block* blockify(Expression* any) {
+ if (any->is<Block>()) return any->cast<Block>();
+ return makeBlock(any);
+ }
};
} // namespace wasm