public static IEnumerable <Group> GroupBody(FunctionDefinition function) { var instance = new InstructionGrouper(function); foreach (var group in instance.GroupBody()) { yield return(group); } }
public static IEnumerable <Group> GroupCode(CacheFile cache, FunctionDefinition function) { var instance = new InstructionGrouper(cache, function); foreach (var group in instance.GroupCode()) { yield return(group); } }
private static void DumpFunction(FunctionDefinition function, StringBuilder sb, bool validate) { if (function.ReturnType == null) { sb.Append("void "); } else { sb.Append($"{GetPath(function.ReturnType)} "); } sb.AppendLine(GetPath(function)); if (function.Flags != FunctionFlags.None) { sb.AppendLine($" // Flags : {function.Flags}"); } if (function.Parameters != null) { foreach (var parameter in function.Parameters) { sb.AppendLine($" // {parameter} : {parameter.Type}"); } } if (function.Locals != null) { foreach (var local in function.Locals) { sb.AppendLine($" // {local} : {local.Type}"); } } var groups = InstructionGrouper.GroupBody(function).ToArray(); var groupStack = new LinkedList <(InstructionGrouper.Group, int)>(); foreach (var group in groups) { groupStack.AddLast((group, 0)); } Opcode?previousOp = null; while (groupStack.Count > 0) { (var group, var depth) = groupStack.First.Value; groupStack.RemoveFirst(); var instruction = group.Instruction; if (previousOp == Opcode.NoOperation || previousOp == Opcode.ReturnWithValue) { if (instruction.Op != Opcode.Switch && instruction.Op != Opcode.SwitchCase && instruction.Op != Opcode.SwitchDefault) { //sb.AppendLine(); } } if (instruction.LoadInfo == null) { sb.Append($" (@0x?????? ????) @????"); } else { var loadInfo = instruction.LoadInfo.Value; long absolutePosition; long relativePosition; if (validate) { absolutePosition = loadInfo.BasePosition + function.LoadPosition; relativePosition = loadInfo.BasePosition - function.BodyLoadPosition; } else { absolutePosition = loadInfo.BasePosition; relativePosition = loadInfo.BasePosition - function.BodyLoadPosition; } sb.Append($" (@0x{absolutePosition:X6} {relativePosition,4}) @{loadInfo.Offset,-4}"); } sb.Append(" | "); DumpInstruction(instruction, sb, depth); foreach (var child in group.Children.Reverse <InstructionGrouper.Group>()) { groupStack.AddFirst((child, depth + 1)); } } }
private static void DumpFunction(CacheFile cacheFile, FunctionDefinition function, StringBuilder sb, bool validate) { sb.Append("function "); sb.Append(function.ToPath()); sb.Append("("); for (int i = 0; i < function.Parameters.Count; i++) { var parameter = function.Parameters[i]; if (i > 0) { sb.Append(", "); } sb.Append($"{parameter.ToName()}: {parameter.Type.ToPath()}"); } sb.Append(")"); if (function.ReturnType != null) { sb.Append($" : {function.ReturnType.ToPath()} "); } sb.AppendLine(); sb.AppendLine("{"); const FunctionFlags ignoredFlags = FunctionFlags.HasReturnValue | FunctionFlags.HasParameters | FunctionFlags.HasLocals | FunctionFlags.HasBody; var flags = function.Flags & ~ignoredFlags; if (flags != FunctionFlags.None) { sb.AppendLine($" // Flags : {flags}"); } if (function.Locals != null) { foreach (var local in function.Locals) { sb.AppendLine($" var {local.ToName()} : {local.Type.ToPath()};"); } } var groups = InstructionGrouper.GroupBody(cacheFile, function).ToArray(); var groupStack = new LinkedList <(InstructionGrouper.Group, int)>(); foreach (var group in groups) { groupStack.AddLast((group, 0)); } int opcodeIndex = 0; while (groupStack.Count > 0) { var(group, depth) = groupStack.First.Value; groupStack.RemoveFirst(); var instruction = group.Instruction; if (instruction.LoadInfo == null) { sb.Append($" (@0x?????? ????) @???? #{opcodeIndex++,-4}"); } else { var loadInfo = instruction.LoadInfo.Value; long absolutePosition; long relativePosition; if (validate) { absolutePosition = loadInfo.BasePosition + function.LoadPosition; relativePosition = loadInfo.BasePosition - function.BodyLoadPosition; } else { absolutePosition = loadInfo.BasePosition; relativePosition = loadInfo.BasePosition - function.BodyLoadPosition; } sb.Append($" (@0x{absolutePosition:X6} {relativePosition,4}) @{loadInfo.Offset,-4} #{opcodeIndex++,-4}"); } sb.Append(" | "); DumpInstruction(instruction, sb, depth); foreach (var child in group.Children.Reverse <InstructionGrouper.Group>()) { groupStack.AddFirst((child, depth + 1)); } } sb.AppendLine("}"); }
private static void DumpFunction(CacheFile cacheFile, FunctionDefinition function, StringBuilder sb, bool validate) { var functionName = function.ToName(); if (function.Name != functionName) { sb.AppendLine($"// {function.Name}"); } sb.AppendLine(GetFunctionDeclaration(function, fullName: true)); sb.AppendLine("{"); const FunctionFlags ignoredFlags = FunctionFlags.HasReturnValue | FunctionFlags.HasParameters | FunctionFlags.HasLocals | FunctionFlags.HasCode; var flags = function.Flags & ~ignoredFlags; if (flags != FunctionFlags.None) { sb.AppendLine($" // Flags : {flags}"); } if (function.Locals != null && function.Locals.Count > 0) { foreach (var local in function.Locals) { sb.AppendLine($" var {local.ToName()} : {local.Type.ToPath()};"); } sb.AppendLine(); } var groups = InstructionGrouper.GroupCode(cacheFile, function).ToArray(); var groupStack = new LinkedList <(InstructionGrouper.Group group, string indent, bool isLast)>(); for (int i = 0; i < groups.Length; i++) { groupStack.AddLast((groups[i], "", i == groups.Length - 1)); } int opcodeIndex = 0; while (groupStack.Count > 0) { var(group, indent, isLast) = groupStack.First.Value; groupStack.RemoveFirst(); var instruction = group.Instruction; sb.Append(' '); if (instruction.LoadPosition < 0) { sb.Append($" (@0x?????? ????)"); } else { var loadPosition = instruction.LoadPosition; long absolutePosition; long relativePosition; if (validate) { absolutePosition = loadPosition + function.LoadPosition; relativePosition = loadPosition - function.CodeLoadPosition; } else { absolutePosition = loadPosition; relativePosition = loadPosition - function.CodeLoadPosition; } sb.Append($" (@0x{absolutePosition:X6} {relativePosition,4})"); } sb.Append($" #{opcodeIndex++,-4}"); sb.Append(indent); sb.Append(isLast == true ? " └─" : " ├─"); DumpInstruction(instruction, sb); var lastChildIndex = group.Children.Count - 1; for (int i = lastChildIndex; i >= 0; i--) { var child = group.Children[i]; groupStack.AddFirst((child, indent + (isLast == true ? " " : " │ "), i == lastChildIndex)); } } sb.AppendLine("}"); }