public static IEnumerable <Group> GroupBody(FunctionDefinition function) { var instance = new InstructionGrouper(function); foreach (var group in instance.GroupBody()) { yield return(group); } }
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(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)); } } }