Пример #1
0
 /// <summary>
 /// Transform the given body.
 /// </summary>
 public void Transform(Dex target, MethodBody body)
 {
     foreach (var ins in body.Instructions)
     {
         switch (ins.Code)
         {
             case RCode.Invoke_direct:
             case RCode.Invoke_virtual:
             case RCode.Invoke_interface:
                 MethodDefinition method;
                 if (((MethodReference)ins.Operand).TryResolve(target, out method))
                 {
                     if (method.Owner.IsInterface)
                     {
                         ins.Code = RCode.Invoke_interface;
                     }
                     else if (method.IsDirect)
                     {
                         ins.Code = RCode.Invoke_direct;
                     }
                     else
                     {
                         ins.Code = RCode.Invoke_virtual;
                     }
                 }
                 break;
         }
     }
 }
Пример #2
0
 /// <summary>
 /// Default ctor
 /// </summary>
 public BranchReRouter(MethodBody body)
 {
     List<Instruction> list = null;
     // Record instructions with branch targets
     foreach (var inst in body.Instructions)
     {
         switch (inst.Code)
         {
             case RCode.Goto:
             case RCode.Leave:
             case RCode.If_eq:
             case RCode.If_ne:
             case RCode.If_lt:
             case RCode.If_ge:
             case RCode.If_gt:
             case RCode.If_le:
             case RCode.If_eqz:
             case RCode.If_nez:
             case RCode.If_ltz:
             case RCode.If_gez:
             case RCode.If_gtz:
             case RCode.If_lez:
             case RCode.Packed_switch:
             case RCode.Sparse_switch:
                 list = list ?? new List<Instruction>();
                 list.Add(inst);
                 break;
         }
     }
     branches = list;
     exceptionHandlers = body.Exceptions.Any() ? body.Exceptions.ToArray() : null;
 }
Пример #3
0
        /// <summary>
        /// Replace all references to oldRegister with newRegister in the given instruction set.
        /// </summary>
        public void ReplaceRegisterWith(Register oldRegister, Register newRegister, MethodBody body)
        {
            var oldRegister2 = (oldRegister.Type == RType.Wide) ? body.GetNext(oldRegister) : null;
            var newRegister2 = (newRegister.Type == RType.Wide) ? body.GetNext(newRegister) : null;

            if (oldRegister.IsKeepWithNext != newRegister.IsKeepWithNext)
                throw new ArgumentException("New register has different keep-with-next value");

            HashSet<Instruction> list;
            if (map.TryGetValue(oldRegister, out list))
            {
                list.ForEach(x => x.ReplaceRegisterWith(oldRegister, newRegister));
                // Update newRegister
                AddRange(newRegister, list);
            }
            if (oldRegister2 != null)
            {
                if (map.TryGetValue(oldRegister2, out list))
                {
                    list.ForEach(x => x.ReplaceRegisterWith(oldRegister2, newRegister2));
                    // Update newRegister2
                    AddRange(newRegister2, list);
                }                
            }
        }
        /// <summary>
        /// Transform the given body.
        /// </summary>
        private static void TransformTempToVariable(MethodBody body, List<BasicBlock> basicBlocks)
        {
            body.Instructions.UpdateIndexCache();
            var allTempRegisterRanges = CollectTempRegisterUsageRanges(basicBlocks).Values.ToList();

            foreach (var iterator in basicBlocks)
            {
                var block = iterator;
                // Collect all register ranges that fit completly within this block and are used exactly 2 times
                var registerRanges = allTempRegisterRanges.Where(x => (x.InstructionCount == 2) && x.ContainsExactlyOne(block)).ToList();

                foreach (var range in registerRanges)
                {
                    var firstIns = range.Range.First;
                    var lastIns = range.Range.Last;
                    if (!lastIns.Code.IsMove())
                        continue;
                    var reg = range.Register;
                    if (lastIns.Registers[1] != reg)
                        continue;
                    var varReg = lastIns.Registers[0];
                    if (varReg.Category != RCategory.Variable)
                        continue;

                    // Replace
                    firstIns.ReplaceRegisterWith(reg, varReg);
                    lastIns.ConvertToNop();
                }
            }
        }
Пример #5
0
        private static IEnumerable<IRLTransformation> GetTransformations(Dex target, MethodBody body)
        {
            foreach (var transformation in optimizations1)
            {
                transformation.Transform(target, body);
                yield return transformation;
            }

            var noopRemove = new NopRemoveTransformation();
            noopRemove.Transform(target, body);
            yield return noopRemove;

            bool hasChanges = true;

            while (hasChanges)
            {
                hasChanges = false;
                foreach (var transformation in incrementalOptimizations)
                {
                    bool changed = transformation.Transform(target, body);
                    if (changed) noopRemove.Transform(target, body);

                    hasChanges = changed || hasChanges;

                    yield return transformation;
                }
            }

            foreach (var transformation in optimizations2)
            {
                transformation.Transform(target, body);
                yield return transformation;
            }    
        }
        public bool Transform(Dex target, MethodBody body)
        {
#if DEBUG
            //return;
#endif
            return DoOptimization(body);
        }
		static void AssertOpCodeSequence (OpCode [] expected, MethodBody body)
		{
			var opcodes = body.Instructions.Select (i => i.OpCode).ToArray ();
			Assert.AreEqual (expected.Length, opcodes.Length);

			for (int i = 0; i < opcodes.Length; i++)
				Assert.AreEqual (expected [i], opcodes [i]);
		}
Пример #8
0
 public void InnerProcess()
 {
     body = Method.Body;
     body.SimplifyMacros();
     InjectStopwatch();
     HandleReturns();
     body.InitLocals = true;
     body.OptimizeMacros();
 }
Пример #9
0
        /// <summary>
        /// Transform the given body.
        /// </summary>
        public void Transform(Dex target, MethodBody body)
        {
            var basicBlocks = BasicBlock.Find(body);
            var registerCount = body.Registers.Count();
            if (registerCount > MaxRegisters)
                return;

            Dictionary<Instruction, ConstantKey> allConstInstructions;
            CollectReadOnlyConstInstructions(body, out allConstInstructions);
            RegisterUsageMap registerUsageMap = null;

            foreach (var block in basicBlocks)
            {
                // Select all const instructions that have a next instruction in the block.
                var list = block.Instructions.ToList();
                var isLargeBlock = list.Count > LargeBlockSize;
                if (isLargeBlock)
                    continue;
                var constInstructionKeys = list.Where(x => allConstInstructions.ContainsKey(x)).Select(x => allConstInstructions[x]).ToList();

                // Select all const instructions where the next instruction is a move.
                while (constInstructionKeys.Count > 0)
                {
                    // Take the first instruction
                    var insKey = constInstructionKeys[0];
                    constInstructionKeys.RemoveAt(0);

                    // Get the register
                    var reg = insKey.Instruction.Registers[0];

                    // Are there other const instructions of the same type and the same operand?
                    var sameConstInstructions = constInstructionKeys.Where(x => x.Equals(insKey)).ToList();
                    if (sameConstInstructions.Count == 0)
                        continue;
                    if (sameConstInstructions.Count < 4)
                        continue;

                    // It is now save to use the register for all const operations
                    foreach (var other in sameConstInstructions)
                    {
                        // Replace all register uses
                        var otherReg = other.Instruction.Registers[0];

                        // Find usages
                        registerUsageMap = registerUsageMap ?? new RegisterUsageMap(body.Instructions);
                        registerUsageMap.ReplaceRegisterWith(otherReg, reg, body);

                        // Remove const
                        constInstructionKeys.Remove(other);
                        allConstInstructions.Remove(other.Instruction);

                        // Change const to nop which will be removed later
                        other.Instruction.ConvertToNop();
                    }
                }
            }
        }
