private bool CompareTypeSigs(ref NativeParser parser1, ref NativeParser parser2)
        {
            // startOffset lets us backtrack to the TypeSignatureKind for external types since the TypeLoader
            // expects to read it in.
            uint data1;
            uint startOffset1 = parser1.Offset;
            var typeSignatureKind1 = parser1.GetTypeSignatureKind(out data1);

            // If the parser is at a lookback type, get a new parser for it and recurse.
            // Since we haven't read the element type of parser2 yet, we just pass it in unchanged
            if (typeSignatureKind1 == TypeSignatureKind.Lookback)
            {
                NativeParser lookbackParser1 = parser1.GetLookbackParser(data1);
                return CompareTypeSigs(ref lookbackParser1, ref parser2);
            }

            uint data2;
            uint startOffset2 = parser2.Offset;
            var typeSignatureKind2 = parser2.GetTypeSignatureKind(out data2);

            // If parser2 is a lookback type, we need to rewind parser1 to its startOffset1
            // before recursing.
            if (typeSignatureKind2 == TypeSignatureKind.Lookback)
            {
                NativeParser lookbackParser2 = parser2.GetLookbackParser(data2);
                parser1 = new NativeParser(parser1.Reader, startOffset1);
                return CompareTypeSigs(ref parser1, ref lookbackParser2);
            }

            if (typeSignatureKind1 != typeSignatureKind2)
                return false;

            switch (typeSignatureKind1)
            {
                case TypeSignatureKind.Lookback:
                    {
                        //  Recursion above better have removed all lookbacks
                        Debug.Assert(false, "Unexpected lookback type");
                        return false;
                    }

                case TypeSignatureKind.Modifier:
                    {
                        // Ensure the modifier kind (vector, pointer, byref) is the same
                        if (data1 != data2)
                            return false;
                        return CompareTypeSigs(ref parser1, ref parser2);
                    }

                case TypeSignatureKind.Variable:
                    {
                        // variable index is in data
                        if (data1 != data2)
                            return false;
                        break;
                    }

                case TypeSignatureKind.MultiDimArray:
                    {
                        // rank is in data
                        if (data1 != data2)
                            return false;

                        if (!CompareTypeSigs(ref parser1, ref parser2))
                            return false;

                        uint boundCount1 = parser1.GetUnsigned();
                        uint boundCount2 = parser2.GetUnsigned();
                        if (boundCount1 != boundCount2)
                            return false;

                        for (uint i = 0; i < boundCount1; i++)
                        {
                            if (parser1.GetUnsigned() != parser2.GetUnsigned())
                                return false;
                        }

                        uint lowerBoundCount1 = parser1.GetUnsigned();
                        uint lowerBoundCount2 = parser2.GetUnsigned();
                        if (lowerBoundCount1 != lowerBoundCount2)
                            return false;

                        for (uint i = 0; i < lowerBoundCount1; i++)
                        {
                            if (parser1.GetUnsigned() != parser2.GetUnsigned())
                                return false;
                        }
                        break;
                    }

                case TypeSignatureKind.FunctionPointer:
                    {
                        // callingConvention is in data
                        if (data1 != data2)
                            return false;
                        uint argCount1 = parser1.GetUnsigned();
                        uint argCount2 = parser2.GetUnsigned();
                        if (argCount1 != argCount2)
                            return false;
                        for (uint i = 0; i < argCount1; i++)
                        {
                            if (!CompareTypeSigs(ref parser1, ref parser2))
                                return false;
                        }
                        break;
                    }

                case TypeSignatureKind.Instantiation:
                    {
                        // Type parameter count is in data
                        if (data1 != data2)
                            return false;

                        if (!CompareTypeSigs(ref parser1, ref parser2))
                            return false;

                        for (uint i = 0; i < data1; i++)
                        {
                            if (!CompareTypeSigs(ref parser1, ref parser2))
                                return false;
                        }
                        break;
                    }

                case TypeSignatureKind.External:
                    {
                        RuntimeTypeHandle typeHandle1 = GetExternalTypeHandle(ref parser1, data1);
                        RuntimeTypeHandle typeHandle2 = GetExternalTypeHandle(ref parser2, data2);
                        if (!typeHandle1.Equals(typeHandle2))
                            return false;

                        break;
                    }

                default:
                    return false;
            }
            return true;
        }
        /// <summary>
        /// IF THESE SEMANTICS EVER CHANGE UPDATE THE LOGIC WHICH DEFINES THIS BEHAVIOR IN 
        /// THE DYNAMIC TYPE LOADER AS WELL AS THE COMPILER. 
        ///
        /// Parameter's are considered to have type layout dependent on their generic instantiation
        /// if the type of the parameter in its signature is a type variable, or if the type is a generic 
        /// structure which meets 2 characteristics:
        /// 1. Structure size/layout is affected by the size/layout of one or more of its generic parameters
        /// 2. One or more of the generic parameters is a type variable, or a generic structure which also recursively
        ///    would satisfy constraint 2. (Note, that in the recursion case, whether or not the structure is affected
        ///    by the size/layout of its generic parameters is not investigated.)
        ///    
        /// Examples parameter types, and behavior.
        /// 
        /// T -> true
        /// List<T> -> false
        /// StructNotDependentOnArgsForSize<T> -> false
        /// GenStructDependencyOnArgsForSize<T> -> true
        /// StructNotDependentOnArgsForSize<GenStructDependencyOnArgsForSize<T>> -> true
        /// StructNotDependentOnArgsForSize<GenStructDependencyOnArgsForSize<List<T>>>> -> false
        /// 
        /// Example non-parameter type behavior
        /// T -> true
        /// List<T> -> false
        /// StructNotDependentOnArgsForSize<T> -> *true*
        /// GenStructDependencyOnArgsForSize<T> -> true
        /// StructNotDependentOnArgsForSize<GenStructDependencyOnArgsForSize<T>> -> true
        /// StructNotDependentOnArgsForSize<GenStructDependencyOnArgsForSize<List<T>>>> -> false
        /// </summary>
        private bool TypeSignatureHasVarsNeedingCallingConventionConverter(ref NativeParser parser, TypeSystemContext context, HasVarsInvestigationLevel investigationLevel)
        {
            uint data;
            var kind = parser.GetTypeSignatureKind(out data);

            switch (kind)
            {
                case TypeSignatureKind.External: return false;
                case TypeSignatureKind.Variable: return true;

                case TypeSignatureKind.Lookback:
                    {
                        var lookbackParser = parser.GetLookbackParser(data);
                        return TypeSignatureHasVarsNeedingCallingConventionConverter(ref lookbackParser, context, investigationLevel);
                    }

                case TypeSignatureKind.Instantiation:
                    {
                        RuntimeTypeHandle genericTypeDef;
                        if (!TryGetTypeFromSimpleTypeSignature(ref parser, out genericTypeDef))
                        {
                            Debug.Assert(false);
                            return true;    // Returning true will prevent further reading from the native parser
                        }

                        if (!RuntimeAugments.IsValueType(genericTypeDef))
                        {
                            // Reference types are treated like pointers. No calling convention conversion needed. Just consume the rest of the signature.
                            for (uint i = 0; i < data; i++)
                                TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, context, HasVarsInvestigationLevel.Ignore);
                            return false;
                        }
                        else
                        {
                            bool result = false;
                            for (uint i = 0; i < data; i++)
                                result = TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, context, HasVarsInvestigationLevel.NotParameter) || result;

                            if ((result == true) && (investigationLevel == HasVarsInvestigationLevel.Parameter))
                            {
                                if (!TryComputeHasInstantiationDeterminedSize(genericTypeDef, context, out result))
                                    Environment.FailFast("Unable to setup calling convention converter correctly");

                                return result;
                            }

                            return result;
                        }
                    }

                case TypeSignatureKind.Modifier:
                    {
                        // Arrays, pointers and byref types signatures are treated as pointers, not requiring calling convention conversion.
                        // Just consume the parameter type from the stream and return false;
                        TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, context, HasVarsInvestigationLevel.Ignore);
                        return false;
                    }

                case TypeSignatureKind.MultiDimArray:
                    {
                        // No need for a calling convention converter for this case. Just consume the signature from the stream.

                        TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, context, HasVarsInvestigationLevel.Ignore);

                        uint boundCount = parser.GetUnsigned();
                        for (uint i = 0; i < boundCount; i++)
                            parser.GetUnsigned();

                        uint lowerBoundCount = parser.GetUnsigned();
                        for (uint i = 0; i < lowerBoundCount; i++)
                            parser.GetUnsigned();
                    }
                    return false;

                case TypeSignatureKind.FunctionPointer:
                    {
                        // No need for a calling convention converter for this case. Just consume the signature from the stream.

                        uint argCount = parser.GetUnsigned();
                        for (uint i = 0; i < argCount; i++)
                            TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, context, HasVarsInvestigationLevel.Ignore);
                    }
                    return false;

                default:
                    parser.ThrowBadImageFormatException();
                    return true;
            }
        }
        private bool TryGetTypeFromSimpleTypeSignature(ref NativeParser parser, out RuntimeTypeHandle typeHandle)
        {
            uint data;
            TypeSignatureKind kind = parser.GetTypeSignatureKind(out data);

            if (kind == TypeSignatureKind.Lookback)
            {
                var lookbackParser = parser.GetLookbackParser(data);
                return TryGetTypeFromSimpleTypeSignature(ref lookbackParser, out typeHandle);
            }
            else if (kind == TypeSignatureKind.External)
            {
                typeHandle = GetExternalTypeHandle(ref parser, data);
                return true;
            }

            // Not a simple type signature... requires more work to skip
            typeHandle = default(RuntimeTypeHandle);
            return false;
        }
        internal TypeDesc GetType(ref NativeParser parser)
        {
            uint data;
            var kind = parser.GetTypeSignatureKind(out data);

            switch (kind)
            {
                case TypeSignatureKind.Lookback:
                    return GetLookbackType(ref parser, data);

                case TypeSignatureKind.Variable:
                    uint index = data >> 1;
                    return (((data & 0x1) != 0) ? _methodArgumentHandles : _typeArgumentHandles)[checked((int)index)];

                case TypeSignatureKind.Instantiation:
                    return GetInstantiationType(ref parser, data);

                case TypeSignatureKind.Modifier:
                    return GetModifierType(ref parser, (TypeModifierKind)data);

                case TypeSignatureKind.External:
                    return GetExternalType(data);

                case TypeSignatureKind.MultiDimArray:
                    {
                        DefType elementType = (DefType)GetType(ref parser);
                        int rank = (int)data;

                        // Skip encoded bounds and lobounds
                        uint boundsCount = parser.GetUnsigned();
                        while (boundsCount > 0)
                            parser.GetUnsigned();

                        uint loBoundsCount = parser.GetUnsigned();
                        while (loBoundsCount > 0)
                            parser.GetUnsigned();

                        return _typeSystemContext.GetArrayType(elementType, rank);
                    }

                case TypeSignatureKind.FunctionPointer:
                    Debug.Assert(false, "NYI!");
                    parser.ThrowBadImageFormatException();
                    return null;

                default:
                    parser.ThrowBadImageFormatException();
                    return null;
            }
        }