Resolve() публичный Метод

public Resolve ( ) : Mono.Cecil.MethodDefinition
Результат Mono.Cecil.MethodDefinition
        static bool MethodMatch(MethodReference candidate, MethodReference method)
        {
            var candidateResolved = candidate.Resolve();

            // Check overrides
            if (candidateResolved.HasOverrides)
            {
                foreach (var @override in candidateResolved.Overrides)
                {
                    var resolvedOverride = ResolveGenericsVisitor.Process(candidate, @override);
                    return MemberEqualityComparer.Default.Equals(resolvedOverride, method);
                }
            }

            if (!candidateResolved.IsVirtual)
                return false;

            if (candidate.Name != method.Name)
                return false;

            if (!TypeMatch(ResolveGenericsVisitor.Process(candidate, candidate.ReturnType), ResolveGenericsVisitor.Process(method, method.ReturnType)))
                return false;

            if (candidate.Parameters.Count != method.Parameters.Count)
                return false;

            for (int i = 0; i < candidate.Parameters.Count; i++)
                if (!TypeMatch(ResolveGenericsVisitor.Process(candidate, candidate.Parameters[i].ParameterType), ResolveGenericsVisitor.Process(method, method.Parameters[i].ParameterType)))
                    return false;

            return true;
        }
Пример #2
0
 private static bool DoesMatchMethod(MethodReference mInternal, MethodReference m) {
     var mInternalDef = mInternal.Resolve();
     if (mInternalDef.GetCustomAttribute<JsRedirectAttribute>() != null) {
         // Can never return a redirected method
         return false;
     }
     // Look for methods with custom signatures
     var detailsAttr = mInternalDef.GetCustomAttribute<JsDetailAttribute>(true);
     if (detailsAttr != null) {
         var signature = detailsAttr.Properties.FirstOrDefault(x => x.Name == "Signature");
         if (signature.Name != null) {
             if (mInternal.Name != m.Name) {
                 return false;
             }
             var sigTypes = ((CustomAttributeArgument[])signature.Argument.Value)
                 .Select(x => ((TypeReference)x.Value).FullResolve(m))
                 .ToArray();
             var mReturnType = m.ReturnType.FullResolve(m);
             if (!mReturnType.IsSame(sigTypes[0])) {
                 return false;
             }
             for (int i = 0; i < m.Parameters.Count; i++) {
                 var mParameterType = m.Parameters[i].ParameterType.FullResolve(m);
                 if (!mParameterType.IsSame(sigTypes[i + 1])) {
                     return false;
                 }
             }
             return true;
         }
     }
     // Look for C# method that matches with custom 'this'
     Func<bool> isFakeThis = () => {
         if (mInternal.HasThis) {
             return false;
         }
         if (mInternal.Name != m.Name) {
             return false;
         }
         if (mInternal.Parameters.Count != m.Parameters.Count + 1) {
             return false;
         }
         if (mInternal.Parameters[0].GetCustomAttribute<JsFakeThisAttribute>() == null) {
             return false;
         }
         if (!mInternal.ReturnType.IsSame(m.ReturnType)) {
             return false;
         }
         for (int i = 1; i < mInternal.Parameters.Count; i++) {
             if (!mInternal.Parameters[i].ParameterType.IsSame(m.Parameters[i - 1].ParameterType)) {
                 return false;
             }
         }
         return true;
     };
     if (isFakeThis()) {
         return true;
     }
     // Look for C# method that match signature
     return mInternal.MatchMethodOnly(m);
 }
Пример #3
0
    void FindGetLogger(TypeDefinition typeDefinition)
    {
        if (!typeDefinition.IsPublic)
        {
            var message = $"The logger factory type '{typeDefinition.FullName}' needs to be public.";
            throw new WeavingException(message);
        }
        GetLoggerMethod = typeDefinition
            .Methods
            .FirstOrDefault(x =>
                x.Name ==  "GetLogger" && 
                x.IsStatic &&
                x.HasGenericParameters &&
                x.GenericParameters.Count == 1 &&
                x.Parameters.Count == 0);

        if (GetLoggerMethod == null)
        {
            throw new WeavingException("Found 'LoggerFactory' but it did not have a static 'GetLogger' method that takes 'string' as a parameter");
        }
        if (!GetLoggerMethod.Resolve().IsPublic)
        {
            var message = $"The logger factory method '{GetLoggerMethod.FullName}' needs to be public.";
            throw new WeavingException(message);
        }
    }
 public bool IsSetup(MethodReference target)
 {
     if (!IsInFixture(target)) return false;
     var field = MSpecTranslator.TranslateGeneratedMethod(target.Resolve());
     if (field == null) return false;
     return field.FieldType.Name == "Establish" || field.FieldType.Name == "Because";
 }
Пример #5
0
        public Function(Type declaringType, MethodReference methodReference, TypeRef functionType, ValueRef generatedValue, FunctionSignature signature)
        {
            Signature = signature;
            DeclaringType = declaringType;
            MethodReference = methodReference;
            FunctionType = functionType;
            GeneratedValue = generatedValue;
            VirtualSlot = -1;

            MethodDefinition = methodReference.Resolve();

            ParameterTypes = signature.ParameterTypes.Select(x => x.Type).ToArray();

            // Generate function type when being called from vtable/IMT (if it applies)
            // If declaring type is a value type, needs to unbox "this" for virtual method
            if (DeclaringType.TypeDefinitionCecil.IsValueType
                && (MethodDefinition.Attributes & MethodAttributes.Virtual) != 0)
            {
                bool hasStructValueReturn = signature.ReturnType.ABIParameterInfo.Kind == ABIParameterInfoKind.Indirect;

                // Create function type with boxed "this"
                var argumentCount = LLVM.CountParamTypes(FunctionType);
                var argumentTypes = new TypeRef[argumentCount];
                LLVM.GetParamTypes(FunctionType, argumentTypes);
                // Change first type to boxed "this"
                var thisIndex = hasStructValueReturn ? 1 : 0;
                argumentTypes[thisIndex] = LLVM.PointerType(DeclaringType.ObjectTypeLLVM, 0);
                VirtualFunctionType = LLVM.FunctionType(LLVM.GetReturnType(FunctionType), argumentTypes, LLVM.IsFunctionVarArg(FunctionType));
            }
            else
            {
                VirtualFunctionType = FunctionType;
            }
        }
Пример #6
0
        public Method(MethodReference methodReference, ComponentCache componentCache)
        {
            Contract.Requires<ArgumentNullException>(methodReference != null);
            Contract.Requires<ArgumentNullException>(componentCache != null);

            method = methodReference.Resolve();
            cache = componentCache;
        }
Пример #7
0
 private static void CloneMethodAttributes(MethodReference sourceMethod, MethodReference clonedMethod)
 {
     var s = sourceMethod.Resolve();
     var c = clonedMethod.Resolve();
     c.CallingConvention = s.CallingConvention;
     c.SemanticsAttributes = s.SemanticsAttributes;
     s.CustomAttributes.ToList().ForEach(a => c.CustomAttributes.Add(a));
     s.SecurityDeclarations.ToList().ForEach(sd => c.SecurityDeclarations.Add(sd));
 }