Пример #10
0
        public ControlFlowGraph2(MethodBody body)
        {
            _body = body;
            _basicBlocks = new ControlFlowGraph(body).ToList();
            _entries = _basicBlocks.ToDictionary(b => b.Entry, b => b);
            _exits = _basicBlocks.ToDictionary(b => b.Exit, b => b);
            _entryInstructions = _basicBlocks.Select(b => b.Entry).ToList();

            IncludeExceptionHandlers(body);
        }
        public bool Transform(Dex target, MethodBody body)
        {
            bool hasChanges = false;

            var registerUsage = new RegisterUsageMap2(body);

            hasChanges = InlineIntConstsIntoBinOp(registerUsage);

            return hasChanges;
        }
        /// <summary>
        /// Transform the given body.
        /// </summary>
        public bool Transform(Dex target, MethodBody body)
        {
            bool hasChanges = false;

            // Find all "const" instructions and record register usage
            var allConstInstructions = new List<Instruction>();
            var registerUsage = new Dictionary<Register, List<Instruction>>();
            CollectInstructionInformation(body, allConstInstructions, registerUsage);

            // Find all basic blocks
            var basicBlocks = BasicBlock.Find(body);

            // Go over each block
            foreach (var iterator in basicBlocks)
            {
                var block = iterator;
                // Select all const instructions where the next instruction is a move.
                foreach (var ins in allConstInstructions)
                {
                    var r = ins.Registers[0];
                    // Only optimize const instructions to temp registers
                    if (r.Category != RCategory.Temp)
                        continue;

                    // Get all instructions using this register
                    var all = registerUsage[r];
                    if ((all.Count != 2) || (all[0] != ins))
                        continue;
                    var next = all[1];
                    // Opcode must match
                    if (next.Code != ConstToMove(ins.Code))
                        continue;
                    // Register must match
                    if (next.Registers[1] != r)
                        continue;
                    
                    // The following are the most expensive, so only test them if we have to.
                    // Only optimize is instruction is in current block
                    if (!block.Contains(ins))
                        continue;

                    // Next must be in same basic block
                    if (!block.Contains(next))
                        continue;

                    // We found a replacement
                    r = next.Registers[0];
                    ins.Registers[0] = r;
                    next.ConvertToNop();

                    hasChanges = true;
                }
            }
            return hasChanges;
        }
Пример #13
0
		public MethodBody ReadMethodBody (MethodDefinition method)
		{
			this.method = method;
			this.body = new MethodBody (method);

			reader.context = method;

			ReadMethodBody ();

			return this.body;
		}
Пример #14
0
        public void Read(MethodBody body, InstructionMapper mapper)
        {
            var method_token = body.Method.MetadataToken;

            PdbFunction function;
            if (!functions.TryGetValue (method_token.ToUInt32 (), out function))
                return;

            ReadSequencePoints (function, mapper);
            ReadScopeAndLocals (function.scopes, null, body, mapper);
        }
Пример #15
0
        public void Read(MethodBody body, InstructionMapper mapper)
        {
            var method_token = body.Method.MetadataToken;
            var entry = symbol_file.GetMethodByToken (method_token.ToInt32	());
            if (entry == null)
                return;

            var scopes = ReadScopes (entry, body, mapper);
            ReadLineNumbers (entry, mapper);
            ReadLocalVariables (entry, body, scopes);
        }
Пример #16
0
 public VariableDefinition InjectStopwatch(MethodBody body, int index)
 {
     // inject as variable
     var stopwatchVar = new VariableDefinition("methodTimerStopwatch", StopwatchType);
     body.Variables.Add(stopwatchVar);
     body.Insert(index, new List<Instruction>(new[] {
         Instruction.Create(OpCodes.Call, StartNewMethod),
         Instruction.Create(OpCodes.Stloc, stopwatchVar)
     }));
     return stopwatchVar;
 }
        public bool Transform(Dex target, MethodBody body)
        {
            bool hasChanges = false;

            var graph = new ControlFlowGraph2(body);
            var registerUsage = new RegisterUsageMap2(graph);

            hasChanges = EliminateRegisterAssigments(registerUsage);
            
            return hasChanges;
        }
Пример #18
0
        public MSILDisassembler(MethodBody body)
        {
            MethodBody = body;

            Section section = Section.GetSectionByRva(body.Method._netheader._assembly, body.Method.RVA);

            _ilOffset = new OffsetConverter(section).RvaToFileOffset(body.Method.RVA) + (uint)body.HeaderSize;

            _reader = section.ParentAssembly._peImage.Reader;
            TokenResolver = new MetaDataTokenResolver(body.Method._netheader);
        }
Пример #19
0
        /// <summary>
        /// Find all instructions that  are "const" and have a destination register that is never assigned to.
        /// </summary>
        private static void CollectReadOnlyConstInstructions(MethodBody body, out Dictionary<Instruction, ConstantKey> constInstructions)
        {
            // Find all const instructions
            constInstructions = body.Instructions
                                    .Where(ins => ins.Code.IsConst() && !ins.Registers[0].PreventOptimization)
                                    .ToDictionary(ins => ins, ins => new ConstantKey(ins));
            if (constInstructions.Count == 0)
                return;

            // Select all registers used by the const instructions
            var constRegs = new Dictionary<Register, Instruction>();
            var toRemove = new HashSet<Instruction>();
            foreach (var ins in constInstructions.Keys)
            {
                var reg = ins.Registers[0];
                if (constRegs.ContainsKey(reg))
                {
                    // Oops, duplicate register, remove this one
                    toRemove.Add(ins);
                    toRemove.Add(constRegs[reg]);
                }
                else
                {
                    // Add it
                    constRegs[reg] = ins;
                }
            }
            foreach (var ins in toRemove)
            {
                constInstructions.Remove(ins);
                constRegs.Remove(ins.Registers[0]);
            }
            foreach (var ins in body.Instructions)
            {
                if (constInstructions.ContainsKey(ins))
                    continue;

                var insRegs = ins.Registers;
                for (var k = 0; k < insRegs.Count; k++)
                {
                    var reg = insRegs[k];
                    Instruction constInst;
                    if (constRegs.TryGetValue(reg, out constInst))
                    {
                        if (ins.IsDestinationRegister(k))
                        {
                            // Register is a destination in another instruction, the constInst is not readonly.
                            constInstructions.Remove(constInst);
                            constRegs.Remove(reg);
                        }
                    }
                }
            }
        }
    public void Execute()
    {
        moduleWeaver.LogInfo("\t\t" + propertyData.PropertyDefinition.Name);
        var property = propertyData.PropertyDefinition;
        setMethodBody = property.SetMethod.Body;
        instructions = property.SetMethod.Body.Instructions;

        foreach (var instruction in GetInstructions())
        {
            Inject(instruction);
        }
    }
