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')); }
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); }
/// <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)); }
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); } } }
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); }
public IEnumerable <PapyrusInstruction> ProcessInstructions(PapyrusAssemblyDefinition targetPapyrusAssembly, PapyrusTypeDefinition targetPapyrusType, PapyrusMethodDefinition targetPapyrusMethod, MethodDefinition method, MethodBody body, Collection <Instruction> instructions, PapyrusCompilerOptions options) { throw new NotImplementedException(); }
private MethodAttributes GetMethodAttributes(PapyrusMethodDefinition m) { var attrs = MethodAttributes.Public; if (m.IsNative || m.IsGlobal) { attrs |= MethodAttributes.Static; } return(attrs); }
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; }
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)); }
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); }
/// <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; } }
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; }
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); }
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); }
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); }
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 }); }
/// <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); }
//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); }
/// <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>(); }
//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(); }
/// <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. } } }
public MethodBodyOptimizerResult(PapyrusMethodDefinition result, bool success, double ratio) { Result = result; Success = success; Ratio = ratio; }
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); }