コード例 #1
0
ファイル: PapyrusCodeGenerator.cs プロジェクト: madawe/Paprus
        public string GetMethodSourceCode(ICodeResult result, PapyrusMethodDefinition method)
        {
            var sb = new StringBuilder();

            var methodBody = result.DecompiledSourceCode;
            var isNone     = method.ReturnTypeName.Value.ToLower() == "none";
            var name       = method.Name?.Value;

            if (string.IsNullOrEmpty(name))
            {
                if (method.IsSetter)
                {
                    name = "Set";
                }
                if (method.IsSetter)
                {
                    name = "Get";
                }
            }
            var returnValue = "";
            var fDesc       = "Function";

            if (method.IsEvent)
            {
                fDesc = "Event";
            }
            else if (!isNone)
            {
                returnValue = method.ReturnTypeName.Value + " ";
            }

            var last = "";

            if (method.IsNative)
            {
                last += " Native";
            }
            if (method.IsGlobal)
            {
                last += " Global";
            }

            var parameters = GetParameterString(method.Parameters);

            sb.AppendLine(returnValue + fDesc + " " + name + parameters + last);

            if (!string.IsNullOrEmpty(method.Documentation?.Value))
            {
                sb.AppendLine("{ " + method.Documentation?.Value + " }");
            }

            sb.AppendLine(IndentedLines(1, methodBody.Trim('\n', '\r')));

            if (!method.IsNative)
            {
                sb.AppendLine("End" + fDesc);
            }

            return(sb.ToString().Trim('\n'));
        }
コード例 #2
0
        public string FindDelegateInvokeReference(IDelegatePairDefinition pairDefinitions,
                                                  PapyrusMethodDefinition papyrusMethod)
        {
            // In case this is a delegate inside a delegate...
            // _UtilizeDelegate4_b__0
            var functionName = papyrusMethod.Name.Value;
            var originalName = papyrusMethod.Name.Value;

            if (functionName.StartsWith("_") && functionName.Contains("b_"))
            {
                functionName = functionName.Split('_')[1];
                papyrusMethod.DelegateInvokeCount++;
            }

            var delegateMethod =
                pairDefinitions.DelegateMethodDefinitions.FirstOrDefault(
                    del =>
                    del.Name.Contains("_" + functionName + "_") &&
                    del.Name.EndsWith("_" + papyrusMethod.DelegateInvokeCount));

            if (delegateMethod == null)
            {
                delegateMethod =
                    pairDefinitions.DelegateMethodDefinitions.FirstOrDefault(
                        del =>
                        del.Name.Contains("_" + functionName + "_") && del.Name.Contains("b_") &&
                        del.Name != originalName);
            }
            papyrusMethod.DelegateInvokeCount++;
            return(delegateMethod?.Name);
        }
コード例 #3
0
        /// <summary>
        ///     Decompiles the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="method">The method.</param>
        /// <returns></returns>
        public IPapyrusDecompilerResult Decompile(IDecompilerContext context, PapyrusMethodDefinition method)
        {
            context.SetTargetMethod(method);


            flowAnalyzer.FindVarTypes();

            flowAnalyzer.CreateFlowBlocks();

            flowAnalyzer.MapLongLivedTempVariables();

            flowAnalyzer.AssignLongLivedTempVariables();

            flowAnalyzer.RebuildExpressionsInBlocks();

            flowAnalyzer.RebuildBooleanOperators(0, method.Body.Instructions.Count);

            var tree = flowAnalyzer.RebuildControlFlow(0, method.Body.Instructions.Count);

            tree = flowAnalyzer.Finalize(tree);

            var result = codeGenerator.Generate(tree);

            var sourceCode = codeGenerator.GetMethodSourceCode(result, method);


            return(new PapyrusDecompilerResult(sourceCode, null));
        }
コード例 #4
0
        private void WriteMethod(PapyrusMethodDefinition method)
        {
            pexWriter.Write(method.ReturnTypeName);
            pexWriter.Write(method.Documentation);
            pexWriter.Write(method.UserFlags);
            pexWriter.Write(method.Flags);

            pexWriter.Write((short)method.Parameters.Count);
            foreach (var param in method.Parameters)
            {
                WriteParameter(param);
            }

            pexWriter.Write((short)method.Body.Variables.Count);
            foreach (var variable in method.Body.Variables)
            {
                WriteVariable(variable);
            }

            pexWriter.Write((short)method.Body.Instructions.ToArray().Count(i => !i.TemporarilyInstruction));
            foreach (var instruction in method.Body.Instructions)
            {
                if (!instruction.TemporarilyInstruction)
                {
                    WriteInstruction(instruction);
                }
            }
        }
コード例 #5
0
 public PapyrusControlFlowGraphBuilder(PapyrusMethodDefinition method)
 {
     this.method = method;
     entryPoint  = new PapyrusControlFlowNode(0, 0, PapyrusControlFlowNodeType.EntryPoint);
     nodes.Add(entryPoint);
     regularExit = new PapyrusControlFlowNode(1, -1, PapyrusControlFlowNodeType.RegularExit);
     nodes.Add(regularExit);
 }
コード例 #6
0
 public IEnumerable <PapyrusInstruction> ProcessInstructions(PapyrusAssemblyDefinition targetPapyrusAssembly,
                                                             PapyrusTypeDefinition targetPapyrusType,
                                                             PapyrusMethodDefinition targetPapyrusMethod, MethodDefinition method, MethodBody body,
                                                             Collection <Instruction> instructions,
                                                             PapyrusCompilerOptions options)
 {
     throw new NotImplementedException();
 }
コード例 #7
0
        private MethodAttributes GetMethodAttributes(PapyrusMethodDefinition m)
        {
            var attrs = MethodAttributes.Public;

            if (m.IsNative || m.IsGlobal)
            {
                attrs |= MethodAttributes.Static;
            }

            return(attrs);
        }
