diff --git a/src/de/inetsoftware/jwebassembly/module/BranchManger.java b/src/de/inetsoftware/jwebassembly/module/BranchManger.java index a45b584..e3d1760 100644 --- a/src/de/inetsoftware/jwebassembly/module/BranchManger.java +++ b/src/de/inetsoftware/jwebassembly/module/BranchManger.java @@ -290,6 +290,30 @@ class BranchManger { * the not consumed operations in the parent branch */ private void calculateIf( BranchNode parent, IfParsedBlock startBlock, List parsedOperations ) { + IfPositions positions = searchElsePosition( startBlock, parsedOperations ); + + BranchNode main = parent; + for( int i = 0; i < positions.ifCount; i++ ) { + IfParsedBlock parsedBlock = (IfParsedBlock)parsedOperations.remove( 0 ); + if( startBlock.endPosition < positions.thenPos || startBlock.endPosition == positions.elsePos ) { + // AND concatenation (&& operator) + int pos = parsedBlock.startPosition + 1; + main.add( new BranchNode( startBlock.nextPosition, pos, WasmBlockOperator.IF, null ) ); + main.add( new BranchNode( pos, pos + 1, WasmBlockOperator.ELSE, WasmBlockOperator.END ) ); + startBlock.negateCompare(); + insertConstBeforePosition( 0, pos + 1, parsedBlock.lineNumber ); // 0 --> FALSE for the next if expression + } else { + // OR concatenation (|| operator) + int pos = startBlock.startPosition + 2; // startBlock.startPosition is the position of the compare operation which need before this if construct + main.add( new BranchNode( pos, startBlock.nextPosition, WasmBlockOperator.IF, null ) ); + BranchNode node = new BranchNode( startBlock.nextPosition, positions.thenPos, WasmBlockOperator.ELSE, WasmBlockOperator.END ); + main.add( node ); + main = node; + insertConstBeforePosition( 1, pos + 1, startBlock.lineNumber ); // 1 --> TRUE for the next if expression + } + startBlock = parsedBlock; + } + int i = 0; int endPos = Math.min( startBlock.endPosition, parent.endPos ); int startPos = startBlock.nextPosition; @@ -298,7 +322,6 @@ class BranchManger { parent.add( new BranchNode( startPos, startPos, WasmBlockOperator.BR_IF, null, 0 ) ); return; } - IfPositions positions = searchElsePosition( startBlock, parsedOperations ); BranchNode branch = null; for( ; i < parsedOperations.size(); i++ ) { ParsedBlock parsedBlock = parsedOperations.get( i ); @@ -345,29 +368,6 @@ class BranchManger { break; } - if( i== 0 && parsedBlock.op == JavaBlockOperator.IF ) { - // AND concatenation (&& operator) - if( endPos == positions.elsePos && parsedBlock.endPosition == positions.elsePos ) { - parent.add( new BranchNode( startPos, parsedBlock.nextPosition - 1, WasmBlockOperator.IF, null ) ); - parent.add( new BranchNode( parsedBlock.nextPosition - 1, parsedBlock.nextPosition, WasmBlockOperator.ELSE, WasmBlockOperator.END ) ); - startPos = parsedBlock.nextPosition; - parsedOperations.remove( 0 ); - i--; - ((IfParsedBlock)parsedBlock).negateCompare(); - insertConstBeforePosition( 0, startPos, parsedBlock.lineNumber ); // 0 --> FALSE for the next if expression - continue; - } - - // OR concatenation (|| operator) - if( startBlock.endPosition == parsedBlock.endPosition || startBlock.endPosition == parsedBlock.nextPosition ) { - int pos = startBlock.startPosition + 1; // startBlock.startPosition is the position of the compare operation which need before this if construct - parent.add( new BranchNode( pos, startPos, WasmBlockOperator.IF, null ) ); - parent.add( new BranchNode( startPos, endPos, WasmBlockOperator.ELSE, WasmBlockOperator.END ) ); - insertConstBeforePosition( 1, pos+1, startBlock.lineNumber ); // 1 --> TRUE for the next if expression - return; - } - } - } if( branch == null ) { @@ -800,11 +800,13 @@ class BranchManger { int nextCodePosition = instr.getCodePosition(); if( nextCodePosition <= codePosition ) { continue; - } else { - codePosition = nextCodePosition; - lineNumber = instr.getLineNumber(); } - idx = root.handle( codePosition, instructions, idx, lineNumber ); + lineNumber = instr.getLineNumber(); + do { + // call it for every position for the case that a Jump is call to a intermediate position + codePosition++; + idx = root.handle( codePosition, instructions, idx, lineNumber ); + } while( codePosition < nextCodePosition ); } root.handle( byteCode.getCodePosition(), instructions, instructions.size(), byteCode.getLineNumber() ); diff --git a/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java b/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java index 1fd9158..f54fed4 100644 --- a/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java +++ b/test/de/inetsoftware/jwebassembly/runtime/ControlFlowOperators.java @@ -66,6 +66,11 @@ public class ControlFlowOperators extends AbstractBaseTest { addParam( list, script, "ifOr3" ); addParam( list, script, "ifOr5" ); addParam( list, script, "ifOr7" ); + addParam( list, script, "ifAndOr0" ); + addParam( list, script, "ifAndOr2" ); + addParam( list, script, "ifAndOr4" ); + addParam( list, script, "ifAndOr6" ); + addParam( list, script, "ifAndOr8" ); } rule.setTestParameters( list ); return list; @@ -410,5 +415,40 @@ public class ControlFlowOperators extends AbstractBaseTest { } return result; } + + @Export + static int ifAndOr0() { + return ifAndOr( 0 ); + } + + @Export + static int ifAndOr2() { + return ifAndOr( 2 ); + } + + @Export + static int ifAndOr4() { + return ifAndOr( 4 ); + } + + @Export + static int ifAndOr6() { + return ifAndOr( 6 ); + } + + @Export + static int ifAndOr8() { + return ifAndOr( 8 ); + } + + private static int ifAndOr( int condition ) { + int result; + if( (condition >= 1 && condition <= 3) || (condition >= 5 && condition <= 7) ) { + result = 42; + } else { + result = 76; + } + return result; + } } }