Пример #8
0
        public static string Create(MethodReference mRef, Resolver resolver, ICode ast) {
            if (mRef.ContainsGenericParameters()) {
                throw new ArgumentException("Cannot create JS for method with open generic parameters");
            }
            var mDef = mRef.Resolve();
            if (mDef.IsAbstract) {
                throw new ArgumentException("Should never need to transcode an abstract method");
            }
            var tRef = mRef.DeclaringType;
            var tDef = tRef.Resolve();

            var v = new JsMethod(resolver);
            v.Visit(ast);
            var js = v.js.ToString();

            var sb = new StringBuilder();
            // Method declaration
            var methodName = resolver.MethodNames[mRef];
            //var parameterNames = mRef.Parameters.Select(x => v.parameters.ValueOrDefault(x).NullThru(y => resolver.LocalVarNames[y])).ToArray();
            // Match parameters, but have to do by position, as method built may be a custom method replacing a BCL method,
            // so parameters are not the same.
            var parameterNames = mRef.Parameters.Select(x => v.parameters.FirstOrDefault(y => y.Key.Sequence == x.Sequence).Value.NullThru(y => resolver.LocalVarNames[y])).ToArray();
            if (!mDef.IsStatic) {
                var thisName = v.vars.FirstOrDefault(x => x.ExprType == Expr.NodeType.VarThis).NullThru(x => resolver.LocalVarNames[x]);
                parameterNames = parameterNames.Prepend(thisName).ToArray();
            }
            var unusedParameterNameGen = new NameGenerator();
            parameterNames = parameterNames.Select(x => x ?? ("_" + unusedParameterNameGen.GetNewName())).ToArray();
            sb.AppendFormat("// {0}", mRef.FullName);
            sb.AppendLine();
            sb.AppendFormat("var {0} = function({1}) {{", methodName, string.Join(", ", parameterNames));
            // Variable declarations
            var declVars = v.vars
                .Select(x => new { name = resolver.LocalVarNames[x], type = x.Type })
                .Where(x => !parameterNames.Contains(x.name))
                .Select(x => {
                    var name = x.name;
                    if (x.type.IsValueType) {
                        name += " = " + DefaultValuer.Get(x.type, resolver.FieldNames);
                    }
                    return name;
                })
                .Distinct() // Bit of a hack, but works for now
                .ToArray();
            if (declVars.Any()) {
                sb.AppendLine();
                sb.Append(' ', tabSize);
                sb.AppendFormat("var {0};", string.Join(", ", declVars));
            }
            // Method body
            sb.AppendLine(js);
            // Method ending
            sb.AppendLine("};");

            var sbStr = sb.ToString();
            return sbStr;
        }
 private bool HasMethod(MethodReference method)
 {
     foreach (var baseMethod in _baseMethodsSet) {
     if (baseMethod.Class == method.DeclaringType && baseMethod.Definition == method.Resolve()) {
       return true;
     }
       }
       return false;
 }
 public MethodDefinition GetFactoryMethod(MethodReference ctor, AssemblyDefinition assembly, IAssemblyTracker tracker)
 {
     if (!_factoryMethods.ContainsKey (ctor))
       {
     var memberId = CecilResolver.CreateMemberID (ctor.Resolve());
     AssemblyNameReference containingTrackedAssembly;
     _factoryMethods[ctor] = CecilResolver.ResolveToMethodDefinition (_infoProvider.GetFactoryMethodFunc (memberId), tracker, out containingTrackedAssembly);
     if (containingTrackedAssembly != null)
       tracker.TrackNewReference (assembly, containingTrackedAssembly);
       }
       return _factoryMethods[ctor];
 }
Пример #11
0
 protected virtual bool IsAssertMethod(MethodReference methodReference)
 {
     var resolved = methodReference.Resolve();
     var name = resolved.DeclaringType.Name;
     if (!resolved.IsStatic || !name.EndsWith("Assert"))
     {
         return false;
     }
     else
     {
         return true;
     }
 }
Пример #12
0
        public MethodDefinition CloneIntoType(MethodReference sourceMethod, TypeDefinition type)
        {
            var s = sourceMethod.Resolve();
            var c = new MethodDefinition(s.Name, s.Attributes, s.ReturnType);
            type.Methods.Add(c);

            CloneMethodProperties(c, s);
            CloneMethodAttributes(c, s);
            CloneMethodParameters(s, c);
            CloneGenericParameters(s, c);

            return c;
        }
Пример #13
0
 private MethodDefinition ResolveMethod(MethodReference aRef)
 {
     var xDef = aRef as MethodDefinition;
     if (xDef != null)
     {
         return xDef;
     }
     var xSpec = aRef as GenericInstanceMethod;
     if (xSpec != null)
     {
         throw new Exception("Queueing generic methods not yet(?) supported!");
     }
     return aRef.Resolve();
 }
Пример #14
0
 public Ctx(TypeReference tRef, MethodReference mRef, Ctx fromCtx = null) {
     this.TRef = tRef;
     this.TDef = tRef.Resolve();
     this.MRef = mRef;
     this.MDef = mRef.Resolve();
     this.HasFakeThis = mRef.Parameters.FirstOrDefault().NullThru(x => x.GetCustomAttribute<JsFakeThisAttribute>() != null);
     this.Module = mRef.Module;
     this.TypeSystem = mRef.Module.TypeSystem;
     this.ExprGen = Expr.CreateExprGen(this);
     this.This = fromCtx == null ? (this.MDef.IsStatic ? null : new ExprVarThis(this, tRef)) : fromCtx.This;
     this.type = new Lazy<TypeReference>(() => this.Module.Import(typeof(Type)));
     this._int64 = new Lazy<TypeReference>(() => this.Module.Import(typeof(Cls._Int64)));
     this._uint64 = new Lazy<TypeReference>(() => this.Module.Import(typeof(Cls._UInt64)));
 }
 public uint GetOrCreateIndex(MethodReference method, IMetadataCollection metadataCollection)
 {
     if (method == null)
     {
         return 0;
     }
     if (method.IsGenericInstance || method.DeclaringType.IsGenericInstance)
     {
         Il2CppGenericMethodCollectorWrite.Add(method);
         if (Il2CppGenericMethodCollectorRead.HasIndex(method))
         {
             return (Il2CppGenericMethodCollectorRead.GetIndex(method) | 0xc0000000);
         }
         return 0xc0000000;
     }
     return (uint) (metadataCollection.GetMethodIndex(method.Resolve()) | 0x60000000);
 }
