예제 #1
0
        public ReadyToRunHelperNode(NodeFactory factory, ReadyToRunHelperId id, Object target)
        {
            _id     = id;
            _target = target;

            switch (id)
            {
            case ReadyToRunHelperId.NewHelper:
            case ReadyToRunHelperId.NewArr1:
            case ReadyToRunHelperId.IsInstanceOf:
            case ReadyToRunHelperId.CastClass:
            {
                // Make sure that if the EEType can't be generated, we throw the exception now.
                // This way we can fail generating code for the method that references the EEType
                // and (depending on the policy), we could avoid scraping the entire compilation.
                TypeDesc type = (TypeDesc)target;
                factory.NecessaryTypeSymbol(type);
            }
            break;

            case ReadyToRunHelperId.GetNonGCStaticBase:
            case ReadyToRunHelperId.GetGCStaticBase:
            case ReadyToRunHelperId.GetThreadStaticBase:
            {
                // Make sure we can compute static field layout now so we can fail early
                DefType defType = (DefType)target;
                defType.ComputeStaticFieldLayout(StaticLayoutKind.StaticRegionSizesAndFields);
            }
            break;
            }
        }
예제 #2
0
        public ReadyToRunHelperNode(ReadyToRunHelperId id, Object target)
        {
            _id     = id;
            _target = target;

            switch (id)
            {
            case ReadyToRunHelperId.GetNonGCStaticBase:
            case ReadyToRunHelperId.GetGCStaticBase:
            case ReadyToRunHelperId.GetThreadStaticBase:
            {
                // Make sure we can compute static field layout now so we can fail early
                DefType defType = (DefType)target;
                defType.ComputeStaticFieldLayout(StaticLayoutKind.StaticRegionSizesAndFields);
            }
            break;

            case ReadyToRunHelperId.VirtualCall:
            case ReadyToRunHelperId.ResolveVirtualFunction:
            {
                // Make sure we aren't trying to callvirt Object.Finalize
                MethodDesc method = (MethodDesc)target;
                if (method.IsFinalizer)
                {
                    ThrowHelper.ThrowInvalidProgramException(ExceptionStringID.InvalidProgramCallVirtFinalize, method);
                }

                // Method should be in fully canonical form. Otherwise we're being wasteful and generate more
                // helpers than needed.
                Debug.Assert(!method.IsCanonicalMethod(CanonicalFormKind.Any) ||
                             method.GetCanonMethodTarget(CanonicalFormKind.Specific) == method);
            }
            break;
            }
        }
예제 #3
0
        public ReadyToRunHelperNode(NodeFactory factory, ReadyToRunHelperId id, Object target)
        {
            _id     = id;
            _target = target;

            switch (id)
            {
            case ReadyToRunHelperId.NewHelper:
            case ReadyToRunHelperId.NewArr1:
            {
                // Make sure that if the EEType can't be generated, we throw the exception now.
                // This way we can fail generating code for the method that references the EEType
                // and (depending on the policy), we could avoid scraping the entire compilation.
                TypeDesc type = (TypeDesc)target;
                factory.ConstructedTypeSymbol(type);
            }
            break;

            case ReadyToRunHelperId.IsInstanceOf:
            case ReadyToRunHelperId.CastClass:
            {
                // Make sure that if the EEType can't be generated, we throw the exception now.
                // This way we can fail generating code for the method that references the EEType
                // and (depending on the policy), we could avoid scraping the entire compilation.
                TypeDesc type = (TypeDesc)target;
                factory.NecessaryTypeSymbol(type);

                Debug.Assert(!type.IsNullable, "Nullable needs to be unwrapped");
            }
            break;

            case ReadyToRunHelperId.GetNonGCStaticBase:
            case ReadyToRunHelperId.GetGCStaticBase:
            case ReadyToRunHelperId.GetThreadStaticBase:
            {
                // Make sure we can compute static field layout now so we can fail early
                DefType defType = (DefType)target;
                defType.ComputeStaticFieldLayout(StaticLayoutKind.StaticRegionSizesAndFields);
            }
            break;

            case ReadyToRunHelperId.VirtualCall:
            case ReadyToRunHelperId.ResolveVirtualFunction:
            {
                // Make sure we aren't trying to callvirt Object.Finalize
                MethodDesc method = (MethodDesc)target;
                if (method.IsFinalizer)
                {
                    ThrowHelper.ThrowInvalidProgramException(ExceptionStringID.InvalidProgramCallVirtFinalize, method);
                }

                // Method should be in fully canonical form. Otherwise we're being wasteful and generate more
                // helpers than needed.
                Debug.Assert(!method.IsCanonicalMethod(CanonicalFormKind.Any) ||
                             method.GetCanonMethodTarget(CanonicalFormKind.Specific) == method);
            }
            break;
            }
        }
