diff options
author | Alon Zakai <alonzakai@gmail.com> | 2016-04-21 19:01:47 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2016-04-21 19:01:47 -0700 |
commit | a180c863ac4b6882f47e5e05ceeebe94b1208a7d (patch) | |
tree | d1e5591a6075f67359f792438f848cd15e834bc9 /src | |
parent | 7b180b286a3df1a231454399869516ae8571d9bb (diff) | |
parent | 171668684ad91dc8d397ef411ce5fd337bc7a976 (diff) | |
download | binaryen-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.cpp | 4 | ||||
-rw-r--r-- | src/support/file.cpp | 2 | ||||
-rw-r--r-- | src/wasm-binary.h | 130 | ||||
-rw-r--r-- | src/wasm-builder.h | 15 |
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 |