diff --git a/src/de/inetsoftware/jwebassembly/module/BranchManger.java b/src/de/inetsoftware/jwebassembly/module/BranchManger.java index 8622ac6..3cd8d4d 100644 --- a/src/de/inetsoftware/jwebassembly/module/BranchManger.java +++ b/src/de/inetsoftware/jwebassembly/module/BranchManger.java @@ -160,6 +160,7 @@ class BranchManger { addLoops(); List 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: + * + *
+     * if (condition) {
+     * } else {
+     *      ....
+     * }
+     * 
+ * + * are changed to: if (!condition) { .... } + * + * 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 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 ) { diff --git a/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java b/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java index cca9042..195687c 100644 --- a/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java +++ b/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java @@ -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;