static void ReplaceOpcodeDest(ref OpCodes.OpCodeR op, short dst) { switch (op.Code) { case OpCodes.OpCodeREnum.Move: case OpCodeREnum.Ldc_I4_0: case OpCodeREnum.Ldc_I4_1: case OpCodeREnum.Ldc_I4_2: case OpCodeREnum.Ldc_I4_3: case OpCodeREnum.Ldc_I4_4: case OpCodeREnum.Ldc_I4_5: case OpCodeREnum.Ldc_I4_6: case OpCodeREnum.Ldc_I4_7: case OpCodeREnum.Ldc_I4_8: case OpCodeREnum.Ldc_I4_M1: case OpCodeREnum.Ldnull: case OpCodeREnum.Ldc_I4: case OpCodeREnum.Ldc_I4_S: case OpCodeREnum.Ldc_I8: case OpCodeREnum.Ldc_R4: case OpCodeREnum.Ldc_R8: case OpCodeREnum.Ldstr: case OpCodeREnum.Add: case OpCodeREnum.Add_Ovf: case OpCodeREnum.Add_Ovf_Un: case OpCodeREnum.Sub: case OpCodeREnum.Sub_Ovf: case OpCodeREnum.Sub_Ovf_Un: case OpCodeREnum.Mul: case OpCodeREnum.Mul_Ovf: case OpCodeREnum.Mul_Ovf_Un: case OpCodeREnum.Div: case OpCodeREnum.Div_Un: case OpCodeREnum.Rem: case OpCodeREnum.Rem_Un: case OpCodeREnum.Xor: case OpCodeREnum.And: case OpCodeREnum.Or: case OpCodeREnum.Shl: case OpCodeREnum.Shr: case OpCodeREnum.Shr_Un: case OpCodeREnum.Clt: case OpCodeREnum.Clt_Un: case OpCodeREnum.Cgt: case OpCodeREnum.Cgt_Un: case OpCodeREnum.Ceq: case OpCodeREnum.Conv_I: case OpCodeREnum.Conv_I1: case OpCodeREnum.Conv_I2: case OpCodeREnum.Conv_I4: case OpCodeREnum.Conv_I8: case OpCodeREnum.Conv_Ovf_I: case OpCodeREnum.Conv_Ovf_I1: case OpCodeREnum.Conv_Ovf_I1_Un: case OpCodeREnum.Conv_Ovf_I2: case OpCodeREnum.Conv_Ovf_I2_Un: case OpCodeREnum.Conv_Ovf_I4: case OpCodeREnum.Conv_Ovf_I4_Un: case OpCodeREnum.Conv_Ovf_I8: case OpCodeREnum.Conv_Ovf_I8_Un: case OpCodeREnum.Conv_Ovf_I_Un: case OpCodeREnum.Conv_Ovf_U: case OpCodeREnum.Conv_Ovf_U1: case OpCodeREnum.Conv_Ovf_U1_Un: case OpCodeREnum.Conv_Ovf_U2: case OpCodeREnum.Conv_Ovf_U2_Un: case OpCodeREnum.Conv_Ovf_U4: case OpCodeREnum.Conv_Ovf_U4_Un: case OpCodeREnum.Conv_Ovf_U8: case OpCodeREnum.Conv_Ovf_U8_Un: case OpCodeREnum.Conv_Ovf_U_Un: case OpCodeREnum.Conv_R4: case OpCodeREnum.Conv_R8: case OpCodeREnum.Conv_R_Un: case OpCodeREnum.Conv_U: case OpCodeREnum.Conv_U1: case OpCodeREnum.Conv_U2: case OpCodeREnum.Conv_U4: case OpCodeREnum.Conv_U8: case OpCodeREnum.Not: case OpCodeREnum.Neg: case OpCodeREnum.Box: case OpCodeREnum.Unbox: case OpCodeREnum.Unbox_Any: case OpCodeREnum.Call: case OpCodeREnum.Callvirt: case OpCodeREnum.Newobj: case OpCodeREnum.Ldind_I: case OpCodeREnum.Ldind_I1: case OpCodeREnum.Ldind_I2: case OpCodeREnum.Ldind_I4: case OpCodeREnum.Ldind_I8: case OpCodeREnum.Ldind_R4: case OpCodeREnum.Ldind_R8: case OpCodeREnum.Ldind_U1: case OpCodeREnum.Ldind_U2: case OpCodeREnum.Ldind_U4: case OpCodeREnum.Ldind_Ref: case OpCodeREnum.Ldobj: case OpCodeREnum.Ldloca: case OpCodeREnum.Ldloca_S: case OpCodeREnum.Ldarg_S: case OpCodeREnum.Ldarga: case OpCodeREnum.Ldarga_S: case OpCodeREnum.Ldlen: case OpCodeREnum.Newarr: case OpCodeREnum.Ldfld: case OpCodeREnum.Ldflda: case OpCodeREnum.Ldsfld: case OpCodeREnum.Ldsflda: case OpCodeREnum.Ldtoken: case OpCodeREnum.Ldftn: case OpCodeREnum.Ldvirtftn: case OpCodeREnum.Isinst: case OpCodeREnum.Ldelem_I1: case OpCodeREnum.Ldelem_U1: case OpCodeREnum.Ldelem_I2: case OpCodeREnum.Ldelem_U2: case OpCodeREnum.Ldelem_I4: case OpCodeREnum.Ldelem_U4: case OpCodeREnum.Ldelem_I8: case OpCodeREnum.Ldelem_R4: case OpCodeREnum.Ldelem_R8: case OpCodeREnum.Ldelem_Any: case OpCodeREnum.Ldelem_Ref: case OpCodeREnum.Ldelema: op.Register1 = dst; break; case OpCodeREnum.Br_S: case OpCodeREnum.Br: case OpCodeREnum.Brtrue: case OpCodeREnum.Brtrue_S: case OpCodeREnum.Brfalse: case OpCodeREnum.Brfalse_S: case OpCodeREnum.Switch: case OpCodeREnum.Blt: case OpCodeREnum.Blt_S: case OpCodeREnum.Blt_Un: case OpCodeREnum.Blt_Un_S: case OpCodeREnum.Ble: case OpCodeREnum.Ble_S: case OpCodeREnum.Ble_Un: case OpCodeREnum.Ble_Un_S: case OpCodeREnum.Bgt: case OpCodeREnum.Bgt_S: case OpCodeREnum.Bgt_Un: case OpCodeREnum.Bgt_Un_S: case OpCodeREnum.Bge: case OpCodeREnum.Bge_S: case OpCodeREnum.Bge_Un: case OpCodeREnum.Bge_Un_S: case OpCodeREnum.Beq: case OpCodeREnum.Beq_S: case OpCodeREnum.Bne_Un: case OpCodeREnum.Bne_Un_S: case OpCodeREnum.Nop: case OpCodeREnum.Ret: case OpCodeREnum.Push: case OpCodeREnum.Constrained: break; default: throw new NotImplementedException(); } }
static void ReplaceOpcodeSource(ref OpCodes.OpCodeR op, int idx, short src) { switch (op.Code) { case OpCodes.OpCodeREnum.Move: case OpCodeREnum.Conv_I: case OpCodeREnum.Conv_I1: case OpCodeREnum.Conv_I2: case OpCodeREnum.Conv_I4: case OpCodeREnum.Conv_I8: case OpCodeREnum.Conv_Ovf_I: case OpCodeREnum.Conv_Ovf_I1: case OpCodeREnum.Conv_Ovf_I1_Un: case OpCodeREnum.Conv_Ovf_I2: case OpCodeREnum.Conv_Ovf_I2_Un: case OpCodeREnum.Conv_Ovf_I4: case OpCodeREnum.Conv_Ovf_I4_Un: case OpCodeREnum.Conv_Ovf_I8: case OpCodeREnum.Conv_Ovf_I8_Un: case OpCodeREnum.Conv_Ovf_I_Un: case OpCodeREnum.Conv_Ovf_U: case OpCodeREnum.Conv_Ovf_U1: case OpCodeREnum.Conv_Ovf_U1_Un: case OpCodeREnum.Conv_Ovf_U2: case OpCodeREnum.Conv_Ovf_U2_Un: case OpCodeREnum.Conv_Ovf_U4: case OpCodeREnum.Conv_Ovf_U4_Un: case OpCodeREnum.Conv_Ovf_U8: case OpCodeREnum.Conv_Ovf_U8_Un: case OpCodeREnum.Conv_Ovf_U_Un: case OpCodeREnum.Conv_R4: case OpCodeREnum.Conv_R8: case OpCodeREnum.Conv_R_Un: case OpCodeREnum.Conv_U: case OpCodeREnum.Conv_U1: case OpCodeREnum.Conv_U2: case OpCodeREnum.Conv_U4: case OpCodeREnum.Conv_U8: case OpCodeREnum.Not: case OpCodeREnum.Neg: case OpCodeREnum.Box: case OpCodeREnum.Unbox: case OpCodeREnum.Unbox_Any: case OpCodeREnum.Ldind_I: case OpCodeREnum.Ldind_I1: case OpCodeREnum.Ldind_I2: case OpCodeREnum.Ldind_I4: case OpCodeREnum.Ldind_I8: case OpCodeREnum.Ldind_R4: case OpCodeREnum.Ldind_R8: case OpCodeREnum.Ldind_U1: case OpCodeREnum.Ldind_U2: case OpCodeREnum.Ldind_U4: case OpCodeREnum.Ldind_Ref: case OpCodeREnum.Ldobj: case OpCodeREnum.Ldloca: case OpCodeREnum.Ldloca_S: case OpCodeREnum.Ldarg_S: case OpCodeREnum.Ldarga: case OpCodeREnum.Ldarga_S: case OpCodeREnum.Ldlen: case OpCodeREnum.Newarr: case OpCodeREnum.Ldfld: case OpCodeREnum.Ldflda: case OpCodeREnum.Ldvirtftn: case OpCodeREnum.Isinst: op.Register2 = src; break; case OpCodeREnum.Stind_I: case OpCodeREnum.Stind_I1: case OpCodeREnum.Stind_I2: case OpCodeREnum.Stind_I4: case OpCodeREnum.Stind_I8: case OpCodeREnum.Stind_R4: case OpCodeREnum.Stind_R8: case OpCodeREnum.Stind_Ref: case OpCodeREnum.Stobj: case OpCodeREnum.Stfld: switch (idx) { case 0: op.Register1 = src; break; case 1: op.Register2 = src; break; default: throw new NotSupportedException(); } break; case OpCodeREnum.Add: case OpCodeREnum.Add_Ovf: case OpCodeREnum.Add_Ovf_Un: case OpCodeREnum.Sub: case OpCodeREnum.Sub_Ovf: case OpCodeREnum.Sub_Ovf_Un: case OpCodeREnum.Mul: case OpCodeREnum.Mul_Ovf: case OpCodeREnum.Mul_Ovf_Un: case OpCodeREnum.Div: case OpCodeREnum.Div_Un: case OpCodeREnum.Rem: case OpCodeREnum.Rem_Un: case OpCodeREnum.Xor: case OpCodeREnum.And: case OpCodeREnum.Or: case OpCodeREnum.Shl: case OpCodeREnum.Shr: case OpCodeREnum.Shr_Un: case OpCodeREnum.Clt: case OpCodeREnum.Clt_Un: case OpCodeREnum.Cgt: case OpCodeREnum.Cgt_Un: case OpCodeREnum.Ceq: case OpCodeREnum.Ldelem_I1: case OpCodeREnum.Ldelem_U1: case OpCodeREnum.Ldelem_I2: case OpCodeREnum.Ldelem_U2: case OpCodeREnum.Ldelem_I4: case OpCodeREnum.Ldelem_U4: case OpCodeREnum.Ldelem_I8: case OpCodeREnum.Ldelem_R4: case OpCodeREnum.Ldelem_R8: case OpCodeREnum.Ldelem_Any: case OpCodeREnum.Ldelem_Ref: case OpCodeREnum.Ldelema: switch (idx) { case 0: op.Register2 = src; break; case 1: op.Register3 = src; break; default: throw new NotSupportedException(); } break; case OpCodeREnum.Stelem_I: case OpCodeREnum.Stelem_I1: case OpCodeREnum.Stelem_I2: case OpCodeREnum.Stelem_I4: case OpCodeREnum.Stelem_I8: case OpCodeREnum.Stelem_R4: case OpCodeREnum.Stelem_R8: case OpCodeREnum.Stelem_Ref: case OpCodeREnum.Stelem_Any: switch (idx) { case 0: op.Register1 = src; break; case 1: op.Register2 = src; break; case 2: op.Register3 = src; break; default: throw new NotSupportedException(); } break; case OpCodeREnum.Call: case OpCodeREnum.Callvirt: case OpCodeREnum.Newobj: switch (idx) { case 0: op.Register2 = src; break; case 1: op.Register3 = src; break; case 2: op.Register4 = src; break; default: throw new NotSupportedException(); } break; case OpCodeREnum.Brtrue: case OpCodeREnum.Brtrue_S: case OpCodeREnum.Brfalse: case OpCodeREnum.Brfalse_S: case OpCodeREnum.Switch: case OpCodeREnum.Push: case OpCodeREnum.Throw: case OpCodeREnum.Stsfld: case OpCodeREnum.Initobj: op.Register1 = src; break; case OpCodeREnum.Blt: case OpCodeREnum.Blt_S: case OpCodeREnum.Blt_Un: case OpCodeREnum.Blt_Un_S: case OpCodeREnum.Ble: case OpCodeREnum.Ble_S: case OpCodeREnum.Ble_Un: case OpCodeREnum.Ble_Un_S: case OpCodeREnum.Bgt: case OpCodeREnum.Bgt_S: case OpCodeREnum.Bgt_Un: case OpCodeREnum.Bgt_Un_S: case OpCodeREnum.Bge: case OpCodeREnum.Bge_S: case OpCodeREnum.Bge_Un: case OpCodeREnum.Bge_Un_S: case OpCodeREnum.Beq: case OpCodeREnum.Beq_S: case OpCodeREnum.Bne_Un: case OpCodeREnum.Bne_Un_S: switch (idx) { case 0: op.Register1 = src; break; case 1: op.Register2 = src; break; default: throw new NotSupportedException(); } break; case OpCodeREnum.Ret: op.Register1 = src; break; default: throw new NotImplementedException(); } }
void Translate(CodeBasicBlock block, Instruction ins, short locVarRegStart, ref short baseRegIdx) { List <OpCodeR> lst = block.FinalInstructions; OpCodeR op = new OpCodeR(); var code = ins.OpCode; var token = ins.Operand; op.Code = (OpCodeREnum)code.Code; bool hasRet; switch (code.Code) { case Code.Br_S: case Code.Br: op.Operand = entryMapping[(Mono.Cecil.Cil.Instruction)token]; break; case Code.Brtrue: case Code.Brtrue_S: case Code.Brfalse: case Code.Brfalse_S: op.Register1 = --baseRegIdx; op.Operand = entryMapping[(Mono.Cecil.Cil.Instruction)token]; break; case Code.Switch: op.Register1 = --baseRegIdx; PrepareJumpTable(token); op.Operand = token.GetHashCode(); break; case Code.Blt: case Code.Blt_S: case Code.Blt_Un: case Code.Blt_Un_S: case Code.Ble: case Code.Ble_S: case Code.Ble_Un: case Code.Ble_Un_S: case Code.Bgt: case Code.Bgt_S: case Code.Bgt_Un: case Code.Bgt_Un_S: case Code.Bge: case Code.Bge_S: case Code.Bge_Un: case Code.Bge_Un_S: case Code.Beq: case Code.Beq_S: case Code.Bne_Un: case Code.Bne_Un_S: op.Register1 = (short)(baseRegIdx - 2); op.Register2 = (short)(baseRegIdx - 1); baseRegIdx -= 2; op.Operand = entryMapping[(Mono.Cecil.Cil.Instruction)token]; break; case Code.Ldc_I4_0: case Code.Ldc_I4_1: case Code.Ldc_I4_2: case Code.Ldc_I4_3: case Code.Ldc_I4_4: case Code.Ldc_I4_5: case Code.Ldc_I4_6: case Code.Ldc_I4_7: case Code.Ldc_I4_8: case Code.Ldc_I4_M1: case Code.Ldnull: op.Register1 = baseRegIdx++; break; case Code.Ldc_I4: op.Register1 = baseRegIdx++; op.Operand = (int)token; break; case Code.Ldc_I4_S: op.Register1 = baseRegIdx++; op.Operand = (sbyte)token; break; case Code.Ldc_I8: op.Register1 = baseRegIdx++; op.OperandLong = (long)token; break; case Code.Ldc_R4: op.Register1 = baseRegIdx++; op.OperandFloat = (float)token; break; case Code.Ldc_R8: op.Register1 = baseRegIdx++; op.OperandDouble = (double)token; break; case Code.Ldstr: op.Register1 = baseRegIdx++; op.OperandLong = appdomain.CacheString(token); break; case Code.Newobj: { bool canInline, isILMethod; ILMethod toInline; IMethod m; var pCnt = InitializeFunctionParam(ref op, token, out hasRet, out canInline, out m, out toInline, out isILMethod); int pushCnt = Math.Max(pCnt - CallRegisterParamCount, 0); for (int i = pCnt; i > pCnt - pushCnt; i--) { OpCodes.OpCodeR op2 = new OpCodes.OpCodeR(); op2.Code = OpCodes.OpCodeREnum.Push; op2.Register1 = (short)(baseRegIdx - i); lst.Add(op2); } if (pushCnt < pCnt) { switch (pCnt - pushCnt) { case 1: op.Register2 = (short)(baseRegIdx - 1); break; case 2: op.Register3 = (short)(baseRegIdx - 1); op.Register2 = (short)(baseRegIdx - 2); break; case 3: op.Register4 = (short)(baseRegIdx - 1); op.Register3 = (short)(baseRegIdx - 2); op.Register2 = (short)(baseRegIdx - 3); break; } } baseRegIdx -= (short)pCnt; op.Register1 = baseRegIdx++; } break; case Code.Call: case Code.Callvirt: { bool canInline, isILMethod; ILMethod toInline; IMethod m; var pCnt = InitializeFunctionParam(ref op, token, out hasRet, out canInline, out m, out toInline, out isILMethod); bool hasConstrained = false; int constrainIdx = -1; if (lst.Count > 0) { constrainIdx = lst.Count - 1; hasConstrained = lst[constrainIdx].Code == OpCodeREnum.Constrained; } bool needInline = canInline && !hasConstrained; if (needInline) { if (toInline.BodyRegister.Length > Optimizer.MaximalInlineInstructionCount / 2) { needInline = false; } } if (!needInline) { if (code.Code == Code.Callvirt && m is ILMethod) { ILMethod ilm = (ILMethod)m; if (!ilm.Definition.IsAbstract && !ilm.Definition.IsVirtual && !ilm.DeclearingType.IsInterface) { op.Code = OpCodeREnum.Call; } } int pushCnt = hasConstrained ? pCnt : Math.Max(pCnt - CallRegisterParamCount, 0); for (int i = pCnt; i > pCnt - pushCnt; i--) { OpCodes.OpCodeR op2 = new OpCodes.OpCodeR(); op2.Code = OpCodes.OpCodeREnum.Push; op2.Operand = isILMethod ? 1 : 0; op2.Register1 = (short)(baseRegIdx - i); lst.Add(op2); } if (pushCnt < pCnt) { switch (pCnt - pushCnt) { case 1: op.Register2 = (short)(baseRegIdx - 1); break; case 2: op.Register3 = (short)(baseRegIdx - 1); op.Register2 = (short)(baseRegIdx - 2); break; case 3: op.Register4 = (short)(baseRegIdx - 1); op.Register3 = (short)(baseRegIdx - 2); op.Register2 = (short)(baseRegIdx - 3); break; } } if (hasConstrained) { op.Operand4 = 1; var old = lst[constrainIdx]; lst.RemoveAt(constrainIdx); old.Operand2 = op.Operand2; var symbol = block.InstructionMapping[constrainIdx]; block.InstructionMapping.Remove(constrainIdx); block.InstructionMapping.Add(lst.Count, symbol); lst.Add(old); } baseRegIdx -= (short)pCnt; if (hasRet) { op.Register1 = baseRegIdx++; } else { op.Register1 = -1; } } else { baseRegIdx -= (short)pCnt; RegisterVMSymbolLink link = null; #if DEBUG && !DISABLE_ILRUNTIME_DEBUG link = new RegisterVMSymbolLink(); link.BaseRegisterIndex = baseRegIdx; link.Value.Instruction = ins; link.Value.Method = method; #endif #if DEBUG && !NO_PROFILER if (System.Threading.Thread.CurrentThread.ManagedThreadId == method.AppDomain.UnityMainThreadID) #if UNITY_5_5_OR_NEWER { UnityEngine.Profiling.Profiler.BeginSample("JITCompiler.InlineMethod"); } #else { UnityEngine.Profiler.BeginSample("JITCompiler.InlineMethod"); } #endif #endif Optimizer.InlineMethod(block, toInline, link, ref jumptables, baseRegIdx, hasRet); #if DEBUG && !NO_PROFILER if (System.Threading.Thread.CurrentThread.ManagedThreadId == method.AppDomain.UnityMainThreadID) #if UNITY_5_5_OR_NEWER { UnityEngine.Profiling.Profiler.EndSample(); } #else { UnityEngine.Profiler.EndSample(); } #endif #endif if (hasRet) { baseRegIdx++; } return; } } break; case Code.Ldsfld: case Code.Ldsflda: op.Register1 = baseRegIdx++; op.OperandLong = appdomain.GetStaticFieldIndex(token, declaringType, method); break; case Code.Stsfld: op.Register1 = --baseRegIdx; op.OperandLong = appdomain.GetStaticFieldIndex(token, declaringType, method); break; case Code.Initobj: op.Register1 = --baseRegIdx; op.Operand = method.GetTypeTokenHashCode(token); break; case Code.Ret: if (hasReturn) { op.Register1 = --baseRegIdx; } break; case Code.Throw: op.Register1 = --baseRegIdx; break; case Code.Add: case Code.Add_Ovf: case Code.Add_Ovf_Un: case Code.Sub: case Code.Sub_Ovf: case Code.Sub_Ovf_Un: case Code.Mul: case Code.Mul_Ovf: case Code.Mul_Ovf_Un: case Code.Div: case Code.Div_Un: case Code.Rem: case Code.Rem_Un: case Code.Shr: case Code.Shr_Un: case Code.Shl: case Code.Xor: case Code.Or: case Code.And: case Code.Clt: case Code.Clt_Un: case Code.Cgt: case Code.Cgt_Un: case Code.Ceq: case Code.Ldelema: case Code.Ldelem_I1: case Code.Ldelem_U1: case Code.Ldelem_I2: case Code.Ldelem_U2: case Code.Ldelem_I4: case Code.Ldelem_U4: case Code.Ldelem_I8: case Code.Ldelem_R4: case Code.Ldelem_R8: case Code.Ldelem_Any: case Code.Ldelem_Ref: op.Register1 = (short)(baseRegIdx - 2); //explicit use dest register for optimization op.Register2 = (short)(baseRegIdx - 2); op.Register3 = (short)(baseRegIdx - 1); baseRegIdx--; break; case Code.Nop: case Code.Castclass: case Code.Readonly: case Code.Volatile: case Code.Endfinally: break; case Code.Leave: case Code.Leave_S: break; case Code.Stloc_0: op.Code = OpCodes.OpCodeREnum.Move; op.Register1 = locVarRegStart; op.Register2 = --baseRegIdx; break; case Code.Stloc_1: op.Code = OpCodes.OpCodeREnum.Move; op.Register1 = (short)(locVarRegStart + 1); op.Register2 = --baseRegIdx; break; case Code.Stloc_2: op.Code = OpCodes.OpCodeREnum.Move; op.Register1 = (short)(locVarRegStart + 2); op.Register2 = --baseRegIdx; break; case Code.Stloc_3: op.Code = OpCodes.OpCodeREnum.Move; op.Register1 = (short)(locVarRegStart + 3); op.Register2 = --baseRegIdx; break; case Code.Stloc_S: op.Code = OpCodes.OpCodeREnum.Move; op.Register1 = (short)(locVarRegStart + ((VariableDefinition)ins.Operand).Index); op.Register2 = --baseRegIdx; break; case Code.Ldloc_0: op.Code = OpCodes.OpCodeREnum.Move; op.Register1 = baseRegIdx++; op.Register2 = locVarRegStart; break; case Code.Ldloc_1: op.Code = OpCodes.OpCodeREnum.Move; op.Register1 = baseRegIdx++; op.Register2 = (short)(locVarRegStart + 1); break; case Code.Ldloc_2: op.Code = OpCodes.OpCodeREnum.Move; op.Register1 = baseRegIdx++; op.Register2 = (short)(locVarRegStart + 2); break; case Code.Ldloc_3: op.Code = OpCodes.OpCodeREnum.Move; op.Register1 = baseRegIdx++; op.Register2 = (short)(locVarRegStart + 3); break; case Code.Ldloc: case Code.Ldloc_S: op.Code = OpCodes.OpCodeREnum.Move; op.Register1 = baseRegIdx++; op.Register2 = (short)(locVarRegStart + ((VariableDefinition)ins.Operand).Index); break; case Code.Ldloca: case Code.Ldloca_S: op.Register1 = baseRegIdx++; op.Register2 = (short)(locVarRegStart + ((VariableDefinition)ins.Operand).Index); break; case Code.Ldarg_0: case Code.Ldarg_1: case Code.Ldarg_2: case Code.Ldarg_3: op.Code = OpCodes.OpCodeREnum.Move; op.Register1 = baseRegIdx++; op.Register2 = (short)(code.Code - (Code.Ldarg_0)); break; case Code.Ldarg_S: op.Code = OpCodes.OpCodeREnum.Move; op.Register1 = baseRegIdx++; op.Register2 = (short)((ParameterDefinition)ins.Operand).Index; if (def.HasThis) { op.Register2++; } break; case Code.Ldarga: case Code.Ldarga_S: op.Register1 = baseRegIdx++; op.Register2 = (short)((ParameterDefinition)ins.Operand).Index; if (def.HasThis) { op.Register2++; } break; case Code.Starg: case Code.Starg_S: op.Code = OpCodes.OpCodeREnum.Move; op.Register2 = --baseRegIdx; op.Register1 = (short)((ParameterDefinition)ins.Operand).Index; if (def.HasThis) { op.Register1++; } break; case Code.Newarr: op.Register1 = (short)(baseRegIdx - 1); op.Register2 = (short)(baseRegIdx - 1); op.Operand = method.GetTypeTokenHashCode(token); break; case Code.Dup: op.Code = OpCodes.OpCodeREnum.Move; op.Register2 = (short)(baseRegIdx - 1); op.Register1 = baseRegIdx++; break; case Code.Stelem_I: case Code.Stelem_I1: case Code.Stelem_I2: case Code.Stelem_I4: case Code.Stelem_I8: case Code.Stelem_R4: case Code.Stelem_R8: case Code.Stelem_Ref: case Code.Stelem_Any: op.Register1 = (short)(baseRegIdx - 3); op.Register2 = (short)(baseRegIdx - 2); op.Register3 = (short)(baseRegIdx - 1); baseRegIdx -= 3; break; case Code.Stind_I: case Code.Stind_I1: case Code.Stind_I2: case Code.Stind_I4: case Code.Stind_I8: case Code.Stind_R4: case Code.Stind_R8: case Code.Stind_Ref: op.Register1 = (short)(baseRegIdx - 2); op.Register2 = (short)(baseRegIdx - 1); baseRegIdx -= 2; break; case Code.Stobj: op.Register1 = (short)(baseRegIdx - 2); op.Register2 = (short)(baseRegIdx - 1); op.Operand = method.GetTypeTokenHashCode(token); baseRegIdx -= 2; break; case Code.Conv_I: case Code.Conv_I1: case Code.Conv_I2: case Code.Conv_I4: case Code.Conv_I8: case Code.Conv_Ovf_I: case Code.Conv_Ovf_I1: case Code.Conv_Ovf_I1_Un: case Code.Conv_Ovf_I2: case Code.Conv_Ovf_I2_Un: case Code.Conv_Ovf_I4: case Code.Conv_Ovf_I4_Un: case Code.Conv_Ovf_I8: case Code.Conv_Ovf_I8_Un: case Code.Conv_Ovf_I_Un: case Code.Conv_Ovf_U: case Code.Conv_Ovf_U1: case Code.Conv_Ovf_U1_Un: case Code.Conv_Ovf_U2: case Code.Conv_Ovf_U2_Un: case Code.Conv_Ovf_U4: case Code.Conv_Ovf_U4_Un: case Code.Conv_Ovf_U8: case Code.Conv_Ovf_U8_Un: case Code.Conv_Ovf_U_Un: case Code.Conv_R4: case Code.Conv_R8: case Code.Conv_R_Un: case Code.Conv_U: case Code.Conv_U1: case Code.Conv_U2: case Code.Conv_U4: case Code.Conv_U8: case Code.Ldlen: case Code.Ldind_I: case Code.Ldind_I2: case Code.Ldind_I4: case Code.Ldind_I8: case Code.Ldind_R4: case Code.Ldind_R8: case Code.Ldind_U1: case Code.Ldind_U2: case Code.Ldind_U4: case Code.Ldind_Ref: case Code.Neg: case Code.Not: op.Register1 = (short)(baseRegIdx - 1); op.Register2 = (short)(baseRegIdx - 1); break; case Code.Ldobj: op.Register1 = (short)(baseRegIdx - 1); op.Register2 = (short)(baseRegIdx - 1); op.Operand = method.GetTypeTokenHashCode(token); break; case Code.Ldfld: case Code.Ldflda: op.Register1 = (short)(baseRegIdx - 1); op.Register2 = (short)(baseRegIdx - 1); op.OperandLong = appdomain.GetStaticFieldIndex(token, declaringType, method); break; case Code.Stfld: op.Register1 = (short)(baseRegIdx - 2); op.Register2 = (short)(baseRegIdx - 1); op.OperandLong = appdomain.GetStaticFieldIndex(token, declaringType, method); baseRegIdx -= 2; break; case Code.Box: case Code.Unbox: case Code.Unbox_Any: case Code.Isinst: op.Register1 = (short)(baseRegIdx - 1); op.Register2 = (short)(baseRegIdx - 1); op.Operand = method.GetTypeTokenHashCode(token); break; case Code.Constrained: op.Operand = method.GetTypeTokenHashCode(token); break; case Code.Ldtoken: op.Register1 = baseRegIdx++; if (token is FieldReference) { op.Operand = 0; op.OperandLong = appdomain.GetStaticFieldIndex(token, declaringType, method); } else if (token is TypeReference) { op.Operand = 1; op.OperandLong = method.GetTypeTokenHashCode(token); } else { throw new NotImplementedException(); } break; case Code.Ldftn: { op.Register1 = baseRegIdx++; bool hasReturn, canInline, isILMethod; ILMethod toInline; IMethod m; InitializeFunctionParam(ref op, token, out hasReturn, out canInline, out m, out toInline, out isILMethod); } break; case Code.Ldvirtftn: { bool hasReturn, canInline, isILMethod; ILMethod toInline; IMethod m; InitializeFunctionParam(ref op, token, out hasReturn, out canInline, out m, out toInline, out isILMethod); op.Register1 = (short)(baseRegIdx - 1); op.Register2 = (short)(baseRegIdx - 1); } break; case Code.Pop: baseRegIdx--; op.Code = OpCodeREnum.Nop; break; default: throw new NotImplementedException(string.Format("Unknown Opcode:{0}", code.Code)); } RegisterVMSymbol s = new RegisterVMSymbol() { Instruction = ins, Method = method }; block.InstructionMapping.Add(lst.Count, s); lst.Add(op); }
public static bool GetOpcodeDestRegister(ref OpCodes.OpCodeR op, out short r1) { r1 = -1; switch (op.Code) { case OpCodes.OpCodeREnum.Move: case OpCodeREnum.Conv_I: case OpCodeREnum.Conv_I1: case OpCodeREnum.Conv_I2: case OpCodeREnum.Conv_I4: case OpCodeREnum.Conv_I8: case OpCodeREnum.Conv_Ovf_I: case OpCodeREnum.Conv_Ovf_I1: case OpCodeREnum.Conv_Ovf_I1_Un: case OpCodeREnum.Conv_Ovf_I2: case OpCodeREnum.Conv_Ovf_I2_Un: case OpCodeREnum.Conv_Ovf_I4: case OpCodeREnum.Conv_Ovf_I4_Un: case OpCodeREnum.Conv_Ovf_I8: case OpCodeREnum.Conv_Ovf_I8_Un: case OpCodeREnum.Conv_Ovf_I_Un: case OpCodeREnum.Conv_Ovf_U: case OpCodeREnum.Conv_Ovf_U1: case OpCodeREnum.Conv_Ovf_U1_Un: case OpCodeREnum.Conv_Ovf_U2: case OpCodeREnum.Conv_Ovf_U2_Un: case OpCodeREnum.Conv_Ovf_U4: case OpCodeREnum.Conv_Ovf_U4_Un: case OpCodeREnum.Conv_Ovf_U8: case OpCodeREnum.Conv_Ovf_U8_Un: case OpCodeREnum.Conv_Ovf_U_Un: case OpCodeREnum.Conv_R4: case OpCodeREnum.Conv_R8: case OpCodeREnum.Conv_R_Un: case OpCodeREnum.Conv_U: case OpCodeREnum.Conv_U1: case OpCodeREnum.Conv_U2: case OpCodeREnum.Conv_U4: case OpCodeREnum.Conv_U8: case OpCodeREnum.Not: case OpCodeREnum.Neg: case OpCodeREnum.Box: case OpCodeREnum.Unbox: case OpCodeREnum.Unbox_Any: case OpCodeREnum.Ldc_I4_0: case OpCodeREnum.Ldc_I4_1: case OpCodeREnum.Ldc_I4_2: case OpCodeREnum.Ldc_I4_3: case OpCodeREnum.Ldc_I4_4: case OpCodeREnum.Ldc_I4_5: case OpCodeREnum.Ldc_I4_6: case OpCodeREnum.Ldc_I4_7: case OpCodeREnum.Ldc_I4_8: case OpCodeREnum.Ldc_I4_M1: case OpCodeREnum.Ldnull: case OpCodeREnum.Ldc_I4: case OpCodeREnum.Ldc_I4_S: case OpCodeREnum.Ldc_I8: case OpCodeREnum.Ldc_R4: case OpCodeREnum.Ldc_R8: case OpCodeREnum.Ldstr: case OpCodeREnum.Callvirt: case OpCodeREnum.Call: case OpCodeREnum.Newobj: case OpCodeREnum.Ldind_I: case OpCodeREnum.Ldind_I1: case OpCodeREnum.Ldind_I2: case OpCodeREnum.Ldind_I4: case OpCodeREnum.Ldind_I8: case OpCodeREnum.Ldind_R4: case OpCodeREnum.Ldind_R8: case OpCodeREnum.Ldind_U1: case OpCodeREnum.Ldind_U2: case OpCodeREnum.Ldind_U4: case OpCodeREnum.Ldind_Ref: case OpCodeREnum.Ldobj: case OpCodeREnum.Ldloca: case OpCodeREnum.Ldloca_S: case OpCodeREnum.Ldarg_S: case OpCodeREnum.Ldarga: case OpCodeREnum.Ldarga_S: case OpCodeREnum.Ldlen: case OpCodeREnum.Newarr: case OpCodeREnum.Ldfld: case OpCodeREnum.Ldflda: case OpCodeREnum.Ldtoken: case OpCodeREnum.Isinst: case OpCodeREnum.Ldsfld: case OpCodeREnum.Ldsflda: case OpCodeREnum.Ldftn: case OpCodeREnum.Ldvirtftn: case OpCodeREnum.Ldelem_I1: case OpCodeREnum.Ldelem_U1: case OpCodeREnum.Ldelem_I2: case OpCodeREnum.Ldelem_U2: case OpCodeREnum.Ldelem_I4: case OpCodeREnum.Ldelem_U4: case OpCodeREnum.Ldelem_I8: case OpCodeREnum.Ldelem_R4: case OpCodeREnum.Ldelem_R8: case OpCodeREnum.Ldelem_Any: case OpCodeREnum.Ldelem_Ref: case OpCodeREnum.Ldelema: r1 = op.Register1; return(true); case OpCodeREnum.Br_S: case OpCodeREnum.Br: case OpCodeREnum.Brtrue: case OpCodeREnum.Brtrue_S: case OpCodeREnum.Brfalse: case OpCodeREnum.Brfalse_S: case OpCodeREnum.Switch: case OpCodeREnum.Blt: case OpCodeREnum.Blt_S: case OpCodeREnum.Blt_Un: case OpCodeREnum.Blt_Un_S: case OpCodeREnum.Ble: case OpCodeREnum.Ble_S: case OpCodeREnum.Ble_Un: case OpCodeREnum.Ble_Un_S: case OpCodeREnum.Bgt: case OpCodeREnum.Bgt_S: case OpCodeREnum.Bgt_Un: case OpCodeREnum.Bgt_Un_S: case OpCodeREnum.Bge: case OpCodeREnum.Bge_S: case OpCodeREnum.Bge_Un: case OpCodeREnum.Bge_Un_S: case OpCodeREnum.Beq: case OpCodeREnum.Beq_S: case OpCodeREnum.Bne_Un: case OpCodeREnum.Bne_Un_S: case OpCodeREnum.Nop: case OpCodeREnum.Constrained: case OpCodeREnum.Ret: case OpCodeREnum.Push: case OpCodeREnum.Initobj: case OpCodeREnum.InlineStart: case OpCodeREnum.InlineEnd: case OpCodeREnum.Stind_I: case OpCodeREnum.Stind_I1: case OpCodeREnum.Stind_I2: case OpCodeREnum.Stind_I4: case OpCodeREnum.Stind_I8: case OpCodeREnum.Stind_R4: case OpCodeREnum.Stind_R8: case OpCodeREnum.Stind_Ref: case OpCodeREnum.Stobj: case OpCodeREnum.Stelem_I: case OpCodeREnum.Stelem_I1: case OpCodeREnum.Stelem_I2: case OpCodeREnum.Stelem_I4: case OpCodeREnum.Stelem_I8: case OpCodeREnum.Stelem_R4: case OpCodeREnum.Stelem_R8: case OpCodeREnum.Stelem_Ref: case OpCodeREnum.Stelem_Any: case OpCodeREnum.Stfld: case OpCodeREnum.Stsfld: case OpCodeREnum.Throw: case OpCodeREnum.Castclass: case OpCodeREnum.Readonly: case OpCodeREnum.Leave: case OpCodeREnum.Leave_S: case OpCodeREnum.Endfinally: case OpCodeREnum.Volatile: return(false); case OpCodeREnum.Add: case OpCodeREnum.Add_Ovf: case OpCodeREnum.Add_Ovf_Un: case OpCodeREnum.Sub: case OpCodeREnum.Sub_Ovf: case OpCodeREnum.Sub_Ovf_Un: case OpCodeREnum.Mul: case OpCodeREnum.Mul_Ovf: case OpCodeREnum.Mul_Ovf_Un: case OpCodeREnum.Div: case OpCodeREnum.Div_Un: case OpCodeREnum.Rem: case OpCodeREnum.Rem_Un: case OpCodeREnum.Xor: case OpCodeREnum.And: case OpCodeREnum.Or: case OpCodeREnum.Shl: case OpCodeREnum.Shr: case OpCodeREnum.Shr_Un: case OpCodeREnum.Clt: case OpCodeREnum.Clt_Un: case OpCodeREnum.Cgt: case OpCodeREnum.Cgt_Un: case OpCodeREnum.Ceq: r1 = op.Register1; return(true); default: throw new NotImplementedException(); } }
int InitializeFunctionParam(ref OpCodes.OpCodeR op, object token, out bool hasReturn, out bool canInline, out IMethod m, out ILMethod toInline, out bool isILMethod) { bool invalidToken; int pCnt = 0; m = appdomain.GetMethod(token, declaringType, method, out invalidToken); toInline = null; canInline = false; op.Register2 = -1; op.Register3 = -1; op.Register4 = -1; if (m != null) { if (invalidToken) { op.Operand2 = m.GetHashCode(); } else { op.Operand2 = token.GetHashCode(); } pCnt = m.ParameterCount; if (!m.IsStatic && op.Code != OpCodeREnum.Newobj) { pCnt++; } hasReturn = m.ReturnType != appdomain.VoidType; if (m is ILMethod) { isILMethod = !m.IsDelegateInvoke; var ilm = (ILMethod)m; bool noJIT = (ilm.JITFlags & ILRuntimeJITFlags.NoJIT) != ILRuntimeJITFlags.None; bool forceInline = (ilm.JITFlags & ILRuntimeJITFlags.ForceInline) != ILRuntimeJITFlags.None; bool hasExceptionHandler = ilm.Definition.HasBody && ilm.Definition.Body.HasExceptionHandlers; if (!ilm.IsDelegateInvoke && !ilm.IsVirtual && !noJIT && !hasExceptionHandler && !ilm.Compiling) { var def = ilm.Definition; bool codeSizeOK = ilm.IsRegisterBodyReady ? ilm.BodyRegister.Length <= Optimizer.MaximalInlineInstructionCount : def.Body.Instructions.Count <= Optimizer.MaximalInlineInstructionCount; if (!def.HasBody || forceInline || codeSizeOK) { canInline = true; toInline = ilm; } } } else { isILMethod = false; } } else { isILMethod = false; //Cannot find method or the method is dummy MethodReference _ref = (MethodReference)token; pCnt = _ref.HasParameters ? _ref.Parameters.Count : 0; if (_ref.HasThis && op.Code != OpCodeREnum.Newobj) { pCnt++; } op.Operand3 = pCnt; hasReturn = false; } return(pCnt); }