| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- 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}\"."),
- };
- }
- }
- }
|