コード例 #8
0
 public PapyrusReferenceValueViewModel(List <PapyrusAssemblyDefinition> loadedAssemblies,
                                       PapyrusTypeDefinition currentType, PapyrusMethodDefinition currentMethod, OpCodeArgumentDescription desc)
 {
     this.loadedAssemblies = loadedAssemblies;
     this.currentType      = currentType;
     this.currentMethod    = currentMethod;
     this.desc             = desc;
     if (currentMethod != null)
     {
         ReferenceCollection = new ObservableCollection <PapyrusMemberReference>(currentMethod.GetVariables());
     }
     ComboBoxItems             = new ObservableCollection <FrameworkElement>(CreateComboBoxItems());
     SelectedReferenceType     = ComboBoxItems.First() as ComboBoxItem;
     ReferenceSelectionVisible = Visibility.Visible;
 }
コード例 #9
0
ファイル: MethodBodyOptimizer.cs プロジェクト: madawe/Paprus
        public IMethodBodyOptimizerResult Optimize(PapyrusMethodDefinition method)
        {
            var methodBody        = method.Body;
            var variables         = method.Body.Variables;
            var success           = false;
            var optimizationRatio = 0d;

            // 1. find all assignment on these variables
            // 2. find all usage on the variables
            // - If a variable is never assigned or never used, it is safe to be removed
            // - If a variable is assigned but never used, it could still be needed.
            //     (Consider this: You have a property getter method that does some logic more than just returning the value)
            //      -- So, depending on what kind of assigning; it should find out if its safe to be removed or not.


            return(new MethodBodyOptimizerResult(method, success, optimizationRatio));
        }
コード例 #10
0
        public void TestPapyrusMethodFlags()
        {
            var m = new PapyrusMethodDefinition(PapyrusAssemblyDefinition.CreateAssembly(PapyrusVersionTargets.Fallout4));

            m.SetFlags(PapyrusMethodFlags.Global);
            Assert.IsTrue(m.IsGlobal);
            Assert.IsFalse(m.IsNative);

            m.IsNative = true;
            Assert.IsTrue(m.IsGlobal);
            Assert.IsTrue(m.IsNative);


            m.IsGlobal = false;
            Assert.IsFalse(m.IsGlobal);
            Assert.IsTrue(m.IsNative);
        }
コード例 #11
0
        /// <summary>
        ///     Builds the type index, mapping a table reference to its type.
        /// </summary>
        public void BuildVarTypeMap(PapyrusAssemblyDefinition asm, PapyrusMethodDefinition method)
        {
            varTypes.Clear();
            var obj = asm.Types.First();

            foreach (var t in obj.Fields)
            {
                varTypes[t.Name.Value.ToLower()] = t.TypeName;
            }
            foreach (var t in method.Parameters)
            {
                varTypes[t.Name.Value.ToLower()] = t.TypeName.Value;
            }
            foreach (var t in method.GetVariables())
            {
                varTypes[t.Name.Value.ToLower()] = t.TypeName.Value;
            }
        }
コード例 #12
0
        public PapyrusReferenceAndConstantValueViewModel(List <PapyrusAssemblyDefinition> loadedAssemblies,
                                                         PapyrusTypeDefinition currentType,
                                                         PapyrusMethodDefinition currentMethod, OpCodeArgumentDescription desc, PapyrusPrimitiveType[] argumentTypes)
        {
            this.loadedAssemblies = loadedAssemblies;
            this.currentType      = currentType;
            this.currentMethod    = currentMethod;
            this.desc             = desc;
            this.argumentTypes    = argumentTypes;

            if (argumentTypes == null)
            {
                argumentTypes = new PapyrusPrimitiveType[0];
            }

            // Update the type constraints so we are only able to assign
            // values of the correct types.
            if (desc != null && argumentTypes.Length > 0)
            {
                UpdateTypeConstraints(argumentTypes);
            }

            if (currentMethod != null)
            {
                var references = new List <PapyrusMemberReference>();
                references.AddRange(currentMethod.Parameters);
                references.AddRange(currentMethod.GetVariables());
                if (currentType != null)
                {
                    references.AddRange(currentType.Fields);
                }

                ReferenceCollection = new ObservableCollection <PapyrusMemberReference>(references);

                HideValueInputs();

                ReferenceValueVisibility = Visibility.Visible;

                //SelectedValueType = ReferenceCollection.LastOrDefault();
            }
            ComboBoxItems     = new ObservableCollection <FrameworkElement>(CreateComboBoxItems());
            SelectedValueType = ComboBoxItems.First() as ComboBoxItem;
        }
コード例 #13
0
        private void ProcessInstructions(IEnumerable <PapyrusAssemblyDefinition> papyrusAssemblyCollection,
                                         IDelegatePairDefinition delegatePairDef, MethodDefinition method, PapyrusAssemblyDefinition asm,
                                         PapyrusTypeDefinition papyrusType, PapyrusMethodDefinition m, PapyrusCompilerOptions options)
        {
            var papyrusInstructions =
                instructionProcessor.ProcessInstructions(papyrusAssemblyCollection, delegatePairDef, asm, papyrusType, m,
                                                         method, method.Body, method.Body.Instructions, options);

            if (method.Name.ToLower() == "oninit")
            {
                List <PapyrusInstruction> structGets;
                var ip = instructionProcessor as ClrInstructionProcessor;
                // TODO: Going against solid here just because im to damn tired, which I ended up breaking in lots of places.
                m.Body.Instructions.Insert(0,
                                           ip.CallProcessor.CreatePapyrusCallInstruction(instructionProcessor, PapyrusOpCodes.Callmethod, constructor,
                                                                                         "self",
                                                                                         "::nonevar", new List <object>(), out structGets));
            }

            m.Body.Instructions.AddRange(papyrusInstructions);
        }