Пример #21
0
        public bool Transform(Dex target, MethodBody body)
        {
            bool hasChanges = false;
#if DEBUG
            //return;
#endif
            var instructions = body.Instructions;
            var hasNops = instructions.Any(x => x.Code == RCode.Nop);
            if (!hasNops)
                return false;

            var rerouter = new BranchReRouter(body);
            var i = 0;
            while (i < instructions.Count)
            {
                var inst = instructions[i];
                if (inst.Code != RCode.Nop)
                {
                    i++;
                    continue;
                }
                if (body.Exceptions.Count > 0)
                {
                    foreach (var ex in body.Exceptions.Where(x => x.TryEnd == inst).ToList())
                    {
                        var exTryEnd = ex.TryEnd;
                        if (exTryEnd.Index > ex.TryStart.Index)
                            exTryEnd = exTryEnd.Previous;

                        if (exTryEnd == ex.TryStart)
                        {
                            // empty exception handler -- remove.
                            body.Exceptions.Remove(ex);
                        }
                        else
                        {
                            ex.TryEnd = exTryEnd;
                        }
                    }
                }

                if (i < instructions.Count - 1)
                {
                    var next = instructions[i + 1];
                    rerouter.Reroute(inst, next);
                }
                instructions.RemoveAt(i);
                hasChanges = true;
            }

            return hasChanges;
        }
Пример #22
0
        /// <summary>
        /// Transform the given body.
        /// </summary>
        public void Transform(Dex target, MethodBody body)
        {
            // Find all basic blocks
            var basicBlocks = BasicBlock.Find(body);

            // Replace temp with variable registers with possible.
            TransformTempToVariable(body, basicBlocks);

            // Share registers in block only
            TransformInBlock(body, basicBlocks);

            // Share register across blocks
            TransformCrossBlock(body, basicBlocks);
        }
Пример #23
0
    public void Execute()
    {
        moduleWeaver.LogDebug("\t\t" + propertyData.PropertyDefinition.Name);
        var property = propertyData.PropertyDefinition;
        setMethodBody = property.SetMethod.Body;
        instructions = property.SetMethod.Body.Instructions;

        var indexes = GetIndexes();
        indexes.Reverse();
        foreach (var index in indexes)
        {
            InjectAtIndex(index);
        }
    }
        /// <summary>
        /// Transform the given body.
        /// </summary>
        private static void TransformCrossBlock(MethodBody body, ICollection<BasicBlock> basicBlocks)
        {
            // Find all basic blocks
            if (basicBlocks.Count <= 1)
                return; // No need for this transformation

            var availableShortRegisters = new List<Register>(); // List of register available from previous blocks
            var availableWideRegisters  = new List<Register>(); // List of register available from previous blocks
            var allTempRegisterRanges   = CollectTempRegisterUsageRanges(basicBlocks)
                                                .Values
                                                .Where(x => x.Register.KeepWith != RFlags.KeepWithPrev)
                                                .ToList();

            foreach (var iterator in basicBlocks)
            {
                var block = iterator;
                // Collect all register ranges that fit completly within this block
                var registerRanges = allTempRegisterRanges.Where(x => x.IsRegisterAssignedInFirstInstruction && block.Contains(x.Range)).ToList();

                // For each register, look for an available to use instead
                foreach (var range in registerRanges)
                {
                    // Validate the range
                    if (!block.ContainsEntireRange(range.Range))
                    {
                        throw new CompilerException("Usage range falls outside block.");
                    }

                    var r = range.Register;
                    var availableList = r.KeepWith == RFlags.KeepWithNext ? availableWideRegisters : availableShortRegisters;
                    var replacement = availableList.FirstOrDefault(x => r.Type == x.Type);
                    if (replacement != null)
                    {
                        // We can replace r with the replacement we found.
                        range.ReplaceRegisterWith(r, replacement, body);
                        // Replacement is no longer available within this block
                        availableList.Remove(replacement);
                    }
                }

                // Make all registers available to following blocks
                foreach (var range in registerRanges)
                {
                    var r = range.Register;
                    var availableList = r.KeepWith == RFlags.KeepWithNext ? availableWideRegisters : availableShortRegisters;
                    if (!availableList.Contains(r))
                        availableList.Add(r);
                }
            }
        }
Пример #25
0
        public bool Transform(Dex target, MethodBody body)
        {
            foreach (var ins in body.Instructions)
            {
                if (ins.Code == RCode.Check_cast)
                {
                    var typeReference = (TypeReference) ins.Operand;
                    if(typeReference.Descriptor == "Ljava/lang/Object;")
                        ins.ConvertToNop();
                }
            }

            return false;
        }
    protected ILMethodBodyRewriter(IMetadataHost host, MethodBody methodBody, ILGenerator generator) {
      Contract.Requires(host != null);
      Contract.Requires(methodBody != null);
      Contract.Requires(generator != null);      
      Contract.Requires(methodBody != Dummy.MethodBody);

      this.host = host;
      this.methodBody = methodBody;
      this.generator = generator;

      // Make a label for each branch target
      this.offset2Label = ILMethodBodyRewriter.RecordBranchTargets(this.methodBody.Operations);
      //Record all offsets that appear as part of an exception handler
      this.offsetsUsedInExceptionInformation = ILMethodBodyRewriter.RecordExceptionHandlerOffsets(this.methodBody.OperationExceptionInformation);
    }
Пример #27
0
        static void WriteExceptionHandlers(TextWriter writer, MethodBody body)
        {
            if (!body.HasExceptionHandlers)
                return;

            foreach (var handler in body.ExceptionHandlers) {
                writer.Write ("\t");
                writer.WriteLine (".try {0} to {1} {2} handler {3} to {4}",
                    FormatLabel (handler.TryStart),
                    FormatLabel (handler.TryEnd),
                    FormatHandlerType (handler),
                    FormatLabel (handler.HandlerStart),
                    FormatLabel (handler.HandlerEnd));
            }
        }
Пример #28
0
        public void AddVariableIndex()
        {
            var object_ref = new TypeReference ("System", "Object", null, null, false);
            var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref);
            var body = new MethodBody (method);

            var x = new VariableDefinition ("x", object_ref);
            var y = new VariableDefinition ("y", object_ref);

            body.Variables.Add (x);
            body.Variables.Add (y);

            Assert.AreEqual (0, x.Index);
            Assert.AreEqual (1, y.Index);
        }
Пример #29
0
        /// <summary>
        /// Transform the given body towards Dex compilation. 
        /// <returns>
        /// Returns the name of the last applied tranformation, or null on full processing.
        /// </returns>
        /// </summary>
        internal static string Transform(Dex target, MethodBody body, int stopAfterSteps = int.MaxValue)
        {
            if (stopAfterSteps == 0) return "(no proccessing)";
            int stepCount = 0;

            foreach (var applied in GetTransformations(target, body))
            {
                if (++stepCount > stopAfterSteps)
                {
                    return applied.GetType().Name;
                }
            }

            return null;
        }
    public void Execute()
    {
        logger.LogMessage("\t\t" + propertyData.PropertyDefinition.Name);
        var property = propertyData.PropertyDefinition;
        setMethodBody = property.SetMethod.Body;
        instructions = property.SetMethod.Body.Instructions;

        logger.LogMessage("\t\t\tCheckForEquality=" + propertyData.CheckForEquality);

        var indexes = GetIndexes();
        indexes.Reverse();
        foreach (var index in indexes)
        {
            InjectAtIndex(index);
        }
    }
Пример #31
0
        public void GetMethodBody_Pinvoke()
        {
            MethodBody mb = typeof(MethodInfoTest).GetMethod("dllImportMethod").GetMethodBody();

            Assert.IsNull(mb);
        }
