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

DebugInfoBuilder for sequence point v2 #1237

Merged
merged 4 commits into from
Nov 14, 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
3 changes: 3 additions & 0 deletions src/Neo.Compiler.CSharp/MethodConvert/CompilerLocation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace Neo.Compiler
{
/// <summary>
/// Which file and method in the compiler generates the OpCode
/// </summary>
public class CompilerLocation
{
public int Line { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,72 @@ static class DebugInfoBuilder
&& oldSequencePointAddressToNew.TryGetValue(startInstructionAddress, out int newStartInstructionAddress))
{
newSequencePoints.Add(new JString($"{newStartInstructionAddress}{sequencePointGroups[2]}"));
previousSequencePoint = startInstructionAddress;
previousSequencePoint = newStartInstructionAddress;
}
else
newSequencePoints.Add(new JString($"{previousSequencePoint}{sequencePointGroups[2]}"));
}
method["sequence-points"] = newSequencePoints;

if (method["sequence-points-v2"] is JObject sequencePointsV2)
{
JObject newSequencePointsV2 = new();
previousSequencePoint = methodStart;
foreach ((string addr, JToken? content) in sequencePointsV2.Properties)
{
int startInstructionAddress = int.Parse(addr);
Instruction oldInstruction = oldAddressToInstruction[startInstructionAddress];
string writeAddr;
if (simplifiedInstructionsToAddress.Contains(oldInstruction))
{
startInstructionAddress = (int)simplifiedInstructionsToAddress[oldInstruction]!;
writeAddr = startInstructionAddress.ToString();
previousSequencePoint = startInstructionAddress;
}
else if (oldSequencePointAddressToNew != null
&& oldSequencePointAddressToNew.TryGetValue(startInstructionAddress, out int newStartInstructionAddress))
{
writeAddr = newStartInstructionAddress.ToString();
previousSequencePoint = newStartInstructionAddress;
if (content is JArray oldContentArray)
foreach (JToken? i in oldContentArray)
((JObject)i!)["optimization"] = Neo.Compiler.CompilationOptions.OptimizationType.Experimental.ToString().ToLowerInvariant();
if (content is JObject oldContentObject)
content["optimization"] = Neo.Compiler.CompilationOptions.OptimizationType.Experimental.ToString().ToLowerInvariant();
}
else
// previousSequencePoint unchanged
writeAddr = previousSequencePoint.ToString();
switch (newSequencePointsV2[writeAddr])
// TODO: compress newSequencePointsV2 array to non-duplicating array
{
case null:
newSequencePointsV2[writeAddr] = content;
break;
case JObject existingObject:
newSequencePointsV2[writeAddr] = new JArray() { existingObject, content };
break;
case JArray existingArray:
if (content is JArray contentArray)
newSequencePointsV2[writeAddr] = existingArray.Concat(contentArray).ToArray();
if (content is JObject contentObject)
existingArray.Add(contentObject);
break;
default:
throw new BadScriptException($"Invalid sequence-points-v2 in debug info: key {addr}, value {content}");
}
}
method["sequence-points-v2"] = newSequencePointsV2;
Copy link
Member

@shargon shargon Nov 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if there is only one entry it should be good to preserve the object, also, in what cases will be more (inline methods?)? it was checked that if it's the same information, don't duplicate it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if there is only one entry it should be good to preserve the object, also, in what cases will be more (inline methods?)? it was checked that if it's the same information, don't duplicate it?

For example, mutiple RET instructions may be compressed to 1 RET.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if there is only one entry it should be good to preserve the object, also, in what cases will be more (inline methods?)? it was checked that if it's the same information, don't duplicate it?

Something like JToken.DeepEquals comparer is needed for a HashSet, if we need to eliminate the duplicates. Not easy.

}
if (method["abi"] is JObject abi && abi["offset"] != null)
{
int offset = int.Parse(abi["offset"]!.ToString());
if (simplifiedInstructionsToAddress.Contains(oldAddressToInstruction[offset]))
offset = (int)simplifiedInstructionsToAddress[oldAddressToInstruction[offset]]!;
else
oldSequencePointAddressToNew?.TryGetValue(offset, out offset);
abi["offset"] = offset;
}
}
JArray methods = (JArray)debugInfo["methods"]!;
foreach (JToken method in methodsToRemove)
Expand Down
1 change: 0 additions & 1 deletion src/Neo.Disassembler.CSharp/Disassembler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ public static List<Instruction> ConvertScriptToInstructions(byte[] script)
if (method["abi"] is JObject abi)
{
var parsedMethod = ContractMethodDescriptor.FromJson(abi);
parsedMethod.Offset = abiMethod.Offset; // It can be optimized, we avoid to check the offset
if (!parsedMethod.Equals(abiMethod)) continue;

return method as JObject;
Expand Down
Loading