public virtual MethodDefinition Resolve(MethodReference method) { if (method == null) { throw new ArgumentNullException("method"); } TypeDefinition type = this.Resolve(method.DeclaringType); if (type == null) { return(null); } method = method.GetElementMethod(); return(type.HasMethods ? this.GetMethod(type, method) : null); }
public virtual MethodDefinition Resolve(MethodReference method) { Mixin.CheckMethod(method); TypeDefinition typeDefinition = Resolve(method.DeclaringType); if (typeDefinition == null) { return(null); } method = method.GetElementMethod(); if (!typeDefinition.HasMethods) { return(null); } return(GetMethod(typeDefinition, method)); }
public static MethodDefinition Resolve(IAssemblyResolver resolver, MethodReference method) { var type = Resolve(resolver, method.DeclaringType); if (type == null) { return(null); } method = method.GetElementMethod(); if (!type.HasMethods) { return(null); } return(GetMethod(resolver, type, method)); }
public virtual MethodDefinition Resolve(MethodReference method) { if (method == null) { throw new ArgumentNullException("method"); } var type = Resolve(method.DeclaringType); if (type == null) { return(null); } method = method.GetElementMethod(); if (!type.HasMethods) { return(null); } return(GetMethod(type, method)); }
public static MethodDefinition Resolve(IAssemblyResolver resolver, MethodReference method) { var type = Resolve (resolver, method.DeclaringType); if (type == null) return null; method = method.GetElementMethod (); if (!type.HasMethods) return null; return GetMethod (resolver, type, method); }
private InvocationResult OnInvocation (MethodDefinition method, ILProcessor processor, Instruction i, MethodReference mr) { Mono.Cecil.GenericParameter genPar = null; if (!mr.FullName.Contains ("<")) { //if(Verbosity >= 8) - shouldn't be reached Console.WriteLine ("[UNREACHABLE] Skipping method that contains no <"); return InvocationResult.Skipped; } if (mr.FullName.Contains (" System.")) { // REVIEW - does AOT somehow support some of these cases? if (Verbosity >= Verbosities.Skipping) Console.WriteLine ("Skipping method invocation that contains ' System.': [[" + mr.FullName + " in " + method.DeclaringType.FullName + "." + method.Name + "]]"); return InvocationResult.Failed; } #if CUSTOM // Custom blacklist if(!mr.FullName.Contains(" LionFire.") && !mr.FullName.Contains(" Dycen.")) { if(Verbosity >= Verbosities.Skipping)Console.WriteLine("Skipping method that is not LionFire or Dycen:" + mr.FullName + " in " + method.DeclaringType.FullName + "."+ method.Name); //continue; return InvocationResult.Skipped } #endif var genPars = mr.Resolve ().GenericParameters; // Console.WriteLine("TEMP2 - " + genPars.Count); // var genPars = mr.GetGenericParameters(method.Module); // Console.WriteLine("TEMP " + mr.Name); // Console.WriteLine("TEMP genPars.Count " + genPars.Count); if (genPars.Count != 1) { if (Verbosity >= Verbosities.Warning) Console.WriteLine ("[NS] Replacing methods with more than 1 generic parameter not supported: " + genPars.Count + ": " + mr.FullName + " in " + method.DeclaringType.FullName + "." + method.Name); return InvocationResult.Failed; } else { genPar = genPars [0]; // var resolved = genPar.Resolve(); // Console.WriteLine("NEW -- <" + (resolved == null ? "null" : resolved.Name) + ">"); if (Verbosity >= 10) Console.WriteLine ("NEW |- <" + genPar + ">"); } #region string genericParameter = ...; string genericParameter; Type genericTypeParameter; TypeDefinition genericTypeParameterDefinition = null; { string n = mr.FullName.Split (' ') [1]; n = n.Split (new string[]{"::"}, StringSplitOptions.RemoveEmptyEntries) [1]; int startI = n.IndexOf ('<') + 1; int stack = 0; int endI = startI + 1; while (stack > 0 || n[endI] != '>') { if (n [endI] == '<') stack++; if (n [endI] == '>') stack--; endI++; } int length = endI - startI; genericParameter = n.Substring (startI, length); // if(genericParameter.StartsWith("!!")) // { // int genParAliasIndex = Convert.ToInt32(genericParameter.Substring(2)); // // var genParAlias = genPars[genParAliasIndex]; // // // genericParameter = genParAlias.FullName; // Console.WriteLine("NEW - Generic method alias param: " + genericParameter); // } // if(genericParameter.Contains("<") || genericParameter.Contains(">")) // { // Console.WriteLine("Unsupported generic method ("+mr.FullName+") with generic parameter: " + genericParameter); // skipped++; // continue; // } if (Verbosity >= 8) Console.WriteLine ("Generic method param: " + genericParameter); genericTypeParameter = Type.GetType (genericParameter, false); //if(genericTypeParameter == null) { foreach (ModuleDefinition modDef in ads.SelectMany(assDef => assDef.Modules)) { // foreach(var modType in modDef.Types) // { // Console.WriteLine("ccc - " + modType); // } genericTypeParameterDefinition = modDef.Types.Where (td => td.FullName == genericParameter // && !td.IsGenericInstance ).FirstOrDefault (); if (genericTypeParameterDefinition != null) { if (Verbosity >= 9) Console.WriteLine ("TODO - got genTD: " + genericTypeParameterDefinition); break; } } if (genericTypeParameterDefinition == null) { if (Verbosity >= 8) Console.WriteLine (" x Could not get TypeDefinition for " + genericParameter); // No continue, this is not a problem } if (genericTypeParameter == null && genericTypeParameterDefinition == null) { if (Verbosity >= Verbosities.Error) { Console.WriteLine (" x - Failed to get Type for " + genericParameter + " in invocation: " + mr.FullName + " in method " + method.FullName); } skipped++; return InvocationResult.Failed; } } } #endregion #if ONLY_VOID_OR_GENPARM // OLD, now other return types are supported if they are the same as replaced method string matchingReturnType = "!!0"; // genericTypeParameter.FullName; if(mr.ReturnType.FullName != "System.Void" && mr.ReturnType.FullName != matchingReturnType) // && mr.ReturnType.FullName != genericTypeParameter.FullName) { if(Verbosity >= 3) Console.WriteLine(" x generic method doesn't return System.Void or '" +matchingReturnType+ "': " + mr.FullName+ ", but instead: " + mr.ReturnType.FullName); continue; } #endif // if(Verbosity >= 9) Console.WriteLine("mr: " + mr.Name); TypeDefinition tr = mr.DeclaringType.Resolve (); MethodDefinition replacementMethod = null; // if(mr.DeclaringType.Name == "MultiType") // { // foreach(MethodDefinition replacementMethod_ in // tr.Methods) // { // Console.WriteLine("z " + replacementMethod_.Name + " " + replacementMethod_.FullName); // } // } bool noCast = false; foreach (MethodDefinition replacementMethod_ in tr.Methods.Where(mr_ => mr_.Name == mr.Name && !mr_.HasGenericParameters)) { noCast = false; // TODO: Verify parameters if (!replacementMethod_.HasParameters) continue; if (replacementMethod_.Parameters.Count != mr.Parameters.Count + 1) { if (Verbosity >= 8) Console.WriteLine (" [x? param count] - (alt) candidate replacement method has wrong parameter count: " + replacementMethod_.FullName + " [[" + mr.FullName + " in " + method.DeclaringType.FullName + "." + method.Name + "]]"); continue; } // Console.WriteLine("Replacement param type: "+ replacementMethod_.Parameters[0].ParameterType.FullName); if (replacementMethod_.Parameters [replacementMethod_.Parameters.Count - 1].ParameterType.FullName != "System.Type") { if (Verbosity >= 8) Console.WriteLine (" [x? param type] - (alt) candidate replacement does not have Type parameter at the end of parameters : " + replacementMethod_.FullName + " [[" + mr.FullName + " in " + method.DeclaringType.FullName + "." + method.Name + "]]"); continue; } if (mr.ReturnType.FullName == replacementMethod_.ReturnType.Resolve ().FullName) { noCast = true; if (Verbosity >= 9) Console.WriteLine (" - (alt) generic method and alt method return same type:: " + mr.ReturnType.FullName); } else if (mr.ReturnType.FullName != "System.Void") { // Replacement must return object if (replacementMethod_.ReturnType.Resolve ().FullName != "System.Object") { if (Verbosity >= 3) Console.WriteLine (" [x? return] (alt) generic method returns T but candidate replacement method does not return System.Object: " + replacementMethod_.FullName + " [[" + mr.FullName + " in " + method.DeclaringType.FullName + "." + method.Name + "]]"); continue; } } if (Verbosity >= 8) Console.WriteLine ("FOUND ALTERNATE METHOD: " + replacementMethod_); replacementMethod = replacementMethod_; break; // FUTURE: don't break here, keep going to see if there are multiple (ambiguous) matches and throw/output error } if (replacementMethod == null) { if (!(" " + mr.FullName).Contains (" System.")) { if (Verbosity >= Verbosities.Warning) Console.WriteLine ("[__] No alternate found for [[" + mr.FullName + " in " + method.DeclaringType.FullName + "." + method.Name + "]]"); // + mr.DeclaringType.FullName+"." +mr.Name + "(...)"); } skipped++; return InvocationResult.Failed; } // if(mr.Name != "TestMethod") continue; // TEMP if (Verbosity >= Verbosities.Success) Console.WriteLine (" O Replacing " + mr.FullName + " " + mr.GenericParameters.Count + " generic parameters" + " " + mr.Parameters.Count + " parameters" + " | " + mr.GetElementMethod ().FullName + "" + " | " + mr.GetElementMethod ().HasGenericParameters + "" + " | " + mr.GetElementMethod ().GenericParameters [0].Name + "" ); // if(Verbosity >= 6) // Console.WriteLine("Resolved non-specific generic method: " + mr.FullName); // if(Verbosity >= 8) Console.WriteLine("RESOLVED TYPE: " + genericTypeParameter); // var typeModuleDefinition = ModuleDefinition.ReadModule(type.Module.Assembly.Location); // var typeDefinition = typeModuleDefinition.Types.Where(td => td.FullName == genericParameter).FirstOrDefault(); // if(typeDefinition != null && Verbosity >= 5) // { // Console.WriteLine("Resolved typeDefinition: " + typeDefinition); // } // else // { // Console.WriteLine("Failed to resolve typeDefinition: " + type.FullName); //// foreach(var td in ModuleDefinition.ReadModule(type.Module.Assembly.Location).Types) //// { //// Console.WriteLine(" ... " + td.FullName); //// } // continue; // } // method.Module.Import(type); // try removing this // IMetadataScope scope = method.Module; // var typeRef = new TypeReference(type.Namespace, type.Name, typeModuleDefinition, scope, type.IsValueType); // Console.WriteLine("TypeRef: "+ typeRef); // method.Module.Import(type); var replacementMethodImported = method.Module.Import (replacementMethod); // IL_0000: ldtoken Rewriter.TestClass if (genericTypeParameter != null) { processor.InsertBefore (i, processor.Create (OpCodes.Ldtoken, method.Module.Import (genericTypeParameter))); } else { processor.InsertBefore (i, processor.Create (OpCodes.Ldtoken, method.Module.Import (genericTypeParameterDefinition))); } // IL_0005: call class [mscorlib]System.Type class // [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) var gtfh = typeof(Type).GetMethod ("GetTypeFromHandle"); MethodReference gtfhRef = method.Module.Import (gtfh, mr); processor.InsertBefore (i, processor.Create (OpCodes.Call, gtfhRef)); // IL_000a: call void class Rewriter.TestClass::TestMethod(class [mscorlib]System.Type) var callMethod = processor.Create (i.OpCode, replacementMethodImported); processor.InsertAfter (i, callMethod); #region Cast the result, if it exists if (mr.ReturnType.FullName != "System.Void" && !noCast) { string castAssembly; string castType; if (genericTypeParameter != null) { castAssembly = genericTypeParameter.Assembly.GetName (false).Name; castType = "[" + castAssembly + "]" + genericTypeParameter.FullName; } else if (genericTypeParameterDefinition != null) { castAssembly = ""; castType = genericTypeParameterDefinition.ToString (); // var resolvedGTPD = genericTypeParameterDefinition.Resolve(); // resolvedGTPD.FullName } else { castType = "???"; Console.WriteLine ("INTERNAL ERROR - genericTypeParameter not set for " + mr.FullName + ". genericTypeParameterDefinition:" + genericTypeParameterDefinition.Resolve ()); return InvocationResult.Failed; } // castAssembly = castAssembly.Substring(castAssembly.IndexOf(",")); if (Verbosity > 8) Console.WriteLine ("CAST to " + castType + " | " + genericTypeParameterDefinition); var importedGenericType = mr.Module.Import (genericTypeParameterDefinition); processor.InsertAfter (callMethod, processor.Create (OpCodes.Castclass, importedGenericType)); } #endregion processor.Remove (i); replaced++; // if(Verbosity >= Verbosities.Success) // Console.WriteLine(" - " + ((MethodReference)i.Operand).Name + " replaced with " + replacementMethod.FullName); // mr.GetGenericParameters(null); // // if(method.GenericParameters.Count == 0) return; // // if(method.GenericParameters.Count > 1) // { // Console.WriteLine("Warning: cannot handle more than one generic parameter yet: " + // method.DeclaringType.FullName + "." + method.Name); // return; // } // // var body = method.Body; // body.Instructions // if(method.GenericParameters.Count == 1) // { // } return InvocationResult.Succeeded; }
private MethodDefinition ResolveManually(MethodReference method) { var metadataResolver = method.Module.MetadataResolver; var type = metadataResolver.Resolve(method.DeclaringType); if (type == null || !type.HasMethods) { return null; } method = method.GetElementMethod(); Func<IEnumerable<MethodDefinition>, MethodReference, MethodDefinition>[] finderMethods = {GetMethodDefinition, GetCompatibleMethodDefinition}; for (int i = 0; i < finderMethods.Length; i++) { while (type != null) { var methodDefinition = finderMethods[i](type.Methods, method); if (methodDefinition != null) { return methodDefinition; } if (type.BaseType == null) { break; } type = metadataResolver.Resolve(type.BaseType); } type = metadataResolver.Resolve(method.DeclaringType); } return null; }
private bool TryToResolveInSupport(MethodReference method) { if (string.IsNullOrEmpty(Context.SupportModulePartialNamespace)) return false; method = method.GetElementMethod(); var originalType = method.DeclaringType; if (originalType.IsGenericInstance || originalType.HasGenericParameters) return false; var support = SupportAssemblyReference(); var ns = Context.SupportModulePartialNamespace; if (!string.IsNullOrEmpty(originalType.Namespace)) ns += '.' + originalType.Namespace; method.DeclaringType = new TypeReference(ns, originalType.Name, Context.TargetModule, support, originalType.IsValueType); MethodDefinition resolved = null; // We can only change declaring type like this for static methods if (!method.HasThis) { resolved = method.Resolve(); } // If our method is instance, we can have a static method in support module that has explicit "this" parameter if (resolved == null && method.HasThis) { method.HasThis = false; method.Parameters.Insert(0, new ParameterDefinition(originalType)); resolved = method.Resolve(); // Our explicit "this" parameter can be of type System.Object if (resolved == null) { method.Parameters[0] = new ParameterDefinition(method.DeclaringType.Module.TypeSystem.Object.Resolve()); resolved = method.Resolve(); } if (resolved == null) { method.HasThis = true; method.Parameters.RemoveAt(0); } } if (resolved != null) { Context.RewriteTarget = true; AddSupportReferenceIfNeeded(support); return true; } method.DeclaringType = originalType; return false; }
private static ulong GetToken (MethodReference method) { return (ulong) method.DeclaringType.Module.Assembly.GetHashCode () << 32 | method.GetElementMethod ().MetadataToken.ToUInt32 (); }
private StaticMethodWrapper WrapMethod(MethodReference methodRefHandle) { var declaringType = MakeDeclaredType(methodRefHandle.DeclaringType); var declaringTypeDefnHandle = (TypeDefinition)declaringType.Handle; var methodDefnHandle = FindMatchingMethod(methodRefHandle.GetElementMethod(), declaringTypeDefnHandle.Methods); var method = new StaticMethodWrapper(this, methodDefnHandle, declaringType, declaringType, declaringType.Substitution); var genericInstance = methodRefHandle as GenericInstanceMethod; if (genericInstance != null) { var genericArguments = CollectionUtils.ConvertAllToArray<TypeReference, ITypeInfo>(genericInstance.GenericArguments, MakeType); method = method.MakeGenericMethod(genericArguments); } return method; }
/// <summary> /// Check the given method reference. /// </summary> private void Check(MethodReference method, string context) { if (!Check(method.DeclaringType, context)) return; var error = false; try { if (method.IsGenericInstance) { Check((GenericInstanceMethod)method, context); } else { var typeDef = method.DeclaringType.GetElementType().Resolve(); var emethod = method.GetElementMethod(); var methodDef = (typeDef != null) ? typeDef.Methods.FirstOrDefault(x => x.AreSameExcludingGenericArguments(emethod, null)) : null; error = (methodDef == null); } } catch (Exception) { error = true; } CheckResolveData data; var key = method.FullName; if (!resolveErrorMethodNames.TryGetValue(key, out data)) { data = new CheckResolveData { IsAvailable = !error }; resolveErrorMethodNames.Add(key, data); if (error) { Error(MessageTypes.MissingMethod, Format(method, false), method.DeclaringType.Scope, context); } } data.CheckCount++; }
public virtual MethodDefinition Resolve (MethodReference method) { if (method == null) throw new ArgumentNullException ("method"); var type = Resolve (method.DeclaringType); if (type == null) return null; method = method.GetElementMethod (); if (!type.HasMethods) return null; return GetMethod (type, method); }
private StaticConstructorWrapper WrapConstructor(MethodReference methodRefHandle) { var declaringType = MakeDeclaredType(methodRefHandle.DeclaringType); var declaringTypeDefnHandle = (TypeDefinition)declaringType.Handle; var methodDefnHandle = FindMatchingMethod(methodRefHandle.GetElementMethod(), GetConstructors(declaringTypeDefnHandle.Methods)); return new StaticConstructorWrapper(this, methodDefnHandle, declaringType); }
public sealed override MethodReference GetElementMethod() { return(method.GetElementMethod()); }
private static uint GetToken (MethodReference method) { return method.GetElementMethod ().MetadataToken.ToUInt32 (); }
public MethodDefinition Resolve (MethodReference method) { TypeDefinition type = Resolve (method.DeclaringType); method = method.GetElementMethod (); return GetMethod (type, method); }
/// <summary> /// Creates the function. /// </summary> /// <param name="method">The method.</param> /// <returns></returns> Function CreateFunction(MethodReference method) { Function function; if (functions.TryGetValue(method, out function)) return function; var resolvedMethod = method.Resolve(); var declaringType = GetType(ResolveGenericsVisitor.Process(method, method.DeclaringType), TypeState.Opaque); // Check if method is only defined in a parent class (can happen in some rare case, i.e. PCL TypeInfo.get_Assembly()). bool hasMatch = MetadataResolver.GetMethod(declaringType.TypeDefinitionCecil.Methods, method.GetElementMethod()) != null; if (resolvedMethod != null && !hasMatch) { var parentType = declaringType.TypeDefinitionCecil.BaseType != null ? ResolveGenericsVisitor.Process(declaringType.TypeReferenceCecil, declaringType.TypeDefinitionCecil.BaseType) : null; if (parentType == null) throw new InvalidOperationException(string.Format("Could not find a matching method in any of the type or its parent for {0}", method)); // Create function with parent type // TODO: Maybe we need to replace generic context with parent type? var parentMethod = method.ChangeDeclaringType(parentType); function = CreateFunction(parentMethod); // Register it so that it can be cached functions.Add(method, function); return function; } var returnType = GetType(ResolveGenericsVisitor.Process(method, method.ReturnType), TypeState.StackComplete); var parameterTypesBuilder = new List<Type>(); if (method.HasThis) { var parameterType = declaringType.TypeReferenceCecil; // Value type uses ByReference type for this if (declaringType.TypeDefinitionCecil.IsValueType) parameterType = parameterType.MakeByReferenceType(); parameterTypesBuilder.Add(GetType(parameterType, TypeState.StackComplete)); } foreach (var parameter in method.Parameters) { parameterTypesBuilder.Add(GetType(ResolveGenericsVisitor.Process(method, parameter.ParameterType), TypeState.StackComplete)); } var parameterTypes = parameterTypesBuilder.ToArray(); // Find calling convention var callingConvention = method.CallingConvention; PInvokeInfo pinvokeInfo = null; if (resolvedMethod != null && resolvedMethod.HasPInvokeInfo) { pinvokeInfo = resolvedMethod.PInvokeInfo; if (resolvedMethod.PInvokeInfo.IsCallConvStdCall || resolvedMethod.PInvokeInfo.IsCallConvWinapi) callingConvention = MethodCallingConvention.StdCall; else if (resolvedMethod.PInvokeInfo.IsCallConvFastcall) callingConvention = MethodCallingConvention.FastCall; } var functionSignature = new FunctionSignature(abi, returnType, parameterTypes, callingConvention, pinvokeInfo); var functionType = CreateFunctionTypeLLVM(functionSignature); // If we have an external with generic parameters, let's try to do some generic sharing (we can write only one in C++) bool isInternal = resolvedMethod != null && ((resolvedMethod.ImplAttributes & MethodImplAttributes.InternalCall) != 0); if (isInternal && resolvedMethod.HasGenericParameters && resolvedMethod.GenericParameters.All(x => x.HasReferenceTypeConstraint)) { // Check if this isn't the shareable method (in which case we should do normal processing) if (!((GenericInstanceMethod)method).GenericArguments.All(x => MemberEqualityComparer.Default.Equals(x, @object.TypeReferenceCecil))) { // Let's share it with default method var sharedGenericInstance = new GenericInstanceMethod(resolvedMethod); foreach (var genericParameter in resolvedMethod.GenericParameters) { sharedGenericInstance.GenericArguments.Add(@object.TypeReferenceCecil); } var sharedMethod = GetFunction(sharedGenericInstance); // Cast shared function to appropriate pointer type var sharedFunctionGlobal = LLVM.ConstPointerCast(sharedMethod.GeneratedValue, LLVM.PointerType(functionType, 0)); function = new Function(declaringType, method, functionType, sharedFunctionGlobal, functionSignature); functions.Add(method, function); return function; } } // Determine if type and function is local, and linkage type bool isLocal; var linkageType = GetLinkageType(method.DeclaringType, out isLocal); if (isInternal) { // Should be switched to non-weak when we have complete implementation of every internal calls linkageType = Linkage.ExternalWeakLinkage; } else if (resolvedMethod != null && resolvedMethod.HasGenericParameters) { isLocal = true; linkageType = Linkage.LinkOnceAnyLinkage; } bool isRuntime = resolvedMethod != null && ((resolvedMethod.ImplAttributes & MethodImplAttributes.Runtime) != 0); bool isInterfaceMethod = declaringType.TypeDefinitionCecil.IsInterface; var hasDefinition = resolvedMethod != null && (resolvedMethod.HasBody || isInternal || isRuntime); var methodMangledName = Regex.Replace(method.MangledName(), @"(\W)", "_"); var functionGlobal = hasDefinition ? LLVM.AddFunction(module, methodMangledName, functionType) : LLVM.ConstPointerNull(LLVM.PointerType(functionType, 0)); // Interface method uses a global so that we can have a unique pointer to use as IMT key if (isInterfaceMethod) { // For test code only: Use linkonce instead of linkageType so that we know if type was forced if (TestMode) { isLocal = true; linkageType = Linkage.LinkOnceAnyLinkage; } functionGlobal = LLVM.AddGlobal(module, LLVM.Int8TypeInContext(context), methodMangledName); if (isLocal) LLVM.SetInitializer(functionGlobal, LLVM.ConstNull(LLVM.Int8TypeInContext(context))); LLVM.SetLinkage(functionGlobal, linkageType); } if (hasDefinition) { ApplyFunctionAttributes(functionSignature, functionGlobal); } function = new Function(declaringType, method, functionType, functionGlobal, functionSignature); functions.Add(method, function); if (hasDefinition) { switch (callingConvention) { case MethodCallingConvention.StdCall: LLVM.SetFunctionCallConv(functionGlobal, (uint)CallConv.X86StdcallCallConv); break; case MethodCallingConvention.FastCall: LLVM.SetFunctionCallConv(functionGlobal, (uint)CallConv.X86FastcallCallConv); break; } if (isLocal && !isInternal) { // Need to compile EmitFunction(function); } // Apply linkage LLVM.SetLinkage(functionGlobal, linkageType); } return function; }