Beispiel #1
0
        /// <summary>
        /// Returns pregenerated interop code for given PInvoke method if one exist
        /// </summary>
        public static MethodDesc TryGetPregeneratedPInvoke(MethodDesc method)
        {
            Debug.Assert(method.IsPInvoke);

            var metadataType = (MetadataType)method.OwningType;
            var module = metadataType.Module;

            var assemblyName = ((IAssemblyDesc)module).GetName();

            var interopAssemblyName = new AssemblyName();

            interopAssemblyName.Name = assemblyName.Name + AssemblyNameSuffix;
            interopAssemblyName.Version = assemblyName.Version;
            interopAssemblyName.SetPublicKeyToken(interopAssemblyName.GetPublicKeyToken());
            interopAssemblyName.CultureName = assemblyName.CultureName;
            interopAssemblyName.ContentType = assemblyName.ContentType;

            var interopModule = module.Context.ResolveAssembly(interopAssemblyName, false);
            if (interopModule == null)
                return null;

            var pregeneratedMethod = GetMatchingMethod(interopModule, method);
            if (pregeneratedMethod == null)
            {
                // TODO: Better error message
                throw new MissingMemberException("Missing method in " + interopAssemblyName.Name + ":" + method.ToString());
            }
            return pregeneratedMethod;
        }
        private List <CustomAttribute> HandleCustomAttributes(Cts.Ecma.EcmaModule module, Ecma.CustomAttributeHandleCollection attributes)
        {
            List <CustomAttribute> customAttributes = new List <CustomAttribute>(attributes.Count);

            var attributeTypeProvider = new Cts.Ecma.CustomAttributeTypeProvider(module);

            Ecma.MetadataReader reader = module.MetadataReader;

            foreach (var attributeHandle in attributes)
            {
                if (!_policy.GeneratesMetadata(module, attributeHandle))
                {
                    continue;
                }

                Ecma.CustomAttribute attribute = reader.GetCustomAttribute(attributeHandle);

                // TODO-NICE: We can intern the attributes based on the CA constructor and blob bytes

                Cts.MethodDesc constructor  = module.GetMethod(attribute.Constructor);
                var            decodedValue = attribute.DecodeValue(attributeTypeProvider);

                customAttributes.Add(HandleCustomAttribute(constructor, decodedValue));
            }

            return(customAttributes);
        }
        public override bool IsMethodInCompilationGroup(MethodDesc method)
        {
            if (method.GetTypicalMethodDefinition().ContainsGenericVariables)
                return true;

            return IsTypeInCompilationGroup(method.OwningType);
        }
Beispiel #4
0
        public static MethodIL EmitIL(MethodDesc target)
        {
            Debug.Assert(target.Name == "Call");
            Debug.Assert(target.Signature.Length > 0
                && target.Signature[0] == target.Context.GetWellKnownType(WellKnownType.IntPtr));

            ILEmitter emitter = new ILEmitter();
            var codeStream = emitter.NewCodeStream();

            // Load all the arguments except the first one (IntPtr address)
            for (int i = 1; i < target.Signature.Length; i++)
            {
                codeStream.EmitLdArg(i);
            }

            // now load IntPtr address
            codeStream.EmitLdArg(0);

            // Create a signature for the calli by copying the signature of the containing method
            // while skipping the first argument
            MethodSignature template = target.Signature;
            TypeDesc returnType = template.ReturnType;
            TypeDesc[] parameters = new TypeDesc[template.Length - 1];
            for (int i = 1; i < template.Length; i++)
            {
                parameters[i - 1] = template[i];
            }

            var signature = new MethodSignature(template.Flags, 0, returnType, parameters);

            codeStream.Emit(ILOpcode.calli, emitter.NewToken(signature));
            codeStream.Emit(ILOpcode.ret);

            return emitter.Link();
        }
Beispiel #5
0
        /// <summary>
        /// Returns true if <paramref name="method"/> requires a stub to be generated.
        /// </summary>
        public static bool IsStubRequired(MethodDesc method)
        {
            Debug.Assert(method.IsPInvoke);

            // TODO: true if there are any custom marshalling rules on the parameters
            // TODO: true if SetLastError is true

            TypeDesc returnType = method.Signature.ReturnType;
            if (!IsBlittableType(returnType) && !returnType.IsVoid)
                return true;

            for (int i = 0; i < method.Signature.Length; i++)
            {
                if (!IsBlittableType(method.Signature[i]))
                {
                    return true;
                }
            }

            if (UseLazyResolution(method, method.GetPInvokeMethodMetadata().Module))
            {
                return true;
            }

            return false;
        }
        public override bool ContainsMethod(MethodDesc method)
        {
            if (method.GetTypicalMethodDefinition().ContainsGenericVariables)
                return true;

            return ContainsType(method.OwningType);
        }
Beispiel #7
0
        private void InitializeMethods()
        {
            int numCtors;

            if (IsSzArray)
            {
                numCtors = 1;

                var t = this.ElementType;
                while (t.IsSzArray)
                {
                    t = ((ArrayType)t).ElementType;
                    numCtors++;
                }
            }
            else
            {
                // ELEMENT_TYPE_ARRAY has two ctor functions, one with and one without lower bounds
                numCtors = 2;
            }

            MethodDesc[] methods = new MethodDesc[(int)ArrayMethodKind.Ctor + numCtors];

            for (int i = 0; i < methods.Length; i++)
                methods[i] = new ArrayMethod(this, (ArrayMethodKind)i);

            Interlocked.CompareExchange(ref _methods, methods, null);
        }
