Use the normal break handling for the GOTO in the CASEs of an SWITCH. This eliminates the need to calculate the end of the SWITCH structure. #43

This commit is contained in:
Volker Berlin 2022-06-06 15:21:14 +02:00
parent c392afc76f
commit 442e0c896c
No known key found for this signature in database
GPG Key ID: 988423EF815BE4CB
2 changed files with 55 additions and 57 deletions

View File

@ -940,55 +940,7 @@ class BranchManager {
}
}
// handle the GOTO (breaks) at the end of the CASE blocks.
int lastBlockPosition = lastPosition;
for( Iterator<ParsedBlock> it = parsedOperations.iterator(); it.hasNext(); ) {
ParsedBlock parsedBlock = it.next();
int start = parsedBlock.startPosition;
if( start >= lastBlockPosition ) {
break;
}
switch( parsedBlock.op ) {
case GOTO:
case IF:
int end = parsedBlock.endPosition;
if( start < end ) {
BranchNode branch = blockNode;
while( branch.size() > 0 ) {
BranchNode node = branch.get( 0 );
if( start > node.endPos ) {
if( end >= branch.endPos ) {
blockCount = 0;
BranchNode parentNode = branch;
while( parentNode != null && end > parentNode.endPos ) {
parentNode = parentNode.parent;
blockCount++;
}
WasmBlockOperator startOp;
if( parsedBlock.op == JavaBlockOperator.GOTO ) {
startOp = WasmBlockOperator.BR;
lastPosition = Math.max( lastPosition, end );
} else {
startOp = WasmBlockOperator.BR_IF;
instructions.remove( ((IfParsedBlock)parsedBlock).jump );
}
start++;
branch.add( new BranchNode( start, start, startOp, null, blockCount ) );
it.remove();
}
break;
}
branch = node;
}
}
}
}
// Create the main block around the switch
BranchNode switchNode = new BranchNode( startPosition, lastPosition, WasmBlockOperator.BLOCK, WasmBlockOperator.END, switchType );
switchNode.add( blockNode );
parent.add( switchNode );
parent.add( blockNode );
if( brTableNode != null ) {
// sort back in the natural order and create a br_table
@ -1000,11 +952,11 @@ class BranchManager {
brTableNode.data = data;
}
for( int i = 0; i < cases.length; i++ ) {
switchCase = cases[i];
calculateSubOperations( switchCase.node, parsedOperations );
}
calculateSubOperations( switchNode, parsedOperations );
blockNode = cases[0].node;
do {
calculateSubOperations( blockNode, parsedOperations );
blockNode = blockNode.parent;
} while( blockNode != parent );
}
/**
@ -1473,8 +1425,7 @@ class BranchManager {
* @return the new node
*/
private BranchNode addMiddleNode( BranchNode parent, int startPos, int endPos ) {
Object data = parent.data == switchType && parent.startPos == startPos ? switchType : null;
BranchNode middleNode = new BranchNode( startPos, endPos, WasmBlockOperator.BLOCK, WasmBlockOperator.END, data );
BranchNode middleNode = new BranchNode( startPos, endPos, WasmBlockOperator.BLOCK, WasmBlockOperator.END );
int idx = 0;
for( Iterator<BranchNode> it = parent.iterator(); it.hasNext(); ) {
BranchNode child = it.next();
@ -1488,8 +1439,18 @@ class BranchManager {
middleNode.add( child );
it.remove();
}
// use same input parameter if parent or child start on same position
if( parent.startPos == startPos ) {
middleNode.data = parent.data;
} else if( middleNode.size() > 0 ) {
BranchNode child = middleNode.get( 0 );
if( child.startPos == startPos ) {
middleNode.data = child.data;
}
}
parent.add( idx, middleNode );
parent = middleNode;
patchBrDeep( middleNode );
return middleNode;
}

View File

@ -47,6 +47,7 @@ public class ControlFlowOperators extends AbstractBaseTest {
addParam( list, script, "ifCompare" );
addParam( list, script, "switchDirect" );
addParam( list, script, "switchWithConditionMethodParams" );
addParam( list, script, "switchWithConditionSelect" );
addParam( list, script, "endlessLoop" );
addParam( list, script, "doWhileLoop" );
addParam( list, script, "doWhileLoopTwoConditions" );
@ -303,6 +304,42 @@ public class ControlFlowOperators extends AbstractBaseTest {
return last;
}
@Export
private static int switchWithConditionSelect() {
boolean cond = true;
int c1 = 1;
int c2 = 2;
int b;
switch( cond ? c1 : c2 ) {
case 1:
b = 17;
switch( cond ? c1 : c2 ) {
case 1:
b = 13;
break;
case 2:
b = 14;
break;
}
break;
case 2:
case 1001:
if( c1 == 1000 ) {
b = 1000;
break;
} else {
b = 1001;
}
//$FALL-THROUGH$
case Integer.MAX_VALUE:
b = 3;
break;
default:
b = 9;
}
return b;
}
@Export
static int endlessLoop() {
int a = 0;