Beispiel #1
0
        bool IsAssignable(StackValue src, StackValue dst)
        {
            if (src.Kind == dst.Kind && src.Type == dst.Type)
            {
                return(true);
            }

            if (dst.Type == null)
            {
                return(false);
            }

            switch (src.Kind)
            {
            case StackValueKind.ObjRef:
                if (dst.Kind != StackValueKind.ObjRef)
                {
                    return(false);
                }

                // null is always assignable
                if (src.Type == null)
                {
                    return(true);
                }

                return(CastingHelper.CanCastTo(src.Type, dst.Type));

            case StackValueKind.ValueType:

                // TODO: Other cases - variance, etc.

                return(false);

            case StackValueKind.ByRef:

                // TODO: Other cases - variance, etc.

                return(false);

            case StackValueKind.Int32:
                return(dst.Kind == StackValueKind.Int64 || dst.Kind == StackValueKind.NativeInt);

            case StackValueKind.Int64:
                return(false);

            case StackValueKind.NativeInt:
                return(dst.Kind == StackValueKind.Int64);

            case StackValueKind.Float:
                return(false);

            default:
                // TODO:
                // return false;
                throw new NotImplementedException();
            }

#if false
            if (child == parent)
            {
                return(TRUE);
            }

            // Normally we just let the runtime sort it out but we wish to be more strict
            // than the runtime wants to be.  For backwards compatibility, the runtime considers
            // int32[] and nativeInt[] to be the same on 32-bit machines.  It also is OK with
            // int64[] and nativeInt[] on a 64-bit machine.

            if (child.IsType(TI_REF) && parent.IsType(TI_REF) &&
                jitInfo->isSDArray(child.GetClassHandleForObjRef()) &&
                jitInfo->isSDArray(parent.GetClassHandleForObjRef()))
            {
                BOOL runtime_OK;

                // never be more lenient than the runtime
                runtime_OK = jitInfo->canCast(child.m_cls, parent.m_cls);
                if (!runtime_OK)
                {
                    return(false);
                }

                CORINFO_CLASS_HANDLE handle;
                CorInfoType          pType = jitInfo->getChildType(child.GetClassHandleForObjRef(), &handle);
                CorInfoType          cType = jitInfo->getChildType(parent.GetClassHandleForObjRef(), &handle);

                // don't care whether it is signed
                if (cType == CORINFO_TYPE_NATIVEUINT)
                {
                    cType = CORINFO_TYPE_NATIVEINT;
                }
                if (pType == CORINFO_TYPE_NATIVEUINT)
                {
                    pType = CORINFO_TYPE_NATIVEINT;
                }

                if (cType == CORINFO_TYPE_NATIVEINT)
                {
                    return(pType == CORINFO_TYPE_NATIVEINT);
                }

                if (pType == CORINFO_TYPE_NATIVEINT)
                {
                    return(cType == CORINFO_TYPE_NATIVEINT);
                }

                return(runtime_OK);
            }

            if (parent.IsUnboxedGenericTypeVar() || child.IsUnboxedGenericTypeVar())
            {
                return(FALSE); // need to have had child == parent
            }
            else if (parent.IsType(TI_REF))
            {
                // An uninitialized objRef is not compatible to initialized.
                if (child.IsUninitialisedObjRef() && !parent.IsUninitialisedObjRef())
                {
                    return(FALSE);
                }

                if (child.IsNullObjRef())           // NULL can be any reference type
                {
                    return(TRUE);
                }
                if (!child.IsType(TI_REF))
                {
                    return(FALSE);
                }

                return(jitInfo->canCast(child.m_cls, parent.m_cls));
            }
            else if (parent.IsType(TI_METHOD))
            {
                if (!child.IsType(TI_METHOD))
                {
                    return(FALSE);
                }

                // Right now we don't bother merging method handles
                return(FALSE);
            }
            else if (parent.IsType(TI_STRUCT))
            {
                if (!child.IsType(TI_STRUCT))
                {
                    return(FALSE);
                }

                // Structures are compatible if they are equivalent
                return(jitInfo->areTypesEquivalent(child.m_cls, parent.m_cls));
            }
            else if (parent.IsByRef())
            {
                return(tiCompatibleWithByRef(jitInfo, child, parent));
            }

            return(FALSE);
#endif
        }
