mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-15 02:44:47 +01:00
support the do while(condition) loop
This commit is contained in:
parent
9b3993450e
commit
0c83869a81
@ -100,14 +100,21 @@ class BranchManger {
|
||||
*/
|
||||
private void addLoops() {
|
||||
for( ParsedBlock parsedBlock : allParsedOperations ) {
|
||||
if( parsedBlock.op == JavaBlockOperator.GOTO && parsedBlock.startPosition > parsedBlock.endPosition ) {
|
||||
int start = parsedBlock.endPosition;
|
||||
ParsedBlock loop = loops.get( start );
|
||||
if( loop == null ) {
|
||||
loop = new ParsedBlock( JavaBlockOperator.LOOP, start, 0, parsedBlock.lineNumber );
|
||||
loops.put( start, loop );
|
||||
if( parsedBlock.startPosition > parsedBlock.endPosition ) {
|
||||
switch ( parsedBlock.op ) {
|
||||
case GOTO: // do while(true) loop; Continue
|
||||
case IF: // do while(condition) loop
|
||||
int start = parsedBlock.endPosition;
|
||||
ParsedBlock loop = loops.get( start );
|
||||
if( loop == null ) {
|
||||
loop = new ParsedBlock( JavaBlockOperator.LOOP, start, 0, parsedBlock.lineNumber );
|
||||
loops.put( start, loop );
|
||||
}
|
||||
loop.endPosition = parsedBlock.startPosition + 3;
|
||||
break;
|
||||
default:
|
||||
throw new WasmException( "Unimplemented loop code operation: " + parsedBlock.op, null, parsedBlock.lineNumber );
|
||||
}
|
||||
loop.endPosition = parsedBlock.startPosition + 3;
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,13 +162,19 @@ class BranchManger {
|
||||
private void caculateIf( BranchNode parent, ParsedBlock startBlock, List<ParsedBlock> parsedOperations ) {
|
||||
int i = 0;
|
||||
int endPos = Math.min( startBlock.endPosition, parent.endPos );
|
||||
int startPos = startBlock.startPosition + 3;
|
||||
if( startPos > endPos ) {
|
||||
// the condition in a do while(condition) loop
|
||||
parent.add( new BranchNode( startPos, startPos, WasmBlockOperator.BR_IF, null, 0 ) );
|
||||
return;
|
||||
}
|
||||
int gotoPos = endPos - 3; // 3 - byte size of goto instruction
|
||||
BranchNode branch = null;
|
||||
for( ; i < parsedOperations.size(); i++ ) {
|
||||
ParsedBlock parsedBlock = parsedOperations.get( i );
|
||||
if( parsedBlock.startPosition == gotoPos && parsedBlock.op == JavaBlockOperator.GOTO && parsedBlock.startPosition < parsedBlock.endPosition) {
|
||||
parsedOperations.remove( i );
|
||||
branch = new BranchNode( startBlock.startPosition, startBlock.endPosition, WasmBlockOperator.IF, null );
|
||||
branch = new BranchNode( startPos, startBlock.endPosition, WasmBlockOperator.IF, null );
|
||||
parent.add( branch );
|
||||
if( i > 0 ) {
|
||||
calculate( branch, parsedOperations.subList( 0, i ) );
|
||||
@ -177,7 +190,7 @@ class BranchManger {
|
||||
}
|
||||
|
||||
if( branch == null ) {
|
||||
branch = new BranchNode( startBlock.startPosition, endPos, WasmBlockOperator.IF, WasmBlockOperator.END );
|
||||
branch = new BranchNode( startPos, endPos, WasmBlockOperator.IF, WasmBlockOperator.END );
|
||||
parent.add( branch );
|
||||
}
|
||||
|
||||
|
@ -466,7 +466,7 @@ public class ModuleGenerator {
|
||||
case 165: // if_acmpeq
|
||||
case 166: // if_acmpne
|
||||
int offset = byteCode.readShort();
|
||||
branchManager.start( JavaBlockOperator.IF, codePosition + 3, offset - 3, lineNumber );
|
||||
branchManager.start( JavaBlockOperator.IF, codePosition, offset, lineNumber );
|
||||
break;
|
||||
case 167: // goto
|
||||
offset = byteCode.readShort();
|
||||
@ -864,40 +864,40 @@ public class ModuleGenerator {
|
||||
opCompare( ValueType.f64, byteCode );
|
||||
break;
|
||||
case 153: // ifeq
|
||||
opIfCondition( NumericOperator.ne, byteCode );
|
||||
opIfCondition( NumericOperator.ne, NumericOperator.eq, byteCode );
|
||||
break;
|
||||
case 154: // ifne
|
||||
opIfCondition( NumericOperator.eq, byteCode );
|
||||
opIfCondition( NumericOperator.eq, NumericOperator.ne, byteCode );
|
||||
break;
|
||||
case 155: // iflt
|
||||
opIfCondition( NumericOperator.ge_s, byteCode );
|
||||
opIfCondition( NumericOperator.ge_s, NumericOperator.lt_s, byteCode );
|
||||
break;
|
||||
case 156: // ifge
|
||||
opIfCondition( NumericOperator.lt_s, byteCode );
|
||||
opIfCondition( NumericOperator.lt_s, NumericOperator.ge_s, byteCode );
|
||||
break;
|
||||
case 157: // ifgt
|
||||
opIfCondition( NumericOperator.le_s, byteCode );
|
||||
opIfCondition( NumericOperator.le_s, NumericOperator.gt, byteCode );
|
||||
break;
|
||||
case 158: // ifle
|
||||
opIfCondition( NumericOperator.gt, byteCode );
|
||||
opIfCondition( NumericOperator.gt, NumericOperator.le_s, byteCode );
|
||||
break;
|
||||
case 159: // if_icmpeq
|
||||
opIfCompareCondition( NumericOperator.ne, byteCode );
|
||||
opIfCompareCondition( NumericOperator.ne, NumericOperator.eq, byteCode );
|
||||
break;
|
||||
case 160: // if_icmpne
|
||||
opIfCompareCondition( NumericOperator.eq, byteCode );
|
||||
opIfCompareCondition( NumericOperator.eq, NumericOperator.ne, byteCode );
|
||||
break;
|
||||
case 161: // if_icmplt
|
||||
opIfCompareCondition( NumericOperator.ge_s, byteCode );
|
||||
opIfCompareCondition( NumericOperator.ge_s, NumericOperator.lt_s, byteCode );
|
||||
break;
|
||||
case 162: // if_icmpge
|
||||
opIfCompareCondition( NumericOperator.lt_s, byteCode );
|
||||
opIfCompareCondition( NumericOperator.lt_s, NumericOperator.ge_s, byteCode );
|
||||
break;
|
||||
case 163: // if_icmpgt
|
||||
opIfCompareCondition( NumericOperator.le_s, byteCode );
|
||||
opIfCompareCondition( NumericOperator.le_s, NumericOperator.gt, byteCode );
|
||||
break;
|
||||
case 164: // if_icmple
|
||||
opIfCompareCondition( NumericOperator.gt, byteCode );
|
||||
opIfCompareCondition( NumericOperator.gt, NumericOperator.le_s, byteCode );
|
||||
break;
|
||||
//TODO case 165: // if_acmpeq
|
||||
//TODO case 166: // if_acmpne
|
||||
@ -1029,37 +1029,40 @@ public class ModuleGenerator {
|
||||
|
||||
/**
|
||||
* Handle the if<condition> of the Java byte code. This Java instruction compare the first stack value with value 0.
|
||||
* Important: In Java the condition for the jump to the else block is saved. In WebAssembler we need to use
|
||||
* Important: In the Java IF expression the condition for the jump to the else block is saved. In WebAssembler we need to use
|
||||
* condition for the if block. The caller of the method must already negate this
|
||||
*
|
||||
* @param numOp
|
||||
* The condition for the if block.
|
||||
* @param byteCode
|
||||
* current byte code stream to read the taget offset.
|
||||
* @throws IOException
|
||||
* if any I/O errors occur.
|
||||
*/
|
||||
private void opIfCondition( NumericOperator numOp, CodeInputStream byteCode ) throws IOException {
|
||||
byteCode.skip(2);
|
||||
writer.writeConstInt( 0 );
|
||||
writer.writeNumericOperator( numOp, ValueType.i32 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the if<condition> of the Java byte code. This Java instruction compare the first stack value with value 0.
|
||||
* Important: In Java the condition for the jump to the else block is saved. In WebAssembler we need to use
|
||||
* condition for the if block. The caller of the method must already negate this
|
||||
*
|
||||
* @param numOp
|
||||
* @param ifNumOp
|
||||
* The condition for the if block.
|
||||
* @param continueNumOp
|
||||
* The condition for the continue of a loop.
|
||||
* @param byteCode
|
||||
* current byte code stream to read the target offset.
|
||||
* @throws IOException
|
||||
* if any I/O errors occur.
|
||||
*/
|
||||
private void opIfCompareCondition( NumericOperator numOp, CodeInputStream byteCode ) throws IOException {
|
||||
byteCode.skip(2);
|
||||
writer.writeNumericOperator( numOp, ValueType.i32 );
|
||||
private void opIfCondition( NumericOperator ifNumOp, NumericOperator continueNumOp, CodeInputStream byteCode ) throws IOException {
|
||||
writer.writeConstInt( 0 );
|
||||
opIfCompareCondition( ifNumOp, continueNumOp, byteCode );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the if<condition> of the Java byte code. This Java instruction compare 2 values from stack.
|
||||
* Important: In the Java IF expression the condition for the jump to the else block is saved. In WebAssembler we need to use
|
||||
* condition for the if block. The caller of the method must already negate this.
|
||||
*
|
||||
* @param ifNumOp
|
||||
* The condition for the if block.
|
||||
* @param continueNumOp
|
||||
* The condition for the continue of a loop.
|
||||
* @param byteCode
|
||||
* current byte code stream to read the target offset.
|
||||
* @throws IOException
|
||||
* if any I/O errors occur.
|
||||
*/
|
||||
private void opIfCompareCondition( NumericOperator ifNumOp, NumericOperator continueNumOp, CodeInputStream byteCode ) throws IOException {
|
||||
int offset = byteCode.readShort();
|
||||
writer.writeNumericOperator( offset > 0 ? ifNumOp : continueNumOp, ValueType.i32 );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -46,6 +46,7 @@ public class ControlFlowOperators extends AbstractBaseTest {
|
||||
addParam( list, script, "ifCompare" );
|
||||
addParam( list, script, "switchDirect" );
|
||||
addParam( list, script, "endlessLoop" );
|
||||
addParam( list, script, "doWhileLoop" );
|
||||
addParam( list, script, "forLoop" );
|
||||
}
|
||||
return list;
|
||||
@ -198,6 +199,17 @@ public class ControlFlowOperators extends AbstractBaseTest {
|
||||
} while( true );
|
||||
}
|
||||
|
||||
@Export
|
||||
static double doWhileLoop() {
|
||||
int a = 0;
|
||||
double d = 1.01;
|
||||
do {
|
||||
d *= 2;
|
||||
a++;
|
||||
} while( a < 10 );
|
||||
return d;
|
||||
}
|
||||
|
||||
@Export
|
||||
static int forLoop() {
|
||||
int a = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user