Beispiel #1
0
        public void AddStringReference()
        {
            const string testConstant = "Lorem ipsum.";

            // set up temp assembly.
            var assembly    = Utilities.CreateTempNetAssembly();
            var tableStream = assembly.NetDirectory.MetadataHeader.GetStream <TableStream>();
            var methodTable = tableStream.GetTable <MethodDefinition>();
            var importer    = new ReferenceImporter(tableStream);

            // write code.
            var body = methodTable[0].MethodBody;

            body.Instructions.Clear();
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Ldstr, testConstant));
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Call,
                                                         importer.ImportMethod(typeof(Console).GetMethod("WriteLine", new Type[]
            {
                typeof(string)
            }))));
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Call,
                                                         importer.ImportMethod(typeof(Console).GetMethod("ReadKey", Type.EmptyTypes))));
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Pop));
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Ret));

            // build and validate.
            assembly    = Utilities.RebuildNetAssembly(assembly);
            methodTable = assembly.NetDirectory.MetadataHeader.GetStream <TableStream>().GetTable <MethodDefinition>();

            var operand = methodTable[0].MethodBody.Instructions[0].Operand;

            Assert.IsInstanceOfType(operand, typeof(string));
            Assert.AreEqual(testConstant, operand);
        }
Beispiel #2
0
 private void ReadInstructions()
 {
     Labels.Clear();
     _instructions.Clear();
     using (var memory = new MemoryStream(_msilBytes))
         using (var reader = new BinaryReader(memory))
             while (memory.Length > memory.Position)
             {
                 var opcodeOffset     = (int)memory.Position;
                 var instructionValue = (short)memory.ReadByte();
                 if (Prefixes.Contains(instructionValue))
                 {
                     instructionValue = (short)((instructionValue << 8) | memory.ReadByte());
                 }
                 if (!OpCodeLookup.TryGetValue(instructionValue, out OpCode opcode))
                 {
                     var msg = $"Unknown opcode {instructionValue:X}";
                     _log.Error(msg);
                     Debug.Assert(false, msg);
                     continue;
                 }
                 if (opcode.Size != memory.Position - opcodeOffset)
                 {
                     throw new Exception(
                               $"Opcode said it was {opcode.Size} but we read {memory.Position - opcodeOffset}");
                 }
                 var instruction = new MsilInstruction(opcode)
                 {
                     Offset = opcodeOffset
                 };
                 _instructions.Add(instruction);
                 instruction.Operand?.Read(this, reader);
             }
 }
Beispiel #3
0
        void MethodInstructions_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (labelInfo != null)
            {
                if (this.SelectedItem != null)
                {
                    Instruction     inst = SelectedInstruction;
                    MsilInstruction ins  = MsilInstruction.GetInstruction(inst.OpCode.ToString());

                    labelInfo.Text = string.Format(@"Instruction info:
Code: {0}", MethodInstructions.InstructionText(inst));

                    if (ins != null)
                    {
                        labelInfo.Text += string.Format(@"
ByteCode: {0}
Format: {1}
Description: {2}
", ins.ByteCode, ins.Format, ins.Description);
                    }
                }
                else
                {
                    labelInfo.Text = "Instruction info:";
                }
            }
        }
Beispiel #4
0
        public void BranchTest()
        {
            // set up temp assembly.
            var assembly    = Utilities.CreateTempNetAssembly();
            var tableStream = assembly.NetDirectory.MetadataHeader.GetStream <TableStream>();
            var methodTable = tableStream.GetTable <MethodDefinition>();

            // write code.
            var body = methodTable[0].MethodBody;

            body.Instructions.Clear();

            var target = MsilInstruction.Create(MsilOpCodes.Nop);

            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Nop));
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Br, target));
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Nop));
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Nop));
            body.Instructions.Add(target);
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Ret));

            body.CalculateOffsets();
            int offset = target.Offset;

            // build and validate.
            assembly    = Utilities.RebuildNetAssembly(assembly);
            methodTable = assembly.NetDirectory.MetadataHeader.GetStream <TableStream>().GetTable <MethodDefinition>();

            var operand = methodTable[0].MethodBody.Instructions[1].Operand;

            Assert.IsInstanceOfType(operand, typeof(MsilInstruction));
            Assert.AreEqual(((MsilInstruction)operand).Offset, offset);
        }