Пример #16
0
        public void WalkMethod(MethodReference methodReference) {
            if (!AddMethod(methodReference))
            {
                return;
            }

            var method = methodReference.Resolve();

            List<Instruction> foundInstructions = (from instruction in method.Body.Instructions
                                                   where method.HasBody && method.Body.Instructions != null && instruction.Operand != null
                                                   select instruction).ToList();

            IEnumerable<TypeReference> typesFound = from instruction in foundInstructions
                                                     let tRef = instruction.Operand as TypeReference
                                                     where tRef != null
                                                     select tRef;

            IEnumerable<MethodReference> methodsFound = from instruction in foundInstructions
                                                         let mRef = instruction.Operand as MethodReference
                                                         where mRef != null && mRef.DeclaringType != null
                                                         select mRef;

            IEnumerable<FieldDefinition> fieldsFound = from instruction in foundInstructions
                                                       let fRef = instruction.Operand as FieldReference
                                                       where fRef != null && fRef.FieldType != null
                                                       let fRefResolved = fRef.Resolve()
                                                       where fRefResolved != null
                                                       select fRefResolved;

            foreach (TypeReference typeDefinition in typesFound)
            {
                AddType(typeDefinition);
            }

            foreach (FieldDefinition fieldDefinition in fieldsFound) {
                AddField(fieldDefinition);
            }

            foreach (MethodReference methodDefinition in methodsFound)
            {
                if (methodDefinition != method) {
                    WalkMethod(methodDefinition);
                }
            }
        }
Пример #17
0
 private static void CloneMethodProperties(MethodReference sourceMethod, MethodReference clonedMethod)
 {
     var s = sourceMethod.Resolve();
     var c = clonedMethod.Resolve();
     c.IsAbstract = s.IsAbstract;
     c.IsAddOn = s.IsAddOn;
     c.IsAssembly = s.IsAssembly;
     c.IsCheckAccessOnOverride = s.IsCheckAccessOnOverride;
     c.IsCompilerControlled = s.IsCompilerControlled;
     c.IsFamily = s.IsFamily;
     c.IsFamilyAndAssembly = s.IsFamilyAndAssembly;
     c.IsFamilyOrAssembly = s.IsFamilyOrAssembly;
     c.IsFinal = s.IsFinal;
     c.IsFire = s.IsFire;
     c.IsForwardRef = s.IsForwardRef;
     c.IsGetter = s.IsGetter;
     c.IsHideBySig = s.IsHideBySig;
     c.IsIL = s.IsIL;
     c.IsInternalCall = s.IsInternalCall;
     c.IsManaged = s.IsManaged;
     c.IsNative = s.IsNative;
     c.IsNewSlot = s.IsNewSlot;
     c.IsPInvokeImpl = s.IsPInvokeImpl;
     c.IsPreserveSig = s.IsPreserveSig;
     c.IsPrivate = s.IsPrivate;
     c.IsPublic = s.IsPublic;
     c.IsRemoveOn = s.IsRemoveOn;
     c.IsReuseSlot = s.IsReuseSlot;
     c.IsRuntime = s.IsRuntime;
     c.IsRuntimeSpecialName = s.IsRuntimeSpecialName;
     c.IsSetter = s.IsSetter;
     c.IsSpecialName = s.IsSpecialName;
     c.IsStatic = s.IsStatic;
     c.IsSynchronized = s.IsSynchronized;
     c.IsUnmanaged = s.IsUnmanaged;
     c.IsUnmanagedExport = s.IsUnmanagedExport;
     c.IsVirtual = s.IsVirtual;
     c.NoInlining = s.NoInlining;
     c.NoOptimization = s.NoOptimization;
 }
Пример #18
0
        void AddMethodToScan(MethodReference m, MethodInfo caller)
        {
            if (m == null) return;
            if (m.DeclaringType.Namespace.StartsWith ("System")) return;
            var def = m as MethodDefinition;
            if (def == null) {
                try {
                    def = m.Resolve ();
                }
                catch (Exception) {
                    def = null;
                }
            }
            if (def != null && def.HasBody) {
                var key = def.FullName;
                if (scannedMethods.ContainsKey (key)) return;
                var mi = default(MethodInfo);
                if (!methodsToScan.TryGetValue (key, out mi)) {

                    mi = new MethodInfo () { Def = def, Caller = caller, };
                    methodsToScan.Add (key, mi);
                }
            }
        }
Пример #19
0
 private static GenericInstanceMethod ConstructGenericMethod(GenericContext context, TypeReference declaringType, MethodDefinition method, IEnumerable<TypeReference> genericArguments)
 {
     MethodReference owner = new MethodReference(method.Name, method.ReturnType, declaringType) {
         HasThis = method.HasThis
     };
     foreach (GenericParameter parameter in method.GenericParameters)
     {
         owner.GenericParameters.Add(new GenericParameter(parameter.Name, owner));
     }
     foreach (ParameterDefinition definition in method.Parameters)
     {
         owner.Parameters.Add(new ParameterDefinition(definition.Name, definition.Attributes, definition.ParameterType));
     }
     if (owner.Resolve() == null)
     {
         throw new Exception();
     }
     GenericInstanceMethod method2 = new GenericInstanceMethod(owner);
     foreach (TypeReference reference3 in genericArguments)
     {
         method2.GenericArguments.Add(InflateType(context, reference3));
     }
     return method2;
 }
        public void Visit(MethodReference method, string referencingEntityName)
        {
            MethodChanged = false;
            ParamsMethod = null;

            if (method.DeclaringType.Scope == SupportAssemblyReference() && TryToResolveInSupport(method))
                return;

            if (method.Resolve() != null || method.DeclaringType.IsArray || TryToResolveInSupport(method) || ResolveManually(method) != null)
                return;

            if (IsIgnoredType(method.DeclaringType))
                return;

            Console.WriteLine("Error: method `{0}` doesn't exist in target framework. It is referenced from {1} at {2}.",
                method, method.Module.Name, referencingEntityName);
        }
		private static bool CheckTypeForMethodUsage (TypeDefinition type, MethodReference method)
		{
			if (type.HasGenericParameters)
				type = type.GetElementType ().Resolve ();

			HashSet<ulong> methods = GetCache (type);
			if (methods.Contains (GetToken (method)))
				return true;

			MethodDefinition md = method.Resolve ();
			if ((md != null) && md.HasOverrides) {
				foreach (MethodReference mr in md.Overrides) {
					if (methods.Contains (GetToken (mr)))
						return true;
				}
			}
			return false;
		}
        /// <summary>
        /// Create a postfix for the name of the given method based on 
        /// - "unsigned" parameter types: these will be mapped to their signed counterparts; 
        /// - on 'ref' our 'out' status, as these will be mapped to arrays; 
        /// - on generic parameters (as these will be mapped to 'object');
        /// - on generic parameters of parameters, as these will be type-erased;
        /// - on generic method parameters, e.g. void Foo[T](), again type-erasure being the reason.
        /// 
        /// See also http://stackoverflow.com/questions/8808703/method-signature-in-c-sharp
        /// </summary>
        private static string CreateSignaturePostfix(MethodReference method)
        {
            var declaringType = method.DeclaringType;

            if (declaringType.IsArray)
                return string.Empty;
            if ((method.Name == ".ctor") || (method.Name == ".cctor"))
                return string.Empty;

            var declType = declaringType.GetElementType().Resolve();
            if ((declType != null) && (declType.IsDelegate()))
                return string.Empty;

            var methodDef = method.Resolve();

            // dont handle events.
            if (methodDef.IsAddOn || methodDef.IsRemoveOn)
                return "";

            var needsPostfix = false;
            var postfix = new StringBuilder("$$");

            const bool processGenerics = true;
            const bool forcePostfixOnParmType = true;

            List<ParameterDefinition> types = new List<ParameterDefinition>(method.Parameters);

            if (ReturnTypeSegregatesOverloads(methodDef) 
             || (methodDef.IsHideBySig && !method.ReturnType.IsVoid())) // TODO: check if it is ok to exlude Void here.
                                                        // Note that for CLR, the return type always segregates overloads.
                                                        // It doesn't for C# (and most high level languages), 
                                                        // and that's what we are aiming at at the moment.
                                                          
                types.Add(new ParameterDefinition(method.ReturnType));

            foreach (var parm in types)
            {
                var parmTypeId = "";
                var parameterType = parm.ParameterType;

                if (parameterType.IsByReference)
                {
                    parmTypeId += "r";
                    parameterType = ((ByReferenceType)parameterType).ElementType;
                }

                if (parmTypeId != "" && forcePostfixOnParmType)
                    needsPostfix = true;

                var typeId = GetTypeId(parameterType, processGenerics);

                if (typeId != null)
                    needsPostfix = true;
                else if (parmTypeId == "")
                    typeId = "_";

                postfix.Append(parmTypeId + typeId);
            }

            // add marker for generic method parameters.
            if (processGenerics && methodDef.HasGenericParameters)
            {
                if (!needsPostfix)
                {
                    postfix.Clear();
                    postfix.Append("$$");
                    postfix.Append(methodDef.GenericParameters.Count);
                }
                else
                {
                    postfix.Insert(2, methodDef.GenericParameters.Count + "$");
                }
                needsPostfix = true;
            }


            if (needsPostfix)
            {
                return postfix.ToString();
            }

            return string.Empty;
        }