Пример #32
0
        static void ProcessMethod(MethodDefinition method, HashSet <TypeReference> typeset)
        {
            // this is needed in case we return an enum, a struct or something mapped
            // to p/invoke (i.e. no ctor called). We also need to check for arrays.
            TypeReference t = method.ReturnType;

            AddType(typeset, t);

            if (method.HasParameters)
            {
                // an "out" from a p/invoke must be flagged
                foreach (ParameterDefinition parameter in method.Parameters)
                {
                    // we don't want the reference (&) on the type
                    t = parameter.ParameterType.GetElementType();
                    AddType(typeset, t);
                }
            }

            if (!method.HasBody)
            {
                return;
            }

            MethodBody body = method.Body;

            if (body.HasVariables)
            {
                // add every type of variables we use
                foreach (VariableDefinition variable in body.Variables)
                {
                    t = variable.VariableType;
                    AddType(typeset, t);
                }
            }

            // add every type we create or refer to (e.g. loading fields from an enum)
            foreach (Instruction ins in body.Instructions)
            {
                if (ins.Operand == null)
                {
                    continue;
                }

                t = ins.Operand as TypeReference;
                if (t == null)
                {
                    MethodReference m = ins.Operand as MethodReference;
                    if (m != null)
                    {
                        t = m.DeclaringType;
                        GenericInstanceType generic = (t as GenericInstanceType);
                        if (generic != null)
                        {
                            t = generic.GetElementType();
                        }
                    }
                    else
                    {
                        FieldReference f = ins.Operand as FieldReference;
                        if (f != null)
                        {
                            t = f.DeclaringType;
                        }
                    }
                }

                if (t != null)
                {
                    AddType(typeset, t);
                }
            }
        }
Пример #33
0
        public static void OptimizeMacros(this MethodBody self)
        {
            if (self == null)
            {
                throw new ArgumentNullException("self");
            }

            var method = self.Method;

            foreach (var instruction in self.Instructions)
            {
                int index;
                switch (instruction.OpCode.Code)
                {
                case Code.Ldarg:
                    index = ((ParameterDefinition)instruction.Operand).Index;
                    if (index == -1 && instruction.Operand == self.ThisParameter)
                    {
                        index = 0;
                    }
                    else if (method.HasThis)
                    {
                        index++;
                    }

                    switch (index)
                    {
                    case 0:
                        MakeMacro(instruction, OpCodes.Ldarg_0);
                        break;

                    case 1:
                        MakeMacro(instruction, OpCodes.Ldarg_1);
                        break;

                    case 2:
                        MakeMacro(instruction, OpCodes.Ldarg_2);
                        break;

                    case 3:
                        MakeMacro(instruction, OpCodes.Ldarg_3);
                        break;

                    default:
                        if (index < 256)
                        {
                            ExpandMacro(instruction, OpCodes.Ldarg_S, instruction.Operand);
                        }
                        break;
                    }
                    break;

                case Code.Ldloc:
                    index = ((VariableDefinition)instruction.Operand).Index;
                    switch (index)
                    {
                    case 0:
                        MakeMacro(instruction, OpCodes.Ldloc_0);
                        break;

                    case 1:
                        MakeMacro(instruction, OpCodes.Ldloc_1);
                        break;

                    case 2:
                        MakeMacro(instruction, OpCodes.Ldloc_2);
                        break;

                    case 3:
                        MakeMacro(instruction, OpCodes.Ldloc_3);
                        break;

                    default:
                        if (index < 256)
                        {
                            ExpandMacro(instruction, OpCodes.Ldloc_S, instruction.Operand);
                        }
                        break;
                    }
                    break;

                case Code.Stloc:
                    index = ((VariableDefinition)instruction.Operand).Index;
                    switch (index)
                    {
                    case 0:
                        MakeMacro(instruction, OpCodes.Stloc_0);
                        break;

                    case 1:
                        MakeMacro(instruction, OpCodes.Stloc_1);
                        break;

                    case 2:
                        MakeMacro(instruction, OpCodes.Stloc_2);
                        break;

                    case 3:
                        MakeMacro(instruction, OpCodes.Stloc_3);
                        break;

                    default:
                        if (index < 256)
                        {
                            ExpandMacro(instruction, OpCodes.Stloc_S, instruction.Operand);
                        }
                        break;
                    }
                    break;

                case Code.Ldarga:
                    index = ((ParameterDefinition)instruction.Operand).Index;
                    if (index == -1 && instruction.Operand == self.ThisParameter)
                    {
                        index = 0;
                    }
                    else if (method.HasThis)
                    {
                        index++;
                    }
                    if (index < 256)
                    {
                        ExpandMacro(instruction, OpCodes.Ldarga_S, instruction.Operand);
                    }
                    break;

                case Code.Ldloca:
                    if (((VariableDefinition)instruction.Operand).Index < 256)
                    {
                        ExpandMacro(instruction, OpCodes.Ldloca_S, instruction.Operand);
                    }
                    break;

                case Code.Ldc_I4:
                    int i = (int)instruction.Operand;
                    switch (i)
                    {
                    case -1:
                        MakeMacro(instruction, OpCodes.Ldc_I4_M1);
                        break;

                    case 0:
                        MakeMacro(instruction, OpCodes.Ldc_I4_0);
                        break;

                    case 1:
                        MakeMacro(instruction, OpCodes.Ldc_I4_1);
                        break;

                    case 2:
                        MakeMacro(instruction, OpCodes.Ldc_I4_2);
                        break;

                    case 3:
                        MakeMacro(instruction, OpCodes.Ldc_I4_3);
                        break;

                    case 4:
                        MakeMacro(instruction, OpCodes.Ldc_I4_4);
                        break;

                    case 5:
                        MakeMacro(instruction, OpCodes.Ldc_I4_5);
                        break;

                    case 6:
                        MakeMacro(instruction, OpCodes.Ldc_I4_6);
                        break;

                    case 7:
                        MakeMacro(instruction, OpCodes.Ldc_I4_7);
                        break;

                    case 8:
                        MakeMacro(instruction, OpCodes.Ldc_I4_8);
                        break;

                    default:
                        if (i >= -128 && i < 128)
                        {
                            ExpandMacro(instruction, OpCodes.Ldc_I4_S, (sbyte)i);
                        }
                        break;
                    }
                    break;
                }
            }

            OptimizeBranches(self);
        }
Пример #34
0
 public InstructionValidator(MethodBody methodBody, Instruction instruction)
 {
     this.instruction = instruction;
     this.methodBody  = methodBody;
 }
Пример #35
0
 private void PushUnknownAndWarnAboutInvalidIL(Stack <StackSlot> stack, MethodBody methodBody, int offset)
 {
     WarnAboutInvalidILInMethod(methodBody, offset);
     PushUnknown(stack);
 }
Пример #36
0
        private static void EmitStringArrayEpilogue(MethodDefinition wrapper, ParameterDefinition parameter, MethodBody body,
                                                    ILProcessor il, GeneratedVariableIdentifier generatedPtrVar)
        {
            if (generatedPtrVar == null)
            {
                throw new ArgumentNullException(nameof(generatedPtrVar));
            }

            // Note: only works for string vectors (1d arrays).
            // We do not (and will probably never) support 2d or higher string arrays
            var free = wrapper.Module.ImportReference(TypeBindingsBase.Methods.First(m => m.Name == "FreeStringArrayPtr"));

            // FreeStringArrayPtr(string_array_ptr, string_array.Length)

            // load string_array_ptr
            il.Emit(OpCodes.Ldloc, generatedPtrVar.Definition.Index);

            // load string_array.Length
            il.Emit(OpCodes.Ldarg, parameter.Index);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);

            // call FreeStringArrayPtr
            il.Emit(OpCodes.Call, free);
        }
