Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor and spanify AVM2 instruction IO logic #15

Merged
merged 5 commits into from
Feb 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 67 additions & 68 deletions Flazzy/ABC/AVM2/ASCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -577,95 +577,94 @@ private void LoadInstructions()
var marks = new Dictionary<long, ASInstruction>();
var sharedExits = new Dictionary<long, List<Jumper>>();
var switchCases = new Dictionary<long, List<(LookUpSwitchIns, int)>>();
using (var input = new FlashReader(_body.Code))

var input = new SpanFlashReader(_body.Code);
while (input.IsDataAvailable)
{
while (input.IsDataAvailable)
{
long previousPosition = input.Position;
var instruction = ASInstruction.Create(_abc, input);
marks[previousPosition] = instruction;
long previousPosition = input.Position;
var instruction = ASInstruction.Create(_abc, ref input);
marks[previousPosition] = instruction;

_indices.Add(instruction, _indices.Count);
_instructions.Add(instruction);
_indices.Add(instruction, _indices.Count);
_instructions.Add(instruction);

if (!_opGroups.TryGetValue(instruction.OP, out List<ASInstruction> instructions))
{
instructions = new List<ASInstruction>();
_opGroups.Add(instruction.OP, instructions);
}
instructions.Add(instruction);
if (!_opGroups.TryGetValue(instruction.OP, out List<ASInstruction> instructions))
{
instructions = new List<ASInstruction>();
_opGroups.Add(instruction.OP, instructions);
}
instructions.Add(instruction);

if (sharedExits.TryGetValue(previousPosition, out List<Jumper> jumpers))
if (sharedExits.TryGetValue(previousPosition, out List<Jumper> jumpers))
{
// This is an exit position two or more jump instructions.
foreach (Jumper jumper in jumpers)
{
// This is an exit position two or more jump instructions.
foreach (Jumper jumper in jumpers)
{
JumpExits.Add(jumper, instruction);
}
sharedExits.Remove(previousPosition);
JumpExits.Add(jumper, instruction);
}
sharedExits.Remove(previousPosition);
}

if (switchCases.TryGetValue(previousPosition, out List<(LookUpSwitchIns, int)> caseExits))
if (switchCases.TryGetValue(previousPosition, out List<(LookUpSwitchIns, int)> caseExits))
{
foreach ((LookUpSwitchIns owner, int index) in caseExits)
{
foreach ((LookUpSwitchIns owner, int index) in caseExits)
{
SwitchExits[owner][index] = instruction;
}
switchCases.Remove(previousPosition);
SwitchExits[owner][index] = instruction;
}
switchCases.Remove(previousPosition);
}

if (instruction.OP == OPCode.LookUpSwitch)
{
var lookUpSwitchIns = (LookUpSwitchIns)instruction;
var offsets = new List<uint>(lookUpSwitchIns.CaseOffsets) { lookUpSwitchIns.DefaultOffset };
if (instruction.OP == OPCode.LookUpSwitch)
{
var lookUpSwitchIns = (LookUpSwitchIns)instruction;
var offsets = new List<uint>(lookUpSwitchIns.CaseOffsets) { lookUpSwitchIns.DefaultOffset };

var exits = new ASInstruction[offsets.Count];
for (int i = 0; i < offsets.Count; i++)
var exits = new ASInstruction[offsets.Count];
for (int i = 0; i < offsets.Count; i++)
{
long exitPosition = previousPosition + offsets[i];
if (exitPosition <= input.Length)
{
long exitPosition = previousPosition + offsets[i];
if (exitPosition <= input.Length)
if (!switchCases.TryGetValue(exitPosition, out caseExits))
{
if (!switchCases.TryGetValue(exitPosition, out caseExits))
{
caseExits = new List<(LookUpSwitchIns, int)>();
switchCases.Add(exitPosition, caseExits);
}
caseExits.Add((lookUpSwitchIns, i));
caseExits = new List<(LookUpSwitchIns, int)>();
switchCases.Add(exitPosition, caseExits);
}
else exits[i] = marks[exitPosition - uint.MaxValue - 1];
caseExits.Add((lookUpSwitchIns, i));
}
SwitchExits.Add(lookUpSwitchIns, exits);
else exits[i] = marks[exitPosition - uint.MaxValue - 1];
}
else if (Jumper.IsValid(instruction.OP))
{
var jumper = (Jumper)instruction;
if (jumper.Offset == 0) continue;
SwitchExits.Add(lookUpSwitchIns, exits);
}
else if (Jumper.IsValid(instruction.OP))
{
var jumper = (Jumper)instruction;
if (jumper.Offset == 0) continue;

long exitPosition = (input.Position + jumper.Offset);
if (exitPosition == input.Length)
{
// Jump exit does not exist at this (non-existent)index, do not look for exit.
continue;
}
else if (exitPosition < input.Length) // Forward jump.
long exitPosition = (input.Position + jumper.Offset);
if (exitPosition == input.Length)
{
// Jump exit does not exist at this (non-existent)index, do not look for exit.
continue;
}
else if (exitPosition < input.Length) // Forward jump.
{
if (!sharedExits.TryGetValue(exitPosition, out jumpers))
{
if (!sharedExits.TryGetValue(exitPosition, out jumpers))
{
jumpers = new List<Jumper>();
sharedExits.Add(exitPosition, jumpers);
}
jumpers.Add(jumper);
jumpers = new List<Jumper>();
sharedExits.Add(exitPosition, jumpers);
}
else // Backwards jump.
jumpers.Add(jumper);
}
else // Backwards jump.
{
long markIndex = exitPosition - uint.MaxValue - 1;
if (marks[markIndex].OP == OPCode.Label)
{
long markIndex = exitPosition - uint.MaxValue - 1;
if (marks[markIndex].OP == OPCode.Label)
{
var label = (LabelIns)marks[markIndex];
JumpExits.Add(jumper, label);
}
// TODO: Check if not adding an impossible label is fine...
var label = (LabelIns)marks[markIndex];
JumpExits.Add(jumper, label);
}
// TODO: Check if not adding an impossible label is fine...
}
}
}
Expand Down
Loading
Loading