mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-25 07:27:52 +01:00
Improve the loop compiling and add support for while{} loops with condition on loop start.
This commit is contained in:
parent
9c1215720d
commit
f2942bffc5
@ -110,7 +110,8 @@ class BranchManger {
|
|||||||
* virtual loop operator on the target position of GOTO operators with a negative offset.
|
* virtual loop operator on the target position of GOTO operators with a negative offset.
|
||||||
*/
|
*/
|
||||||
private void addLoops() {
|
private void addLoops() {
|
||||||
for( ParsedBlock parsedBlock : allParsedOperations ) {
|
for( int b = 0; b < allParsedOperations.size(); b++ ) {
|
||||||
|
ParsedBlock parsedBlock = allParsedOperations.get( b );
|
||||||
if( parsedBlock.startPosition > parsedBlock.endPosition ) {
|
if( parsedBlock.startPosition > parsedBlock.endPosition ) {
|
||||||
switch ( parsedBlock.op ) {
|
switch ( parsedBlock.op ) {
|
||||||
case GOTO: // do while(true) loop; Continue
|
case GOTO: // do while(true) loop; Continue
|
||||||
@ -126,6 +127,57 @@ class BranchManger {
|
|||||||
default:
|
default:
|
||||||
throw new WasmException( "Unimplemented loop code operation: " + parsedBlock.op, null, parsedBlock.lineNumber );
|
throw new WasmException( "Unimplemented loop code operation: " + parsedBlock.op, null, parsedBlock.lineNumber );
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
switch ( parsedBlock.op ) {
|
||||||
|
case GOTO:
|
||||||
|
// forward GOTO can be a while(condition) loop.
|
||||||
|
// while(condition) {
|
||||||
|
// ....
|
||||||
|
// }
|
||||||
|
// will be compiled from Java to:
|
||||||
|
// GOTO CONDITION:
|
||||||
|
// START:
|
||||||
|
// ....
|
||||||
|
// CONDITION:
|
||||||
|
// if<cond> START:
|
||||||
|
// we can not match this in WASM because a missing GOTO that we need to move the condition to the start of the loop
|
||||||
|
int nextPos = parsedBlock.startPosition + 3;
|
||||||
|
for( int n = b + 1; n < allParsedOperations.size(); n++ ) {
|
||||||
|
ParsedBlock nextBlock = allParsedOperations.get( n );
|
||||||
|
if( nextBlock.op == JavaBlockOperator.IF && nextBlock.endPosition == nextPos ) {
|
||||||
|
int conditionStart = parsedBlock.endPosition; // 15
|
||||||
|
int conditionEnd = nextBlock.startPosition + 3; // 22
|
||||||
|
int conditionNew = parsedBlock.startPosition; // 4
|
||||||
|
int conditionIdx = -1;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for( i = 0; i < instructions.size(); i++ ) {
|
||||||
|
WasmInstruction instr = instructions.get( i );
|
||||||
|
int codePos = instr.getCodePosition();
|
||||||
|
if( codePos == nextPos ) {
|
||||||
|
conditionIdx = i;
|
||||||
|
}
|
||||||
|
if( codePos >= conditionEnd ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if( codePos >= conditionStart ) {
|
||||||
|
instr.setCodePosition( conditionNew );
|
||||||
|
instructions.remove( i );
|
||||||
|
instructions.add( conditionIdx++, instr );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedBlock.op = JavaBlockOperator.LOOP;
|
||||||
|
parsedBlock.endPosition = conditionEnd;
|
||||||
|
allParsedOperations.remove( n );
|
||||||
|
instructions.add( i, new WasmBlockInstruction( WasmBlockOperator.BR, 0, conditionNew ) );
|
||||||
|
instructions.add( conditionIdx++, new WasmBlockInstruction( WasmBlockOperator.BR_IF, 1, conditionNew ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,8 +243,16 @@ class BranchManger {
|
|||||||
calculate( branch, parsedOperations.subList( 0, i ) );
|
calculate( branch, parsedOperations.subList( 0, i ) );
|
||||||
}
|
}
|
||||||
endPos = parsedBlock.endPosition;
|
endPos = parsedBlock.endPosition;
|
||||||
branch = new BranchNode( startBlock.endPosition, endPos, WasmBlockOperator.ELSE, WasmBlockOperator.END );
|
|
||||||
parent.add( branch );
|
int breakDeep = calculateBreakDeep( parent, endPos );
|
||||||
|
if( breakDeep >= 0 ) {
|
||||||
|
branch.endOp = WasmBlockOperator.END;
|
||||||
|
branch.add( new BranchNode( startBlock.endPosition, endPos, WasmBlockOperator.BR, null, breakDeep + 1 ) );
|
||||||
|
endPos = branch.endPos;
|
||||||
|
} else {
|
||||||
|
branch = new BranchNode( startBlock.endPosition, endPos, WasmBlockOperator.ELSE, WasmBlockOperator.END );
|
||||||
|
parent.add( branch );
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if( parsedBlock.startPosition > gotoPos ) {
|
if( parsedBlock.startPosition > gotoPos ) {
|
||||||
@ -219,6 +279,24 @@ class BranchManger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the deep of a break.
|
||||||
|
*
|
||||||
|
* @param parent
|
||||||
|
* the current parent node.
|
||||||
|
* @param endPos
|
||||||
|
* the end position of the jump
|
||||||
|
* @return the deep level for "br" or -1 if there is no parent node with this end position
|
||||||
|
*/
|
||||||
|
private int calculateBreakDeep( BranchNode parent, int endPos ) {
|
||||||
|
int deep = -1;
|
||||||
|
while( parent != null && parent.endPos == endPos ) {
|
||||||
|
deep++;
|
||||||
|
parent = parent.parent;
|
||||||
|
}
|
||||||
|
return deep;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the blocks of a switch.
|
* Calculate the blocks of a switch.
|
||||||
*
|
*
|
||||||
@ -418,8 +496,10 @@ class BranchManger {
|
|||||||
* the not consumed operations in the parent branch
|
* the not consumed operations in the parent branch
|
||||||
*/
|
*/
|
||||||
private void caculateLoop ( BranchNode parent, ParsedBlock loopBlock, List<ParsedBlock> parsedOperations ) {
|
private void caculateLoop ( BranchNode parent, ParsedBlock loopBlock, List<ParsedBlock> parsedOperations ) {
|
||||||
|
BranchNode blockNode = new BranchNode( loopBlock.startPosition, loopBlock.endPosition, WasmBlockOperator.BLOCK, WasmBlockOperator.END );
|
||||||
|
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 );
|
||||||
parent.add( loopNode );
|
blockNode.add( loopNode );
|
||||||
|
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for( ; idx < parsedOperations.size(); idx++ ) {
|
for( ; idx < parsedOperations.size(); idx++ ) {
|
||||||
@ -502,7 +582,7 @@ class BranchManger {
|
|||||||
|
|
||||||
private final WasmBlockOperator startOp;
|
private final WasmBlockOperator startOp;
|
||||||
|
|
||||||
private final WasmBlockOperator endOp;
|
private WasmBlockOperator endOp;
|
||||||
|
|
||||||
private Object data;
|
private Object data;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user