mirror of
https://github.com/AssetRipper/Cpp2IL.git
synced 2026-11-13 04:26:33 -10:00
63 lines
1.8 KiB
C#
63 lines
1.8 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using Cpp2IL.Core.ISIL;
|
|
|
|
namespace Cpp2IL.Core.Graphs;
|
|
|
|
public class Block : ISIL.IOperand
|
|
{
|
|
public BlockType BlockType { get; set; } = BlockType.Unknown;
|
|
public List<Block> Predecessors = [];
|
|
public List<Block> Successors = [];
|
|
|
|
public List<IOperand> Use = [];
|
|
public List<IOperand> Def = [];
|
|
|
|
public List<Instruction> Instructions = [];
|
|
|
|
public int ID { get; set; } = -1;
|
|
|
|
public bool Dirty { get; set; }
|
|
public bool Visited = false;
|
|
|
|
public override string ToString()
|
|
{
|
|
StringBuilder stringBuilder = new StringBuilder();
|
|
stringBuilder.AppendLine($"{BlockType} {ID}");
|
|
stringBuilder.AppendLine();
|
|
foreach (var instruction in Instructions)
|
|
{
|
|
stringBuilder.AppendLine(instruction.ToString());
|
|
}
|
|
|
|
return stringBuilder.ToString();
|
|
}
|
|
|
|
public void AddInstruction(Instruction instruction) => Instructions.Add(instruction);
|
|
|
|
public void CalculateBlockType()
|
|
{
|
|
if (Instructions.Count <= 0)
|
|
return;
|
|
|
|
var instruction = Instructions.Last();
|
|
|
|
BlockType = instruction.OpCode switch
|
|
{
|
|
OpCode.Jump => BlockType.OneWay,
|
|
OpCode.ConditionalJump => BlockType.TwoWay,
|
|
OpCode.IndirectJump => BlockType.TailCall, //TODO this is wrong for switch statements but that's better than tail calls to virtual methods stopping the stack settling
|
|
OpCode.Call or OpCode.CallVoid => BlockType.Call,
|
|
OpCode.Return => BlockType.Return,
|
|
_ => BlockType.Fall,
|
|
};
|
|
|
|
if (BlockType == BlockType.Call && Successors.Count > 0)
|
|
{
|
|
if (Successors[0].BlockType == BlockType.Exit)
|
|
BlockType = BlockType.TailCall;
|
|
}
|
|
}
|
|
}
|