Пример #23
0
        /// <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 numParams = method.Parameters.Count;
            if (method.HasThis)
                numParams++;
            var parameterTypes = new Type[numParams];
            var parameterTypesLLVM = new TypeRef[numParams];
            var declaringType = CreateType(ResolveGenericsVisitor.Process(method, method.DeclaringType));
            for (int index = 0; index < numParams; index++)
            {
                TypeReference parameterTypeReference;
                if (method.HasThis && index == 0)
                {
                    parameterTypeReference = declaringType.TypeReference;

                    // Value type uses ByReference type for this
                    if (parameterTypeReference.IsValueType)
                        parameterTypeReference = parameterTypeReference.MakeByReferenceType();
                }
                else
                {
                    var parameter = method.Parameters[method.HasThis ? index - 1 : index];
                    parameterTypeReference = ResolveGenericsVisitor.Process(method, parameter.ParameterType);
                }
                var parameterType = CreateType(parameterTypeReference);
                if (parameterType.DefaultType.Value == IntPtr.Zero)
                    throw new InvalidOperationException();
                parameterTypes[index] = parameterType;
                parameterTypesLLVM[index] = parameterType.DefaultType;
            }

            var returnType = CreateType(ResolveGenericsVisitor.Process(method, method.ReturnType));

            // Generate function global
            bool isExternal = method.DeclaringType.Resolve().Module.Assembly != assembly;
            var methodMangledName = Regex.Replace(method.FullName, @"(\W)", "_");
            var functionType = LLVM.FunctionType(returnType.DefaultType, parameterTypesLLVM, false);

            var resolvedMethod = method.Resolve();
            var hasDefinition = resolvedMethod != null
                && (resolvedMethod.HasBody
                    || ((resolvedMethod.ImplAttributes & (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime)) != 0));
            var functionGlobal = hasDefinition
                ? LLVM.AddFunction(module, methodMangledName, functionType)
                : LLVM.ConstPointerNull(LLVM.PointerType(functionType, 0));

            function = new Function(declaringType, method, functionType, functionGlobal, returnType, parameterTypes);
            functions.Add(method, function);

            if (hasDefinition)
            {
                if (isExternal)
                {
                    // External weak linkage
                    LLVM.SetLinkage(functionGlobal, Linkage.ExternalWeakLinkage);
                }
                else
                {
                    // Need to compile
                    EmitFunction(function);
                }
            }

            return function;
        }
