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); }
public IEnumerable <PapyrusInstruction> ProcessInstructions( IEnumerable <PapyrusAssemblyDefinition> papyrusAssemblyCollection, IDelegatePairDefinition delegatePairDef, PapyrusAssemblyDefinition targetPapyrusAssembly, PapyrusTypeDefinition targetPapyrusType, PapyrusMethodDefinition targetPapyrusMethod, MethodDefinition method, MethodBody body, Collection <Instruction> instructions, PapyrusCompilerOptions options) { throw new NotImplementedException(); }
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); }
/// <summary> /// Converts the assembly. /// </summary> /// <param name="input">The input.</param> /// <returns></returns> protected override PapyrusAssemblyOutput ConvertAssembly(ClrAssemblyInput input) { var clr = input.Assembly; var mainModule = clr.MainModule; papyrusAssemblies.Clear(); propertyMethods = new List <MethodDefinition>(); var papyrusAssemblyToTypeDefinition = new Dictionary <PapyrusAssemblyDefinition, TypeDefinition>(); // Keep track on the enum types so we can verify any parameter, variables, etc, and change the type into integers. ResolveEnumDefinitions(mainModule); foreach (var type in mainModule.Types) { try { // We will skip this one for now // as it will not really provide us with any necessary information at this early stage. if (type.Name == "<Module>") { continue; } // Find all delegate types and methods and create references to them. delegatePairDefinition = delegateFinder.FindDelegateTypes(type); activeClrType = type; var pex = PapyrusAssemblyDefinition.CreateAssembly(input.TargetPapyrusVersion); SetHeaderInfo(input, pex, type); CreateType(pex, type, processorOptions); papyrusAssemblies.Add(pex); papyrusAssemblyToTypeDefinition.Add(pex, type); // After the type has been processed // we will create the methods and then create the debug info as we do not have any info regarding the methods until those have been created ;-) foreach (var t in pex.Types) { var firstState = t.States.FirstOrDefault(); if (firstState == null) { continue; // no state was found?? } CreateMethods(papyrusAssemblies, type, t, pex, processorOptions) .ForEach(firstState.Methods.Add); CreateDebugInfo(pex, t, type); } } catch (ProhibitedCodingBehaviourException exc) { userInterface.DrawError($"Error processing '{type.FullName}': Prohibited use of " + exc.OpCode.GetValueOrDefault().Code + " in " + exc.Method.FullName + " at " + exc.Offset); } catch (Exception exc) { userInterface.DrawError($"Error processing '{type.FullName}': Unhandled Exception - " + exc); } } return(new PapyrusAssemblyOutput(papyrusAssemblies.ToArray())); }
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); }