private void CompileLogicNot(ILExpression e, ExpectType expect) { CompileExpression(e.Arguments[0], ExpectType.Primitive); // push exp // ifeq zero // iconst_0 // goto exit //zero: // iconst_1 //exit string labelSufixes = rnd.Next().ToString(); string zeroLabel = "zero" + labelSufixes; string exitLabel = "exit" + labelSufixes; Java.OpCodes branch = Java.OpCodes.ifeq; TranslateToBool(e.Arguments[0].InferredType, ref branch, e); codeGenerator .Add(branch, zeroLabel, e) .Add(Java.OpCodes.iconst_0, null, e) .Add(Java.OpCodes._goto, exitLabel, e) .Label(zeroLabel) .Add(Java.OpCodes.iconst_1) .Label(exitLabel); }
private void CompileLogicAnd(ILExpression e, ExpectType expect) { string labelsSufix = rnd.Next().ToString(); string falseLabel = "false" + labelsSufix; string exitLabel = "exit" + labelsSufix; Java.OpCodes branch = Java.OpCodes.ifeq; CompileExpression(e.Arguments[0], ExpectType.Primitive); TranslateToBool(e.Arguments[0].InferredType, ref branch, e); codeGenerator.Add(branch, falseLabel, e); CompileExpression(e.Arguments[1], ExpectType.Primitive); TranslateToBool(e.Arguments[1].InferredType, ref branch, e); branch = Java.OpCodes.ifeq; codeGenerator .Add(branch, falseLabel, e) .Add(Java.OpCodes.iconst_1, null, e) .Add(Java.OpCodes._goto, exitLabel, e) .Label(falseLabel) .Add(Java.OpCodes.iconst_0, null, e) .Label(exitLabel); }
public JavaBytecodeWriter AddArrayLoad(JavaArrayType arrType, object tag) { Java.OpCodes opcode = Java.OpCodes.aaload; switch (arrType) { case JavaArrayType.Boolean: opcode = Java.OpCodes.baload; break; case JavaArrayType.Byte: opcode = Java.OpCodes.baload; break; case JavaArrayType.Char: opcode = Java.OpCodes.caload; break; case JavaArrayType.Double: opcode = Java.OpCodes.daload; break; case JavaArrayType.Float: opcode = Java.OpCodes.faload; break; case JavaArrayType.Int: opcode = Java.OpCodes.iaload; break; case JavaArrayType.Long: opcode = Java.OpCodes.laload; break; case JavaArrayType.Short: opcode = Java.OpCodes.saload; break; } return(Add(opcode, null, tag)); }
public JavaBytecodeWriter AddReturn(JavaPrimitiveType jp, object tag) { Java.OpCodes opcode = Java.OpCodes.areturn; switch (jp) { case JavaPrimitiveType.Bool: case JavaPrimitiveType.Byte: case JavaPrimitiveType.Char: case JavaPrimitiveType.Int: case JavaPrimitiveType.Short: opcode = Java.OpCodes.ireturn; break; case JavaPrimitiveType.Long: opcode = Java.OpCodes.lreturn; break; case JavaPrimitiveType.Float: opcode = Java.OpCodes.freturn; break; case JavaPrimitiveType.Double: opcode = Java.OpCodes.dreturn; break; case JavaPrimitiveType.Void: opcode = Java.OpCodes._return; break; } AddInstruction(new JavaInstruction(opcode, null, tag)); return(this); }
public JavaBytecodeWriter AddDefaultValue(JavaPrimitiveType jp, object tag) { Java.OpCodes opcode = Java.OpCodes.aconst_null; switch (jp) { case JavaPrimitiveType.Bool: case JavaPrimitiveType.Byte: case JavaPrimitiveType.Char: case JavaPrimitiveType.Int: case JavaPrimitiveType.Short: opcode = Java.OpCodes.iconst_0; break; case JavaPrimitiveType.Long: opcode = Java.OpCodes.lconst_0; break; case JavaPrimitiveType.Float: opcode = Java.OpCodes.fconst_0; break; case JavaPrimitiveType.Double: opcode = Java.OpCodes.dconst_0; break; } AddInstruction(new JavaInstruction(opcode, null, tag)); return(this); }
private void AddLocalVarStore(JavaPrimitiveType varType, int varIndex, object tag) { Java.OpCodes shortOpcode = Java.OpCodes.astore_0; Java.OpCodes longOpcode = Java.OpCodes.astore; switch (varType) { case JavaPrimitiveType.Bool: case JavaPrimitiveType.Byte: case JavaPrimitiveType.Char: case JavaPrimitiveType.Short: case JavaPrimitiveType.Int: shortOpcode = Java.OpCodes.istore_0; longOpcode = Java.OpCodes.istore; break; case JavaPrimitiveType.Long: shortOpcode = Java.OpCodes.lstore_0; longOpcode = Java.OpCodes.lstore; break; case JavaPrimitiveType.Float: shortOpcode = Java.OpCodes.fstore_0; longOpcode = Java.OpCodes.fstore; break; case JavaPrimitiveType.Double: shortOpcode = Java.OpCodes.dstore_0; longOpcode = Java.OpCodes.dstore; break; } AddLocalVarInstruction(shortOpcode, longOpcode, varIndex, tag); }
private void TranslateToBool(TypeReference inferredType, ref Java.OpCodes cmpOp, object tag) { JavaPrimitiveType gettedType = JavaHelpers.InterTypeToJavaPrimitive(resolver.Resolve( inferredType, thisMethod.FullGenericArguments)); switch (gettedType) { case JavaPrimitiveType.Double: codeGenerator.Add(Java.OpCodes.d2i, null, tag); break; case JavaPrimitiveType.Float: codeGenerator.Add(Java.OpCodes.f2i, null, tag); break; case JavaPrimitiveType.Long: codeGenerator.Add(Java.OpCodes.l2i, null, tag); break; case JavaPrimitiveType.Ref: cmpOp = (cmpOp == Java.OpCodes.ifne ? Java.OpCodes.ifnonnull : Java.OpCodes.ifnull); break; } }
private void AddLocalVarInstruction(Java.OpCodes shortOpcode, Java.OpCodes longOpcode, int varIndex, object tag) { if (varIndex < 4) { AddInstruction(new JavaInstruction((Java.OpCodes)(((int)shortOpcode) + varIndex), null, tag)); } else if (varIndex < byte.MaxValue) { AddInstruction(new JavaInstruction(longOpcode, (byte)varIndex, tag)); } else { AddInstruction(new JavaInstruction(Java.OpCodes.wide, null, tag)); AddInstruction(new JavaInstruction(longOpcode, (ushort)varIndex, tag)); } }
public static void SimulateStack(Java.ConstantPool Pool, Java.Attributes.Code resultCode) { List <int> SimulatedInstructions = new List <int>(); Dictionary <int, int> Branches = new Dictionary <int, int>(); StackImitator Stack = new StackImitator(); Branches.Add(0, 0); foreach (Java.Attributes.Code.Exception E in resultCode.ExceptionTable) { Branches.Add(E.HandlerPC, 1); } byte[] Code = resultCode.CodeBytes; int CodeLength = Code.Length; bool LastWide = false; int LocalVarCount = 0; while (Branches.Count > 0) { KeyValuePair <int, int> Branch = Branches.First(); Branches.Remove(Branch.Key); Stack.Value = Branch.Value; int Position = Branch.Key; while (Position < CodeLength) { if (SimulatedInstructions.Contains(Position)) { break; } SimulatedInstructions.Add(Position); Java.OpCodes OpCode = (Java.OpCodes)Code[Position]; if (OpCode == Java.OpCodes.wide) { LastWide = true; Position++; continue; } ByteCode.JavaInstructionDescption Desc = ByteCode.JavaInstructions[OpCode]; int Size = Desc.Size; if (LastWide) { Size = (Size - 1) * 2 + 1; LastWide = false; } int Operand = 0; if ((Desc.OpType != ByteCode.JavaOperandType.None) && (Desc.OpType != ByteCode.JavaOperandType.Special)) { Operand = BitConverterBE.ReadAsInt32(Code, Position + 1, Size - 1); } if (OpCodeToVarIndex.ContainsKey(OpCode)) { int varIndex = OpCodeToVarIndex[OpCode]; if (varIndex < 0) { varIndex = Operand; } if (Array.IndexOf(DoubleSizeVars, OpCode) >= 0) { varIndex++; } LocalVarCount = Math.Max(LocalVarCount, varIndex + 1); } if (Desc.OpType == ByteCode.JavaOperandType.Special) { if (OpCode == Java.OpCodes.invokeinterface) { Operand = BitConverterBE.ReadAsInt32(Code, Position + 1, Size - 1); uint tmp = ((uint)((Operand & 0xffff0000) >> 16) | (uint)((Operand & 0xffff) << 16)); Operand = unchecked ((int)tmp); } } if (Desc.PopAction != null) { Stack.Pop(Desc.PopAction(Operand, Pool)); } if (Desc.PushAction != null) { Stack.Push(Desc.PushAction(Operand, Pool)); } if (Desc.BranchType == ByteCode.JavaBranchType.Break) { break; } else if (Desc.BranchType == ByteCode.JavaBranchType.Conditional) { if ((OpCode == Java.OpCodes.jsr) || (OpCode == Java.OpCodes.jsr_w)) { Stack.Push(1); } int NextPosition = Position + Operand; if (!Branches.ContainsKey(NextPosition)) { Branches.Add(NextPosition, Stack.Value); } if ((OpCode == Java.OpCodes.jsr) || (OpCode == Java.OpCodes.jsr_w)) { Stack.Pop(0); } Position += Size; } else if (Desc.BranchType == ByteCode.JavaBranchType.Switch) { int PaddingLength = (4 - ((Position + 1) % 4)) % 4; int SwitchArrayStart = Position + PaddingLength + 1; int NextPosition = BitConverterBE.ReadAsInt32(Code, SwitchArrayStart, 4); if (OpCode == Java.OpCodes.lookupswitch) { int Count = BitConverterBE.ReadAsInt32(Code, SwitchArrayStart + 4, 4); for (int i = 0; i < Count; i++) { int Offset = BitConverterBE.ReadAsInt32(Code, SwitchArrayStart + 8 + (i * 8) + 4, 4); int NextPos = Position + Offset; if (!Branches.ContainsKey(NextPos)) { Branches.Add(Position + Offset, Stack.Value); } } } else if (OpCode == Java.OpCodes.tableswitch) { int low = BitConverterBE.ReadAsInt32(Code, SwitchArrayStart + 4, 4); int hight = BitConverterBE.ReadAsInt32(Code, SwitchArrayStart + 8, 4); for (int i = 0; i < hight - low + 1; i++) { int Offset = BitConverterBE.ReadAsInt32(Code, SwitchArrayStart + 12 + (i * 4), 4); int NextPos = Position + Offset; if (!Branches.ContainsKey(NextPos)) { Branches.Add(Position + Offset, Stack.Value); } } } Position += NextPosition; } else if (Desc.BranchType == ByteCode.JavaBranchType.Goto) { Position += Operand; } else if (Desc.BranchType == ByteCode.JavaBranchType.Next) { Position += Size; } } } resultCode.MaxStack = (ushort)Stack.MaxValue; resultCode.MaxLocals = (ushort)LocalVarCount; }
private void CompileFlowC(ILExpression e, Java.OpCodes IntCmp, Java.OpCodes RefCmp, Java.OpCodes OtherCmp, bool unsigned = false) { unsigned = unsigned && Program.Unsigned; JavaPrimitiveType jpt = JavaHelpers.InterTypeToJavaPrimitive( resolver.Resolve(e.Arguments[0].InferredType, thisMethod.FullGenericArguments)); Action modifOp = () => { }; if (unsigned) { //From http://habrahabr.ru/post/225901 (author: @elw00d) switch (jpt) { case JavaPrimitiveType.Bool: case JavaPrimitiveType.Byte: modifOp = () => codeGenerator.AddIntConst(0x80, e).Add(OpCodes.ixor, null, e); break; case JavaPrimitiveType.Short: modifOp = () => codeGenerator.AddIntConst(0x8000, e).Add(OpCodes.ixor, null, e); break; case JavaPrimitiveType.Int: modifOp = () => codeGenerator.AddIntConst((unchecked ((int)0x80000000)), e).Add(OpCodes.ixor, null, e); break; case JavaPrimitiveType.Long: modifOp = () => codeGenerator.AddLongConst((unchecked ((long)0x8000000000000000)), e).Add(OpCodes.lxor, null, e); break; } } CompileExpression(e.Arguments[0], ExpectType.Any); modifOp(); CompileExpression(e.Arguments[1], ExpectType.Any); modifOp(); // if OtherCmp - dcmpg or fcmpg or lcmp // *Cmp true // iconst_0 // goto end //:true // iconst_1 //:end string labelPrefix = rnd.Next().ToString(); string trueLabel = labelPrefix + "true"; string endLabel = labelPrefix + "end"; switch (jpt) { case JavaPrimitiveType.Bool: case JavaPrimitiveType.Byte: case JavaPrimitiveType.Char: case JavaPrimitiveType.Short: case JavaPrimitiveType.Int: codeGenerator.Add(IntCmp, trueLabel, e); break; case JavaPrimitiveType.Ref: codeGenerator.Add(RefCmp, trueLabel, e); break; case JavaPrimitiveType.Long: codeGenerator.Add(Java.OpCodes.lcmp, null, e).Add(OtherCmp, trueLabel, e); break; case JavaPrimitiveType.Float: codeGenerator.Add(Java.OpCodes.fcmpg, null, e).Add(OtherCmp, trueLabel, e); break; case JavaPrimitiveType.Double: codeGenerator.Add(Java.OpCodes.dcmpg, null, e).Add(OtherCmp, trueLabel, e); break; } codeGenerator .Add(Java.OpCodes.iconst_0, null, e) .Add(Java.OpCodes._goto, endLabel, e) .Label(trueLabel) .Add(Java.OpCodes.iconst_1, null, e) .Label(endLabel); }
public JavaBytecodeWriter Add(Java.OpCodes op, object operand, object tag) { return(AddInstruction(new JavaInstruction(op, operand, tag))); }
public JavaBytecodeWriter Add(Java.OpCodes op) { return(AddInstruction(new JavaInstruction(op, null, null))); }
public JavaInstruction(Java.OpCodes opcode, object operand, object tag) { this.Opcode = opcode; this.Operand = operand; this.Tag = tag; }
public JavaInstruction(Java.OpCodes opcode, object operand) { this.Opcode = opcode; this.Operand = operand; this.Tag = null; }
public JavaInstruction(Java.OpCodes opcode) { this.Opcode = opcode; this.Operand = null; this.Tag = null; }