Пример #1
0
        /// <summary>
        /// Checks if two types are compatible according to compatible-with as described in ECMA 335 I.8.7.1
        /// Most of the checks are performed by the CanCastTo, but some cases are pre-filtered out.
        /// </summary>
        public static bool IsCompatibleWith(this TypeDesc thisType, TypeDesc otherType)
        {
            // Structs can be cast to the interfaces they implement, but they are not compatible according to ECMA I.8.7.1
            bool isCastFromValueTypeToReferenceType = otherType.IsValueType && !thisType.IsValueType;

            if (isCastFromValueTypeToReferenceType)
            {
                return(false);
            }

            // Managed pointers are compatible only if they are pointer-element-compatible-with as described in ECMA I.8.7.2
            if (thisType.IsByRef && otherType.IsByRef)
            {
                return(AreVerificationTypesEqual(thisType.GetParameterType(), otherType.GetParameterType()));
            }

            // Unmanaged pointers are handled the same way as managed pointers
            if (thisType.IsPointer && otherType.IsPointer)
            {
                return(AreVerificationTypesEqual(thisType.GetParameterType(), otherType.GetParameterType()));
            }

            // Function pointers are compatible only if they are method-signature-compatible-with as described in ECMA I.8.7.1
            if (thisType.IsFunctionPointer && otherType.IsFunctionPointer)
            {
                return(IsMethodSignatureCompatibleWith(thisType, otherType));
            }

            // None of the types can be a managed pointer, a pointer or a function pointer here,
            // all the valid cases were handled above.
            if (thisType.IsByRef || otherType.IsByRef ||
                thisType.IsPointer || otherType.IsPointer ||
                thisType.IsFunctionPointer || otherType.IsFunctionPointer)
            {
                return(false);
            }

            // Nullable<T> can be cast to T, but this is not compatible according to ECMA I.8.7.1
            bool isCastFromNullableOfTtoT = thisType.IsNullable && otherType.IsEquivalentTo(thisType.Instantiation[0]);

            if (isCastFromNullableOfTtoT)
            {
                return(false);
            }

            return(otherType.CanCastTo(thisType));
        }
Пример #2
0
        //
        //  Struct Marshalling
        //  To support struct marshalling compiler needs to generate a native type which
        //  imitates the original struct being passed to managed side with corresponding
        //  fields of marshalled types. Additionally it needs to generate three thunks
        //      1. Managed to Native Thunk: For forward marshalling
        //      2. Native to Managed Thunk: For reverse marshalling
        //      3. Cleanup Thunk: for cleaning up any allocated resources
        //
        /// <summary>
        /// Generates a Native struct type which imitates the managed struct
        /// </summary>
        public NativeStructType GetStructMarshallingNativeType(TypeDesc managedType)
        {
            if (managedType is ByRefType)
            {
                managedType = managedType.GetParameterType();
            }

            Debug.Assert(managedType is MetadataType);

            return(_nativeStructHashtable.GetOrCreateValue((MetadataType)managedType));
        }
Пример #3
0
        public PInvokeDelegateWrapper GetPInvokeDelegateWrapper(TypeDesc delegateType)
        {
            if (delegateType is ByRefType)
            {
                delegateType = delegateType.GetParameterType();
            }

            Debug.Assert(delegateType is MetadataType);

            // Get the Type that wraps the native function
            return(_pInvokeDelegateWrapperHashtable.GetOrCreateValue((MetadataType)delegateType));
        }
Пример #4
0
        /// <summary>
        /// Generates thunk for creating delegate
        /// </summary>
        public ForwardDelegateCreationThunk GetForwardDelegateCreationThunk(TypeDesc delegateType)
        {
            if (delegateType is ByRefType)
            {
                delegateType = delegateType.GetParameterType();
            }

            Debug.Assert(delegateType is MetadataType);

            // Get the stub for creating delegate
            return(_forwardDelegateCreationStubHashtable.GetOrCreateValue((MetadataType)delegateType));
        }
Пример #5
0
        /// <summary>
        ///  Generates a thunk to marshal the fields of the struct from native to managed
        /// </summary>
        public MethodDesc GetStructMarshallingNativeToManagedThunk(TypeDesc managedType)
        {
            if (managedType is ByRefType)
            {
                managedType = managedType.GetParameterType();
            }

            Debug.Assert(managedType is MetadataType);

            var methodKey = new StructMarshallingThunkKey((MetadataType)managedType, StructMarshallingThunkType.NativeToManaged);

            return(_structMarshallingThunkHashtable.GetOrCreateValue(methodKey));
        }
