// 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;
}
}
}
|