private static Instruction GetInstuction(NormalizedByteCode bc) { Instruction instruction = new Instruction(); instruction.PatchOpCode(bc); return(instruction); }
private static Instruction GetInstuction(NormalizedByteCode bc, int arg1, short arg2) { Instruction instruction = new Instruction(); instruction.PatchOpCode(bc, arg1, arg2); return(instruction); }
internal static bool CanThrowException(NormalizedByteCode bc) { switch (bc) { case NormalizedByteCode.__dynamic_invokeinterface: case NormalizedByteCode.__dynamic_invokestatic: case NormalizedByteCode.__dynamic_invokevirtual: case NormalizedByteCode.__dynamic_getstatic: case NormalizedByteCode.__dynamic_putstatic: case NormalizedByteCode.__dynamic_getfield: case NormalizedByteCode.__dynamic_putfield: case NormalizedByteCode.__clone_array: case NormalizedByteCode.__static_error: case NormalizedByteCode.__methodhandle_invoke: case NormalizedByteCode.__methodhandle_link: return(true); case NormalizedByteCode.__iconst: case NormalizedByteCode.__ldc_nothrow: return(false); default: return((data[(int)bc].flags & ByteCodeFlags.CannotThrow) == 0); } }
private static bool IsStoreLocal(NormalizedByteCode bc) { return(bc == NormalizedByteCode.__astore || bc == NormalizedByteCode.__istore || bc == NormalizedByteCode.__lstore || bc == NormalizedByteCode.__fstore || bc == NormalizedByteCode.__dstore); }
private static bool IsLoadLocal(NormalizedByteCode bc) { return(bc == NormalizedByteCode.__aload || bc == NormalizedByteCode.__iload || bc == NormalizedByteCode.__lload || bc == NormalizedByteCode.__fload || bc == NormalizedByteCode.__dload || bc == NormalizedByteCode.__iinc || bc == NormalizedByteCode.__ret); }
private ByteCodeMetaData(ByteCode bc, ByteCodeMode reg, ByteCodeModeWide wide, bool cannotThrow) { this.reg = reg; this.wide = wide; this.normbc = (NormalizedByteCode)bc; this.arg = 0; this.flags = ByteCodeFlags.None; if (cannotThrow) { this.flags |= ByteCodeFlags.CannotThrow; } data[(int)bc] = this; }
private ByteCodeMetaData(ByteCode bc, NormalizedByteCode normbc, int arg, ByteCodeMode reg, ByteCodeModeWide wide, bool cannotThrow) { this.reg = reg; this.wide = wide; this.normbc = normbc; this.arg = arg; this.flags = ByteCodeFlags.FixedArg; if (cannotThrow) { this.flags |= ByteCodeFlags.CannotThrow; } data[(int)bc] = this; }
internal static bool IsBranch(NormalizedByteCode bc) { switch (data[(int)bc].reg) { case ByteCodeMode.Branch_2: case ByteCodeMode.Branch_4: case ByteCodeMode.Lookupswitch: case ByteCodeMode.Tableswitch: return(true); default: return(false); } }
internal static ByteCodeFlowControl GetFlowControl(NormalizedByteCode bc) { switch (bc) { case NormalizedByteCode.__tableswitch: case NormalizedByteCode.__lookupswitch: return(ByteCodeFlowControl.Switch); case NormalizedByteCode.__goto: case NormalizedByteCode.__goto_finally: return(ByteCodeFlowControl.Branch); case NormalizedByteCode.__ifeq: case NormalizedByteCode.__ifne: case NormalizedByteCode.__iflt: case NormalizedByteCode.__ifge: case NormalizedByteCode.__ifgt: case NormalizedByteCode.__ifle: case NormalizedByteCode.__if_icmpeq: case NormalizedByteCode.__if_icmpne: case NormalizedByteCode.__if_icmplt: case NormalizedByteCode.__if_icmpge: case NormalizedByteCode.__if_icmpgt: case NormalizedByteCode.__if_icmple: case NormalizedByteCode.__if_acmpeq: case NormalizedByteCode.__if_acmpne: case NormalizedByteCode.__ifnull: case NormalizedByteCode.__ifnonnull: return(ByteCodeFlowControl.CondBranch); case NormalizedByteCode.__ireturn: case NormalizedByteCode.__lreturn: case NormalizedByteCode.__freturn: case NormalizedByteCode.__dreturn: case NormalizedByteCode.__areturn: case NormalizedByteCode.__return: return(ByteCodeFlowControl.Return); case NormalizedByteCode.__athrow: case NormalizedByteCode.__athrow_no_unmap: case NormalizedByteCode.__static_error: return(ByteCodeFlowControl.Throw); default: return(ByteCodeFlowControl.Next); } }
internal void PatchOpCode(int offset, NormalizedByteCode opc) { Code[OpcodeIndex + offset].PatchOpCode(opc); }
private static bool IsStoreLocal(NormalizedByteCode bc) { return bc == NormalizedByteCode.__astore || bc == NormalizedByteCode.__istore || bc == NormalizedByteCode.__lstore || bc == NormalizedByteCode.__fstore || bc == NormalizedByteCode.__dstore; }
private static bool IsLoadLocal(NormalizedByteCode bc) { return bc == NormalizedByteCode.__aload || bc == NormalizedByteCode.__iload || bc == NormalizedByteCode.__lload || bc == NormalizedByteCode.__fload || bc == NormalizedByteCode.__dload || bc == NormalizedByteCode.__iinc || bc == NormalizedByteCode.__ret; }
internal static ByteCodeFlowControl GetFlowControl(NormalizedByteCode bc) { switch (bc) { case NormalizedByteCode.__tableswitch: case NormalizedByteCode.__lookupswitch: return ByteCodeFlowControl.Switch; case NormalizedByteCode.__goto: case NormalizedByteCode.__goto_finally: return ByteCodeFlowControl.Branch; case NormalizedByteCode.__ifeq: case NormalizedByteCode.__ifne: case NormalizedByteCode.__iflt: case NormalizedByteCode.__ifge: case NormalizedByteCode.__ifgt: case NormalizedByteCode.__ifle: case NormalizedByteCode.__if_icmpeq: case NormalizedByteCode.__if_icmpne: case NormalizedByteCode.__if_icmplt: case NormalizedByteCode.__if_icmpge: case NormalizedByteCode.__if_icmpgt: case NormalizedByteCode.__if_icmple: case NormalizedByteCode.__if_acmpeq: case NormalizedByteCode.__if_acmpne: case NormalizedByteCode.__ifnull: case NormalizedByteCode.__ifnonnull: return ByteCodeFlowControl.CondBranch; case NormalizedByteCode.__ireturn: case NormalizedByteCode.__lreturn: case NormalizedByteCode.__freturn: case NormalizedByteCode.__dreturn: case NormalizedByteCode.__areturn: case NormalizedByteCode.__return: return ByteCodeFlowControl.Return; case NormalizedByteCode.__athrow: case NormalizedByteCode.__athrow_no_unmap: case NormalizedByteCode.__static_error: return ByteCodeFlowControl.Throw; default: return ByteCodeFlowControl.Next; } }
internal static bool IsBranch(NormalizedByteCode bc) { switch (data[(int)bc].reg) { case ByteCodeMode.Branch_2: case ByteCodeMode.Branch_4: case ByteCodeMode.Lookupswitch: case ByteCodeMode.Tableswitch: return true; default: return false; } }
private ByteCodeMetaData(ByteCode bc, NormalizedByteCode normbc, int arg, ByteCodeMode reg, ByteCodeModeWide wide, bool cannotThrow) { this.reg = reg; this.wide = wide; this.normbc = normbc; this.arg = arg; this.flags = ByteCodeFlags.FixedArg; if(cannotThrow) { this.flags |= ByteCodeFlags.CannotThrow; } data[(int)bc] = this; }
internal static bool CanThrowException(NormalizedByteCode bc) { switch(bc) { case NormalizedByteCode.__dynamic_invokeinterface: case NormalizedByteCode.__dynamic_invokestatic: case NormalizedByteCode.__dynamic_invokevirtual: case NormalizedByteCode.__dynamic_getstatic: case NormalizedByteCode.__dynamic_putstatic: case NormalizedByteCode.__dynamic_getfield: case NormalizedByteCode.__dynamic_putfield: case NormalizedByteCode.__clone_array: case NormalizedByteCode.__static_error: return true; case NormalizedByteCode.__iconst: return false; default: return (data[(int)bc].flags & ByteCodeFlags.CannotThrow) == 0; } }
internal void SetHardError(HardError error, int messageId) { normopcode = NormalizedByteCode.__static_error; arg2 = (short)error; arg1 = messageId; }
private ByteCodeMetaData(ByteCode bc, ByteCodeMode reg, ByteCodeModeWide wide, bool cannotThrow) { this.reg = reg; this.wide = wide; this.normbc = (NormalizedByteCode)bc; this.arg = 0; this.flags = ByteCodeFlags.None; if(cannotThrow) { this.flags |= ByteCodeFlags.CannotThrow; } data[(int)bc] = this; }
internal void PatchOpCode(NormalizedByteCode bc) { this.normopcode = bc; }
internal void PatchOpCode(NormalizedByteCode bc, int arg1, short arg2) { this.normopcode = bc; this.arg1 = arg1; this.arg2 = arg2; }
internal bool Match(int offset, NormalizedByteCode opcode) { return(Code[OpcodeIndex + offset].NormalizedOpCode == opcode); }
internal void SetTermNop(ushort pc) { // TODO what happens if we already have exactly the maximum number of instructions? this.pc = pc; this.normopcode = NormalizedByteCode.__nop; }
internal void Read(ushort pc, BigEndianBinaryReader br, ClassFile classFile) { this.pc = pc; ByteCode bc = (ByteCode)br.ReadByte(); switch(ByteCodeMetaData.GetMode(bc)) { case ByteCodeMode.Simple: break; case ByteCodeMode.Constant_1: arg1 = br.ReadByte(); classFile.MarkLinkRequiredConstantPoolItem(arg1); break; case ByteCodeMode.Local_1: arg1 = br.ReadByte(); break; case ByteCodeMode.Constant_2: arg1 = br.ReadUInt16(); classFile.MarkLinkRequiredConstantPoolItem(arg1); break; case ByteCodeMode.Branch_2: arg1 = br.ReadInt16(); break; case ByteCodeMode.Branch_4: arg1 = br.ReadInt32(); break; case ByteCodeMode.Constant_2_1_1: arg1 = br.ReadUInt16(); classFile.MarkLinkRequiredConstantPoolItem(arg1); arg2 = br.ReadByte(); if(br.ReadByte() != 0) { throw new ClassFormatError("invokeinterface filler must be zero"); } break; case ByteCodeMode.Immediate_1: arg1 = br.ReadSByte(); break; case ByteCodeMode.Immediate_2: arg1 = br.ReadInt16(); break; case ByteCodeMode.Local_1_Immediate_1: arg1 = br.ReadByte(); arg2 = br.ReadSByte(); break; case ByteCodeMode.Constant_2_Immediate_1: arg1 = br.ReadUInt16(); classFile.MarkLinkRequiredConstantPoolItem(arg1); arg2 = br.ReadSByte(); break; case ByteCodeMode.Tableswitch: { // skip the padding uint p = pc + 1u; uint align = ((p + 3) & 0x7ffffffc) - p; br.Skip(align); int default_offset = br.ReadInt32(); this.arg1 = default_offset; int low = br.ReadInt32(); int high = br.ReadInt32(); if(low > high || high > 16384L + low) { throw new ClassFormatError("Incorrect tableswitch"); } SwitchEntry[] entries = new SwitchEntry[high - low + 1]; for(int i = low; i < high; i++) { entries[i - low].value = i; entries[i - low].target = br.ReadInt32(); } // do the last entry outside the loop, to avoid overflowing "i", if high == int.MaxValue entries[high - low].value = high; entries[high - low].target = br.ReadInt32(); this.switch_entries = entries; break; } case ByteCodeMode.Lookupswitch: { // skip the padding uint p = pc + 1u; uint align = ((p + 3) & 0x7ffffffc) - p; br.Skip(align); int default_offset = br.ReadInt32(); this.arg1 = default_offset; int count = br.ReadInt32(); if(count < 0 || count > 16384) { throw new ClassFormatError("Incorrect lookupswitch"); } SwitchEntry[] entries = new SwitchEntry[count]; for(int i = 0; i < count; i++) { entries[i].value = br.ReadInt32(); entries[i].target = br.ReadInt32(); } this.switch_entries = entries; break; } case ByteCodeMode.WidePrefix: bc = (ByteCode)br.ReadByte(); // NOTE the PC of a wide instruction is actually the PC of the // wide prefix, not the following instruction (vmspec 4.9.2) switch(ByteCodeMetaData.GetWideMode(bc)) { case ByteCodeModeWide.Local_2: arg1 = br.ReadUInt16(); break; case ByteCodeModeWide.Local_2_Immediate_2: arg1 = br.ReadUInt16(); arg2 = br.ReadInt16(); break; default: throw new ClassFormatError("Invalid wide prefix on opcode: {0}", bc); } break; default: throw new ClassFormatError("Invalid opcode: {0}", bc); } this.normopcode = ByteCodeMetaData.GetNormalizedByteCode(bc); arg1 = ByteCodeMetaData.GetArg(bc, arg1); }
internal bool Match(int offset, NormalizedByteCode opcode, int arg) { return(Code[OpcodeIndex + offset].NormalizedOpCode == opcode && Code[OpcodeIndex + offset].Arg1 == arg); }
private static bool MatchInvoke(EmitIntrinsicContext eic, ref Instruction instr, NormalizedByteCode opcode, string clazz, string name, string sig) { if (instr.NormalizedOpCode == opcode) { ClassFile.ConstantPoolItemMI method = eic.ClassFile.GetMethodref(instr.Arg1); return(method.Class == clazz && method.Name == name && method.Signature == sig); } return(false); }