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; } }
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; } }
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; } }
/// <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); } }