Skip to content

Commit

Permalink
Added debug support for T7, fixed self calls, changed function id gen…
Browse files Browse the repository at this point in the history
…eration, fix for multiple returns order, fixed varargs
  • Loading branch information
JariKCoding committed Nov 6, 2021
1 parent 2bf83d3 commit cfc5c51
Show file tree
Hide file tree
Showing 32 changed files with 569 additions and 32 deletions.
4 changes: 2 additions & 2 deletions CoDLuaDecompiler.AssetExporter/AssetExport.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
Expand Down Expand Up @@ -115,7 +115,7 @@ private void HandleLuaFiles(List<LuaFileData> luaFiles, IGame game, bool dumpRaw
}
}
var luaFile = LuaFileFactory.Create(file.Reader);
var luaFile = LuaFileFactory.Create(file.Reader, null);
try
{
if (String.IsNullOrEmpty(hash))
Expand Down
12 changes: 10 additions & 2 deletions CoDLuaDecompiler.CLI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Program
{
private readonly IAssetExport _assetExport;
private readonly IDecompiler _decompiler;
public static bool UsesDebugInfo = false;

public Program(IDecompiler decompiler, IAssetExport assetExport)
{
Expand All @@ -25,7 +26,7 @@ private void HandleFile(string filePath)
try
{
// parse lua file
var file = LuaFileFactory.Create(filePath);
var file = LuaFileFactory.Create(filePath, UsesDebugInfo);

// decompile file
var output = _decompiler.Decompile(file);
Expand All @@ -47,6 +48,13 @@ private static List<string> ParseFilesFromArgs(IEnumerable<string> args)
{
var files = new List<string>();

string luaExtension = "*.lua*";
if (args.Contains("--debug"))
{
UsesDebugInfo = true;
luaExtension = "*.luac";
}

foreach (var arg in args)
{
if (!File.Exists(arg) && !Directory.Exists(arg))
Expand All @@ -57,7 +65,7 @@ private static List<string> ParseFilesFromArgs(IEnumerable<string> args)
// if so only includes file that are of ".lua" or ".luac" extension
if (attr.HasFlag(FileAttributes.Directory))
{
files.AddRange(Directory.GetFiles(arg, "*.lua*", SearchOption.AllDirectories).ToList());
files.AddRange(Directory.GetFiles(arg, luaExtension, SearchOption.AllDirectories).ToList());
}
else if (Path.GetExtension(arg).Contains(".lua"))
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System.Linq;
using CoDLuaDecompiler.Decompiler.IR.Functions;
using CoDLuaDecompiler.Decompiler.IR.Instruction;

namespace CoDLuaDecompiler.Decompiler.Analyzers.Havok
{
public class DebugLineInfoAnalyzer : IAnalyzer
{
public void Analyze(Function f)
{
if (f.FunctionDebugInfo == null)
return;

AddLines(f);
}

public void AddLines(Function f)
{
f.Closures.ForEach(AddLines);
for (int bi = 0; bi < f.Blocks.Count; bi++)
{
var b = f.Blocks[bi];
if (b.Instructions.Count <= 1)
continue;
var prevLine = b.Instructions[0].LineLocation == 0 && bi > 0 ? b.Instructions[1].LineLocation - 1 : b.Instructions[0].LineLocation;
var prevLength = b.Instructions[0].ToString()!.Count(s => s == '\n') + 1;
for (int i = 1; i < b.Instructions.Count; i++)
{
var instr = b.Instructions[i];
for (int j = 0; j < instr.LineLocation - prevLine - prevLength; j++)
{
b.Instructions.Insert(i, new NewLine());
i++;
}

prevLine = instr.LineLocation == 0 ? prevLine + 1 : instr.LineLocation;
prevLength = instr.ToString()!.Count(s => s == '\n') + 1;
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ int LocalIdentifyVisit(BasicBlock b, HashSet<Identifier> localRegs)
{
if (use.DefiningInstruction != null &&
use.DefiningInstruction is Assignment a &&
(a.Left.Count() == 1 || a.Left.Count > 1 && a.Right is Constant {Type: ValueType.Nil}) && !(a.Right is IdentifierReference {HasIndex: false} ir && ir.GetUses(true).Count > 1) &&
(a.LocalAssignments == null || a.LocalAssignments.Count == 0) &&
(a.Left.Count() == 1 || a.Left.Count > 1 && a.Right is Constant {Type: ValueType.Nil or ValueType.Boolean}) && !(a.Right is IdentifierReference {HasIndex: false} ir && ir.GetUses(true).Count > 1) &&
((use.UseCount == 1 && ((i - 1 >= 0 && b.Instructions[i - 1] == use.DefiningInstruction) || (inst is Assignment a2 && a2.IsListAssignment)) && !definitelyLocal.Contains(use)) || a.PropagateAlways) &&
!a.Left[0].Identifier.IsClosureBound)
{
Expand Down Expand Up @@ -335,7 +336,7 @@ private bool PropagateFunctionCallOnSelf(Function f)
{
if (expression is FunctionCall {Function: IdentifierReference ir} fc && ir.TableIndices.Count >= 1 &&
ir.TableIndices[^1] is Constant {Type: ValueType.String} && fc.Arguments.Any() &&
fc.Arguments[0] is IdentifierReference {HasIndex: false} argIr &&
fc.Arguments[0] is IdentifierReference {HasIndex: false} argIr && !fc.IsFunctionCalledOnSelf &&
(ir == argIr || ir.HasIndex && ir.Identifier == argIr.Identifier))
{
fc.Arguments.RemoveAt(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ public void Analyze(Function f)
{
il.Expressions.Add(new ListAssignment(a2.Left[0].TableIndices[0], a2.Right));
}
if (a2.LocalAssignments != null)
{
a.LocalAssignments.AddRange(a2.LocalAssignments);
}
a2.Left[0].Identifier.UseCount--;
b.Instructions.RemoveAt(i + 1);
initIndex++;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using System.Collections.Generic;
using System.Linq;
using CoDLuaDecompiler.Decompiler.IR.Expression;
using CoDLuaDecompiler.Decompiler.IR.Functions;
using CoDLuaDecompiler.Decompiler.IR.Identifiers;
using CoDLuaDecompiler.Decompiler.IR.Instruction;

namespace CoDLuaDecompiler.Decompiler.Analyzers.Havok
{
public class LoopIdentifierReplacementAnalyzer : IAnalyzer
{
// We need to replace the identifiers used by loops because the ssa doesn't notice it's used in different scope
public void Analyze(Function f)
{
for (int i = 1; i < f.Blocks.Count; i++)
{
var b = f.Blocks[i];

if (!b.IsLoopHead)
continue;



if (b.Instructions.Any() && b.Instructions[0] is Assignment a && a.Left.Count == 2 && a.Right is FunctionCall fc && fc.Arguments.Count == 2)
{
if (fc.Function is IdentifierReference ir2 && ir2.Identifier.DefiningInstruction is Assignment a2 && a2.Left.Count == 3 && b.LoopLatches.Any() &&
b.LoopLatches[0].Instructions.Any() && b.LoopLatches[0].Instructions[0] is Assignment a3 && a3.Left.Count == 1 && a3.Right is IdentifierReference ir && ir.Identifier == a.Left[0].Identifier)
{
var newFuncId = f.SymbolTable.GetNewRegister();
var newIterId = f.SymbolTable.GetNewRegister();
var newIndexId = f.SymbolTable.GetNewRegister();
var oldFuncId = ((IdentifierReference)fc.Function).Identifier;
var oldIterId = ((IdentifierReference)fc.Arguments[0]).Identifier;
var oldIndexId = ((IdentifierReference)fc.Arguments[1]).Identifier;
((IdentifierReference) fc.Function).Identifier = newFuncId;
((IdentifierReference) fc.Arguments[0]).Identifier = newIterId;
((IdentifierReference) fc.Arguments[1]).Identifier = newIndexId;
a2.Left[0].Identifier = newFuncId;
a2.Left[1].Identifier = newIterId;
a2.Left[2].Identifier = newIndexId;
a3.Left[0].Identifier = newIndexId;
}

var newKeyId = f.SymbolTable.GetNewRegister();
var newValueId = f.SymbolTable.GetNewRegister();
var oldKeyId = a.Left[0].Identifier;
var oldValueId = a.Left[1].Identifier;

for (int j = i + 1; j < f.Blocks.Count; j++)
{
var b2 = f.Blocks[j];
if (b2 == b.LoopFollow)
break;

for (int k = 0; k < b2.Instructions.Count; k++)
{
var instr = b2.Instructions[k];
ReplaceRegisterUses(oldKeyId, newKeyId, instr.GetUses(true), instr);
ReplaceRegisterUses(oldKeyId, newKeyId, instr.GetDefines(true), instr);
ReplaceRegisterUses(oldValueId, newValueId, instr.GetUses(true), instr);
ReplaceRegisterUses(oldValueId, newValueId, instr.GetDefines(true), instr);
}
}

a.Left[0].Identifier = newKeyId;
a.Left[1].Identifier = newValueId;
}
}
}

private void ReplaceRegisterUses(Identifier original, Identifier newId, HashSet<Identifier> ids, IInstruction instr)
{
foreach (var uses in ids)
{
if (uses == original)
{
instr.ReplaceUses(uses, new IdentifierReference(newId));
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ public void Analyze(Function f)
a2.Right is Constant {Type: ValueType.Nil})
{
a1.Left.AddRange(a2.Left);
if (a1.LocalAssignments == null)
a1.LocalAssignments = a2.LocalAssignments;
else
a1.LocalAssignments.AddRange(a2.LocalAssignments);
f.Instructions.RemoveAt(i + 1);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ public void Analyze(Function f)
if (ir == null || type == BinOperationType.None || !(a.Left[0].Identifier == ir.Identifier && a2.Left[0].Identifier == ir.Identifier))
return;

f.Instructions.Insert(f.Instructions.IndexOf(j.Dest), new Assignment(ir.Identifier, new BinOp(new IdentifierReference(a.Left[0].Identifier), a2.Right, type)));
f.Instructions.Insert(f.Instructions.IndexOf(j.Dest), new Assignment(ir.Identifier, new BinOp(new IdentifierReference(a.Left[0].Identifier), a2.Right, type))
{
LocalAssignments = a2.LocalAssignments,
LineLocation = a2.LineLocation
});

if (l.UsageCount > 1)
l.UsageCount--;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,16 @@ public void Analyze(Function f)
{
for (int i = f.Instructions.Count - 1; i > 0; i--)
{
if (f.Instructions[i] is Data)
if (f.Instructions[i] is Data d1)
{
if (f.Instructions[i - 1] is Data d2)
{
d2.Locals = d1.Locals;
}
else if (f.Instructions[i - 1] is Assignment a)
{
a.LocalAssignments = d1.Locals;
}
f.Instructions.RemoveAt(i);
i++;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using CoDLuaDecompiler.Decompiler.IR.Functions;
using CoDLuaDecompiler.Decompiler.IR.Identifiers;
using CoDLuaDecompiler.Decompiler.IR.Instruction;
using CoDLuaDecompiler.Decompiler.LuaFile.Havok.Debug;
using CoDLuaDecompiler.Decompiler.LuaFile.Structures.LuaFunction.Structures;
using ValueType = CoDLuaDecompiler.Decompiler.IR.Identifiers.ValueType;

Expand Down Expand Up @@ -41,14 +42,23 @@ public void Analyze(Function f)
{
if (i is Assignment a)
{
int ll = 0;
foreach (var l in a.Left)
{
if (!l.HasIndex && l.Identifier.IdentifierType == IdentifierType.Register && !renamed.Contains(l.Identifier))
{
renamed.Add(l.Identifier);
l.Identifier.Name = $@"f{f.Id}_local{localCounter}";
localCounter++;
if (a.LocalAssignments != null && ll < a.LocalAssignments.Count)
{
l.Identifier.Name = a.LocalAssignments[ll].Name;
}
else
{
l.Identifier.Name = $@"f{f.Id}_local{localCounter}";
localCounter++;
}
}
ll++;

if (!l.HasIndex &&
l.Identifier.IdentifierType == IdentifierType.Upvalue &&
Expand All @@ -62,6 +72,9 @@ public void Analyze(Function f)
}
}
}

if (f.FunctionDebugInfo != null)
return;

// Adding special variable names for LUI widgets
foreach (var b in f.Blocks)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Linq;
using CoDLuaDecompiler.Decompiler.IR.Functions;
using CoDLuaDecompiler.Decompiler.IR.Identifiers;
using CoDLuaDecompiler.Decompiler.IR.Instruction;

namespace CoDLuaDecompiler.Decompiler.Analyzers.Havok
{
Expand Down Expand Up @@ -47,6 +48,8 @@ Identifier NewName(Identifier orig)
counter++;
newName.IdentifierType = IdentifierType.Register;
newName.OriginalIdentifier = orig;
newName.UpvalueVarName = orig.UpvalueVarName;
newName.UpValueResolved = orig.UpValueResolved;
return newName;
}

Expand Down Expand Up @@ -89,7 +92,7 @@ void visit(CFG.BasicBlock b, Dictionary<Identifier, Identifier> replacements)
}
foreach (var def in instruction.GetDefines(true))
{
/*if (instruction is Assignment a && a.LocalAssignments != null && !reassigned)
if (instruction is Assignment a && a.LocalAssignments != null && a.LocalAssignments.Count != 0 && !reassigned && !def.IsClosureBound)
{
var newname = NewName(def);
instruction.RenameDefines(def, newname);
Expand All @@ -106,7 +109,7 @@ void visit(CFG.BasicBlock b, Dictionary<Identifier, Identifier> replacements)
changed = true;
reassigned = true;
}
else*/ if (newreplacements.ContainsKey(def))
else if (newreplacements.ContainsKey(def))
{
instruction.RenameDefines(def, newreplacements[def]);
changed = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,21 @@ namespace CoDLuaDecompiler.Decompiler.Analyzers.Havok
{
public class VarargListAssignmentAnalyzer : IAnalyzer
{
// Adds the vararg to a table
public void Analyze(Function f)
{
// Pretty hacky way to do this, don't know another way to add it if the table already has items
for (int i = 0; i < f.Instructions.Count - 1; i++)
{
if (f.Instructions[i] is Assignment {IsIndeterminateVararg: true} && f.Instructions[i + 1] is Assignment
if (f.Instructions[i] is Assignment {IsIndeterminateVararg: true} a1 && f.Instructions[i + 1] is Assignment
{
IsIndeterminateVararg: true
} a3)
{
f.Instructions[i] = new Assignment(new List<IdentifierReference>(), new FunctionCall(new IdentifierReference(new Identifier() {Name = "table.insert", IdentifierType = IdentifierType.Global}), new List<IExpression>(){new IdentifierReference(f.SymbolTable.GetRegister(a3.VarargAssignmentReg)), new IdentifierReference(f.SymbolTable.GetVarargs())}));
var idRef = new IdentifierReference(a3.Left[0].Identifier);
idRef.TableIndices.Add(new Constant(ValueType.VarArgs, -1));
var assn = new Assignment(idRef, new IdentifierReference(f.SymbolTable.GetVarargs()));
assn.LocalAssignments = a3.LocalAssignments;
f.Instructions[i] = assn;
f.Instructions.RemoveAt(i + 1);
}
}
Expand Down
3 changes: 3 additions & 0 deletions CoDLuaDecompiler.Decompiler/Analyzers/HavokAnalyzerList.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using CoDLuaDecompiler.Decompiler.Analyzers.Havok;
using CoDLuaDecompiler.Decompiler.Analyzers.Shared;

namespace CoDLuaDecompiler.Decompiler.Analyzers
{
Expand Down Expand Up @@ -45,7 +46,9 @@ public List<IAnalyzer> GetAnalyzers()
new DeadAssignmentsAnalyzer(),
new ExpressionPropagationAnalyzer(),
new LivenessNoInterferenceAnalyzer(),
new MultipleReturnsOrderAnalyzer(),

//new LoopIdentifierReplacementAnalyzer(),
// Convert out of SSA and rename variables
new SSADropSubscriptsAnalyzer(),
new LocalDeclarationsAnalyzer(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public List<IAnalyzer> GetAnalyzers()
new PrePostLoadFuncAnalyzer(),
new PostRequireStatementsNewLine(),
new UIModelFunctionValueVarNamesAnalyzer(),
//new DebugLineInfoAnalyzer(),
};
}
}
Expand Down
2 changes: 2 additions & 0 deletions CoDLuaDecompiler.Decompiler/Analyzers/LuaJitAnalyzerList.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using CoDLuaDecompiler.Decompiler.Analyzers.Havok;
using CoDLuaDecompiler.Decompiler.Analyzers.LuaJit;
using CoDLuaDecompiler.Decompiler.Analyzers.Shared;

namespace CoDLuaDecompiler.Decompiler.Analyzers
{
Expand Down Expand Up @@ -45,6 +46,7 @@ public List<IAnalyzer> GetAnalyzers()
new DeadAssignmentsAnalyzer(),
new ExpressionPropagationAnalyzer(),
new LivenessNoInterferenceAnalyzer(),
new MultipleReturnsOrderAnalyzer(),

// Convert out of SSA and rename variables
new SSADropSubscriptsAnalyzer(),
Expand Down
Loading

0 comments on commit cfc5c51

Please sign in to comment.