mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-15 02:44:47 +01:00
Implements the ELSE control structure
This commit is contained in:
parent
e633fc79b5
commit
79ee98e8ce
@ -470,6 +470,22 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case gt:
|
||||
switch( valueType ) {
|
||||
case i32:
|
||||
op = I32_GT_S;
|
||||
break;
|
||||
case i64:
|
||||
op = I64_NE;
|
||||
break;
|
||||
case f32:
|
||||
op = F32_NE;
|
||||
break;
|
||||
case f64:
|
||||
op = F64_NE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if( op == 0 ) {
|
||||
throw new Error( valueType + "." + numOp );
|
||||
@ -527,6 +543,9 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
||||
codeStream.write( IF );
|
||||
codeStream.write( 0x40 ); // void; the return type of the block. currently we does not use it
|
||||
break;
|
||||
case ELSE:
|
||||
codeStream.write( ELSE );
|
||||
break;
|
||||
case END:
|
||||
codeStream.write( END );
|
||||
break;
|
||||
|
@ -1,3 +1,19 @@
|
||||
/*
|
||||
Copyright 2018 Volker Berlin (i-net software)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
package de.inetsoftware.jwebassembly.module;
|
||||
|
||||
/**
|
||||
@ -8,5 +24,7 @@ package de.inetsoftware.jwebassembly.module;
|
||||
*/
|
||||
public enum BlockOperator {
|
||||
IF,
|
||||
ELSE,
|
||||
END,
|
||||
GOTO,
|
||||
}
|
||||
|
@ -1,7 +1,23 @@
|
||||
/*
|
||||
Copyright 2018 Volker Berlin (i-net software)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
package de.inetsoftware.jwebassembly.module;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import de.inetsoftware.classparser.CodeInputStream;
|
||||
|
||||
@ -13,20 +29,79 @@ import de.inetsoftware.classparser.CodeInputStream;
|
||||
*/
|
||||
class BranchManger {
|
||||
|
||||
private final ArrayDeque<Block> stack = new ArrayDeque<>();
|
||||
private final ArrayList<Block> stack = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Remove all branch information.
|
||||
*/
|
||||
void reset() {
|
||||
stack.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new block.
|
||||
*
|
||||
* @param op
|
||||
* the start operation
|
||||
* @param basePosition
|
||||
* @param startPosition
|
||||
* the byte position of the start position
|
||||
* @param offset
|
||||
* the relative jump position
|
||||
*/
|
||||
void start( BlockOperator op, int basePosition, int offset ) {
|
||||
stack.push( new Block( op, basePosition, offset ) );
|
||||
void start( BlockOperator op, int startPosition, int offset ) {
|
||||
stack.add( new Block( op, startPosition, offset ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate all block operators from the parsed information.
|
||||
*/
|
||||
void calculate() {
|
||||
for( int i = 0; i < stack.size(); i++ ) {
|
||||
Block block = stack.get( i );
|
||||
switch( block.op ) {
|
||||
case IF:
|
||||
caculateIf( i, block );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the ELSE and END position of an IF control structure.
|
||||
*
|
||||
* @param i
|
||||
* the index in the stack
|
||||
* @param startBlock
|
||||
* the start block of the if control structure
|
||||
*/
|
||||
private void caculateIf( int i, Block startBlock ) {
|
||||
i++;
|
||||
int gotoPos = startBlock.endPosition - 3; // 3 - byte size of goto instruction
|
||||
for( ; i < stack.size(); i++ ) {
|
||||
Block block = stack.get( i );
|
||||
if( block.startPosition == gotoPos && block.op == BlockOperator.GOTO ) {
|
||||
block.op = BlockOperator.ELSE;
|
||||
block.startPosition += 3;
|
||||
startBlock = block;
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
if( block.startPosition > gotoPos ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the index in the stack to add the END operator
|
||||
*/
|
||||
int endPos = startBlock.endPosition;
|
||||
for( ; i < stack.size(); i++ ) {
|
||||
Block block = stack.get( i );
|
||||
if( block.startPosition >= endPos ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
stack.add( i, new Block( BlockOperator.END, endPos, 0 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -40,13 +115,14 @@ class BranchManger {
|
||||
* if any I/O exception occur
|
||||
*/
|
||||
void handle( CodeInputStream byteCode, ModuleWriter writer ) throws IOException {
|
||||
if( stack.isEmpty() ) {
|
||||
return;
|
||||
}
|
||||
int position = byteCode.getCodePosition();
|
||||
Block block = stack.peek();
|
||||
if( block != null ) {
|
||||
if( block.endPosition == position ) {
|
||||
writer.writeBlockCode( BlockOperator.END );
|
||||
stack.pop();
|
||||
}
|
||||
Block block = stack.get( 0 );
|
||||
if( block.startPosition == position ) {
|
||||
writer.writeBlockCode( block.op );
|
||||
stack.remove( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,14 +132,14 @@ class BranchManger {
|
||||
private static class Block {
|
||||
private BlockOperator op;
|
||||
|
||||
private int basePosition;
|
||||
private int startPosition;
|
||||
|
||||
private int endPosition;
|
||||
|
||||
private Block( BlockOperator op, int basePosition, int offset ) {
|
||||
private Block( BlockOperator op, int startPosition, int offset ) {
|
||||
this.op = op;
|
||||
this.basePosition = basePosition;
|
||||
this.endPosition = basePosition + offset;
|
||||
this.startPosition = startPosition;
|
||||
this.endPosition = startPosition + offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 Volker Berlin (i-net software)
|
||||
* Copyright 2017 - 2018 Volker Berlin (i-net software)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -32,7 +32,6 @@ import de.inetsoftware.classparser.Code;
|
||||
import de.inetsoftware.classparser.CodeInputStream;
|
||||
import de.inetsoftware.classparser.ConstantPool;
|
||||
import de.inetsoftware.classparser.ConstantRef;
|
||||
import de.inetsoftware.classparser.LineNumberTable;
|
||||
import de.inetsoftware.classparser.LocalVariableTable;
|
||||
import de.inetsoftware.classparser.MethodInfo;
|
||||
import de.inetsoftware.jwebassembly.WasmException;
|
||||
@ -132,21 +131,15 @@ public abstract class ModuleWriter implements Closeable {
|
||||
writeMethodSignature( method );
|
||||
locals.clear();
|
||||
localTable = code.getLocalVariableTable();
|
||||
LineNumberTable lineNumberTable = code.getLineNumberTable();
|
||||
if( lineNumberTable != null ) {
|
||||
int lineNumber;
|
||||
for( int i = 0; i < lineNumberTable.size(); i++ ) {
|
||||
lineNumber = lineNumberTable.getLineNumber( i );
|
||||
int offset = lineNumberTable.getStartOffset( i );
|
||||
int nextOffset =
|
||||
i + 1 == lineNumberTable.size() ? code.getCodeSize()
|
||||
: lineNumberTable.getStartOffset( i + 1 );
|
||||
CodeInputStream byteCode = code.getByteCode( offset, nextOffset - offset );
|
||||
writeCodeChunk( byteCode, lineNumber, method.getConstantPool() );
|
||||
}
|
||||
} else {
|
||||
CodeInputStream byteCode = code.getByteCode();
|
||||
writeCodeChunk( byteCode, -1, method.getConstantPool() );
|
||||
|
||||
branchManager.reset();
|
||||
for( CodeInputStream byteCode : code.getByteCodes() ) {
|
||||
prepareBranchManager( byteCode, byteCode.getLineNumber() );
|
||||
}
|
||||
branchManager.calculate();
|
||||
|
||||
for( CodeInputStream byteCode : code.getByteCodes() ) {
|
||||
writeCodeChunk( byteCode, byteCode.getLineNumber(), method.getConstantPool() );
|
||||
}
|
||||
for( int i = Math.min( paramCount, locals.size() ); i > 0; i-- ) {
|
||||
locals.remove( 0 );
|
||||
@ -290,6 +283,72 @@ public abstract class ModuleWriter implements Closeable {
|
||||
*/
|
||||
protected abstract void writeMethodFinish( List<ValueType> locals ) throws IOException;
|
||||
|
||||
/**
|
||||
* Write a chunk of byte code.
|
||||
*
|
||||
* @param byteCode
|
||||
* a stream of byte code
|
||||
* @param lineNumber
|
||||
* the current line number
|
||||
* @throws WasmException
|
||||
* if some Java code can't converted
|
||||
*/
|
||||
private void prepareBranchManager( CodeInputStream byteCode, int lineNumber ) throws WasmException {
|
||||
try {
|
||||
while( byteCode.available() > 0 ) {
|
||||
int op = byteCode.readUnsignedByte();
|
||||
switch( op ) {
|
||||
case 16: // bipush
|
||||
case 18: // ldc
|
||||
case 21: //iload
|
||||
case 22: //lload
|
||||
case 23: //fload
|
||||
case 24: //dload
|
||||
case 25: //aload
|
||||
case 54: // istore
|
||||
case 55: // lstore
|
||||
case 56: // fstore
|
||||
case 57: // dstore
|
||||
case 58: // astore
|
||||
case 179: // putstatic
|
||||
case 181: // putfield
|
||||
byteCode.skip(1);
|
||||
break;
|
||||
case 17: // sipush
|
||||
case 20: // ldc2_w
|
||||
case 132: // iinc
|
||||
case 184: // invokestatic
|
||||
byteCode.skip( 2);
|
||||
break;
|
||||
case 153: // ifeq
|
||||
case 154: // ifne
|
||||
case 155: // iflt
|
||||
case 156: // ifge
|
||||
case 157: // ifgt
|
||||
case 158: // ifle
|
||||
case 159: // if_icmpeq
|
||||
case 160: // if_icmpne
|
||||
case 161: // if_icmplt
|
||||
case 162: // if_icmpge
|
||||
case 163: // if_icmpgt
|
||||
case 164: // if_icmple
|
||||
case 165: // if_acmpeq
|
||||
case 166: // if_acmpne
|
||||
int startPosition = byteCode.getCodePosition() + 2;
|
||||
int offset = byteCode.readUnsignedShort();
|
||||
branchManager.start( BlockOperator.IF, startPosition, offset - 3 );
|
||||
break;
|
||||
case 167: // goto
|
||||
startPosition = byteCode.getCodePosition() - 1;
|
||||
offset = byteCode.readUnsignedShort();
|
||||
branchManager.start( BlockOperator.GOTO, startPosition, offset );
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch( Exception ex ) {
|
||||
throw WasmException.create( ex, sourceFile, lineNumber );
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Write a chunk of byte code.
|
||||
*
|
||||
@ -502,10 +561,11 @@ public abstract class ModuleWriter implements Closeable {
|
||||
case 154: // ifne
|
||||
opIfCondition( NumericOperator.eq, byteCode );
|
||||
break;
|
||||
case 155: // iflt
|
||||
opIfCondition( NumericOperator.gt, byteCode );
|
||||
break;
|
||||
case 167: // goto
|
||||
int baseCodePosition = byteCode.getCodePosition() - 1;
|
||||
int offset = byteCode.readUnsignedShort();
|
||||
if(true)throw new WasmException( "Unimplemented byte code operation: " + op, sourceFile, lineNumber );
|
||||
byteCode.skip(2);
|
||||
break;
|
||||
case 172: // ireturn
|
||||
case 173: // lreturn
|
||||
@ -541,12 +601,10 @@ public abstract class ModuleWriter implements Closeable {
|
||||
* if any I/O errors occur.
|
||||
*/
|
||||
private void opIfCondition( NumericOperator numOp, CodeInputStream byteCode ) throws IOException {
|
||||
int baseCodePosition = byteCode.getCodePosition() - 1;
|
||||
int offset = byteCode.readUnsignedShort();
|
||||
branchManager.start( BlockOperator.IF, baseCodePosition, offset );
|
||||
byteCode.skip(2);
|
||||
writeConstInt( 0 );
|
||||
writeNumericOperator( numOp, ValueType.i32 );
|
||||
writeBlockCode( BlockOperator.IF );
|
||||
//writeBlockCode( BlockOperator.IF );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 Volker Berlin (i-net software)
|
||||
* Copyright 2017 - 2018 Volker Berlin (i-net software)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -32,4 +32,6 @@ public enum NumericOperator {
|
||||
shr_u,
|
||||
eq,
|
||||
ne,
|
||||
gt,
|
||||
lt_s,
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 Volker Berlin (i-net software)
|
||||
* Copyright 2017 - 2018 Volker Berlin (i-net software)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -234,6 +234,12 @@ public class TextModuleWriter extends ModuleWriter {
|
||||
methodOutput.append( "if" );
|
||||
inset++;
|
||||
break;
|
||||
case ELSE:
|
||||
inset--;
|
||||
newline( methodOutput );
|
||||
methodOutput.append( "else" );
|
||||
inset++;
|
||||
break;
|
||||
case END:
|
||||
inset--;
|
||||
newline( methodOutput );
|
||||
|
Loading…
x
Reference in New Issue
Block a user