Normalize empty THEN blocks to fix concated conditional operators

This commit is contained in:
Volker Berlin 2021-12-26 20:17:15 +01:00
parent c9e34715c9
commit d68c74f032
2 changed files with 45 additions and 15 deletions

View File

@ -160,6 +160,7 @@ class BranchManger {
addLoops();
List<ParsedBlock> parsedOperations = allParsedOperations;
Collections.sort( parsedOperations );
normalizeEmptyThenBlocks( parsedOperations );
calculate( root, parsedOperations );
for( BreakBlock breakBlock : breakOperations ) {
calculateBreak( breakBlock );
@ -283,6 +284,40 @@ class BranchManger {
instructions.add( conditionIdx++, new WasmBlockInstruction( WasmBlockOperator.BR_IF, 1, conditionNew, gotoBlock.lineNumber ) );
}
/**
* Normalize all empty THEN blocks like:
*
* <pre>
* if (condition) {
* } else {
* ....
* }
* </pre>
*
* are changed to: if (!condition) { .... }
* </pre>
* The THEN block contains only a single GOTO operation. This operation is removed and the IF condition is negate.
* The removing of the GOTO operation make it easer to convert it to a valid WebAssembly structure without GOTO.
*
* @param parsedOperations
* the parsed operations
*/
private static void normalizeEmptyThenBlocks( List<ParsedBlock> parsedOperations ) {
// occur also with cascaded conditional operator like: int result = (a < 0 ? false : a == c ) && (b < 0 ? false : b == c ) ? 17 : 18;
for( int i = 0; i < parsedOperations.size() - 1; i++ ) {
ParsedBlock ifBlock = parsedOperations.get( i );
if( ifBlock.op == JavaBlockOperator.IF ) {
ParsedBlock nextBlock = parsedOperations.get( i + 1 );
if( nextBlock.op == JavaBlockOperator.GOTO && nextBlock.startPosition == ifBlock.nextPosition
&& ifBlock.endPosition == nextBlock.nextPosition ) {
((IfParsedBlock)ifBlock).negateCompare();
ifBlock.endPosition = nextBlock.endPosition;
parsedOperations.remove( i + 1 );
}
}
}
}
/**
* Calculate the branch tree for the given branch and parsed sub operations.
*
@ -400,21 +435,6 @@ class BranchManger {
// end position can not be outside of the parent
endPos = Math.min( parsedBlock.endPosition, parent.endPos );
// special case if there is only one goto in the IF block. Occur with goto_w
if( parsedBlock.startPosition == startPos ) {
int nextPos = Math.min( parsedBlock.endPosition, parent.endPos );
for( int j = i; j < parsedOperations.size(); j++ ) {
ParsedBlock parsedBlock2 = parsedOperations.get( j );
if( parsedBlock2.nextPosition == nextPos && parsedBlock2.op == JavaBlockOperator.GOTO && parsedBlock2.startPosition < parsedBlock2.endPosition ) {
parsedOperations.remove( j );
positions.elsePos = nextPos;
endPos = parsedBlock2.endPosition;
startBlock.negateCompare();
i = j;
}
}
}
branch = new BranchNode( startPos, positions.elsePos, WasmBlockOperator.IF, null );
parent.add( branch );
if( i > 0 ) {

View File

@ -54,6 +54,7 @@ public class ControlFlowOperators extends AbstractBaseTest {
addParam( list, script, "forLoop" );
addParam( list, script, "conditionalOperator" );
addParam( list, script, "conditionalOperator2" );
addParam( list, script, "conditionalOperatorConcated" );
addParam( list, script, "redifineVariable" );
addParam( list, script, "ifAnd_0" );
addParam( list, script, "ifAnd_3" );
@ -371,6 +372,15 @@ public class ControlFlowOperators extends AbstractBaseTest {
return result;
}
@Export
static int conditionalOperatorConcated () {
int a = 7;
int b = 13;
int c = 42;
int result = (a < 0 ? false : a == c ) && (b < 0 ? false : b == c ) ? 3 : 4;
return result;
}
@Export
static double redifineVariable() {
int x = 42;