From 6785f14a25822bd3dfac1bcf5efe2d009cfda665 Mon Sep 17 00:00:00 2001 From: ShiningLea Date: Wed, 8 May 2024 15:23:47 +0200 Subject: [PATCH] Synchronize changes with WinForms version + more changes (#1228) --- .../CompilerData.cs | 6 - .../ExplorerMethodCompileTimeStage.cs | 1 - .../FormatInstructions.cs | 193 ++++++++++++++++++ .../InstructionRecord.cs | 95 +++++++++ .../MainWindow.axaml | 56 ++--- .../MainWindow.axaml.cs | 148 ++++++++------ .../Mosa.Tool.Explorer.Avalonia/MethodData.cs | 6 +- .../MethodStore.cs | 149 ++------------ .../Mosa.Tool.Explorer.Avalonia.csproj | 8 +- .../Stages/DebugInfoStage.cs | 104 ---------- .../Stages/DisassemblyStage.cs | 12 +- .../Stages/GraphVizStage.cs | 29 --- .../TypeSystemTree.cs | 12 +- Source/Mosa.Tool.Explorer.Avalonia/Utils.cs | 6 +- Source/Mosa.sln | 21 ++ 15 files changed, 460 insertions(+), 386 deletions(-) create mode 100644 Source/Mosa.Tool.Explorer.Avalonia/FormatInstructions.cs create mode 100644 Source/Mosa.Tool.Explorer.Avalonia/InstructionRecord.cs delete mode 100755 Source/Mosa.Tool.Explorer.Avalonia/Stages/DebugInfoStage.cs delete mode 100755 Source/Mosa.Tool.Explorer.Avalonia/Stages/GraphVizStage.cs diff --git a/Source/Mosa.Tool.Explorer.Avalonia/CompilerData.cs b/Source/Mosa.Tool.Explorer.Avalonia/CompilerData.cs index 0e053b325f..11daa34113 100755 --- a/Source/Mosa.Tool.Explorer.Avalonia/CompilerData.cs +++ b/Source/Mosa.Tool.Explorer.Avalonia/CompilerData.cs @@ -38,9 +38,7 @@ public void UpdateLog(string section, List lines, bool dirty) } lock (log) - { log.AddRange(lines); - } DirtyLog = dirty; } @@ -59,9 +57,7 @@ private void UpdateLog(string section, string line) } lock (log) - { log.Add(line); - } DirtyLog = true; } @@ -70,9 +66,7 @@ private void UpdateLog(string section, string line) public List GetLog(string section) { lock (Logs) - { return Logs.GetValueOrDefault(section); - } } public void AddTraceEvent(CompilerEvent compilerEvent, string message, int threadID) diff --git a/Source/Mosa.Tool.Explorer.Avalonia/CompilerStage/ExplorerMethodCompileTimeStage.cs b/Source/Mosa.Tool.Explorer.Avalonia/CompilerStage/ExplorerMethodCompileTimeStage.cs index 0bdbece160..404ef1139c 100755 --- a/Source/Mosa.Tool.Explorer.Avalonia/CompilerStage/ExplorerMethodCompileTimeStage.cs +++ b/Source/Mosa.Tool.Explorer.Avalonia/CompilerStage/ExplorerMethodCompileTimeStage.cs @@ -17,7 +17,6 @@ protected override void Finalization() var log = new TraceLog(TraceType.GlobalDebug, null, null, "Compiler Time"); log.Log("Ticks\tMilliseconds\tCompiler Count\tMethod"); - foreach (var data in methods) log.Log($"{data.ElapsedTicks}{'\t'}{data.ElapsedTicks / TimeSpan.TicksPerMillisecond}{'\t'}{data.Version}{'\t'}{data.Method.FullName}"); diff --git a/Source/Mosa.Tool.Explorer.Avalonia/FormatInstructions.cs b/Source/Mosa.Tool.Explorer.Avalonia/FormatInstructions.cs new file mode 100644 index 0000000000..8d60d9358d --- /dev/null +++ b/Source/Mosa.Tool.Explorer.Avalonia/FormatInstructions.cs @@ -0,0 +1,193 @@ +// Copyright (c) MOSA Project. Licensed under the New BSD License. + +using System.Text; + +namespace Mosa.Tool.Explorer.Avalonia; + +public static class FormatInstructions +{ + private const int Padding = 34; + + public static string Format(List records, string blockLabel, bool strip, bool removeNop, bool lineBetweenBlocks) + { + var sb = new StringBuilder(); + var blocks = new StringBuilder(); + + if (records == null || records.Count == 0) + return string.Empty; + + var allLines = string.IsNullOrWhiteSpace(blockLabel); + var inBlock = allLines; + + foreach (var record in records) + { + switch (record.Type) + { + case "M": + { + sb.AppendLine($"{record.MethodName} [v{record.Version}] @ {record.Stage}:"); + sb.AppendLine(); + break; + } + case "S": + { + inBlock = record.BlockLabel == blockLabel; + + if (!inBlock && !allLines) + continue; + + sb.Append($"{record.BlockLabel}:"); + + blocks.Clear(); + + // Previous Branch Targets + if (record.PreviousBlockCount != 0) + { + for (var i = 0; i < record.PreviousBlockCount; i++) + { + if (i != 0) + blocks.Append(' '); + + var op = record.GetPreviousBlocks(i); + + blocks.Append(op); + } + + sb.Append("".PadRight(record.PreviousBlockCount == 1 ? Padding : Padding - 8)); + + sb.Append(blocks); + } + + sb.AppendLine(); + break; + } + case "I": + { + if (!inBlock && !allLines) + continue; + + if (record.Instruction is "IR.BlockStart" or "IR.BlockEnd") + break; + + if (removeNop && record.Instruction == "IR.Nop") + continue; + + sb.Append(" "); + + var instruction = record.Instruction; + var condition = !string.IsNullOrEmpty(record.Condition) ? " [" + record.Condition + "]" : string.Empty; + + var both = $"{instruction}{condition}"; + + blocks.Clear(); + + // Branch Targets + if (record.BranchTargetCount != 0) + { + if (condition.Length != 0) + blocks.Append(' '); + + for (var i = 0; i < record.BranchTargetCount; i++) + { + if (i != 0) + blocks.Append(' '); + + var op = record.GetBranchTarget(i); + + blocks.Append(op); + } + } + + var count = Padding + 2 - both.Length - blocks.Length; + if (count < 0) + count = 1; + + var padding = string.Empty.PadRight(count); + + sb.Append($"{record.Label[..5]}:{record.Mark.PadLeft(1)}{both}{padding}{blocks} "); + + // Result + for (var i = 0; i < record.ResultCount; i++) + { + if (i != 0) + sb.Append(", "); + + var op = record.GetResult(i); + + op = Simplify(op); + + if (strip) + op = StripBracketData(op); + + sb.Append(op); + } + + if (record.ResultCount != 0 && record.OperandCount != 0) + sb.Append(" <= "); + + // Operands + for (var i = 0; i < record.OperandCount; i++) + { + if (i != 0) + sb.Append(", "); + + var op = record.GetOperand(i); + + op = Simplify(op); + + if (strip) + op = StripBracketData(op); + + sb.Append(op); + } + + // Phi Blocks + if (record.PhiBlockCount != 0) + { + sb.Append(" ("); + + for (var i = 0; i < record.PhiBlockCount; i++) + { + if (i != 0) + sb.Append(", "); + + var op = record.GetPhilBlock(i); + + sb.Append(op); + } + + sb.Append(") "); + } + + while (sb.Length > 0 && sb[^1] == ' ') + sb.Length--; + + sb.AppendLine(); + break; + } + case "E": + { + inBlock = false; + + if (!inBlock && !allLines) + continue; + + if (lineBetweenBlocks) + sb.AppendLine(); + + break; + } + } + } + + return sb.ToString(); + } + + private static string StripBracketData(string s) + { + var i = s.IndexOf('['); + return i <= 0 ? s : s[..(i - 1)].Trim(); + } + + private static string Simplify(string s) => s.Replace("const=", string.Empty); +} diff --git a/Source/Mosa.Tool.Explorer.Avalonia/InstructionRecord.cs b/Source/Mosa.Tool.Explorer.Avalonia/InstructionRecord.cs new file mode 100644 index 0000000000..08fab30bdb --- /dev/null +++ b/Source/Mosa.Tool.Explorer.Avalonia/InstructionRecord.cs @@ -0,0 +1,95 @@ +// Copyright (c) MOSA Project. Licensed under the New BSD License. + +namespace Mosa.Tool.Explorer.Avalonia; + +public class InstructionRecord +{ + public readonly string Data; + + public readonly string[] Parts; + + public readonly string Type; + + public readonly bool IsInstruction; + + public readonly bool IsMethod; + + public readonly bool IsStartBlock; + + public readonly bool IsEndBlock; + + public string Label => Parts[1]; + + // Block + public string BlockLabel => Parts[1]; + + // Start Block + public string BlockSequence => Parts[2]; + + public string BlockType => Parts[3]; + + public readonly int PreviousBlockCount; + + public string GetPreviousBlocks(int index) => Parts[5 + index]; + + // End Block + public int NextBlockCount => Convert.ToInt32(Parts[2]); + + // Instruction + public string Mark => Parts[2]; + + public string Instruction => Parts[3]; + + public string Condition => Parts[4]; + + public readonly int ResultCount = 0; + + public readonly int OperandCount = 0; + + public readonly int BranchTargetCount = 0; + + public readonly int PhiBlockCount = 0; + + public string GetResult(int index) => Parts[9 + index]; + + public string GetOperand(int index) => Parts[9 + ResultCount + index]; + + public string GetBranchTarget(int index) => Parts[9 + ResultCount + OperandCount + index]; + + public string GetPhilBlock(int index) => Parts[9 + ResultCount + OperandCount + BranchTargetCount + index]; + + // Method + + public string MethodName => Parts[1]; + + public int Version => Convert.ToInt32(Parts[2]); + + public string Stage => Parts[3]; + + public int Step => Convert.ToInt32(Parts[4]); + + public InstructionRecord(string data) + { + Data = data; + Parts = data.Split('\t'); + + Type = Parts[0]; + + IsInstruction = Type == "I"; + IsMethod = Type == "M"; + IsStartBlock = Type == "S"; + IsEndBlock = Type == "E"; + + if (IsInstruction) + { + ResultCount = Convert.ToInt32(Parts[5]); + OperandCount = Convert.ToInt32(Parts[6]); + BranchTargetCount = Convert.ToInt32(Parts[7]); + PhiBlockCount = Convert.ToInt32(Parts[8]); + } + else if (IsStartBlock) + { + PreviousBlockCount = Convert.ToInt32(Parts[4]); + } + } +} diff --git a/Source/Mosa.Tool.Explorer.Avalonia/MainWindow.axaml b/Source/Mosa.Tool.Explorer.Avalonia/MainWindow.axaml index 0b88995dac..41f204125a 100755 --- a/Source/Mosa.Tool.Explorer.Avalonia/MainWindow.axaml +++ b/Source/Mosa.Tool.Explorer.Avalonia/MainWindow.axaml @@ -36,10 +36,10 @@ + + - - @@ -72,7 +72,7 @@ - + @@ -159,24 +159,17 @@ - - - - - - - - - - - + + + + + - + + - - - - + + @@ -193,24 +186,17 @@ - - - - - - - - - - - + + + + + - + + - - - - + + diff --git a/Source/Mosa.Tool.Explorer.Avalonia/MainWindow.axaml.cs b/Source/Mosa.Tool.Explorer.Avalonia/MainWindow.axaml.cs index 4101c94c62..5a9b6eea16 100755 --- a/Source/Mosa.Tool.Explorer.Avalonia/MainWindow.axaml.cs +++ b/Source/Mosa.Tool.Explorer.Avalonia/MainWindow.axaml.cs @@ -15,8 +15,6 @@ using Mosa.Tool.Explorer.Avalonia.CompilerStage; using Mosa.Tool.Explorer.Avalonia.Stages; using Mosa.Utility.Configuration; -using DebugInfoStage = Mosa.Tool.Explorer.Avalonia.Stages.DebugInfoStage; -using GraphVizStage = Mosa.Tool.Explorer.Avalonia.Stages.GraphVizStage; using Timer = System.Timers.Timer; namespace Mosa.Tool.Explorer.Avalonia; @@ -31,7 +29,7 @@ public partial class MainWindow : Window private readonly ObservableCollection counterCollection = new ObservableCollection(); private readonly ObservableCollection compilerCounterCollection = new ObservableCollection(); - private MosaSettings mosaSettings = new MosaSettings(); + private readonly MosaSettings mosaSettings = new MosaSettings(); private MosaCompiler compiler; private int completedMethods; @@ -316,7 +314,15 @@ private void TreeView_OnSelectionChanged(object _, SelectionChangedEventArgs e) return; compilerData.Stopwatch.Reset(); - compiler.CompileSingleMethod(currentMethod); + ThreadPool.QueueUserWorkItem(_ => compiler.CompileSingleMethod(currentMethod)); + } + + private void TabControl_OnSelectionChanged(object _, SelectionChangedEventArgs e) + { + compilerData.DirtyLog = true; + + if (TabControl != null) + RefreshCompilerLog(); } private void InstructionsStage_OnSelectionChanged(object _, SelectionChangedEventArgs e) => UpdateInstructionStageSelection(); @@ -337,12 +343,12 @@ private void UpdateInstructionStageSelection() private void UpdateInstructionBlocks() { - var lines = GetCurrentInstructionLines(); + var records = GetCurrentInstructionLines(); InstructionsBlock.Items.Clear(); InstructionsBlock.Items.Add("All"); - var labels = ExtractLabels(lines); + var labels = ExtractLabels(records); if (labels == null) return; @@ -350,20 +356,16 @@ private void UpdateInstructionBlocks() InstructionsBlock.Items.Add(label); } - private static List ExtractLabels(List lines) + private static List ExtractLabels(List records) { - if (lines == null) + if (records == null) return null; var labels = new List(); - foreach (var line in lines) - { - if (!line.StartsWith("Block #")) - continue; - - labels.Add(line[line.IndexOf("L_", StringComparison.Ordinal)..]); - } + foreach (var record in records) + if (record.IsStartBlock) + labels.Add(record.BlockLabel); return labels; } @@ -429,6 +431,18 @@ private void TransformsGrid_OnSelectionChanged(object _, SelectionChangedEventAr private void CountersGridFilter_OnTextChanged(object _, TextChangedEventArgs e) => UpdateCounters(); + private async void CopyCountersText_OnClick(object _, RoutedEventArgs e) + { + if (Clipboard == null) + { + SetStatus("Error: No Clipboard Detected."); + return; + } + + await Clipboard.SetTextAsync(CreateText(currentMethodData.Counters)); + SetStatus("Text Copied!"); + } + private void CompilerLogsSection_OnSelectionChanged(object _, SelectionChangedEventArgs e) { var formatted = CompilerLogsSection.SelectionBoxItem?.ToString(); @@ -443,6 +457,22 @@ private void CompilerLogsSection_OnSelectionChanged(object _, SelectionChangedEv private void CompilerCountersGridFilter_OnTextChanged(object _, TextChangedEventArgs e) => UpdateCompilerCounters(); + private async void CopyCompilerCountersText_OnClick(object _, RoutedEventArgs e) + { + if (Clipboard == null) + { + SetStatus("Error: No Clipboard Detected."); + return; + } + + var lines = compilerData.GetLog("Counters"); + if (lines == null) + return; + + await Clipboard.SetTextAsync(CreateText(lines)); + SetStatus("Text Copied!"); + } + private void SetTransformationStep(int step) { if (step <= 0) @@ -529,7 +559,7 @@ private void PopulateTransformList() entry = new TransformEntry { - ID = Convert.ToInt32(parts[0].Trim()) + 1, + ID = Convert.ToInt32(parts[0].Trim()), Name = part1, Pass = pass }; @@ -542,7 +572,7 @@ private void PopulateTransformList() private void UpdateTransformLabels() { - var lines = GetCurrentTransformLines(); + var lines = GetCurrentTransformRecords(); TransformsBlock.Items.Clear(); TransformsBlock.Items.Add("All"); @@ -577,13 +607,7 @@ private List GetCurrentDebugLines() return stage == null ? null : currentMethodData.DebugLogs[stage]; } - private void UpdateGraphviz() - { - var graphviz = ShowGraphviz(); - - DebugPanel.IsVisible = graphviz; - Debug.IsVisible = !graphviz; - } + private void UpdateGraphviz() => DebugPanel.IsVisible = ShowGraphviz(); private bool ShowGraphviz() { @@ -595,11 +619,11 @@ private bool ShowGraphviz() if (DisplayGraphviz.IsChecked != null && !DisplayGraphviz.IsChecked.Value) return false; - if (string.IsNullOrEmpty(Debug.Text) || !Debug.Text.Contains("digraph blocks")) + if (string.IsNullOrEmpty(Debug.Text) || !Debug.Text.StartsWith("digraph blocks")) return false; var dot = Path.GetTempFileName(); - var bmp = Path.GetTempFileName(); + var img = Path.GetTempFileName(); try { @@ -608,29 +632,27 @@ private bool ShowGraphviz() var startInfo = new ProcessStartInfo { FileName = mosaSettings.GraphwizApp, - Arguments = $"dot -Tbmp -o \"{bmp}\" \"{dot}\"", + Arguments = $"-Tpng -o \"{img}\" \"{dot}\"", CreateNoWindow = true }; var process = Process.Start(startInfo); process?.WaitForExit(); - var file = File.ReadAllBytes(bmp); - - using var stream = new MemoryStream(file); + using var stream = File.OpenRead(img); var bitmap = new Bitmap(stream); - var picture = new Image + var image = new Image { Source = bitmap }; - DebugPanel.Children.Add(picture); + DebugPanel.Children.Add(image); } finally { File.Delete(dot); - File.Delete(bmp); + File.Delete(img); } return true; @@ -671,12 +693,24 @@ private void ExtendMethodCompilerPipeline(Pipeline pipe if (Dispatcher.UIThread.Invoke(() => DebugDiagnostic.IsChecked)) { for (var i = 1; i < pipeline.Count; i += 2) - pipeline.Insert(i, new GraphVizStage()); + pipeline.Insert(i, new ControlFlowGraphStage()); } else { - pipeline.InsertAfterLast(new GraphVizStage()); - pipeline.Add(new GraphVizStage()); + if (mosaSettings.InlineMethods || mosaSettings.InlineExplicit) + { + pipeline.InsertBefore(new ControlFlowGraphStage()); + pipeline.InsertAfterLast(new ControlFlowGraphStage()); + } + + if (mosaSettings.SSA) + { + pipeline.InsertBefore(new DominanceAnalysisStage()); + pipeline.InsertBefore(new ControlFlowGraphStage()); + } + + pipeline.InsertAfterLast(new ControlFlowGraphStage()); + pipeline.Add(new ControlFlowGraphStage()); } } @@ -780,19 +814,19 @@ private void UpdateInstructions() if (currentMethod == null) return; - var lines = GetCurrentInstructionLines(); + var records = GetCurrentInstructionLines(); var label = InstructionsBlock.SelectionBoxItem?.ToString(); SetStatus(currentMethod.FullName); - if (lines == null) + if (records == null) return; if (string.IsNullOrWhiteSpace(label) || label == "All") label = string.Empty; - Instructions.Text = methodStore.GetStageInstructions(lines, label, !ShowOperandTypes.IsChecked, - PadInstructions.IsChecked, RemoveIrNop.IsChecked); + Instructions.Text = FormatInstructions.Format(records, label, !ShowOperandTypes.IsChecked, + RemoveIrNop.IsChecked, LineBetweenBlocks.IsChecked); } private void UpdateTransforms() @@ -802,20 +836,20 @@ private void UpdateTransforms() if (currentMethod == null) return; - var lines = GetCurrentTransformLines(); + var records = GetCurrentTransformRecords(); var label = TransformsBlock.SelectionBoxItem?.ToString(); - if (lines == null) + if (records == null) return; if (string.IsNullOrWhiteSpace(label) || label == "All") label = string.Empty; - Transforms.Text = methodStore.GetStageInstructions(lines, label, !ShowOperandTypes.IsChecked, - PadInstructions.IsChecked, RemoveIrNop.IsChecked); + Transforms.Text = FormatInstructions.Format(records, label, !ShowOperandTypes.IsChecked, + RemoveIrNop.IsChecked, LineBetweenBlocks.IsChecked); } - private List GetCurrentTransformLines() + private List GetCurrentTransformRecords() { if (currentMethodData == null) return null; @@ -830,14 +864,13 @@ private List GetCurrentTransformLines() return log; } - private List GetCurrentInstructionLines() + private List GetCurrentInstructionLines() { if (currentMethodData == null) return null; var stage = InstructionsStage.SelectionBoxItem?.ToString(); return stage == null ? null : currentMethodData.InstructionLogs[stage]; - } private void UpdateInstructionStages() @@ -869,13 +902,9 @@ private void UpdateDebugStages() private void UpdateCounters() { - Counters.Clear(); - if (currentMethodData == null) return; - Counters.Text = CreateText(currentMethodData.Counters); - counterCollection.Clear(); var filter = CountersGridFilter.Text ?? string.Empty; @@ -1074,10 +1103,17 @@ private void LoadAssembly() UpdateSettings(); compiler = new MosaCompiler(mosaSettings, CreateCompilerHooks(), new ClrModuleLoader(), new ClrTypeResolver()); - compiler.Load(); - CreateTree(); - SetStatus("Assemblies Loaded!"); + ThreadPool.QueueUserWorkItem(_ => + { + Dispatcher.UIThread.Post(() => SetStatus("Loading Types...")); + compiler.Load(); + + Dispatcher.UIThread.Post(() => SetStatus("Building Type System Tree...")); + Dispatcher.UIThread.Post(CreateTree); + + Dispatcher.UIThread.Post(() => SetStatus("Assemblies Loaded!")); + }); } private void ClearAll() @@ -1176,10 +1212,8 @@ private static string CreateText(List list) var sb = new StringBuilder(); lock (list) - { foreach (var l in list) sb.AppendLine(l); - } return sb.ToString(); } @@ -1201,8 +1235,6 @@ private void UpdateCompilerCounters() var entry = ExtractCounterData(line); compilerCounterCollection.Add(entry); } - - CompilerCounters.Text = CreateText(lines); } private static CounterEntry ExtractCounterData(string line) diff --git a/Source/Mosa.Tool.Explorer.Avalonia/MethodData.cs b/Source/Mosa.Tool.Explorer.Avalonia/MethodData.cs index 4cbd5f0006..09a38d53a2 100755 --- a/Source/Mosa.Tool.Explorer.Avalonia/MethodData.cs +++ b/Source/Mosa.Tool.Explorer.Avalonia/MethodData.cs @@ -13,10 +13,10 @@ public class MethodData public readonly List OrderedTransformStageNames = new List(); - public readonly Dictionary> InstructionLogs = new Dictionary>(); + public readonly Dictionary> InstructionLogs = new Dictionary>(); + public readonly Dictionary>> TransformLogs = new Dictionary>>(); + public readonly Dictionary> DebugLogs = new Dictionary>(); public List Counters = new List(); - - public Dictionary>> TransformLogs = new Dictionary>>(); } diff --git a/Source/Mosa.Tool.Explorer.Avalonia/MethodStore.cs b/Source/Mosa.Tool.Explorer.Avalonia/MethodStore.cs index 8d8d79366f..a9a620d7e8 100755 --- a/Source/Mosa.Tool.Explorer.Avalonia/MethodStore.cs +++ b/Source/Mosa.Tool.Explorer.Avalonia/MethodStore.cs @@ -1,6 +1,5 @@ // Copyright (c) MOSA Project. Licensed under the New BSD License. -using System.Text; using Mosa.Compiler.Common; using Mosa.Compiler.MosaTypeSystem; @@ -13,9 +12,7 @@ public class MethodStore public void Clear() { lock (methodDataStore) - { methodDataStore.Clear(); - } } private static void ClearMethodDataOnNewVersion(int version, MethodData methodData) @@ -49,6 +46,10 @@ public MethodData GetMethodData(MosaMethod method, bool create) public void SetInstructionTraceInformation(MosaMethod method, string stage, List lines, int version) { var methodData = GetMethodData(method, true); + var records = new List(); + + foreach (var line in lines) + records.Add(new InstructionRecord(line)); lock (methodData) { @@ -56,13 +57,17 @@ public void SetInstructionTraceInformation(MosaMethod method, string stage, List methodData.OrderedStageNames.AddIfNew(stage); methodData.InstructionLogs.Remove(stage); - methodData.InstructionLogs.Add(stage, lines); + methodData.InstructionLogs.Add(stage, records); } } public void SetTransformTraceInformation(MosaMethod method, string stage, List lines, int version, int step) { var methodData = GetMethodData(method, true); + var records = new List(); + + foreach (var line in lines) + records.Add(new InstructionRecord(line)); lock (methodData) { @@ -70,13 +75,13 @@ public void SetTransformTraceInformation(MosaMethod method, string stage, List>(); - methodData.TransformLogs.Add(stage, directionary); + dictionary = new Dictionary>(); + methodData.TransformLogs.Add(stage, dictionary); } - directionary.Add(step, lines); + dictionary.Add(step, records); } } @@ -105,132 +110,4 @@ public void SetMethodCounterInformation(MosaMethod method, List lines, i methodData.Counters = lines; } } - - public string GetStageInstructions(List lines, string blockLabel, bool strip, bool pad, bool removeNop) - { - var result = new StringBuilder(); - - if (lines == null) - return string.Empty; - - if (string.IsNullOrWhiteSpace(blockLabel)) - { - foreach (var l in lines) - { - var line = l; - - if (line.Contains("IR.BlockStart") || line.Contains("IR.BlockEnd")) - continue; - - if (removeNop && line.Contains("IR.Nop")) - continue; - - if (strip) - line = StripBracketContents(line); - - if (pad) - line = PadInstruction(line); - - line = Simplify(line); - - result.Append(line); - result.Append('\n'); - } - - return result.ToString(); - } - - var inBlock = false; - - foreach (var l in lines) - { - var line = l; - - if ((!inBlock) && line.StartsWith("Block #") && line.EndsWith(blockLabel)) - inBlock = true; - - if (!inBlock) - continue; - - if (line.Contains("IR.BlockStart") || line.Contains("IR.BlockEnd")) - continue; - - if (strip) - line = StripBracketContents(line); - - if (pad) - line = PadInstruction(line); - - line = Simplify(line); - - result.Append(line); - result.Append('\n'); - - if (line.StartsWith(" Next:")) - return result.ToString(); - } - - return result.ToString(); - } - - private static string StripBracketContents(string s) - { - if (string.IsNullOrEmpty(s) || s.Length < 5) - return s; - - if (!char.IsDigit(s[0])) - return s; - - var at = 0; - while (true) - { - var open = s.IndexOf(" [", at, StringComparison.Ordinal); - if (open < 0) - return s; - - var close = s.IndexOf(']', open); - if (close < 0) - return s; - - var part = s.Substring(open + 2, close - open - 2); - if (part == "NULL" || char.IsSymbol(part[0]) || char.IsPunctuation(part[0])) - { - at = close; - continue; - } - - s = s.Remove(open, close - open + 1); - at = open; - } - } - - private static string PadInstruction(string s) - { - const int padding = 30; - - if (string.IsNullOrEmpty(s) || s.Length < 5) - return s; - - if (!char.IsDigit(s[0])) - return s; - - var first = s.IndexOf(':'); - if (first is < 0 or > 15) - return s; - - var second = s.IndexOf(' ', first + 2); - - switch (second) - { - case < 0: return s; - case > padding: return s; - default: - { - s = s.Insert(second, new string(' ', padding - second)); - return s; - } - } - } - - private static string Simplify(string s) => s.Replace("const=", string.Empty); } diff --git a/Source/Mosa.Tool.Explorer.Avalonia/Mosa.Tool.Explorer.Avalonia.csproj b/Source/Mosa.Tool.Explorer.Avalonia/Mosa.Tool.Explorer.Avalonia.csproj index b95bc0556d..0cf19b81e2 100755 --- a/Source/Mosa.Tool.Explorer.Avalonia/Mosa.Tool.Explorer.Avalonia.csproj +++ b/Source/Mosa.Tool.Explorer.Avalonia/Mosa.Tool.Explorer.Avalonia.csproj @@ -19,10 +19,10 @@ - - - - + + + + diff --git a/Source/Mosa.Tool.Explorer.Avalonia/Stages/DebugInfoStage.cs b/Source/Mosa.Tool.Explorer.Avalonia/Stages/DebugInfoStage.cs deleted file mode 100755 index 458e3135d4..0000000000 --- a/Source/Mosa.Tool.Explorer.Avalonia/Stages/DebugInfoStage.cs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) MOSA Project. Licensed under the New BSD License. - -using Mosa.Compiler.Framework; - -namespace Mosa.Tool.Explorer.Avalonia.Stages; - -public class DebugInfoStage : BaseMethodCompilerStage -{ - protected override void Run() - { - DumpByInstructions(); - DumpRegions(); - DumpSourceInfo(); - } - - protected void DumpByInstructions() - { - var trace = CreateTraceLog("Instructions"); - if (trace == null) - return; - - trace.Log("Label\tAddress\tLength\tStartLine\tEndLine\tStartColumn\tEndColumn\tInstruction\tDocument"); - - foreach (var block in BasicBlocks) - { - for (var node = block.First; !node.IsBlockEndInstruction; node = node.Next) - { - if (node.IsEmpty) - continue; - - if (node.Instruction.IgnoreDuringCodeGeneration) - continue; - - var label = node.Label; - var startLine = -1; - var endLine = 0; - var endColumn = 0; - var startColumn = 0; - var document = string.Empty; - - //var offset = node.Offset; - - var address = -1; - var length = 0; - - foreach (var instruction in Method.Code) - { - if (instruction.Offset != label) - continue; - - startLine = instruction.StartLine; - endLine = instruction.EndLine; - startColumn = instruction.StartColumn; - endColumn = instruction.EndColumn; - document = instruction.Document; - - break; - } - - if (startLine == -1) - continue; - - foreach (var region in MethodData.LabelRegions) - { - if (region.Label != label) - continue; - - address = region.Start; - length = region.Length; - break; - } - - if (address == -1) - continue; - - trace.Log($"{label:X5}\t{address}\t{length}\t{startLine}\t{endLine}\t{startColumn}\t{endColumn}\t{node}\t{document}"); - } - } - } - - protected void DumpRegions() - { - var trace = CreateTraceLog("Regions"); - - trace.Log("Label\tAddress\tLength"); - - foreach (var region in MethodData.LabelRegions) - { - trace.Log($"{region.Label:X5}\t{region.Start}\t{region.Length}"); - } - } - - protected void DumpSourceInfo() - { - var trace = CreateTraceLog("Source"); - - trace.Log("Label\tStartLine\tEndLine\tStartColumn\tEndColumn\tDocument"); - - foreach (var instruction in Method.Code) - { - trace.Log($"{instruction.Offset:X5}\t{instruction.StartLine}\t{instruction.EndLine}\t{instruction.StartColumn}\t{instruction.EndColumn}\t{instruction.Document}"); - } - } -} diff --git a/Source/Mosa.Tool.Explorer.Avalonia/Stages/DisassemblyStage.cs b/Source/Mosa.Tool.Explorer.Avalonia/Stages/DisassemblyStage.cs index 521c6a09cd..da89e79ea6 100755 --- a/Source/Mosa.Tool.Explorer.Avalonia/Stages/DisassemblyStage.cs +++ b/Source/Mosa.Tool.Explorer.Avalonia/Stages/DisassemblyStage.cs @@ -16,7 +16,7 @@ protected override void Run() TracePatchRequests(); } - protected void TraceDisassembly() + private void TraceDisassembly() { var trace = CreateTraceLog(); if (trace == null) @@ -30,9 +30,15 @@ protected void TraceDisassembly() var memory = new byte[length]; stream.Position = 0; - stream.Read(memory, 0, length); + var read = stream.Read(memory, 0, length); stream.Position = oldPosition; + if (read != length) + { + trace.Log("Error: Couldn't read enough bytes to disassemble."); + return; + } + var disassembler = new Disassembler(Architecture.PlatformName, memory, 0); var instruction = disassembler.DecodeNext(); @@ -43,7 +49,7 @@ protected void TraceDisassembly() } } - protected void TracePatchRequests() + private void TracePatchRequests() { var trace = CreateTraceLog("Patch-Requests"); if (trace == null) diff --git a/Source/Mosa.Tool.Explorer.Avalonia/Stages/GraphVizStage.cs b/Source/Mosa.Tool.Explorer.Avalonia/Stages/GraphVizStage.cs deleted file mode 100755 index 2052ab2a57..0000000000 --- a/Source/Mosa.Tool.Explorer.Avalonia/Stages/GraphVizStage.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) MOSA Project. Licensed under the New BSD License. - -using Mosa.Compiler.Framework; - -namespace Mosa.Tool.Explorer.Avalonia.Stages; - -public class GraphVizStage : BaseMethodCompilerStage -{ - private const int TraceLevel = 6; - - protected override void Run() - { - if (!IsTraceable(TraceLevel)) - return; - - var trace = CreateTraceLog(); - trace.Log("digraph blocks {"); - - foreach (var block in BasicBlocks) - { - // trace.Log($"\t{block}"); - - foreach (var next in block.NextBlocks) - trace.Log($"\t{block} -> {next}"); - } - - trace.Log("}"); - } -} diff --git a/Source/Mosa.Tool.Explorer.Avalonia/TypeSystemTree.cs b/Source/Mosa.Tool.Explorer.Avalonia/TypeSystemTree.cs index b689c8a75a..7f19e95f02 100755 --- a/Source/Mosa.Tool.Explorer.Avalonia/TypeSystemTree.cs +++ b/Source/Mosa.Tool.Explorer.Avalonia/TypeSystemTree.cs @@ -296,7 +296,7 @@ private TreeViewItem GetOrCreateNode(MosaType type) GetOrCreateNode(method); } - // Method Table + // Method Table if (TypeLayout.GetMethodTable(type) != null) { var methodTableNode = new TreeViewItem { Header = "Method Table" }; @@ -306,11 +306,11 @@ private TreeViewItem GetOrCreateNode(MosaType type) foreach (var method in methodList) { - if (included == null || included.Contains(method)) - { - var methodNode = new TreeViewItem { Header = method.ShortName, Tag = method }; - methodTableNode.Items.Add(methodNode); - } + if (included != null && !included.Contains(method)) + continue; + + var methodNode = new TreeViewItem { Header = method.ShortName, Tag = method }; + methodTableNode.Items.Add(methodNode); } } diff --git a/Source/Mosa.Tool.Explorer.Avalonia/Utils.cs b/Source/Mosa.Tool.Explorer.Avalonia/Utils.cs index 1215ebfbf4..32082e2ea5 100755 --- a/Source/Mosa.Tool.Explorer.Avalonia/Utils.cs +++ b/Source/Mosa.Tool.Explorer.Avalonia/Utils.cs @@ -13,8 +13,12 @@ public static class Utils public static readonly FilePickerOpenOptions LibraryOpenOptions = new FilePickerOpenOptions { + Title = "Select a library to open in the explorer", FileTypeFilter = new List { LibraryFileType } }; - public static readonly FolderPickerOpenOptions FolderOpenOptions = new FolderPickerOpenOptions(); + public static readonly FolderPickerOpenOptions FolderOpenOptions = new FolderPickerOpenOptions + { + Title = "Select a folder where to dump all method stages" + }; } diff --git a/Source/Mosa.sln b/Source/Mosa.sln index 96f56a44c5..8c5ee8e7c1 100644 --- a/Source/Mosa.sln +++ b/Source/Mosa.sln @@ -252,6 +252,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Template", "Template", "{A1 TemplateLibrary.txt = TemplateLibrary.txt EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mosa.Tool.Explorer.Avalonia", "Mosa.Tool.Explorer.Avalonia\Mosa.Tool.Explorer.Avalonia.csproj", "{763FDCF2-2501-4756-A7A1-62813D610B00}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1436,6 +1438,24 @@ Global {26667157-E909-4F7A-9130-F8B5C15A1E4E}.Release|Mixed Platforms.Build.0 = Release|Any CPU {26667157-E909-4F7A-9130-F8B5C15A1E4E}.Release|x86.ActiveCfg = Release|Any CPU {26667157-E909-4F7A-9130-F8B5C15A1E4E}.Release|x86.Build.0 = Release|Any CPU + {763FDCF2-2501-4756-A7A1-62813D610B00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {763FDCF2-2501-4756-A7A1-62813D610B00}.Debug|Any CPU.Build.0 = Debug|Any CPU + {763FDCF2-2501-4756-A7A1-62813D610B00}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {763FDCF2-2501-4756-A7A1-62813D610B00}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {763FDCF2-2501-4756-A7A1-62813D610B00}.Debug|x86.ActiveCfg = Debug|Any CPU + {763FDCF2-2501-4756-A7A1-62813D610B00}.Debug|x86.Build.0 = Debug|Any CPU + {763FDCF2-2501-4756-A7A1-62813D610B00}.Description|Any CPU.ActiveCfg = Debug|Any CPU + {763FDCF2-2501-4756-A7A1-62813D610B00}.Description|Any CPU.Build.0 = Debug|Any CPU + {763FDCF2-2501-4756-A7A1-62813D610B00}.Description|Mixed Platforms.ActiveCfg = Debug|Any CPU + {763FDCF2-2501-4756-A7A1-62813D610B00}.Description|Mixed Platforms.Build.0 = Debug|Any CPU + {763FDCF2-2501-4756-A7A1-62813D610B00}.Description|x86.ActiveCfg = Debug|Any CPU + {763FDCF2-2501-4756-A7A1-62813D610B00}.Description|x86.Build.0 = Debug|Any CPU + {763FDCF2-2501-4756-A7A1-62813D610B00}.Release|Any CPU.ActiveCfg = Release|Any CPU + {763FDCF2-2501-4756-A7A1-62813D610B00}.Release|Any CPU.Build.0 = Release|Any CPU + {763FDCF2-2501-4756-A7A1-62813D610B00}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {763FDCF2-2501-4756-A7A1-62813D610B00}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {763FDCF2-2501-4756-A7A1-62813D610B00}.Release|x86.ActiveCfg = Release|Any CPU + {763FDCF2-2501-4756-A7A1-62813D610B00}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1512,6 +1532,7 @@ Global {E94607AB-584E-4D15-B0FA-68E086FE9E70} = {75BB6B40-C122-422F-8B40-F50A70A08E0D} {26667157-E909-4F7A-9130-F8B5C15A1E4E} = {3A538FDC-0226-4971-A3C0-31570CDA340D} {A1660856-2153-477F-BAAC-39E8BEB75971} = {F0EFF742-92D5-4219-939A-8F6F8DAB24E5} + {763FDCF2-2501-4756-A7A1-62813D610B00} = {D032B24A-CE3A-4881-BACE-CC4FE0AFD69D} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C22A5C94-6B05-4B1B-845A-A2EA7615E093}