예제 #1
0
        public static void PrintScript(MjoScript script, IColoredWriter writer)
        {
            writer.ForegroundColor = ConsoleColor.DarkYellow;
            writer.Write("readmark ");
            writer.ForegroundColor = script.EnableReadMark ? ConsoleColor.Green : ConsoleColor.Red;
            writer.WriteLine(script.EnableReadMark ? "enable" : "disable");
            //writer.ForegroundColor = ConsoleColor.DarkYellow;
            //writer.Write("entrypoint ");
            //writer.ForegroundColor = ConsoleColor.Blue;
            //writer.WriteLine($"${script.EntryPointFunction.NameHash:x8}");
            writer.ResetColor();
            writer.WriteLine();

            switch (script.Representation)
            {
            case MjoScriptRepresentation.ControlFlowGraph:
                bool first = true;
                foreach (var function in script.Functions)
                {
                    if (!first)
                    {
                        writer.WriteLine();
                    }
                    first = false;
                    PrintFunction(function, writer);
                }
                break;

            default:
                foreach (var functionEntry in script.FunctionIndex)
                {
                    writer.ForegroundColor = ConsoleColor.DarkYellow;
                    writer.Write("index ");
                    writer.ForegroundColor = ConsoleColor.Blue;
                    writer.Write($"${functionEntry.NameHash:x8} ");
                    writer.ForegroundColor = ConsoleColor.DarkGray;
                    writer.Write($"0x{functionEntry.Offset:x4}");
                    if (functionEntry.Offset == script.EntryPointOffset)
                    {
                        writer.ForegroundColor = ConsoleColor.DarkYellow;
                        writer.Write(" entrypoint");
                    }
                    writer.ResetColor();
                    writer.WriteLine();
                }
                writer.WriteLine();

                foreach (var instruction in script.Instructions)
                {
                    PrintInstruction(instruction, writer);
                }
                break;
            }
        }
예제 #2
0
        public static void PrintFunction(Function function, IColoredWriter writer)
        {
            PrintFunctionHeader(function, writer);
            bool first = true;

            foreach (var block in function.Blocks)
            {
                if (!first)
                {
                    writer.WriteLine();
                }
                first = false;
                PrintBasicBlock(block, writer);
            }
            writer.WriteLine('}');
        }
예제 #3
0
        public static void PrintBasicBlock(BasicBlock block, IColoredWriter writer)
        {
            writer.Write(Indent);
            writer.ForegroundColor = ConsoleColor.Magenta;
            writer.Write(block.Name);
            writer.WriteLine(':');
            writer.ResetColor();

            foreach (var instruction in block.Instructions)
            {
                writer.Write(Indent);
                writer.Write(Indent);
                PrintInstruction(instruction, writer);
            }
        }
예제 #4
0
        public static void PrintFunctionHeader(Function function, IColoredWriter writer)
        {
            writer.ForegroundColor = ConsoleColor.Blue;
            writer.Write("func ");
            writer.Write($"${function.NameHash:x8}");
            writer.ResetColor();
            writer.Write("(");
            bool first = true;

            foreach (var type in function.ParameterTypes)
            {
                if (!first)
                {
                    writer.Write(", ");
                }
                first = false;
                writer.ForegroundColor = ConsoleColor.Cyan;
                writer.Write(type.ToString().ToLower());
                writer.ResetColor();
            }
            writer.Write(") ");
            if (function.IsEntryPoint)
            {
                writer.ForegroundColor = ConsoleColor.DarkYellow;
                writer.Write("entrypoint ");
                writer.ResetColor();
            }
            writer.Write("{");
            if (function.Script.Project != null && function.Script.Project.TryGetFunctionName(function.NameHash, out string name) ||
                Data.KnownFunctionNamesByHash.TryGetValue(function.NameHash, out name))
            {
                writer.ForegroundColor = ConsoleColor.DarkGray;
                writer.Write(" ; ");
                writer.Write(name);
                writer.ResetColor();
            }
            writer.WriteLine();
        }
