diff --git a/src/de/inetsoftware/jwebassembly/module/BranchManger.java b/src/de/inetsoftware/jwebassembly/module/BranchManger.java index 5a838c2..a013058 100644 --- a/src/de/inetsoftware/jwebassembly/module/BranchManger.java +++ b/src/de/inetsoftware/jwebassembly/module/BranchManger.java @@ -559,13 +559,13 @@ class BranchManger { return; } if( codePositions == startPos && startOp != null ) { - instructions.add( new WasmBlockInstruction( startOp, data ) ); + instructions.add( new WasmBlockInstruction( startOp, data, codePositions ) ); } for( BranchNode branch : this ) { branch.handle( codePositions, instructions ); } if( codePositions == endPos && endOp != null ) { - instructions.add( new WasmBlockInstruction( endOp, null ) ); + instructions.add( new WasmBlockInstruction( endOp, null, codePositions ) ); } } } diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java index 36f170d..9c4ef3a 100644 --- a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java +++ b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java @@ -166,10 +166,11 @@ public class ModuleGenerator { byteCode = code.getByteCode(); prepareCodeChunk( byteCode, method.getConstantPool() ); branchManager.calculate(); - localVariables.calculate(); byteCode = code.getByteCode(); writeCode( byteCode, method.getConstantPool() ); + localVariables.calculate(); + for( WasmInstruction instruction : instructions ) { instruction.writeTo( writer ); } @@ -528,6 +529,7 @@ public class ModuleGenerator { try { while( byteCode.available() > 0 ) { WasmInstruction instr = null; + int codePos = byteCode.getCodePosition(); branchManager.handle( byteCode ); endWithReturn = false; int op = byteCode.readUnsignedByte(); @@ -542,111 +544,111 @@ public class ModuleGenerator { case 6: // iconst_3 case 7: // iconst_4 case 8: // iconst_5 - instr = new WasmConstInstruction( Integer.valueOf( op - 3 ) ); + instr = new WasmConstInstruction( Integer.valueOf( op - 3 ), codePos ); break; case 9: // lconst_0 case 10: // lconst_1 - instr = new WasmConstInstruction( Long.valueOf( op - 9 ) ); + instr = new WasmConstInstruction( Long.valueOf( op - 9 ), codePos ); break; case 11: // fconst_0 case 12: // fconst_1 case 13: // fconst_2 - instr = new WasmConstInstruction( Float.valueOf( op - 11 ) ); + instr = new WasmConstInstruction( Float.valueOf( op - 11 ), codePos ); break; case 14: // dconst_0 case 15: // dconst_1 - instr = new WasmConstInstruction( Double.valueOf( op - 14 ) ); + instr = new WasmConstInstruction( Double.valueOf( op - 14 ), codePos ); break; case 16: // bipush - instr = new WasmConstInstruction( Integer.valueOf( byteCode.readByte() ) ); + instr = new WasmConstInstruction( Integer.valueOf( byteCode.readByte() ), codePos ); break; case 17: // sipush - instr = new WasmConstInstruction( Integer.valueOf( byteCode.readShort() ) ); + instr = new WasmConstInstruction( Integer.valueOf( byteCode.readShort() ), codePos ); break; case 18: // ldc - instr = new WasmConstInstruction( (Number)constantPool.get( byteCode.readUnsignedByte() ) ); + instr = new WasmConstInstruction( (Number)constantPool.get( byteCode.readUnsignedByte() ), codePos ); break; case 19: // ldc_w case 20: // ldc2_w - instr = new WasmConstInstruction( (Number)constantPool.get( byteCode.readUnsignedShort() ) ); + instr = new WasmConstInstruction( (Number)constantPool.get( byteCode.readUnsignedShort() ), codePos ); break; case 21: // iload - instr = new WasmLoadStoreInstruction( true, byteCode.readUnsignedByte(), localVariables ); + instr = new WasmLoadStoreInstruction( true, byteCode.readUnsignedByte(), localVariables, codePos ); break; case 22: // lload - instr = new WasmLoadStoreInstruction( true, byteCode.readUnsignedByte(), localVariables ); + instr = new WasmLoadStoreInstruction( true, byteCode.readUnsignedByte(), localVariables, codePos ); break; case 23: // fload - instr = new WasmLoadStoreInstruction( true, byteCode.readUnsignedByte(), localVariables ); + instr = new WasmLoadStoreInstruction( true, byteCode.readUnsignedByte(), localVariables, codePos ); break; case 24: // dload - instr = new WasmLoadStoreInstruction( true, byteCode.readUnsignedByte(), localVariables ); + instr = new WasmLoadStoreInstruction( true, byteCode.readUnsignedByte(), localVariables, codePos ); break; //TODO case 25: // aload case 26: // iload_0 case 27: // iload_1 case 28: // iload_2 case 29: // iload_3 - instr = new WasmLoadStoreInstruction( true, op - 26, localVariables ); + instr = new WasmLoadStoreInstruction( true, op - 26, localVariables, codePos ); break; case 30: // lload_0 case 31: // lload_1 case 32: // lload_2 case 33: // lload_3 - instr = new WasmLoadStoreInstruction( true, op - 30, localVariables ); + instr = new WasmLoadStoreInstruction( true, op - 30, localVariables, codePos ); break; case 34: // fload_0 case 35: // fload_1 case 36: // fload_2 case 37: // fload_3 - instr = new WasmLoadStoreInstruction( true, op - 34, localVariables ); + instr = new WasmLoadStoreInstruction( true, op - 34, localVariables, codePos ); break; case 38: // dload_0 case 39: // dload_1 case 40: // dload_2 case 41: // dload_3 - instr = new WasmLoadStoreInstruction( true, op - 38, localVariables ); + instr = new WasmLoadStoreInstruction( true, op - 38, localVariables, codePos ); break; case 54: // istore - instr = new WasmLoadStoreInstruction( false, byteCode.readUnsignedByte(), localVariables ); + instr = new WasmLoadStoreInstruction( false, byteCode.readUnsignedByte(), localVariables, codePos ); break; case 55: // lstore - instr = new WasmLoadStoreInstruction( false, byteCode.readUnsignedByte(), localVariables ); + instr = new WasmLoadStoreInstruction( false, byteCode.readUnsignedByte(), localVariables, codePos ); break; case 56: // fstore - instr = new WasmLoadStoreInstruction( false, byteCode.readUnsignedByte(), localVariables ); + instr = new WasmLoadStoreInstruction( false, byteCode.readUnsignedByte(), localVariables, codePos ); break; case 57: // dstore - instr = new WasmLoadStoreInstruction( false, byteCode.readUnsignedByte(), localVariables ); + instr = new WasmLoadStoreInstruction( false, byteCode.readUnsignedByte(), localVariables, codePos ); break; //TODO case 58: // astore case 59: // istore_0 case 60: // istore_1 case 61: // istore_2 case 62: // istore_3 - instr = new WasmLoadStoreInstruction( false, op - 59, localVariables ); + instr = new WasmLoadStoreInstruction( false, op - 59, localVariables, codePos ); break; case 63: // lstore_0 case 64: // lstore_1 case 65: // lstore_2 case 66: // lstore_3 - instr = new WasmLoadStoreInstruction( false, op - 63, localVariables ); + instr = new WasmLoadStoreInstruction( false, op - 63, localVariables, codePos ); break; case 67: // fstore_0 case 68: // fstore_1 case 69: // fstore_2 case 70: // fstore_3 - instr = new WasmLoadStoreInstruction( false, op - 67, localVariables ); + instr = new WasmLoadStoreInstruction( false, op - 67, localVariables, codePos ); break; case 71: // dstore_0 case 72: // dstore_1 case 73: // dstore_2 case 74: // dstore_3 - instr = new WasmLoadStoreInstruction( false, op - 71, localVariables ); + instr = new WasmLoadStoreInstruction( false, op - 71, localVariables, codePos ); break; case 87: // pop case 88: // pop2 - instr = new WasmBlockInstruction( WasmBlockOperator.DROP, null ); + instr = new WasmBlockInstruction( WasmBlockOperator.DROP, null, codePos ); break; case 89: // dup: duplicate the value on top of the stack case 90: // dup_x1 @@ -658,221 +660,221 @@ public class ModuleGenerator { // can be do with functions with more as one return value in future WASM standard throw new WasmException( "Stack duplicate is not supported in current WASM. try to save immediate values in a local variable: " + op, sourceFile, byteCode.getLineNumber() ); case 96: // iadd - instr = new WasmNumericInstruction( NumericOperator.add, ValueType.i32); + instr = new WasmNumericInstruction( NumericOperator.add, ValueType.i32, codePos); break; case 97: // ladd - instr = new WasmNumericInstruction( NumericOperator.add, ValueType.i64 ); + instr = new WasmNumericInstruction( NumericOperator.add, ValueType.i64, codePos ); break; case 98: // fadd - instr = new WasmNumericInstruction( NumericOperator.add, ValueType.f32 ); + instr = new WasmNumericInstruction( NumericOperator.add, ValueType.f32, codePos ); break; case 99: // dadd - instr = new WasmNumericInstruction( NumericOperator.add, ValueType.f64 ); + instr = new WasmNumericInstruction( NumericOperator.add, ValueType.f64, codePos ); break; case 100: // isub - instr = new WasmNumericInstruction( NumericOperator.sub, ValueType.i32 ); + instr = new WasmNumericInstruction( NumericOperator.sub, ValueType.i32, codePos ); break; case 101: // lsub - instr = new WasmNumericInstruction( NumericOperator.sub, ValueType.i64 ); + instr = new WasmNumericInstruction( NumericOperator.sub, ValueType.i64, codePos ); break; case 102: // fsub - instr = new WasmNumericInstruction( NumericOperator.sub, ValueType.f32 ); + instr = new WasmNumericInstruction( NumericOperator.sub, ValueType.f32, codePos ); break; case 103: // dsub - instr = new WasmNumericInstruction( NumericOperator.sub, ValueType.f64 ); + instr = new WasmNumericInstruction( NumericOperator.sub, ValueType.f64, codePos ); break; case 104: // imul; - instr = new WasmNumericInstruction( NumericOperator.mul, ValueType.i32 ); + instr = new WasmNumericInstruction( NumericOperator.mul, ValueType.i32, codePos ); break; case 105: // lmul - instr = new WasmNumericInstruction( NumericOperator.mul, ValueType.i64 ); + instr = new WasmNumericInstruction( NumericOperator.mul, ValueType.i64, codePos ); break; case 106: // fmul - instr = new WasmNumericInstruction( NumericOperator.mul, ValueType.f32 ); + instr = new WasmNumericInstruction( NumericOperator.mul, ValueType.f32, codePos ); break; case 107: // dmul - instr = new WasmNumericInstruction( NumericOperator.mul, ValueType.f64 ); + instr = new WasmNumericInstruction( NumericOperator.mul, ValueType.f64, codePos ); break; case 108: // idiv - instr = new WasmNumericInstruction( NumericOperator.div, ValueType.i32 ); + instr = new WasmNumericInstruction( NumericOperator.div, ValueType.i32, codePos ); break; case 109: // ldiv - instr = new WasmNumericInstruction( NumericOperator.div, ValueType.i64 ); + instr = new WasmNumericInstruction( NumericOperator.div, ValueType.i64, codePos ); break; case 110: // fdiv - instr = new WasmNumericInstruction( NumericOperator.div, ValueType.f32 ); + instr = new WasmNumericInstruction( NumericOperator.div, ValueType.f32, codePos ); break; case 111: // ddiv - instr = new WasmNumericInstruction( NumericOperator.div, ValueType.f64 ); + instr = new WasmNumericInstruction( NumericOperator.div, ValueType.f64, codePos ); break; case 112: // irem - instr = new WasmNumericInstruction( NumericOperator.rem, ValueType.i32 ); + instr = new WasmNumericInstruction( NumericOperator.rem, ValueType.i32, codePos ); break; case 113: // lrem - instr = new WasmNumericInstruction( NumericOperator.rem, ValueType.i64 ); + instr = new WasmNumericInstruction( NumericOperator.rem, ValueType.i64, codePos ); break; case 114: // frem case 115: // drem //TODO can be implemented with a helper function like: (a - (long)(a / b) * (double)b) throw new WasmException( "Modulo/Remainder for floating numbers is not supported in WASM. Use int or long data types." + op, sourceFile, byteCode.getLineNumber() ); case 116: // ineg - instructions.add( new WasmConstInstruction( -1 ) ); - instr = new WasmNumericInstruction( NumericOperator.mul, ValueType.i32 ); + instructions.add( new WasmConstInstruction( -1, codePos ) ); + instr = new WasmNumericInstruction( NumericOperator.mul, ValueType.i32, codePos ); break; case 117: // lneg - instructions.add( new WasmConstInstruction( (long)-1 ) ) ; - instr = new WasmNumericInstruction( NumericOperator.mul, ValueType.i64 ); + instructions.add( new WasmConstInstruction( (long)-1, codePos ) ) ; + instr = new WasmNumericInstruction( NumericOperator.mul, ValueType.i64, codePos ); break; case 118: // fneg - instr = new WasmNumericInstruction( NumericOperator.neg, ValueType.f32 ); + instr = new WasmNumericInstruction( NumericOperator.neg, ValueType.f32, codePos ); break; case 119: // dneg - instr = new WasmNumericInstruction( NumericOperator.neg, ValueType.f64 ); + instr = new WasmNumericInstruction( NumericOperator.neg, ValueType.f64, codePos ); break; case 120: // ishl - instr = new WasmNumericInstruction( NumericOperator.shl, ValueType.i32 ); + instr = new WasmNumericInstruction( NumericOperator.shl, ValueType.i32, codePos ); break; case 121: // lshl - instructions.add( ValueTypeConvertion.i2l ); // the shift parameter must be of type long!!! - instr = new WasmNumericInstruction( NumericOperator.shl, ValueType.i64 ); + instructions.add( new WasmConvertInstruction( ValueTypeConvertion.i2l, codePos ) ); // the shift parameter must be of type long!!! + instr = new WasmNumericInstruction( NumericOperator.shl, ValueType.i64, codePos ); break; case 122: // ishr - instr = new WasmNumericInstruction( NumericOperator.shr_s, ValueType.i32 ); + instr = new WasmNumericInstruction( NumericOperator.shr_s, ValueType.i32, codePos ); break; case 123: // lshr - instructions.add( ValueTypeConvertion.i2l ); // the shift parameter must be of type long!!! - instr = new WasmNumericInstruction( NumericOperator.shr_s, ValueType.i64 ); + instructions.add( new WasmConvertInstruction( ValueTypeConvertion.i2l, codePos ) ); // the shift parameter must be of type long!!! + instr = new WasmNumericInstruction( NumericOperator.shr_s, ValueType.i64, codePos ); break; case 124: // iushr - instr = new WasmNumericInstruction( NumericOperator.shr_u, ValueType.i32 ); + instr = new WasmNumericInstruction( NumericOperator.shr_u, ValueType.i32, codePos ); break; case 125: // lushr - instructions.add( ValueTypeConvertion.i2l ); // the shift parameter must be of type long!!! - instr = new WasmNumericInstruction( NumericOperator.shr_u, ValueType.i64 ); + instructions.add( new WasmConvertInstruction( ValueTypeConvertion.i2l, codePos ) ); // the shift parameter must be of type long!!! + instr = new WasmNumericInstruction( NumericOperator.shr_u, ValueType.i64, codePos ); break; case 126: // iand - instr = new WasmNumericInstruction( NumericOperator.and, ValueType.i32 ); + instr = new WasmNumericInstruction( NumericOperator.and, ValueType.i32, codePos ); break; case 127: // land - instr = new WasmNumericInstruction( NumericOperator.and, ValueType.i64 ); + instr = new WasmNumericInstruction( NumericOperator.and, ValueType.i64, codePos ); break; case 128: // ior - instr = new WasmNumericInstruction( NumericOperator.or, ValueType.i32 ); + instr = new WasmNumericInstruction( NumericOperator.or, ValueType.i32, codePos ); break; case 129: // lor - instr = new WasmNumericInstruction( NumericOperator.or, ValueType.i64 ); + instr = new WasmNumericInstruction( NumericOperator.or, ValueType.i64, codePos ); break; case 130: // ixor - instr = new WasmNumericInstruction( NumericOperator.xor, ValueType.i32 ); + instr = new WasmNumericInstruction( NumericOperator.xor, ValueType.i32, codePos ); break; case 131: // lxor - instr = new WasmNumericInstruction( NumericOperator.xor, ValueType.i64 ); + instr = new WasmNumericInstruction( NumericOperator.xor, ValueType.i64, codePos ); break; case 132: // iinc int idx = byteCode.readUnsignedByte(); - instructions.add( new WasmLoadStoreInstruction( true, idx, localVariables ) ); - instructions.add( new WasmConstInstruction( byteCode.readUnsignedByte() ) ); - instructions.add( new WasmNumericInstruction( NumericOperator.add, ValueType.i32) ); - instr = new WasmLoadStoreInstruction( false, idx, localVariables ); + instructions.add( new WasmLoadStoreInstruction( true, idx, localVariables, codePos ) ); + instructions.add( new WasmConstInstruction( byteCode.readUnsignedByte(), codePos ) ); + instructions.add( new WasmNumericInstruction( NumericOperator.add, ValueType.i32, codePos) ); + instr = new WasmLoadStoreInstruction( false, idx, localVariables, codePos ); break; case 133: // i2l - instr = ValueTypeConvertion.i2l; + instr = new WasmConvertInstruction( ValueTypeConvertion.i2l, codePos ); break; case 134: // i2f - instr = ValueTypeConvertion.i2f; + instr = new WasmConvertInstruction( ValueTypeConvertion.i2f, codePos ); break; case 135: // i2d - instr = ValueTypeConvertion.i2d; + instr = new WasmConvertInstruction( ValueTypeConvertion.i2d, codePos ); break; case 136: // l2i - instr = ValueTypeConvertion.l2i; + instr = new WasmConvertInstruction( ValueTypeConvertion.l2i, codePos ); break; case 137: // l2f - instr = ValueTypeConvertion.l2f; + instr = new WasmConvertInstruction( ValueTypeConvertion.l2f, codePos ); break; case 138: // l2d - instr = ValueTypeConvertion.l2d; + instr = new WasmConvertInstruction( ValueTypeConvertion.l2d, codePos ); break; case 139: // f2i - instr = ValueTypeConvertion.f2i; + instr = new WasmConvertInstruction( ValueTypeConvertion.f2i, codePos ); break; case 140: // f2l - instr = ValueTypeConvertion.f2l; + instr = new WasmConvertInstruction( ValueTypeConvertion.f2l, codePos ); break; case 141: // f2d - instr = ValueTypeConvertion.f2d; + instr = new WasmConvertInstruction( ValueTypeConvertion.f2d, codePos ); break; case 142: // d2i - instr = ValueTypeConvertion.d2i; + instr = new WasmConvertInstruction( ValueTypeConvertion.d2i, codePos ); break; case 143: // d2l - instr = ValueTypeConvertion.d2l; + instr = new WasmConvertInstruction( ValueTypeConvertion.d2l, codePos ); break; case 144: // d2f - instr = ValueTypeConvertion.d2f; + instr = new WasmConvertInstruction( ValueTypeConvertion.d2f, codePos ); break; case 145: // i2b - instructions.add( new WasmConstInstruction( 24 ) ); - instructions.add( new WasmNumericInstruction( NumericOperator.shl, ValueType.i32 ) ); - instructions.add( new WasmConstInstruction( 24 ) ); - instr = new WasmNumericInstruction( NumericOperator.shr_s, ValueType.i32 ); + instructions.add( new WasmConstInstruction( 24, codePos ) ); + instructions.add( new WasmNumericInstruction( NumericOperator.shl, ValueType.i32, codePos ) ); + instructions.add( new WasmConstInstruction( 24, codePos ) ); + instr = new WasmNumericInstruction( NumericOperator.shr_s, ValueType.i32, codePos ); break; case 146: // i2c - instructions.add( new WasmConstInstruction( 0xFFFF ) ); - instr = new WasmNumericInstruction( NumericOperator.and, ValueType.i32 ); + instructions.add( new WasmConstInstruction( 0xFFFF, codePos ) ); + instr = new WasmNumericInstruction( NumericOperator.and, ValueType.i32, codePos ); break; case 147: // i2s - instructions.add( new WasmConstInstruction( 16 ) ); - instructions.add( new WasmNumericInstruction( NumericOperator.shl, ValueType.i32 ) ); - instructions.add( new WasmConstInstruction( 16 ) ); - instr = new WasmNumericInstruction( NumericOperator.shr_s, ValueType.i32 ); + instructions.add( new WasmConstInstruction( 16, codePos ) ); + instructions.add( new WasmNumericInstruction( NumericOperator.shl, ValueType.i32, codePos ) ); + instructions.add( new WasmConstInstruction( 16, codePos ) ); + instr = new WasmNumericInstruction( NumericOperator.shr_s, ValueType.i32, codePos ); break; case 148: // lcmp - opCompare( ValueType.i64, byteCode ); + opCompare( ValueType.i64, byteCode, codePos ); break; case 149: // fcmpl case 150: // fcmpg - opCompare( ValueType.f32, byteCode ); + opCompare( ValueType.f32, byteCode, codePos ); break; case 151: // dcmpl case 152: // dcmpg - opCompare( ValueType.f64, byteCode ); + opCompare( ValueType.f64, byteCode, codePos ); break; case 153: // ifeq - opIfCondition( NumericOperator.ne, NumericOperator.eq, byteCode ); + opIfCondition( NumericOperator.ne, NumericOperator.eq, byteCode, codePos ); break; case 154: // ifne - opIfCondition( NumericOperator.eq, NumericOperator.ne, byteCode ); + opIfCondition( NumericOperator.eq, NumericOperator.ne, byteCode, codePos ); break; case 155: // iflt - opIfCondition( NumericOperator.ge_s, NumericOperator.lt_s, byteCode ); + opIfCondition( NumericOperator.ge_s, NumericOperator.lt_s, byteCode, codePos ); break; case 156: // ifge - opIfCondition( NumericOperator.lt_s, NumericOperator.ge_s, byteCode ); + opIfCondition( NumericOperator.lt_s, NumericOperator.ge_s, byteCode, codePos ); break; case 157: // ifgt - opIfCondition( NumericOperator.le_s, NumericOperator.gt, byteCode ); + opIfCondition( NumericOperator.le_s, NumericOperator.gt, byteCode, codePos ); break; case 158: // ifle - opIfCondition( NumericOperator.gt, NumericOperator.le_s, byteCode ); + opIfCondition( NumericOperator.gt, NumericOperator.le_s, byteCode, codePos ); break; case 159: // if_icmpeq - opIfCompareCondition( NumericOperator.ne, NumericOperator.eq, byteCode ); + opIfCompareCondition( NumericOperator.ne, NumericOperator.eq, byteCode, codePos ); break; case 160: // if_icmpne - opIfCompareCondition( NumericOperator.eq, NumericOperator.ne, byteCode ); + opIfCompareCondition( NumericOperator.eq, NumericOperator.ne, byteCode, codePos ); break; case 161: // if_icmplt - opIfCompareCondition( NumericOperator.ge_s, NumericOperator.lt_s, byteCode ); + opIfCompareCondition( NumericOperator.ge_s, NumericOperator.lt_s, byteCode, codePos ); break; case 162: // if_icmpge - opIfCompareCondition( NumericOperator.lt_s, NumericOperator.ge_s, byteCode ); + opIfCompareCondition( NumericOperator.lt_s, NumericOperator.ge_s, byteCode, codePos ); break; case 163: // if_icmpgt - opIfCompareCondition( NumericOperator.le_s, NumericOperator.gt, byteCode ); + opIfCompareCondition( NumericOperator.le_s, NumericOperator.gt, byteCode, codePos ); break; case 164: // if_icmple - opIfCompareCondition( NumericOperator.gt, NumericOperator.le_s, byteCode ); + opIfCompareCondition( NumericOperator.gt, NumericOperator.le_s, byteCode, codePos ); break; //TODO case 165: // if_acmpeq //TODO case 166: // if_acmpne @@ -888,13 +890,13 @@ public class ModuleGenerator { case 174: // freturn case 175: // dreturn case 177: // return void - instr = new WasmBlockInstruction( WasmBlockOperator.RETURN, null ); + instr = new WasmBlockInstruction( WasmBlockOperator.RETURN, null, codePos ); endWithReturn = true; break; case 184: // invokestatic idx = byteCode.readUnsignedShort(); ConstantRef method = (ConstantRef)constantPool.get( idx ); - instr = new WasmCallInstruction( method.getConstantClass().getName() + '.' + method.getName() + method.getType() ); + instr = new WasmCallInstruction( method.getConstantClass().getName() + '.' + method.getName() + method.getType(), codePos ); break; default: throw new WasmException( "Unimplemented Java byte code operation: " + op, sourceFile, byteCode.getLineNumber() ); @@ -910,20 +912,20 @@ public class ModuleGenerator { // But WebAssembly need the dead code to validate switch( returnType ) { case i32: - instructions.add( new WasmConstInstruction( 0 ) ); + instructions.add( new WasmConstInstruction( 0, byteCode.getCodePosition() ) ); break; case i64: - instructions.add( new WasmConstInstruction( 0L ) ); + instructions.add( new WasmConstInstruction( 0L, byteCode.getCodePosition() ) ); break; case f32: - instructions.add( new WasmConstInstruction( 0F ) ); + instructions.add( new WasmConstInstruction( 0F, byteCode.getCodePosition() ) ); break; case f64: - instructions.add( new WasmConstInstruction( 0D ) ); + instructions.add( new WasmConstInstruction( 0D, byteCode.getCodePosition() ) ); break; default: } - instructions.add( new WasmBlockInstruction( WasmBlockOperator.RETURN, null ) ); + instructions.add( new WasmBlockInstruction( WasmBlockOperator.RETURN, null, byteCode.getCodePosition() ) ); } } catch( WasmException ex ) { throw ex; @@ -943,7 +945,8 @@ public class ModuleGenerator { * if any I/O error occur */ private void writeSwitchCode( CodeInputStream byteCode, boolean isLookupSwitch ) throws IOException { - int startPosition = byteCode.getCodePosition(); + int codePos = byteCode.getCodePosition(); + int startPosition = codePos; int padding = startPosition % 4; if( padding > 0 ) { byteCode.skip( 4 - padding ); @@ -963,7 +966,7 @@ public class ModuleGenerator { int block = 0; int defaultBlock = -1; int currentPos = -1; - instructions.add( new WasmLoadStoreInstruction( false, tempI32, localVariables ) ); + instructions.add( new WasmLoadStoreInstruction( false, tempI32, localVariables, codePos ) ); do { int nextPos = findNext( currentPos, positions ); if( nextPos == currentPos ) { @@ -980,10 +983,10 @@ public class ModuleGenerator { } for( int i = 0; i < positions.length; i++ ) { if( positions[i] == currentPos ) { - instructions.add( new WasmLoadStoreInstruction( true, tempI32, localVariables ) ); - instructions.add( new WasmConstInstruction( keys[i] ) ); - instructions.add( new WasmNumericInstruction( NumericOperator.eq, ValueType.i32 ) ); - instructions.add( new WasmBlockInstruction( WasmBlockOperator.BR_IF, block ) ); + instructions.add( new WasmLoadStoreInstruction( true, tempI32, localVariables, codePos ) ); + instructions.add( new WasmConstInstruction( keys[i], codePos ) ); + instructions.add( new WasmNumericInstruction( NumericOperator.eq, ValueType.i32, codePos ) ); + instructions.add( new WasmBlockInstruction( WasmBlockOperator.BR_IF, block, codePos ) ); } } block++; @@ -991,7 +994,7 @@ public class ModuleGenerator { if( defaultBlock < 0 ) { defaultBlock = block; } - instructions.add( new WasmBlockInstruction( WasmBlockOperator.BR, defaultBlock ) ); + instructions.add( new WasmBlockInstruction( WasmBlockOperator.BR, defaultBlock, codePos ) ); } else { int low = byteCode.readInt(); int count = byteCode.readInt() - low + 1; @@ -999,8 +1002,8 @@ public class ModuleGenerator { byteCode.readInt(); } if( low != 0 ) { // the br_table starts ever with the value 0. That we need to subtract the start value if it different - instructions.add( new WasmConstInstruction( low ) ); - instructions.add( new WasmNumericInstruction( NumericOperator.sub, ValueType.i32 ) ); + instructions.add( new WasmConstInstruction( low, codePos ) ); + instructions.add( new WasmNumericInstruction( NumericOperator.sub, ValueType.i32, codePos ) ); } } } @@ -1028,8 +1031,8 @@ public class ModuleGenerator { /** * Handle the if of the Java byte code. This Java instruction compare the first stack value with value 0. - * 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 + * 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. @@ -1037,12 +1040,14 @@ public class ModuleGenerator { * The condition for the continue of a loop. * @param byteCode * current byte code stream to read the target offset. + * @param codePos + * the code position/offset in the Java method * @throws IOException * if any I/O errors occur. */ - private void opIfCondition( NumericOperator ifNumOp, NumericOperator continueNumOp, CodeInputStream byteCode ) throws IOException { - instructions.add( new WasmConstInstruction( 0 ) ); - opIfCompareCondition( ifNumOp, continueNumOp, byteCode ); + private void opIfCondition( NumericOperator ifNumOp, NumericOperator continueNumOp, CodeInputStream byteCode, int codePos ) throws IOException { + instructions.add( new WasmConstInstruction( 0, codePos ) ); + opIfCompareCondition( ifNumOp, continueNumOp, byteCode, codePos ); } /** @@ -1056,12 +1061,14 @@ public class ModuleGenerator { * The condition for the continue of a loop. * @param byteCode * current byte code stream to read the target offset. + * @param codePos + * the code position/offset in the Java method * @throws IOException * if any I/O errors occur. */ - private void opIfCompareCondition( NumericOperator ifNumOp, NumericOperator continueNumOp, CodeInputStream byteCode ) throws IOException { + private void opIfCompareCondition( NumericOperator ifNumOp, NumericOperator continueNumOp, CodeInputStream byteCode, int codePos ) throws IOException { int offset = byteCode.readShort(); - instructions.add( new WasmNumericInstruction( offset > 0 ? ifNumOp : continueNumOp, ValueType.i32 ) ); + instructions.add( new WasmNumericInstruction( offset > 0 ? ifNumOp : continueNumOp, ValueType.i32, codePos ) ); } /** @@ -1072,10 +1079,12 @@ public class ModuleGenerator { * the value type of the compared * @param byteCode * current byte code stream to read the next operation. + * @param codePos + * the code position/offset in the Java method * @throws IOException * if any I/O errors occur. */ - private void opCompare( ValueType valueType, CodeInputStream byteCode ) throws IOException { + private void opCompare( ValueType valueType, CodeInputStream byteCode, int codePos ) throws IOException { NumericOperator numOp; int nextOp = byteCode.read(); switch( nextOp ){ @@ -1101,7 +1110,7 @@ public class ModuleGenerator { throw new WasmException( "Unexpected compare sub operation: " + nextOp, null, -1 ); } byteCode.skip(2); - instructions.add( new WasmNumericInstruction( numOp, valueType ) ); + instructions.add( new WasmNumericInstruction( numOp, valueType, codePos ) ); } } diff --git a/src/de/inetsoftware/jwebassembly/module/ValueTypeConvertion.java b/src/de/inetsoftware/jwebassembly/module/ValueTypeConvertion.java index c14dd76..e4e7bd1 100644 --- a/src/de/inetsoftware/jwebassembly/module/ValueTypeConvertion.java +++ b/src/de/inetsoftware/jwebassembly/module/ValueTypeConvertion.java @@ -23,7 +23,7 @@ import java.io.IOException; * @author Volker Berlin * */ -public enum ValueTypeConvertion implements WasmInstruction { +public enum ValueTypeConvertion { i2l, i2f, i2d, @@ -36,13 +36,4 @@ public enum ValueTypeConvertion implements WasmInstruction { d2i, d2l, d2f, - ; - - /** - * {@inheritDoc} - */ - @Override - public void writeTo( ModuleWriter writer ) throws IOException { - writer.writeCast( this ); - } -} +} \ No newline at end of file diff --git a/src/de/inetsoftware/jwebassembly/module/WasmBlockInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmBlockInstruction.java index b54d8df..b98f053 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmBlockInstruction.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmBlockInstruction.java @@ -27,7 +27,7 @@ import javax.annotation.Nullable; * @author Volker Berlin * */ -class WasmBlockInstruction implements WasmInstruction { +class WasmBlockInstruction extends WasmInstruction { private final WasmBlockOperator op; @@ -40,8 +40,11 @@ class WasmBlockInstruction implements WasmInstruction { * the operation * @param data * extra data depending of the operator + * @param javaCodePos + * the code position/offset in the Java method */ - WasmBlockInstruction( @Nonnull WasmBlockOperator op, @Nullable Object data ) { + WasmBlockInstruction( @Nonnull WasmBlockOperator op, @Nullable Object data, int javaCodePos ) { + super( javaCodePos ); this.op = op; this.data = data; } diff --git a/src/de/inetsoftware/jwebassembly/module/WasmCallInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmCallInstruction.java index cb1635e..57c58ae 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmCallInstruction.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmCallInstruction.java @@ -26,15 +26,20 @@ import javax.annotation.Nonnull; * @author Volker Berlin * */ -class WasmCallInstruction implements WasmInstruction { +class WasmCallInstruction extends WasmInstruction { private final String name; /** - * Create an instance of a function call instruction - * @param name the Java function name + * Create an instance of a function call instruction + * + * @param name + * the Java function name + * @param javaCodePos + * the code position/offset in the Java method */ - WasmCallInstruction( String name ) { + WasmCallInstruction( String name, int javaCodePos ) { + super( javaCodePos ); this.name = name; } diff --git a/src/de/inetsoftware/jwebassembly/module/WasmConstInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmConstInstruction.java index 9340ff6..e1796d0 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmConstInstruction.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmConstInstruction.java @@ -28,15 +28,20 @@ import de.inetsoftware.jwebassembly.WasmException; * @author Volker Berlin * */ -class WasmConstInstruction implements WasmInstruction { +class WasmConstInstruction extends WasmInstruction { private final Number value; /** - * Create an instance of a constant instruction - * @param value the constant value + * Create an instance of a constant instruction + * + * @param value + * the constant value + * @param javaCodePos + * the code position/offset in the Java method */ - WasmConstInstruction( Number value ) { + WasmConstInstruction( Number value, int javaCodePos ) { + super( javaCodePos ); this.value = value; } diff --git a/src/de/inetsoftware/jwebassembly/module/WasmConvertInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmConvertInstruction.java new file mode 100644 index 0000000..a826850 --- /dev/null +++ b/src/de/inetsoftware/jwebassembly/module/WasmConvertInstruction.java @@ -0,0 +1,50 @@ +/* + * 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; + +/** + * Cast operations for converting one data type to another + * + * @author Volker Berlin + * + */ +class WasmConvertInstruction extends WasmInstruction { + + private ValueTypeConvertion conversion; + + /** + * Create an instance of a convert instruction + * + * @param conversion + * the conversion type + * @param javaCodePos + * the code position/offset in the Java method + */ + WasmConvertInstruction( ValueTypeConvertion conversion, int javaCodePos ) { + super( javaCodePos ); + this.conversion = conversion; + } + + /** + * {@inheritDoc} + */ + @Override + public void writeTo( ModuleWriter writer ) throws IOException { + writer.writeCast( conversion ); + } +} diff --git a/src/de/inetsoftware/jwebassembly/module/WasmInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmInstruction.java index baae473..607c385 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmInstruction.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmInstruction.java @@ -26,7 +26,19 @@ import javax.annotation.Nonnull; * @author Volker Berlin * */ -abstract interface WasmInstruction { +abstract class WasmInstruction { + + private int javaCodePos; + + /** + * Create a new instance of an instruction + * + * @param javaCodePos + * the code position/offset in the Java method + */ + WasmInstruction( int javaCodePos ) { + this.javaCodePos = javaCodePos; + } /** * Write this instruction to the WASM module. diff --git a/src/de/inetsoftware/jwebassembly/module/WasmLoadStoreInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmLoadStoreInstruction.java index 0e298c0..f4060cb 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmLoadStoreInstruction.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmLoadStoreInstruction.java @@ -27,7 +27,7 @@ import javax.annotation.Nonnull; * @author Volker Berlin * */ -class WasmLoadStoreInstruction implements WasmInstruction { +class WasmLoadStoreInstruction extends WasmInstruction { private boolean load; @@ -44,8 +44,11 @@ class WasmLoadStoreInstruction implements WasmInstruction { * the memory/slot idx of the variable * @param localVariables * the manager for local variables + * @param javaCodePos + * the code position/offset in the Java method */ - WasmLoadStoreInstruction( boolean load, @Nonnegative int idx, LocaleVariableManager localVariables ) { + WasmLoadStoreInstruction( boolean load, @Nonnegative int idx, LocaleVariableManager localVariables, int javaCodePos ) { + super( javaCodePos ); this.load = load; this.idx = idx; this.localVariables = localVariables; diff --git a/src/de/inetsoftware/jwebassembly/module/WasmNumericInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmNumericInstruction.java index 3e4c1eb..b0a7c0c 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmNumericInstruction.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmNumericInstruction.java @@ -27,7 +27,7 @@ import javax.annotation.Nullable; * @author Volker Berlin * */ -class WasmNumericInstruction implements WasmInstruction { +class WasmNumericInstruction extends WasmInstruction { private final NumericOperator numOp; @@ -40,9 +40,11 @@ class WasmNumericInstruction implements WasmInstruction { * the numeric operation * @param valueType * the type of the parameters - * + * @param javaCodePos + * the code position/offset in the Java method */ - WasmNumericInstruction( @Nullable NumericOperator numOp, @Nullable ValueType valueType ) { + WasmNumericInstruction( @Nullable NumericOperator numOp, @Nullable ValueType valueType, int javaCodePos ) { + super( javaCodePos ); this.numOp = numOp; this.valueType = valueType; }