Beispiel #8
0
        /// <summary>
        /// Returns method as defined on a non-generic base class or on a base
        /// instantiation.
        /// For example, If Foo&lt;T&gt; : Bar&lt;T&gt; and overrides method M,
        /// if method is Bar&lt;string&gt;.M(), then this returns Bar&lt;T&gt;.M()
        /// but if Foo : Bar&lt;string&gt;, then this returns Bar&lt;string&gt;.M()
        /// </summary>
        /// <param name="typeExamine">A potentially derived type</param>
        /// <param name="method">A base class's virtual method</param>
        static public MethodDesc FindMethodOnTypeWithMatchingTypicalMethod(this TypeDesc targetType, MethodDesc method)
        {
            // If method is nongeneric and on a nongeneric type, then it is the matching method
            if (!method.HasInstantiation && !method.OwningType.HasInstantiation)
            {
                return method;
            }

            // Since method is an instantiation that may or may not be the same as typeExamine's hierarchy,
            // find a matching base class on an open type and then work from the instantiation in typeExamine's
            // hierarchy
            TypeDesc typicalTypeOfTargetMethod = method.GetTypicalMethodDefinition().OwningType;
            TypeDesc targetOrBase = targetType;
            do
            {
                TypeDesc openTargetOrBase = targetOrBase;
                if (openTargetOrBase is InstantiatedType)
                {
                    openTargetOrBase = openTargetOrBase.GetTypeDefinition();
                }
                if (openTargetOrBase == typicalTypeOfTargetMethod)
                {
                    // Found an open match. Now find an equivalent method on the original target typeOrBase
                    MethodDesc matchingMethod = targetOrBase.FindMethodOnExactTypeWithMatchingTypicalMethod(method);
                    return matchingMethod;
                }
                targetOrBase = targetOrBase.BaseType;
            } while (targetOrBase != null);

            Debug.Assert(false, "method has no related type in the type hierarchy of type");
            return null;
        }
        public static MethodIL EmitIL(MethodDesc target)
        {
            Debug.Assert(target.Name == "EETypePtrOf");
            Debug.Assert(target.Signature.Length == 0
                && target.Signature.ReturnType == target.OwningType);
            Debug.Assert(target.Instantiation.Length == 1);

            ILEmitter emitter = new ILEmitter();
            var codeStream = emitter.NewCodeStream();

            TypeSystemContext context = target.Context;
            TypeDesc runtimeTypeHandleType = context.GetWellKnownType(WellKnownType.RuntimeTypeHandle);
            MethodDesc getValueInternalMethod = runtimeTypeHandleType.GetKnownMethod("GetValueInternal", null);
            MethodDesc eetypePtrCtorMethod = context.SystemModule
                .GetKnownType("System", "EETypePtr")
                .GetKnownMethod(".ctor", new MethodSignature(0, 0, context.GetWellKnownType(WellKnownType.Void),
                new TypeDesc[] { context.GetWellKnownType(WellKnownType.IntPtr) }));

            // The sequence of these instructions is important. JIT is able to optimize out
            // the LDTOKEN+GetValueInternal call into "load EEType pointer onto the evaluation stack".
            codeStream.Emit(ILOpcode.ldtoken, emitter.NewToken(context.GetSignatureVariable(0, true)));
            codeStream.Emit(ILOpcode.call, emitter.NewToken(getValueInternalMethod));
            codeStream.Emit(ILOpcode.newobj, emitter.NewToken(eetypePtrCtorMethod));
            codeStream.Emit(ILOpcode.ret);

            return emitter.Link(target);
        }
        public sealed override bool ContainsMethod(MethodDesc method)
        {
            if (method.HasInstantiation)
                return true;

            return ContainsType(method.OwningType);
        }
 public FixupCellMetadataResolver(NativeFormatMetadataUnit metadataUnit, MethodDesc methodContext)
 {
     _metadataUnit = metadataUnit;
     _methodContext = methodContext;
     _typeContext = methodContext.OwningType;
     _loadContextFromNativeLayout = null;
 }
        /// <summary>
        /// Constructs a new instance of <see cref="DelegateCreationInfo"/> set up to construct a delegate of type
        /// '<paramref name="delegateType"/>' pointing to '<paramref name="targetMethod"/>'.
        /// </summary>
        public static DelegateCreationInfo Create(TypeDesc delegateType, MethodDesc targetMethod, NodeFactory factory)
        {
            var context = (CompilerTypeSystemContext)delegateType.Context;
            var systemDelegate = targetMethod.Context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType;

            int paramCountTargetMethod = targetMethod.Signature.Length;
            if (!targetMethod.Signature.IsStatic)
            {
                paramCountTargetMethod++;
            }

            DelegateInfo delegateInfo = context.GetDelegateInfo(delegateType.GetTypeDefinition());
            int paramCountDelegateClosed = delegateInfo.Signature.Length + 1;
            bool closed = false;
            if (paramCountDelegateClosed == paramCountTargetMethod)
            {
                closed = true;
            }
            else
            {
                Debug.Assert(paramCountDelegateClosed == paramCountTargetMethod + 1);
            }

            if (targetMethod.Signature.IsStatic)
            {
                MethodDesc invokeThunk;
                if (!closed)
                {
                    // Open delegate to a static method
                    invokeThunk = delegateInfo.Thunks[DelegateThunkKind.OpenStaticThunk];
                }
                else
                {
                    // Closed delegate to a static method (i.e. delegate to an extension method that locks the first parameter)
                    invokeThunk = delegateInfo.Thunks[DelegateThunkKind.ClosedStaticThunk];
                }

                var instantiatedDelegateType = delegateType as InstantiatedType;
                if (instantiatedDelegateType != null)
                    invokeThunk = context.GetMethodForInstantiatedType(invokeThunk, instantiatedDelegateType);

                // We use InitializeClosedStaticThunk for both because RyuJIT generates same code for both,
                // but passes null as the first parameter for the open one.
                return new DelegateCreationInfo(
                    factory.MethodEntrypoint(systemDelegate.GetKnownMethod("InitializeClosedStaticThunk", null)),
                    factory.MethodEntrypoint(targetMethod),
                    factory.MethodEntrypoint(invokeThunk));
            }
            else
            {
                if (!closed)
                    throw new NotImplementedException("Open instance delegates");

                bool useUnboxingStub = targetMethod.OwningType.IsValueType;

                return new DelegateCreationInfo(
                    factory.MethodEntrypoint(systemDelegate.GetKnownMethod("InitializeClosedInstance", null)),
                    factory.MethodEntrypoint(targetMethod, useUnboxingStub));
            }
        }
Beispiel #13
0
        private bool IsBlockedCustomAttribute(Cts.MethodDesc constructor, Ecma.CustomAttributeValue <Cts.TypeDesc> decodedValue)
        {
            if (IsBlocked(constructor.OwningType))
            {
                return(true);
            }

            foreach (var fixedArgument in decodedValue.FixedArguments)
            {
                if (IsBlockedCustomAttributeConstantValue(fixedArgument.Type, fixedArgument.Value))
                {
                    return(true);
                }

                if (fixedArgument.Type.IsEnum && IsBlocked(fixedArgument.Type))
                {
                    return(true);
                }
            }

            foreach (var namedArgument in decodedValue.NamedArguments)
            {
                if (IsBlockedCustomAttributeConstantValue(namedArgument.Type, namedArgument.Value))
                {
                    return(true);
                }
            }

            return(false);
        }
        private CustomAttribute HandleCustomAttribute(Cts.MethodDesc constructor, Ecma.CustomAttributeValue <Cts.TypeDesc> decodedValue)
        {
            CustomAttribute result = new CustomAttribute
            {
                Constructor = HandleQualifiedMethod(constructor),
            };

            result.FixedArguments.Capacity = decodedValue.FixedArguments.Length;
            foreach (var decodedArgument in decodedValue.FixedArguments)
            {
                var fixedArgument = HandleCustomAttributeConstantValue(decodedArgument.Type, decodedArgument.Value);
                result.FixedArguments.Add(fixedArgument);
            }

            result.NamedArguments.Capacity = decodedValue.NamedArguments.Length;
            foreach (var decodedArgument in decodedValue.NamedArguments)
            {
                var namedArgument = new NamedArgument
                {
                    Flags = decodedArgument.Kind == Ecma.CustomAttributeNamedArgumentKind.Field ?
                            NamedArgumentMemberKind.Field : NamedArgumentMemberKind.Property,
                    Name  = HandleString(decodedArgument.Name),
                    Type  = HandleType(decodedArgument.Type),
                    Value = HandleCustomAttributeConstantValue(decodedArgument.Type, decodedArgument.Value)
                };
                result.NamedArguments.Add(namedArgument);
            }

            return(result);
        }
Beispiel #15
0
        public override MetadataRecord HandleQualifiedMethod(Cts.MethodDesc method)
        {
            MetadataRecord rec;

            if (method is Cts.InstantiatedMethod)
            {
                rec = HandleMethodInstantiation(method);
            }
            else if (method.IsTypicalMethodDefinition && _policy.GeneratesMetadata(method))
            {
                rec = new QualifiedMethod
                {
                    EnclosingType = (TypeDefinition)HandleType(method.OwningType),
                    Method        = HandleMethodDefinition(method),
                };
            }
            else
            {
                rec = HandleMethodReference(method);
            }

            Debug.Assert(rec is QualifiedMethod || rec is MemberReference || rec is MethodInstantiation);

            return(rec);
        }
        /// <summary>
        /// Given a virtual method decl, return its VTable slot if the method is used on its containing type.
        /// Return -1 if the virtual method is not used.
        /// </summary>
        public static int GetVirtualMethodSlot(NodeFactory factory, MethodDesc method)
        {
            // TODO: More efficient lookup of the slot
            TypeDesc owningType = method.OwningType;
            int baseSlots = 0;
            var baseType = owningType.BaseType;

            while (baseType != null)
            {
                List<MethodDesc> baseVirtualSlots;
                factory.VirtualSlots.TryGetValue(baseType, out baseVirtualSlots);

                if (baseVirtualSlots != null)
                    baseSlots += baseVirtualSlots.Count;
                baseType = baseType.BaseType;
            }

            List<MethodDesc> virtualSlots = factory.VirtualSlots[owningType];
            int methodSlot = -1;
            for (int slot = 0; slot < virtualSlots.Count; slot++)
            {
                if (virtualSlots[slot] == method)
                {
                    methodSlot = slot;
                    break;
                }
            }
            
            return methodSlot == -1 ? -1 : baseSlots + methodSlot;
        }
Beispiel #17
0
        private void AppendMethodSignature(StringBuilder sb, MethodDesc method)
        {
            // If this is an instantiated generic method, the formatted signature should
            // be uninstantiated (e.g. "void Foo::Bar<int>(!!0 param)", not "void Foo::Bar<int>(int param)")
            MethodSignature signature = method.GetMethodDefinition().Signature;

            AppendSignaturePrefix(sb, signature);
            sb.Append(' ');
            AppendOwningType(sb, method.OwningType);
            sb.Append("::");
            sb.Append(method.Name);

            if (method.HasInstantiation)
            {
                sb.Append('<');

                for (int i = 0; i < method.Instantiation.Length; i++)
                {
                    if (i != 0)
                        sb.Append(", ");
                    _typeNameFormatter.AppendNameWithValueClassPrefix(sb, method.Instantiation[i]);
                }

                sb.Append('>');
            }

            sb.Append('(');
            AppendSignatureArgumentList(sb, signature);
            sb.Append(')');
        }