Beispiel #5
0
        public void VariablesTest()
        {
            // set up temp assembly.
            var assembly       = Utilities.CreateTempNetAssembly();
            var typeSystem     = assembly.NetDirectory.MetadataHeader.TypeSystem;
            var tableStream    = assembly.NetDirectory.MetadataHeader.GetStream <TableStream>();
            var methodTable    = tableStream.GetTable <MethodDefinition>();
            var signatureTable = tableStream.GetTable <StandAloneSignature>();

            var variable  = new VariableSignature(typeSystem.String);
            var variable2 = new VariableSignature(typeSystem.Int32);

            // create localvarsig.
            var localVarSig = new LocalVariableSignature();

            localVarSig.Variables.Add(variable);
            localVarSig.Variables.Add(variable2);
            var signature = new StandAloneSignature(localVarSig);

            signatureTable.Add(signature);

            // write code.
            var body = methodTable[0].MethodBody;

            body.Signature = signature;

            body.Instructions.Clear();
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Ldloc, variable));
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Pop));
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Ldloc, variable2));
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Pop));
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Ret));

            // build and validate.
            assembly    = Utilities.RebuildNetAssembly(assembly, true);
            methodTable = assembly.NetDirectory.MetadataHeader.GetStream <TableStream>().GetTable <MethodDefinition>();
            var newBody = methodTable[0].MethodBody;

            Assert.IsNotNull(newBody.Signature);
            Assert.IsInstanceOfType(newBody.Signature.Signature, typeof(LocalVariableSignature));

            var newLocalVarSig = (LocalVariableSignature)newBody.Signature.Signature;

            Assert.AreEqual(localVarSig.Variables.Count, newLocalVarSig.Variables.Count);

            for (int i = 0; i < localVarSig.Variables.Count; i++)
            {
                Utilities.ValidateType(localVarSig.Variables[i].VariableType, newLocalVarSig.Variables[i].VariableType);
            }

            Assert.IsInstanceOfType(newBody.Instructions[0].Operand, typeof(VariableSignature));
            Utilities.ValidateType(variable.VariableType,
                                   ((VariableSignature)newBody.Instructions[0].Operand).VariableType);

            Assert.IsInstanceOfType(newBody.Instructions[2].Operand, typeof(VariableSignature));
            Utilities.ValidateType(variable2.VariableType,
                                   ((VariableSignature)newBody.Instructions[2].Operand).VariableType);
        }
Beispiel #6
0
 private void ResolveLabels()
 {
     foreach (var label in Labels)
     {
         MsilInstruction target = FindInstruction(label.Key);
         Debug.Assert(target != null, $"No label for offset {label.Key}");
         target?.Labels?.Add(label.Value);
     }
 }
Beispiel #7
0
        private static void PatchDistributedUpdate(PatchContext ctx, MethodBase callerMethod)
        {
            var foundAnyIterate         = false;
            List <MsilInstruction> msil = PatchUtilities.ReadInstructions(callerMethod).ToList();

            for (var i = 0; i < msil.Count; i++)
            {
                MsilInstruction insn = msil[i];
                if ((insn.OpCode == OpCodes.Callvirt || insn.OpCode == OpCodes.Call) &&
                    IsDistributedIterate((insn.Operand as MsilOperandInline <MethodBase>)?.Value as MethodInfo))
                {
                    foundAnyIterate = true;
                    // Call to Iterate().  Backtrace up the instruction stack to find the statement creating the delegate.
                    var foundNewDel = false;
                    for (int j = i - 1; j >= 1; j--)
                    {
                        MsilInstruction insn2 = msil[j];
                        if (insn2.OpCode == OpCodes.Newobj)
                        {
                            Type ctorType = (insn2.Operand as MsilOperandInline <MethodBase>)?.Value?.DeclaringType;
                            if (ctorType != null && ctorType.IsGenericType &&
                                ctorType.GetGenericTypeDefinition() == typeof(Action <>))
                            {
                                foundNewDel = true;
                                // Find the instruction loading the function pointer this delegate is created with
                                MsilInstruction ldftn = msil[j - 1];
                                if (ldftn.OpCode != OpCodes.Ldftn ||
                                    !(ldftn.Operand is MsilOperandInline <MethodBase> targetMethod))
                                {
                                    _log.Error(
                                        $"Unable to find ldftn instruction for call to Iterate in {callerMethod.DeclaringType}#{callerMethod}");
                                }
                                else
                                {
                                    _log.Debug($"Patching {targetMethod.Value.DeclaringType}#{targetMethod.Value} for {callerMethod.DeclaringType}#{callerMethod}");
                                    PatchDistUpdateDel(ctx, targetMethod.Value);
                                }
                                break;
                            }
                        }
                    }
                    if (!foundNewDel)
                    {
                        _log.Error($"Unable to find new Action() call for Iterate in {callerMethod.DeclaringType}#{callerMethod}");
                    }
                }
            }
            if (!foundAnyIterate)
            {
                _log.Error($"Unable to find any calls to {_distributedUpdaterIterate} in {callerMethod.DeclaringType}#{callerMethod}");
            }
        }