コード例 #14
0
        public PapyrusMethodDefinition ReadMethod(PapyrusAssemblyDefinition asm)
        {
            var method = new PapyrusMethodDefinition(asm);

            method.ReturnTypeName = pexReader.ReadStringRef();
            method.Documentation  = pexReader.ReadStringRef();
            method.UserFlags      = pexReader.ReadInt32();
            method.Flags          = pexReader.ReadByte();

            var parameterCount = pexReader.ReadInt16();

            for (var i = 0; i < parameterCount; i++)
            {
                method.Parameters.Add(ReadParameter(asm));
            }

            var localVariableCount = pexReader.ReadInt16();

            for (var i = 0; i < localVariableCount; i++)
            {
                method.Body.Variables.Add(ReadVariable(asm));
            }

            var instructionCount = pexReader.ReadInt16();

            for (var i = 0; i < instructionCount; i++)
            {
                var instruction = ReadInstruction(asm);
                instruction.Offset = i;
                method.Body.Instructions.Add(instruction);
            }

            for (var i = 0; i < instructionCount; i++)
            {
                var instruction = method.Body.Instructions[i];
                if (i > 0)
                {
                    var previous = method.Body.Instructions[i - 1];
                    previous.Next        = instruction;
                    instruction.Previous = previous;
                }
                if (i < instructionCount - 1)
                {
                    var next = method.Body.Instructions[i + 1];
                    instruction.Next = next;
                    next.Previous    = instruction;
                }
            }

            //var last = method.Body.Instructions.LastOrDefault();
            //if (last != null)
            //{
            //    if (last.OpCode != PapyrusOpCodes.Return)
            //    {
            //        var ret = new PapyrusInstruction()
            //        {
            //            OpCode = PapyrusOpCodes.Return,
            //            Previous = last,
            //            Offset = last.Offset + 1,
            //            TemporarilyInstruction = true,
            //            Arguments = new List<PapyrusVariableReference>(),
            //            OperandArguments = new List<PapyrusVariableReference>()
            //        };
            //        last.Next = ret;
            //        if (IsJump(last.OpCode))
            //        {
            //            last.Operand = ret;
            //        }
            //        ret.Operand = null;
            //        method.Body.Instructions.Add(ret);
            //    }
            //}

            return(method);
        }
コード例 #15
0
        private PapyrusMethodDefinition CreatePapyrusMethodDefinition(
            IEnumerable <PapyrusAssemblyDefinition> papyrusAssemblyCollection, PapyrusAssemblyDefinition asm,
            PapyrusTypeDefinition papyrusType,
            MethodDefinition method, IDelegatePairDefinition delegatePairDef, PapyrusCompilerOptions options)
        {
            if (method.IsConstructor)
            {
                // Replace: .ctor with __ctor
                method.Name = method.Name.Replace(".", "__");
                constructor = method;
            }

            var m = new PapyrusMethodDefinition(asm);

            m.Documentation = "".Ref(asm);
            m.UserFlags     = attributeReader.ReadPapyrusAttributes(method).UserFlagsValue;
            m.IsGlobal      = method.IsStatic;
            m.IsNative      = method.CustomAttributes.Any(i => i.AttributeType.Name.Equals("NativeAttribute"));
            m.Name          = method.Name.Ref(asm);
            var papyrusReturnType = Utility.GetPapyrusReturnType(method.ReturnType, activeClrType);

            if (EnumDefinitions.Any(m2 => m2.FullName == method.ReturnType.FullName))
            {
                papyrusReturnType = "Int";
            }

            m.ReturnTypeName = papyrusReturnType.Ref(asm); // method.ReturnType.Name
            m.Parameters     = new List <PapyrusParameterDefinition>();
            foreach (var p in method.Parameters)
            {
                // TODO: Add support for delegate as parameter

                var paramTypeName = Utility.GetPapyrusReturnType(p.ParameterType, activeClrType, true);

                // Replace enum types into Integer
                if (EnumDefinitions.Any(i => i.FullName == p.ParameterType.FullName))
                {
                    paramTypeName = "Int";
                }

                m.Parameters.Add(new PapyrusParameterDefinition
                {
                    Name     = p.Name.Ref(asm),
                    TypeName = paramTypeName.Ref(asm)
                });
            }

            var clrVariables = method.Body.Variables;

            var varNum = 0;

            foreach (var clrVar in clrVariables)
            {
                var delegateVars =
                    delegatePairDef.DelegateMethodLocalPair.Where(d => d.Key == method).SelectMany(d => d.Value);

                if (delegateVars.Any(d => "V_" + d.Index == "V_" + clrVar.Index))
                {
                    // This local variable is pointing to a delegate
                    // and since we are removing all Delegate types, this wont work. So we have to change the type into something else.
                    // in this case, we are changing it into a Int

                    if (!clrVar.Name.Contains("$<>"))
                    // if we are reading symbols, delegate variables contains unwanted characters in their names.
                    // And since those are not going to be used. We can just skip these.
                    {
                        var varName = (!string.IsNullOrEmpty(clrVar.Name) ? clrVar.Name : clrVar.ToString()).Ref(asm);

                        var delegateInvokeRef = delegateFinder.FindDelegateInvokeReference(delegatePairDefinition, m);

                        m.Body.Variables.Add(new PapyrusVariableReference(varName, "Int".Ref(asm))
                        {
                            IsDelegateReference     = true,
                            DelegateInvokeReference = delegateInvokeRef,
                            Value = varName.Value,
                            Type  = PapyrusPrimitiveType.Reference
                        });
                    }
                }
                else
                {
                    var varName          = (!string.IsNullOrEmpty(clrVar.Name) ? clrVar.Name : clrVar.ToString()).Ref(asm);
                    var variableTypeName = Utility.GetPapyrusReturnType(clrVar.VariableType.FullName);

                    // If its an enum, we want to change the type into a Int
                    if (EnumDefinitions.Any(i => i.FullName == clrVar.VariableType.FullName))
                    {
                        variableTypeName = "Int";
                    }

                    m.Body.Variables.Add(new PapyrusVariableReference(varName, variableTypeName.Ref(asm))
                    {
                        Value = varName.Value,
                        Type  = PapyrusPrimitiveType.Reference
                    });
                }
                varNum++;
            }

            if (method.HasBody)
            {
                ProcessInstructions(papyrusAssemblyCollection, delegatePairDef, method, asm, papyrusType, m, options);

                if (papyrusReturnType == "None")
                {
                    if (m.Body.Variables.All(n => n.Name.Value.ToLower() != "::nonevar"))
                    {
                        var nonevar = "::NoneVar".Ref(asm);
                        m.Body.Variables.Add(new PapyrusVariableReference(nonevar, "None".Ref(asm))
                        {
                            Value = nonevar.Value,
                            Type  = PapyrusPrimitiveType.Reference
                        });
                    }
                }
                m.Body.Instructions.RecalculateOffsets();
            }

            return(m);
        }