Пример #24
0
        /// <summary>
        /// Compiles the given method definition.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <param name="function">The function.</param>
        /// <exception cref="System.NotSupportedException"></exception>
        /// <exception cref="System.NotImplementedException"></exception>
        /// <exception cref="System.InvalidOperationException">Backward jump with a non-empty stack unknown target.</exception>
        private void CompileFunction(MethodReference methodReference, Function function)
        {
            var method = methodReference.Resolve();

            var body = method.Body;
            var codeSize = body != null ? body.CodeSize : 0;
            var functionGlobal = function.GeneratedValue;

            var functionContext = new FunctionCompilerContext(function);
            functionContext.BasicBlock = LLVM.AppendBasicBlockInContext(context, functionGlobal, string.Empty);
            LLVM.PositionBuilderAtEnd(builder, functionContext.BasicBlock);

            if (body == null && (method.ImplAttributes & MethodImplAttributes.Runtime) != 0)
            {
                var declaringClass = GetClass(function.DeclaringType);

                // Generate IL for various methods
                if (declaringClass.BaseType != null &&
                    declaringClass.BaseType.Type.TypeReference.FullName == typeof(MulticastDelegate).FullName)
                {
                    body = GenerateDelegateMethod(method, declaringClass);
                    if (body == null)
                        return;

                    codeSize = UpdateOffsets(body);
                }
            }

            if (body == null)
                return;

            var numParams = method.Parameters.Count;

            // Create stack, locals and args
            var stack = new List<StackValue>(body.MaxStackSize);
            var locals = new List<StackValue>(body.Variables.Count);
            var args = new List<StackValue>(numParams);
            var exceptionHandlers = new List<ExceptionHandlerInfo>();
            var activeTryHandlers = new List<ExceptionHandlerInfo>();

            functionContext.Stack = stack;
            functionContext.Locals = locals;
            functionContext.Arguments = args;
            functionContext.ExceptionHandlers = exceptionHandlers;
            functionContext.ActiveTryHandlers = activeTryHandlers;

            // Process locals
            foreach (var local in body.Variables)
            {
                // TODO: Anything to do on pinned objects?
                //if (local.IsPinned)
                //    throw new NotSupportedException();

                var type = CreateType(ResolveGenericsVisitor.Process(methodReference, local.VariableType));
                locals.Add(new StackValue(type.StackType, type, LLVM.BuildAlloca(builder, type.DefaultType, local.Name)));
            }

            // Process args
            for (int index = 0; index < function.ParameterTypes.Length; index++)
            {
                var argType = function.ParameterTypes[index];
                var arg = LLVM.GetParam(functionGlobal, (uint)index);

                // Copy argument on stack
                var storage = LLVM.BuildAlloca(builder, argType.DefaultType, "arg" + index.ToString());
                LLVM.BuildStore(builder, arg, storage);

                args.Add(new StackValue(argType.StackType, argType, storage));
            }

            // Some wasted space due to unused offsets, but we only keep one so it should be fine.
            // TODO: Reuse same allocated instance per thread, and grow it only if necessary
            var branchTargets = new bool[codeSize];
            var basicBlocks = new BasicBlockRef[codeSize];
            var forwardStacks = new StackValue[codeSize][];

            functionContext.BasicBlocks = basicBlocks;
            functionContext.ForwardStacks = forwardStacks;

            // Find branch targets (which will require PHI node for stack merging)
            for (int index = 0; index < body.Instructions.Count; index++)
            {
                var instruction = body.Instructions[index];

                var flowControl = instruction.OpCode.FlowControl;

                // Process branch targets
                if (flowControl == FlowControl.Cond_Branch
                    || flowControl == FlowControl.Branch)
                {
                    var targets = instruction.Operand is Instruction[] ? (Instruction[])instruction.Operand : new[] { (Instruction)instruction.Operand };

                    foreach (var target in targets)
                    {
                        // Operand Target can be reached
                        branchTargets[target.Offset] = true;
                    }
                }

                // Need to enforce a block to be created for the next instruction after a conditional branch
                // TODO: Break?
                if (flowControl == FlowControl.Cond_Branch)
                {
                    if (instruction.Next != null)
                        branchTargets[instruction.Next.Offset] = true;
                }
            }

            // Setup exception handling
            if (body.HasExceptionHandlers)
            {
                // Add an "ehselector.slot" i32 local, and a "exn.slot" Object reference local
                functionContext.ExceptionHandlerSelectorSlot = LLVM.BuildAlloca(builder, int32Type, "ehselector.slot");
                functionContext.ExceptionSlot = LLVM.BuildAlloca(builder, @object.DefaultType, "exn.slot");
                functionContext.EndfinallyJumpTarget = LLVM.BuildAlloca(builder, int32Type, "endfinally.jumptarget");

                // Create resume exception block
                functionContext.ResumeExceptionBlock = LLVM.AppendBasicBlockInContext(context, functionGlobal, "eh.resume");
                LLVM.PositionBuilderAtEnd(builder2, functionContext.ResumeExceptionBlock);
                var exceptionObject = LLVM.BuildLoad(builder2, functionContext.ExceptionSlot, "exn");
                var ehselectorValue = LLVM.BuildLoad(builder2, functionContext.ExceptionHandlerSelectorSlot, "sel");

                exceptionObject = LLVM.BuildPointerCast(builder2, exceptionObject, intPtrType, "exn");
                var landingPadValue = LLVM.BuildInsertValue(builder2, LLVM.GetUndef(caughtResultType), exceptionObject, 0, "lpad.val");
                landingPadValue = LLVM.BuildInsertValue(builder2, landingPadValue, ehselectorValue, 1, "lpad.val");

                LLVM.BuildResume(builder2, landingPadValue);

                // Exception handlers blocks are also branch targets
                foreach (var exceptionHandler in body.ExceptionHandlers)
                {
                    branchTargets[exceptionHandler.HandlerStart.Offset] = true;
                }
            }

            // Create basic block
            // TODO: Could be done during previous pass
            for (int offset = 0; offset < branchTargets.Length; offset++)
            {
                // Create a basic block if this was a branch target or an instruction after a conditional branch
                if (branchTargets[offset])
                {
                    basicBlocks[offset] = LLVM.AppendBasicBlockInContext(context, functionGlobal, string.Format("L_{0:x4}", offset));
                }
            }

            // Create catch clause stack
            if (body.HasExceptionHandlers)
            {
                // Exception handlers blocks are also branch targets
                foreach (var exceptionHandler in body.ExceptionHandlers)
                {
                    exceptionHandlers.Add(new ExceptionHandlerInfo(exceptionHandler));

                    if (exceptionHandler.HandlerType != ExceptionHandlerType.Catch)
                        continue;

                    var handlerStart = exceptionHandler.HandlerStart.Offset;

                    var catchBlock = basicBlocks[handlerStart];
                    var catchClass = GetClass(ResolveGenericsVisitor.Process(methodReference, exceptionHandler.CatchType));

                    // Extract exception
                    LLVM.PositionBuilderAtEnd(builder2, catchBlock);
                    var exceptionObject = LLVM.BuildLoad(builder2, functionContext.ExceptionSlot, string.Empty);
                    exceptionObject = LLVM.BuildPointerCast(builder2, exceptionObject, catchClass.Type.DefaultType, string.Empty);

                    // Erase exception from exn.slot (it has been handled)
                    LLVM.BuildStore(builder2, LLVM.ConstNull(@object.DefaultType), functionContext.ExceptionSlot);
                    LLVM.BuildStore(builder2, LLVM.ConstInt(int32Type, 0, false), functionContext.ExceptionHandlerSelectorSlot);
                     
                    forwardStacks[handlerStart] = new[]
                    {
                        new StackValue(catchClass.Type.StackType, catchClass.Type, exceptionObject)
                    };
                }
            }

            foreach (var instruction in body.Instructions)
            {
                try
                {
                    // Check if any exception handlers might have changed
                    if (body.HasExceptionHandlers)
                        UpdateExceptionHandlers(functionContext, instruction);

                    if (branchTargets[instruction.Offset])
                        UpdateBranching(functionContext, instruction);

                    // Reset states
                    functionContext.FlowingNextInstructionMode = FlowingNextInstructionMode.Implicit;

                    EmitInstruction(functionContext, instruction);

                    // If we do a jump, let's merge stack
                    var flowControl = instruction.OpCode.FlowControl;
                    if (flowControl == FlowControl.Cond_Branch
                        || flowControl == FlowControl.Branch)
                        MergeStacks(functionContext, instruction);
                }
                catch (Exception e)
                {
                    throw new InvalidOperationException(string.Format("Error while processing instruction {0} of method {1}", instruction, methodReference), e);
                }
            }
        }
Пример #25
0
		static MethodDefinition GetMethodDefinition(MethodReference method)
		{
				if (method != null && method.DeclaringType.IsGenericInstance)
				return method.Resolve();
			else
				return method as MethodDefinition;
		}
Пример #26
0
 public void Add(Mono.Cecil.MethodReference reference)
 {
     Add(reference.Resolve());
 }
        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;
        }
        protected virtual string GetMethodName(MethodReference method)
        {
            MethodDefinition methodDefinition = method.Resolve();

            if (methodDefinition != null && methodDefinition.Module.FilePath == this.ModuleContext.Module.FilePath)
            {
                if (this.TypeContext.MethodDefinitionToNameMap.ContainsKey(methodDefinition))
                {
                    return this.TypeContext.MethodDefinitionToNameMap[methodDefinition];
                }

                if (this.TypeContext.GeneratedMethodDefinitionToNameMap.ContainsKey(methodDefinition))
                {
                    return this.TypeContext.GeneratedMethodDefinitionToNameMap[methodDefinition];
                }

                return this.ModuleContext.RenamedMembersMap[methodDefinition.MetadataToken.ToUInt32()];
            }

            return Utilities.EscapeName(GenericHelper.GetNonGenericName(method.Name), this.Language);
        }