예제 #4
0
        /// <summary>
        /// Validates that it will be possible to create an EEType for '<paramref name="type"/>'.
        /// </summary>
        public static void CheckCanGenerateEEType(NodeFactory factory, TypeDesc type)
        {
            // Don't validate generic definitons
            if (type.IsGenericDefinition)
            {
                return;
            }

            // It must be possible to create an EEType for the base type of this type
            TypeDesc baseType = type.BaseType;

            if (baseType != null)
            {
                // Make sure EEType can be created for this.
                factory.NecessaryTypeSymbol(baseType);
            }

            // We need EETypes for interfaces
            foreach (var intf in type.RuntimeInterfaces)
            {
                // Make sure EEType can be created for this.
                factory.NecessaryTypeSymbol(intf);
            }

            // Validate classes, structs, enums, interfaces, and delegates
            DefType defType = type as DefType;

            if (defType != null)
            {
                // Ensure we can compute the type layout
                defType.ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields);

                //
                // The fact that we generated an EEType means that someone can call RuntimeHelpers.RunClassConstructor.
                // We need to make sure this is possible.
                //
                if (factory.TypeSystemContext.HasLazyStaticConstructor(defType))
                {
                    defType.ComputeStaticFieldLayout(StaticLayoutKind.StaticRegionSizesAndFields);
                }

                // Make sure instantiation length matches the expectation
                // TODO: it might be more resonable for the type system to enforce this (also for methods)
                if (defType.Instantiation.Length != defType.GetTypeDefinition().Instantiation.Length)
                {
                    throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
                }

                foreach (TypeDesc typeArg in defType.Instantiation)
                {
                    // ByRefs, pointers, function pointers, and System.Void are never valid instantiation arguments
                    if (typeArg.IsByRef || typeArg.IsPointer || typeArg.IsFunctionPointer || typeArg.IsVoid)
                    {
                        throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
                    }

                    // TODO: validate constraints
                }
            }

            // Validate parameterized types
            ParameterizedType parameterizedType = type as ParameterizedType;

            if (parameterizedType != null)
            {
                TypeDesc parameterType = parameterizedType.ParameterType;

                // Make sure EEType can be created for this.
                factory.NecessaryTypeSymbol(parameterType);

                if (parameterizedType.IsArray)
                {
                    if (parameterType.IsPointer || parameterType.IsFunctionPointer)
                    {
                        // Arrays of pointers and function pointers are not currently supported
                        throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
                    }

                    int elementSize = parameterType.GetElementSize();
                    if (elementSize >= ushort.MaxValue)
                    {
                        // Element size over 64k can't be encoded in the GCDesc
                        throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadValueClassTooLarge, parameterType);
                    }
                }

                // Validate we're not constructing a type over a ByRef
                if (parameterType.IsByRef)
                {
                    // CLR compat note: "ldtoken int32&&" will actually fail with a message about int32&; "ldtoken int32&[]"
                    // will fail with a message about being unable to create an array of int32&. This is a middle ground.
                    throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
                }

                // It might seem reasonable to disallow array of void, but the CLR doesn't prevent that too hard.
                // E.g. "newarr void" will fail, but "newarr void[]" or "ldtoken void[]" will succeed.
            }

            // Function pointer EETypes are not currently supported
            if (type.IsFunctionPointer)
            {
                throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
            }
        }