コード例 #16
0
 public void AddResult(PapyrusTypeDefinition type, PapyrusStateDefinition state, PapyrusMethodDefinition method,
                       PapyrusInstruction instruction, string search, string resultRepresentation)
 {
     SearchText = search;
     usageRepresentaitons.Add(new FindResultData
     {
         Type        = type,
         State       = state,
         Method      = method,
         Instruction = instruction,
         Text        = resultRepresentation,
         SearchText  = search
     });
 }
コード例 #17
0
        /// <summary>
        ///     Writes the method.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <param name="type">The type.</param>
        /// <param name="asm">The asm.</param>
        /// <param name="indent">The indent.</param>
        /// <param name="isGetter">if set to <c>true</c> [is getter].</param>
        /// <param name="isSetter">if set to <c>true</c> [is setter].</param>
        private void WriteMethod(PapyrusMethodDefinition method, PapyrusTypeDefinition type,
                                 PapyrusAssemblyDefinition asm, int indent, PapyrusPropertyDefinition prop = null, bool isGetter = false,
                                 bool isSetter = false)
        {
            // SetGlobalIndent(indent);
            if (!isGetter && !isSetter)
            {
                if (method.Documentation != null && !string.IsNullOrEmpty(method.Documentation.Value))
                {
                    WriteDoc(method.Documentation, indent);
                }
                Append("public " +
                       (method.IsGlobal ? "static " : "") +
                       (method.IsNative ? "extern " : "") +
                       ((string)method.ReturnTypeName).Replace("None", "void") + " " +
                       (string)method.Name
                       , indent);
                Append("(");
                Append(string.Join(",",
                                   method.Parameters.Select(i => (string)i.TypeName + " " + (string)i.Name)));
                AppendLine(")");
            }
            AppendLine("{", indent);
            //if (isGetter)
            //{
            //    if (prop != null)
            //    {
            //        prop.
            //    }
            //    // type.Fields.FirstOrDefault(f=>f.Name.Value.Contains());
            //    AppendLine("return <backing_field>;", indent + 1);
            //}
            //else if (isSetter)
            //{
            //    AppendLine("<backing_field> = value;", indent + 1);
            //}
            //else
            {
                if (method.HasBody)
                {
                    var debug =
                        asm.DebugInfo.MethodDescriptions.FirstOrDefault(
                            m => method.Name != null && m.Name.Value == method.Name.Value);
                    if (debug != null)
                    {
                        AppendLine("// DEBUG LINE NUMBER: " + string.Join(",", debug.BodyLineNumbers.ToArray()),
                                   indent + 1);
                    }
                    foreach (var var in method.GetVariables())
                    {
                        if (var.Name.Value.ToLower() == "::nonevar")
                        {
                            continue;
                        }

                        var typeName = (string)var.TypeName;
                        if (typeName.Contains("#"))
                        {
                            AppendLine("// Struct Variable: " + typeName, indent + 1);
                            AppendLine(typeName.Split('#').LastOrDefault() + " " + (string)var.Name + ";", indent + 1);
                        }
                        else
                        {
                            AppendLine(typeName + " " + (string)var.Name + ";", indent + 1);
                        }
                    }


                    //var flowGraphBuilder = new PapyrusControlFlowGraphBuilder(method);
                    //var graph = flowGraphBuilder.Build();
                    //graph.ComputeDominance();
                    //graph.ComputeDominanceFrontier();
                    //var nodes = graph.Nodes.Skip(2).ToList();
                    //var count = nodes.Count;

                    foreach (var instruction in method.Body.Instructions)
                    {
                        var instructionString = WriteInstruction(instruction, method, type);
                        foreach (
                            var row in instructionString.Split(new[] { Environment.NewLine }, StringSplitOptions.None))
                        {
                            AppendLine("/* " + instruction.Offset + " */ " + row, indent + 1);
                        }
                    }

                    //List<PapyrusInstruction> targetEnd = new List<PapyrusInstruction>();
                    //foreach (var n in nodes)
                    //{

                    //    var end = n.End;

                    //    //if (count > 1)
                    //    //    AppendLine("/* ====== Node Start ====== */", 1);

                    //    foreach (var instruction in n.Instructions)
                    //    {
                    //        Append("/* " + instruction.Offset + " */ ", 1);

                    //        WriteInstruction(indent, instruction, method, type, asm);
                    //    }

                    //    if (end != null && IsJump(end.OpCode))
                    //    {

                    //        var direction = int.Parse(end.GetArg(IsJumpf(end.OpCode) || IsJumpt(end.OpCode) ? 1 : 0));
                    //        if (direction < 0)
                    //        {
                    //            // LOOP?
                    //        }
                    //        else
                    //        {
                    //            // BRANCHING
                    //        }
                    //    }
                    //}
                }
            }
            AppendLine("}", indent);
        }
