Пример #1
0
    private void SplitSinglePointOfReturn()
    {
        if (!_context.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")}");
        }
    }
Пример #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");
        }
    }