// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using Mono.Cecil.Cil;
namespace Mono.Linker.Dataflow
{
static class ScannerExtensions
{
public static bool IsControlFlowInstruction(in this OpCode opcode)
{
return opcode.FlowControl == FlowControl.Branch
|| opcode.FlowControl == FlowControl.Cond_Branch
|| (opcode.FlowControl == FlowControl.Return && opcode.Code != Code.Ret);
}
public static HashSet<int> ComputeBranchTargets(this MethodIL methodIL)
{
HashSet<int> branchTargets = new HashSet<int>();
foreach (Instruction operation in methodIL.Instructions)
{
if (!operation.OpCode.IsControlFlowInstruction())
continue;
object value = operation.Operand;
if (value is Instruction inst)
{
branchTargets.Add(inst.Offset);
}
else if (value is Instruction[] instructions)
{
foreach (Instruction switchLabel in instructions)
{
branchTargets.Add(switchLabel.Offset);
}
}
}
foreach (ExceptionHandler einfo in methodIL.ExceptionHandlers)
{
if (einfo.HandlerType == ExceptionHandlerType.Filter)
{
branchTargets.Add(einfo.FilterStart.Offset);
}
branchTargets.Add(einfo.HandlerStart.Offset);
}
return branchTargets;
}
}
}
|