private ILCode CreateCode(string moduleName, string typeName, AstNode exp) { if (Path.GetFileName(moduleName) != moduleName) { throw new Exception("can only output into current directory!"); } var name = new AssemblyName(Path.GetFileNameWithoutExtension(moduleName)); AssemblyBuilder asmb = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Save); ModuleBuilder modb = asmb.DefineDynamicModule(moduleName); TypeBuilder typeBuilder = modb.DefineType(typeName); MethodBuilder methMain = typeBuilder.DefineMethod("Main", MethodAttributes.Static, typeof(void), Type.EmptyTypes); var ilcode = new ILCode { Type = typeBuilder, Method = methMain, Module = modb }; init.CodeInfo = ilcode; init.GeneratePredifinedCode(); TypeBuilder nested = AddFunctionMainToCode(ilcode, methMain); ilcode.Type = nested; ILCodeGenerator codeGenerator = new ILCodeGenerator(ilcode); //generacion de codigos exp.Accept(codeGenerator); ILGenerator il = methMain.GetILGenerator(); il.Emit(OpCodes.Ret); nested.CreateType(); typeBuilder.CreateType(); modb.CreateGlobalFunctions(); asmb.SetEntryPoint(methMain); asmb.Save(moduleName); return(ilcode); }
public static bool IsConvFromUnsigned(this ILCode self) { switch (self) { case ILCode.Conv_Ovf_I_Un: case ILCode.Conv_Ovf_I1_Un: case ILCode.Conv_Ovf_I2_Un: case ILCode.Conv_Ovf_I4_Un: case ILCode.Conv_Ovf_I8_Un: case ILCode.Conv_Ovf_U_Un: case ILCode.Conv_Ovf_U1_Un: case ILCode.Conv_Ovf_U2_Un: case ILCode.Conv_Ovf_U4_Un: case ILCode.Conv_Ovf_U8_Un: case ILCode.Conv_R_Un: return(Program.Unsigned); default: return(false); } }
public override string ToString() { var ret = new StringBuilder(); ret.AppendFormat("{0}{1}(", ILCode.ToOpCode().Name, Type == null ? "" : ":" + Type.Value); if (Operand != null) { if (Operand is string) { ASTConstant.EscapeString(ret, (string)Operand, true); } else if (Operand is IBasicBlock) { ret.AppendFormat("Block_{0:x2}", ((IBasicBlock)Operand).Id); } else if (Operand is IBasicBlock[]) { var targets = ((IBasicBlock[])Operand).Select(block => string.Format("Block_{0:x2}", block.Id)); ret.AppendFormat("[{0}]", string.Join(", ", targets)); } else { ret.Append(Operand); } if (Arguments.Length > 0) { ret.Append(";"); } } for (int i = 0; i < Arguments.Length; i++) { if (i != 0) { ret.Append(","); } ret.Append(Arguments[i]); } ret.Append(")"); return(ret.ToString()); }
private void CreateParams(ILCode code, bool isFunction, out Type returnType, out Type[] parameterTypes) { returnType = null; if (isFunction) { string typeCodeName = _functionInvocation.CurrentScope.GetTypeInfo(ReturnTypeId()).CodeName; returnType = code.DefinedType[typeCodeName]; } parameterTypes = null; List <KeyValuePair <string, string> > ParameterList = GetParameterList(); if (ParameterList != null) { parameterTypes = new Type[ParameterList.Count]; for (int i = 0; i < ParameterList.Count; i++) { string typeCodeName = _functionInvocation.CurrentScope.GetTypeInfo(ParameterList[i].Value).CodeName; parameterTypes[i] = code.DefinedType[typeCodeName]; } } }
private MethodBuilder GetMethod(string funCodeName, ILCode code) { //si esta definida la uso if (code.DefinedMethod.ContainsKey(funCodeName)) { return(code.DefinedMethod[funCodeName]); } //sino no esta definida creo su signatura. //este es el nombre de la clase que contiene a este funcion string parentWrapper = string.Format("Tg_{0}", FunctionParentCodeName()); //obtengo el tipo de la clase var container = (TypeBuilder)code.DefinedType[parentWrapper]; Type returnType; Type[] parameterTypes; //creo los paremtros de la funcion bool isFunction = !string.IsNullOrEmpty(ReturnTypeId()); //creando los parametros y el tipo de retorno CreateParams(code, isFunction, out returnType, out parameterTypes); //creo la funcion como un metodo de instancia. MethodBuilder mBuilder = container.DefineMethod(FunctionCodeName(), MethodAttributes.Public, returnType, parameterTypes); //adiciono la nueva funcion que he declarado code.DefinedMethod.Add(mBuilder.Name, mBuilder); //Tener en cuenta cuando se llame la funcion antes de ser declarada ,hay que annadir el metodo a su padre string currentFunctionParent = _functionInvocation.CurrentScope.CurrentFunction.FunctionParent.CodeName; TypeCodeInfo typeCodeInfo = code.GetWrapperAsociatteTo(currentFunctionParent); typeCodeInfo.AddMethod(mBuilder.Name, mBuilder); //typcodeindo return(mBuilder); }
//public static Dictionary<MethodBase, uint> MethodUIDs = new Dictionary<MethodBase, uint>(); public OpMethod(ILCode aCode, int aPosition, int aNextPosition, MethodBase aValue, ExceptionHandlingClause aEhc) : base(aCode, aPosition, aNextPosition, aEhc) { Value = aValue; MethodUID = 0; if (aValue.IsAbstract) { MethodUID = (uint)aValue.GetHashCode(); /* * if (MethodUIDs.ContainsKey(aValue)) * { * MethodUID = MethodUIDs[aValue]; * } * else * { * MethodUID = Counter++; * MethodUIDs.Add(aValue, MethodUID); * }*/ } }
public static bool IsUnconditionalControlFlow(this ILCode code) { switch (code) { case ILCode.Br: case ILCode.__Br_S: case ILCode.Leave: case ILCode.__Leave_S: case ILCode.Ret: case ILCode.Endfilter: case ILCode.Endfinally: case ILCode.Throw: case ILCode.Rethrow: case ILCode.LoopContinue: case ILCode.LoopOrSwitchBreak: case ILCode.YieldBreak: return(true); default: return(false); } }
public static bool IsLoadFromArray(this ILCode code) { switch (code) { case ILCode.Ldelem_Any: case ILCode.Ldelem_I: case ILCode.Ldelem_I1: case ILCode.Ldelem_I2: case ILCode.Ldelem_I4: case ILCode.Ldelem_I8: case ILCode.Ldelem_U1: case ILCode.Ldelem_U2: case ILCode.Ldelem_U4: case ILCode.Ldelem_R4: case ILCode.Ldelem_R8: case ILCode.Ldelem_Ref: return(true); default: return(false); } }
private static TypeBuilder AddFunctionMainToCode(ILCode code, MethodBuilder main) { code.DefinedMethod.Add(MainFunction, main); //crear lo que sera el wrapper a esta funcion string currentWrapper = string.Format("Tg_{0}", MainFunction); TypeBuilder typeNested = code.Type.DefineNestedType(currentWrapper, TypeAttributes.NestedPublic); //crear en la variable de instancia de la clase contenedora,pues el Let asume que la tiene creada. ILGenerator il = main.GetILGenerator(); il.DeclareLocal(typeNested); //annadir a la clase code el tipo. code.DefinedType.Add(typeNested.Name, typeNested); //asociar el tipo wrapper al metodo code.AsociatteMethodToWrapper(MainFunction, currentWrapper); code.GetWrapperAsociatteTo(MainFunction); //PopulateNestedTypeWithVar(code, typeNested, typeCodeInfo); return(typeNested); }
private void code_OnBeginMethod_var(VarDeclarationAST varDecl, ILCode theCode, BeginMethodEventArgs e) { VarInfo varInfo = varDecl.CurrentScope.GetVarInfo(varDecl.Id); var isMyFunction = varDecl.CurrentScope.GetFunction(varInfo.FunctionNameParent).CodeName == e.FunctionCodeName; //it is true if the funcion (e.FunctionCodeName) is the same that the function that declares this variable. if (isMyFunction) { ILGenerator il = code.Method.GetILGenerator(); //---> bool pushOnStack = code.PushOnStack; code.PushOnStack = true; string varCodeName = varInfo.CodeName; if (!varInfo.IsUsedForAnotherFunction) { if (!varInfo.IsParameterFunction) //significa que es una variable local { varDecl.ExpressionValue.Accept(this); il.Emit(OpCodes.Stloc, code.DefinedLocal[varCodeName].LocalIndex); } } else { if (!varInfo.IsParameterFunction) //significa que es un campo de la clase { //cargar la instancia de la clase contenedora que tengo como variable local il.Emit(OpCodes.Ldloc_0); varDecl.ExpressionValue.Accept(this); il.Emit(OpCodes.Stfld, code.DefinedField[varCodeName]); } } //<--- code.PushOnStack = pushOnStack; } }
private void GenerateCodeForLogicalExpression(ILCode code) { ILGenerator il = code.Method.GetILGenerator(); //hacer el corto circuito. //---> me quedo con el valor bool pushOnStack = code.PushOnStack; Label result = il.DefineLabel(); Label end = il.DefineLabel(); // cargar valor exp1 code.PushOnStack = true; _binaryExpression.LeftExp.Accept(_codeGenerator); //poner el salto PushJump(code, result); //cargar valor expr2 code.PushOnStack = true; _binaryExpression.RightExp.Accept(_codeGenerator); il.Emit(OpCodes.Br, end); il.MarkLabel(result); PushResult(code); il.MarkLabel(end); if (!pushOnStack) { il.Emit(OpCodes.Pop); } //<--- pongo el valor il code.PushOnStack = pushOnStack; }
private static void OrdFunction(string functionName, ILCode codeInfo) { TypeBuilder type = codeInfo.Type; //ord(s:string) MethodBuilder ord = type.DefineMethod(functionName, MethodAttributes.Static | MethodAttributes.Public, typeof(int), new[] { typeof(string) }); ILGenerator il = ord.GetILGenerator(); //TODO: Esto fue cambiado LocalBuilder result = il.DeclareLocal(typeof(int)); Label asciiValue = il.DefineLabel(); Label end = il.DefineLabel(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, typeof(string).GetMethod("IsNullOrEmpty")); il.Emit(OpCodes.Brfalse_S, asciiValue); il.Emit(OpCodes.Ldc_I4_M1); il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Br_S, end); il.MarkLabel(asciiValue); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Callvirt, typeof(string).GetMethod("get_Chars", new[] { typeof(int) })); il.Emit(OpCodes.Conv_I1); il.Emit(OpCodes.Stloc_0); il.MarkLabel(end); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ret); codeInfo.DefinedMethod.Add(functionName, ord); }
public static bool IsOvf(this ILCode self) { switch (self) { case ILCode.Conv_Ovf_I: case ILCode.Conv_Ovf_I_Un: case ILCode.Conv_Ovf_I1: case ILCode.Conv_Ovf_I1_Un: case ILCode.Conv_Ovf_I2: case ILCode.Conv_Ovf_I2_Un: case ILCode.Conv_Ovf_I4: case ILCode.Conv_Ovf_I4_Un: case ILCode.Conv_Ovf_I8: case ILCode.Conv_Ovf_I8_Un: case ILCode.Conv_Ovf_U: case ILCode.Conv_Ovf_U_Un: case ILCode.Conv_Ovf_U1: case ILCode.Conv_Ovf_U1_Un: case ILCode.Conv_Ovf_U2: case ILCode.Conv_Ovf_U2_Un: case ILCode.Conv_Ovf_U4: case ILCode.Conv_Ovf_U4_Un: case ILCode.Conv_Ovf_U8: case ILCode.Conv_Ovf_U8_Un: case ILCode.Add_Ovf: case ILCode.Add_Ovf_Un: case ILCode.Sub_Ovf: case ILCode.Sub_Ovf_Un: case ILCode.Mul_Ovf: case ILCode.Mul_Ovf_Un: return(Program.OverflowCheck); default: return(false); } }
ILExpression MakeLeftAssociativeShortCircuit(ILCode code, ILExpression left, ILExpression right) { // Assuming that the inputs are already left associative if (right.Match(code)) { // Find the leftmost logical expression ILExpression current = right; while(current.Arguments[0].Match(code)) current = current.Arguments[0]; current.Arguments[0] = new ILExpression(code, null, left, current.Arguments[0]); return right; } else { return new ILExpression(code, null, left, right); } }
internal OpField(ILCode aCode, int aPosition, int aNextPosition, FieldInfo aValue, ExceptionHandlingClause aEhc) : base(aCode, aPosition, aNextPosition, aEhc) { Value = aValue; }
public VariablePattern(ILCode code, bool b) : base(null) { this.code = code; this.b = b; }
public ILPattern(ILCode code, params Pattern[] arguments) : base(arguments) { this.code = code; }
/// <summary> /// 指令优化,合并指令 /// </summary> /// <param name="input"></param> /// <returns></returns> public static List <ILCode> MergeCodes(List <ILCode> input, List <string> locals = null, List <string> args = null) { List <ILCode> outPut = new List <ILCode>(); var opSpeed = new List <string>(new string[] { "add", "sub", "mul", "div" }); for (int i = 0; i < input.Count; i++) { var now = input[i]; //if (now.OpCode == "nop") //{ // continue; //} if (i > 2 && i < input.Count - 2) { var before2 = input[i - 1 - 1]; var before = input[i - 1]; var next = input[i + 1]; var newx2 = input[i + 1 + 1]; if (opSpeed.Contains(now.Op) && locals != null) { if (before2.Op == "ldc") { now.OpCode += "." + before2.OpArg0; } else if (before.Op == "ldc") { now.OpCode += "." + before.OpArg0; } else if (before2.Op == "ldloc") { now.OpCode += "." + locals[int.Parse(before2.OpArg0)]; } else if (before.Op == "ldloc") { now.OpCode += "." + locals[int.Parse(before.OpArg0)]; } else if (before2.Op == "ldarg") { now.OpCode += "." + args[int.Parse(before2.OpArg0)]; } else if (before.Op == "ldarg") { now.OpCode += "." + args[int.Parse(before.OpArg0)]; } } } if (i < input.Count - 2) { var next = input[i + 1]; var newx2 = input[i + 1 + 1]; #if SPEED if (now.Op == "ldc" && next.Op == "stloc") { var opcode = new ILCode() { OpCode = "LdcStloc", Arg0 = now.OpArg0, Arg1 = now.OpArg1 == null ? now.Arg0 : now.OpArg1, Arg2 = next.OpArg0, Lable = now.Lable, Line = now.Line + " " + next.Line }; opcode.Op = opcode.OpCode; i++; outPut.Add(opcode); continue; } if (now.Op == "ldloc" && next.Op == "ldloc") { var opcode = new ILCode() { OpCode = "ldlocldloc", Arg0 = now.OpArg0, Arg1 = next.OpArg0, Lable = now.Lable, Line = now.Line + " " + next.Line }; i++; outPut.Add(opcode); continue; } #endif } outPut.Add(now); } return(outPut); }
public static bool Match(this ILNode node, ILCode code) { ILExpression expr = node as ILExpression; return(expr != null && expr.Prefixes == null && expr.Code == code); }
bool isMatchControlBr(ILCode c, int value) { switch (c) { case ILCode.__Beq_S: case ILCode.__Bge_S: case ILCode.__Bgt_S: case ILCode.__Ble_S: case ILCode.__Blt_S: case ILCode.__Bne_Un_S: case ILCode.__Bge_Un_S: case ILCode.__Bgt_Un_S: case ILCode.__Ble_Un_S: case ILCode.__Blt_Un_S: case ILCode.__Beq: case ILCode.__Bge: case ILCode.__Bgt: case ILCode.__Ble: case ILCode.__Blt: case ILCode.__Bne_Un: case ILCode.__Bge_Un: case ILCode.__Bgt_Un: case ILCode.__Ble_Un: case ILCode.__Blt_Un: break; case ILCode.__Brfalse_S: case ILCode.__Brfalse: return value == 0; case ILCode.__Brtrue_S: case ILCode.Brtrue: return value != 0; default: break; } return false; }
ILExpression IntroducePostIncrementForInstanceFields(ILExpression expr) { // stfld(field, ldloc(instance), add(stloc(helperVar, ldfld(field, ldloc(instance))), ldc.i4(1))) // -> stloc(helperVar, postincrement(1, ldflda(field, ldloc(instance)))) // Also works for array elements and pointers: // stelem.any(T, ldloc(instance), ldloc(pos), add(stloc(helperVar, ldelem.any(T, ldloc(instance), ldloc(pos))), ldc.i4(1))) // -> stloc(helperVar, postincrement(1, ldelema(ldloc(instance), ldloc(pos)))) // stobj(T, ldloc(ptr), add(stloc(helperVar, ldobj(T, ldloc(ptr)), ldc.i4(1)))) // -> stloc(helperVar, postIncrement(1, ldloc(ptr))) // callsetter(set_P, ldloc(instance), add(stloc(helperVar, callgetter(get_P, ldloc(instance))), ldc.i4(1))) // -> stloc(helperVar, postIncrement(1, propertyaddress. callgetter(get_P, ldloc(instance)))) if (!(expr.Code == ILCode.Stfld || expr.Code.IsStoreToArray() || expr.Code == ILCode.Stobj || expr.Code == ILCode.CallSetter || expr.Code == ILCode.CallvirtSetter)) { return(null); } // Test that all arguments except the last are ldloc (1 arg for fields and pointers, 2 args for arrays) for (int i = 0; i < expr.Arguments.Count - 1; i++) { if (expr.Arguments[i].Code != ILCode.Ldloc) { return(null); } } ILExpression addExpr = expr.Arguments[expr.Arguments.Count - 1]; int incrementAmount; ILCode incrementCode = GetIncrementCode(addExpr, out incrementAmount); ILVariable helperVar; ILExpression initialValue; if (!(incrementAmount != 0 && addExpr.Arguments[0].Match(ILCode.Stloc, out helperVar, out initialValue))) { return(null); } if (expr.Code == ILCode.Stfld) { if (initialValue.Code != ILCode.Ldfld) { return(null); } // There might be two different FieldReference instances, so we compare the field's signatures: FieldReference getField = (FieldReference)initialValue.Operand; FieldReference setField = (FieldReference)expr.Operand; if (!(TypeAnalysis.IsSameType(getField.DeclaringType, setField.DeclaringType) && getField.Name == setField.Name && TypeAnalysis.IsSameType(getField.FieldType, setField.FieldType))) { return(null); } } else if (expr.Code == ILCode.Stobj) { if (!(initialValue.Code == ILCode.Ldobj && initialValue.Operand == expr.Operand)) { return(null); } } else if (expr.Code == ILCode.CallSetter) { if (!(initialValue.Code == ILCode.CallGetter && IsGetterSetterPair(initialValue.Operand, expr.Operand))) { return(null); } } else if (expr.Code == ILCode.CallvirtSetter) { if (!(initialValue.Code == ILCode.CallvirtGetter && IsGetterSetterPair(initialValue.Operand, expr.Operand))) { return(null); } } else { if (!initialValue.Code.IsLoadFromArray()) { return(null); } } Debug.Assert(expr.Arguments.Count - 1 == initialValue.Arguments.Count); for (int i = 0; i < initialValue.Arguments.Count; i++) { if (!initialValue.Arguments[i].MatchLdloc((ILVariable)expr.Arguments[i].Operand)) { return(null); } } ILExpression stloc = addExpr.Arguments[0]; if (expr.Code == ILCode.Stobj) { stloc.Arguments[0] = new ILExpression(ILCode.PostIncrement, incrementAmount, initialValue.Arguments[0]); } else if (expr.Code == ILCode.CallSetter || expr.Code == ILCode.CallvirtSetter) { initialValue = new ILExpression(ILCode.AddressOf, null, initialValue); stloc.Arguments[0] = new ILExpression(ILCode.PostIncrement, incrementAmount, initialValue); } else { stloc.Arguments[0] = new ILExpression(ILCode.PostIncrement, incrementAmount, initialValue); initialValue.Code = (expr.Code == ILCode.Stfld ? ILCode.Ldflda : ILCode.Ldelema); } // TODO: ILRanges? return(stloc); }
static object InvokeNodeTranslator(ILCode code, object thisReference, object[] arguments) { MethodBase boundMethod = null; var methods = GetNodeTranslators(code); if (methods != null) { if (methods.Length > 1) { var bindingFlags = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.NonPublic; var binder = Type.DefaultBinder; object state; try { boundMethod = binder.BindToMethod( bindingFlags, methods, ref arguments, null, null, null, out state ); } catch (Exception exc) { throw new Exception(String.Format( "Failed to bind to translator method for ILCode.{0}. Had {1} options:{2}{3}", code, methods.Length, Environment.NewLine, String.Join(Environment.NewLine, (from m in methods select m.ToString()).ToArray()) ), exc); } } else { boundMethod = methods[0]; } } if (boundMethod == null) { throw new MissingMethodException( String.Format("Could not find a node translator for the node type '{0}'.", code) ); } return boundMethod.Invoke(thisReference, arguments); }
static System.Reflection.MethodInfo[] GetNodeTranslators(ILCode code) { return NodeTranslatorCache.GetOrCreate( code, () => { var methodName = String.Format("Translate_{0}", code); var bindingFlags = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.NonPublic; var t = typeof(ILBlockTranslator); var methods = t.GetMember( methodName, MemberTypes.Method, bindingFlags ).OfType<System.Reflection.MethodInfo>().ToArray(); if (methods.Length == 0) { var alternateMethodName = methodName.Substring(0, methodName.LastIndexOf("_")); methods = t.GetMember( alternateMethodName, MemberTypes.Method, bindingFlags ).OfType<System.Reflection.MethodInfo>().ToArray(); } if (methods.Length == 0) return null; return methods; } ); }
public static void ExpandMacro(ref ILCode code, ref object operand, MethodBody methodBody) { switch (code) { case ILCode.__Ldarg_0: code = ILCode.Ldarg; operand = methodBody.GetParameter(0); break; case ILCode.__Ldarg_1: code = ILCode.Ldarg; operand = methodBody.GetParameter(1); break; case ILCode.__Ldarg_2: code = ILCode.Ldarg; operand = methodBody.GetParameter(2); break; case ILCode.__Ldarg_3: code = ILCode.Ldarg; operand = methodBody.GetParameter(3); break; case ILCode.__Ldloc_0: code = ILCode.Ldloc; operand = methodBody.Variables[0]; break; case ILCode.__Ldloc_1: code = ILCode.Ldloc; operand = methodBody.Variables[1]; break; case ILCode.__Ldloc_2: code = ILCode.Ldloc; operand = methodBody.Variables[2]; break; case ILCode.__Ldloc_3: code = ILCode.Ldloc; operand = methodBody.Variables[3]; break; case ILCode.__Stloc_0: code = ILCode.Stloc; operand = methodBody.Variables[0]; break; case ILCode.__Stloc_1: code = ILCode.Stloc; operand = methodBody.Variables[1]; break; case ILCode.__Stloc_2: code = ILCode.Stloc; operand = methodBody.Variables[2]; break; case ILCode.__Stloc_3: code = ILCode.Stloc; operand = methodBody.Variables[3]; break; case ILCode.__Ldarg_S: code = ILCode.Ldarg; break; case ILCode.__Ldarga_S: code = ILCode.Ldarga; break; case ILCode.__Starg_S: code = ILCode.Starg; break; case ILCode.__Ldloc_S: code = ILCode.Ldloc; break; case ILCode.__Ldloca_S: code = ILCode.Ldloca; break; case ILCode.__Stloc_S: code = ILCode.Stloc; break; case ILCode.__Ldc_I4_M1: code = ILCode.Ldc_I4; operand = -1; break; case ILCode.__Ldc_I4_0: code = ILCode.Ldc_I4; operand = 0; break; case ILCode.__Ldc_I4_1: code = ILCode.Ldc_I4; operand = 1; break; case ILCode.__Ldc_I4_2: code = ILCode.Ldc_I4; operand = 2; break; case ILCode.__Ldc_I4_3: code = ILCode.Ldc_I4; operand = 3; break; case ILCode.__Ldc_I4_4: code = ILCode.Ldc_I4; operand = 4; break; case ILCode.__Ldc_I4_5: code = ILCode.Ldc_I4; operand = 5; break; case ILCode.__Ldc_I4_6: code = ILCode.Ldc_I4; operand = 6; break; case ILCode.__Ldc_I4_7: code = ILCode.Ldc_I4; operand = 7; break; case ILCode.__Ldc_I4_8: code = ILCode.Ldc_I4; operand = 8; break; case ILCode.__Ldc_I4_S: code = ILCode.Ldc_I4; operand = (int) (sbyte) operand; break; case ILCode.__Br_S: code = ILCode.Br; break; case ILCode.__Brfalse_S: code = ILCode.__Brfalse; break; case ILCode.__Brtrue_S: code = ILCode.Brtrue; break; case ILCode.__Beq_S: code = ILCode.__Beq; break; case ILCode.__Bge_S: code = ILCode.__Bge; break; case ILCode.__Bgt_S: code = ILCode.__Bgt; break; case ILCode.__Ble_S: code = ILCode.__Ble; break; case ILCode.__Blt_S: code = ILCode.__Blt; break; case ILCode.__Bne_Un_S: code = ILCode.__Bne_Un; break; case ILCode.__Bge_Un_S: code = ILCode.__Bge_Un; break; case ILCode.__Bgt_Un_S: code = ILCode.__Bgt_Un; break; case ILCode.__Ble_Un_S: code = ILCode.__Ble_Un; break; case ILCode.__Blt_Un_S: code = ILCode.__Blt_Un; break; case ILCode.__Leave_S: code = ILCode.Leave; break; } }
static bool IsWithoutSideEffects(ILCode code) { return code == ILCode.Ldloc; }
public static void ExpandMacro(ref ILCode code, ref object operand, MethodBody methodBody) { switch (code) { case ILCode.__Ldarg_0: code = ILCode.__Ldarg; operand = methodBody.GetParameter(0); break; case ILCode.__Ldarg_1: code = ILCode.__Ldarg; operand = methodBody.GetParameter(1); break; case ILCode.__Ldarg_2: code = ILCode.__Ldarg; operand = methodBody.GetParameter(2); break; case ILCode.__Ldarg_3: code = ILCode.__Ldarg; operand = methodBody.GetParameter(3); break; case ILCode.__Ldloc_0: code = ILCode.Ldloc; operand = methodBody.Variables[0]; break; case ILCode.__Ldloc_1: code = ILCode.Ldloc; operand = methodBody.Variables[1]; break; case ILCode.__Ldloc_2: code = ILCode.Ldloc; operand = methodBody.Variables[2]; break; case ILCode.__Ldloc_3: code = ILCode.Ldloc; operand = methodBody.Variables[3]; break; case ILCode.__Stloc_0: code = ILCode.Stloc; operand = methodBody.Variables[0]; break; case ILCode.__Stloc_1: code = ILCode.Stloc; operand = methodBody.Variables[1]; break; case ILCode.__Stloc_2: code = ILCode.Stloc; operand = methodBody.Variables[2]; break; case ILCode.__Stloc_3: code = ILCode.Stloc; operand = methodBody.Variables[3]; break; case ILCode.__Ldarg_S: code = ILCode.__Ldarg; break; case ILCode.__Ldarga_S: code = ILCode.__Ldarga; break; case ILCode.__Starg_S: code = ILCode.__Starg; break; case ILCode.__Ldloc_S: code = ILCode.Ldloc; break; case ILCode.__Ldloca_S: code = ILCode.Ldloca; break; case ILCode.__Stloc_S: code = ILCode.Stloc; break; case ILCode.__Ldc_I4_M1: code = ILCode.Ldc_I4; operand = -1; break; case ILCode.__Ldc_I4_0: code = ILCode.Ldc_I4; operand = 0; break; case ILCode.__Ldc_I4_1: code = ILCode.Ldc_I4; operand = 1; break; case ILCode.__Ldc_I4_2: code = ILCode.Ldc_I4; operand = 2; break; case ILCode.__Ldc_I4_3: code = ILCode.Ldc_I4; operand = 3; break; case ILCode.__Ldc_I4_4: code = ILCode.Ldc_I4; operand = 4; break; case ILCode.__Ldc_I4_5: code = ILCode.Ldc_I4; operand = 5; break; case ILCode.__Ldc_I4_6: code = ILCode.Ldc_I4; operand = 6; break; case ILCode.__Ldc_I4_7: code = ILCode.Ldc_I4; operand = 7; break; case ILCode.__Ldc_I4_8: code = ILCode.Ldc_I4; operand = 8; break; case ILCode.__Ldc_I4_S: code = ILCode.Ldc_I4; operand = (int) (sbyte) operand; break; case ILCode.__Br_S: code = ILCode.Br; break; case ILCode.__Brfalse_S: code = ILCode.__Brfalse; break; case ILCode.__Brtrue_S: code = ILCode.Brtrue; break; case ILCode.__Beq_S: code = ILCode.__Beq; break; case ILCode.__Bge_S: code = ILCode.__Bge; break; case ILCode.__Bgt_S: code = ILCode.__Bgt; break; case ILCode.__Ble_S: code = ILCode.__Ble; break; case ILCode.__Blt_S: code = ILCode.__Blt; break; case ILCode.__Bne_Un_S: code = ILCode.__Bne_Un; break; case ILCode.__Bge_Un_S: code = ILCode.__Bge_Un; break; case ILCode.__Bgt_Un_S: code = ILCode.__Bgt_Un; break; case ILCode.__Ble_Un_S: code = ILCode.__Ble_Un; break; case ILCode.__Blt_Un_S: code = ILCode.__Blt_Un; break; case ILCode.__Leave_S: code = ILCode.Leave; break; case ILCode.__Ldind_I: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.IntPtr; break; case ILCode.__Ldind_I1: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.SByte; break; case ILCode.__Ldind_I2: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Int16; break; case ILCode.__Ldind_I4: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Int32; break; case ILCode.__Ldind_I8: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Int64; break; case ILCode.__Ldind_U1: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Byte; break; case ILCode.__Ldind_U2: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.UInt16; break; case ILCode.__Ldind_U4: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.UInt32; break; case ILCode.__Ldind_R4: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Single; break; case ILCode.__Ldind_R8: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Double; break; case ILCode.__Stind_I: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.IntPtr; break; case ILCode.__Stind_I1: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Byte; break; case ILCode.__Stind_I2: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Int16; break; case ILCode.__Stind_I4: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Int32; break; case ILCode.__Stind_I8: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Int64; break; case ILCode.__Stind_R4: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Single; break; case ILCode.__Stind_R8: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Double; break; } }
public OpString(ILCode aCode, int aPosition, int aNextPosition, string aValue, ExceptionHandlingClause aEhc) : base(aCode, aPosition, aNextPosition, aEhc) { Value = aValue; }
public static List <ILCode> ReadILCodes(string[] lines, List <string> locals = null, List <string> args = null) { var list = new List <ILCode>(); //重置堆栈 list.Add(new ILCode() { OpCode = "Reset", Line = "Reset", }); bool switchStart = false; StringBuilder sline = new StringBuilder(); foreach (var xline in lines) { var line = xline; var values = line.Trim().Split(' '); if (values.Length >= 2 && values[1] == "switch") { switchStart = true; sline = new StringBuilder(); } if (switchStart) { sline.Append(line); if (line.EndsWith(")")) { switchStart = false; line = sline.ToString(); values = line.Trim().Split(' '); } else { continue; } } if (values.Length > 4) { for (int i = 5; i < values.Length; i++) { values[4] += " " + values[i]; } } { //如果是字符串 int index = line.IndexOf("\""); int indexe = line.LastIndexOf("\""); if (indexe != -1 && index != -1) { var str = line.Substring(index + 1, indexe - index - 1); var subline = line.Substring(0, index + 1) + "str" + line.Substring(indexe); values = subline.Trim().Split(' '); var indexx = new List <string>(values).IndexOf("\"str\""); values[indexx] = str; } } var illine = new ILCode(); illine.Line = line; if (list.Count > 0 && (list.Last().OpCode == "try" || list.Last().OpCode == "catch" || list.Last().OpCode == "finally")) { list.Last().Arg1 = line; } list.Add(illine); for (int i = 0; i < values.Length; i++) { if (i == 0) { illine.Lable = values[0].Replace(":", ""); } if (i == 1) { illine.OpCode = values[1]; var opcodeValue = illine.OpCode.Split('.'); illine.Op = opcodeValue[0]; if (opcodeValue.Length >= 2) { illine.OpArg0 = opcodeValue[1]; } if (opcodeValue.Length >= 3) { illine.OpArg1 = opcodeValue[2]; } } if (i == 2) { illine.Arg0 = values[2]; } if (i == 3) { illine.Arg1 = values[3]; } if (i == 4) { illine.Arg2 = values[4]; } } } list = FixTryCatchFinally(list); //解析 生成 list = MergeCodes(list, locals, args); return(list); }
public bool SimplifyTernaryOperator(List <ILNode> body, ILBasicBlock head, int pos) { Debug.Assert(body.Contains(head)); ILExpression condExpr; ILLabel trueLabel; ILLabel falseLabel; ILVariable trueLocVar = null; ILExpression trueExpr; ILLabel trueFall; ILVariable falseLocVar = null; ILExpression falseExpr; ILLabel falseFall; object unused; if (head.MatchLastAndBr(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel) && labelGlobalRefCount[trueLabel] == 1 && labelGlobalRefCount[falseLabel] == 1 && ((labelToBasicBlock[trueLabel].MatchSingleAndBr(ILCode.Stloc, out trueLocVar, out trueExpr, out trueFall) && labelToBasicBlock[falseLabel].MatchSingleAndBr(ILCode.Stloc, out falseLocVar, out falseExpr, out falseFall) && trueLocVar == falseLocVar && trueFall == falseFall) || (labelToBasicBlock[trueLabel].MatchSingle(ILCode.Ret, out unused, out trueExpr) && labelToBasicBlock[falseLabel].MatchSingle(ILCode.Ret, out unused, out falseExpr))) && body.Contains(labelToBasicBlock[trueLabel]) && body.Contains(labelToBasicBlock[falseLabel]) ) { bool isStloc = trueLocVar != null; ILCode opCode = isStloc ? ILCode.Stloc : ILCode.Ret; TypeReference retType = isStloc ? trueLocVar.Type : this.context.CurrentMethod.ReturnType; bool retTypeIsBoolean = TypeAnalysis.IsBoolean(retType); int leftBoolVal; int rightBoolVal; ILExpression newExpr; // a ? true:false is equivalent to a // a ? false:true is equivalent to !a // a ? true : b is equivalent to a || b // a ? b : true is equivalent to !a || b // a ? b : false is equivalent to a && b // a ? false : b is equivalent to !a && b if (retTypeIsBoolean && trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal) && falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal) && ((leftBoolVal != 0 && rightBoolVal == 0) || (leftBoolVal == 0 && rightBoolVal != 0)) ) { // It can be expressed as trivilal expression if (leftBoolVal != 0) { newExpr = condExpr; } else { newExpr = new ILExpression(ILCode.LogicNot, null, condExpr); } } else if (retTypeIsBoolean && trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal)) { // It can be expressed as logical expression if (leftBoolVal != 0) { newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, condExpr, falseExpr); } else { newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, new ILExpression(ILCode.LogicNot, null, condExpr), falseExpr); } } else if (retTypeIsBoolean && falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal)) { // It can be expressed as logical expression if (rightBoolVal != 0) { newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, new ILExpression(ILCode.LogicNot, null, condExpr), trueExpr); } else { newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, condExpr, trueExpr); } } else { // Ternary operator tends to create long complicated return statements if (opCode == ILCode.Ret) { return(false); } // Only simplify generated variables if (opCode == ILCode.Stloc && !trueLocVar.IsGenerated) { return(false); } // Create ternary expression newExpr = new ILExpression(ILCode.TernaryOp, null, condExpr, trueExpr, falseExpr); } head.Body.RemoveTail(ILCode.Brtrue, ILCode.Br); head.Body.Add(new ILExpression(opCode, trueLocVar, newExpr)); if (isStloc) { head.Body.Add(new ILExpression(ILCode.Br, trueFall)); } // Remove the old basic blocks body.RemoveOrThrow(labelToBasicBlock[trueLabel]); body.RemoveOrThrow(labelToBasicBlock[falseLabel]); return(true); } return(false); }
ILExpression MakeLeftAssociativeShortCircuit(ILCode code, ILExpression left, ILExpression right) { // Assuming that the inputs are already left associative if (right.Match(code)) { // Find the leftmost logical expression ILExpression current = right; while(current.Arguments[0].Match(code)) current = current.Arguments[0]; current.Arguments[0].AddSelfAndChildrenRecursiveILRanges(current.ILRanges); current.Arguments[0] = new ILExpression(code, null, left, current.Arguments[0]) { InferredType = corLib.Boolean }; return right; } else { return new ILExpression(code, null, left, right) { InferredType = corLib.Boolean }; } }
static bool CanBeRepresentedAsCompoundAssignment(ILCode code) { switch (code) { case ILCode.Add: case ILCode.Add_Ovf: case ILCode.Add_Ovf_Un: case ILCode.Sub: case ILCode.Sub_Ovf: case ILCode.Sub_Ovf_Un: case ILCode.Mul: case ILCode.Mul_Ovf: case ILCode.Mul_Ovf_Un: case ILCode.Div: case ILCode.Div_Un: case ILCode.Rem: case ILCode.Rem_Un: case ILCode.And: case ILCode.Or: case ILCode.Xor: case ILCode.Shl: case ILCode.Shr: case ILCode.Shr_Un: return true; default: return false; } }
public MethodPattern(ILCode code, string method, params Pattern[] arguments) : base(arguments) { this.code = code; this.method = method; }
bool isFlowControlCode(ILCode c) { switch (c) { case ILCode.__Brfalse_S: case ILCode.__Brtrue_S: case ILCode.__Beq_S: case ILCode.__Bge_S: case ILCode.__Bgt_S: case ILCode.__Ble_S: case ILCode.__Blt_S: case ILCode.__Bne_Un_S: case ILCode.__Bge_Un_S: case ILCode.__Bgt_Un_S: case ILCode.__Ble_Un_S: case ILCode.__Blt_Un_S: case ILCode.__Brfalse: case ILCode.Brtrue: case ILCode.__Beq: case ILCode.__Bge: case ILCode.__Bgt: case ILCode.__Ble: case ILCode.__Blt: case ILCode.__Bne_Un: case ILCode.__Bge_Un: case ILCode.__Bgt_Un: case ILCode.__Ble_Un: case ILCode.__Blt_Un: return true; default: break; } return false; }
public static string GetName(this ILCode code) { return(code.ToString().ToLowerInvariant().TrimStart('_').Replace('_', '.')); }
static bool IsStoreToArray(ILCode code) { switch (code) { case ILCode.Stelem_Any: case ILCode.Stelem_I: case ILCode.Stelem_I1: case ILCode.Stelem_I2: case ILCode.Stelem_I4: case ILCode.Stelem_I8: case ILCode.Stelem_R4: case ILCode.Stelem_R8: case ILCode.Stelem_Ref: return true; default: return false; } }
public static void ExpandMacro(ref ILCode code, ref object operand, MethodBody methodBody) { switch (code) { case ILCode.__Ldarg_0: code = ILCode.__Ldarg; operand = methodBody.GetParameter(0); break; case ILCode.__Ldarg_1: code = ILCode.__Ldarg; operand = methodBody.GetParameter(1); break; case ILCode.__Ldarg_2: code = ILCode.__Ldarg; operand = methodBody.GetParameter(2); break; case ILCode.__Ldarg_3: code = ILCode.__Ldarg; operand = methodBody.GetParameter(3); break; case ILCode.__Ldloc_0: code = ILCode.Ldloc; operand = methodBody.Variables[0]; break; case ILCode.__Ldloc_1: code = ILCode.Ldloc; operand = methodBody.Variables[1]; break; case ILCode.__Ldloc_2: code = ILCode.Ldloc; operand = methodBody.Variables[2]; break; case ILCode.__Ldloc_3: code = ILCode.Ldloc; operand = methodBody.Variables[3]; break; case ILCode.__Stloc_0: code = ILCode.Stloc; operand = methodBody.Variables[0]; break; case ILCode.__Stloc_1: code = ILCode.Stloc; operand = methodBody.Variables[1]; break; case ILCode.__Stloc_2: code = ILCode.Stloc; operand = methodBody.Variables[2]; break; case ILCode.__Stloc_3: code = ILCode.Stloc; operand = methodBody.Variables[3]; break; case ILCode.__Ldarg_S: code = ILCode.__Ldarg; break; case ILCode.__Ldarga_S: code = ILCode.__Ldarga; break; case ILCode.__Starg_S: code = ILCode.__Starg; break; case ILCode.__Ldloc_S: code = ILCode.Ldloc; break; case ILCode.__Ldloca_S: code = ILCode.Ldloca; break; case ILCode.__Stloc_S: code = ILCode.Stloc; break; case ILCode.__Ldc_I4_M1: code = ILCode.Ldc_I4; operand = -1; break; case ILCode.__Ldc_I4_0: code = ILCode.Ldc_I4; operand = 0; break; case ILCode.__Ldc_I4_1: code = ILCode.Ldc_I4; operand = 1; break; case ILCode.__Ldc_I4_2: code = ILCode.Ldc_I4; operand = 2; break; case ILCode.__Ldc_I4_3: code = ILCode.Ldc_I4; operand = 3; break; case ILCode.__Ldc_I4_4: code = ILCode.Ldc_I4; operand = 4; break; case ILCode.__Ldc_I4_5: code = ILCode.Ldc_I4; operand = 5; break; case ILCode.__Ldc_I4_6: code = ILCode.Ldc_I4; operand = 6; break; case ILCode.__Ldc_I4_7: code = ILCode.Ldc_I4; operand = 7; break; case ILCode.__Ldc_I4_8: code = ILCode.Ldc_I4; operand = 8; break; case ILCode.__Ldc_I4_S: code = ILCode.Ldc_I4; operand = (int)(sbyte)operand; break; case ILCode.__Br_S: code = ILCode.Br; break; case ILCode.__Brfalse_S: code = ILCode.__Brfalse; break; case ILCode.__Brtrue_S: code = ILCode.Brtrue; break; case ILCode.__Beq_S: code = ILCode.__Beq; break; case ILCode.__Bge_S: code = ILCode.__Bge; break; case ILCode.__Bgt_S: code = ILCode.__Bgt; break; case ILCode.__Ble_S: code = ILCode.__Ble; break; case ILCode.__Blt_S: code = ILCode.__Blt; break; case ILCode.__Bne_Un_S: code = ILCode.__Bne_Un; break; case ILCode.__Bge_Un_S: code = ILCode.__Bge_Un; break; case ILCode.__Bgt_Un_S: code = ILCode.__Bgt_Un; break; case ILCode.__Ble_Un_S: code = ILCode.__Ble_Un; break; case ILCode.__Blt_Un_S: code = ILCode.__Blt_Un; break; case ILCode.__Leave_S: code = ILCode.Leave; break; case ILCode.__Ldind_I: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.IntPtr; break; case ILCode.__Ldind_I1: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.SByte; break; case ILCode.__Ldind_I2: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Int16; break; case ILCode.__Ldind_I4: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Int32; break; case ILCode.__Ldind_I8: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Int64; break; case ILCode.__Ldind_U1: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Byte; break; case ILCode.__Ldind_U2: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.UInt16; break; case ILCode.__Ldind_U4: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.UInt32; break; case ILCode.__Ldind_R4: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Single; break; case ILCode.__Ldind_R8: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Double; break; case ILCode.__Stind_I: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.IntPtr; break; case ILCode.__Stind_I1: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Byte; break; case ILCode.__Stind_I2: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Int16; break; case ILCode.__Stind_I4: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Int32; break; case ILCode.__Stind_I8: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Int64; break; case ILCode.__Stind_R4: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Single; break; case ILCode.__Stind_R8: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Double; break; } }
public bool SimplifyCustomShortCircuit(List <ILNode> body, ILBasicBlock head, int pos) { Debug.Assert(body.Contains(head)); // --- looking for the following pattern --- // stloc(targetVar, leftVar) // brtrue(exitLabel, call(op_False, leftVar) // br(followingBlock) // // FollowingBlock: // stloc(targetVar, call(op_BitwiseAnd, leftVar, rightExpression)) // br(exitLabel) // --- if (head.Body.Count < 3) { return(false); } // looking for: // stloc(targetVar, leftVar) ILVariable targetVar; ILExpression targetVarInitExpr; if (!head.Body[head.Body.Count - 3].Match(ILCode.Stloc, out targetVar, out targetVarInitExpr)) { return(false); } ILVariable leftVar; if (!targetVarInitExpr.Match(ILCode.Ldloc, out leftVar)) { return(false); } // looking for: // brtrue(exitLabel, call(op_False, leftVar) // br(followingBlock) ILExpression callExpr; ILLabel exitLabel; ILLabel followingBlock; if (!head.MatchLastAndBr(ILCode.Brtrue, out exitLabel, out callExpr, out followingBlock)) { return(false); } if (labelGlobalRefCount[followingBlock] > 1) { return(false); } IMethod opFalse; ILExpression opFalseArg; if (!callExpr.Match(ILCode.Call, out opFalse, out opFalseArg)) { return(false); } // ignore operators other than op_False and op_True if (opFalse.Name != "op_False" && opFalse.Name != "op_True") { return(false); } if (!opFalseArg.MatchLdloc(leftVar)) { return(false); } ILBasicBlock followingBasicBlock = labelToBasicBlock[followingBlock]; // FollowingBlock: // stloc(targetVar, call(op_BitwiseAnd, leftVar, rightExpression)) // br(exitLabel) ILVariable _targetVar; ILExpression opBitwiseCallExpr; ILLabel _exitLabel; if (!followingBasicBlock.MatchSingleAndBr(ILCode.Stloc, out _targetVar, out opBitwiseCallExpr, out _exitLabel)) { return(false); } if (_targetVar != targetVar || exitLabel != _exitLabel) { return(false); } IMethod opBitwise; ILExpression leftVarExpression; ILExpression rightExpression; if (!opBitwiseCallExpr.Match(ILCode.Call, out opBitwise, out leftVarExpression, out rightExpression)) { return(false); } if (!leftVarExpression.MatchLdloc(leftVar)) { return(false); } // ignore operators other than op_BitwiseAnd and op_BitwiseOr if (opBitwise.Name != "op_BitwiseAnd" && opBitwise.Name != "op_BitwiseOr") { return(false); } // insert: // stloc(targetVar, LogicAnd(C::op_BitwiseAnd, leftVar, rightExpression) // br(exitLabel) ILCode op = opBitwise.Name == "op_BitwiseAnd" ? ILCode.LogicAnd : ILCode.LogicOr; if (op == ILCode.LogicAnd && opFalse.Name != "op_False") { return(false); } if (op == ILCode.LogicOr && opFalse.Name != "op_True") { return(false); } ILExpression shortCircuitExpr = MakeLeftAssociativeShortCircuit(op, opFalseArg, rightExpression); shortCircuitExpr.Operand = opBitwise; var tail = head.Body.RemoveTail(ILCode.Stloc, ILCode.Brtrue, ILCode.Br); //TODO: Keep tail's ILRanges //TODO: Keep ILRanges of other things that are removed by this method head.Body.Add(new ILExpression(ILCode.Stloc, targetVar, shortCircuitExpr)); head.Body.Add(new ILExpression(ILCode.Br, exitLabel)); body.Remove(followingBasicBlock); return(true); }
List <ByteCode> StackAnalysis(MethodDefinition methodDef) { Dictionary <Instruction, ByteCode> instrToByteCode = new Dictionary <Instruction, ByteCode>(); // Create temporary structure for the stack analysis List <ByteCode> body = new List <ByteCode>(methodDef.Body.Instructions.Count); List <Instruction> prefixes = null; foreach (Instruction inst in methodDef.Body.Instructions) { if (inst.OpCode.OpCodeType == OpCodeType.Prefix) { if (prefixes == null) { prefixes = new List <Instruction>(1); } prefixes.Add(inst); continue; } ILCode code = (ILCode)inst.OpCode.Code; object operand = inst.Operand; ILCodeUtil.ExpandMacro(ref code, ref operand, methodDef.Body); ByteCode byteCode = new ByteCode() { Offset = inst.Offset, EndOffset = inst.Next != null ? inst.Next.Offset : methodDef.Body.CodeSize, Code = code, Operand = operand, PopCount = inst.GetPopDelta(methodDef), PushCount = inst.GetPushDelta() }; if (prefixes != null) { instrToByteCode[prefixes[0]] = byteCode; byteCode.Offset = prefixes[0].Offset; byteCode.Prefixes = prefixes.ToArray(); prefixes = null; } else { instrToByteCode[inst] = byteCode; } body.Add(byteCode); } for (int i = 0; i < body.Count - 1; i++) { body[i].Next = body[i + 1]; } Stack <ByteCode> agenda = new Stack <ByteCode>(); int varCount = methodDef.Body.Variables.Count; var exceptionHandlerStarts = new HashSet <ByteCode>(methodDef.Body.ExceptionHandlers.Select(eh => instrToByteCode[eh.HandlerStart])); // Add known states if (methodDef.Body.HasExceptionHandlers) { foreach (ExceptionHandler ex in methodDef.Body.ExceptionHandlers) { ByteCode handlerStart = instrToByteCode[ex.HandlerStart]; handlerStart.StackBefore = new List <StackSlot>(); handlerStart.VariablesBefore = VariableSlot.MakeFullState(varCount); if (ex.HandlerType == ExceptionHandlerType.Catch || ex.HandlerType == ExceptionHandlerType.Filter) { // Catch and Filter handlers start with the exeption on the stack ByteCode ldexception = new ByteCode() { Code = ILCode.Ldexception, Operand = ex.CatchType, PopCount = 0, PushCount = 1 }; ldexceptions[ex] = ldexception; handlerStart.StackBefore.Add(new StackSlot(ldexception)); } agenda.Push(handlerStart); if (ex.HandlerType == ExceptionHandlerType.Filter) { ByteCode filterStart = instrToByteCode[ex.FilterStart]; filterStart.StackBefore = new List <StackSlot>(); filterStart.VariablesBefore = VariableSlot.MakeFullState(varCount); ByteCode ldexception = new ByteCode() { Code = ILCode.Ldexception, Operand = ex.CatchType, PopCount = 0, PushCount = 1 }; // TODO: ldexceptions[ex] = ldexception; filterStart.StackBefore.Add(new StackSlot(ldexception)); agenda.Push(filterStart); } } } body[0].StackBefore = new List <StackSlot>(); body[0].VariablesBefore = VariableSlot.MakeEmptyState(varCount); agenda.Push(body[0]); // Process agenda while (agenda.Count > 0) { ByteCode byteCode = agenda.Pop(); // Calculate new stack List <StackSlot> newStack = StackSlot.CloneStack(byteCode.StackBefore, byteCode.PopCount); for (int i = 0; i < byteCode.PushCount; i++) { newStack.Add(new StackSlot(byteCode)); } // Calculate new variable state VariableSlot[] newVariableState = VariableSlot.CloneVariableState(byteCode.VariablesBefore); if (byteCode.Code == ILCode.Stloc) { int varIndex = ((VariableReference)byteCode.Operand).Index; newVariableState[varIndex] = new VariableSlot(byteCode); } // After the leave, finally block might have touched the variables if (byteCode.Code == ILCode.Leave) { newVariableState = VariableSlot.MakeFullState(varCount); } // Find all successors List <ByteCode> branchTargets = new List <ByteCode>(); if (!byteCode.Code.IsUnconditionalControlFlow()) { if (exceptionHandlerStarts.Contains(byteCode.Next)) { // Do not fall though down to exception handler // It is invalid IL as per ECMA-335 §12.4.2.8.1, but some obfuscators produce it } else { branchTargets.Add(byteCode.Next); } } if (byteCode.Operand is Instruction[]) { foreach (Instruction inst in (Instruction[])byteCode.Operand) { ByteCode target = instrToByteCode[inst]; branchTargets.Add(target); // The target of a branch must have label if (target.Label == null) { target.Label = new ILLabel() { Name = target.Name }; } } } else if (byteCode.Operand is Instruction) { ByteCode target = instrToByteCode[(Instruction)byteCode.Operand]; branchTargets.Add(target); // The target of a branch must have label if (target.Label == null) { target.Label = new ILLabel() { Name = target.Name }; } } // Apply the state to successors foreach (ByteCode branchTarget in branchTargets) { if (branchTarget.StackBefore == null && branchTarget.VariablesBefore == null) { if (branchTargets.Count == 1) { branchTarget.StackBefore = newStack; branchTarget.VariablesBefore = newVariableState; } else { // Do not share data for several bytecodes branchTarget.StackBefore = StackSlot.CloneStack(newStack, 0); branchTarget.VariablesBefore = VariableSlot.CloneVariableState(newVariableState); } agenda.Push(branchTarget); } else { if (branchTarget.StackBefore.Count != newStack.Count) { throw new Exception("Inconsistent stack size at " + byteCode.Name); } // Be careful not to change our new data - it might be reused for several branch targets. // In general, be careful that two bytecodes never share data structures. bool modified = false; // Merge stacks - modify the target for (int i = 0; i < newStack.Count; i++) { ByteCode[] oldPushedBy = branchTarget.StackBefore[i].PushedBy; ByteCode[] newPushedBy = oldPushedBy.Union(newStack[i].PushedBy); if (newPushedBy.Length > oldPushedBy.Length) { branchTarget.StackBefore[i] = new StackSlot(newPushedBy, null); modified = true; } } // Merge variables - modify the target for (int i = 0; i < newVariableState.Length; i++) { VariableSlot oldSlot = branchTarget.VariablesBefore[i]; VariableSlot newSlot = newVariableState[i]; // All can not be unioned further if (!oldSlot.StoredByAll) { if (newSlot.StoredByAll) { branchTarget.VariablesBefore[i] = newSlot; modified = true; } else { ByteCode[] oldStoredBy = oldSlot.StoredBy; ByteCode[] newStoredBy = oldStoredBy.Union(newSlot.StoredBy); if (newStoredBy.Length > oldStoredBy.Length) { branchTarget.VariablesBefore[i] = new VariableSlot(newStoredBy, false); modified = true; } } } } if (modified) { agenda.Push(branchTarget); } } } } // Occasionally the compilers or obfuscators generate unreachable code (which migt be intentonally invalid) // I belive it is safe to just remove it body.RemoveAll(b => b.StackBefore == null); // Genertate temporary variables to replace stack foreach (ByteCode byteCode in body) { int argIdx = 0; int popCount = byteCode.PopCount ?? byteCode.StackBefore.Count; for (int i = byteCode.StackBefore.Count - popCount; i < byteCode.StackBefore.Count; i++) { ILVariable tmpVar = new ILVariable() { Name = string.Format("arg_{0:X2}_{1}", byteCode.Offset, argIdx), IsGenerated = true }; byteCode.StackBefore[i] = new StackSlot(byteCode.StackBefore[i].PushedBy, tmpVar); foreach (ByteCode pushedBy in byteCode.StackBefore[i].PushedBy) { if (pushedBy.StoreTo == null) { pushedBy.StoreTo = new List <ILVariable>(1); } pushedBy.StoreTo.Add(tmpVar); } argIdx++; } } // Try to use single temporary variable insted of several if possilbe (especially useful for dup) // This has to be done after all temporary variables are assigned so we know about all loads foreach (ByteCode byteCode in body) { if (byteCode.StoreTo != null && byteCode.StoreTo.Count > 1) { var locVars = byteCode.StoreTo; // For each of the variables, find the location where it is loaded - there should be preciesly one var loadedBy = locVars.Select(locVar => body.SelectMany(bc => bc.StackBefore).Single(s => s.LoadFrom == locVar)).ToList(); // We now know that all the variables have a single load, // Let's make sure that they have also a single store - us if (loadedBy.All(slot => slot.PushedBy.Length == 1 && slot.PushedBy[0] == byteCode)) { // Great - we can reduce everything into single variable ILVariable tmpVar = new ILVariable() { Name = string.Format("expr_{0:X2}", byteCode.Offset), IsGenerated = true }; byteCode.StoreTo = new List <ILVariable>() { tmpVar }; foreach (ByteCode bc in body) { for (int i = 0; i < bc.StackBefore.Count; i++) { // Is it one of the variable to be merged? if (locVars.Contains(bc.StackBefore[i].LoadFrom)) { // Replace with the new temp variable bc.StackBefore[i] = new StackSlot(bc.StackBefore[i].PushedBy, tmpVar); } } } } } } // Split and convert the normal local variables ConvertLocalVariables(body); // Convert branch targets to labels foreach (ByteCode byteCode in body) { if (byteCode.Operand is Instruction[]) { List <ILLabel> newOperand = new List <ILLabel>(); foreach (Instruction target in (Instruction[])byteCode.Operand) { newOperand.Add(instrToByteCode[target].Label); } byteCode.Operand = newOperand.ToArray(); } else if (byteCode.Operand is Instruction) { byteCode.Operand = instrToByteCode[(Instruction)byteCode.Operand].Label; } } // Convert parameters to ILVariables ConvertParameters(body); return(body); }
public bool SimplifyTernaryOperator(List <ILNode> body, ILBasicBlock head, int pos) { Debug.Assert(body.Contains(head)); ILExpression condExpr; ILLabel trueLabel; ILLabel falseLabel; ILVariable trueLocVar = null; ILExpression trueExpr; ILLabel trueFall; ILVariable falseLocVar = null; ILExpression falseExpr; ILLabel falseFall; object unused; if (head.MatchLastAndBr(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel) && labelGlobalRefCount[trueLabel] == 1 && labelGlobalRefCount[falseLabel] == 1 && ((labelToBasicBlock[trueLabel].MatchSingleAndBr(ILCode.Stloc, out trueLocVar, out trueExpr, out trueFall) && labelToBasicBlock[falseLabel].MatchSingleAndBr(ILCode.Stloc, out falseLocVar, out falseExpr, out falseFall) && trueLocVar == falseLocVar && trueFall == falseFall) || (labelToBasicBlock[trueLabel].MatchSingle(ILCode.Ret, out unused, out trueExpr) && labelToBasicBlock[falseLabel].MatchSingle(ILCode.Ret, out unused, out falseExpr))) && body.Contains(labelToBasicBlock[trueLabel]) && body.Contains(labelToBasicBlock[falseLabel]) ) { bool isStloc = trueLocVar != null; ILCode opCode = isStloc ? ILCode.Stloc : ILCode.Ret; TypeSig retType = isStloc ? trueLocVar.Type : this.context.CurrentMethod.ReturnType; bool retTypeIsBoolean = retType.GetElementType() == ElementType.Boolean; int leftBoolVal; int rightBoolVal; ILExpression newExpr; // a ? true:false is equivalent to a // a ? false:true is equivalent to !a // a ? true : b is equivalent to a || b // a ? b : true is equivalent to !a || b // a ? b : false is equivalent to a && b // a ? false : b is equivalent to !a && b if (retTypeIsBoolean && trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal) && falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal) && ((leftBoolVal != 0 && rightBoolVal == 0) || (leftBoolVal == 0 && rightBoolVal != 0)) ) { // It can be expressed as trivilal expression if (leftBoolVal != 0) { newExpr = condExpr; } else { newExpr = new ILExpression(ILCode.LogicNot, null, condExpr) { InferredType = corLib.Boolean }; } } else if ((retTypeIsBoolean || falseExpr.InferredType.GetElementType() == ElementType.Boolean) && trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal) && (leftBoolVal == 0 || leftBoolVal == 1)) { // It can be expressed as logical expression if (leftBoolVal != 0) { newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, condExpr, falseExpr); } else { newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, new ILExpression(ILCode.LogicNot, null, condExpr), falseExpr); } } else if ((retTypeIsBoolean || trueExpr.InferredType.GetElementType() == ElementType.Boolean) && falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal) && (rightBoolVal == 0 || rightBoolVal == 1)) { // It can be expressed as logical expression if (rightBoolVal != 0) { newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, new ILExpression(ILCode.LogicNot, null, condExpr), trueExpr); } else { newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, condExpr, trueExpr); } } else { // Ternary operator tends to create long complicated return statements if (opCode == ILCode.Ret) { return(false); } // Only simplify generated variables if (opCode == ILCode.Stloc && !trueLocVar.GeneratedByDecompiler) { return(false); } // Create ternary expression newExpr = new ILExpression(ILCode.TernaryOp, null, condExpr, trueExpr, falseExpr); } var tail = head.Body.RemoveTail(ILCode.Brtrue, ILCode.Br); var listNodes = new List <ILNode>(); var newExprNodes = newExpr.GetSelfAndChildrenRecursive <ILNode>(listNodes).ToArray(); foreach (var node in labelToBasicBlock[trueLabel].GetSelfAndChildrenRecursive <ILNode>(listNodes).Except(newExprNodes)) { newExpr.ILRanges.AddRange(node.AllILRanges); } foreach (var node in labelToBasicBlock[falseLabel].GetSelfAndChildrenRecursive <ILNode>(listNodes).Except(newExprNodes)) { newExpr.ILRanges.AddRange(node.AllILRanges); } newExpr.ILRanges.AddRange(tail[0].ILRanges); tail[1].AddSelfAndChildrenRecursiveILRanges(newExpr.ILRanges); head.Body.Add(new ILExpression(opCode, trueLocVar, newExpr)); if (isStloc) { head.Body.Add(new ILExpression(ILCode.Br, trueFall)); } // Remove the old basic blocks body.RemoveOrThrow(labelToBasicBlock[trueLabel]); body.RemoveOrThrow(labelToBasicBlock[falseLabel]); return(true); } return(false); }
public ILExpressionPrefix(ILCode code, object operand = null) { this.Code = code; this.Operand = operand; }
public static void ExpandMacro(ref ILCode code, ref object operand, MethodDef method) { var methodBody = method.Body; switch (code) { case ILCode.Ldarg_0: code = ILCode.Ldarg; operand = method.Parameters[0]; break; case ILCode.Ldarg_1: code = ILCode.Ldarg; operand = method.Parameters[1]; break; case ILCode.Ldarg_2: code = ILCode.Ldarg; operand = method.Parameters[2]; break; case ILCode.Ldarg_3: code = ILCode.Ldarg; operand = method.Parameters[3]; break; case ILCode.Ldloc_0: code = ILCode.Ldloc; operand = methodBody.Variables[0]; break; case ILCode.Ldloc_1: code = ILCode.Ldloc; operand = methodBody.Variables[1]; break; case ILCode.Ldloc_2: code = ILCode.Ldloc; operand = methodBody.Variables[2]; break; case ILCode.Ldloc_3: code = ILCode.Ldloc; operand = methodBody.Variables[3]; break; case ILCode.Stloc_0: code = ILCode.Stloc; operand = methodBody.Variables[0]; break; case ILCode.Stloc_1: code = ILCode.Stloc; operand = methodBody.Variables[1]; break; case ILCode.Stloc_2: code = ILCode.Stloc; operand = methodBody.Variables[2]; break; case ILCode.Stloc_3: code = ILCode.Stloc; operand = methodBody.Variables[3]; break; case ILCode.Ldarg_S: code = ILCode.Ldarg; break; case ILCode.Ldarga_S: code = ILCode.Ldarga; break; case ILCode.Starg_S: code = ILCode.Starg; break; case ILCode.Ldloc_S: code = ILCode.Ldloc; break; case ILCode.Ldloca_S: code = ILCode.Ldloca; break; case ILCode.Stloc_S: code = ILCode.Stloc; break; case ILCode.Ldc_I4_M1: code = ILCode.Ldc_I4; operand = -1; break; case ILCode.Ldc_I4_0: code = ILCode.Ldc_I4; operand = 0; break; case ILCode.Ldc_I4_1: code = ILCode.Ldc_I4; operand = 1; break; case ILCode.Ldc_I4_2: code = ILCode.Ldc_I4; operand = 2; break; case ILCode.Ldc_I4_3: code = ILCode.Ldc_I4; operand = 3; break; case ILCode.Ldc_I4_4: code = ILCode.Ldc_I4; operand = 4; break; case ILCode.Ldc_I4_5: code = ILCode.Ldc_I4; operand = 5; break; case ILCode.Ldc_I4_6: code = ILCode.Ldc_I4; operand = 6; break; case ILCode.Ldc_I4_7: code = ILCode.Ldc_I4; operand = 7; break; case ILCode.Ldc_I4_8: code = ILCode.Ldc_I4; operand = 8; break; case ILCode.Ldc_I4_S: code = ILCode.Ldc_I4; operand = (int) (sbyte) operand; break; case ILCode.Br_S: code = ILCode.Br; break; case ILCode.Brfalse_S: code = ILCode.Brfalse; break; case ILCode.Brtrue_S: code = ILCode.Brtrue; break; case ILCode.Beq_S: code = ILCode.Beq; break; case ILCode.Bge_S: code = ILCode.Bge; break; case ILCode.Bgt_S: code = ILCode.Bgt; break; case ILCode.Ble_S: code = ILCode.Ble; break; case ILCode.Blt_S: code = ILCode.Blt; break; case ILCode.Bne_Un_S: code = ILCode.Bne_Un; break; case ILCode.Bge_Un_S: code = ILCode.Bge_Un; break; case ILCode.Bgt_Un_S: code = ILCode.Bgt_Un; break; case ILCode.Ble_Un_S: code = ILCode.Ble_Un; break; case ILCode.Blt_Un_S: code = ILCode.Blt_Un; break; case ILCode.Leave_S: code = ILCode.Leave; break; case ILCode.Ldind_I: code = ILCode.Ldobj; operand = method.Module.CorLibTypes.IntPtr.TypeDefOrRef; break; case ILCode.Ldind_I1: code = ILCode.Ldobj; operand = method.Module.CorLibTypes.SByte.TypeDefOrRef; break; case ILCode.Ldind_I2: code = ILCode.Ldobj; operand = method.Module.CorLibTypes.Int16.TypeDefOrRef; break; case ILCode.Ldind_I4: code = ILCode.Ldobj; operand = method.Module.CorLibTypes.Int32.TypeDefOrRef; break; case ILCode.Ldind_I8: code = ILCode.Ldobj; operand = method.Module.CorLibTypes.Int64.TypeDefOrRef; break; case ILCode.Ldind_U1: code = ILCode.Ldobj; operand = method.Module.CorLibTypes.Byte.TypeDefOrRef; break; case ILCode.Ldind_U2: code = ILCode.Ldobj; operand = method.Module.CorLibTypes.UInt16.TypeDefOrRef; break; case ILCode.Ldind_U4: code = ILCode.Ldobj; operand = method.Module.CorLibTypes.UInt32.TypeDefOrRef; break; case ILCode.Ldind_R4: code = ILCode.Ldobj; operand = method.Module.CorLibTypes.Single.TypeDefOrRef; break; case ILCode.Ldind_R8: code = ILCode.Ldobj; operand = method.Module.CorLibTypes.Double.TypeDefOrRef; break; case ILCode.Stind_I: code = ILCode.Stobj; operand = method.Module.CorLibTypes.IntPtr.TypeDefOrRef; break; case ILCode.Stind_I1: code = ILCode.Stobj; operand = method.Module.CorLibTypes.Byte.TypeDefOrRef; break; case ILCode.Stind_I2: code = ILCode.Stobj; operand = method.Module.CorLibTypes.Int16.TypeDefOrRef; break; case ILCode.Stind_I4: code = ILCode.Stobj; operand = method.Module.CorLibTypes.Int32.TypeDefOrRef; break; case ILCode.Stind_I8: code = ILCode.Stobj; operand = method.Module.CorLibTypes.Int64.TypeDefOrRef; break; case ILCode.Stind_R4: code = ILCode.Stobj; operand = method.Module.CorLibTypes.Single.TypeDefOrRef; break; case ILCode.Stind_R8: code = ILCode.Stobj; operand = method.Module.CorLibTypes.Double.TypeDefOrRef; break; } }
public ILInstructionPattern(ILCode opCode, object operand, params ILExpressionPattern[] arguments) : this(new ILOpCodePattern(opCode), new ILOperandPattern(operand), arguments) { }