Пример #6
0
        /// <summary>
        /// Generates marshalling stubs for closed instance delegates
        /// </summary>
        public DelegateMarshallingMethodThunk GetClosedDelegateMarshallingThunk(TypeDesc delegateType)
        {
            if (delegateType is ByRefType)
            {
                delegateType = delegateType.GetParameterType();
            }

            Debug.Assert(delegateType is MetadataType);


            // Get the stub for marshalling open static delegate
            var stubKey = new DelegateMarshallingStubHashtableKey((MetadataType)delegateType, DelegateMarshallingMethodThunkKind.ReverseClosed);

            return(_delegateMarshallingThunkHashtable.GetOrCreateValue(stubKey));
        }
        private void EncodeType(BlobBuilder blobBuilder, TypeDesc type, EmbeddedSignatureDataEmitter signatureDataEmitter)
        {
            signatureDataEmitter.Push();
            signatureDataEmitter.Push();
            signatureDataEmitter.EmitAtCurrentIndexStack(blobBuilder);
            signatureDataEmitter.Pop();

            signatureDataEmitter.Push();
            if (type.IsPrimitive)
            {
                SignatureTypeCode primitiveCode;
                switch (type.Category)
                {
                case TypeFlags.Void:
                    primitiveCode = SignatureTypeCode.Void;
                    break;

                case TypeFlags.Boolean:
                    primitiveCode = SignatureTypeCode.Boolean;
                    break;

                case TypeFlags.Char:
                    primitiveCode = SignatureTypeCode.Char;
                    break;

                case TypeFlags.SByte:
                    primitiveCode = SignatureTypeCode.SByte;
                    break;

                case TypeFlags.Byte:
                    primitiveCode = SignatureTypeCode.Byte;
                    break;

                case TypeFlags.Int16:
                    primitiveCode = SignatureTypeCode.Int16;
                    break;

                case TypeFlags.UInt16:
                    primitiveCode = SignatureTypeCode.UInt16;
                    break;

                case TypeFlags.Int32:
                    primitiveCode = SignatureTypeCode.Int32;
                    break;

                case TypeFlags.UInt32:
                    primitiveCode = SignatureTypeCode.UInt32;
                    break;

                case TypeFlags.Int64:
                    primitiveCode = SignatureTypeCode.Int64;
                    break;

                case TypeFlags.UInt64:
                    primitiveCode = SignatureTypeCode.UInt64;
                    break;

                case TypeFlags.IntPtr:
                    primitiveCode = SignatureTypeCode.IntPtr;
                    break;

                case TypeFlags.UIntPtr:
                    primitiveCode = SignatureTypeCode.UIntPtr;
                    break;

                case TypeFlags.Single:
                    primitiveCode = SignatureTypeCode.Single;
                    break;

                case TypeFlags.Double:
                    primitiveCode = SignatureTypeCode.Double;
                    break;

                default:
                    throw new Exception("Unknown primitive type");
                }

                blobBuilder.WriteByte((byte)primitiveCode);
            }
            else if (type.IsSzArray)
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.SZArray);
                EncodeType(blobBuilder, type.GetParameterType(), signatureDataEmitter);
            }
            else if (type.IsArray)
            {
                var arrayType = (ArrayType)type;
                blobBuilder.WriteByte((byte)SignatureTypeCode.Array);
                EncodeType(blobBuilder, type.GetParameterType(), signatureDataEmitter);

                signatureDataEmitter.EmitArrayShapeAtCurrentIndexStack(blobBuilder, arrayType.Rank);
            }
            else if (type.IsPointer)
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.Pointer);
                EncodeType(blobBuilder, type.GetParameterType(), signatureDataEmitter);
            }
            else if (type.IsFunctionPointer)
            {
                FunctionPointerType fnptrType = (FunctionPointerType)type;
                blobBuilder.WriteByte((byte)SignatureTypeCode.FunctionPointer);
                EncodeMethodSignature(blobBuilder, fnptrType.Signature, signatureDataEmitter);
            }
            else if (type.IsByRef)
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.ByReference);
                EncodeType(blobBuilder, type.GetParameterType(), signatureDataEmitter);
            }
            else if (type.IsObject)
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.Object);
            }
            else if (type.IsString)
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.String);
            }
            else if (type.IsWellKnownType(WellKnownType.TypedReference))
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.TypedReference);
            }
            else if (type.IsWellKnownType(WellKnownType.Void))
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.Void);
            }
            else if (type is SignatureVariable)
            {
                SignatureVariable sigVar = (SignatureVariable)type;
                SignatureTypeCode code   = sigVar.IsMethodSignatureVariable ? SignatureTypeCode.GenericMethodParameter : SignatureTypeCode.GenericTypeParameter;
                blobBuilder.WriteByte((byte)code);
                blobBuilder.WriteCompressedInteger(sigVar.Index);
            }
            else if (type is InstantiatedType)
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.GenericTypeInstance);
                EncodeType(blobBuilder, type.GetTypeDefinition(), signatureDataEmitter);
                blobBuilder.WriteCompressedInteger(type.Instantiation.Length);
                foreach (var instantiationArg in type.Instantiation)
                {
                    EncodeType(blobBuilder, instantiationArg, signatureDataEmitter);
                }
            }
            else if (type is MetadataType)
            {
                var metadataType = (MetadataType)type;
                // Must be class or valuetype
                blobBuilder.WriteByte(type.IsValueType ? (byte)SignatureTypeKind.ValueType : (byte)SignatureTypeKind.Class);
                int codedIndex = CodedIndex.TypeDefOrRef(GetTypeRef(metadataType));
                blobBuilder.WriteCompressedInteger(codedIndex);
            }
            else
            {
                throw new Exception("Unexpected type");
            }
            signatureDataEmitter.Pop();
            signatureDataEmitter.Pop();
        }