Beispiel #18
0
        public DelegateInfo(Compilation compilation, MethodDesc target)
        {
            this.Target = target;

            var systemDelegate = compilation.TypeSystemContext.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType;

            // TODO: delegates on virtuals
            if (target.IsVirtual && !target.IsFinal)
                throw new NotImplementedException("Delegate to virtual");

            // TODO: Delegates on valuetypes
            if (target.OwningType.IsValueType)
                throw new NotImplementedException("Delegate to valuetype");

            if (target.Signature.IsStatic)
            {
                this.ShuffleThunk = new DelegateShuffleThunk(target);

                this.Ctor = systemDelegate.GetKnownMethod("InitializeClosedStaticThunk", null);
            }
            else
            {
                this.Ctor = systemDelegate.GetKnownMethod("InitializeClosedInstance", null);
            }
        }
Beispiel #19
0
        public MethodIL GetMethodIL(MethodDesc method)
        {
            if (method is EcmaMethod)
            {
                // TODO: Workaround: we should special case methods with Intrinsic attribute, but since
                //       CoreLib source is still not in the repo, we have to work with what we have, which is
                //       an MCG attribute on the type itself...
                if (((MetadataType)method.OwningType).HasCustomAttribute("System.Runtime.InteropServices", "McgIntrinsicsAttribute"))
                {
                    if (method.Name == "Call")
                    {
                        return CalliIntrinsic.EmitIL(method);
                    }
                }

                if (method.IsIntrinsic)
                {
                    MethodIL result = TryGetIntrinsicMethodIL(method);
                    if (result != null)
                        return result;
                }

                if (method.IsPInvoke)
                {
                    return PInvokeMarshallingILEmitter.EmitIL(method);
                }

                return EcmaMethodIL.Create((EcmaMethod)method);
            }
            else
            if (method is MethodForInstantiatedType)
            {
                var methodDefinitionIL = GetMethodIL(method.GetTypicalMethodDefinition());
                if (methodDefinitionIL == null)
                    return null;
                return new InstantiatedMethodIL(methodDefinitionIL, method.OwningType.Instantiation, new Instantiation());
            }
            else
            if (method is InstantiatedMethod)
            {
                var methodDefinitionIL = GetMethodIL(method.GetMethodDefinition());
                if (methodDefinitionIL == null)
                    return null;
                return new InstantiatedMethodIL(methodDefinitionIL, new Instantiation(), method.Instantiation);
            }
            else
            if (method is ILStubMethod)
            {
                return ((ILStubMethod)method).EmitIL();
            }
            else
            if (method is ArrayMethod)
            {
                return ArrayMethodILEmitter.EmitIL((ArrayMethod)method);
            }
            else
            {
                return null;
            }
        }
        public FatFunctionPointerNode(MethodDesc methodRepresented)
        {
            // We should not create these for methods that don't have a canonical method body
            Debug.Assert(methodRepresented.GetCanonMethodTarget(CanonicalFormKind.Specific) != methodRepresented);

            Method = methodRepresented;
        }
Beispiel #21
0
 // Returns null if no matching method is found
 private static MethodDesc GetMatchingMethod(ModuleDesc module, MethodDesc method)
 {
     var matchingType = GetMatchingType(module, method.OwningType);
     if (matchingType == null)
         return null;
     return matchingType.GetMethod(method.Name, method.Signature);
 }
Beispiel #22
0
        private List <CustomAttribute> HandleCustomAttributes(Cts.Ecma.EcmaModule module, Ecma.CustomAttributeHandleCollection attributes)
        {
            List <CustomAttribute> customAttributes = new List <CustomAttribute>(attributes.Count);

            var attributeTypeProvider = new Cts.Ecma.CustomAttributeTypeProvider(module);

            foreach (var attributeHandle in attributes)
            {
                Ecma.MetadataReader  reader    = module.MetadataReader;
                Ecma.CustomAttribute attribute = reader.GetCustomAttribute(attributeHandle);

                // TODO-NICE: We can intern the attributes based on the CA constructor and blob bytes

                try
                {
                    Cts.MethodDesc constructor  = module.GetMethod(attribute.Constructor);
                    var            decodedValue = attribute.DecodeValue(attributeTypeProvider);

                    if (IsBlockedCustomAttribute(constructor, decodedValue))
                    {
                        continue;
                    }

                    customAttributes.Add(HandleCustomAttribute(constructor, decodedValue));
                }
                catch (Cts.TypeSystemException)
                {
                    // TODO: We should emit unresolvable custom attributes instead of skipping these
                }
            }

            return(customAttributes);
        }
        private void InitializeMethodDefinition(Cts.MethodDesc entity, Method record)
        {
            record.Name      = HandleString(entity.Name);
            record.Signature = HandleMethodSignature(entity.Signature);

            if (entity.HasInstantiation)
            {
                var genericParams = new List <GenericParameter>(entity.Instantiation.Length);
                foreach (var p in entity.Instantiation)
                {
                    genericParams.Add(HandleGenericParameter((Cts.GenericParameterDesc)p));
                }
                record.GenericParameters = genericParams;
            }

            if (entity.Signature.Length > 0)
            {
                List <Parameter> parameters = new List <Parameter>(entity.Signature.Length);
                for (ushort i = 0; i < entity.Signature.Length; i++)
                {
                    parameters.Add(new Parameter
                    {
                        Sequence = i
                    });
                }

                var ecmaEntity = entity as Cts.Ecma.EcmaMethod;
                if (ecmaEntity != null)
                {
                    Ecma.MetadataReader            reader       = ecmaEntity.MetadataReader;
                    Ecma.MethodDefinition          methodDef    = reader.GetMethodDefinition(ecmaEntity.Handle);
                    Ecma.ParameterHandleCollection paramHandles = methodDef.GetParameters();

                    Debug.Assert(paramHandles.Count == entity.Signature.Length);

                    int i = 0;
                    foreach (var paramHandle in paramHandles)
                    {
                        Ecma.Parameter param = reader.GetParameter(paramHandle);
                        parameters[i].Flags = param.Attributes;
                        parameters[i].Name  = HandleString(reader.GetString(param.Name));

                        // TODO: CustomAttributes
                        // TODO: DefaultValue

                        i++;
                    }
                }

                record.Parameters = parameters;
            }

            record.Flags     = GetMethodAttributes(entity);
            record.ImplFlags = GetMethodImplAttributes(entity);

            //TODO: MethodImpls
            //TODO: RVA
            //TODO: CustomAttributes
        }
