aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ARMeilleure/Diagnostics/IRDumper.cs304
-rw-r--r--ARMeilleure/Diagnostics/Symbols.cs84
-rw-r--r--ARMeilleure/Translation/EmitterContext.cs3
-rw-r--r--ARMeilleure/Translation/JumpTable.cs6
4 files changed, 301 insertions, 96 deletions
diff --git a/ARMeilleure/Diagnostics/IRDumper.cs b/ARMeilleure/Diagnostics/IRDumper.cs
index 100a9b11..7ff76077 100644
--- a/ARMeilleure/Diagnostics/IRDumper.cs
+++ b/ARMeilleure/Diagnostics/IRDumper.cs
@@ -2,168 +2,282 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
namespace ARMeilleure.Diagnostics
{
- static class IRDumper
+ class IRDumper
{
private const string Indentation = " ";
- public static string GetDump(ControlFlowGraph cfg)
+ private int _indentLevel;
+
+ private readonly StringBuilder _builder;
+
+ private readonly Dictionary<Operand, string> _localNames;
+ private readonly Dictionary<ulong, string> _symbolNames;
+
+ private IRDumper(int indent)
{
- StringBuilder sb = new StringBuilder();
+ _indentLevel = indent;
- Dictionary<Operand, string> localNames = new Dictionary<Operand, string>();
+ _builder = new StringBuilder();
- string indentation = string.Empty;
+ _localNames = new Dictionary<Operand, string>();
+ _symbolNames = new Dictionary<ulong, string>();
+ }
+
+ private void Indent()
+ {
+ _builder.EnsureCapacity(_builder.Capacity + _indentLevel * Indentation.Length);
- void IncreaseIndentation()
+ for (int index = 0; index < _indentLevel; index++)
{
- indentation += Indentation;
+ _builder.Append(Indentation);
}
+ }
+
+ private void IncreaseIndentation()
+ {
+ _indentLevel++;
+ }
+
+ private void DecreaseIndentation()
+ {
+ _indentLevel--;
+ }
+
+ private void DumpBlockName(BasicBlock block)
+ {
+ _builder.Append("block").Append(block.Index);
+ }
- void DecreaseIndentation()
+ private void DumpBlockHeader(BasicBlock block)
+ {
+ DumpBlockName(block);
+
+ if (block.Next != null)
{
- indentation = indentation.Substring(0, indentation.Length - Indentation.Length);
+ _builder.Append(" (next ");
+ DumpBlockName(block.Next);
+ _builder.Append(')');
}
- void AppendLine(string text)
+ if (block.Branch != null)
{
- sb.AppendLine(indentation + text);
+ _builder.Append(" (branch ");
+ DumpBlockName(block.Branch);
+ _builder.Append(')');
}
- IncreaseIndentation();
+ _builder.Append(':');
+ }
- for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
+ private void DumpOperand(Operand operand)
+ {
+ if (operand == null)
{
- string blockName = GetBlockName(block);
+ _builder.Append("<NULL>");
+ return;
+ }
- if (block.Next != null)
- {
- blockName += $" (next {GetBlockName(block.Next)})";
- }
+ _builder.Append(GetTypeName(operand.Type)).Append(' ');
- if (block.Branch != null)
- {
- blockName += $" (branch {GetBlockName(block.Branch)})";
- }
+ switch (operand.Kind)
+ {
+ case OperandKind.LocalVariable:
+ if (!_localNames.TryGetValue(operand, out string localName))
+ {
+ localName = $"%{_localNames.Count}";
- blockName += ":";
+ _localNames.Add(operand, localName);
+ }
- AppendLine(blockName);
+ _builder.Append(localName);
+ break;
- IncreaseIndentation();
+ case OperandKind.Register:
+ Register reg = operand.GetRegister();
- for (Node node = block.Operations.First; node != null; node = node.ListNext)
- {
- string[] sources = new string[node.SourcesCount];
+ 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;
- string instName = string.Empty;
+ case OperandKind.Constant:
+ string symbolName = Symbols.Get(operand.Value);
- if (node is PhiNode phi)
+ if (symbolName != null && !_symbolNames.ContainsKey(operand.Value))
{
- for (int index = 0; index < sources.Length; index++)
- {
- string phiBlockName = GetBlockName(phi.GetBlock(index));
+ _symbolNames.Add(operand.Value, symbolName);
+ }
- string operName = GetOperandName(phi.GetSource(index), localNames);
+ _builder.Append("0x").Append(operand.Value.ToString("X"));
+ break;
- sources[index] = $"({phiBlockName}: {operName})";
- }
+ case OperandKind.Memory:
+ var memOp = (MemoryOperand)operand;
- instName = "Phi";
- }
- else if (node is Operation operation)
+ _builder.Append('[');
+
+ DumpOperand(memOp.BaseAddress);
+
+ if (memOp.Index != null)
{
- for (int index = 0; index < sources.Length; index++)
+ _builder.Append(" + ");
+
+ DumpOperand(memOp.Index);
+
+ switch (memOp.Scale)
{
- sources[index] = GetOperandName(operation.GetSource(index), localNames);
+ case Multiplier.x2: _builder.Append("*2"); break;
+ case Multiplier.x4: _builder.Append("*4"); break;
+ case Multiplier.x8: _builder.Append("*8"); break;
}
-
- instName = operation.Instruction.ToString();
}
- string allSources = string.Join(", ", sources);
-
- string line = instName + " " + allSources;
-
- if (node.Destination != null)
+ if (memOp.Displacement != 0)
{
- line = GetOperandName(node.Destination, localNames) + " = " + line;
+ _builder.Append(" + 0x").Append(memOp.Displacement.ToString("X"));
}
- AppendLine(line);
- }
+ _builder.Append(']');
+ break;
- DecreaseIndentation();
+ default:
+ _builder.Append(operand.Type);
+ break;
}
-
- return sb.ToString();
- }
-
- private static string GetBlockName(BasicBlock block)
- {
- return $"block{block.Index}";
}
- private static string GetOperandName(Operand operand, Dictionary<Operand, string> localNames)
+ private void DumpNode(Node node)
{
- if (operand == null)
+ for (int index = 0; index < node.DestinationsCount; index++)
{
- return "<NULL>";
- }
+ DumpOperand(node.GetDestination(index));
- string name = string.Empty;
+ if (index == node.DestinationsCount - 1)
+ {
+ _builder.Append(" = ");
+ }
+ else
+ {
+ _builder.Append(", ");
+ }
+ }
- if (operand.Kind == OperandKind.LocalVariable)
+ switch (node)
{
- if (!localNames.TryGetValue(operand, out string localName))
- {
- localName = "%" + localNames.Count;
+ case PhiNode phi:
+ _builder.Append("Phi ");
- localNames.Add(operand, localName);
- }
+ for (int index = 0; index < phi.SourcesCount; index++)
+ {
+ _builder.Append('(');
+
+ DumpBlockName(phi.GetBlock(index));
+
+ _builder.Append(": ");
+
+ DumpOperand(phi.GetSource(index));
+
+ _builder.Append(')');
+
+ if (index < phi.SourcesCount - 1)
+ {
+ _builder.Append(", ");
+ }
+ }
+ break;
+
+ case Operation operation:
+ _builder.Append(operation.Instruction);
+
+ if (operation.Instruction == Instruction.Extended)
+ {
+ var intrinOp = (IntrinsicOperation)operation;
+
+ _builder.Append('.').Append(intrinOp.Intrinsic);
+ }
+
+ _builder.Append(' ');
+
+ for (int index = 0; index < operation.SourcesCount; index++)
+ {
+ DumpOperand(operation.GetSource(index));
- name = localName;
+ if (index < operation.SourcesCount - 1)
+ {
+ _builder.Append(", ");
+ }
+ }
+ break;
}
- else if (operand.Kind == OperandKind.Register)
+
+ if (_symbolNames.Count == 1)
{
- Register reg = operand.GetRegister();
+ _builder.Append(" ;; ").Append(_symbolNames.First().Value);
+ }
+ else if (_symbolNames.Count > 1)
+ {
+ _builder.Append(" ;;");
- switch (reg.Type)
+ foreach ((ulong value, string name) in _symbolNames)
{
- case RegisterType.Flag: name = "b" + reg.Index; break;
- case RegisterType.FpFlag: name = "f" + reg.Index; break;
- case RegisterType.Integer: name = "r" + reg.Index; break;
- case RegisterType.Vector: name = "v" + reg.Index; break;
+ _builder.Append(" 0x").Append(value.ToString("X")).Append(" = ").Append(name);
}
}
- else if (operand.Kind == OperandKind.Constant)
- {
- name = "0x" + operand.Value.ToString("X");
- }
- else
+
+ // 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)
{
- name = operand.Kind.ToString().ToLower();
+ dumper.Indent();
+ dumper.DumpBlockHeader(block);
+
+ dumper._builder.AppendLine();
+
+ dumper.IncreaseIndentation();
+
+ for (Node node = block.Operations.First; node != null; node = node.ListNext)
+ {
+ dumper.Indent();
+ dumper.DumpNode(node);
+
+ dumper._builder.AppendLine();
+ }
+
+ dumper.DecreaseIndentation();
}
- return GetTypeName(operand.Type) + " " + name;
+ return dumper._builder.ToString();
}
private static string GetTypeName(OperandType type)
{
- switch (type)
+ return type switch
{
- case OperandType.FP32: return "f32";
- case OperandType.FP64: return "f64";
- case OperandType.I32: return "i32";
- case OperandType.I64: return "i64";
- case OperandType.None: return "none";
- case OperandType.V128: return "v128";
- }
-
- throw new ArgumentException($"Invalid operand type \"{type}\".");
+ 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}\"."),
+ };
}
}
} \ No newline at end of file
diff --git a/ARMeilleure/Diagnostics/Symbols.cs b/ARMeilleure/Diagnostics/Symbols.cs
new file mode 100644
index 00000000..17764f7e
--- /dev/null
+++ b/ARMeilleure/Diagnostics/Symbols.cs
@@ -0,0 +1,84 @@
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace ARMeilleure.Diagnostics
+{
+ static class Symbols
+ {
+ private 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));
+ }
+ }
+ }
+}
diff --git a/ARMeilleure/Translation/EmitterContext.cs b/ARMeilleure/Translation/EmitterContext.cs
index d9e0a4ed..7abda1a7 100644
--- a/ARMeilleure/Translation/EmitterContext.cs
+++ b/ARMeilleure/Translation/EmitterContext.cs
@@ -1,3 +1,4 @@
+using ARMeilleure.Diagnostics;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using System;
@@ -85,6 +86,8 @@ namespace ARMeilleure.Translation
IntPtr ptr = Marshal.GetFunctionPointerForDelegate<Delegate>(func);
+ Symbols.Add((ulong)ptr.ToInt64(), func.Method.Name);
+
OperandType returnType = GetOperandType(func.Method.ReturnType);
return Call(Const(ptr.ToInt64()), returnType, callArgs);
diff --git a/ARMeilleure/Translation/JumpTable.cs b/ARMeilleure/Translation/JumpTable.cs
index e444e96d..40ea0fce 100644
--- a/ARMeilleure/Translation/JumpTable.cs
+++ b/ARMeilleure/Translation/JumpTable.cs
@@ -1,4 +1,5 @@
-using ARMeilleure.Memory;
+using ARMeilleure.Diagnostics;
+using ARMeilleure.Memory;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -60,6 +61,9 @@ namespace ARMeilleure.Translation
_targets = new ConcurrentDictionary<ulong, TranslatedFunction>();
_dependants = new ConcurrentDictionary<ulong, LinkedList<int>>();
+
+ Symbols.Add((ulong)_jumpRegion.Pointer.ToInt64(), JumpTableByteSize, JumpTableStride, "JMP_TABLE");
+ Symbols.Add((ulong)_dynamicRegion.Pointer.ToInt64(), DynamicTableByteSize, DynamicTableStride, "DYN_TABLE");
}
public void RegisterFunction(ulong address, TranslatedFunction func)