mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-07-29 20:47:11 +02:00
Move solution and projects to src
This commit is contained in:
parent
cd124bda58
commit
cee7121058
3466 changed files with 55 additions and 55 deletions
311
src/ARMeilleure/Diagnostics/IRDumper.cs
Normal file
311
src/ARMeilleure/Diagnostics/IRDumper.cs
Normal file
|
@ -0,0 +1,311 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Diagnostics
|
||||
{
|
||||
class IRDumper
|
||||
{
|
||||
private const string Indentation = " ";
|
||||
|
||||
private int _indentLevel;
|
||||
|
||||
private readonly StringBuilder _builder;
|
||||
|
||||
private readonly Dictionary<Operand, string> _localNames;
|
||||
private readonly Dictionary<ulong, string> _symbolNames;
|
||||
|
||||
public IRDumper(int indent)
|
||||
{
|
||||
_indentLevel = indent;
|
||||
|
||||
_builder = new StringBuilder();
|
||||
|
||||
_localNames = new Dictionary<Operand, string>();
|
||||
_symbolNames = new Dictionary<ulong, string>();
|
||||
}
|
||||
|
||||
private void Indent()
|
||||
{
|
||||
_builder.EnsureCapacity(_builder.Capacity + _indentLevel * Indentation.Length);
|
||||
|
||||
for (int index = 0; index < _indentLevel; index++)
|
||||
{
|
||||
_builder.Append(Indentation);
|
||||
}
|
||||
}
|
||||
|
||||
private void IncreaseIndentation()
|
||||
{
|
||||
_indentLevel++;
|
||||
}
|
||||
|
||||
private void DecreaseIndentation()
|
||||
{
|
||||
_indentLevel--;
|
||||
}
|
||||
|
||||
private void DumpBlockName(BasicBlock block)
|
||||
{
|
||||
_builder.Append("block").Append(block.Index);
|
||||
}
|
||||
|
||||
private void DumpBlockHeader(BasicBlock block)
|
||||
{
|
||||
DumpBlockName(block);
|
||||
|
||||
if (block.Frequency == BasicBlockFrequency.Cold)
|
||||
{
|
||||
_builder.Append(" cold");
|
||||
}
|
||||
|
||||
if (block.SuccessorsCount > 0)
|
||||
{
|
||||
_builder.Append(" (");
|
||||
|
||||
for (int i = 0; i < block.SuccessorsCount; i++)
|
||||
{
|
||||
DumpBlockName(block.GetSuccessor(i));
|
||||
|
||||
if (i < block.SuccessorsCount - 1)
|
||||
{
|
||||
_builder.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
_builder.Append(')');
|
||||
}
|
||||
|
||||
_builder.Append(':');
|
||||
}
|
||||
|
||||
private void DumpOperand(Operand operand)
|
||||
{
|
||||
if (operand == default)
|
||||
{
|
||||
_builder.Append("<NULL>");
|
||||
return;
|
||||
}
|
||||
|
||||
_builder.Append(GetTypeName(operand.Type)).Append(' ');
|
||||
|
||||
switch (operand.Kind)
|
||||
{
|
||||
case OperandKind.LocalVariable:
|
||||
if (!_localNames.TryGetValue(operand, out string localName))
|
||||
{
|
||||
localName = $"%{_localNames.Count}";
|
||||
|
||||
_localNames.Add(operand, localName);
|
||||
}
|
||||
|
||||
_builder.Append(localName);
|
||||
break;
|
||||
|
||||
case OperandKind.Register:
|
||||
Register reg = operand.GetRegister();
|
||||
|
||||
switch (reg.Type)
|
||||
{
|
||||
case RegisterType.Flag: _builder.Append('b'); break;
|
||||
case RegisterType.FpFlag: _builder.Append('f'); break;
|
||||
case RegisterType.Integer: _builder.Append('r'); break;
|
||||
case RegisterType.Vector: _builder.Append('v'); break;
|
||||
}
|
||||
|
||||
_builder.Append(reg.Index);
|
||||
break;
|
||||
|
||||
case OperandKind.Constant:
|
||||
string symbolName = Symbols.Get(operand.Value);
|
||||
|
||||
if (symbolName != null && !_symbolNames.ContainsKey(operand.Value))
|
||||
{
|
||||
_symbolNames.Add(operand.Value, symbolName);
|
||||
}
|
||||
|
||||
_builder.Append("0x").Append(operand.Value.ToString("X"));
|
||||
break;
|
||||
|
||||
case OperandKind.Memory:
|
||||
var memOp = operand.GetMemory();
|
||||
|
||||
_builder.Append('[');
|
||||
|
||||
DumpOperand(memOp.BaseAddress);
|
||||
|
||||
if (memOp.Index != default)
|
||||
{
|
||||
_builder.Append(" + ");
|
||||
|
||||
DumpOperand(memOp.Index);
|
||||
|
||||
switch (memOp.Scale)
|
||||
{
|
||||
case Multiplier.x2: _builder.Append("*2"); break;
|
||||
case Multiplier.x4: _builder.Append("*4"); break;
|
||||
case Multiplier.x8: _builder.Append("*8"); break;
|
||||
}
|
||||
}
|
||||
|
||||
if (memOp.Displacement != 0)
|
||||
{
|
||||
_builder.Append(" + 0x").Append(memOp.Displacement.ToString("X"));
|
||||
}
|
||||
|
||||
_builder.Append(']');
|
||||
break;
|
||||
|
||||
default:
|
||||
_builder.Append(operand.Type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void DumpNode(ControlFlowGraph cfg, Operation node)
|
||||
{
|
||||
for (int index = 0; index < node.DestinationsCount; index++)
|
||||
{
|
||||
DumpOperand(node.GetDestination(index));
|
||||
|
||||
if (index == node.DestinationsCount - 1)
|
||||
{
|
||||
_builder.Append(" = ");
|
||||
}
|
||||
else
|
||||
{
|
||||
_builder.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
switch (node)
|
||||
{
|
||||
case Operation operation:
|
||||
if (operation.Instruction == Instruction.Phi)
|
||||
{
|
||||
PhiOperation phi = operation.AsPhi();
|
||||
|
||||
_builder.Append("Phi ");
|
||||
|
||||
for (int index = 0; index < phi.SourcesCount; index++)
|
||||
{
|
||||
_builder.Append('(');
|
||||
|
||||
DumpBlockName(phi.GetBlock(cfg, index));
|
||||
|
||||
_builder.Append(": ");
|
||||
|
||||
DumpOperand(phi.GetSource(index));
|
||||
|
||||
_builder.Append(')');
|
||||
|
||||
if (index < phi.SourcesCount - 1)
|
||||
{
|
||||
_builder.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
bool comparison = false;
|
||||
|
||||
_builder.Append(operation.Instruction);
|
||||
|
||||
if (operation.Instruction == Instruction.Extended)
|
||||
{
|
||||
_builder.Append('.').Append(operation.Intrinsic);
|
||||
}
|
||||
else if (operation.Instruction == Instruction.BranchIf ||
|
||||
operation.Instruction == Instruction.Compare)
|
||||
{
|
||||
comparison = true;
|
||||
}
|
||||
|
||||
_builder.Append(' ');
|
||||
|
||||
for (int index = 0; index < operation.SourcesCount; index++)
|
||||
{
|
||||
Operand source = operation.GetSource(index);
|
||||
|
||||
if (index < operation.SourcesCount - 1)
|
||||
{
|
||||
DumpOperand(source);
|
||||
|
||||
_builder.Append(", ");
|
||||
}
|
||||
else if (comparison)
|
||||
{
|
||||
_builder.Append((Comparison)source.AsInt32());
|
||||
}
|
||||
else
|
||||
{
|
||||
DumpOperand(source);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (_symbolNames.Count == 1)
|
||||
{
|
||||
_builder.Append(" ;; ").Append(_symbolNames.First().Value);
|
||||
}
|
||||
else if (_symbolNames.Count > 1)
|
||||
{
|
||||
_builder.Append(" ;;");
|
||||
|
||||
foreach ((ulong value, string name) in _symbolNames)
|
||||
{
|
||||
_builder.Append(" 0x").Append(value.ToString("X")).Append(" = ").Append(name);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the set of symbols for the next Node we're going to dump.
|
||||
_symbolNames.Clear();
|
||||
}
|
||||
|
||||
public static string GetDump(ControlFlowGraph cfg)
|
||||
{
|
||||
var dumper = new IRDumper(1);
|
||||
|
||||
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||
{
|
||||
dumper.Indent();
|
||||
dumper.DumpBlockHeader(block);
|
||||
|
||||
dumper._builder.AppendLine();
|
||||
|
||||
dumper.IncreaseIndentation();
|
||||
|
||||
for (Operation node = block.Operations.First; node != default; node = node.ListNext)
|
||||
{
|
||||
dumper.Indent();
|
||||
dumper.DumpNode(cfg, node);
|
||||
|
||||
dumper._builder.AppendLine();
|
||||
}
|
||||
|
||||
dumper.DecreaseIndentation();
|
||||
}
|
||||
|
||||
return dumper._builder.ToString();
|
||||
}
|
||||
|
||||
private static string GetTypeName(OperandType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
OperandType.None => "none",
|
||||
OperandType.I32 => "i32",
|
||||
OperandType.I64 => "i64",
|
||||
OperandType.FP32 => "f32",
|
||||
OperandType.FP64 => "f64",
|
||||
OperandType.V128 => "v128",
|
||||
_ => throw new ArgumentException($"Invalid operand type \"{type}\"."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
56
src/ARMeilleure/Diagnostics/Logger.cs
Normal file
56
src/ARMeilleure/Diagnostics/Logger.cs
Normal file
|
@ -0,0 +1,56 @@
|
|||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ARMeilleure.Diagnostics
|
||||
{
|
||||
static class Logger
|
||||
{
|
||||
private static long _startTime;
|
||||
|
||||
private static long[] _accumulatedTime;
|
||||
|
||||
static Logger()
|
||||
{
|
||||
_accumulatedTime = new long[(int)PassName.Count];
|
||||
}
|
||||
|
||||
[Conditional("M_DEBUG")]
|
||||
public static void StartPass(PassName name)
|
||||
{
|
||||
WriteOutput(name + " pass started...");
|
||||
|
||||
_startTime = Stopwatch.GetTimestamp();
|
||||
}
|
||||
|
||||
[Conditional("M_DEBUG")]
|
||||
public static void EndPass(PassName name, ControlFlowGraph cfg)
|
||||
{
|
||||
EndPass(name);
|
||||
|
||||
WriteOutput("IR after " + name + " pass:");
|
||||
|
||||
WriteOutput(IRDumper.GetDump(cfg));
|
||||
}
|
||||
|
||||
[Conditional("M_DEBUG")]
|
||||
public static void EndPass(PassName name)
|
||||
{
|
||||
long elapsedTime = Stopwatch.GetTimestamp() - _startTime;
|
||||
|
||||
_accumulatedTime[(int)name] += elapsedTime;
|
||||
|
||||
WriteOutput($"{name} pass ended after {GetMilliseconds(_accumulatedTime[(int)name])} ms...");
|
||||
}
|
||||
|
||||
private static long GetMilliseconds(long ticks)
|
||||
{
|
||||
return (long)(((double)ticks / Stopwatch.Frequency) * 1000);
|
||||
}
|
||||
|
||||
private static void WriteOutput(string text)
|
||||
{
|
||||
Console.WriteLine(text);
|
||||
}
|
||||
}
|
||||
}
|
19
src/ARMeilleure/Diagnostics/PassName.cs
Normal file
19
src/ARMeilleure/Diagnostics/PassName.cs
Normal file
|
@ -0,0 +1,19 @@
|
|||
namespace ARMeilleure.Diagnostics
|
||||
{
|
||||
enum PassName
|
||||
{
|
||||
Decoding,
|
||||
Translation,
|
||||
RegisterUsage,
|
||||
TailMerge,
|
||||
Dominance,
|
||||
SsaConstruction,
|
||||
RegisterToLocal,
|
||||
Optimization,
|
||||
PreAllocation,
|
||||
RegisterAllocation,
|
||||
CodeGeneration,
|
||||
|
||||
Count
|
||||
}
|
||||
}
|
84
src/ARMeilleure/Diagnostics/Symbols.cs
Normal file
84
src/ARMeilleure/Diagnostics/Symbols.cs
Normal file
|
@ -0,0 +1,84 @@
|
|||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ARMeilleure.Diagnostics
|
||||
{
|
||||
static class Symbols
|
||||
{
|
||||
private readonly struct RangedSymbol
|
||||
{
|
||||
public readonly ulong Start;
|
||||
public readonly ulong End;
|
||||
public readonly ulong ElementSize;
|
||||
public readonly string Name;
|
||||
|
||||
public RangedSymbol(ulong start, ulong end, ulong elemSize, string name)
|
||||
{
|
||||
Start = start;
|
||||
End = end;
|
||||
ElementSize = elemSize;
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly ConcurrentDictionary<ulong, string> _symbols;
|
||||
private static readonly List<RangedSymbol> _rangedSymbols;
|
||||
|
||||
static Symbols()
|
||||
{
|
||||
_symbols = new ConcurrentDictionary<ulong, string>();
|
||||
_rangedSymbols = new List<RangedSymbol>();
|
||||
}
|
||||
|
||||
public static string Get(ulong address)
|
||||
{
|
||||
string result;
|
||||
|
||||
if (_symbols.TryGetValue(address, out result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
lock (_rangedSymbols)
|
||||
{
|
||||
foreach (RangedSymbol symbol in _rangedSymbols)
|
||||
{
|
||||
if (address >= symbol.Start && address <= symbol.End)
|
||||
{
|
||||
ulong diff = address - symbol.Start;
|
||||
ulong rem = diff % symbol.ElementSize;
|
||||
|
||||
result = symbol.Name + "_" + diff / symbol.ElementSize;
|
||||
|
||||
if (rem != 0)
|
||||
{
|
||||
result += "+" + rem;
|
||||
}
|
||||
|
||||
_symbols.TryAdd(address, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
[Conditional("M_DEBUG")]
|
||||
public static void Add(ulong address, string name)
|
||||
{
|
||||
_symbols.TryAdd(address, name);
|
||||
}
|
||||
|
||||
[Conditional("M_DEBUG")]
|
||||
public static void Add(ulong address, ulong size, ulong elemSize, string name)
|
||||
{
|
||||
lock (_rangedSymbols)
|
||||
{
|
||||
_rangedSymbols.Add(new RangedSymbol(address, address + size, elemSize, name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
67
src/ARMeilleure/Diagnostics/TranslatorEventSource.cs
Normal file
67
src/ARMeilleure/Diagnostics/TranslatorEventSource.cs
Normal file
|
@ -0,0 +1,67 @@
|
|||
using System.Diagnostics.Tracing;
|
||||
using System.Threading;
|
||||
|
||||
namespace ARMeilleure.Diagnostics
|
||||
{
|
||||
[EventSource(Name = "ARMeilleure")]
|
||||
class TranslatorEventSource : EventSource
|
||||
{
|
||||
public static readonly TranslatorEventSource Log = new();
|
||||
|
||||
private int _rejitQueue;
|
||||
private ulong _funcTabSize;
|
||||
private ulong _funcTabLeafSize;
|
||||
private PollingCounter _rejitQueueCounter;
|
||||
private PollingCounter _funcTabSizeCounter;
|
||||
private PollingCounter _funcTabLeafSizeCounter;
|
||||
|
||||
public TranslatorEventSource()
|
||||
{
|
||||
_rejitQueueCounter = new PollingCounter("rejit-queue-length", this, () => _rejitQueue)
|
||||
{
|
||||
DisplayName = "Rejit Queue Length"
|
||||
};
|
||||
|
||||
_funcTabSizeCounter = new PollingCounter("addr-tab-alloc", this, () => _funcTabSize / 1024d / 1024d)
|
||||
{
|
||||
DisplayName = "AddressTable Total Bytes Allocated",
|
||||
DisplayUnits = "MiB"
|
||||
};
|
||||
|
||||
_funcTabLeafSizeCounter = new PollingCounter("addr-tab-leaf-alloc", this, () => _funcTabLeafSize / 1024d / 1024d)
|
||||
{
|
||||
DisplayName = "AddressTable Total Leaf Bytes Allocated",
|
||||
DisplayUnits = "MiB"
|
||||
};
|
||||
}
|
||||
|
||||
public void RejitQueueAdd(int count)
|
||||
{
|
||||
Interlocked.Add(ref _rejitQueue, count);
|
||||
}
|
||||
|
||||
public void AddressTableAllocated(int bytes, bool leaf)
|
||||
{
|
||||
_funcTabSize += (uint)bytes;
|
||||
|
||||
if (leaf)
|
||||
{
|
||||
_funcTabLeafSize += (uint)bytes;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
_rejitQueueCounter.Dispose();
|
||||
_rejitQueueCounter = null;
|
||||
|
||||
_funcTabLeafSizeCounter.Dispose();
|
||||
_funcTabLeafSizeCounter = null;
|
||||
|
||||
_funcTabSizeCounter.Dispose();
|
||||
_funcTabSizeCounter = null;
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue