Skip to content

Commit

Permalink
added "copy to clipboard" for disassembled program, fixed invalid sav…
Browse files Browse the repository at this point in the history
…ing of IReferenceVariable values
  • Loading branch information
Xytabich committed Sep 25, 2021
1 parent c494011 commit aa5fd91
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 37 deletions.
2 changes: 0 additions & 2 deletions Assets/Katsudon/Builder/UdonMachine/MachineUtility.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@

using Katsudon.Builder;
using VRC.Udon.VM.Common;

namespace Katsudon.Builder
Expand Down
11 changes: 9 additions & 2 deletions Assets/Katsudon/Builder/UdonMachine/UdonProgramBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ private class UdonBlockBuilder : IUdonMachine, IRawUdonMachine
private IUdonProgramBlock block;
private PrimitiveConvertersList convertersList;

private Stack<int> referencesStackStart = new Stack<int>();
private Stack<IReferenceVariable> referencesStack = new Stack<IReferenceVariable>();

public UdonBlockBuilder(UdonMachine udonMachine, IUdonProgramBlock block, PrimitiveConvertersList convertersList)
Expand Down Expand Up @@ -192,7 +193,9 @@ public void AddPush(VariableMeta variableInfo)
{
if(variableInfo.variable is IReferenceVariable reference)
{
referencesStackStart.Push(referencesStack.Count);
reference.LoadValue(block);
referencesStackStart.Pop();
variable = reference.GetValueVariable();
}

Expand All @@ -210,9 +213,13 @@ public void AddPush(VariableMeta variableInfo)

public void ApplyReferences()
{
while(referencesStack.Count > 0)
int stopCount = referencesStackStart.Count > 0 ? referencesStackStart.Peek() : 0;
while(referencesStack.Count != stopCount)
{
referencesStack.Pop().StoreValue(block);
var reference = referencesStack.Pop();
referencesStackStart.Push(referencesStack.Count);
reference.StoreValue(block);
referencesStackStart.Pop();
}
}

Expand Down
111 changes: 78 additions & 33 deletions Assets/Katsudon/Editor Scripts/Window/UdonProgramDisassemblyWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using UnityEngine;
using UnityEngine.UIElements;
using VRC.Udon.Common.Interfaces;
using VRC.Udon.Editor;
using VRC.Udon.VM.Common;

namespace Katsudon.Editor
Expand Down Expand Up @@ -49,7 +50,7 @@ private static Action<VisualElement, bool> SetChecked
private ListView programRowsRoot;

private StringBuilder cachedSb = new StringBuilder();
private IUdonProgram program;
private IUdonProgram program = null;
private List<ProgramRowInfo> programRows = new List<ProgramRowInfo>();

private List<VisualElement> selectedHeapElements = new List<VisualElement>(4);
Expand Down Expand Up @@ -105,7 +106,7 @@ private void OnEnable()
programRoot.style.minHeight = 256f;
programRoot.style.flexBasis = 256f;

AddToolbarLabel(programRoot, "Program:");
AddToolbarLabel(programRoot, "Program:").RegisterCallback<ContextClickEvent>(ShowProgramMenu);

programRowsRoot = new ListView();
programRowsRoot.AddToClassList(Box.ussClassName);
Expand Down Expand Up @@ -137,7 +138,7 @@ private VisualElement CreateRow()
private void UpdateRow(VisualElement element, int index)
{
var row = (ProgramRowElement)element;
row.Init(programRows[index], program);
row.Init(cachedSb, programRows[index], program);
}

private void InitProgram(IUdonProgram program)
Expand Down Expand Up @@ -218,6 +219,38 @@ private void InitHeapFields(IUdonSymbolTable symbols, List<(uint address, IStron
}
}

private void ShowProgramMenu(ContextClickEvent evt)
{
if(program == null) return;
var menu = new GenericMenu();
menu.AddItem(new GUIContent("Copy disassembly"), false, () => {
cachedSb.Clear();
foreach(var row in programRows)
{
if(row.opCode == OpCode.ANNOTATION)
{
cachedSb.AppendLine();
cachedSb.AppendLine();
var symbol = program.EntryPoints.GetSymbolFromAddress(row.argument);
if(program.EntryPoints.HasExportedSymbol(symbol))
{
cachedSb.Append(".export ");
}
cachedSb.Append(symbol);
cachedSb.Append(':');
}
else
{
cachedSb.AppendFormat("0x{0:X8}: ", row.address);
row.AppendInfo(cachedSb, program);
}
cachedSb.AppendLine();
}
GUIUtility.systemCopyBuffer = cachedSb.ToString();
});
menu.ShowAsContext();
}

private void SelectHeapField(PointerDownEvent evt)
{
var root = (VisualElement)evt.currentTarget;
Expand Down Expand Up @@ -330,7 +363,7 @@ private static void AddTableCell(VisualElement root, string text)
root.Add(label);
}

private static void AddToolbarLabel(VisualElement root, string text)
private static VisualElement AddToolbarLabel(VisualElement root, string text)
{
var label = new Label(text);
label.AddToClassList(ProgressBar.ussClassName);
Expand All @@ -340,6 +373,7 @@ private static void AddToolbarLabel(VisualElement root, string text)
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.unityFontStyleAndWeight = FontStyle.Bold;
root.Add(label);
return label;
}

public static void AppendObjectValue(StringBuilder sb, object value)
Expand Down Expand Up @@ -414,6 +448,32 @@ private struct ProgramRowInfo
public uint address;
public OpCode opCode;
public uint argument;

public void AppendInfo(StringBuilder sb, IUdonProgram program)
{
switch(opCode)
{
case OpCode.JUMP:
case OpCode.JUMP_IF_FALSE:
sb.AppendFormat("{0}, 0x{1:X8}", opCode, argument);
break;
case OpCode.PUSH:
case OpCode.JUMP_INDIRECT:
sb.AppendFormat("{0}, {1}", opCode, GetSymbol(program.SymbolTable, argument));
break;
case OpCode.EXTERN:
sb.AppendFormat("{0}, \"{1}\"", opCode, program.Heap.GetHeapVariable(argument));
break;
default:
sb.Append(opCode);
break;
}
}

private static string GetSymbol(IUdonSymbolTable symbols, uint address)
{
return symbols.TryGetSymbolFromAddress(address, out var symbol) ? symbol : string.Format("<0x{0:X8}>", address);
}
}

private class ProgramRowElement : VisualElement
Expand All @@ -431,41 +491,26 @@ public ProgramRowElement()
infoLabel.style.unityTextAlign = TextAnchor.MiddleLeft;
}

public void Init(ProgramRowInfo info, IUdonProgram program)
public void Init(StringBuilder sb, ProgramRowInfo info, IUdonProgram program)
{
addressLabel.style.display = info.opCode != OpCode.ANNOTATION ? DisplayStyle.Flex : DisplayStyle.None;
addressLabel.text = info.address.ToString("X8");
infoLabel.style.unityFontStyleAndWeight = info.opCode != OpCode.ANNOTATION ? FontStyle.Normal : FontStyle.Bold;
switch(info.opCode)
if(info.opCode == OpCode.ANNOTATION)
{
case OpCode.JUMP:
case OpCode.JUMP_IF_FALSE:
infoLabel.text = string.Format("{0}, 0x{1:X8}", info.opCode, info.argument);
break;
case OpCode.PUSH:
case OpCode.JUMP_INDIRECT:
infoLabel.text = string.Format("{0}, {1}", info.opCode, GetSymbol(program.SymbolTable, info.argument));
break;
case OpCode.ANNOTATION:
var symbol = program.EntryPoints.GetSymbolFromAddress(info.argument);
if(program.EntryPoints.HasExportedSymbol(symbol))
{
infoLabel.text = ".export " + symbol + ":";
}
else infoLabel.text = symbol + ":";
break;
case OpCode.EXTERN:
infoLabel.text = string.Format("{0}, \"{1}\"", info.opCode, program.Heap.GetHeapVariable(info.argument));
break;
default:
infoLabel.text = info.opCode.ToString();
break;
var symbol = program.EntryPoints.GetSymbolFromAddress(info.argument);
if(program.EntryPoints.HasExportedSymbol(symbol))
{
infoLabel.text = ".export " + symbol + ":";
}
else infoLabel.text = symbol + ":";
}
else
{
sb.Clear();
info.AppendInfo(sb, program);
infoLabel.text = sb.ToString();
}
}

private static string GetSymbol(IUdonSymbolTable symbols, uint address)
{
return symbols.TryGetSymbolFromAddress(address, out var symbol) ? symbol : string.Format("<0x{0:X8}>", address);
}
}
}
Expand Down

0 comments on commit aa5fd91

Please sign in to comment.