コード例 #1
0
        public static IEnumerable <Group> GroupBody(FunctionDefinition function)
        {
            var instance = new InstructionGrouper(function);

            foreach (var group in instance.GroupBody())
            {
                yield return(group);
            }
        }
コード例 #2
0
        public static IEnumerable <Group> GroupCode(CacheFile cache, FunctionDefinition function)
        {
            var instance = new InstructionGrouper(cache, function);

            foreach (var group in instance.GroupCode())
            {
                yield return(group);
            }
        }
コード例 #3
0
        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));
                }
            }
        }
コード例 #4
0
        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("}");
        }
コード例 #5
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("}");
        }