Beispiel #24
0
        internal MethodIL GetMethodIL(MethodDesc method)
        {
            // Flush the cache when it grows too big
            if (_methodILCache.Count > 1000)
                _methodILCache = new ILProvider();

            return _methodILCache.GetMethodIL(method);
        }
        internal InstantiatedMethod(MethodDesc methodDef, Instantiation instantiation)
        {
            Debug.Assert(!(methodDef is InstantiatedMethod));
            _methodDef = methodDef;

            Debug.Assert(instantiation.Length > 0);
            _instantiation = instantiation;
        }
 public static MethodIL EmitIL(MethodDesc method)
 {
     ILEmitter emit = new ILEmitter();
     ILCodeStream codeStream = emit.NewCodeStream();
     MethodDesc typeLoadExceptionHelper = method.Context.GetHelperEntryPoint("ThrowHelpers", "ThrowTypeLoadException");
     codeStream.EmitCallThrowHelper(emit, typeLoadExceptionHelper);
     return emit.Link();
 }
        /// <summary>
        /// Resolve a MethodDesc to a callable method address and unboxing stub address by searching
        /// by searching in the InvokeMaps. This function is a wrapper around TryGetMethodInvokeDataFromInvokeMap
        /// that produces output in the format which matches the code table system.
        /// </summary>
        /// <param name="method">Native metadata method description object</param>
        /// <param name="methodAddress">Resolved method address</param>
        /// <param name="unboxingStubAddress">Resolved unboxing stub address</param>
        /// <returns>true when the resolution succeeded, false when not</returns>
        private static bool TryGetMethodAddressFromTypeSystemMethodViaInvokeMap(
            MethodDesc method,
            out IntPtr methodAddress,
            out IntPtr unboxingStubAddress,
            out MethodAddressType foundAddressType)
        {
            methodAddress = IntPtr.Zero;
            unboxingStubAddress = IntPtr.Zero;
            foundAddressType = MethodAddressType.None;
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
            NativeFormatMethod nativeFormatMethod = method.GetTypicalMethodDefinition() as NativeFormatMethod;
            if (nativeFormatMethod == null)
                return false;

            MethodSignatureComparer methodSignatureComparer = new MethodSignatureComparer(
                nativeFormatMethod.MetadataReader, nativeFormatMethod.Handle);

            // Try to find a specific canonical match, or if that fails, a universal match
            if (TryGetMethodInvokeDataFromInvokeMap(
                nativeFormatMethod,
                method,
                ref methodSignatureComparer,
                CanonicalFormKind.Specific,
                out methodAddress,
                out foundAddressType) ||

                TryGetMethodInvokeDataFromInvokeMap(
                nativeFormatMethod,
                method,
                ref methodSignatureComparer,
                CanonicalFormKind.Universal,
                out methodAddress,
                out foundAddressType))
            {
                if (method.OwningType.IsValueType && !method.Signature.IsStatic)
                {
                    // In this case the invoke map found an unboxing stub, and we should pull the method address out as well
                    unboxingStubAddress = methodAddress;
                    methodAddress = RuntimeAugments.GetCodeTarget(unboxingStubAddress);

                    if (!method.HasInstantiation && ((foundAddressType != MethodAddressType.Exact) || method.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any)))
                    {
                        IntPtr underlyingTarget; // unboxing and instantiating stub handling
                        if (!TypeLoaderEnvironment.TryGetTargetOfUnboxingAndInstantiatingStub(methodAddress, out underlyingTarget))
                        {
                            Environment.FailFast("Expected this to be an unboxing and instantiating stub.");
                        }
                        methodAddress = underlyingTarget;
                    }
                }

                return true;
            }

#endif
            return false;
        }
Beispiel #28
0
 // Returns null if no matching method is found
 private static MethodDesc GetMatchingMethod(ModuleDesc module, MethodDesc method)
 {
   // TODO:Enable this once mcg generated code match GetMatchingType
   // type lookup. 
   // var matchingType = GetMatchingType(module, method.OwningType);
     var matchingType = TryGetMcgGeneratedType(module);
     if (matchingType == null)
         return null;
     return matchingType.GetMethod(method.Name, method.Signature);
 }
Beispiel #29
0
 private void InitializeMethodInstantiation(Cts.MethodDesc entity, MethodInstantiation record)
 {
     Cts.InstantiatedMethod instantiation = (Cts.InstantiatedMethod)entity;
     record.Method = HandleQualifiedMethod(instantiation.GetMethodDefinition());
     record.GenericTypeArguments.Capacity = instantiation.Instantiation.Length;
     foreach (Cts.TypeDesc typeArgument in instantiation.Instantiation)
     {
         record.GenericTypeArguments.Add(HandleType(typeArgument));
     }
 }
Beispiel #30
0
        public static IntrinsicMethodKind GetIntrinsicMethodClassification(MethodDesc method)
        {
            // TODO: make this reliable
            if (method.Name == "InitializeArray" && method.OwningType.Name == "System.Runtime.CompilerServices.RuntimeHelpers")
            {
                return IntrinsicMethodKind.RuntimeHelpersInitializeArray;
            }

            return IntrinsicMethodKind.None;
        }
Beispiel #31
0
        /// <summary>
        /// Returns true if <paramref name="method"/> is pregenerated interop code
        /// </summary>
        public static bool IsPregeneratedInterop(MethodDesc method)
        {
            var metadataType = (MetadataType)method.OwningType;
            var module = metadataType.Module;

            var assemblyName = ((IAssemblyDesc)module).GetName();
            var simpleName = assemblyName.Name;

            return simpleName.EndsWith(AssemblyNameSuffix);
        }
Beispiel #32
0
        public MethodCode CompileMethod(MethodDesc method)
        {
            try
            {
                CORINFO_METHOD_INFO methodInfo;
                Get_CORINFO_METHOD_INFO(method, out methodInfo);

                uint flags = (uint)(
                    CorJitFlag.CORJIT_FLG_SKIP_VERIFICATION |
                    CorJitFlag.CORJIT_FLG_READYTORUN |
                    CorJitFlag.CORJIT_FLG_RELOC |
                    CorJitFlag.CORJIT_FLG_DEBUG_INFO |
                    CorJitFlag.CORJIT_FLG_PREJIT);

                if (!_compilation.Options.NoLineNumbers)
                {
                    CompilerTypeSystemContext typeSystemContext = _compilation.TypeSystemContext;
                    IEnumerable<ILSequencePoint> ilSequencePoints = typeSystemContext.GetSequencePointsForMethod(method);
                    if (ilSequencePoints != null)
                    {
                        Dictionary<int, SequencePoint> sequencePoints = new Dictionary<int, SequencePoint>();
                        foreach (var point in ilSequencePoints)
                        {
                            sequencePoints.Add(point.Offset, new SequencePoint() { Document = point.Document, LineNumber = point.LineNumber });
                        }
                        _sequencePoints = sequencePoints;
                    }
                }

                IntPtr nativeEntry;
                uint codeSize;
                _compile(_jit, _comp, ref methodInfo, flags, out nativeEntry, out codeSize);

                if (_relocs != null)
                    _relocs.Sort((x, y) => (x.Block != y.Block) ? (x.Block - y.Block) : (x.Offset - y.Offset));

                return new MethodCode()
                {
                    Code = _code,
                    ColdCode = _coldCode,

                    RODataAlignment = _roDataAlignment,
                    ROData = _roData,

                    Relocs = (_relocs != null) ? _relocs.ToArray() : null,

                    FrameInfos = _frameInfos,
                    DebugLocInfos = _debugLocInfos
                };
            }
            finally
            {
                FlushPins();
            }
        }
Beispiel #33
0
        /// <summary>
        /// Validates that it will be possible to generate '<paramref name="method"/>' based on the types 
        /// in its signature. Unresolvable types in a method's signature prevent RyuJIT from generating
        /// even a stubbed out throwing implementation.
        /// </summary>
        private static void CheckCanGenerateMethod(MethodDesc method)
        {
            MethodSignature signature = method.Signature;

            CheckTypeCanBeUsedInSignature(signature.ReturnType);

            for (int i = 0; i < signature.Length; i++)
            {
                CheckTypeCanBeUsedInSignature(signature[i]);
            }
        }
 protected override IMethodNode CreateMethodEntrypointNode(MethodDesc method)
 {
     if (CompilationModuleGroup.ContainsMethod(method))
     {
         return new CppMethodCodeNode(method);
     }
     else
     {
         return new ExternMethodSymbolNode(method);
     }
 }
        private PInvokeMarshallingILEmitter(MethodDesc targetMethod)
        {
            Debug.Assert(targetMethod.IsPInvoke);
            Debug.Assert(RequiresMarshalling(targetMethod));

            _targetMethod = targetMethod;
            _importMetadata = targetMethod.GetPInvokeMethodMetadata();

            _emitter = null;
            _marshallingCodeStream = null;
        }
Beispiel #36
0
 private MethodImplAttributes GetMethodImplAttributes(Cts.MethodDesc method)
 {
     var ecmaMethod = method as Cts.Ecma.EcmaMethod;
     if (ecmaMethod != null)
     {
         Ecma.MetadataReader reader = ecmaMethod.MetadataReader;
         Ecma.MethodDefinition methodDef = reader.GetMethodDefinition(ecmaMethod.Handle);
         return methodDef.ImplAttributes;
     }
     else
         throw new NotImplementedException();
 }