Пример #37
0
 public Tests()
 {
     this.MainClassType  = Type.GetType($"{@namespace}.{mainclass},{@namespace}");
     this.MainMethod     = this.MainClassType.GetMethod("Main", new[] { typeof(string[]) });
     this.MainMethodBody = this.MainMethod.GetMethodBody();
 }
Пример #38
0
        static void EmitStringEpilogue(MethodDefinition wrapper, ParameterDefinition parameter, MethodBody body, ILProcessor il)
        {
            var p    = parameter.ParameterType;
            var free = wrapper.Module.Import(TypeBindingsBase.Methods.First(m => m.Name == "FreeStringPtr"));

            // FreeStringPtr(ptr)
            var variable_name = parameter.Name + "_string_ptr";
            var v             = body.Variables.First(m => m.Name == variable_name);

            il.Emit(OpCodes.Ldloc, v.Index);
            il.Emit(OpCodes.Call, free);
        }
Пример #39
0
        public void GetMethodBody_Runtime()
        {
            MethodBody mb = typeof(AsyncCallback).GetMethod("Invoke").GetMethodBody();

            Assert.IsNull(mb);
        }
Пример #40
0
 protected virtual void WarnAboutInvalidILInMethod(MethodBody method, int ilOffset)
 {
 }
Пример #41
0
 protected override bool MatchesPredicate(MethodBody body, int instructionIndex)
 {
     return(!isVisitedMap[body.Instructions[instructionIndex]] && !IsWithinExceptionHandler(body.ExceptionHandlers, body.Instructions[instructionIndex]));
 }
Пример #42
0
        static void EmitStringArrayEpilogue(MethodDefinition wrapper, ParameterDefinition parameter, MethodBody body, ILProcessor il)
        {
            // Note: only works for string vectors (1d arrays).
            // We do not (and will probably never) support 2d or higher string arrays
            var p    = parameter.ParameterType;
            var free = wrapper.Module.Import(TypeBindingsBase.Methods.First(m => m.Name == "FreeStringArrayPtr"));

            // FreeStringArrayPtr(string_array_ptr, string_array.Length)
            var variable_name = parameter.Name + "_string_array_ptr";
            var v             = body.Variables.First(m => m.Name == variable_name);

            // load string_array_ptr
            il.Emit(OpCodes.Ldloc, v.Index);

            // load string_array.Length
            il.Emit(OpCodes.Ldarg, parameter.Index);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);

            // call FreeStringArrayPtr
            il.Emit(OpCodes.Call, free);
        }
Пример #43
0
 public MethodEditor(MethodDefinition method)
 {
     _body = method.Body;
     _il   = method.Body.GetILProcessor();
 }
Пример #44
0
        public static void SimplifyMacros(MethodBody self)
        {
            if (self == null)
            {
                throw new ArgumentNullException("self");
            }

            foreach (Instruction instruction in self.Instructions)
            {
                if (instruction.OpCode.OpCodeType != OpCodeType.Macro)
                {
                    continue;
                }

                switch (instruction.OpCode.Code)
                {
                case Code.Ldarg_0:
                    ExpandMacro(instruction, OpCodes.Ldarg, GetParameter(self, 0));
                    break;

                case Code.Ldarg_1:
                    ExpandMacro(instruction, OpCodes.Ldarg, GetParameter(self, 1));
                    break;

                case Code.Ldarg_2:
                    ExpandMacro(instruction, OpCodes.Ldarg, GetParameter(self, 2));
                    break;

                case Code.Ldarg_3:
                    ExpandMacro(instruction, OpCodes.Ldarg, GetParameter(self, 3));
                    break;

                case Code.Ldloc_0:
                    ExpandMacro(instruction, OpCodes.Ldloc, self.Variables [0]);
                    break;

                case Code.Ldloc_1:
                    ExpandMacro(instruction, OpCodes.Ldloc, self.Variables [1]);
                    break;

                case Code.Ldloc_2:
                    ExpandMacro(instruction, OpCodes.Ldloc, self.Variables [2]);
                    break;

                case Code.Ldloc_3:
                    ExpandMacro(instruction, OpCodes.Ldloc, self.Variables [3]);
                    break;

                case Code.Stloc_0:
                    ExpandMacro(instruction, OpCodes.Stloc, self.Variables [0]);
                    break;

                case Code.Stloc_1:
                    ExpandMacro(instruction, OpCodes.Stloc, self.Variables [1]);
                    break;

                case Code.Stloc_2:
                    ExpandMacro(instruction, OpCodes.Stloc, self.Variables [2]);
                    break;

                case Code.Stloc_3:
                    ExpandMacro(instruction, OpCodes.Stloc, self.Variables [3]);
                    break;

                case Code.Ldarg_S:
                    instruction.OpCode = OpCodes.Ldarg;
                    break;

                case Code.Ldarga_S:
                    instruction.OpCode = OpCodes.Ldarga;
                    break;

                case Code.Starg_S:
                    instruction.OpCode = OpCodes.Starg;
                    break;

                case Code.Ldloc_S:
                    instruction.OpCode = OpCodes.Ldloc;
                    break;

                case Code.Ldloca_S:
                    instruction.OpCode = OpCodes.Ldloca;
                    break;

                case Code.Stloc_S:
                    instruction.OpCode = OpCodes.Stloc;
                    break;

                case Code.Ldc_I4_M1:
                    ExpandMacro(instruction, OpCodes.Ldc_I4, -1);
                    break;

                case Code.Ldc_I4_0:
                    ExpandMacro(instruction, OpCodes.Ldc_I4, 0);
                    break;

                case Code.Ldc_I4_1:
                    ExpandMacro(instruction, OpCodes.Ldc_I4, 1);
                    break;

                case Code.Ldc_I4_2:
                    ExpandMacro(instruction, OpCodes.Ldc_I4, 2);
                    break;

                case Code.Ldc_I4_3:
                    ExpandMacro(instruction, OpCodes.Ldc_I4, 3);
                    break;

                case Code.Ldc_I4_4:
                    ExpandMacro(instruction, OpCodes.Ldc_I4, 4);
                    break;

                case Code.Ldc_I4_5:
                    ExpandMacro(instruction, OpCodes.Ldc_I4, 5);
                    break;

                case Code.Ldc_I4_6:
                    ExpandMacro(instruction, OpCodes.Ldc_I4, 6);
                    break;

                case Code.Ldc_I4_7:
                    ExpandMacro(instruction, OpCodes.Ldc_I4, 7);
                    break;

                case Code.Ldc_I4_8:
                    ExpandMacro(instruction, OpCodes.Ldc_I4, 8);
                    break;

                case Code.Ldc_I4_S:
                    ExpandMacro(instruction, OpCodes.Ldc_I4, (int)(sbyte)instruction.Operand);
                    break;

                case Code.Br_S:
                    instruction.OpCode = OpCodes.Br;
                    break;

                case Code.Brfalse_S:
                    instruction.OpCode = OpCodes.Brfalse;
                    break;

                case Code.Brtrue_S:
                    instruction.OpCode = OpCodes.Brtrue;
                    break;

                case Code.Beq_S:
                    instruction.OpCode = OpCodes.Beq;
                    break;

                case Code.Bge_S:
                    instruction.OpCode = OpCodes.Bge;
                    break;

                case Code.Bgt_S:
                    instruction.OpCode = OpCodes.Bgt;
                    break;

                case Code.Ble_S:
                    instruction.OpCode = OpCodes.Ble;
                    break;

                case Code.Blt_S:
                    instruction.OpCode = OpCodes.Blt;
                    break;

                case Code.Bne_Un_S:
                    instruction.OpCode = OpCodes.Bne_Un;
                    break;

                case Code.Bge_Un_S:
                    instruction.OpCode = OpCodes.Bge_Un;
                    break;

                case Code.Bgt_Un_S:
                    instruction.OpCode = OpCodes.Bgt_Un;
                    break;

                case Code.Ble_Un_S:
                    instruction.OpCode = OpCodes.Ble_Un;
                    break;

                case Code.Blt_Un_S:
                    instruction.OpCode = OpCodes.Blt_Un;
                    break;

                case Code.Leave_S:
                    instruction.OpCode = OpCodes.Leave;
                    break;
                }
            }
        }
