mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-25 07:27:52 +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() {
|
private void addLoops() {
|
||||||
for( ParsedBlock parsedBlock : allParsedOperations ) {
|
for( ParsedBlock parsedBlock : allParsedOperations ) {
|
||||||
if( parsedBlock.op == JavaBlockOperator.GOTO && parsedBlock.startPosition > parsedBlock.endPosition ) {
|
if( parsedBlock.startPosition > parsedBlock.endPosition ) {
|
||||||
int start = parsedBlock.endPosition;
|
switch ( parsedBlock.op ) {
|
||||||
ParsedBlock loop = loops.get( start );
|
case GOTO: // do while(true) loop; Continue
|
||||||
if( loop == null ) {
|
case IF: // do while(condition) loop
|
||||||
loop = new ParsedBlock( JavaBlockOperator.LOOP, start, 0, parsedBlock.lineNumber );
|
int start = parsedBlock.endPosition;
|
||||||
loops.put( start, loop );
|
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 ) {
|
private void caculateIf( BranchNode parent, ParsedBlock startBlock, List<ParsedBlock> parsedOperations ) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int endPos = Math.min( startBlock.endPosition, parent.endPos );
|
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
|
int gotoPos = endPos - 3; // 3 - byte size of goto instruction
|
||||||
BranchNode branch = null;
|
BranchNode branch = null;
|
||||||
for( ; i < parsedOperations.size(); i++ ) {
|
for( ; i < parsedOperations.size(); i++ ) {
|
||||||
ParsedBlock parsedBlock = parsedOperations.get( i );
|
ParsedBlock parsedBlock = parsedOperations.get( i );
|
||||||
if( parsedBlock.startPosition == gotoPos && parsedBlock.op == JavaBlockOperator.GOTO && parsedBlock.startPosition < parsedBlock.endPosition) {
|
if( parsedBlock.startPosition == gotoPos && parsedBlock.op == JavaBlockOperator.GOTO && parsedBlock.startPosition < parsedBlock.endPosition) {
|
||||||
parsedOperations.remove( i );
|
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 );
|
parent.add( branch );
|
||||||
if( i > 0 ) {
|
if( i > 0 ) {
|
||||||
calculate( branch, parsedOperations.subList( 0, i ) );
|
calculate( branch, parsedOperations.subList( 0, i ) );
|
||||||
@ -177,7 +190,7 @@ class BranchManger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( branch == null ) {
|
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 );
|
parent.add( branch );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,7 +466,7 @@ public class ModuleGenerator {
|
|||||||
case 165: // if_acmpeq
|
case 165: // if_acmpeq
|
||||||
case 166: // if_acmpne
|
case 166: // if_acmpne
|
||||||
int offset = byteCode.readShort();
|
int offset = byteCode.readShort();
|
||||||
branchManager.start( JavaBlockOperator.IF, codePosition + 3, offset - 3, lineNumber );
|
branchManager.start( JavaBlockOperator.IF, codePosition, offset, lineNumber );
|
||||||
break;
|
break;
|
||||||
case 167: // goto
|
case 167: // goto
|
||||||
offset = byteCode.readShort();
|
offset = byteCode.readShort();
|
||||||
@ -864,40 +864,40 @@ public class ModuleGenerator {
|
|||||||
opCompare( ValueType.f64, byteCode );
|
opCompare( ValueType.f64, byteCode );
|
||||||
break;
|
break;
|
||||||
case 153: // ifeq
|
case 153: // ifeq
|
||||||
opIfCondition( NumericOperator.ne, byteCode );
|
opIfCondition( NumericOperator.ne, NumericOperator.eq, byteCode );
|
||||||
break;
|
break;
|
||||||
case 154: // ifne
|
case 154: // ifne
|
||||||
opIfCondition( NumericOperator.eq, byteCode );
|
opIfCondition( NumericOperator.eq, NumericOperator.ne, byteCode );
|
||||||
break;
|
break;
|
||||||
case 155: // iflt
|
case 155: // iflt
|
||||||
opIfCondition( NumericOperator.ge_s, byteCode );
|
opIfCondition( NumericOperator.ge_s, NumericOperator.lt_s, byteCode );
|
||||||
break;
|
break;
|
||||||
case 156: // ifge
|
case 156: // ifge
|
||||||
opIfCondition( NumericOperator.lt_s, byteCode );
|
opIfCondition( NumericOperator.lt_s, NumericOperator.ge_s, byteCode );
|
||||||
break;
|
break;
|
||||||
case 157: // ifgt
|
case 157: // ifgt
|
||||||
opIfCondition( NumericOperator.le_s, byteCode );
|
opIfCondition( NumericOperator.le_s, NumericOperator.gt, byteCode );
|
||||||
break;
|
break;
|
||||||
case 158: // ifle
|
case 158: // ifle
|
||||||
opIfCondition( NumericOperator.gt, byteCode );
|
opIfCondition( NumericOperator.gt, NumericOperator.le_s, byteCode );
|
||||||
break;
|
break;
|
||||||
case 159: // if_icmpeq
|
case 159: // if_icmpeq
|
||||||
opIfCompareCondition( NumericOperator.ne, byteCode );
|
opIfCompareCondition( NumericOperator.ne, NumericOperator.eq, byteCode );
|
||||||
break;
|
break;
|
||||||
case 160: // if_icmpne
|
case 160: // if_icmpne
|
||||||
opIfCompareCondition( NumericOperator.eq, byteCode );
|
opIfCompareCondition( NumericOperator.eq, NumericOperator.ne, byteCode );
|
||||||
break;
|
break;
|
||||||
case 161: // if_icmplt
|
case 161: // if_icmplt
|
||||||
opIfCompareCondition( NumericOperator.ge_s, byteCode );
|
opIfCompareCondition( NumericOperator.ge_s, NumericOperator.lt_s, byteCode );
|
||||||
break;
|
break;
|
||||||
case 162: // if_icmpge
|
case 162: // if_icmpge
|
||||||
opIfCompareCondition( NumericOperator.lt_s, byteCode );
|
opIfCompareCondition( NumericOperator.lt_s, NumericOperator.ge_s, byteCode );
|
||||||
break;
|
break;
|
||||||
case 163: // if_icmpgt
|
case 163: // if_icmpgt
|
||||||
opIfCompareCondition( NumericOperator.le_s, byteCode );
|
opIfCompareCondition( NumericOperator.le_s, NumericOperator.gt, byteCode );
|
||||||
break;
|
break;
|
||||||
case 164: // if_icmple
|
case 164: // if_icmple
|
||||||
opIfCompareCondition( NumericOperator.gt, byteCode );
|
opIfCompareCondition( NumericOperator.gt, NumericOperator.le_s, byteCode );
|
||||||
break;
|
break;
|
||||||
//TODO case 165: // if_acmpeq
|
//TODO case 165: // if_acmpeq
|
||||||
//TODO case 166: // if_acmpne
|
//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.
|
* 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
|
* 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 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
|
|
||||||
* The condition for the if block.
|
* The condition for the if block.
|
||||||
|
* @param continueNumOp
|
||||||
|
* The condition for the continue of a loop.
|
||||||
* @param byteCode
|
* @param byteCode
|
||||||
* current byte code stream to read the target offset.
|
* current byte code stream to read the target offset.
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* if any I/O errors occur.
|
* if any I/O errors occur.
|
||||||
*/
|
*/
|
||||||
private void opIfCompareCondition( NumericOperator numOp, CodeInputStream byteCode ) throws IOException {
|
private void opIfCondition( NumericOperator ifNumOp, NumericOperator continueNumOp, CodeInputStream byteCode ) throws IOException {
|
||||||
byteCode.skip(2);
|
writer.writeConstInt( 0 );
|
||||||
writer.writeNumericOperator( numOp, ValueType.i32 );
|
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, "ifCompare" );
|
||||||
addParam( list, script, "switchDirect" );
|
addParam( list, script, "switchDirect" );
|
||||||
addParam( list, script, "endlessLoop" );
|
addParam( list, script, "endlessLoop" );
|
||||||
|
addParam( list, script, "doWhileLoop" );
|
||||||
addParam( list, script, "forLoop" );
|
addParam( list, script, "forLoop" );
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
@ -198,6 +199,17 @@ public class ControlFlowOperators extends AbstractBaseTest {
|
|||||||
} while( true );
|
} while( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Export
|
||||||
|
static double doWhileLoop() {
|
||||||
|
int a = 0;
|
||||||
|
double d = 1.01;
|
||||||
|
do {
|
||||||
|
d *= 2;
|
||||||
|
a++;
|
||||||
|
} while( a < 10 );
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
@Export
|
@Export
|
||||||
static int forLoop() {
|
static int forLoop() {
|
||||||
int a = 0;
|
int a = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user