Beispiel #37
0
        public static MethodIL EmitIL(MethodDesc target)
        {
            Debug.Assert(target.Name == "Call");
            Debug.Assert(target.Signature.Length > 0
                && target.Signature[0] == target.Context.GetWellKnownType(WellKnownType.IntPtr));

            ILEmitter emitter = new ILEmitter();
            var codeStream = emitter.NewCodeStream();

            // Load all the arguments except the first one (IntPtr address)
            for (int i = 1; i < target.Signature.Length; i++)
            {
                codeStream.EmitLdArg(i);
            }

            // now load IntPtr address
            codeStream.EmitLdArg(0);

            // Create a signature for the calli by copying the signature of the containing method
            // while skipping the first argument
            MethodSignature template = target.Signature;
            TypeDesc returnType = template.ReturnType;
            TypeDesc[] parameters = new TypeDesc[template.Length - 1];
            for (int i = 1; i < template.Length; i++)
            {
                parameters[i - 1] = template[i];
            }

            var signature = new MethodSignature(template.Flags, 0, returnType, parameters);

            bool useTransformedCalli = true;

            if ((signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask) != 0)
            {
                // Fat function pointer only ever exist for managed targets.
                useTransformedCalli = false;
            }

            if (((MetadataType)target.OwningType).Name == "RawCalliHelper")
            {
                // RawCalliHelper doesn't need the transform.
                useTransformedCalli = false;
            }

            if (useTransformedCalli)
                EmitTransformedCalli(emitter, codeStream, signature);
            else
                codeStream.Emit(ILOpcode.calli, emitter.NewToken(signature));
            
            codeStream.Emit(ILOpcode.ret);

            return emitter.Link(target);
        }
Beispiel #38
0
        public InstantiatedMethodIL(MethodDesc owningMethod, MethodIL methodIL)
        {
            Debug.Assert(methodIL.GetMethodILDefinition() == methodIL);
            Debug.Assert(owningMethod.HasInstantiation || owningMethod.OwningType.HasInstantiation);
            Debug.Assert(owningMethod.GetTypicalMethodDefinition() == methodIL.OwningMethod);
            
            _methodIL = methodIL;
            _method = owningMethod;

            _typeInstantiation = owningMethod.OwningType.Instantiation;
            _methodInstantiation = owningMethod.Instantiation;
        }
        /// <summary>
        /// Attempts to retrieve a <see cref="Method"/> record corresponding to the specified
        /// <paramref name="method"/>. Returns null if not found.
        /// </summary>
        public Method GetTransformedMethodDefinition(Cts.MethodDesc method)
        {
            Debug.Assert(method.IsTypicalMethodDefinition);

            MetadataRecord rec;

            if (!_transform._methods.TryGet(method, out rec))
            {
                return(null);
            }

            return(rec as Method);
        }
Beispiel #40
0
        public void TestMethodImplMetadata()
        {
            // Test that custom attributes referring to blocked types don't show up in metadata

            var sampleMetadataModule = _context.GetModuleForSimpleName("SampleMetadataAssembly");

            Cts.MetadataType iCloneable                      = sampleMetadataModule.GetType("SampleMetadataMethodImpl", "ICloneable");
            Cts.MetadataType implementsICloneable            = sampleMetadataModule.GetType("SampleMetadataMethodImpl", "ImplementsICloneable");
            Cts.MethodDesc   iCloneableDotClone              = iCloneable.GetMethod("Clone", null);
            Cts.MethodDesc   iCloneableImplementation        = implementsICloneable.GetMethod("SampleMetadataMethodImpl.ICloneable.Clone", null);
            Cts.MethodDesc   iCloneableDotGenericClone       = iCloneable.GetMethod("GenericClone", null);
            Cts.MethodDesc   iCloneableGenericImplementation = implementsICloneable.GetMethod("SampleMetadataMethodImpl.ICloneable.GenericClone", null);

            var policy          = new SingleFileMetadataPolicy();
            var transformResult = MetadataTransform.Run(policy,
                                                        new[] { _systemModule, sampleMetadataModule });

            var iCloneableType           = transformResult.GetTransformedTypeDefinition(iCloneable);
            var implementsICloneableType = transformResult.GetTransformedTypeDefinition(implementsICloneable);

            Assert.Equal(2, implementsICloneableType.MethodImpls.Count);

            // non-generic MethodImpl
            Method          iCloneableDotCloneMethod       = transformResult.GetTransformedMethodDefinition(iCloneableDotClone);
            Method          iCloneableImplementationMethod = transformResult.GetTransformedMethodDefinition(iCloneableImplementation);
            QualifiedMethod methodImplMethodDecl           = (QualifiedMethod)implementsICloneableType.MethodImpls[0].MethodDeclaration;
            QualifiedMethod methodImplMethodBody           = (QualifiedMethod)implementsICloneableType.MethodImpls[0].MethodBody;

            Assert.Equal(iCloneableDotCloneMethod, methodImplMethodDecl.Method);
            Assert.Equal(iCloneableType, methodImplMethodDecl.EnclosingType);

            Assert.Equal(iCloneableImplementationMethod, methodImplMethodBody.Method);
            Assert.Equal(implementsICloneableType, methodImplMethodBody.EnclosingType);

            // generic MethodImpl
            Method          iCloneableDotGenericCloneMethod       = transformResult.GetTransformedMethodDefinition(iCloneableDotGenericClone);
            Method          iCloneableGenericImplementationMethod = transformResult.GetTransformedMethodDefinition(iCloneableGenericImplementation);
            QualifiedMethod methodImplGenericMethodDecl           = (QualifiedMethod)implementsICloneableType.MethodImpls[1].MethodDeclaration;
            QualifiedMethod methodImplGenericMethodBody           = (QualifiedMethod)implementsICloneableType.MethodImpls[1].MethodBody;

            Assert.Equal(iCloneableDotGenericCloneMethod, methodImplGenericMethodDecl.Method);
            Assert.Equal(iCloneableType, methodImplGenericMethodDecl.EnclosingType);

            Assert.Equal(iCloneableGenericImplementationMethod, methodImplGenericMethodBody.Method);
            Assert.Equal(implementsICloneableType, methodImplGenericMethodBody.EnclosingType);
        }
        private MetadataRecord HandleMethod(Cts.MethodDesc method)
        {
            // TODO: MethodSpecs
            Debug.Assert(method.IsTypicalMethodDefinition);

            MetadataRecord rec;

            if (_policy.GeneratesMetadata(method))
            {
                rec = HandleMethodDefinition(method);
            }
            else
            {
                rec = _methods.GetOrCreate(method, _initMethodRef ?? (_initMethodRef = InitializeMethodReference));
            }

            Debug.Assert(rec is Method || rec is MemberReference);

            return(rec);
        }
Beispiel #42
0
        private MetadataRecord HandleQualifiedMethod(Cts.MethodDesc method)
        {
            MetadataRecord rec;

            if (_policy.GeneratesMetadata(method))
            {
                rec = new QualifiedMethod
                {
                    EnclosingType = (TypeDefinition)HandleType(method.OwningType),
                    Method        = HandleMethodDefinition(method),
                };
            }
            else
            {
                rec = HandleMethodReference(method);
            }

            Debug.Assert(rec is QualifiedMethod || rec is MemberReference);

            return(rec);
        }
 public override MethodDesc ResolveInterfaceMethodToVirtualMethodOnType(MethodDesc interfaceMethod, TypeDesc currentType)
 {
     return(ResolveInterfaceMethodToVirtualMethodOnType(interfaceMethod, (MetadataType)currentType));
 }
Beispiel #44
0
 private MethodInstantiation HandleMethodInstantiation(Cts.MethodDesc method)
 {
     return((MethodInstantiation)_methods.GetOrCreate(method, _initMethodInst ??= InitializeMethodInstantiation));
 }
Beispiel #45
0
 private void InitializeMethodReference(Cts.MethodDesc entity, MemberReference record)
 {
     record.Name      = HandleString(entity.Name);
     record.Parent    = HandleType(entity.OwningType);
     record.Signature = HandleMethodSignature(entity.GetTypicalMethodDefinition().Signature);
 }
Beispiel #46
0
 private MemberReference HandleMethodReference(Cts.MethodDesc method)
 {
     Debug.Assert(method.IsMethodDefinition);
     return((MemberReference)_methods.GetOrCreate(method, _initMethodRef ??= InitializeMethodReference));
 }
        // Return true if the slot that defines methodToVerify matches slotDefiningMethod
        private static bool VerifyMethodsHaveTheSameVirtualSlot(MethodDesc methodToVerify, MethodDesc slotDefiningMethod)
        {
            MethodDesc slotDefiningMethodOfMethodToVerify = FindSlotDefiningMethodForVirtualMethod(methodToVerify);

            return(slotDefiningMethodOfMethodToVerify == slotDefiningMethod);
        }