コード例 #18
0
        //private void WriteInstructionConditional(SourceBuilder source, int indent, PapyrusInstruction instruction, PapyrusMethodDefinition method, PapyrusTypeDefinition type, PapyrusAssemblyDefinition asm)
        //{
        //    SetBuilder(source, indent);
        //    var i = instruction;
        //    var boolean = instruction.GetArg(0);
        //    AppendLine("if (" + boolean + ")");
        //}

        //private bool IsJumpf(PapyrusOpCode opCode)
        //{
        //    return opCode == PapyrusOpCode.Jmpf;
        //}
        //private bool IsJumpt(PapyrusOpCode opCode)
        //{
        //    return opCode == PapyrusOpCode.Jmpt;
        //}
        //private bool IsJump(PapyrusOpCode opCode)
        //{
        //    return opCode == PapyrusOpCode.Jmp || opCode == PapyrusOpCode.Jmpf || opCode == PapyrusOpCode.Jmpt;
        //}

        private string WriteInstruction(PapyrusInstruction instruction, PapyrusMethodDefinition method,
                                        PapyrusTypeDefinition type)
        {
            var i = instruction;

            switch (i.OpCode)
            {
            case PapyrusOpCodes.Nop:
            {
                return("// Do Nothing Operator (NOP)");
            }

            case PapyrusOpCodes.Callstatic:
            {
                var comment      = WritePapyrusInstruction(i) + Environment.NewLine;
                var val          = string.Join(",", i.Arguments.Skip(2).Take(i.Arguments.Count - 3).Select(GetArgumentValue));
                var location     = GetArgumentValue(i.Arguments[0]);
                var functionName = GetArgumentValue(i.Arguments[1]);
                var assignee     = GetArgumentValue(i.Arguments.LastOrDefault());

                var args =
                    string.Join(",", val, string.Join(",", i.OperandArguments.Select(GetArgumentValue))).Trim(',');

                if (assignee != null)
                {
                    assignee += " = ";
                    if (assignee.ToLower().Contains("::nonevar"))
                    {
                        assignee = string.Empty;
                    }
                }
                return(comment + assignee + (location + ".").Replace("self.", "") + functionName + "(" + args + ");");
            }

            case PapyrusOpCodes.Callmethod:
            {
                var comment = WritePapyrusInstruction(i) + Environment.NewLine;

                var val          = string.Join(",", i.Arguments.Skip(2).Take(i.Arguments.Count - 3).Select(GetArgumentValue));
                var location     = GetArgumentValue(i.Arguments[1]);
                var functionName = GetArgumentValue(i.Arguments[0]);
                var assignee     = GetArgumentValue(i.Arguments.LastOrDefault());

                var args =
                    string.Join(",", val, string.Join(",", i.OperandArguments.Select(GetArgumentValue))).Trim(',');

                if (assignee != null)
                {
                    assignee += " = ";
                    if (assignee.ToLower().Contains("::nonevar"))
                    {
                        assignee = string.Empty;
                    }
                }

                return(comment + assignee + (location + ".").Replace("self.", "") + functionName + "(" + args + ");");
            }

            case PapyrusOpCodes.Return:
            {
                var comment = WritePapyrusInstruction(i) + Environment.NewLine;

                string val;
                var    firstArg    = GetArgumentValue(i.Arguments.FirstOrDefault());
                var    firstVarArg = GetArgumentValue(i.OperandArguments.FirstOrDefault());
                if (firstArg != null)
                {
                    val = " " + firstArg;
                }
                else if (firstVarArg != null)
                {
                    val = " " + firstVarArg;
                }
                else
                {
                    val = "";
                }

                return(comment + ("return" + val).Trim() + ";");
                //WritePapyrusInstruction(i);
            }

            case PapyrusOpCodes.Assign:
            {
                var comment = WritePapyrusInstruction(i) + Environment.NewLine;

                var val1 = GetArgumentValue(i.Arguments.FirstOrDefault());
                var val2 = GetArgumentValue(i.Arguments.LastOrDefault());
                var val3 = GetArgumentValue(i.OperandArguments.FirstOrDefault());
                var val4 = GetArgumentValue(i.OperandArguments.LastOrDefault());

                var var0 = val1 ?? val3;
                var var1 = val2 ?? val4;
                if (string.IsNullOrEmpty(var1))
                {
                    return(var0 + " = null;");
                }
                return(comment + var0 + " = " + var1 + ";");
            }

            case PapyrusOpCodes.ArrayRemoveElements:
            {
                var comment = WritePapyrusInstruction(i) + Environment.NewLine;

                var array = GetArgumentValue(i.Arguments[0]);
                var index = GetArgumentValue(i.Arguments[1]);
                var count = GetArgumentValue(i.Arguments[2]);

                return(comment + "Array.RemoveItems(" + array + ", " + index + ", " + count + ");");
            }

            case PapyrusOpCodes.ArrayFindElement:
            {
                var comment = WritePapyrusInstruction(i) + Environment.NewLine;

                var array         = GetArgumentValue(i.Arguments[0]);
                var destination   = GetArgumentValue(i.Arguments[1]);
                var elementToFind = GetArgumentValue(i.Arguments[2]);
                var startIndex    = GetArgumentValue(i.Arguments[3]);

                return(comment + destination + " = Array.IndexOf(" + array + ", " + elementToFind + ", " +
                       startIndex + ");");
            }

            case PapyrusOpCodes.ArrayFindStruct:
            {
                var comment = WritePapyrusInstruction(i) + Environment.NewLine;

                var array        = GetArgumentValue(i.Arguments[0]);
                var destination  = GetArgumentValue(i.Arguments[1]);
                var fieldToMatch = GetArgumentValue(i.Arguments[2]);
                var value        = GetArgumentValue(i.Arguments[3]);
                var startIndex   = GetArgumentValue(i.Arguments[4]);

                return(comment + destination + " = Structs.IndexOf(" + array + ", " + fieldToMatch + ", " + value +
                       ", " + startIndex + ");");
            }

            case PapyrusOpCodes.PropGet:
            {
                var comment = WritePapyrusInstruction(i) + Environment.NewLine;

                var property  = GetArgumentValue(i.Arguments[0]);
                var owner     = GetArgumentValue(i.Arguments[1]);
                var targetVar = GetArgumentValue(i.Arguments[2]);

                return(comment + targetVar + " = " + owner + "." + property + ";");
            }

            case PapyrusOpCodes.PropSet:
            {
                var comment = WritePapyrusInstruction(i) + Environment.NewLine;

                var property = GetArgumentValue(i.Arguments[0]);
                var owner    = GetArgumentValue(i.Arguments[1]);
                var value    = GetArgumentValue(i.Arguments[2]);


                return(comment + owner + "." + property + " = " + value + ";");
            }

            case PapyrusOpCodes.StructSet:
            {
                var structVar   = GetArgumentValue(i.Arguments[0]);
                var structField = GetArgumentValue(i.Arguments[1]);
                var value       = GetArgumentValue(i.Arguments[2]);
                return(structVar + "." + structField + " = " + value + ";");
                // (value + "." + structField + " = " + structVar + "." + structField + ";");
            }

            case PapyrusOpCodes.StructGet:
            {
                var asignee     = GetArgumentValue(i.Arguments[0]);
                var structVar   = GetArgumentValue(i.Arguments[1]);
                var structField = GetArgumentValue(i.Arguments[2]);
                return(asignee + " = " + structVar + "." + structField + ";");
            }

            case PapyrusOpCodes.ArraySetElement:
            {
                var array = GetArgumentValue(i.Arguments[0]);
                var index = GetArgumentValue(i.Arguments[1]);
                var value = GetArgumentValue(i.Arguments[2]);
                return(array + "[" + index + "] = " + value + ";");
            }

            case PapyrusOpCodes.ArrayGetElement:
            {
                var asignee = GetArgumentValue(i.Arguments[0]);
                var array   = GetArgumentValue(i.Arguments[1]);
                var index   = GetArgumentValue(i.Arguments[2]);
                return(asignee + " = " + array + "[" + index + "];");
            }

            case PapyrusOpCodes.ArrayLength:
            {
                var asignee = GetArgumentValue(i.Arguments[0]);
                var array   = GetArgumentValue(i.Arguments[1]);
                return(asignee + " = " + array + ".Length;");
            }

            case PapyrusOpCodes.ArrayCreate:
            {
                var asignee     = GetArgumentValue(i.Arguments[0]);
                var size        = GetArgumentValue(i.Arguments[1]);
                var possibleVar =
                    method.GetVariables().FirstOrDefault(v => v.Name.Value == asignee);
                var field = type.Fields.FirstOrDefault(v => v.Name.Value == asignee);
                var prop  = type.Properties.FirstOrDefault(v => v.Name.Value == asignee);
                if (possibleVar != null)
                {
                    return(asignee + " = new " + possibleVar.TypeName.Value.Replace("[]", "") + "[" + size + "];");
                }
                if (field != null)
                {
                    return(asignee + " = new " + field.TypeName.Replace("[]", "") + "[" + size + "];");
                }
                if (prop != null)
                {
                    return(asignee + " = new " + prop.TypeName.Value.Replace("[]", "") + "[" + size + "];");
                }
            }
            break;

            case PapyrusOpCodes.Strcat:
            {
                var asignee = GetArgumentValue(i.Arguments[0]);
                var str     = GetArgumentValue(i.Arguments[1]);
                var value   = GetArgumentValue(i.Arguments[2]);
                return(asignee + " = " + str + " + " + value + ";");
            }

            case PapyrusOpCodes.Fsub:
            case PapyrusOpCodes.Isub:
            {
                return(DoMath(i, "-"));
            }

            case PapyrusOpCodes.Fadd:
            case PapyrusOpCodes.Iadd:
            {
                return(DoMath(i, "+"));
            }

            case PapyrusOpCodes.Imod:
            {
                return(DoMath(i, "%"));
            }

            case PapyrusOpCodes.Fdiv:
            case PapyrusOpCodes.Idiv:
            {
                return(DoMath(i, "/"));
            }

            case PapyrusOpCodes.Fmul:
            case PapyrusOpCodes.Imul:
            {
                return(DoMath(i, "*"));
            }

            case PapyrusOpCodes.Fneg:
            case PapyrusOpCodes.Ineg:
            {
                var comment = WritePapyrusInstruction(i) + Environment.NewLine;
                var asignee = GetArgumentValue(i.Arguments[0]);
                var target  = GetArgumentValue(i.Arguments[1]);
                return(comment + asignee + " = -" + target + ";");
            }

            case PapyrusOpCodes.CmpEq:
            {
                return(DoMath(i, "=="));
            }

            case PapyrusOpCodes.CmpGt:
            {
                return(DoMath(i, ">"));
            }

            case PapyrusOpCodes.CmpGte:
            {
                return(DoMath(i, ">="));
            }

            case PapyrusOpCodes.CmpLt:
            {
                return(DoMath(i, "<"));
            }

            case PapyrusOpCodes.CmpLte:
            {
                return(DoMath(i, "<="));
            }

            case PapyrusOpCodes.Not:
            {
                // var comment = WritePapyrusInstruction(i) + Environment.NewLine;

                var assignee = i.GetArg(0);
                var target   = i.GetArg(1);
                return(assignee + " = !" + target + ";");
            }

            case PapyrusOpCodes.Jmp:
            {
                var destination = GetArgumentValue(i.Arguments[0]);
                return("// " + i.OpCode + " " + destination + " (offset: " +
                       (i.Offset + int.Parse(destination)) + ")");
            }

            case PapyrusOpCodes.Jmpt:
            case PapyrusOpCodes.Jmpf:
            {
                var boolVal     = GetArgumentValue(i.Arguments[0]);
                var destination = GetArgumentValue(i.Arguments[1]);
                return("// " + i.OpCode + " " + boolVal + " " + destination + " (offset: " +
                       (i.Offset + int.Parse(destination)) + ")");
            }

            default:
            {
                return(WritePapyrusInstruction(i));
            }
            }
            return(null);
        }
