@@ -271,7 +271,7 @@ void WasmBinaryWriter::writeFunctions() {
271271 if (numLocalsByType[f32 ]) o << U32LEB (numLocalsByType[f32 ]) << binaryWasmType (f32 );
272272 if (numLocalsByType[f64 ]) o << U32LEB (numLocalsByType[f64 ]) << binaryWasmType (f64 );
273273
274- writeExpression (function->body );
274+ recursePossibleBlockContents (function->body );
275275 o << int8_t (BinaryConsts::End);
276276 size_t size = o.size () - start;
277277 assert (size <= std::numeric_limits<uint32_t >::max ());
@@ -1633,7 +1633,7 @@ void WasmBinaryBuilder::readFunctions() {
16331633 breakStack.emplace_back (RETURN_BREAK, func->result != none); // the break target for the function scope
16341634 assert (expressionStack.empty ());
16351635 assert (depth == 0 );
1636- func->body = getMaybeBlock (func->result );
1636+ func->body = getBlockOrSingleton (func->result );
16371637 assert (depth == 0 );
16381638 assert (breakStack.size () == 1 );
16391639 breakStack.pop_back ();
@@ -2225,38 +2225,34 @@ void WasmBinaryBuilder::visitBlock(Block *curr) {
22252225 }
22262226}
22272227
2228- Expression* WasmBinaryBuilder::getMaybeBlock (WasmType type) {
2228+ Expression* WasmBinaryBuilder::getBlockOrSingleton (WasmType type) {
2229+ Name label = getNextLabel ();
2230+ breakStack.push_back ({label, type != none && type != unreachable});
22292231 auto start = expressionStack.size ();
22302232 processExpressions ();
22312233 size_t end = expressionStack.size ();
2232- if (start - end == 1 ) {
2233- return popExpression ();
2234- }
2235- if (start > end) {
2236- throw ParseException (" block cannot pop from outside" );
2237- }
2234+ breakStack.pop_back ();
22382235 auto * block = allocator.alloc <Block>();
22392236 pushBlockElements (block, start, end);
2237+ block->name = label;
22402238 block->finalize (type);
2241- return block;
2242- }
2243-
2244- Expression* WasmBinaryBuilder::getBlock (WasmType type) {
2245- Name label = getNextLabel ();
2246- breakStack.push_back ({label, type != none && type != unreachable});
2247- auto * block = Builder (wasm).blockify (getMaybeBlock (type));
2248- breakStack.pop_back ();
2249- block->cast <Block>()->name = label;
2239+ // maybe we don't need a block here?
2240+ if (!brokenTo (block)) {
2241+ block->name = Name ();
2242+ if (block->list .size () == 1 ) {
2243+ return block->list [0 ];
2244+ }
2245+ }
22502246 return block;
22512247}
22522248
22532249void WasmBinaryBuilder::visitIf (If *curr) {
22542250 if (debug) std::cerr << " zz node: If" << std::endl;
22552251 curr->type = getWasmType ();
22562252 curr->condition = popNonVoidExpression ();
2257- curr->ifTrue = getBlock (curr->type );
2253+ curr->ifTrue = getBlockOrSingleton (curr->type );
22582254 if (lastSeparator == BinaryConsts::Else) {
2259- curr->ifFalse = getBlock (curr->type );
2255+ curr->ifFalse = getBlockOrSingleton (curr->type );
22602256 }
22612257 curr->finalize (curr->type );
22622258 if (lastSeparator != BinaryConsts::End) {
@@ -2269,7 +2265,25 @@ void WasmBinaryBuilder::visitLoop(Loop *curr) {
22692265 curr->type = getWasmType ();
22702266 curr->name = getNextLabel ();
22712267 breakStack.push_back ({curr->name , 0 });
2272- curr->body = getMaybeBlock (curr->type );
2268+ // find the expressions in the block, and create the body
2269+ // a loop may have a list of instructions in wasm, much like
2270+ // a block, but it only has a label at the top of the loop,
2271+ // so even if we need a block (if there is more than 1
2272+ // expression) we never need a label on the block.
2273+ auto start = expressionStack.size ();
2274+ processExpressions ();
2275+ size_t end = expressionStack.size ();
2276+ if (end - start == 1 ) {
2277+ curr->body = popExpression ();
2278+ } else {
2279+ if (start > end) {
2280+ throw ParseException (" block cannot pop from outside" );
2281+ }
2282+ auto * block = allocator.alloc <Block>();
2283+ pushBlockElements (block, start, end);
2284+ block->finalize (curr->type );
2285+ curr->body = block;
2286+ }
22732287 breakStack.pop_back ();
22742288 curr->finalize (curr->type );
22752289}
0 commit comments