Beispiel #48
0
        private void InitializeMethodDefinition(Cts.MethodDesc entity, Method record)
        {
            record.Name      = HandleString(entity.Name);
            record.Signature = HandleMethodSignature(entity.Signature);

            if (entity.HasInstantiation)
            {
                record.GenericParameters.Capacity = entity.Instantiation.Length;
                foreach (var p in entity.Instantiation)
                {
                    record.GenericParameters.Add(HandleGenericParameter((Cts.GenericParameterDesc)p));
                }
            }

            var ecmaEntity = entity as Cts.Ecma.EcmaMethod;

            if (ecmaEntity != null)
            {
                Ecma.MetadataReader            reader       = ecmaEntity.MetadataReader;
                Ecma.MethodDefinition          methodDef    = reader.GetMethodDefinition(ecmaEntity.Handle);
                Ecma.ParameterHandleCollection paramHandles = methodDef.GetParameters();

                record.Parameters.Capacity = paramHandles.Count;
                foreach (var paramHandle in paramHandles)
                {
                    Ecma.Parameter param       = reader.GetParameter(paramHandle);
                    Parameter      paramRecord = new Parameter
                    {
                        Flags    = param.Attributes,
                        Name     = HandleString(reader.GetString(param.Name)),
                        Sequence = checked ((ushort)param.SequenceNumber)
                    };

                    Ecma.ConstantHandle defaultValue = param.GetDefaultValue();
                    if (!defaultValue.IsNil)
                    {
                        paramRecord.DefaultValue = HandleConstant(ecmaEntity.Module, defaultValue);
                    }

                    Ecma.CustomAttributeHandleCollection paramAttributes = param.GetCustomAttributes();
                    if (paramAttributes.Count > 0)
                    {
                        paramRecord.CustomAttributes = HandleCustomAttributes(ecmaEntity.Module, paramAttributes);
                    }

                    record.Parameters.Add(paramRecord);
                }

                Ecma.CustomAttributeHandleCollection attributes = methodDef.GetCustomAttributes();
                if (attributes.Count > 0)
                {
                    record.CustomAttributes = HandleCustomAttributes(ecmaEntity.Module, attributes);
                }
            }
            else
            {
                throw new NotImplementedException();
            }

            record.Flags     = GetMethodAttributes(entity);
            record.ImplFlags = GetMethodImplAttributes(entity);

            //TODO: RVA
        }
        // Helper routine used during implicit interface implementation discovery
        private static MethodDesc ResolveInterfaceMethodToVirtualMethodOnTypeRecursive(MethodDesc interfaceMethod, MetadataType currentType)
        {
            while (true)
            {
                if (currentType == null)
                {
                    return(null);
                }

                MetadataType interfaceType = (MetadataType)interfaceMethod.OwningType;

                if (!IsInterfaceImplementedOnType(currentType, interfaceType))
                {
                    // If the interface isn't implemented on this type at all, don't go searching
                    return(null);
                }

                MethodDesc currentTypeInterfaceResolution = ResolveInterfaceMethodToVirtualMethodOnType(interfaceMethod, currentType);
                if (currentTypeInterfaceResolution != null)
                {
                    return(currentTypeInterfaceResolution);
                }

                currentType = currentType.MetadataBaseType;
            }
        }
 public UnificationGroup(MethodDesc definingMethod)
 {
     DefiningMethod = definingMethod;
     // TODO! Add assertion that DefiningMethod is a slot defining method
 }
Beispiel #51
0
        private Event HandleEvent(Cts.Ecma.EcmaModule module, Ecma.EventDefinitionHandle eventHandle)
        {
            Ecma.MetadataReader reader = module.MetadataReader;

            Ecma.EventDefinition eventDef = reader.GetEventDefinition(eventHandle);

            Ecma.EventAccessors acc           = eventDef.GetAccessors();
            Cts.MethodDesc      adderMethod   = acc.Adder.IsNil ? null : module.GetMethod(acc.Adder);
            Cts.MethodDesc      raiserMethod  = acc.Raiser.IsNil ? null : module.GetMethod(acc.Raiser);
            Cts.MethodDesc      removerMethod = acc.Remover.IsNil ? null : module.GetMethod(acc.Remover);

            bool adderHasMetadata   = adderMethod != null && _policy.GeneratesMetadata(adderMethod);
            bool raiserHasMetadata  = raiserMethod != null && _policy.GeneratesMetadata(raiserMethod);
            bool removerHasMetadata = removerMethod != null && _policy.GeneratesMetadata(removerMethod);

            // Policy: If none of the accessors has metadata, event doesn't have metadata
            if (!adderHasMetadata && !raiserHasMetadata && !removerHasMetadata)
            {
                return(null);
            }

            Event result = new Event
            {
                Name  = HandleString(reader.GetString(eventDef.Name)),
                Flags = eventDef.Attributes,
                Type  = HandleType(module.GetType(eventDef.Type)),
            };

            if (adderHasMetadata)
            {
                result.MethodSemantics.Add(new MethodSemantics
                {
                    Attributes = MethodSemanticsAttributes.AddOn,
                    Method     = HandleMethodDefinition(adderMethod),
                });
            }

            if (raiserHasMetadata)
            {
                result.MethodSemantics.Add(new MethodSemantics
                {
                    Attributes = MethodSemanticsAttributes.Fire,
                    Method     = HandleMethodDefinition(raiserMethod),
                });
            }

            if (removerHasMetadata)
            {
                result.MethodSemantics.Add(new MethodSemantics
                {
                    Attributes = MethodSemanticsAttributes.RemoveOn,
                    Method     = HandleMethodDefinition(removerMethod),
                });
            }

            Ecma.CustomAttributeHandleCollection customAttributes = eventDef.GetCustomAttributes();
            if (customAttributes.Count > 0)
            {
                result.CustomAttributes = HandleCustomAttributes(module, customAttributes);
            }

            return(result);
        }
 /// <summary>
 /// Retrieves an existing <see cref="QualifiedMethod"/>, <see cref="MemberReference"/>, or <see cref="MethodInstantiation"/>
 /// record representing specified method in the metadata writer object model, or creates a new one.
 /// </summary>
 public abstract MetadataRecord HandleQualifiedMethod(Cts.MethodDesc method);
        private static void FindBaseUnificationGroup(MetadataType currentType, UnificationGroup unificationGroup)
        {
            MethodDesc originalDefiningMethod = unificationGroup.DefiningMethod;

            MethodDesc methodImpl = FindImplFromDeclFromMethodImpls(currentType, unificationGroup.DefiningMethod);

            if (methodImpl != null)
            {
                unificationGroup.SetDefiningMethod(methodImpl);
            }

            MethodDesc   nameSigMatchMethod = FindMatchingVirtualMethodOnTypeByNameAndSigWithSlotCheck(unificationGroup.DefiningMethod, currentType);
            MetadataType baseType           = currentType.MetadataBaseType;

            // Unless the current type has a name/sig match for the group, look to the base type to define the unification group further
            if ((nameSigMatchMethod == null) && (baseType != null))
            {
                FindBaseUnificationGroup(baseType, unificationGroup);
            }

            Debug.Assert(unificationGroup.IsInGroupOrIsDefiningSlot(originalDefiningMethod));

            // Now, we have the unification group from the type, or have discovered its defined on the current type.
            // Adjust the group to contain all of the elements that are added to it on this type, remove the components that
            // have seperated themselves from the group

            // Start with removing methods that seperated themselves from the group via name/sig matches
            MethodDescHashtable separatedMethods = null;

            foreach (MethodDesc memberMethod in unificationGroup)
            {
                MethodDesc nameSigMatchMemberMethod = FindMatchingVirtualMethodOnTypeByNameAndSigWithSlotCheck(memberMethod, currentType);
                if (nameSigMatchMemberMethod != null)
                {
                    if (separatedMethods == null)
                    {
                        separatedMethods = new MethodDescHashtable();
                    }
                    separatedMethods.AddOrGetExisting(memberMethod);
                }
            }

            if (separatedMethods != null)
            {
                foreach (MethodDesc seperatedMethod in MethodDescHashtable.Enumerator.Get(separatedMethods))
                {
                    unificationGroup.RemoveFromGroup(seperatedMethod);
                }
            }

            // Next find members which have seperated or added themselves to the group via MethodImpls
            foreach (MethodImplRecord methodImplRecord in currentType.VirtualMethodImplsForType)
            {
                MethodDesc declSlot = FindSlotDefiningMethodForVirtualMethod(methodImplRecord.Decl);
                MethodDesc implSlot = FindSlotDefiningMethodForVirtualMethod(methodImplRecord.Body);

                if (unificationGroup.IsInGroup(declSlot) && !unificationGroup.IsInGroupOrIsDefiningSlot(implSlot))
                {
                    unificationGroup.RemoveFromGroup(declSlot);

                    if (separatedMethods == null)
                    {
                        separatedMethods = new MethodDescHashtable();
                    }
                    separatedMethods.AddOrGetExisting(declSlot);
                    continue;
                }
                if (!unificationGroup.IsInGroupOrIsDefiningSlot(declSlot) && unificationGroup.IsInGroupOrIsDefiningSlot(implSlot))
                {
                    // Add decl to group.

                    // To do so, we need to have the Unification Group of the decl slot, as it may have multiple members itself
                    UnificationGroup addDeclGroup = new UnificationGroup(declSlot);
                    FindBaseUnificationGroup(baseType, addDeclGroup);
                    Debug.Assert(addDeclGroup.IsInGroupOrIsDefiningSlot(declSlot));

                    // Add all members from the decl's unification group except for ones that have been seperated by name/sig matches
                    // or previously processed methodimpls. NOTE: This implies that method impls are order dependent.
                    if (separatedMethods == null || !separatedMethods.Contains(addDeclGroup.DefiningMethod))
                    {
                        unificationGroup.AddToGroup(addDeclGroup.DefiningMethod);
                    }

                    foreach (MethodDesc addDeclGroupMemberMethod in addDeclGroup)
                    {
                        if (separatedMethods == null || !separatedMethods.Contains(addDeclGroupMemberMethod))
                        {
                            unificationGroup.AddToGroup(addDeclGroupMemberMethod);
                        }
                    }
                }
            }
        }
 internal Enumerator(MethodDesc[] arrayToEnumerate)
 {
     _arrayToEnumerate = arrayToEnumerate;
     _index            = 0;
     _current          = default(MethodDesc);
 }