Пример #45
0
        static void EmitParameterEpilogues(MethodDefinition wrapper, MethodDefinition native, MethodBody body, ILProcessor il)
        {
            foreach (var p in wrapper.Parameters)
            {
                if (p.ParameterType.Name == "StringBuilder")
                {
                    EmitStringBuilderEpilogue(wrapper, native, p, body, il);
                }

                if (!p.ParameterType.IsArray && p.ParameterType.Name == "String")
                {
                    EmitStringEpilogue(wrapper, p, body, il);
                }

                if (p.ParameterType.IsArray && p.ParameterType.GetElementType().Name == "String")
                {
                    EmitStringArrayEpilogue(wrapper, p, body, il);
                }
            }
        }
Пример #46
0
 public void ReplaceByNop(MethodBody methodBody, Instruction instruction)
 {
     methodBody.GetILProcessor().Replace(instruction, Instruction.Create(OpCodes.Nop));
 }
Пример #47
0
        private static void EmitReturnTypeWrapper(MethodDefinition wrapper, MethodDefinition native, MethodBody body, ILProcessor il)
        {
            if (wrapper.Parameters.Count < native.Parameters.Count)
            {
                // Convenience wrapper. The result is stored in the last local variable
                il.Emit(OpCodes.Ldloc, body.Variables.Count - 1);
            }
            else if (wrapper.ReturnType != native.ReturnType)
            {
                if (wrapper.ReturnType.Name == "String")
                {
                    // String return-type wrapper
                    // return new string((sbyte*)((void*)GetString()));

                    var intptr_to_voidpointer = wrapper.Module.Import(mscorlib.MainModule.GetType("System.IntPtr").GetMethods()
                                                                      .First(m =>
                    {
                        return
                        (m.Name == "op_Explicit" &&
                         m.ReturnType.Name == "Void*");
                    }));

                    var string_constructor = wrapper.Module.Import(mscorlib.MainModule.GetType("System.String").GetConstructors()
                                                                   .First(m =>
                    {
                        var p = m.Parameters;
                        return(p.Count > 0 && p[0].ParameterType.Name == "SByte*");
                    }));

                    il.Emit(OpCodes.Call, intptr_to_voidpointer);
                    il.Emit(OpCodes.Newobj, string_constructor);
                }
                else if (wrapper.ReturnType.Resolve().IsEnum)
                {
                    // Nothing to do
                }
                else if (wrapper.ReturnType.Name == "Boolean" && native.ReturnType.Name == "Byte")
                {
                    // Nothing to do
                    // It appears that a byte with 1 = true (GL_TRUE) and 0 = false (GL_FALSE)
                    // can be reinterpreted as a bool without a problem.
                    // Todo: maybe we should return (value == 0 ? false : true) just to be
                    // on the safe side?
                }
                else
                {
                    Console.Error.WriteLine("Return wrapper for '{1}' not implemented yet ({0})", native.Name, wrapper.ReturnType.Name);
                }
            }
            else
            {
                // nothing to do, the native call leaves the return value
                // on the stack and we return that unmodified to the caller.
            }
        }
Пример #48
0
        private static GeneratedVariableIdentifier EmitStringArrayParameter(MethodDefinition wrapper, ParameterDefinition parameter, MethodBody body,
                                                                            ILProcessor il)
        {
            // string[] masrhaling:
            // IntPtr ptr = MarshalStringArrayToPtr(strings);
            // try { calli }
            // finally { FreeStringArrayPtr(ptr); }
            var marshal_str_array_to_ptr = wrapper.Module.ImportReference(TypeBindingsBase.Methods.First(m => m.Name == "MarshalStringArrayToPtr"));

            // IntPtr ptr;
            var variableDefinition = new VariableDefinition(TypeIntPtr);

            body.Variables.Add(variableDefinition);
            int generatedPointerVarIndex = body.Variables.Count - 1;

            GeneratedVariableIdentifier stringArrayPtrVar = new GeneratedVariableIdentifier(body, variableDefinition, parameter.Name + "_string_array_ptr");

            // ptr = MarshalStringArrayToPtr(strings);
            il.Emit(OpCodes.Call, marshal_str_array_to_ptr);
            il.Emit(OpCodes.Stloc, generatedPointerVarIndex);
            il.Emit(OpCodes.Ldloc, generatedPointerVarIndex);

            // The finally block will be emitted in the function epilogue

            return(stringArrayPtrVar);
        }
Пример #49
0
 public BasicBlockIterator(MethodBody methodBody)
 {
     _methodBranchTargets = methodBody.ComputeBranchTargets();
     _currentBlockIndex   = -1;
     _foundEndOfPrevBlock = true;
 }
Пример #50
0
        static void EmitConvenienceWrapper(MethodDefinition wrapper,
                                           MethodDefinition native, int difference, MethodBody body, ILProcessor il)
        {
            if (wrapper.Parameters.Count > 2)
            {
                // Todo: emit all parameters bar the last two
                throw new NotImplementedException();
            }

            if (wrapper.ReturnType.Name != "Void")
            {
                if (difference == 2)
                {
                    // Convert sized out-array/reference to return value, for example:
                    // void GenTextures(int n, int[] textures) -> int GenTexture()
                    // {
                    //  const int n = 1;
                    //  int buffers;
                    //  calli GenTextures(n, &textures);
                    //  return result;
                    // }
                    body.Variables.Add(new VariableDefinition(wrapper.ReturnType));
                    il.Emit(OpCodes.Ldc_I4, 1);                        // const int n = 1
                    il.Emit(OpCodes.Ldloca, body.Variables.Count - 1); // &buffers
                }
                else if (difference == 1)
                {
                    // Convert unsized out-array/reference to return value, for example:
                    // void GetBoolean(GetPName pname, out bool data) -> bool GetBoolean(GetPName pname)
                    // {
                    //   bool result;
                    //   GetBooleanv(pname, &result);
                    //   return result;
                    // }
                    body.Variables.Add(new VariableDefinition(wrapper.ReturnType));
                    EmitParameters(wrapper, native, body, il);
                    il.Emit(OpCodes.Ldloca, body.Variables.Count - 1);
                }
                else
                {
                    Console.Error.WriteLine("Unknown wrapper type for ({0})", native.Name);
                }
            }
            else
            {
                if (difference == 1)
                {
                    // Convert in-array/reference to single element, for example:
                    // void DeleteTextures(int n, ref int textures) -> void DeleteTexture(int texture)
                    // {
                    //   const int n = 1;
                    //   calli DeleteTextures(n, &textures);
                    // }
                    il.Emit(OpCodes.Ldc_I4, 1);                         // const int n = 1
                    il.Emit(OpCodes.Ldarga, wrapper.Parameters.Last()); // &textures
                }
                else
                {
                    Console.Error.WriteLine("Unknown wrapper type for ({0})", native.Name);
                }
            }
        }
