mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-25 07:27:52 +01:00
Handle a GOTO instruction that come from a CONTINUE in a loop.
This commit is contained in:
parent
296df907b8
commit
effd5813c9
@ -183,6 +183,7 @@ class BranchManger {
|
|||||||
loop = new ParsedBlock( JavaBlockOperator.LOOP, start, 0, start, parsedBlock.lineNumber );
|
loop = new ParsedBlock( JavaBlockOperator.LOOP, start, 0, start, parsedBlock.lineNumber );
|
||||||
loops.put( start, loop );
|
loops.put( start, loop );
|
||||||
}
|
}
|
||||||
|
loop.nextPosition = parsedBlock.startPosition; // Jump position for Continue
|
||||||
loop.endPosition = parsedBlock.nextPosition;
|
loop.endPosition = parsedBlock.nextPosition;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -262,7 +263,7 @@ class BranchManger {
|
|||||||
for( i = 0; i < instructions.size(); i++ ) {
|
for( i = 0; i < instructions.size(); i++ ) {
|
||||||
WasmInstruction instr = instructions.get( i );
|
WasmInstruction instr = instructions.get( i );
|
||||||
int codePos = instr.getCodePosition();
|
int codePos = instr.getCodePosition();
|
||||||
if( codePos == nextPos ) {
|
if( codePos == nextPos && conditionIdx < 0 ) {
|
||||||
conditionIdx = i;
|
conditionIdx = i;
|
||||||
}
|
}
|
||||||
if( codePos >= conditionEnd ) {
|
if( codePos >= conditionEnd ) {
|
||||||
@ -276,6 +277,7 @@ class BranchManger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gotoBlock.op = JavaBlockOperator.LOOP;
|
gotoBlock.op = JavaBlockOperator.LOOP;
|
||||||
|
gotoBlock.nextPosition = conditionStart; // Jump position for Continue
|
||||||
gotoBlock.endPosition = conditionEnd;
|
gotoBlock.endPosition = conditionEnd;
|
||||||
instructions.add( i, new WasmBlockInstruction( WasmBlockOperator.BR, 0, conditionNew, gotoBlock.lineNumber ) );
|
instructions.add( i, new WasmBlockInstruction( WasmBlockOperator.BR, 0, conditionNew, gotoBlock.lineNumber ) );
|
||||||
instructions.add( conditionIdx++, new WasmBlockInstruction( WasmBlockOperator.BR_IF, 1, conditionNew, gotoBlock.lineNumber ) );
|
instructions.add( conditionIdx++, new WasmBlockInstruction( WasmBlockOperator.BR_IF, 1, conditionNew, gotoBlock.lineNumber ) );
|
||||||
@ -312,6 +314,33 @@ class BranchManger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a break to the node if the block jump to the continue position of an outer loop.
|
||||||
|
*
|
||||||
|
* @param parent
|
||||||
|
* the container for adding the break
|
||||||
|
* @param startBlock
|
||||||
|
* an IF or GOTO block.
|
||||||
|
* @return true, if the break was added
|
||||||
|
*/
|
||||||
|
private boolean addBreakIfLoopContinue( BranchNode parent, ParsedBlock startBlock ) {
|
||||||
|
BranchNode main = parent;
|
||||||
|
int endPos = startBlock.endPosition;
|
||||||
|
int breakDeep = 0;
|
||||||
|
while( main != null ) {
|
||||||
|
if( main.startOp == WasmBlockOperator.LOOP && main.continuePos == endPos ) {
|
||||||
|
// possible operation values here are IF and GOTO
|
||||||
|
WasmBlockOperator op = startBlock.op == JavaBlockOperator.IF ? WasmBlockOperator.BR_IF : WasmBlockOperator.BR;
|
||||||
|
int startPos = startBlock.nextPosition;
|
||||||
|
parent.add( new BranchNode( startPos, startPos, op, null, breakDeep ) );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
main = main.parent;
|
||||||
|
breakDeep++;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the ELSE and END position of an IF control structure.
|
* Calculate the ELSE and END position of an IF control structure.
|
||||||
*
|
*
|
||||||
@ -326,6 +355,10 @@ class BranchManger {
|
|||||||
instructions.remove( startBlock.jump );
|
instructions.remove( startBlock.jump );
|
||||||
IfPositions positions = searchElsePosition( startBlock, parsedOperations );
|
IfPositions positions = searchElsePosition( startBlock, parsedOperations );
|
||||||
|
|
||||||
|
if( addBreakIfLoopContinue( parent, startBlock ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
BranchNode main = parent;
|
BranchNode main = parent;
|
||||||
for( int i = 0; i < positions.ifCount; i++ ) {
|
for( int i = 0; i < positions.ifCount; i++ ) {
|
||||||
IfParsedBlock parsedBlock = (IfParsedBlock)parsedOperations.remove( 0 );
|
IfParsedBlock parsedBlock = (IfParsedBlock)parsedOperations.remove( 0 );
|
||||||
@ -389,6 +422,11 @@ class BranchManger {
|
|||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( addBreakIfLoopContinue( branch, parsedBlock ) ) {
|
||||||
|
branch.endOp = WasmBlockOperator.END;
|
||||||
|
endPos = branch.endPos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
// if with block type signature must have an else block
|
// if with block type signature must have an else block
|
||||||
int breakDeep = calculateBreakDeep( parent, endPos );
|
int breakDeep = calculateBreakDeep( parent, endPos );
|
||||||
if( breakDeep > 0 ) {
|
if( breakDeep > 0 ) {
|
||||||
@ -863,6 +901,29 @@ class BranchManger {
|
|||||||
blockInstr.setData( data + 1 );
|
blockInstr.setData( data + 1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
patchBrDeepInTree( newNode, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Patch the existing BR instructions in the tree after a new BLOCK node was injected in the hierarchy. The break position must
|
||||||
|
* only increment if the old break position is outside of the new BLOCK.
|
||||||
|
*
|
||||||
|
* @param newNode
|
||||||
|
* the new node
|
||||||
|
* @param deep
|
||||||
|
* the deep of recursion
|
||||||
|
*/
|
||||||
|
private void patchBrDeepInTree( BranchNode newNode, int deep ) {
|
||||||
|
for( BranchNode node : newNode ) {
|
||||||
|
if( node.startOp == WasmBlockOperator.BR || node.startOp == WasmBlockOperator.BR_IF ) {
|
||||||
|
Integer data = (Integer)node.data;
|
||||||
|
if( data >= deep ) {
|
||||||
|
node.data = data + 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
patchBrDeepInTree( node, deep + 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -906,6 +967,7 @@ class BranchManger {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//breakOperations.add( new BreakBlock( parent, jump ) );
|
||||||
throw new WasmException( "GOTO code without target loop/block. Jump from " + start + " to " + jump, gotoBlock.lineNumber );
|
throw new WasmException( "GOTO code without target loop/block. Jump from " + start + " to " + jump, gotoBlock.lineNumber );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -922,6 +984,7 @@ class BranchManger {
|
|||||||
BranchNode blockNode = new BranchNode( loopBlock.startPosition, loopBlock.endPosition, WasmBlockOperator.BLOCK, WasmBlockOperator.END );
|
BranchNode blockNode = new BranchNode( loopBlock.startPosition, loopBlock.endPosition, WasmBlockOperator.BLOCK, WasmBlockOperator.END );
|
||||||
parent.add( blockNode );
|
parent.add( blockNode );
|
||||||
BranchNode loopNode = new BranchNode( loopBlock.startPosition, loopBlock.endPosition, WasmBlockOperator.LOOP, WasmBlockOperator.END );
|
BranchNode loopNode = new BranchNode( loopBlock.startPosition, loopBlock.endPosition, WasmBlockOperator.LOOP, WasmBlockOperator.END );
|
||||||
|
loopNode.continuePos = loopBlock.nextPosition;
|
||||||
blockNode.add( loopNode );
|
blockNode.add( loopNode );
|
||||||
|
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
@ -1415,6 +1478,9 @@ class BranchManger {
|
|||||||
|
|
||||||
private int elseEndPos;
|
private int elseEndPos;
|
||||||
|
|
||||||
|
/** jump position for a CONTINUE in a loop */
|
||||||
|
private int continuePos;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new description.
|
* Create a new description.
|
||||||
*
|
*
|
||||||
|
@ -50,6 +50,7 @@ public class ControlFlowOperators extends AbstractBaseTest {
|
|||||||
addParam( list, script, "doWhileLoopTwoConditions" );
|
addParam( list, script, "doWhileLoopTwoConditions" );
|
||||||
addParam( list, script, "doWhileLoopWithBreak" );
|
addParam( list, script, "doWhileLoopWithBreak" );
|
||||||
addParam( list, script, "whileLoop" );
|
addParam( list, script, "whileLoop" );
|
||||||
|
addParam( list, script, "whileLoopWithContinue" );
|
||||||
addParam( list, script, "forLoop" );
|
addParam( list, script, "forLoop" );
|
||||||
addParam( list, script, "conditionalOperator" );
|
addParam( list, script, "conditionalOperator" );
|
||||||
addParam( list, script, "conditionalOperator2" );
|
addParam( list, script, "conditionalOperator2" );
|
||||||
@ -334,6 +335,20 @@ public class ControlFlowOperators extends AbstractBaseTest {
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Export
|
||||||
|
public static int whileLoopWithContinue() {
|
||||||
|
int i = 0;
|
||||||
|
int value = 0;
|
||||||
|
while( i < 16 ) {
|
||||||
|
i++;
|
||||||
|
if( i > 8 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
value |= 1 << i;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
@Export
|
@Export
|
||||||
static int forLoop() {
|
static int forLoop() {
|
||||||
int a = 0;
|
int a = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user