Beispiel #2
0
        bool IsBinaryComparable(StackValue src, StackValue dst, ILOpcode op)
        {
            if (src.Kind == dst.Kind && src.Type == dst.Type)
            {
                return(true);
            }

            switch (src.Kind)
            {
            case StackValueKind.ObjRef:
                switch (dst.Kind)
                {
                case StackValueKind.ObjRef:
                    // ECMA-335 III.1.5 Operand type table, P. 303:
                    // __cgt.un__ is allowed and verifiable on ObjectRefs (O). This is commonly used when
                    // comparing an ObjectRef with null(there is no "compare - not - equal" instruction, which
                    // would otherwise be a more obvious solution)
                    return(op == ILOpcode.beq || op == ILOpcode.beq_s ||
                           op == ILOpcode.bne_un || op == ILOpcode.bne_un_s ||
                           op == ILOpcode.ceq || op == ILOpcode.cgt_un);

                default:
                    return(false);
                }

            case StackValueKind.ValueType:
                return(false);

            case StackValueKind.ByRef:
                switch (dst.Kind)
                {
                case StackValueKind.ByRef:
                    return(true);

                case StackValueKind.NativeInt:
                    return(op == ILOpcode.beq || op == ILOpcode.beq_s ||
                           op == ILOpcode.bne_un || op == ILOpcode.bne_un_s ||
                           op == ILOpcode.ceq);

                default:
                    return(false);
                }

            case StackValueKind.Int32:
                return(dst.Kind == StackValueKind.Int64 || dst.Kind == StackValueKind.NativeInt);

            case StackValueKind.Int64:
                return(dst.Kind == StackValueKind.Int64);

            case StackValueKind.NativeInt:
                switch (dst.Kind)
                {
                case StackValueKind.Int32:
                case StackValueKind.NativeInt:
                    return(true);

                case StackValueKind.ByRef:
                    return(op == ILOpcode.beq || op == ILOpcode.beq_s ||
                           op == ILOpcode.bne_un || op == ILOpcode.bne_un_s ||
                           op == ILOpcode.ceq);

                default:
                    return(false);
                }

            case StackValueKind.Float:
                return(dst.Kind == StackValueKind.Float);

            default:
                throw new NotImplementedException();
            }
        }
        bool IsBinaryComparable(StackValue src, StackValue dst, ILOpcode op)
        {
            if (src.Kind == dst.Kind && src.Type == dst.Type)
            {
                return(true);
            }

            switch (src.Kind)
            {
            case StackValueKind.ObjRef:
                switch (dst.Kind)
                {
                case StackValueKind.ObjRef:
                    return(op == ILOpcode.beq || op == ILOpcode.beq_s ||
                           op == ILOpcode.bne_un || op == ILOpcode.bne_un_s ||
                           op == ILOpcode.ceq);

                default:
                    return(false);
                }

            case StackValueKind.ValueType:
                return(false);

            case StackValueKind.ByRef:
                switch (dst.Kind)
                {
                case StackValueKind.ByRef:
                    return(true);

                case StackValueKind.NativeInt:
                    return(op == ILOpcode.beq || op == ILOpcode.beq_s ||
                           op == ILOpcode.bne_un || op == ILOpcode.bne_un_s ||
                           op == ILOpcode.ceq);

                default:
                    return(false);
                }

            case StackValueKind.Int32:
                return(dst.Kind == StackValueKind.Int64 || dst.Kind == StackValueKind.NativeInt);

            case StackValueKind.Int64:
                return(dst.Kind == StackValueKind.Int64);

            case StackValueKind.NativeInt:
                switch (dst.Kind)
                {
                case StackValueKind.Int32:
                case StackValueKind.NativeInt:
                    return(true);

                case StackValueKind.ByRef:
                    return(op == ILOpcode.beq || op == ILOpcode.beq_s ||
                           op == ILOpcode.bne_un || op == ILOpcode.bne_un_s ||
                           op == ILOpcode.ceq);

                default:
                    return(false);
                }

            case StackValueKind.Float:
                return(dst.Kind == StackValueKind.Float);

            default:
                throw new NotImplementedException();
            }
        }