Пример #51
0
        public void GetMethodBody_Abstract()
        {
            MethodBody mb = typeof(ICloneable).GetMethod("Clone").GetMethodBody();

            Assert.IsNull(mb);
        }
Пример #52
0
 public ControlFlowAnalysis(MethodBody methodBody)
 {
     this.methodBody             = methodBody;
     this.exceptionHandlersStart = new HashSet <string>();
 }
Пример #53
0
        static void EmitStringBuilderEpilogue(MethodDefinition wrapper, MethodDefinition native, ParameterDefinition parameter, MethodBody body, ILProcessor il)
        {
            var p = parameter.ParameterType;

            if (p.Name == "StringBuilder")
            {
                // void GetShaderInfoLog(..., StringBuilder foo)
                // try {
                //  foo_sb_ptr = Marshal.AllocHGlobal(sb.Capacity + 1); -- already emitted
                //  glGetShaderInfoLog(..., foo_sb_ptr); -- already emitted
                //  MarshalPtrToStringBuilder(foo_sb_ptr, foo);
                // }
                // finally {
                //  Marshal.FreeHGlobal(foo_sb_ptr);
                // }

                // Make sure we have imported BindingsBase::MasrhalPtrToStringBuilder and Marshal::FreeHGlobal
                var ptr_to_sb    = wrapper.Module.Import(TypeBindingsBase.Methods.First(m => m.Name == "MarshalPtrToStringBuilder"));
                var free_hglobal = wrapper.Module.Import(TypeMarshal.Methods.First(m => m.Name == "FreeHGlobal"));

                var block = new ExceptionHandler(ExceptionHandlerType.Finally);
                block.TryStart = body.Instructions[0];

                var variable_name = parameter.Name + " _sb_ptr";
                var v             = body.Variables.First(m => m.Name == variable_name);
                il.Emit(OpCodes.Ldloc, v.Index);
                il.Emit(OpCodes.Ldarg, parameter.Index);
                il.Emit(OpCodes.Call, ptr_to_sb);

                block.TryEnd       = body.Instructions.Last();
                block.HandlerStart = body.Instructions.Last();

                il.Emit(OpCodes.Ldloc, v.Index);
                il.Emit(OpCodes.Call, free_hglobal);

                block.HandlerEnd = body.Instructions.Last();
            }
        }
Пример #54
0
        static void EmitStringBuilderParameter(MethodDefinition method, ParameterDefinition parameter, MethodBody body, ILProcessor il)
        {
            var p = parameter.ParameterType;

            // void GetShaderInfoLog(..., StringBuilder foo)
            // IntPtr foo_sb_ptr;
            // try {
            //  foo_sb_ptr = Marshal.AllocHGlobal(sb.Capacity + 1);
            //  glGetShaderInfoLog(..., foo_sb_ptr);
            //  MarshalPtrToStringBuilder(foo_sb_ptr, sb);
            // }
            // finally {
            //  Marshal.FreeHGlobal(sb_ptr);
            // }
            // Make sure we have imported StringBuilder::Capacity and Marshal::AllocHGlobal
            var sb_get_capacity = method.Module.Import(TypeStringBuilder.Methods.First(m => m.Name == "get_Capacity"));
            var alloc_hglobal   = method.Module.Import(TypeMarshal.Methods.First(m => m.Name == "AllocHGlobal"));

            // IntPtr ptr;
            var variable_name = parameter.Name + " _sb_ptr";

            body.Variables.Add(new VariableDefinition(variable_name, TypeIntPtr));
            int index = body.Variables.Count - 1;

            // ptr = Marshal.AllocHGlobal(sb.Capacity + 1);
            il.Emit(OpCodes.Callvirt, sb_get_capacity);
            il.Emit(OpCodes.Call, alloc_hglobal);
            il.Emit(OpCodes.Stloc, index);
            il.Emit(OpCodes.Ldloc, index);

            // We'll emit the try-finally block in the epilogue implementation,
            // because we haven't yet emitted all necessary instructions here.
        }
Пример #55
0
        bool TryCoreCompile(MethodDefinition initComp, MethodDefinition initCompRuntime, ILRootNode rootnode, out Exception exception)
        {
            try {
                var body = new MethodBody(initComp);
                var il   = body.GetILProcessor();
                il.Emit(OpCodes.Nop);

                if (initCompRuntime != null)
                {
                    // Generating branching code for the Previewer
                    //	IL_0007:  call class [mscorlib]System.Func`2<class [mscorlib]System.Type,string> class [Xamarin.Forms.Xaml.Internals]Xamarin.Forms.Xaml.XamlLoader::get_XamlFileProvider()
                    //  IL_000c:  brfalse IL_0031
                    //  IL_0011:  call class [mscorlib]System.Func`2<class [mscorlib]System.Type,string> class [Xamarin.Forms.Xaml.Internals]Xamarin.Forms.Xaml.XamlLoader::get_XamlFileProvider()
                    //  IL_0016:  ldarg.0
                    //  IL_0017:  call instance class [mscorlib]System.Type object::GetType()
                    //  IL_001c:  callvirt instance !1 class [mscorlib]System.Func`2<class [mscorlib]System.Type, string>::Invoke(!0)
                    //  IL_0021:  brfalse IL_0031
                    //  IL_0026:  ldarg.0
                    //  IL_0027:  call instance void class Xamarin.Forms.Xaml.UnitTests.XamlLoaderGetXamlForTypeTests::__InitComponentRuntime()
                    //  IL_002c:  ret
                    //  IL_0031:  nop

                    var nop = Instruction.Create(OpCodes.Nop);

                    var getXamlFileProvider = body.Method.Module.ImportReference(body.Method.Module.ImportReference(typeof(Xamarin.Forms.Xaml.Internals.XamlLoader))
                                                                                 .Resolve()
                                                                                 .Properties.FirstOrDefault(pd => pd.Name == "XamlFileProvider")
                                                                                 .GetMethod);
                    il.Emit(OpCodes.Call, getXamlFileProvider);
                    il.Emit(OpCodes.Brfalse, nop);
                    il.Emit(OpCodes.Call, getXamlFileProvider);
                    il.Emit(OpCodes.Ldarg_0);
                    var getType = body.Method.Module.ImportReference(body.Method.Module.ImportReference(typeof(object))
                                                                     .Resolve()
                                                                     .Methods.FirstOrDefault(md => md.Name == "GetType"));
                    il.Emit(OpCodes.Call, getType);
                    var func = body.Method.Module.ImportReference(body.Method.Module.ImportReference(typeof(Func <Type, string>))
                                                                  .Resolve()
                                                                  .Methods.FirstOrDefault(md => md.Name == "Invoke"));
                    func = func.ResolveGenericParameters(body.Method.Module.ImportReference(typeof(Func <Type, string>)), body.Method.Module);
                    il.Emit(OpCodes.Callvirt, func);
                    il.Emit(OpCodes.Brfalse, nop);
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Call, initCompRuntime);
                    il.Emit(OpCodes.Ret);
                    il.Append(nop);
                }

                var visitorContext = new ILContext(il, body, body.Method.Module);

                rootnode.Accept(new XamlNodeVisitor((node, parent) => node.Parent = parent), null);
                rootnode.Accept(new ExpandMarkupsVisitor(visitorContext), null);
                rootnode.Accept(new PruneIgnoredNodesVisitor(), null);
                rootnode.Accept(new CreateObjectVisitor(visitorContext), null);
                rootnode.Accept(new SetNamescopesAndRegisterNamesVisitor(visitorContext), null);
                rootnode.Accept(new SetFieldVisitor(visitorContext), null);
                rootnode.Accept(new SetResourcesVisitor(visitorContext), null);
                rootnode.Accept(new SetPropertiesVisitor(visitorContext, true), null);

                il.Emit(OpCodes.Ret);
                initComp.Body = body;
                exception     = null;
                return(true);
            } catch (Exception e) {
                exception = e;
                return(false);
            }
        }