Beispiel #8
0
        public void SwitchTest()
        {
            // set up temp assembly.
            var assembly    = Utilities.CreateTempNetAssembly();
            var tableStream = assembly.NetDirectory.MetadataHeader.GetStream <TableStream>();
            var methodTable = tableStream.GetTable <MethodDefinition>();

            // write code.
            var body = methodTable[0].MethodBody;

            body.Instructions.Clear();

            var targets = new[]
            {
                MsilInstruction.Create(MsilOpCodes.Nop),
                MsilInstruction.Create(MsilOpCodes.Nop),
                MsilInstruction.Create(MsilOpCodes.Nop),
                MsilInstruction.Create(MsilOpCodes.Nop),
            };
            var end = MsilInstruction.Create(MsilOpCodes.Ret);

            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Ldc_I4_1));
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Switch, targets));
            foreach (var target in targets)
            {
                body.Instructions.Add(target);
                body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Br, end));
            }

            body.Instructions.Add(end);

            body.CalculateOffsets();

            // build and validate.
            assembly    = Utilities.RebuildNetAssembly(assembly);
            methodTable = assembly.NetDirectory.MetadataHeader.GetStream <TableStream>().GetTable <MethodDefinition>();

            var operand = methodTable[0].MethodBody.Instructions[1].Operand;

            Assert.IsInstanceOfType(operand, typeof(MsilInstruction[]));
            var newTargets = (MsilInstruction[])operand;

            Assert.AreEqual(targets.Length, newTargets.Length);
            for (int i = 0; i < targets.Length; i++)
            {
                Assert.AreEqual(targets[i].Offset, newTargets[i].Offset);
            }
        }
Beispiel #9
0
        public void ImportUsingReflection()
        {
            // set up temp assembly.
            var assembly    = Utilities.CreateTempNetAssembly();
            var tableStream = assembly.NetDirectory.MetadataHeader.GetStream <TableStream>();
            var methodTable = tableStream.GetTable <MethodDefinition>();
            var importer    = new ReferenceImporter(tableStream);

            // import members.
            var originalWriteLine = typeof(Console).GetMethod("WriteLine", new Type[]
            {
                typeof(int)
            });
            var newWriteLine = importer.ImportMethod(originalWriteLine);

            Utilities.ValidateMethod(originalWriteLine, newWriteLine);

            var originalReadKey = typeof(Console).GetMethod("ReadKey", Type.EmptyTypes);
            var newReadKey      = importer.ImportMethod(originalReadKey);

            Utilities.ValidateMethod(originalReadKey, newReadKey);

            // write code.
            var body = methodTable[0].MethodBody;

            body.Instructions.Clear();
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Ldc_I4, 1337));
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Call, newWriteLine));
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Call, newReadKey));
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Pop));
            body.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Ret));

            // build and validate.
            assembly    = Utilities.RebuildNetAssembly(assembly);
            methodTable = assembly.NetDirectory.MetadataHeader.GetStream <TableStream>().GetTable <MethodDefinition>();

            var writeLineReference = methodTable[methodTable.Count - 1].MethodBody.Instructions[1].Operand;

            Assert.IsInstanceOfType(writeLineReference, typeof(MemberReference));
            Utilities.ValidateMethod(originalWriteLine, (MemberReference)writeLineReference);

            var readKeyReference = methodTable[methodTable.Count - 1].MethodBody.Instructions[2].Operand;

            Assert.IsInstanceOfType(readKeyReference, typeof(MemberReference));
            Utilities.ValidateMethod(originalReadKey, (MemberReference)readKeyReference);
        }
