public static IEnumerable <Group> GroupCode(CacheFile cache, FunctionDefinition function)
        {
            var instance = new InstructionGrouper(cache, function);

            foreach (var group in instance.GroupCode())
            {
                yield return(group);
            }
        }
예제 #2
0
        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("}");
        }