Example #1
0
        private void SplitSinglePointOfReturn()
        {
            if (!Module.IsDebugBuild())
            {
                return;
            }

            var lastRetInstruction = Instructions.LastOrDefault();

            if (lastRetInstruction?.OpCode != OpCodes.Ret)
            {
                return;
            }

            var ldlocInstruction = lastRetInstruction.Previous;

            if (ldlocInstruction?.OpCode != OpCodes.Ldloc)
            {
                return;
            }

            var refsToLdloc = Instructions.Where(i => i.Operand == ldlocInstruction).ToList();

            var leaveOriginalReturnPoint = false;
            var insertedRet = 0;

            foreach (var brInstruction in refsToLdloc)
            {
                var stlocInstruction = brInstruction.Previous;

                if (brInstruction.OpCode == OpCodes.Br &&
                    stlocInstruction != null &&
                    stlocInstruction.OpCode == OpCodes.Stloc &&
                    stlocInstruction.Operand == ldlocInstruction.Operand)
                {
                    _il.Remove(stlocInstruction);
                    _il.Replace(brInstruction, Instruction.Create(OpCodes.Ret));
                    ++insertedRet;
                }
                else
                {
                    leaveOriginalReturnPoint = true;
                }
            }

            if (!leaveOriginalReturnPoint)
            {
                // If the compiler ever stops emitting no-op branch instructions
                var stlocInstruction = ldlocInstruction.PrevSkipNops();
                if (stlocInstruction != null && stlocInstruction.OpCode == OpCodes.Stloc && stlocInstruction.Operand == ldlocInstruction.Operand)
                {
                    _il.Remove(stlocInstruction);
                }

                _il.RemoveNopsAround(ldlocInstruction);
                _il.Remove(ldlocInstruction);

                if (lastRetInstruction.Previous?.OpCode == OpCodes.Ret)
                {
                    _il.Remove(lastRetInstruction);
                }
            }

            if (insertedRet > 0)
            {
                _log.Debug($"Split single point of return: {insertedRet} ret inserted, original {(leaveOriginalReturnPoint ? "left" : "removed")}");
            }
        }
Example #2
0
        public string ConsumeArgString(Instruction instruction)
        {
            switch (instruction.OpCode.Code)
            {
            case Code.Ldstr:
                _il.Remove(instruction);
                return((string)instruction.Operand);

            case Code.Ldnull:
                throw new InstructionWeavingException(instruction, "A non-null string literal is expected");

            default:
                throw UnexpectedInstruction(instruction, "a string literal");
            }
        }