Beispiel #10
0
        private static IEnumerable <MsilInstruction> FoliageRenderFix(IEnumerable <MsilInstruction> src)
        {
            foreach (var call in src)
            {
                if ((call.OpCode == OpCodes.Callvirt || call.OpCode == OpCodes.Call) && call.Operand is MsilOperandInline <MethodBase> op &&
                    op.Value == _rcDrawAuto)
                {
                    var end      = new MsilLabel();
                    var noStereo = new MsilLabel();
                    yield return(new MsilInstruction(OpCodes.Call).InlineValue(_stereoRenderEnable.GetMethod));

                    yield return(new MsilInstruction(OpCodes.Brfalse).InlineTarget(noStereo));

                    yield return(new MsilInstruction(OpCodes.Dup));                                      // [... RC, RC]

                    yield return(new MsilInstruction(OpCodes.Call).InlineValue(_beginDrawGBufferPass));  // [... RC]

                    yield return(new MsilInstruction(OpCodes.Dup));                                      // [... RC, RC]

                    yield return(new MsilInstruction(call.OpCode).InlineValue(_rcDrawAuto));             // [... RC]

                    yield return(new MsilInstruction(OpCodes.Dup));                                      // [... RC, RC]

                    yield return(new MsilInstruction(OpCodes.Call).InlineValue(_switchDrawGBufferPass)); // [... RC]

                    yield return(new MsilInstruction(OpCodes.Dup));                                      // [... RC, RC]

                    yield return(new MsilInstruction(call.OpCode).InlineValue(_rcDrawAuto));             // [... RC]

                    yield return(new MsilInstruction(OpCodes.Call).InlineValue(_endDrawGBufferPass));    // [...]

                    yield return(new MsilInstruction(OpCodes.Br).InlineTarget(end));

                    call.Labels.Add(noStereo);
                    yield return(call);

                    var t = new MsilInstruction(OpCodes.Nop);
                    t.Labels.Add(end);
                    yield return(t);
                }
                else
                {
                    yield return(call);
                }
            }
        }
Beispiel #11
0
        public static WindowsAssembly CreateTempNetAssembly()
        {
            var assembly = NetAssemblyFactory.CreateAssembly("TempAssembly", false);

            assembly.NetDirectory.EntryPointToken = 0x06000001;
            var header      = assembly.NetDirectory.MetadataHeader;
            var tableStream = header.GetStream <TableStream>();

            var mainMethod = new MethodDefinition("Main", MethodAttributes.Static,
                                                  new MethodSignature(header.TypeSystem.Void));

            mainMethod.MetadataRow.Column6 = 1; // TODO: remove ParamList setter.
            mainMethod.MethodBody          = new MethodBody(mainMethod);
            mainMethod.MethodBody.Instructions.Add(MsilInstruction.Create(MsilOpCodes.Ret));
            tableStream.GetTable <MethodDefinition>().Add(mainMethod);
            return(assembly);
        }
