GetElementMethod() public method

public GetElementMethod ( ) : MethodReference
return MethodReference
Beispiel #1
0
        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);
        }
Beispiel #2
0
        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));
        }
Beispiel #3
0
        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));
        }
Beispiel #4
0
        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));
        }
Beispiel #5
0
        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;
        }
Beispiel #11
0
 /// <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++;
 }
Beispiel #12
0
		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);
 }
Beispiel #14
0
 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;
        }