コード例 #19
0
 /// <summary>
 ///     Sets the target method.
 /// </summary>
 /// <param name="method">The method.</param>
 public void SetTargetMethod(PapyrusMethodDefinition method)
 {
     targetMethod      = method;
     longLivedTempVars = new List <string>();
     codeBlocks        = new Map <int, PapyrusCodeBlock>();
 }
コード例 #20
0
        //public object GetOperand()
        //{
        //    OperandLookup()
        //    throw new System.NotImplementedException();
        //}

        private void ShowArgumentSelectionDialog(OpCodeArgumentDescription d)
        {
            if (d.Ref == OpCodeRef.Instruction)
            {
                var dialog = new PapyrusInstructionSelectorViewModel(currentMethod.Body.Instructions.ToArray(), d);
                var result = dialogService.ShowDialog(dialog);
                if (result == DialogResult.OK)
                {
                    Arguments[d.Index] = dialog.SelectedInstruction;
                }
            }
            else if (d.Ref == OpCodeRef.Type)
            {
                var dialog = new PapyrusTypeSelectorViewModel(loadedAssemblies, d);
                var result = dialogService.ShowDialog(dialog);
                if (result == DialogResult.OK)
                {
                    Arguments[d.Index] = dialog.SelectedType;
                }
            }
            else if (d.Ref == OpCodeRef.Method)
            {
                var targetType = GetTargetType(currentType);

                var dialog = new PapyrusMethodSelectorViewModel(loadedAssemblies, targetType, d);
                var result = dialogService.ShowDialog(dialog); // change currentType to selected type later
                if (result == DialogResult.OK)
                {
                    PapyrusMethodDefinition method = null;
                    var selMethod = dialog.SelectedMethod;
                    if (selMethod != null)
                    {
                        method = dialog.SelectedMethod.Item as PapyrusMethodDefinition;
                    }

                    if ((method != null && dialog.SelectedMethodName != null &&
                         (method.Name.Value != dialog.SelectedMethodName)) ||
                        (method == null && dialog.SelectedMethodName != null))
                    {
                        Arguments[d.Index] = CreateReferenceFromName(dialog.SelectedMethodName);
                    }
                    else
                    {
                        Arguments[d.Index] = method;
                    }
                }
            }
            else
            {
                if (d.ValueType == OpCodeValueTypes.Constant)
                {
                    var dialog = new PapyrusConstantValueViewModel(d);
                    var result = dialogService.ShowDialog(dialog);
                    if (result == DialogResult.OK)
                    {
                        Arguments[d.Index] = dialog.SelectedValue;
                    }
                }
                else if (d.ValueType == OpCodeValueTypes.Reference)
                {
                    var dialog = new PapyrusReferenceValueViewModel(loadedAssemblies, currentType, currentMethod, d);
                    var result = dialogService.ShowDialog(dialog);
                    if (result == DialogResult.OK)
                    {
                        if (dialog.SelectedReference == null)
                        {
                            var name = dialog.SelectedReferenceName;
                            Arguments[d.Index] = CreateReferenceFromName(name);
                        }
                        else
                        {
                            Arguments[d.Index] = dialog.SelectedReference;
                        }
                    }
                }
                else
                {
                    UpdateArgumentConstraintTypes();

                    var dialog = new PapyrusReferenceAndConstantValueViewModel(loadedAssemblies, currentType,
                                                                               currentMethod, d, ArgumentTypes);
                    var result = dialogService.ShowDialog(dialog);
                    if (result == DialogResult.OK)
                    {
                        if (dialog.SelectedConstantValue == null && dialog.SelectedReferenceValue == null && dialog.SelectedReferenceName != null)
                        {
                            var name = dialog.SelectedReferenceName;
                            Arguments[d.Index] = CreateReferenceFromName(name);
                        }
                        else
                        {
                            Arguments[d.Index] = dialog.SelectedItem;
                        }
                    }
                }
            }
            UpdateArguments();
        }