Пример #56
0
 static bool IsEmptyDefault(this MethodBody body)
 {
     return(body.Instructions.All(instruction => instruction.OpCode == OpCodes.Nop || instruction.OpCode == OpCodes.Ret));
 }
Пример #57
0
        static void EmitStringArrayParameter(MethodDefinition wrapper, ParameterDefinition parameter, MethodBody body, ILProcessor il)
        {
            var p = parameter.ParameterType;

            // string[] masrhaling:
            // IntPtr ptr = MarshalStringArrayToPtr(strings);
            // try { calli }
            // finally { FreeStringArrayPtr(ptr); }
            var marshal_str_array_to_ptr = wrapper.Module.Import(TypeBindingsBase.Methods.First(m => m.Name == "MarshalStringArrayToPtr"));

            // IntPtr ptr;
            var variable_name = parameter.Name + "_string_array_ptr";

            body.Variables.Add(new VariableDefinition(variable_name, TypeIntPtr));
            int index = body.Variables.Count - 1;

            // ptr = MarshalStringArrayToPtr(strings);
            il.Emit(OpCodes.Call, marshal_str_array_to_ptr);
            il.Emit(OpCodes.Stloc, index);
            il.Emit(OpCodes.Ldloc, index);

            // The finally block will be emitted in the function epilogue
        }
Пример #58
0
 private void CheckForInvalidStack(Stack <StackSlot> stack, int depthRequired, MethodBody method, int ilOffset)
 {
     if (stack.Count < depthRequired)
     {
         WarnAboutInvalidILInMethod(method, ilOffset);
         while (stack.Count < depthRequired)
         {
             stack.Push(new StackSlot());                       // Push dummy values to avoid crashes.
         }
         // Analysis of this method will be incorrect.
     }
 }
Пример #59
0
 public static void Emit(this MethodBody body, Action <ILProcessor> il)
 {
     il(body.GetILProcessor());
 }
Пример #60
0
        static int EmitParameters(MethodDefinition method, MethodDefinition native, MethodBody body, ILProcessor il)
        {
            int i;

            for (i = 0; i < method.Parameters.Count; i++)
            {
                var parameter = method.Parameters[i];
                var p         = method.Module.Import(method.Parameters[i].ParameterType);
                il.Emit(OpCodes.Ldarg, i);

                if (p.Name.Contains("Int32") && native.Parameters[i].ParameterType.Name.Contains("IntPtr"))
                {
                    // This is a convenience Int32 overload for an IntPtr (size_t) parameter.
                    // We need to convert the loaded argument to IntPtr.
                    il.Emit(OpCodes.Conv_I);
                }
                else if (p.Name == "StringBuilder")
                {
                    EmitStringBuilderParameter(method, parameter, body, il);
                }
                else if (p.Name == "String" && !p.IsArray)
                {
                    EmitStringParameter(method, parameter, body, il);
                }
                else if (p.IsByReference)
                {
                    body.Variables.Add(new VariableDefinition(new PinnedType(p)));
                    var index = body.Variables.Count - 1;
                    il.Emit(OpCodes.Stloc, index);
                    il.Emit(OpCodes.Ldloc, index);
                    il.Emit(OpCodes.Conv_I);
                }
                else if (p.IsArray)
                {
                    if (p.Name != method.Module.Import(typeof(string[])).Name)
                    {
                        // .Net treats 1d arrays differently than higher rank arrays.
                        // 1d arrays are directly supported by instructions such as ldlen and ldelema.
                        // Higher rank arrays must be accessed through System.Array methods such as get_Length.
                        // 1d array:
                        //    check array is not null
                        //    check ldlen array > 0
                        //    ldc.i4.0
                        //    ldelema
                        // 2d array:
                        //    check array is not null
                        //    check array.get_Length() > 0
                        //    ldc.i4.0
                        //    ldc.i4.0
                        //    call instance T& T[0..., 0...]::Address(int32, int32)
                        // Mono treats everything as a 1d array.
                        // Interestingly, the .Net approach works on both Mono and .Net.
                        // The Mono approach fails when using high-rank arrays on .Net.
                        // We should report a bug to http://bugzilla.xamarin.com

                        // Pin the array and pass the address
                        // of its first element.
                        var array        = (ArrayType)p;
                        var element_type = p.GetElementType();
                        body.Variables.Add(new VariableDefinition(new PinnedType(new ByReferenceType(element_type))));
                        int pinned_index = body.Variables.Count - 1;

                        var empty = il.Create(OpCodes.Ldc_I4, 0);
                        var pin   = il.Create(OpCodes.Ldarg, i);
                        var end   = il.Create(OpCodes.Stloc, pinned_index);

                        // if (array == null) goto empty
                        il.Emit(OpCodes.Brfalse, empty);

                        // else if (array.Length != 0) goto pin
                        il.Emit(OpCodes.Ldarg, i);
                        if (array.Rank == 1)
                        {
                            il.Emit(OpCodes.Ldlen);
                            il.Emit(OpCodes.Conv_I4);
                        }
                        else
                        {
                            var get_length = method.Module.Import(
                                mscorlib.MainModule.GetType("System.Array").Methods.First(m => m.Name == "get_Length"));
                            il.Emit(OpCodes.Callvirt, get_length);
                        }
                        il.Emit(OpCodes.Brtrue, pin);

                        // empty: IntPtr ptr = IntPtr.Zero
                        il.Append(empty);
                        il.Emit(OpCodes.Conv_U);
                        il.Emit(OpCodes.Br, end);

                        // pin: &array[0]
                        il.Append(pin);
                        if (array.Rank == 1)
                        {
                            // 1d array (vector), address is taken by ldelema
                            il.Emit(OpCodes.Ldc_I4, 0);
                            il.Emit(OpCodes.Ldelema, element_type);
                        }
                        else
                        {
                            // 2d-3d array, address must be taken as follows:
                            // call instance T& T[0..., 0..., 0...]::Address(int, int, int)
                            ByReferenceType t_ref       = array.ElementType.MakeByReferenceType();
                            MethodReference get_address = new MethodReference("Address", t_ref, array);
                            for (int r = 0; r < array.Rank; r++)
                            {
                                get_address.Parameters.Add(new ParameterDefinition(TypeInt32));
                            }
                            get_address.HasThis = true;

                            // emit the get_address call
                            for (int r = 0; r < array.Rank; r++)
                            {
                                il.Emit(OpCodes.Ldc_I4, 0);
                            }
                            il.Emit(OpCodes.Call, get_address);
                        }

                        // end: fixed (IntPtr ptr = &array[0])
                        il.Append(end);
                        il.Emit(OpCodes.Ldloc, pinned_index);
                        il.Emit(OpCodes.Conv_I);
                    }
                    else
                    {
                        EmitStringArrayParameter(method, parameter, body, il);
                    }
                }
            }
            return(i);
        }