Пример #29
0
        //static public MethodReference HHH(this MethodDefinition @this, Dictionary<TypeReference, TypeReference> genericity, MethodReference met)
        //{
        //    if (met is GenericInstanceMethod)
        //    {
        //        if (met.DeclaringType is GenericInstanceType)
        //        {
        //            //var mmm = new MethodReference(met.Name, @this.HHH(genericity, met.ReturnType), @this.HHH(genericity, met.DeclaringType))
        //            //{
        //            //    HasThis = met.HasThis,
        //            //    ExplicitThis = met.ExplicitThis,
        //            //    CallingConvention = met.CallingConvention
        //            //};
        //            //foreach (var parameter in met.Parameters)
        //            //{
        //            //    mmm.Parameters.Add(new ParameterDefinition(@this.HHH(genericity, parameter.ParameterType)));
        //            //}

        //            //foreach (var generic_parameter in met.GenericParameters)
        //            //{
        //            //    mmm.GenericParameters.Add(new GenericParameter(generic_parameter.Name, mmm));
        //            //}
        //            ////var hhhh = new GenericInstanceMethod(mmm);
        //            ////hhhh.
        //            //return mmm.MakeGenericMethod((met as GenericInstanceMethod).GenericArguments.Select(_Type => @this.HHH(genericity, _Type)).ToArray());
        //            //return mmm.MakeGenericMethod((met as GenericInstanceMethod).GenericArguments.Select(_Type => @this.HHH(genericity, _Type)).ToArray());


        //            return @this.Module.Import(@this.Module.Import(met.Resolve())

        //            .MakeGenericMethod((met as GenericInstanceMethod).GenericArguments.Select(_Type => @this.HHH(genericity, _Type)).ToArray())
        //            .MakeHostInstanceGeneric((@this.HHH(genericity, met.DeclaringType) as GenericInstanceType).GenericArguments.ToArray()));

        //            ////var ggg = new GenericInstanceMethod(@this.Module.Import(met.Resolve()));
        //            //ggg.DeclaringType = @this.HHH(genericity, met.DeclaringType);
        //            //ggg.Parameters.Clear();
        //            //foreach (var _parameter in met.Parameters) { ggg.Parameters.Add(new ParameterDefinition(_parameter.Name, _parameter.Attributes, /*@this.HHH(genericity, */_parameter.ParameterType/*)*/)); }
        //            //foreach (var _type in (met as GenericInstanceMethod).GenericArguments) { ggg.GenericArguments.Add(@this.HHH(genericity, _type)); }

        //            //var m = @this.Module.Import(@this.Module.Import(met.Resolve()).MakeHostInstanceGeneric((@this.HHH(genericity, met.DeclaringType) as GenericInstanceType).GenericArguments.Select(_Type => @this.HHH(genericity, _Type)).ToArray()).MakeGenericMethod((met as GenericInstanceMethod).GenericArguments.Select(ppp => @this.HHH(genericity, ppp)).Select(_Type => @this.HHH(genericity, _Type)).ToArray()));
        //            //return met;
        //            //return ggg;
        //        }
        //        else
        //        {
        //            var m =  @this.Module.Import(@this.Module.Import(met.Resolve()).MakeGenericMethod((met as GenericInstanceMethod).GenericArguments.Select(ppp => @this.HHH(genericity, ppp)).ToArray()));
        //            return m;
        //        }
        //    }
        //    else
        //    {
        //        if (met.DeclaringType is GenericInstanceType)
        //        {
        //            var m = @this.Module.Import(met.Resolve()).MakeHostInstanceGeneric((@this.HHH(genericity, met.DeclaringType) as GenericInstanceType).GenericArguments.Select(_Type =>
        //            {
        //                var hhhhhhh = met;
        //                return @this.HHH(genericity, _Type);
        //            }).ToArray());
        //            return m;
        //        }
        //        else
        //        {
        //            return met;
        //        }
        //    }
        //}

        //static public TypeReference HHH(this MethodDefinition @this, Dictionary<TypeReference, TypeReference> genericity, TypeReference type)
        //{
        //    if (type.IsByReference/* || type.Name.EndsWith("&")*/) { return new ByReferenceType(@this.HHH(genericity, (type as ByReferenceType).ElementType)); }
        //    if (genericity.TryGetValue(type, out var _type)) { return _type; }
        //    //var _genericity = @this.DeclaringType.GenericParameters.Concat(@this.GenericParameters).ToArray();
        //    //if (type.Name.StartsWith("!!")) { return _genericity[int.Parse(type.Name.Substring(2)) + @this.DeclaringType.DeclaringType.GenericParameters.Count]; }
        //    //if (type.Name.StartsWith("!")) { return _genericity[int.Parse(type.Name.Substring(1))]; }
        //    if (type is GenericInstanceType) { return @this.Module.Import(type.Resolve()).MakeGenericType((type as GenericInstanceType).GenericArguments.Select(_Type => @this.HHH(genericity, _Type))); }
        //    return type;
        //}

        static public MethodReference Repair(this MethodReference that, MethodReference method)
        {
            var _types = that.GenericParameterTypes().Select(_Type => _Type.Name.StartsWith("!!") ? that.GenericParameters[int.Parse(_Type.Name.Substring(2))] : (_Type.Name.StartsWith("!") ? that.DeclaringType.GenericParameters[int.Parse(_Type.Name.Substring(1))] : _Type)).ToArray();

            if (_types.Length > 0)
            {
                if (method.GenericParameters.Count > 0) //TODO test it!
                {
                    var dec = that.GetRealType(method.DeclaringType);
                    if (dec is GenericInstanceType)
                    {
                        var _method = that.Module.Import(method.Resolve()).MakeHostInstanceGeneric((dec as GenericInstanceType).GenericArguments.ToArray());
                        //var _method = new MethodReference(method.Name, that.GetRealType(method.ReturnType), that.GetRealType(method.DeclaringType));
                        //foreach (var _parameter in method.Parameters) { _method.Parameters.Add(new ParameterDefinition(_parameter.Name, _parameter.Attributes, that.GetRealType(_parameter.ParameterType))); }
                        return(_method.MakeGenericMethod(method.GenericParameters.Select(k => k.Name.StartsWith("!!") ? that.GenericParameters[int.Parse(k.Name.Substring(2))] : (k.Name.StartsWith("!") ? that.DeclaringType.GenericParameters[int.Parse(k.Name.Substring(1))] : k)).ToArray()));
                    }
                    else
                    {
                        return(method.MakeGenericMethod(method.GenericParameters.Select(k => k.Name.StartsWith("!!") ? that.GenericParameters[int.Parse(k.Name.Substring(2))] : (k.Name.StartsWith("!") ? that.DeclaringType.GenericParameters[int.Parse(k.Name.Substring(1))] : k)).ToArray()));
                    }
                }
                else if (method is GenericInstanceMethod)
                {
                    var dec = that.GetRealType(method.DeclaringType);
                    if (dec is GenericInstanceType)
                    {
                        var _method = that.Module.Import(method.Resolve()).MakeHostInstanceGeneric((dec as GenericInstanceType).GenericArguments.ToArray());
                        //var _method = new MethodReference(method.Name, that.GetRealType(method.ReturnType), that.GetRealType(method.DeclaringType));
                        //foreach (var _parameter in method.Parameters) { _method.Parameters.Add(new ParameterDefinition(_parameter.Name, _parameter.Attributes, that.GetRealType(_parameter.ParameterType))); }
                        return(_method.MakeGenericMethod((method as GenericInstanceMethod).GenericArguments.Select(k => k.Name.StartsWith("!!") ? that.GenericParameters[int.Parse(k.Name.Substring(2))] : (k.Name.StartsWith("!") ? that.DeclaringType.GenericParameters[int.Parse(k.Name.Substring(1))] : k)).ToArray()));
                    }
                    else
                    {
                        return(method.MakeGenericMethod((method as GenericInstanceMethod).GenericArguments.Select(k => k.Name.StartsWith("!!") ? that.GenericParameters[int.Parse(k.Name.Substring(2))] : (k.Name.StartsWith("!") ? that.DeclaringType.GenericParameters[int.Parse(k.Name.Substring(1))] : k)).ToArray()));
                    }
                }
                else
                {
                    var dec = that.GetRealType(method.DeclaringType);
                    if (dec is GenericInstanceType)
                    {
                        var _method = that.Module.Import(method.Resolve()).MakeHostInstanceGeneric((dec as GenericInstanceType).GenericArguments.ToArray());
                        //var _method = new MethodReference(method.Name, that.GetRealType(method.ReturnType), that.GetRealType(method.DeclaringType));
                        //foreach (var _parameter in method.Parameters) { _method.Parameters.Add(new ParameterDefinition(_parameter.Name, _parameter.Attributes, that.GetRealType(_parameter.ParameterType))); }
                        return(_method);
                    }
                    else
                    {
                        return(method);
                    }
                }
            }
            //var met = method.Resolve();
            //if (met.GenericParameters.Count > 0)
            //{
            //    var kk = method.Module.Import(met).MakeGenericMethod(_types.Reverse().Take(met.GenericParameters.Count).Reverse().ToArray());
            //    if (met.DeclaringType.GenericParameters.Count > 0) { kk.DeclaringType = met.DeclaringType.MakeGenericType(_types.Take(met.DeclaringType.GenericParameters.Count)); }
            //    return kk;
            //}
            //if (met.DeclaringType.GenericParameters.Count > 0)
            //{
            //    var kk = method.Module.Import(met);
            //    kk.DeclaringType = met.DeclaringType.MakeGenericType(_types.Take(met.DeclaringType.GenericParameters.Count));
            //    return kk;
            //}
            return(method);
        }
		private bool IsPure (MethodReference mr)
		{
			MethodDefinition method = mr.Resolve ();
			
			if (method != null) {
				TypeDefinition type = method.DeclaringType;
				string type_name = type.GetFullName ();
				string method_name = method.Name;

				// getters
				if (method.IsGetter)
					return true;
				
				// System.String, System.Type, etc methods
				if (types_considered_pure.Contains (type_name))
					return true;
				
				// Equals, GetHashCode, Contains, etc
				if (methods_considered_pure.Contains (method_name))
					return true;
				
				// operators
				if (method_name.StartsWith ("op_", StringComparison.Ordinal) && method_name != "op_Implicit" && method_name != "op_Explicit")
					return true;
					
				// Contract methods (skip namespace)
				if (type_name == "System.Diagnostics.Contracts.Contract")
					return true;
					
				// System.Predicate<T> and System.Comparison<T>
				if (type_name.StartsWith ("System.Predicate`1", StringComparison.Ordinal))
					return true;
					
				if (type_name.StartsWith ("System.Comparison`1", StringComparison.Ordinal))
					return true;
					
				// delegate invocation
				if (MethodSignatures.Invoke.Matches (method)) {
					if (type.HasCustomAttributes) {
						if (HasPureAttribute (type.CustomAttributes)) {
							return true;
						}
					}
				}
				
				// PureAttribute
				if (method.HasCustomAttributes) {
					if (HasPureAttribute (method.CustomAttributes)) {
						return true;
					}
				}
				
				return false;
			}
			
			// If we can't resolve the method we have to assume it's OK to call.
			Log.WriteLine (this, "couldn't resolve {0} call: assuming it is pure", mr);
			return true;
		}
 protected bool ShouldChangeToCallVirt(MethodReference method)
 {
     return
     method.DeclaringType.Resolve() == _sourceType &&
     method.Resolve().RemainsInRoleInterface();
 }