コード例 #21
0
        /// <summary>
        ///     Initializes a new instance of the <see cref="InstructionArgumentEditorViewModel" /> class.
        /// </summary>
        /// <param name="dialogService">The dialog service.</param>
        /// <param name="loadedAssemblies">The loaded assemblies.</param>
        /// <param name="loadedAssembly">The loaded assembly.</param>
        /// <param name="currentType">Type of the current.</param>
        /// <param name="currentMethod">The current method.</param>
        /// <param name="currentInstruction">The current instruction.</param>
        /// <param name="desc">The desc.</param>
        public InstructionArgumentEditorViewModel(IDialogService dialogService,
                                                  List <PapyrusAssemblyDefinition> loadedAssemblies,
                                                  PapyrusAssemblyDefinition loadedAssembly,
                                                  PapyrusTypeDefinition currentType,
                                                  PapyrusMethodDefinition currentMethod,
                                                  PapyrusInstruction currentInstruction,
                                                  OpCodeDescription desc)
        {
            this.dialogService      = dialogService;
            this.loadedAssemblies   = loadedAssemblies;
            this.loadedAssembly     = loadedAssembly;
            this.currentType        = currentType;
            this.currentMethod      = currentMethod;
            this.currentInstruction = currentInstruction;
            this.desc = desc;


            if (loadedAssembly != null && currentMethod != null)
            {
                BuildVarTypeMap(loadedAssembly, currentMethod);
            }


            Argument0Command = new RelayCommand(SelectArgument0);
            Argument1Command = new RelayCommand(SelectArgument1);
            Argument2Command = new RelayCommand(SelectArgument2);
            Argument3Command = new RelayCommand(SelectArgument3);
            Argument4Command = new RelayCommand(SelectArgument4);

            var maxArgCount = 5;

            if (this.desc != null)
            {
                maxArgCount   = this.desc.Arguments.Count;
                Arguments     = new object[maxArgCount];
                ArgumentTypes = new PapyrusPrimitiveType[maxArgCount];
            }

            if (currentInstruction != null)
            {
                var args = currentInstruction.Arguments.ToArray().Cast <object>().ToList();

                while (args.Count < maxArgCount)
                {
                    args.Add(null);
                }
                Arguments = OperandLookup(args.ToArray());
            }

            if (this.desc != null)
            {
                UpdateVisibilities();

                try
                {
                    UpdateArguments();
                }
                catch
                {
                    // this.desc was null after all.
                }
            }
        }
