File: Compiler\Dataflow\ScannerExtensions.cs
Web Access
Project: src\src\runtime\src\coreclr\tools\aot\ILCompiler.Compiler\ILCompiler.Compiler.csproj (ILCompiler.Compiler)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;

using Internal.IL;

namespace ILCompiler.Dataflow
{
    internal static class ScannerExtensions
    {
        public static bool IsControlFlowInstruction(this ILOpcode opcode)
        {
            switch (opcode)
            {
                case ILOpcode.br_s:
                case ILOpcode.br:
                case ILOpcode.brfalse_s:
                case ILOpcode.brtrue_s:
                case ILOpcode.beq_s:
                case ILOpcode.bge_s:
                case ILOpcode.bgt_s:
                case ILOpcode.ble_s:
                case ILOpcode.blt_s:
                case ILOpcode.bne_un_s:
                case ILOpcode.bge_un_s:
                case ILOpcode.bgt_un_s:
                case ILOpcode.ble_un_s:
                case ILOpcode.blt_un_s:
                case ILOpcode.brfalse:
                case ILOpcode.brtrue:
                case ILOpcode.beq:
                case ILOpcode.bge:
                case ILOpcode.bgt:
                case ILOpcode.ble:
                case ILOpcode.blt:
                case ILOpcode.bne_un:
                case ILOpcode.bge_un:
                case ILOpcode.bgt_un:
                case ILOpcode.ble_un:
                case ILOpcode.blt_un:
                case ILOpcode.switch_:
                case ILOpcode.leave:
                case ILOpcode.leave_s:
                case ILOpcode.endfilter:
                case ILOpcode.endfinally:
                case ILOpcode.throw_:
                case ILOpcode.rethrow:
                    return true;
            }
            return false;
        }

        public static HashSet<int> ComputeBranchTargets(this MethodIL methodBody)
        {
            HashSet<int> branchTargets = new HashSet<int>();
            var reader = new ILReader(methodBody.GetILBytes());
            while (reader.HasNext)
            {
                ILOpcode opcode = reader.ReadILOpcode();
                if (opcode >= ILOpcode.br_s && opcode <= ILOpcode.blt_un)
                {
                    branchTargets.Add(reader.ReadBranchDestination(opcode));
                }
                else if (opcode == ILOpcode.switch_)
                {
                    uint count = reader.ReadILUInt32();
                    int jmpBase = reader.Offset + (int)(4 * count);
                    for (uint i = 0; i < count; i++)
                    {
                        branchTargets.Add((int)reader.ReadILUInt32() + jmpBase);
                    }
                }
                else
                {
                    reader.Skip(opcode);
                }
            }
            foreach (ILExceptionRegion einfo in methodBody.GetExceptionRegions())
            {
                if (einfo.Kind == ILExceptionRegionKind.Filter)
                {
                    branchTargets.Add(einfo.FilterOffset);
                }
                branchTargets.Add(einfo.HandlerOffset);
            }
            return branchTargets;
        }
    }
}