mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-25 15:37:52 +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;
|
||||||
}
|
}
|
||||||
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 ) {
|
if( op == 0 ) {
|
||||||
throw new Error( valueType + "." + numOp );
|
throw new Error( valueType + "." + numOp );
|
||||||
@ -527,6 +543,9 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
|||||||
codeStream.write( IF );
|
codeStream.write( IF );
|
||||||
codeStream.write( 0x40 ); // void; the return type of the block. currently we does not use it
|
codeStream.write( 0x40 ); // void; the return type of the block. currently we does not use it
|
||||||
break;
|
break;
|
||||||
|
case ELSE:
|
||||||
|
codeStream.write( ELSE );
|
||||||
|
break;
|
||||||
case END:
|
case END:
|
||||||
codeStream.write( END );
|
codeStream.write( END );
|
||||||
break;
|
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;
|
package de.inetsoftware.jwebassembly.module;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -8,5 +24,7 @@ package de.inetsoftware.jwebassembly.module;
|
|||||||
*/
|
*/
|
||||||
public enum BlockOperator {
|
public enum BlockOperator {
|
||||||
IF,
|
IF,
|
||||||
|
ELSE,
|
||||||
END,
|
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;
|
package de.inetsoftware.jwebassembly.module;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import de.inetsoftware.classparser.CodeInputStream;
|
import de.inetsoftware.classparser.CodeInputStream;
|
||||||
|
|
||||||
@ -13,20 +29,79 @@ import de.inetsoftware.classparser.CodeInputStream;
|
|||||||
*/
|
*/
|
||||||
class BranchManger {
|
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.
|
* Start a new block.
|
||||||
*
|
*
|
||||||
* @param op
|
* @param op
|
||||||
* the start operation
|
* the start operation
|
||||||
* @param basePosition
|
* @param startPosition
|
||||||
* the byte position of the start position
|
* the byte position of the start position
|
||||||
* @param offset
|
* @param offset
|
||||||
* the relative jump position
|
* the relative jump position
|
||||||
*/
|
*/
|
||||||
void start( BlockOperator op, int basePosition, int offset ) {
|
void start( BlockOperator op, int startPosition, int offset ) {
|
||||||
stack.push( new Block( op, basePosition, 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
|
* if any I/O exception occur
|
||||||
*/
|
*/
|
||||||
void handle( CodeInputStream byteCode, ModuleWriter writer ) throws IOException {
|
void handle( CodeInputStream byteCode, ModuleWriter writer ) throws IOException {
|
||||||
int position = byteCode.getCodePosition();
|
if( stack.isEmpty() ) {
|
||||||
Block block = stack.peek();
|
return;
|
||||||
if( block != null ) {
|
|
||||||
if( block.endPosition == position ) {
|
|
||||||
writer.writeBlockCode( BlockOperator.END );
|
|
||||||
stack.pop();
|
|
||||||
}
|
}
|
||||||
|
int position = byteCode.getCodePosition();
|
||||||
|
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 static class Block {
|
||||||
private BlockOperator op;
|
private BlockOperator op;
|
||||||
|
|
||||||
private int basePosition;
|
private int startPosition;
|
||||||
|
|
||||||
private int endPosition;
|
private int endPosition;
|
||||||
|
|
||||||
private Block( BlockOperator op, int basePosition, int offset ) {
|
private Block( BlockOperator op, int startPosition, int offset ) {
|
||||||
this.op = op;
|
this.op = op;
|
||||||
this.basePosition = basePosition;
|
this.startPosition = startPosition;
|
||||||
this.endPosition = basePosition + offset;
|
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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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.CodeInputStream;
|
||||||
import de.inetsoftware.classparser.ConstantPool;
|
import de.inetsoftware.classparser.ConstantPool;
|
||||||
import de.inetsoftware.classparser.ConstantRef;
|
import de.inetsoftware.classparser.ConstantRef;
|
||||||
import de.inetsoftware.classparser.LineNumberTable;
|
|
||||||
import de.inetsoftware.classparser.LocalVariableTable;
|
import de.inetsoftware.classparser.LocalVariableTable;
|
||||||
import de.inetsoftware.classparser.MethodInfo;
|
import de.inetsoftware.classparser.MethodInfo;
|
||||||
import de.inetsoftware.jwebassembly.WasmException;
|
import de.inetsoftware.jwebassembly.WasmException;
|
||||||
@ -132,21 +131,15 @@ public abstract class ModuleWriter implements Closeable {
|
|||||||
writeMethodSignature( method );
|
writeMethodSignature( method );
|
||||||
locals.clear();
|
locals.clear();
|
||||||
localTable = code.getLocalVariableTable();
|
localTable = code.getLocalVariableTable();
|
||||||
LineNumberTable lineNumberTable = code.getLineNumberTable();
|
|
||||||
if( lineNumberTable != null ) {
|
branchManager.reset();
|
||||||
int lineNumber;
|
for( CodeInputStream byteCode : code.getByteCodes() ) {
|
||||||
for( int i = 0; i < lineNumberTable.size(); i++ ) {
|
prepareBranchManager( byteCode, byteCode.getLineNumber() );
|
||||||
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 {
|
branchManager.calculate();
|
||||||
CodeInputStream byteCode = code.getByteCode();
|
|
||||||
writeCodeChunk( byteCode, -1, method.getConstantPool() );
|
for( CodeInputStream byteCode : code.getByteCodes() ) {
|
||||||
|
writeCodeChunk( byteCode, byteCode.getLineNumber(), method.getConstantPool() );
|
||||||
}
|
}
|
||||||
for( int i = Math.min( paramCount, locals.size() ); i > 0; i-- ) {
|
for( int i = Math.min( paramCount, locals.size() ); i > 0; i-- ) {
|
||||||
locals.remove( 0 );
|
locals.remove( 0 );
|
||||||
@ -290,6 +283,72 @@ public abstract class ModuleWriter implements Closeable {
|
|||||||
*/
|
*/
|
||||||
protected abstract void writeMethodFinish( List<ValueType> locals ) throws IOException;
|
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.
|
* Write a chunk of byte code.
|
||||||
*
|
*
|
||||||
@ -502,10 +561,11 @@ public abstract class ModuleWriter implements Closeable {
|
|||||||
case 154: // ifne
|
case 154: // ifne
|
||||||
opIfCondition( NumericOperator.eq, byteCode );
|
opIfCondition( NumericOperator.eq, byteCode );
|
||||||
break;
|
break;
|
||||||
|
case 155: // iflt
|
||||||
|
opIfCondition( NumericOperator.gt, byteCode );
|
||||||
|
break;
|
||||||
case 167: // goto
|
case 167: // goto
|
||||||
int baseCodePosition = byteCode.getCodePosition() - 1;
|
byteCode.skip(2);
|
||||||
int offset = byteCode.readUnsignedShort();
|
|
||||||
if(true)throw new WasmException( "Unimplemented byte code operation: " + op, sourceFile, lineNumber );
|
|
||||||
break;
|
break;
|
||||||
case 172: // ireturn
|
case 172: // ireturn
|
||||||
case 173: // lreturn
|
case 173: // lreturn
|
||||||
@ -541,12 +601,10 @@ public abstract class ModuleWriter implements Closeable {
|
|||||||
* if any I/O errors occur.
|
* if any I/O errors occur.
|
||||||
*/
|
*/
|
||||||
private void opIfCondition( NumericOperator numOp, CodeInputStream byteCode ) throws IOException {
|
private void opIfCondition( NumericOperator numOp, CodeInputStream byteCode ) throws IOException {
|
||||||
int baseCodePosition = byteCode.getCodePosition() - 1;
|
byteCode.skip(2);
|
||||||
int offset = byteCode.readUnsignedShort();
|
|
||||||
branchManager.start( BlockOperator.IF, baseCodePosition, offset );
|
|
||||||
writeConstInt( 0 );
|
writeConstInt( 0 );
|
||||||
writeNumericOperator( numOp, ValueType.i32 );
|
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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -32,4 +32,6 @@ public enum NumericOperator {
|
|||||||
shr_u,
|
shr_u,
|
||||||
eq,
|
eq,
|
||||||
ne,
|
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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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" );
|
methodOutput.append( "if" );
|
||||||
inset++;
|
inset++;
|
||||||
break;
|
break;
|
||||||
|
case ELSE:
|
||||||
|
inset--;
|
||||||
|
newline( methodOutput );
|
||||||
|
methodOutput.append( "else" );
|
||||||
|
inset++;
|
||||||
|
break;
|
||||||
case END:
|
case END:
|
||||||
inset--;
|
inset--;
|
||||||
newline( methodOutput );
|
newline( methodOutput );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user