コード例 #22
0
 public MethodBodyOptimizerResult(PapyrusMethodDefinition result, bool success, double ratio)
 {
     Result  = result;
     Success = success;
     Ratio   = ratio;
 }
コード例 #23
0
        public PapyrusInstructionEditorViewModel(IDialogService dialogService,
                                                 List <PapyrusAssemblyDefinition> loadedAssemblies, PapyrusAssemblyDefinition loadedAssembly,
                                                 PapyrusTypeDefinition currentType, PapyrusMethodDefinition currentMethod,
                                                 PapyrusInstruction instruction = null)
        {
            opCodeDescriptionReader = new OpCodeDescriptionReader();

            if (File.Exists("OpCodeDescriptions.xml"))
            {
                opCodeDescriptionDefinition = opCodeDescriptionReader.Read("OpCodeDescriptions.xml");
            }
            else if (File.Exists(
                         @"C:\git\PapyrusDotNet\Source\PapyrusDotNet.PexInspector\OpCodeDescriptions.xml"))
            {
                opCodeDescriptionDefinition =
                    opCodeDescriptionReader.Read(
                        @"C:\git\PapyrusDotNet\Source\PapyrusDotNet.PexInspector\OpCodeDescriptions.xml");
            }
            else
            {
                opCodeDescriptionDefinition =
                    opCodeDescriptionReader.Read(
                        @"D:\git\PapyrusDotNet\Source\PapyrusDotNet.PexInspector\OpCodeDescriptions.xml");
            }

            this.dialogService    = dialogService;
            this.loadedAssemblies = loadedAssemblies;
            this.loadedAssembly   = loadedAssembly;
            this.currentType      = currentType;
            this.currentMethod    = currentMethod;
            this.instruction      = instruction;
            if (instruction == null)
            {
                isNewInstruction = true;
                var defaultOpCode = PapyrusOpCodes.Nop;
                SelectedOpCodeDescription = new InstructionArgumentEditorViewModel(dialogService, loadedAssemblies,
                                                                                   loadedAssembly, currentType, currentMethod, null, opCodeDescriptionDefinition.GetDesc(defaultOpCode));

                SelectedOpCode = defaultOpCode;

                // ArgumentsDescription = defaultOpCode.GetArgumentsDescription();
                OperandArgumentsDescription = defaultOpCode.GetOperandArgumentsDescription();
                OperandArgumentsVisible     = !operandArgumentsDescription.ToLower().Contains("no operand");

                OperandArguments = new ObservableCollection <PapyrusVariableReference>();
            }
            else
            {
                SelectedOpCode = instruction.OpCode;
                SelectedOpCodeDescriptionString = instruction.OpCode.GetDescription();
                SelectedOpCodeDescription       = new InstructionArgumentEditorViewModel(dialogService, loadedAssemblies,
                                                                                         loadedAssembly,
                                                                                         currentType, currentMethod, instruction, opCodeDescriptionDefinition.GetDesc(instruction.OpCode));
                // instruction.OpCode.GetDescription();
                // ArgumentsDescription = instruction.OpCode.GetArgumentsDescription();
                OperandArgumentsDescription = instruction.OpCode.GetOperandArgumentsDescription();
                OperandArgumentsVisible     = !operandArgumentsDescription.ToLower().Contains("no operand");
                OperandArguments            = new ObservableCollection <PapyrusVariableReference>(instruction.OperandArguments);
            }
            AvailableOpCodes =
                new ObservableCollection <PapyrusOpCodes>(Enum.GetValues(typeof(PapyrusOpCodes)).Cast <PapyrusOpCodes>());

            AddOperandArgumentCommand    = new RelayCommand(AddOpArg);
            RemoveOperandArgumentCommand = new RelayCommand(RemoveOpArg, CanEdit);
            EditOperandArgumentCommand   = new RelayCommand(EditOpArg, CanEdit);
        }