Skip to content

Commit 96a5a0c

Browse files
authored
[NFC] Remove a goto (#7804)
Move the code skipped over with the goto into a separate function. The goto used to break out of multiple loops is now a return from that function.
1 parent 32539d4 commit 96a5a0c

File tree

1 file changed

+49
-48
lines changed

1 file changed

+49
-48
lines changed

src/wasm/wasm-ir-builder.cpp

Lines changed: 49 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -411,27 +411,57 @@ struct IRBuilder::ChildPopper
411411
Result<> popConstrainedChildren(std::vector<Child>& children) {
412412
auto& scope = builder.getScope();
413413

414-
// Two-part indices into the stack of available expressions and the vector
415-
// of requirements, allowing them to move independently with the granularity
416-
// of a single tuple element.
417-
size_t stackIndex = scope.exprStack.size();
418-
size_t stackTupleIndex = 0;
419-
size_t childIndex = children.size();
420-
size_t childTupleIndex = 0;
421-
422-
// The index of the shallowest unreachable instruction on the stack.
414+
// The index of the shallowest unreachable instruction on the stack, found
415+
// by checkNeedsUnreachableFallback.
423416
std::optional<size_t> unreachableIndex;
424417

425418
// Whether popping the children past the unreachable would produce a type
426419
// mismatch or try to pop from an empty stack.
427420
bool needUnreachableFallback = false;
428421

429-
if (!scope.unreachable) {
430-
// We only need to check requirements if there is an unreachable.
431-
// Otherwise the validator will catch any problems.
432-
goto pop;
422+
// We only need to check requirements if there is an unreachable.
423+
// Otherwise the validator will catch any problems.
424+
if (scope.unreachable) {
425+
needUnreachableFallback =
426+
checkNeedsUnreachableFallback(children, unreachableIndex);
433427
}
434428

429+
// We have checked all the constraints, so we are ready to pop children.
430+
for (int i = children.size() - 1; i >= 0; --i) {
431+
if (needUnreachableFallback &&
432+
scope.exprStack.size() == *unreachableIndex + 1 && i > 0) {
433+
// The next item on the stack is the unreachable instruction we must
434+
// not pop past. We cannot insert unreachables in front of it because
435+
// it might be a branch we actually have to execute, so this next item
436+
// must be child 0. But we are not ready to pop child 0 yet, so
437+
// synthesize an unreachable instead of popping. The deeper
438+
// instructions that would otherwise have been popped will remain on
439+
// the stack to become prior children of future expressions or to be
440+
// implicitly dropped at the end of the scope.
441+
*children[i].childp = builder.builder.makeUnreachable();
442+
continue;
443+
}
444+
445+
// Pop a child normally.
446+
auto val = pop(children[i].constraint.size());
447+
CHECK_ERR(val);
448+
*children[i].childp = *val;
449+
}
450+
return Ok{};
451+
}
452+
453+
bool checkNeedsUnreachableFallback(const std::vector<Child>& children,
454+
std::optional<size_t>& unreachableIndex) {
455+
auto& scope = builder.getScope();
456+
457+
// Two-part indices into the stack of available expressions and the vector
458+
// of requirements, allowing them to move independently with the granularity
459+
// of a single tuple element.
460+
size_t stackIndex = scope.exprStack.size();
461+
size_t stackTupleIndex = 0;
462+
size_t childIndex = children.size();
463+
size_t childTupleIndex = 0;
464+
435465
// Check whether the values on the stack will be able to meet the given
436466
// requirements.
437467
while (true) {
@@ -458,8 +488,7 @@ struct IRBuilder::ChildPopper
458488
// the input unreachable instruction is executed first. If we are
459489
// not reaching past an unreachable, the error will be caught when
460490
// we pop.
461-
needUnreachableFallback = true;
462-
goto pop;
491+
return true;
463492
}
464493
--stackIndex;
465494
stackTupleIndex = scope.exprStack[stackIndex]->type.size() - 1;
@@ -483,13 +512,11 @@ struct IRBuilder::ChildPopper
483512
// Always succeeds.
484513
} else if (constraint.isAnyReference()) {
485514
if (!type.isRef() && type != Type::unreachable) {
486-
needUnreachableFallback = true;
487-
break;
515+
return true;
488516
}
489517
} else if (auto bound = constraint.getSubtype()) {
490518
if (!Type::isSubType(type, *bound)) {
491-
needUnreachableFallback = true;
492-
break;
519+
return true;
493520
}
494521
} else if (constraint.isAnyI8ArrayReference()) {
495522
bool isI8Array =
@@ -498,8 +525,7 @@ struct IRBuilder::ChildPopper
498525
bool isNone =
499526
type.isRef() && type.getHeapType().isMaybeShared(HeapType::none);
500527
if (!isI8Array && !isNone && type != Type::unreachable) {
501-
needUnreachableFallback = true;
502-
break;
528+
return true;
503529
}
504530
} else if (constraint.isAnyI16ArrayReference()) {
505531
bool isI16Array =
@@ -508,8 +534,7 @@ struct IRBuilder::ChildPopper
508534
bool isNone =
509535
type.isRef() && type.getHeapType().isMaybeShared(HeapType::none);
510536
if (!isI16Array && !isNone && type != Type::unreachable) {
511-
needUnreachableFallback = true;
512-
break;
537+
return true;
513538
}
514539
} else {
515540
WASM_UNREACHABLE("unexpected constraint");
@@ -518,34 +543,10 @@ struct IRBuilder::ChildPopper
518543

519544
// No problems for children after this unreachable.
520545
if (type == Type::unreachable) {
521-
assert(!needUnreachableFallback);
522546
unreachableIndex = stackIndex;
523547
}
524548
}
525-
526-
pop:
527-
// We have checked all the constraints, so we are ready to pop children.
528-
for (int i = children.size() - 1; i >= 0; --i) {
529-
if (needUnreachableFallback &&
530-
scope.exprStack.size() == *unreachableIndex + 1 && i > 0) {
531-
// The next item on the stack is the unreachable instruction we must
532-
// not pop past. We cannot insert unreachables in front of it because
533-
// it might be a branch we actually have to execute, so this next item
534-
// must be child 0. But we are not ready to pop child 0 yet, so
535-
// synthesize an unreachable instead of popping. The deeper
536-
// instructions that would otherwise have been popped will remain on
537-
// the stack to become prior children of future expressions or to be
538-
// implicitly dropped at the end of the scope.
539-
*children[i].childp = builder.builder.makeUnreachable();
540-
continue;
541-
}
542-
543-
// Pop a child normally.
544-
auto val = pop(children[i].constraint.size());
545-
CHECK_ERR(val);
546-
*children[i].childp = *val;
547-
}
548-
return Ok{};
549+
return false;
549550
}
550551

551552
Result<Expression*> pop(size_t size) {

0 commit comments

Comments
 (0)