예제 #5
0
        public static void PrintInstruction(Instruction instruction, IColoredWriter writer)
        {
            if (instruction.Offset != null)
            {
                writer.ForegroundColor = ConsoleColor.DarkGray;
                writer.Write($"{instruction.Offset:x4}: ");
            }

            writer.ForegroundColor = instruction.Opcode.Mnemonic == "line"
                                ? ConsoleColor.DarkGray
                                : instruction.Opcode.Mnemonic == "phi"
                                        ? ConsoleColor.DarkYellow
                                        : ConsoleColor.White;
            writer.Write($"{instruction.Opcode.Mnemonic,-13}");
            writer.ResetColor();

            foreach (char operand in instruction.Opcode.Encoding)
            {
                if (operand == '0')
                {
                    continue;
                }
                writer.Write(' ');

                if (operand == 'o' &&
                    instruction.Flags.Scope() != MjoScope.Local &&
                    instruction.VarOffset == -1)
                {
                    continue;
                }

                switch (operand)
                {
                case 't':
                    // type list
                    writer.Write('[');
                    bool first = true;
                    foreach (var type in instruction.TypeList)
                    {
                        if (!first)
                        {
                            writer.Write(", ");
                        }
                        writer.ForegroundColor = ConsoleColor.Cyan;
                        writer.Write(type.ToString().ToLower());
                        writer.ResetColor();
                        first = false;
                    }
                    writer.Write(']');
                    break;

                case 's':
                    // string data
                    if (instruction.String != null)
                    {
                        writer.ForegroundColor = ConsoleColor.DarkGreen;
                        writer.Write('"');
                        writer.Write(instruction.String.Escape());
                        writer.Write('"');
                        writer.ResetColor();
                    }
                    else
                    {
                        Debug.Assert(instruction.ExternalKey != null);
                        writer.ForegroundColor = ConsoleColor.Blue;
                        writer.Write('%');
                        writer.Write('{');
                        writer.ForegroundColor = ConsoleColor.White;
                        writer.Write(instruction.ExternalKey);
                        writer.ForegroundColor = ConsoleColor.Blue;
                        writer.Write('}');
                        writer.ForegroundColor = ConsoleColor.DarkGray;
                        if (instruction.Script != null)
                        {
                            writer.Write(" ; ");
                            writer.Write('"');
                            writer.Write(instruction.Script.ExternalizedStrings[instruction.ExternalKey].Escape());
                            writer.Write('"');
                            writer.ResetColor();
                        }
                    }
                    break;

                case 'f': {
                    // flags
                    var flags = instruction.Flags;
                    writer.ForegroundColor = ConsoleColor.Cyan;
                    writer.Write(flags.Scope().ToString().ToLower());
                    writer.Write(' ');
                    writer.Write(flags.Type().ToString().ToLower());
                    switch (flags.InvertMode())
                    {
                    case MjoInvertMode.Numeric:
                        writer.Write(" invert_numeric");
                        break;

                    case MjoInvertMode.Boolean:
                        writer.Write(" invert_boolean");
                        break;

                    case MjoInvertMode.Bitwise:
                        writer.Write(" invert_bitwise");
                        break;
                    }
                    switch (flags.Modifier())
                    {
                    case MjoModifier.PreIncrement:
                        writer.Write(" preinc");
                        break;

                    case MjoModifier.PreDecrement:
                        writer.Write(" predec");
                        break;

                    case MjoModifier.PostIncrement:
                        writer.Write(" postinc");
                        break;

                    case MjoModifier.PostDecrement:
                        writer.Write(" postdec");
                        break;
                    }
                    switch (flags.Dimension())
                    {
                    case 1:
                        writer.Write(" dim1");
                        break;

                    case 2:
                        writer.Write(" dim2");
                        break;

                    case 3:
                        writer.Write(" dim3");
                        break;
                    }
                    writer.ResetColor();
                    break;
                }

                case 'h':
                    // name hash
                    if (instruction.IsSysCall)
                    {
                        writer.ForegroundColor = ConsoleColor.Yellow;
                    }
                    else if (instruction.IsCall)
                    {
                        writer.ForegroundColor = ConsoleColor.Blue;
                    }
                    else
                    {
                        writer.ForegroundColor = ConsoleColor.Red;
                    }
                    writer.Write('$');
                    writer.Write(instruction.Hash.ToString("x8"));
                    writer.ResetColor();
                    break;

                case 'o':
                    // variable offset
                    writer.Write(instruction.VarOffset);
                    break;

                case '0':
                    // 4 byte address placeholder
                    break;

                case 'i':
                    // integer constant
                    writer.Write(instruction.IntValue);
                    break;

                case 'r':
                    // float constant
                    writer.Write(instruction.FloatValue.ToString(CultureInfo.InvariantCulture));
                    break;

                case 'a':
                    // argument count
                    writer.Write('(');
                    writer.Write(instruction.ArgumentCount);
                    writer.Write(')');
                    break;

                case 'j':
                    // jump offset
                    writer.ForegroundColor = ConsoleColor.Magenta;
                    if (instruction.JumpTarget != null)
                    {
                        Debug.Assert(instruction.Block != null);
                        writer.Write('@');
                        writer.Write(instruction.JumpTarget.Name);
                    }
                    else
                    {
                        Debug.Assert(instruction.Block == null);
                        PrintRelativeJump(instruction.JumpOffset !.Value, writer);
                    }
                    writer.ResetColor();
                    break;

                case 'l':
                    // line number
                    writer.ForegroundColor = ConsoleColor.DarkGray;
                    writer.Write('#');
                    writer.Write(instruction.LineNumber);
                    writer.ResetColor();
                    break;

                case 'c':
                    // switch case table
                    first = true;
                    if (instruction.SwitchTargets != null)
                    {
                        Debug.Assert(instruction.Block != null);
                        foreach (var targetBlock in instruction.SwitchTargets)
                        {
                            if (!first)
                            {
                                writer.Write(", ");
                            }
                            writer.ForegroundColor = ConsoleColor.Magenta;
                            writer.Write('@');
                            writer.Write(targetBlock.Name);
                            writer.ResetColor();
                            first = false;
                        }
                    }
                    else
                    {
                        Debug.Assert(instruction.Block == null);
                        foreach (int offset in instruction.SwitchOffsets)
                        {
                            if (!first)
                            {
                                writer.Write(", ");
                            }
                            writer.ForegroundColor = ConsoleColor.Magenta;
                            PrintRelativeJump(offset, writer);
                            writer.ResetColor();
                            first = false;
                        }
                    }
                    break;

                case 'p':
                    // phi node
                    first = true;
                    if (instruction is PhiInstruction phi)
                    {
                        foreach (var predecessor in phi.Block.Predecessors)
                        {
                            if (!first)
                            {
                                writer.Write(", ");
                            }
                            writer.ForegroundColor = ConsoleColor.Magenta;
                            writer.Write('@');
                            writer.Write(predecessor.Name);
                            writer.ResetColor();
                            first = false;
                        }
                    }
                    else
                    {
                        throw new Exception("Only phi instructions are allowed to have the 'p' encoding specifier");
                    }
                    break;
                }
            }

            if (instruction.IsSysCall && Data.KnownSyscallNamesByHash.TryGetValue(instruction.Hash, out string name))
            {
                writer.ForegroundColor = ConsoleColor.DarkGray;
                writer.Write(" ; $");
                writer.Write(name);
                writer.ResetColor();
            }
            else if (instruction.IsCall)
            {
                var  project = instruction.Script?.Project;
                uint hash    = instruction.Hash;
                if (project != null && project.TryGetFunctionName(hash, out string calleeName) ||
                    Data.KnownFunctionNamesByHash.TryGetValue(hash, out calleeName))
                {
                    writer.ForegroundColor = ConsoleColor.DarkGray;
                    writer.Write(" ; ");
                    writer.Write(calleeName);
                    writer.ResetColor();
                }
                else if (project != null && project.FunctionMap.TryGetValue(hash, out var functions) && functions.Any())
                {
                    writer.ForegroundColor = ConsoleColor.DarkGray;
                    writer.Write(" ; declared in ");
                    writer.Write(functions[0].DeclaringScript);
                    writer.ResetColor();
                }
            }
            else if (instruction.IsLoad || instruction.IsStore)
            {
                uint hash = instruction.Hash;
                if (Data.KnownVariableNamesByHash.TryGetValue(hash, out string varName))
                {
                    writer.ForegroundColor = ConsoleColor.DarkGray;
                    writer.Write(" ; ");
                    writer.Write(varName);
                    writer.ResetColor();
                }
            }

            writer.WriteLine();
        }
예제 #6
0
 public static void PrintLabel(BasicBlock block, IColoredWriter writer)
 {
     writer.ForegroundColor = ConsoleColor.Magenta;
     writer.WriteLine($"{block.Name}:");
     writer.ResetColor();
 }