@@ -281,6 +281,15 @@ Result<> IRBuilder::visitArrayNew(ArrayNew* curr) {
281281 return Ok{};
282282}
283283
284+ Result<> IRBuilder::visitFunctionStart (Function* func) {
285+ if (!scopeStack.empty ()) {
286+ return Err{" unexpected start of function" };
287+ }
288+ scopeStack.push_back (ScopeCtx::makeFunc (func));
289+ this ->func = func;
290+ return Ok{};
291+ }
292+
284293Result<> IRBuilder::visitBlockStart (Block* curr) {
285294 scopeStack.push_back (ScopeCtx::makeBlock (curr));
286295 return Ok{};
@@ -327,12 +336,12 @@ Result<Expression*> IRBuilder::finishScope(Block* block) {
327336 auto hoisted = hoistLastValue ();
328337 CHECK_ERR (hoisted);
329338 auto hoistedType = scope.exprStack .back ()->type ;
330- if (hoistedType.size () != block-> type .size ()) {
339+ if (hoistedType.size () != type.size ()) {
331340 // We cannot propagate the hoisted value directly because it does not
332341 // have the correct number of elements. Break it up if necessary and
333342 // construct our returned tuple from parts.
334343 CHECK_ERR (packageHoistedValue (*hoisted));
335- std::vector<Expression*> elems (block-> type .size ());
344+ std::vector<Expression*> elems (type.size ());
336345 for (size_t i = 0 ; i < elems.size (); ++i) {
337346 auto elem = pop ();
338347 CHECK_ERR (elem);
@@ -369,11 +378,11 @@ Result<Expression*> IRBuilder::finishScope(Block* block) {
369378 } else {
370379 // More than one expression, so we need a block. Allocate one if we weren't
371380 // already given one.
372- if (!block) {
373- block = wasm.allocator .alloc <Block>();
374- block->type = type;
381+ if (block) {
382+ block->list .set (scope.exprStack );
383+ } else {
384+ block = builder.makeBlock (scope.exprStack , type);
375385 }
376- block->list .set (scope.exprStack );
377386 ret = block;
378387 }
379388 scopeStack.pop_back ();
@@ -395,50 +404,45 @@ Result<> IRBuilder::visitElse() {
395404}
396405
397406Result<> IRBuilder::visitEnd () {
398- auto & scope = getScope ();
407+ auto scope = getScope ();
399408 if (scope.isNone ()) {
400409 return Err{" unexpected end" };
401410 }
402- if (auto * block = scope.getBlock ()) {
403- auto expr = finishScope (block);
404- CHECK_ERR (expr);
411+ auto expr = finishScope (scope.getBlock ());
412+ CHECK_ERR (expr);
413+
414+ // If the scope expression cannot be directly labeled, we may need to wrap it
415+ // in a block.
416+ auto maybeWrapForLabel = [&](Expression* curr) -> Expression* {
417+ if (auto label = scope.getLabel ()) {
418+ return builder.makeBlock (label, {curr}, curr->type );
419+ }
420+ return curr;
421+ };
422+
423+ if (auto * func = scope.getFunction ()) {
424+ func->body = *expr;
425+ } else if (auto * block = scope.getBlock ()) {
405426 assert (*expr == block);
406427 // TODO: Track branches so we can know whether this block is a target and
407428 // finalize more efficiently.
408429 block->finalize (block->type );
409430 push (block);
410- return Ok{};
411431 } else if (auto * loop = scope.getLoop ()) {
412- auto expr = finishScope ();
413- CHECK_ERR (expr);
414432 loop->body = *expr;
415433 loop->finalize (loop->type );
416434 push (loop);
417- return Ok{};
418- }
419- auto label = scope.getLabel ();
420- Expression* scopeExpr = nullptr ;
421- if (auto * iff = scope.getIf ()) {
422- auto expr = finishScope ();
423- CHECK_ERR (expr);
435+ } else if (auto * iff = scope.getIf ()) {
424436 iff->ifTrue = *expr;
425437 iff->ifFalse = nullptr ;
426438 iff->finalize (iff->type );
427- scopeExpr = iff;
439+ push ( maybeWrapForLabel ( iff)) ;
428440 } else if (auto * iff = scope.getElse ()) {
429- auto expr = finishScope ();
430- CHECK_ERR (expr);
431441 iff->ifFalse = *expr;
432442 iff->finalize (iff->type );
433- scopeExpr = iff;
434- }
435- assert (scopeExpr && " unexpected scope kind" );
436- if (label) {
437- // We cannot directly name an If in Binaryen IR, so we need to wrap it in
438- // a block.
439- push (builder.makeBlock (label, {scopeExpr}, scopeExpr->type ));
443+ push (maybeWrapForLabel (iff));
440444 } else {
441- push (scopeExpr );
445+ WASM_UNREACHABLE ( " unexpected scope kind " );
442446 }
443447 return Ok{};
444448}
0 commit comments