mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-25 07:27:52 +01:00
Handle Conditional operator inside an if expression
This commit is contained in:
parent
fec40f1d40
commit
87be1faafe
@ -62,6 +62,9 @@ class BranchManger {
|
|||||||
|
|
||||||
private TryCatchFinally[] exceptionTable;
|
private TryCatchFinally[] exceptionTable;
|
||||||
|
|
||||||
|
private final ArrayList<BreakBlock> breakOperations = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a branch manager.
|
* Create a branch manager.
|
||||||
*
|
*
|
||||||
@ -88,7 +91,7 @@ class BranchManger {
|
|||||||
allParsedOperations.clear();
|
allParsedOperations.clear();
|
||||||
root.clear();
|
root.clear();
|
||||||
loops.clear();
|
loops.clear();
|
||||||
root.endPos = code.getCodeSize();
|
root.endPos = root.elseEndPos = code.getCodeSize();
|
||||||
exceptionTable = code.getExceptionTable();
|
exceptionTable = code.getExceptionTable();
|
||||||
for( TryCatchFinally ex : exceptionTable ) {
|
for( TryCatchFinally ex : exceptionTable ) {
|
||||||
if ( ex.getStart() == ex.getHandler() ) {
|
if ( ex.getStart() == ex.getHandler() ) {
|
||||||
@ -161,6 +164,9 @@ class BranchManger {
|
|||||||
List<ParsedBlock> parsedOperations = allParsedOperations;
|
List<ParsedBlock> parsedOperations = allParsedOperations;
|
||||||
Collections.sort( parsedOperations );
|
Collections.sort( parsedOperations );
|
||||||
calculate( root, parsedOperations );
|
calculate( root, parsedOperations );
|
||||||
|
for( BreakBlock breakBlock : breakOperations ) {
|
||||||
|
calculateBreak( breakBlock );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -393,6 +399,7 @@ class BranchManger {
|
|||||||
branch.add( new BranchNode( positions.elsePos, endPos, WasmBlockOperator.BR, null, breakDeep + 1 ) );
|
branch.add( new BranchNode( positions.elsePos, endPos, WasmBlockOperator.BR, null, breakDeep + 1 ) );
|
||||||
endPos = branch.endPos;
|
endPos = branch.endPos;
|
||||||
} else {
|
} else {
|
||||||
|
branch.elseEndPos = endPos;
|
||||||
branch = new BranchNode( positions.elsePos, endPos, WasmBlockOperator.ELSE, WasmBlockOperator.END );
|
branch = new BranchNode( positions.elsePos, endPos, WasmBlockOperator.ELSE, WasmBlockOperator.END );
|
||||||
parent.add( branch );
|
parent.add( branch );
|
||||||
}
|
}
|
||||||
@ -406,6 +413,29 @@ class BranchManger {
|
|||||||
if( branch == null ) {
|
if( branch == null ) {
|
||||||
branch = new BranchNode( startPos, endPos, WasmBlockOperator.IF, WasmBlockOperator.END, ValueType.empty );
|
branch = new BranchNode( startPos, endPos, WasmBlockOperator.IF, WasmBlockOperator.END, ValueType.empty );
|
||||||
parent.add( branch );
|
parent.add( branch );
|
||||||
|
if( startBlock.endPosition > parent.endPos ) {
|
||||||
|
int count = 0;
|
||||||
|
for( int j = 0; j < instructions.size(); j++ ) {
|
||||||
|
WasmInstruction instr = instructions.get( j );
|
||||||
|
int pos = instr.getCodePosition();
|
||||||
|
if( pos < startPos ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if( pos >= endPos ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if( instr.getType() == Type.Jump ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if( count == 0 ) {
|
||||||
|
// we jump outside the parent and there are no instructions. This is lie a conditional break
|
||||||
|
//TODO should be BR_IF
|
||||||
|
breakOperations.add( new BreakBlock( branch, startBlock.endPosition ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
startBlock.negateCompare();
|
startBlock.negateCompare();
|
||||||
|
|
||||||
@ -585,7 +615,7 @@ class BranchManger {
|
|||||||
private int calculateBreakDeep( BranchNode parent, int endPos ) {
|
private int calculateBreakDeep( BranchNode parent, int endPos ) {
|
||||||
int deep = -1;
|
int deep = -1;
|
||||||
boolean wasLoop = false;
|
boolean wasLoop = false;
|
||||||
while( parent != null && parent.endPos == endPos && parent.data == null ) {
|
while( parent != null && parent.elseEndPos <= endPos && parent.data == null ) {
|
||||||
deep++;
|
deep++;
|
||||||
wasLoop |= parent.startOp == WasmBlockOperator.LOOP; // only in a loop we need to jump for exit
|
wasLoop |= parent.startOp == WasmBlockOperator.LOOP; // only in a loop we need to jump for exit
|
||||||
parent = parent.parent;
|
parent = parent.parent;
|
||||||
@ -1160,6 +1190,43 @@ class BranchManger {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the break to the block hierarchy. Add an extra block if needed and correct the break deep of other
|
||||||
|
* instructions.
|
||||||
|
*
|
||||||
|
* @param breakBlock
|
||||||
|
* the description of the break.
|
||||||
|
*/
|
||||||
|
private void calculateBreak( BreakBlock breakBlock ) {
|
||||||
|
int deep = -1;
|
||||||
|
int gotoEndPos = breakBlock.endPosition;
|
||||||
|
BranchNode branch = breakBlock.branch;
|
||||||
|
BranchNode parent = branch;
|
||||||
|
while( parent != null && parent.elseEndPos < gotoEndPos ) {
|
||||||
|
deep++;
|
||||||
|
parent = parent.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( parent != null && parent.elseEndPos > gotoEndPos ) {
|
||||||
|
BranchNode middleNode = new BranchNode( parent.startPos, gotoEndPos, WasmBlockOperator.BLOCK, WasmBlockOperator.END );
|
||||||
|
for( Iterator<BranchNode> it = parent.iterator(); it.hasNext(); ) {
|
||||||
|
BranchNode child = it.next();
|
||||||
|
if( child.endPos > gotoEndPos ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
middleNode.add( child );
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
parent.add( middleNode );
|
||||||
|
//deep++;
|
||||||
|
parent = middleNode;
|
||||||
|
patchBrDeep( middleNode );
|
||||||
|
}
|
||||||
|
|
||||||
|
BranchNode breakNode = new BranchNode( branch.endPos, branch.endPos, WasmBlockOperator.BR, null, deep + 1 );
|
||||||
|
branch.add( breakNode );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check on every instruction position if there any branch is ending
|
* Check on every instruction position if there any branch is ending
|
||||||
*
|
*
|
||||||
@ -1349,6 +1416,8 @@ class BranchManger {
|
|||||||
*/
|
*/
|
||||||
private int startIdx;
|
private int startIdx;
|
||||||
|
|
||||||
|
private int elseEndPos;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new description.
|
* Create a new description.
|
||||||
*
|
*
|
||||||
@ -1381,7 +1450,7 @@ class BranchManger {
|
|||||||
*/
|
*/
|
||||||
BranchNode( int startPos, int endPos, WasmBlockOperator startOp, WasmBlockOperator endOp, Object data ) {
|
BranchNode( int startPos, int endPos, WasmBlockOperator startOp, WasmBlockOperator endOp, Object data ) {
|
||||||
this.startPos = startPos;
|
this.startPos = startPos;
|
||||||
this.endPos = endPos;
|
this.endPos = this.elseEndPos = endPos;
|
||||||
this.startOp = startOp;
|
this.startOp = startOp;
|
||||||
this.endOp = endOp;
|
this.endOp = endOp;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
@ -1539,4 +1608,27 @@ class BranchManger {
|
|||||||
/** The position of the first instruction in the ELSE part. */
|
/** The position of the first instruction in the ELSE part. */
|
||||||
private int elsePos;
|
private int elsePos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Described a break to a block that will be added later.
|
||||||
|
*/
|
||||||
|
private static class BreakBlock {
|
||||||
|
|
||||||
|
private final int endPosition;
|
||||||
|
|
||||||
|
private final BranchNode branch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create Break
|
||||||
|
*
|
||||||
|
* @param branch
|
||||||
|
* the parent block which should contain the break
|
||||||
|
* @param endPosition
|
||||||
|
* the Jump position
|
||||||
|
*/
|
||||||
|
public BreakBlock( BranchNode branch, int endPosition ) {
|
||||||
|
this.endPosition = endPosition;
|
||||||
|
this.branch = branch;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,6 +74,10 @@ public class ControlFlowOperators extends AbstractBaseTest {
|
|||||||
addParam( list, script, "ifOrWithMulti" );
|
addParam( list, script, "ifOrWithMulti" );
|
||||||
addParam( list, script, "ifMultipleInsideThen" );
|
addParam( list, script, "ifMultipleInsideThen" );
|
||||||
addParam( list, script, "ifWithConditionalInsideThen" );
|
addParam( list, script, "ifWithConditionalInsideThen" );
|
||||||
|
addParam( list, script, "conditionalInsideIf_1" );
|
||||||
|
addParam( list, script, "conditionalInsideIf_2" );
|
||||||
|
addParam( list, script, "conditionalInsideIf_3" );
|
||||||
|
addParam( list, script, "conditionalInsideIf_4" );
|
||||||
addParam( list, script, "stringSwitchNormalFoo" );
|
addParam( list, script, "stringSwitchNormalFoo" );
|
||||||
addParam( list, script, "stringSwitchNormalBar" );
|
addParam( list, script, "stringSwitchNormalBar" );
|
||||||
addParam( list, script, "stringSwitchNormalDefault" );
|
addParam( list, script, "stringSwitchNormalDefault" );
|
||||||
@ -547,7 +551,7 @@ public class ControlFlowOperators extends AbstractBaseTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Export
|
@Export
|
||||||
static int ifWithConditionalInsideThen() throws CloneNotSupportedException {
|
static int ifWithConditionalInsideThen() {
|
||||||
int val = 42;
|
int val = 42;
|
||||||
int result = 0;
|
int result = 0;
|
||||||
if( val > 20 ) {
|
if( val > 20 ) {
|
||||||
@ -560,6 +564,34 @@ public class ControlFlowOperators extends AbstractBaseTest {
|
|||||||
return result + 13;
|
return result + 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Export
|
||||||
|
static int conditionalInsideIf_1() {
|
||||||
|
return conditionalInsideIf( null, null, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Export
|
||||||
|
static int conditionalInsideIf_2() {
|
||||||
|
return conditionalInsideIf( null, null, "foo" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Export
|
||||||
|
static int conditionalInsideIf_3() {
|
||||||
|
return conditionalInsideIf( "foo", null, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Export
|
||||||
|
static int conditionalInsideIf_4() {
|
||||||
|
return conditionalInsideIf( null, "foo", null );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int conditionalInsideIf( Object a, Object b, Object c ) {
|
||||||
|
if( (a == null ? b == null : a == b ) ) {
|
||||||
|
return c == null ? 1 : 2;
|
||||||
|
} else {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Export
|
@Export
|
||||||
static int stringSwitchNormalFoo() {
|
static int stringSwitchNormalFoo() {
|
||||||
return stringSwitchNormal( "foo" );
|
return stringSwitchNormal( "foo" );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user