public void ModifyAssembly(string fileName) { MethodInfo writeLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }); // ReaderParameters { ReadWrite = true } is necessary to later write the file using (ModuleDefinition module = ModuleDefinition.ReadModule(fileName, new ReaderParameters { ReadWrite = true })) { // Modify the assembly TypeDefinition[] types = module.Types.ToArray(); MethodReference methodReference = module.ImportReference(writeLineMethod); foreach (var type in types) { foreach (MethodDefinition methodToChange in type.Methods) { string sentence = String.Concat("Code added in ", methodToChange.Name); Mono.Cecil.Cil.ILProcessor ilProcessor = methodToChange.Body.GetILProcessor(); Mono.Cecil.Cil.Instruction loadStringInstruction = ilProcessor.Create(OpCodes.Ldstr, sentence); Mono.Cecil.Cil.Instruction callInstruction = ilProcessor.Create(OpCodes.Call, methodReference); Mono.Cecil.Cil.Instruction methodFirstInstruction = methodToChange.Body.Instructions[0]; ilProcessor.InsertBefore(methodFirstInstruction, loadStringInstruction); ilProcessor.InsertAfter(loadStringInstruction, callInstruction); } } module.Write(); // Write to the same file that was used to open the file } }
public static int[] BranchTargets (Instruction instruction) { if (instruction == null) throw new ArgumentNullException ("instruction"); int[] result = null; switch (instruction.OpCode.OperandType) { case OperandType.InlineSwitch: Instruction[] targets = (Instruction[])instruction.Operand; result = new int[targets.Length]; int i = 0; foreach (Instruction target in targets) { result [i] = target.Offset; i++; } break; case OperandType.InlineBrTarget: result = new int[1]; result [0] = ((Instruction)instruction.Operand).Offset; break; case OperandType.ShortInlineBrTarget: result = new int[1]; result [0] = ((Instruction)instruction.Operand).Offset; break; } return result; }
public static void Instance(JavaCode code, CodeLocals locals, Mono.Cecil.Cil.Instruction cilInst) { if (cilInst.Operand is TypeReference cilType && cilInst.Next != null) { var stackTop = (CilType)code.StackMap.PopStack(CilMain.Where); if (!stackTop.IsReference) { throw new InvalidProgramException(); // top of stack is a primitive type } var castType = (CilType)CilType.From(cilType); JavaType castClass = CilType.From(cilType).AsWritableClass; if (GenericUtil.ShouldCallGenericCast(stackTop, castType) || castType.IsGenericParameter) { code.StackMap.PushStack(stackTop); // casting to a generic type is done via GenericType.TestCast GenericUtil.CastToGenericType(cilType, 0, code); code.StackMap.PopStack(CilMain.Where); // stackTop if (!castType.IsGenericParameter) { code.NewInstruction(0xC0 /* checkcast */, castClass, null); } code.StackMap.PushStack(castClass); } else if (CodeArrays.CheckCast(castType, false, code)) { // if casting to Object[], ValueType[], to an array of // interface type, or to an array of a generic parameter, // then CodeArrays.CheckCast already generated a call to // system.Array.CheckCast in baselib, and we are done here if (!castType.IsGenericParameter) { // avoid cast since T[] might be a primitive array code.NewInstruction(0xC0 /* checkcast */, castClass, null); } code.StackMap.PushStack(castClass); } // // the cil 'isinst' casts the operand to the requested class, // but the jvm 'instanceof' only returns zero or one. so we // also use 'checkcast' to get the jvm to acknowledge the cast // // however, if the cil 'isinst' is immediately followed by // 'brtrue' or 'brfalse' then we don't have to actually cast // else if (!TestForBranch(code, castClass, cilInst.Next)) { ushort nextLabel = (ushort)cilInst.Next.Offset; int localIndex = locals.GetTempIndex(stackTop); TestAndCast(code, castClass, stackTop, nextLabel, localIndex); locals.FreeTempIndex(localIndex); } }
internal static void AssertInstruction(Instruction actual, OpCode opCode, MemberReference expectedCtor) { Assert.AreEqual(opCode, actual.OpCode); MethodReference actualCtor = (MethodReference)actual.Operand; Assert.AreEqual(expectedCtor.DeclaringType.Name, actualCtor.DeclaringType.Name, opCode.ToString()); Assert.AreEqual(expectedCtor, actualCtor.Resolve(), opCode.ToString()); }
private static bool IsMethodCallOnList(Instruction candidate) { if (candidate.OpCode != OpCodes.Call && candidate.OpCode != OpCodes.Callvirt) return false; MethodDefinition callee = ((MethodReference)candidate.Operand).Resolve(); return callee.DeclaringType.Resolve().FullName == callee.DeclaringType.Module.Import(typeof(List<>)).FullName; }
public override void VisitInstruction(Instruction instr) { /* if (instr.Operand is TypeReference) { _modelCreator.UseType(((TypeReference)instr.Operand).ToTypeKey()); } if (instr.Operand is FieldReference) { TypeKey typeKey = ((FieldReference)instr.Operand).FieldType.ToTypeKey(); if (typeKey != null) { _modelCreator.UseType(typeKey); } } */ if (instr.Operand is MethodReference) { _modelCreator.UseType(((MethodReference)instr.Operand).DeclaringType.ToTypeKey()); _modelCreator.UseMethod(((MethodReference)instr.Operand).ToMethodKey()); } if (instr.Operand is PropertyReference) { _modelCreator.UseType(((PropertyReference)instr.Operand).DeclaringType.ToTypeKey()); _modelCreator.UseProperty(((PropertyReference)instr.Operand).ToPropertyKey()); } }
public InvokeMethodReplacement(Instruction executeOriginalInstructions, VariableDefinition methodReplacementProvider, VariableDefinition classMethodReplacementProvider, VariableDefinition invocationInfo) { _executeOriginalInstructions = executeOriginalInstructions; _methodReplacementProvider = methodReplacementProvider; _classMethodReplacementProvider = classMethodReplacementProvider; _invocationInfo = invocationInfo; }
public CompiledString(MethodDefinition method, Instruction instruction) { Method = method; Instruction = instruction; OriginalValue = Value; }
/// <summary> /// Gets the instructions that generate the arguments for the call in the given instructions. /// </summary> public static Instruction[] GetCallArguments(this Instruction call, ILSequence sequence, bool includeThis) { var method = (MethodReference)call.Operand; var count = method.Parameters.Count; if (includeThis && method.HasThis) { count++; } var result = new Instruction[count]; var current = call; var height = count; for (int i = count - 1; i >= 0; i--) { // Look for the starting instruction where stack height is i while (result[i] == null) { var prevIndex = sequence.IndexOf(current); var prev = (prevIndex >= 1) ? sequence[prevIndex - 1] : null; if (prev == null) throw new ArgumentException(string.Format("Cannot find arguments for call to {0}", method)); height -= prev.GetPushDelta(); if (height == i) result[i] = prev; height += prev.GetPopDelta(0, true); current = prev; } } return result; }
protected override int _Pushes(Instruction i) { MethodReference method = (MethodReference)i.Operand; if (method.ReturnType == null) return 0; return 1; }
private static int CountElementsInTheStack (MethodDefinition method, Instruction start, Instruction end) { Instruction current = start; int counter = 0; bool newarrDetected = false; while (end != current) { if (newarrDetected) { //Count only the stelem instructions if //there are a newarr instruction. if (current.OpCode == OpCodes.Stelem_Ref) counter++; } else { //Count with the stack counter += current.GetPushCount (); counter -= current.GetPopCount (method); } //If there are a newarr we need an special //behaviour if (current.OpCode == OpCodes.Newarr) { newarrDetected = true; counter = 0; } current = current.Next; } return counter; }
public static void InsertFront(this ILProcessor processor, Instruction instr) { if (processor.Body.Instructions.Count <= 0) processor.Append(instr); else processor.InsertBefore(processor.Body.Instructions[0], instr); }
protected override int _Pops(Instruction i, int stackSize) { // Check i.Operand? if (stackSize == 1) return 1; return 0; }
public object ReadOperand(Instruction instruction) { while (instruction.Operand is Instruction) instruction = (Instruction)instruction.Operand; return instruction.Operand; }
private bool TryGetInstruction(List<ILRange> ilRanges, OpCode opCode, out Instruction instruction) { int fromOffset = 0; int toOffset = 0; if (ilRanges == null || ilRanges.Count == 0) { instruction = null; return false; } fromOffset = ilRanges[0].From; toOffset = ilRanges[0].To; instruction = InstructionAt(fromOffset); do { if (instruction.OpCode == opCode) { return true; } instruction = instruction.Next; fromOffset = instruction.Offset; } while (fromOffset != toOffset); return instruction.OpCode == opCode; }
public void Store(Code op, Mono.Cecil.Cil.Instruction inst) { TypeCode elemType; switch (op) { case Code.Stelem_Ref: case Code.Stelem_Any: Store(null, null); return; case Code.Stelem_I1: elemType = TypeCode.Byte; break; case Code.Stelem_I2: elemType = TypeCode.Int16; break; case Code.Stelem_I4: elemType = TypeCode.Int32; break; case Code.Stelem_I8: case Code.Stelem_I: elemType = TypeCode.Int64; break; case Code.Stelem_R4: elemType = TypeCode.Single; break; case Code.Stelem_R8: elemType = TypeCode.Double; break; default: throw new InvalidProgramException(); } Store(CilType.From(new JavaType(elemType, 0, null)), inst); }
private static IEnumerable<Instruction> NextInstructions(Instruction v) { var fc = v.OpCode.FlowControl; switch (fc) { case FlowControl.Next: case FlowControl.Call: // stay within the method yield return v.Next; break; case FlowControl.Return: yield break; case FlowControl.Cond_Branch: yield return v.Next; if (v.Operand is Instruction[]) { // switch statement foreach (var i in (Instruction[])v.Operand) yield return i; } else yield return (Instruction)v.Operand; break; case FlowControl.Branch: yield return (Instruction)v.Operand; break; default: throw new NotImplementedException(fc.ToString()); } }
public StackAnalysisResult(Instruction consumer, int offset, bool match, int stackHeight) { _consumer = consumer; _offset = offset; _match = match; _stackHeight = stackHeight; }
public void Append(Instruction instruction) { if (instruction == null) throw new ArgumentNullException ("instruction"); instructions.Add (instruction); }
// look for a virtual call to a specific method static bool IsCallVirt (Instruction ins, string typeName, string methodName) { if (ins.OpCode.Code != Code.Callvirt) return false; MethodReference mr = (ins.Operand as MethodReference); return ((mr != null) && (mr.Name == methodName) && (mr.DeclaringType.FullName == typeName)); }
internal PrimitiveEmitter(PrimitiveExpression primitiveExpression, ILGenerator ilGenerator, IOpCodeIndexer instructionsIndexer) : base(ilGenerator, instructionsIndexer) { PrimitiveExpression = primitiveExpression; Type = PrimitiveExpression.Value.GetType(); PrimitiveInstruction = InstructionsIndexer.GetInstruction(PrimitiveExpression); }
public static void ChangeThreeToSeven(Instruction i) { if (i.OpCode.Code == Code.Ldc_I4_3 && i.Previous.OpCode == OpCodes.Stloc_S && i.Next.OpCode == OpCodes.Stloc_S) { i.OpCode = OpCodes.Ldc_I4_7; } }
// Sets pops to -1 if the stack is supposed to be cleared public static void calculateStackUsage(Instruction instr, bool methodHasReturnValue, out int pushes, out int pops) { if (instr.OpCode.FlowControl == FlowControl.Call) calculateStackUsage_call(instr, out pushes, out pops); else calculateStackUsage_nonCall(instr, methodHasReturnValue, out pushes, out pops); }
public IEnumerable <ValidationResult> Validate(Mono.Cecil.Cil.Instruction instruction, MethodDefinition method) { if (!(instruction.Operand is MemberReference reference)) { return(Enumerable.Empty <ValidationResult>()); } if (reference is MethodReference methodReference) { var validationResults = new List <ValidationResult>(); validationResults.AddRange(this.ValidateReference(method, methodReference.DeclaringType, methodReference.Name)); validationResults.AddRange(this.ValidateReference(method, methodReference.ReturnType)); return(validationResults); } if (reference is FieldReference fieldReference) { var validationResults = new List <ValidationResult>(); validationResults.AddRange(this.ValidateReference(method, fieldReference.DeclaringType, fieldReference.Name)); validationResults.AddRange(this.ValidateReference(method, fieldReference.FieldType)); return(validationResults); } if (reference is TypeReference typeReference) { return(this.ValidateReference(method, typeReference)); } return(Enumerable.Empty <ValidationResult>()); }
private static bool IsCastTo(TypeDefinition castTarget, Instruction instruction) { if (instruction.OpCode != OpCodes.Castclass) return false; TypeReference typeReference = (TypeReference)instruction.Operand; return typeReference.Resolve() == castTarget; }
private Instruction EmitCodeInit(TypeReference role, Instruction instructionBeforeInit, ILProcessor il) { var current = instructionBeforeInit; current = InsertAfter(il, current, il.Create(OpCodes.Ldarg_0)); current = InsertAfter(il, current, il.Create(OpCodes.Call, ResolveInitReference(role))); return current; }
private static bool IsInstantiationOf(TypeDefinition definition, Instruction candidate) { if (candidate.OpCode != OpCodes.Newobj) return false; MethodReference ctor = (MethodReference) candidate.Operand; return ctor.DeclaringType.Resolve() == definition; }
public static void ChangeFoursToEights(Instruction i) { if (i.OpCode.Code == Code.Ldc_I4_4) { i.OpCode = OpCodes.Ldc_I4_8; } }
public static void CompareEq(JavaType stackTop, JavaType stackTop2, Mono.Cecil.Cil.Instruction cilInst, JavaCode code) { if (stackTop.Equals(SpanType) && (stackTop2.PrimitiveType == TypeCode.Int64 || stackTop2.PrimitiveType == TypeCode.UInt64)) { // compare Span with long throw new InvalidProgramException(); } if (stackTop2.Equals(SpanType) && (stackTop.PrimitiveType == TypeCode.Int64 || stackTop.PrimitiveType == TypeCode.UInt64)) { if (cilInst.Previous == null || cilInst.Previous.OpCode.Code != Code.Conv_U || cilInst.Previous.Previous == null || cilInst.Previous.Previous.OpCode.Code != Code.Ldc_I4_0) { // make sure the program is comparing the span address against // a zero value, which we can convert to a null reference. // ldarg.1 (span argument) // ldc.i4.0 // conv.u // bne.un label throw new InvalidProgramException(); } // compare long with Span code.NewInstruction(0x58 /* pop2 */, null, null); code.NewInstruction(0x01 /* aconst_null */, null, null); } }
/// <summary> /// Replaces instruction references (ie if, try) to a new instruction target. /// This is useful if you are injecting new code before a section of code that is already /// the receiver of a try/if block. /// </summary> /// <param name="current">The original instruction</param> /// <param name="newTarget">The new instruction that will receive the transfer</param> /// <param name="originalMethod">The original method that is used to search for transfers</param> public static void ReplaceTransfer(this Instruction current, Instruction newTarget, MethodDefinition originalMethod) { //If a method has a body then check the instruction targets & exceptions if (originalMethod.HasBody) { //Replaces instruction references from the old instruction to the new instruction foreach (var ins in originalMethod.Body.Instructions.Where(x => x.Operand == current)) ins.Operand = newTarget; //If there are exception handlers, it's possible that they will also need to be switched over if (originalMethod.Body.HasExceptionHandlers) { foreach (var handler in originalMethod.Body.ExceptionHandlers) { if (handler.FilterStart == current) handler.FilterStart = newTarget; if (handler.HandlerEnd == current) handler.HandlerEnd = newTarget; if (handler.HandlerStart == current) handler.HandlerStart = newTarget; if (handler.TryEnd == current) handler.TryEnd = newTarget; if (handler.TryStart == current) handler.TryStart = newTarget; } } //Update the new target to take the old targets place newTarget.Offset = current.Offset; newTarget.SequencePoint = current.SequencePoint; newTarget.Offset++; //TODO: spend some time to figure out why this is incrementing } }
//public OpCode opCode; //public static Queue<Instruction> LoadParameter(MethodCallStackFrame closure, int index) //{ // //var loadParameter = new Queue<Instruction>(); // //Instruction current; // ////if(index == 0) // //// current = closure.thisLoad; // ////else // // current = closure.parameters[index - 1]; // //while (current != closure.parameters[index]) // //{ // // current = current.Next; // // loadParameter.Enqueue(current); // //} // //return loadParameter; //} public static MethodCallStackFrame GetMethodCallStackFrame(Instruction methodCall) { var methodReference = methodCall.Operand as MethodReference; var parametersCount = methodReference.Parameters.Count + (methodReference.HasThis ? 1 : 0); var stackFrame = new MethodCallStackFrame() { methodReference = methodReference, methodCall = methodCall, parameters = new Instruction[parametersCount] }; var instructionsCoutner = parametersCount; var currentParameter = parametersCount - 1; // zero based var currentInstruction = methodCall; while(instructionsCoutner != 0) { currentInstruction = currentInstruction.Previous; instructionsCoutner -= GetStackModifier(currentInstruction); if (instructionsCoutner == currentParameter) stackFrame.parameters[currentParameter--] = currentInstruction; } return stackFrame; }
public void OnInstruction(Mono.Cecil.Cil.Instruction i) { foreach (AbstractCollector col in m_collectionTable.Values) { col.OnInstruction(i); } }
static bool IsFloatingPointArguments (Instruction ins, MethodDefinition method) { TypeReference tr = ins.GetOperandType (method); if (tr == null) return false; return tr.IsFloatingPoint (); }
public SwitchRunnable(BlockDecomposer block, IList<int> cyclomaticComplexity, Instruction defaultCase, params Instruction[] cases) { this.block = block; this.cyclomaticComplexity = cyclomaticComplexity; this.defaultCase = defaultCase; this.cases = cases; }
/// <summary> /// Performs the optimization starting at the current instruction. /// </summary> /// <param name="instruction">The instruction to target.</param> /// <param name="worker">The worker for optimization actions.</param> public override void OptimizeInstruction(Instruction instruction, OptimizationWorker worker) { // TODO: allow arguments // TODO: allow return values // TODO: allow generic methods // TODO: allow non-static methods var opCode = instruction.OpCode; if (opCode.FlowControl != FlowControl.Call) { return; } var methodRef = (MethodReference) instruction.Operand; var typeRef = methodRef.DeclaringType; var module = typeRef.Module; var type = module.Types[typeRef.FullName]; if (type == null) { return; } var method = type.Methods.GetMethod(methodRef.Name, methodRef.Parameters); bool shouldInlineMethod; if (!this.shouldInline.TryGetValue(method, out shouldInlineMethod)) { shouldInlineMethod = this.configuration.ShouldInline(method); this.shouldInline[method] = shouldInlineMethod; } if (shouldInlineMethod) { InlineMethod(instruction, worker, method); } }
public static void Dispatch (Instruction instruction, IInstructionVisitor visitor) { switch (instruction.OpCode.Code) { <% for instr in Instructions: for opcode in instr.OpCodes: %> case Code.${opcode}:
public static string InstructionText(Instruction inst) { if (inst.Operand is Mono.Cecil.Cil.Instruction) { Mono.Cecil.Cil.Instruction instruccion = (Instruction)inst.Operand; return(string.Format("{0} {1}", inst.OpCode.ToString(), instruccion.Offset.ToString())); } else if (inst.Operand is string) { return(string.Format("{0} \"{1}\"", inst.OpCode.ToString(), inst.Operand.ToString())); } else if (inst.Operand is MethodReference) { MethodReference metodo = (MethodReference)inst.Operand; return(inst.OpCode.ToString() + " " + metodo.ToString()); } else if (inst.Operand != null) { return(inst.OpCode.ToString() + " " + inst.Operand.ToString()); } else { return(inst.OpCode.ToString()); } }
private static int GetOperatorValue(Mono.Cecil.Cil.Instruction parameterInstruction) { switch (parameterInstruction.OpCode.ToString()) { case "ldc.i4.0": return(0); case "ldc.i4.1": return(1); case "ldc.i4.2": return(2); case "ldc.i4.3": return(3); case "ldc.i4.4": return(4); case "ldc.i4.5": return(5); case "ldc.i4.6": return(7); case "ldc.i4.7": return(8); default: return(Convert.ToInt32(parameterInstruction.Operand)); } }
public static void ChangeThreesToSevens(Instruction i) { if (i.OpCode.Code == Code.Ldc_I4_3) { i.OpCode = OpCodes.Ldc_I4_7; } }
public static void Switch(JavaCode code, Mono.Cecil.Cil.Instruction cilInst) { if (cilInst.Operand is Mono.Cecil.Cil.Instruction[] targets) { if ((targets.Length > Int32.MaxValue - 1) || cilInst.Next == null || (!code.StackMap.PopStack(CilMain.Where).IsIntLike)) { throw new InvalidProgramException(); } ushort offset = (ushort)cilInst.Next.Offset; code.StackMap.SaveFrame(offset, true, CilMain.Where); int n = targets.Length; var instdata = new int[3 + n]; instdata[0] = offset; instdata[2] = n - 1; for (int i = 0; i < n; i++) { offset = (ushort)targets[i].Offset; code.StackMap.SaveFrame(offset, true, CilMain.Where); instdata[i + 3] = offset; } code.NewInstruction(0xAA /* tableswitch */, null, instdata); } }
public static bool IsAndBeforeShift(Mono.Cecil.Cil.Instruction inst, JavaCode code) { // jvm shift instructions mask the shift count, so // eliminate AND-ing with 31 and 63 prior to a shift. // the input inst should point to the first of three // instructions, and here we check if the sequence is: // ldc_i4 31 or 63; and; shift // used by LoadConstant (see above), CodeNumber::Calculation var next1 = inst.Next; if (next1 != null && next1.OpCode.Code == Code.And) { var next2 = next1.Next; if (next2 != null && (next2.OpCode.Code == Code.Shl || next2.OpCode.Code == Code.Shr || next2.OpCode.Code == Code.Shr_Un)) { var stackArray = code.StackMap.StackArray(); if (stackArray.Length >= 2 && IsLoadConstant(inst) is int shiftMask && ((shiftMask == 31 && stackArray[0].Equals(JavaType.IntegerType)) || (shiftMask == 63 && stackArray[0].Equals(JavaType.LongType)))) { return(true); } } } return(false); }
private static void CompileStoreLocalN(CInstruction instruction, List <string> imports, List <SectionEntry> code, int n) { // pop local N // Pop a value from stack into local variable n // addr=LCL+2 // SP-- // *addr=*SP throw new NotImplementedException(); }
static byte TestEq(JavaCode code, JavaType stackTop, JavaType stackTop2, Mono.Cecil.Cil.Instruction cilInst) { if (stackTop.IsReference || stackTop2.IsReference) { byte cmpOp = CodeSpan.CompareEq(stackTop, stackTop2, cilInst, code); if (cmpOp == 0) { cmpOp = 0xA5; // if_acmpeq (reference) } return(cmpOp); } if (stackTop2.IsIntLike && (stackTop.PrimitiveType == TypeCode.Int32 || stackTop.PrimitiveType == TypeCode.UInt32 || stackTop.PrimitiveType == TypeCode.Int16 || stackTop.PrimitiveType == TypeCode.UInt16 || stackTop.PrimitiveType == TypeCode.SByte || stackTop.PrimitiveType == TypeCode.Byte || stackTop.PrimitiveType == TypeCode.Char || stackTop.PrimitiveType == TypeCode.Boolean)) { return(0x9F); // if_icmpeq } byte op; if ((stackTop.PrimitiveType == TypeCode.Int64 || stackTop.PrimitiveType == TypeCode.UInt64) && (stackTop2.PrimitiveType == TypeCode.Int64 || stackTop2.PrimitiveType == TypeCode.UInt64)) { op = 0x94; // lcmp (long) } else if (stackTop.PrimitiveType == TypeCode.Single && stackTop2.PrimitiveType == TypeCode.Single) { op = 0x95; // fcmpl (float) } else if (stackTop.PrimitiveType == TypeCode.Double && stackTop2.PrimitiveType == TypeCode.Double) { op = 0x97; // dcmpl (double) } else { throw new Exception($"incompatible types '{stackTop}' and '{stackTop2}'"); } code.NewInstruction(op, null, null); return(0x99); // ifeq == zero }
private static void Compile(CInstruction instruction, List <string> imports, List <SectionEntry> textSectionInstructions) { if (_compileInstructionActions.TryGetValue(instruction.OpCode.Code, out var compileAction)) { textSectionInstructions.Add(new SectionLabel($"CIL_{instruction.Offset:X4}")); compileAction(instruction, imports, textSectionInstructions); } throw new NotSupportedException($"Unsupported op code {instruction.OpCode.Code} while compiling instruction: {instruction}"); }
public IEnumerable <ValidationResult> Validate(Mono.Cecil.Cil.Instruction instruction, MethodDefinition method) { var errors = new List <FloatValidationResult>(); if (IsFloat(instruction)) { errors.Add(new FloatValidationResult(method)); } return(errors); }
public override bool MoveToNext(Navigator n) { bool result = false; InstructionDefinition instruction = Cast(n); if (instruction.Next != null) { n.Current = instruction.Next; result = true; } return(result); }
public static bool IsMethodCall(Mono.Cecil.Cil.Instruction i) { if (i.Operand is Mono.Cecil.CallSite || i.Operand is Mono.Cecil.FieldReference) return false; return i.OpCode == Mono.Cecil.Cil.OpCodes.Call || i.OpCode == Mono.Cecil.Cil.OpCodes.Calli || i.OpCode == Mono.Cecil.Cil.OpCodes.Callvirt || // Constructor i.OpCode == Mono.Cecil.Cil.OpCodes.Newobj; }
static public int Add(this MethodBody body, Mono.Cecil.Cil.Instruction instruction) { body.Instructions.Add(instruction); var _branch = Branch.Query(body); if (_branch == null) { return(body.Instructions.Count - 1); } _branch.Finialize(instruction); return(body.Instructions.Count - 1); }
public static void Straight(JavaCode code, Code cilOp, CodeLocals locals, Mono.Cecil.Cil.Instruction cilInst) { // // a straight branch maps to the corresponding compare logic // (beq = ceq, bgt = cgt, blt = clt), plus logic for brtrue. // byte op; ushort nextInstOffset = 0; if (cilOp == Code.Br || cilOp == Code.Br_S) { if (cilInst.Operand is Mono.Cecil.Cil.Instruction inst) { if (inst == cilInst.Next) { op = 0x00; // nop } else { op = 0xA7; // goto if (cilInst.Next != null) { nextInstOffset = (ushort)cilInst.Next.Offset; } } } else { throw new InvalidProgramException(); } } else { var stackTop = code.StackMap.PopStack(CilMain.Where); op = Common(code, cilOp, cilInst, stackTop); } Finish(code, locals, cilInst, op); if (nextInstOffset != 0) { if (!code.StackMap.LoadFrame(nextInstOffset, true, null)) { if (op == 0xA7 /* goto */) { locals.TrackUnconditionalBranch(cilInst); } } } }
private void InsertAndBoxConstant(Injector injector, object constant, TypeReference type, TypeReference boxType = null) { if (type.IsType <string>()) { injector.Insert(OpCodes.Ldstr, (string)constant); } else if (type.IsType <int>()) { injector.Insert(OpCodes.Ldc_I4, (int)constant); } else if (type.IsType <long>()) { injector.Insert(OpCodes.Ldc_I8, (long)constant); } else if (type.IsType <double>()) { injector.Insert(OpCodes.Ldc_R8, (double)constant); } else if (type.IsType <float>()) { injector.Insert(OpCodes.Ldc_R4, (float)constant); } else if (type.IsType <short>()) { injector.Insert(OpCodes.Ldc_I4, (short)constant); } else if (type.IsType <byte>()) { injector.Insert(OpCodes.Ldc_I4, (byte)constant); } else if (type.IsType <uint>()) { injector.Insert(OpCodes.Ldc_I4, (int)(uint)constant); } else if (type.IsType <ulong>()) { injector.Insert(OpCodes.Ldc_I8, (long)(ulong)constant); } else if (type.IsType <ushort>()) { injector.Insert(OpCodes.Ldc_I4, (ushort)constant); } else if (type.IsType <sbyte>()) { injector.Insert(OpCodes.Ldc_I4, (sbyte)constant); } if (boxType != null) { injector.Insert(Instruction.Create(OpCodes.Box, boxType)); } Logger.Warning($"Unknown constant type {constant.GetType().FullName}"); }
public Vertex FindEntry(Mono.Cecil.Cil.Instruction inst) { Vertex result = null; foreach (CFG.Vertex node in this.Vertices) { if (node.Instructions.First().Instruction == inst) { return(node); } } return(result); }
static byte Common(JavaCode code, Code cilOp, Mono.Cecil.Cil.Instruction cilInst, JavaType stackTop) { if (cilInst.Operand is Mono.Cecil.Cil.Instruction inst) { bool branchToNext = (inst == cilInst.Next); if (cilOp == Code.Brtrue || cilOp == Code.Brtrue_S) { if (branchToNext) { return(PopOpCode(stackTop)); } else { return(TestBool(code, stackTop)); } } // all other conditionals pop a second value off the stack var stackTop2 = code.StackMap.PopStack(CilMain.Where); if (branchToNext) { code.NewInstruction(PopOpCode(stackTop2), null, null); return(PopOpCode(stackTop)); } if (cilOp == Code.Beq || cilOp == Code.Beq_S) { return(TestEq(code, stackTop, stackTop2, cilInst)); } else { return(TestGtLt(code, stackTop, stackTop2, /* if greater than */ (cilOp == Code.Bgt || /* (vs less than) */ cilOp == Code.Bgt_S || cilOp == Code.Bgt_Un || cilOp == Code.Bgt_Un_S), /* if unsigned */ (cilOp == Code.Bgt_Un || /* or unordered */ cilOp == Code.Bgt_Un_S || cilOp == Code.Blt_Un || cilOp == Code.Blt_Un_S))); } } else { throw new InvalidProgramException(); } byte PopOpCode(JavaType forType) => (byte)(0x56 + forType.Category); }
bool InstructionIsFontSizeConverterCtor(MethodDefinition methodDef, Mono.Cecil.Cil.Instruction instruction) { if (instruction.OpCode != OpCodes.Newobj) { return(false); } if (!(instruction.Operand is MethodReference methodRef)) { return(false); } if (!Build.Tasks.TypeRefComparer.Default.Equals(methodRef.DeclaringType, methodDef.Module.ImportReference(typeof(Microsoft.Maui.Controls.FontSizeConverter)))) { return(false); } return(true); }
/// <summary> /// Reads an instruction operand by recursive calling until non-instruction /// operand is found /// </summary> /// <param name="instruction">An instruction with operand</param> /// <returns>An instruction operand</returns> public object ReadOperand(Mono.Cecil.Cil.Instruction instruction) { if (instruction.Operand == null) { return(null); } var nextInstruction = instruction.Operand as Mono.Cecil.Cil.Instruction; if (nextInstruction != null) { return(ReadOperand(nextInstruction)); } return(instruction.Operand); }
bool InstructionIsOnPlatformExtensionCtor(MethodDefinition methodDef, Mono.Cecil.Cil.Instruction instruction) { if (instruction.OpCode != OpCodes.Newobj) { return(false); } if (!(instruction.Operand is MethodReference methodRef)) { return(false); } if (!Build.Tasks.TypeRefComparer.Default.Equals(methodRef.DeclaringType, methodDef.Module.ImportReference(typeof(OnPlatformExtension)))) { return(false); } return(true); }
static void Finish(JavaCode code, CodeLocals locals, Mono.Cecil.Cil.Instruction cilInst, byte op) { var inst = (Mono.Cecil.Cil.Instruction)cilInst.Operand; bool isNop; if (op == 0x00 || op == 0x57 || op == 0x58) // nop, pop, pop2 { isNop = true; } else { isNop = false; int diff = cilInst.Offset - inst.Offset; if (diff < -0x2000 || diff > 0x2000) { // branch instructions use 16-bits for the signed offset. // for farther branches, we have to negate the condition, // and insert a 32-bit 'goto_w' instruction. if (cilInst.Next != null) { op = NegateCondition(op); var nextOffset = (ushort)cilInst.Next.Offset; code.NewInstruction(op, null, nextOffset); code.StackMap.SaveFrame(nextOffset, true, CilMain.Where); } op = 0xC8; } } code.NewInstruction(op, null, (ushort)inst.Offset); if (!isNop) // no stack frame for 'nop' or 'pop' { var resetLocals = code.StackMap.SaveFrame((ushort)inst.Offset, true, CilMain.Where); if (resetLocals != null) { ResetLocalsOutOfScope(code.StackMap, locals, resetLocals, cilInst, inst); } } }
private static void CompileLoadLocalN(CInstruction instruction, List <string> imports, List <SectionEntry> code, int n) { // push local N // Load local variable of index n onto stack // PUSH constant 17 // @17 // D=17 // D=A // @SP // *SP=D // A=M // M=D // @SP // M=M+1 // mov rax, SP // add rsp, 1 throw new NotImplementedException(); }
private static bool AnalyzeMethodFieldSets(MethodDefinition methodDefinition, XElement entity, XElement newMethodNode) { bool result = false; Mono.Cecil.Cil.MethodBody body = methodDefinition.Body; if (null != body) { foreach (Instruction itemInstruction in body.Instructions) { if (itemInstruction.OpCode.Name.StartsWith("stfld") || itemInstruction.OpCode.Name.StartsWith("stsfld")) { Mono.Cecil.Cil.Instruction methodInstruction = itemInstruction as Mono.Cecil.Cil.Instruction; Mono.Cecil.FieldDefinition fieldDefinition = methodInstruction.Operand as Mono.Cecil.FieldDefinition; if (fieldDefinition != null && fieldDefinition.FieldType.IsValueType) { Mono.Cecil.Cil.Instruction paramInstruction = GetParameterInstructionForField(methodInstruction); if (null != paramInstruction) { bool sucseed = false; int opValue = GetOperatorValue(paramInstruction, out sucseed); if (sucseed) { string[] supportByLibrary = _netOfficeSupportTable.GetEnumMemberSupport(fieldDefinition.FieldType.FullName, (int)opValue); if (null != supportByLibrary) { XElement newParameter = new XElement("Field", new XAttribute("Name", fieldDefinition.Name)); string componentName = NetOfficeSupportTable.GetLibrary(fieldDefinition.FieldType.FullName); XElement supportByNode = new XElement("SupportByLibrary", new XAttribute("Api", componentName)); string memberName = _netOfficeSupportTable.GetEnumMemberNameFromValue(fieldDefinition.FieldType.FullName, opValue); supportByNode.Add(new XAttribute("Name", fieldDefinition.FieldType + "." + memberName)); foreach (string item in supportByLibrary) { supportByNode.Add(new XElement("Version", item)); } newParameter.Add(supportByNode); newMethodNode.Element("FieldSets").Add(newParameter); } } } } } } } return(result); }
public static int?IsLoadConstant(Mono.Cecil.Cil.Instruction inst) { if (inst != null) { var op = inst.OpCode.Code; var data = inst.Operand; if (op == Code.Ldc_I4 && data is int intVal) { return(intVal); } if (op == Code.Ldc_I4_S && data is sbyte sbyteVal) { return(sbyteVal); } } return(null); }
public void Call(CilMethod method, Mono.Cecil.Cil.Instruction inst) { int numDims = method.Parameters.Count; var elemType = method.DeclType; if (method.Name == "Get") { Deref(numDims); stackMap.PopStack(CilMain.Where); // pop index stackMap.PopStack(CilMain.Where); // pop array Load(null, elemType, inst); } else if (method.Name == "Set") { numDims--; // last parameter is value if (numDims > 1) { var valueType = stackMap.PopStack(CilMain.Where); int localIndex = locals.GetTempIndex(valueType); code.NewInstruction(valueType.StoreOpcode, null, localIndex); Deref(numDims); code.NewInstruction(valueType.LoadOpcode, null, localIndex); stackMap.PushStack(valueType); } Store(elemType); } else if (method.Name == "Address") { Deref(numDims); Address(elemType); } else { throw new InvalidProgramException(); } }