Пример #32
0
		MethodDefinition ResolveMethodDefinition (MethodReference method)
		{
			MethodDefinition md = method as MethodDefinition;
			if (md == null)
				md = method.Resolve ();

			return md;
		}
Пример #33
0
        private void ExtractBasicBlocksOfMethod(MethodDefinition definition)
        {
            _done.Add(definition);
            // Make sure definition assembly is loaded.
            String full_name = definition.Module.FullyQualifiedName;

            LoadAssembly(full_name);
            if (definition.Body == null)
            {
                System.Console.WriteLine("WARNING: METHOD BODY NULL! " + definition);
                return;
            }
            int instruction_count = definition.Body.Instructions.Count;
            StackQueue <Mono.Cecil.Cil.Instruction> leader_list = new StackQueue <Mono.Cecil.Cil.Instruction>();

            // Each method is a leader of a block.
            CFGVertex v = (CFGVertex)this.AddVertex(_node_number++);

            v.Method         = definition;
            v.HasReturnValue = definition.IsReuseSlot;
            v._entry         = v;
            this._entries.Add(v);
            v._ordered_list_of_blocks = new List <CFGVertex>();
            v._ordered_list_of_blocks.Add(v);
            for (int j = 0; j < instruction_count; ++j)
            {
                // accumulate jump to locations since these split blocks.
                Mono.Cecil.Cil.Instruction mi = definition.Body.Instructions[j];
                //System.Console.WriteLine(mi);
                Inst i = Inst.Wrap(mi, this);
                Mono.Cecil.Cil.OpCode      op = i.OpCode;
                Mono.Cecil.Cil.FlowControl fc = op.FlowControl;

                v._instructions.Add(i);

                // Verify that mi not owned already.
                CFG.CFGVertex asdfasdf;
                Debug.Assert(!partition_of_instructions.TryGetValue(mi, out asdfasdf));
                // Update ownership.
                partition_of_instructions.Add(mi, v);

                if (fc == Mono.Cecil.Cil.FlowControl.Next)
                {
                    continue;
                }
                if (fc == Mono.Cecil.Cil.FlowControl.Branch ||
                    fc == Mono.Cecil.Cil.FlowControl.Cond_Branch)
                {
                    // Save leader target of branch.
                    object o = i.Operand;
                    // Two cases that I know of: operand is just and instruction,
                    // or operand is an array of instructions (via a switch instruction).

                    Mono.Cecil.Cil.Instruction   oo  = o as Mono.Cecil.Cil.Instruction;
                    Mono.Cecil.Cil.Instruction[] ooa = o as Mono.Cecil.Cil.Instruction[];
                    if (oo != null)
                    {
                        leader_list.Push(oo);
                    }
                    else if (ooa != null)
                    {
                        foreach (Mono.Cecil.Cil.Instruction ins in ooa)
                        {
                            Debug.Assert(ins != null);
                            leader_list.Push(ins);
                        }
                    }
                    else
                    {
                        throw new Exception("Unknown operand type for basic block partitioning.");
                    }
                }
            }
            StackQueue <int> ordered_leader_list = new StackQueue <int>();

            for (int j = 0; j < instruction_count; ++j)
            {
                // Order jump targets. These denote locations
                // where to split blocks. However, it's ordered,
                // so that splitting is done from last instruction in block
                // to first instruction in block.
                Mono.Cecil.Cil.Instruction i = definition.Body.Instructions[j];
                //System.Console.WriteLine("Looking for " + i);
                if (leader_list.Contains(i))
                {
                    ordered_leader_list.Push(j);
                }
            }
            // Split block at jump targets in reverse.
            while (ordered_leader_list.Count > 0)
            {
                int           i        = ordered_leader_list.Pop();
                CFG.CFGVertex new_node = v.Split(i);
            }

            //this.Dump();

            StackQueue <CFG.CFGVertex> stack = new StackQueue <CFG.CFGVertex>();

            foreach (CFG.CFGVertex node in this.VertexNodes)
            {
                stack.Push(node);
            }
            while (stack.Count > 0)
            {
                // Split blocks at branches, not including calls, with following
                // instruction a leader of new block.
                CFG.CFGVertex node = stack.Pop();
                int           node_instruction_count = node._instructions.Count;
                for (int j = 0; j < node_instruction_count; ++j)
                {
                    Inst i = node._instructions[j];
                    Mono.Cecil.Cil.OpCode      op = i.OpCode;
                    Mono.Cecil.Cil.FlowControl fc = op.FlowControl;
                    if (fc == Mono.Cecil.Cil.FlowControl.Next)
                    {
                        continue;
                    }
                    if (fc == Mono.Cecil.Cil.FlowControl.Call)
                    {
                        continue;
                    }
                    if (fc == Mono.Cecil.Cil.FlowControl.Meta)
                    {
                        continue;
                    }
                    if (fc == Mono.Cecil.Cil.FlowControl.Phi)
                    {
                        continue;
                    }
                    if (j + 1 >= node_instruction_count)
                    {
                        continue;
                    }
                    CFG.CFGVertex new_node = node.Split(j + 1);
                    stack.Push(new_node);
                    break;
                }
            }

            //this.Dump();
            stack = new StackQueue <CFG.CFGVertex>();
            foreach (CFG.CFGVertex node in this.VertexNodes)
            {
                stack.Push(node);
            }
            while (stack.Count > 0)
            {
                // Add in all final non-fallthrough branch edges.
                CFG.CFGVertex              node = stack.Pop();
                int                        node_instruction_count = node._instructions.Count;
                Inst                       i  = node._instructions[node_instruction_count - 1];
                Mono.Cecil.Cil.OpCode      op = i.OpCode;
                Mono.Cecil.Cil.FlowControl fc = op.FlowControl;
                switch (fc)
                {
                case Mono.Cecil.Cil.FlowControl.Branch:
                case Mono.Cecil.Cil.FlowControl.Cond_Branch:
                {
                    // Two cases: i.Operand is a single instruction, or an array of instructions.
                    if (i.Operand as Mono.Cecil.Cil.Instruction != null)
                    {
                        Mono.Cecil.Cil.Instruction target_instruction = i.Operand as Mono.Cecil.Cil.Instruction;
                        CFGVertex target_node = this.VertexNodes.First(
                            (CFGVertex x) =>
                            {
                                if (!x._instructions.First().Instruction.Equals(target_instruction))
                                {
                                    return(false);
                                }
                                return(true);
                            });
                        if (Options.Singleton.Get(Options.OptionType.DisplaySSAComputation))
                        {
                            System.Console.WriteLine("Create edge a " + node.Name + " to " + target_node.Name);
                        }
                        this.AddEdge(node, target_node);
                    }
                    else if (i.Operand as Mono.Cecil.Cil.Instruction[] != null)
                    {
                        foreach (Mono.Cecil.Cil.Instruction target_instruction in (i.Operand as Mono.Cecil.Cil.Instruction[]))
                        {
                            CFGVertex target_node = this.VertexNodes.First(
                                (CFGVertex x) =>
                                {
                                    if (!x._instructions.First().Instruction.Equals(target_instruction))
                                    {
                                        return(false);
                                    }
                                    return(true);
                                });
                            System.Console.WriteLine("Create edge a " + node.Name + " to " + target_node.Name);
                            this.AddEdge(node, target_node);
                        }
                    }
                    else
                    {
                        throw new Exception("Unknown operand type for conditional branch.");
                    }
                    break;
                }

                case Mono.Cecil.Cil.FlowControl.Break:
                    break;

                case Mono.Cecil.Cil.FlowControl.Call:
                {
                    // We no longer split at calls. Splitting causes
                    // problems because interprocedural edges are
                    // produced. That's not good because it makes
                    // code too "messy".
                    break;

                    object o = i.Operand;
                    if (o as Mono.Cecil.MethodReference != null)
                    {
                        Mono.Cecil.MethodReference  r = o as Mono.Cecil.MethodReference;
                        Mono.Cecil.MethodDefinition d = r.Resolve();
                        IEnumerable <CFGVertex>     target_node_list = this.VertexNodes.Where(
                            (CFGVertex x) =>
                            {
                                return(x.Method.FullName == r.FullName &&
                                       x._entry == x);
                            });
                        int c = target_node_list.Count();
                        if (c >= 1)
                        {
                            // target_node is the entry for a method. Also get the exit.
                            CFGVertex target_node = target_node_list.First();
                            CFGVertex exit_node   = target_node.Exit;
                            // check if this is a recursive call. DO NOT BOTHER!!
                            if (node.Method == target_node.Method)
                            {
                            }
                            else
                            {
                                // Create edges from exit to successor blocks of the call.
                                foreach (CFGEdge e in node._Successors)
                                {
                                    System.Console.WriteLine("Create edge c " + exit_node.Name + " to " + e.to.Name);
                                    this._interprocedure_graph.AddEdge(exit_node, e.to);
                                }
                                // Create edge from node to method entry.
                                System.Console.WriteLine("Create edge b " + node.Name + " to " + target_node.Name);
                                this._interprocedure_graph.AddEdge(node, target_node);
                            }
                        }
                    }
                    break;
                }

                case Mono.Cecil.Cil.FlowControl.Meta:
                    break;

                case Mono.Cecil.Cil.FlowControl.Next:
                    break;

                case Mono.Cecil.Cil.FlowControl.Phi:
                    break;

                case Mono.Cecil.Cil.FlowControl.Return:
                    break;

                case Mono.Cecil.Cil.FlowControl.Throw:
                    break;
                }
            }

            //this.Dump();
        }