Beispiel #55
0
 private Method HandleMethodDefinition(Cts.MethodDesc method)
 {
     Debug.Assert(method.IsTypicalMethodDefinition);
     Debug.Assert(_policy.GeneratesMetadata(method));
     return((Method)_methods.GetOrCreate(method, _initMethodDef ??= InitializeMethodDefinition));
 }
        //////////////////////// INTERFACE RESOLUTION
        //Interface function resolution
        //    Interface function resolution follows the following rules
        //    1.    Apply any method impl that may exist, if once of these exists, resolve to target immediately.
        //    2.    If an interface is explicitly defined on a type, then attempt to perform a namesig match on the
        //          current type to resolve.If the interface isn’t resolved, if it isn’t implemented on a base type,
        //          scan all base types for name / sig matches.
        //    3.    If implicitly defined, attempt to perform a namesig match if the interface method implementation
        //          has not been found on some base type.
        //    The above will resolve an interface to a virtual method slot. From there perform virtual resolution
        //    to find out the actual target.Note, to preserve correct behavior in the presence of variance, this
        //    function returns null if the interface method implementation is not defined by the current type in
        //    the hierarchy.For variance to work correctly, this requires that interfaces be queried in correct order.
        //    See current interface call resolution for details on how that happens.
        private static MethodDesc ResolveInterfaceMethodToVirtualMethodOnType(MethodDesc interfaceMethod, MetadataType currentType)
        {
            if (currentType.IsInterface)
            {
                return(null);
            }

            MethodDesc methodImpl = FindImplFromDeclFromMethodImpls(currentType, interfaceMethod);

            if (methodImpl != null)
            {
                return(methodImpl);
            }

            MetadataType interfaceType = (MetadataType)interfaceMethod.OwningType;

            // If interface is explicitly defined on a type, search for a name/sig match.
            bool         foundExplicitInterface = IsInterfaceExplicitlyImplementedOnType(currentType, interfaceType);
            MetadataType baseType = currentType.MetadataBaseType;

            if (foundExplicitInterface)
            {
                MethodDesc foundOnCurrentType = FindMatchingVirtualMethodOnTypeByNameAndSig(interfaceMethod, currentType);
                foundOnCurrentType = FindSlotDefiningMethodForVirtualMethod(foundOnCurrentType);

                if (baseType == null)
                {
                    return(foundOnCurrentType);
                }

                if (foundOnCurrentType == null && (ResolveInterfaceMethodToVirtualMethodOnType(interfaceMethod, baseType) == null))
                {
                    // TODO! Does this handle the case where the base type explicitly implements the interface, but is abstract
                    // and doesn't actually have an implementation?
                    if (!IsInterfaceImplementedOnType(baseType, interfaceType))
                    {
                        return(FindNameSigOverrideForInterfaceMethodRecursive(interfaceMethod, baseType));
                    }
                }
                return(foundOnCurrentType);
            }
            else
            {
                // Implicit interface case
                if (!IsInterfaceImplementedOnType(currentType, interfaceType))
                {
                    // If the interface isn't implemented on this type at all, don't go searching
                    return(null);
                }

                // This is an implicitly implemented interface method. Only return a vlaue if this is the first type in the class
                // hierarchy that implements the interface. NOTE: If we pay attention to whether or not the parent type is
                // abstract or not, we may be able to be more efficient here, but let's skip that for now
                MethodDesc baseClassImplementationOfInterfaceMethod = ResolveInterfaceMethodToVirtualMethodOnTypeRecursive(interfaceMethod, baseType);
                if (baseClassImplementationOfInterfaceMethod != null)
                {
                    return(null);
                }
                else
                {
                    return(FindNameSigOverrideForInterfaceMethodRecursive(interfaceMethod, currentType));
                }
            }
        }
Beispiel #57
0
        private Property HandleProperty(Cts.Ecma.EcmaModule module, Ecma.PropertyDefinitionHandle property)
        {
            Ecma.MetadataReader reader = module.MetadataReader;

            Ecma.PropertyDefinition propDef = reader.GetPropertyDefinition(property);

            Ecma.PropertyAccessors acc          = propDef.GetAccessors();
            Cts.MethodDesc         getterMethod = acc.Getter.IsNil ? null : module.GetMethod(acc.Getter);
            Cts.MethodDesc         setterMethod = acc.Setter.IsNil ? null : module.GetMethod(acc.Setter);

            bool getterHasMetadata = getterMethod != null && _policy.GeneratesMetadata(getterMethod);
            bool setterHasMetadata = setterMethod != null && _policy.GeneratesMetadata(setterMethod);

            // Policy: If neither the getter nor setter have metadata, property doesn't have metadata
            if (!getterHasMetadata && !setterHasMetadata)
            {
                return(null);
            }

            Ecma.BlobReader       sigBlobReader = reader.GetBlobReader(propDef.Signature);
            Cts.PropertySignature sig           = new Cts.Ecma.EcmaSignatureParser(module, sigBlobReader, Cts.NotFoundBehavior.Throw).ParsePropertySignature();

            Property result = new Property
            {
                Name      = HandleString(reader.GetString(propDef.Name)),
                Flags     = propDef.Attributes,
                Signature = new PropertySignature
                {
                    CallingConvention = sig.IsStatic ? CallingConventions.Standard : CallingConventions.HasThis,
                    Type = HandleType(sig.ReturnType)
                },
            };

            result.Signature.Parameters.Capacity = sig.Length;
            for (int i = 0; i < sig.Length; i++)
            {
                result.Signature.Parameters.Add(HandleType(sig[i]));
            }

            if (getterHasMetadata)
            {
                result.MethodSemantics.Add(new MethodSemantics
                {
                    Attributes = MethodSemanticsAttributes.Getter,
                    Method     = HandleMethodDefinition(getterMethod),
                });
            }

            if (setterHasMetadata)
            {
                result.MethodSemantics.Add(new MethodSemantics
                {
                    Attributes = MethodSemanticsAttributes.Setter,
                    Method     = HandleMethodDefinition(setterMethod),
                });
            }

            Ecma.ConstantHandle defaultValue = propDef.GetDefaultValue();
            if (!defaultValue.IsNil)
            {
                result.DefaultValue = HandleConstant(module, defaultValue);
            }

            Ecma.CustomAttributeHandleCollection customAttributes = propDef.GetCustomAttributes();
            if (customAttributes.Count > 0)
            {
                result.CustomAttributes = HandleCustomAttributes(module, customAttributes);
            }

            return(result);
        }