Beispiel #12
0
        private static IEnumerable <MsilInstruction> FixDrawCalls(IEnumerable <MsilInstruction> src)
        {
            foreach (var call in src)
            {
                if ((call.OpCode == OpCodes.Callvirt || call.OpCode == OpCodes.Call) && call.Operand is MsilOperandInline <MethodBase> op &&
                    _stereoCallReplace.TryGetValue(op.Value, out MethodBase replaceTarget))
                {
                    var end      = new MsilLabel();
                    var noStereo = new MsilLabel();
                    yield return(new MsilInstruction(OpCodes.Call).InlineValue(_stereoRenderEnable.GetMethod));

                    yield return(new MsilInstruction(OpCodes.Brfalse).InlineTarget(noStereo));

                    yield return(new MsilInstruction(OpCodes.Call).InlineValue(replaceTarget));

                    yield return(new MsilInstruction(OpCodes.Br).InlineTarget(end));

                    call.Labels.Add(noStereo);
                    yield return(call);

                    var t = new MsilInstruction(OpCodes.Nop);
                    t.Labels.Add(end);
                    yield return(t);
                }
Beispiel #13
0
        private static IEnumerable <MsilInstruction> TranspileInitMultiplayer(IEnumerable <MsilInstruction> ins)
        {
            var findCtor = typeof(MyReplicationServer).GetConstructor(new[]
                                                                      { typeof(IReplicationServerCallback), typeof(EndpointId?), typeof(bool) });

            if (findCtor == null)
            {
                throw new InvalidOperationException(
                          "Couldn't find MyReplicationServer.ctor(IReplicationServerCallback, EndpointId?, bool)");
            }
            var replaceCtor = typeof(ThreadedReplicationServer).GetConstructor(new[]
                                                                               { typeof(IReplicationServerCallback), typeof(EndpointId?), typeof(bool) });

            if (replaceCtor == null)
            {
                throw new InvalidOperationException(
                          "Couldn't find ThreadedReplicationServer.ctor(IReplicationServerCallback, EndpointId?, bool)");
            }
            foreach (var k in ins)
            {
                if (k.Operand is MsilOperandInline <MethodBase> meth && meth.Value == findCtor)
                {
                    var repl = new MsilInstruction(k.OpCode);
                    repl.InlineValue(replaceCtor);
                    foreach (var l in k.Labels)
                    {
                        repl.Labels.Add(l);
                    }
                    yield return(repl);

                    continue;
                }

                yield return(k);
            }
        }
Beispiel #14
0
        private static IEnumerable <MsilInstruction> Transpile(IEnumerable <MsilInstruction> method)
        {
            var msil = method.ToList();

            for (var i = 0; i < msil.Count; i++)
            {
                if (msil[i].TryCatchOperations.All(x => x.Type != MsilTryCatchOperationType.BeginClauseBlock))
                {
                    continue;
                }

                for (; i < msil.Count; i++)
                {
                    if (msil[i].OpCode != OpCodes.Leave)
                    {
                        continue;
                    }

                    msil[i] = new MsilInstruction(OpCodes.Rethrow);
                    break;
                }
            }
            return(msil);
        }
Beispiel #15
0
        private static IEnumerable <MsilInstruction> TranspileSingleMethod(IEnumerable <MsilInstruction> insn, Func <Type, MsilLocal> __localCreator, MethodBase __methodBase)
        {
            MethodInfo profilerCall = null;

            foreach (var method in typeof(ProfilerData).GetMethods(BindingFlags.Static | BindingFlags.NonPublic |
                                                                   BindingFlags.Public))
            {
                if (IsSingleMethodProfilerCall(__methodBase, method))
                {
                    profilerCall = method;
                    break;
                }
            }
            if (profilerCall == null)
            {
                foreach (var method in typeof(ProfilerPatch).GetMethods(BindingFlags.Static | BindingFlags.NonPublic |
                                                                        BindingFlags.Public))
                {
                    if (IsSingleMethodProfilerCall(__methodBase, method))
                    {
                        profilerCall = method;
                        break;
                    }
                }
            }
            if (profilerCall == null)
            {
                _log.Warn($"Single method profiler for {__methodBase.DeclaringType?.FullName}#{__methodBase.Name} couldn't find a profiler call; will not operate");
            }

            FieldInfo stringPool = typeof(ProfilerPatch).GetField(nameof(_keyedStringPool),
                                                                  BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            if (stringPool == null)
            {
                _log.Warn($"Single method profiler for {__methodBase.DeclaringType?.FullName}#{__methodBase.Name} couldn't file string pool; will not operate");
            }


            if (profilerCall == null || stringPool == null)
            {
                foreach (var i in insn)
                {
                    yield return(i);
                }
                yield break;
            }

            // Reserve a keyed string.
            int stringKey = 0;

            lock (_keyedStringPoolLock)
            {
                while (_usedStrings >= _keyedStringPool.Length)
                {
                    Array.Resize(ref _keyedStringPool, Math.Max(64, _keyedStringPool.Length * 2));
                }
                stringKey = _usedStrings;
                _keyedStringPool[stringKey] = __methodBase.Name;
                _usedStrings++;
            }

            var profilerLocal = __localCreator(typeof(SlimProfilerEntry));

            _log.Debug($"Attaching profiling to {__methodBase?.DeclaringType?.FullName}#{__methodBase?.Name} with profiler call {profilerCall.DeclaringType?.FullName}#{profilerCall}");


            var labelNoProfiling    = new MsilLabel();
            var labelStoreProfiling = new MsilLabel();

            yield return(new MsilInstruction(OpCodes.Ldsfld).InlineValue(ProfilerData.FieldProfileSingleMethods));

            yield return(new MsilInstruction(OpCodes.Brfalse).InlineTarget(labelNoProfiling));

            { // if (ProfilerData.FieldProfileSingleMethods)
                foreach (var stub in EmitSingleMethodProfilerCall(__methodBase, profilerCall, stringPool, stringKey))
                {
                    yield return(stub);
                }
                yield return(new MsilInstruction(OpCodes.Br).InlineTarget(labelStoreProfiling));
            }
            { // else
                yield return(new MsilInstruction(OpCodes.Ldnull).LabelWith(labelNoProfiling));
            }
            yield return(new MsilInstruction(OpCodes.Dup).LabelWith(labelStoreProfiling)); // Duplicate profiler entry for brnull

            yield return(profilerLocal.AsValueStore());                                    // store the profiler entry for later

            var skipProfilerOne = new MsilLabel();

            yield return(new MsilInstruction(OpCodes.Brfalse).InlineTarget(skipProfilerOne));

            { // if (profiler != null)
                yield return(profilerLocal.AsValueLoad());

                yield return(new MsilInstruction(OpCodes.Call).InlineValue(ProfilerData.ProfilerEntryStart));
            }

            // consumes from the first Dup
            yield return(new MsilInstruction(OpCodes.Nop).LabelWith(skipProfilerOne));

            var skipMainMethod = new MsilLabel();

            foreach (var i in insn)
            {
                if (i.OpCode == OpCodes.Ret)
                {
                    MsilInstruction j = new MsilInstruction(OpCodes.Br).InlineTarget(skipMainMethod);
                    foreach (MsilLabel l in i.Labels)
                    {
                        j.Labels.Add(l);
                    }
                    yield return(j);
                }
                else
                {
                    yield return(i);
                }
            }

            var skipProfilerTwo = new MsilLabel();

            yield return(profilerLocal.AsValueLoad().LabelWith(skipMainMethod));

            yield return(new MsilInstruction(OpCodes.Brfalse).InlineTarget(skipProfilerTwo)); // Brfalse == Brnull

            {
                yield return(profilerLocal.AsValueLoad()); // stop the profiler

                yield return(new MsilInstruction(OpCodes.Call).InlineValue(ProfilerData.ProfilerEntryStop));
            }
            yield return(new MsilInstruction(OpCodes.Nop).LabelWith(skipProfilerTwo));
        }
Beispiel #16
0
        internal static void EmitMethod(IReadOnlyList <MsilInstruction> source, LoggingIlGenerator target)
        {
            var instructions = source.ToArray();
            var offsets      = new int[instructions.Length];
            // Calc worst case offsets
            {
                var j = 0;
                for (var i = 0; i < instructions.Length; i++)
                {
                    offsets[i] = j;
                    j         += instructions[i].MaxBytes;
                }
            }

            // Perform label markup
            var targets = new Dictionary <MsilLabel, int>();

            for (var i = 0; i < instructions.Length; i++)
            {
                foreach (var label in instructions[i].Labels)
                {
                    if (targets.TryGetValue(label, out var other))
                    {
                        _log.Warn($"Label {label} is applied to ({i}: {instructions[i]}) and ({other}: {instructions[other]})");
                    }
                    targets[label] = i;
                }
            }

            // Simplify branch instructions
            for (var i = 0; i < instructions.Length; i++)
            {
                var existing = instructions[i];
                if (existing.Operand is MsilOperandBrTarget brOperand && _longToShortBranch.TryGetValue(existing.OpCode, out var shortOpcode))
                {
                    var targetIndex = targets[brOperand.Target];
                    var delta       = offsets[targetIndex] - offsets[i];
                    if (sbyte.MinValue < delta && delta < sbyte.MaxValue)
                    {
                        instructions[i] = instructions[i].CopyWith(shortOpcode);
                    }
                }
            }

            for (var i = 0; i < instructions.Length; i++)
            {
                MsilInstruction il = instructions[i];
                foreach (var tro in il.TryCatchOperations)
                {
                    switch (tro.Type)
                    {
                    case MsilTryCatchOperationType.BeginExceptionBlock:
                        target.BeginExceptionBlock();
                        break;

                    case MsilTryCatchOperationType.BeginClauseBlock:
                        target.BeginCatchBlock(tro.CatchType);
                        break;

                    case MsilTryCatchOperationType.BeginFaultBlock:
                        target.BeginFaultBlock();
                        break;

                    case MsilTryCatchOperationType.BeginFinallyBlock:
                        target.BeginFinallyBlock();
                        break;

                    case MsilTryCatchOperationType.EndExceptionBlock:
                        target.EndExceptionBlock();
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }

                foreach (MsilLabel label in il.Labels)
                {
                    target.MarkLabel(label.LabelFor(target));
                }

                MsilInstruction ilNext = i < instructions.Length - 1 ? instructions[i + 1] : null;

                // Leave opcodes emitted by these:
                if (il.OpCode == OpCodes.Endfilter && ilNext != null &&
                    ilNext.TryCatchOperations.Any(x => x.Type == MsilTryCatchOperationType.BeginClauseBlock))
                {
                    continue;
                }
                if ((il.OpCode == OpCodes.Leave || il.OpCode == OpCodes.Leave_S) && ilNext != null &&
                    ilNext.TryCatchOperations.Any(x => x.Type == MsilTryCatchOperationType.EndExceptionBlock ||
                                                  x.Type == MsilTryCatchOperationType.BeginClauseBlock ||
                                                  x.Type == MsilTryCatchOperationType.BeginFaultBlock ||
                                                  x.Type == MsilTryCatchOperationType.BeginFinallyBlock))
                {
                    continue;
                }
                if ((il.OpCode == OpCodes.Leave || il.OpCode == OpCodes.Leave_S || il.OpCode == OpCodes.Endfinally) &&
                    ilNext != null && ilNext.TryCatchOperations.Any(x => x.Type == MsilTryCatchOperationType.EndExceptionBlock))
                {
                    continue;
                }
                if (il.OpCode == OpCodes.Endfinally && ilNext != null &&
                    ilNext.TryCatchOperations.Any(x => x.Type == MsilTryCatchOperationType.EndExceptionBlock))
                {
                    continue;
                }

                if (il.Operand != null)
                {
                    il.Operand.Emit(target);
                }
                else
                {
                    target.Emit(il.OpCode);
                }
            }
        }
 public MsilInstructionListViewItem(MsilInstruction instruction, byte[] bytes)
 {
     Instruction = instruction;
     Bytes       = bytes;
 }
        private static IEnumerable <MsilInstruction> MoveAmbientOcclusionOutOfLoop(
            IEnumerable <MsilInstruction> instructionStream)
        {
            var labelPosition        = new Dictionary <MsilLabel, int>();
            var body                 = instructionStream.ToList();
            var positionBeginAo      = -1;
            var positionEndAo        = -1;
            var positionAsFullscreen = -1;

            for (var i = 0; i < body.Count; i++)
            {
                var ins = body[i];
                foreach (var k in ins.Labels)
                {
                    labelPosition.Add(k, i);
                }
                if (ins.OpCode == OpCodes.Stsfld && ins.Operand is MsilOperandInline <FieldInfo> fieldInfo && fieldInfo.Value == _stereoRenderRegion &&
                    i > 0 && body[i - 1].IsConstIntLoad() && body[i - 1].GetConstInt() == (int)Types.StereoRenderRegion.Fullscreen)
                {
                    positionAsFullscreen = i;
                }
                if (ins.OpCode == OpCodes.Ldstr && ins.Operand is MsilOperandInline <string> inStr &&
                    inStr.Value.Equals("SSAO"))
                {
                    // Advance back up until we find the end of the previous block.
                    var j = i;
                    while (j-- > 0)
                    {
                        if (body[j].Operand is MsilOperandInline <MethodBase> operand &&
                            operand.Value == _gpuProfilerEndBlock)
                        {
                            positionBeginAo = j + 1;
                            break;
                        }
                    }
                    j = i;
                    MsilLabel endLabel = null;
                    while (++j < body.Count)
                    {
                        if (body[j].OpCode == OpCodes.Br || body[j].OpCode == OpCodes.Br_S)
                        {
                            endLabel = ((MsilOperandBrTarget)body[j].Operand).Target;
                            break;
                        }
                    }
                    while (++j < body.Count)
                    {
                        if (body[j].Labels.Contains(endLabel))
                        {
                            positionEndAo = j;
                        }
                    }
                }
            }
            if (positionEndAo == -1 || positionBeginAo == -1 || positionAsFullscreen == -1)
            {
                foreach (var k in body)
                {
                    yield return(k);
                }
                yield break;
            }

            for (var i = 0; i < body.Count; i++)
            {
                if (i < positionBeginAo)
                {
                    yield return(body[i]);
                }
                else if (i >= positionEndAo)
                {
                    yield return(body[i]);
                }
                if (i == positionAsFullscreen)
                {
                    var endOfAo = new MsilLabel();
                    for (var j = positionBeginAo; j < positionEndAo; j++)
                    {
                        if (body[j].Operand is MsilOperandBrTarget target)
                        {
                            var tiv = labelPosition[target.Target];
                            if (tiv == positionEndAo)
                            {
                                yield return(body[j].CopyWith(body[j].OpCode).InlineTarget(endOfAo));

                                continue;
                            }
                            else if (tiv > positionEndAo || tiv < positionBeginAo)
                            {
                                _log.Warn($"Unable to figure out how to deal with label {target.Target} at {tiv}.  AO data is from {positionBeginAo}-{positionEndAo}");
                            }
                        }
                        yield return(body[j]);
                    }
                    var temp = new MsilInstruction(OpCodes.Nop);
                    temp.Labels.Add(endOfAo);
                    yield return(temp);
                }
            }
        }
Beispiel #19
0
        internal static void EmitMethod(IReadOnlyList <MsilInstruction> instructions, LoggingIlGenerator target)
        {
            for (var i = 0; i < instructions.Count; i++)
            {
                MsilInstruction il = instructions[i];
                if (il.TryCatchOperation != null)
                {
                    switch (il.TryCatchOperation.Type)
                    {
                    case MsilTryCatchOperationType.BeginExceptionBlock:
                        target.BeginExceptionBlock();
                        break;

                    case MsilTryCatchOperationType.BeginClauseBlock:
                        target.BeginCatchBlock(il.TryCatchOperation.CatchType);
                        break;

                    case MsilTryCatchOperationType.BeginFaultBlock:
                        target.BeginFaultBlock();
                        break;

                    case MsilTryCatchOperationType.BeginFinallyBlock:
                        target.BeginFinallyBlock();
                        break;

                    case MsilTryCatchOperationType.EndExceptionBlock:
                        target.EndExceptionBlock();
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }

                foreach (MsilLabel label in il.Labels)
                {
                    target.MarkLabel(label.LabelFor(target));
                }

                MsilInstruction ilNext = i < instructions.Count - 1 ? instructions[i + 1] : null;

                // Leave opcodes emitted by these:
                if (il.OpCode == OpCodes.Endfilter && ilNext?.TryCatchOperation?.Type ==
                    MsilTryCatchOperationType.BeginClauseBlock)
                {
                    continue;
                }
                if ((il.OpCode == OpCodes.Leave || il.OpCode == OpCodes.Leave_S) &&
                    (ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.EndExceptionBlock ||
                     ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.BeginClauseBlock ||
                     ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.BeginFaultBlock ||
                     ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.BeginFinallyBlock))
                {
                    continue;
                }
                if ((il.OpCode == OpCodes.Leave || il.OpCode == OpCodes.Leave_S || il.OpCode == OpCodes.Endfinally) &&
                    ilNext?.TryCatchOperation?.Type == MsilTryCatchOperationType.EndExceptionBlock)
                {
                    continue;
                }

                if (il.Operand != null)
                {
                    il.Operand.Emit(target);
                }
                else
                {
                    target.Emit(il.OpCode);
                }
            }
        }