Beispiel #58
0
        private void InitializeScopeDefinition(Cts.ModuleDesc module, ScopeDefinition scopeDefinition)
        {
            var assemblyDesc = module as Cts.IAssemblyDesc;

            if (assemblyDesc != null)
            {
                var assemblyName = assemblyDesc.GetName();

                scopeDefinition.Name = HandleString(assemblyName.Name);
#if NETFX_45
                // With NET 4.5 contract System.Reflection 4.0.0.0 EcmaModule has no way
                // to set Culture in its AssemblyName.
                scopeDefinition.Culture = HandleString(assemblyName.CultureName ?? "");
#else
                scopeDefinition.Culture = HandleString(assemblyName.CultureName);
#endif
                scopeDefinition.MajorVersion   = checked ((ushort)assemblyName.Version.Major);
                scopeDefinition.MinorVersion   = checked ((ushort)assemblyName.Version.Minor);
                scopeDefinition.BuildNumber    = checked ((ushort)assemblyName.Version.Build);
                scopeDefinition.RevisionNumber = checked ((ushort)assemblyName.Version.Revision);

                Debug.Assert((int)AssemblyFlags.PublicKey == (int)AssemblyNameFlags.PublicKey);
                Debug.Assert((int)AssemblyFlags.Retargetable == (int)AssemblyNameFlags.Retargetable);
                scopeDefinition.Flags = (AssemblyFlags)assemblyName.Flags;

                if (assemblyName.ContentType == AssemblyContentType.WindowsRuntime)
                {
                    scopeDefinition.Flags |= (AssemblyFlags)((int)AssemblyContentType.WindowsRuntime << 9);
                }

                if ((scopeDefinition.Flags & AssemblyFlags.PublicKey) != 0)
                {
                    scopeDefinition.PublicKey = assemblyName.GetPublicKey();
                }
                else
                {
                    scopeDefinition.PublicKey = assemblyName.GetPublicKeyToken();
                }

                Cts.MetadataType moduleType = module.GetGlobalModuleType();
                if (moduleType != null && _policy.GeneratesMetadata(moduleType))
                {
                    scopeDefinition.GlobalModuleType = (TypeDefinition)HandleType(moduleType);
                }

                Cts.Ecma.EcmaAssembly ecmaAssembly = module as Cts.Ecma.EcmaAssembly;
                if (ecmaAssembly != null)
                {
                    Ecma.CustomAttributeHandleCollection customAttributes = ecmaAssembly.AssemblyDefinition.GetCustomAttributes();
                    if (customAttributes.Count > 0)
                    {
                        scopeDefinition.CustomAttributes = HandleCustomAttributes(ecmaAssembly, customAttributes);
                    }

                    Cts.MethodDesc entryPoint = ecmaAssembly.EntryPoint;
                    if (entryPoint != null && _policy.GeneratesMetadata(entryPoint))
                    {
                        scopeDefinition.EntryPoint = (QualifiedMethod)HandleQualifiedMethod(entryPoint);
                    }
                }
            }
            else
            {
                throw new NotSupportedException("Multi-module assemblies");
            }
        }
Beispiel #59
0
 private MemberReference HandleMethodReference(Cts.MethodDesc method)
 {
     Debug.Assert(method.IsTypicalMethodDefinition);
     Debug.Assert(!_policy.GeneratesMetadata(method));
     return((MemberReference)_methods.GetOrCreate(method, _initMethodRef ?? (_initMethodRef = InitializeMethodReference)));
 }
Beispiel #60
0
        private void InitializeTypeDef(Cts.MetadataType entity, TypeDefinition record)
        {
            Debug.Assert(entity.IsTypeDefinition);

            Cts.MetadataType containingType = (Cts.MetadataType)entity.ContainingType;
            if (containingType != null)
            {
                var enclosingType = (TypeDefinition)HandleType(containingType);
                record.EnclosingType = enclosingType;
                enclosingType.NestedTypes.Add(record);

                var namespaceDefinition =
                    HandleNamespaceDefinition(containingType.Module, entity.ContainingType.Namespace);
                record.NamespaceDefinition = namespaceDefinition;
            }
            else
            {
                var namespaceDefinition = HandleNamespaceDefinition(entity.Module, entity.Namespace);
                record.NamespaceDefinition = namespaceDefinition;
                namespaceDefinition.TypeDefinitions.Add(record);
            }

            record.Name = HandleString(entity.Name);

            Cts.ClassLayoutMetadata layoutMetadata = entity.GetClassLayout();
            record.Size        = checked ((uint)layoutMetadata.Size);
            record.PackingSize = checked ((ushort)layoutMetadata.PackingSize);
            record.Flags       = GetTypeAttributes(entity);

            if (entity.HasBaseType)
            {
                record.BaseType = HandleType(entity.BaseType);
            }

            record.Interfaces.Capacity = entity.ExplicitlyImplementedInterfaces.Length;
            foreach (var interfaceType in entity.ExplicitlyImplementedInterfaces)
            {
                if (IsBlocked(interfaceType))
                {
                    continue;
                }
                record.Interfaces.Add(HandleType(interfaceType));
            }

            if (entity.HasInstantiation)
            {
                record.GenericParameters.Capacity = entity.Instantiation.Length;
                foreach (var p in entity.Instantiation)
                {
                    record.GenericParameters.Add(HandleGenericParameter((Cts.GenericParameterDesc)p));
                }
            }

            foreach (var field in entity.GetFields())
            {
                if (_policy.GeneratesMetadata(field))
                {
                    record.Fields.Add(HandleFieldDefinition(field));
                }
            }

            foreach (var method in entity.GetMethods())
            {
                if (_policy.GeneratesMetadata(method))
                {
                    record.Methods.Add(HandleMethodDefinition(method));
                }
            }

            var ecmaEntity = entity as Cts.Ecma.EcmaType;

            if (ecmaEntity != null)
            {
                Ecma.TypeDefinition ecmaRecord = ecmaEntity.MetadataReader.GetTypeDefinition(ecmaEntity.Handle);

                foreach (var e in ecmaRecord.GetEvents())
                {
                    Event evt = HandleEvent(ecmaEntity.EcmaModule, e);
                    if (evt != null)
                    {
                        record.Events.Add(evt);
                    }
                }

                foreach (var property in ecmaRecord.GetProperties())
                {
                    Property prop = HandleProperty(ecmaEntity.EcmaModule, property);
                    if (prop != null)
                    {
                        record.Properties.Add(prop);
                    }
                }

                Ecma.CustomAttributeHandleCollection customAttributes = ecmaRecord.GetCustomAttributes();
                if (customAttributes.Count > 0)
                {
                    record.CustomAttributes = HandleCustomAttributes(ecmaEntity.EcmaModule, customAttributes);
                }

                foreach (var miHandle in ecmaRecord.GetMethodImplementations())
                {
                    Ecma.MetadataReader reader = ecmaEntity.EcmaModule.MetadataReader;

                    Ecma.MethodImplementation miDef = reader.GetMethodImplementation(miHandle);

                    Cts.MethodDesc methodBody = (Cts.MethodDesc)ecmaEntity.EcmaModule.GetObject(miDef.MethodBody);
                    if (_policy.IsBlocked(methodBody))
                    {
                        continue;
                    }

                    Cts.MethodDesc methodDecl = (Cts.MethodDesc)ecmaEntity.EcmaModule.GetObject(miDef.MethodDeclaration);
                    if (_policy.IsBlocked(methodDecl.GetTypicalMethodDefinition()))
                    {
                        continue;
                    }

                    MethodImpl methodImplRecord = new MethodImpl
                    {
                        MethodBody        = HandleQualifiedMethod(methodBody),
                        MethodDeclaration = HandleQualifiedMethod(methodDecl)
                    };

                    record.MethodImpls.Add(methodImplRecord);
                }
            }
        }