| File: Compiler\ReadyToRunLibraryRootProvider.cs | Web Access |
| Project: src\runtime\src\coreclr\tools\aot\ILCompiler.ReadyToRun\ILCompiler.ReadyToRun.csproj (ILCompiler.ReadyToRun) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using Internal.TypeSystem.Ecma; using Internal.TypeSystem; using Internal.JitInterface; using System.Reflection.Metadata; namespace ILCompiler { /// <summary> /// Roots all methods in the input IL module. /// </summary> public class ReadyToRunLibraryRootProvider : ICompilationRootProvider { private EcmaModule _module; private InstructionSetSupport _instructionSetSupport; public ReadyToRunLibraryRootProvider(EcmaModule module) { _module = module; _instructionSetSupport = ((ReadyToRunCompilerContext)module.Context).InstructionSetSupport; } public void AddCompilationRoots(IRootingServiceProvider rootProvider) { foreach (MetadataType type in _module.GetAllTypes()) { MetadataType typeWithMethods = type; if (type.HasInstantiation) { typeWithMethods = InstantiateIfPossible(type); if (typeWithMethods == null) continue; } RootMethods(typeWithMethods, "Library module method", rootProvider); } } private void RootMethods(MetadataType type, string reason, IRootingServiceProvider rootProvider) { foreach (MethodDesc method in type.GetAllMethods()) { // Skip methods with no IL if (method.IsAbstract) continue; if (method.IsInternalCall) continue; MethodDesc methodToRoot = method; if (method.HasInstantiation) { methodToRoot = InstantiateIfPossible(method); if (methodToRoot == null) continue; } try { if (!CorInfoImpl.ShouldSkipCompilation(_instructionSetSupport, method)) { CheckCanGenerateMethod(methodToRoot); rootProvider.AddCompilationRoot(methodToRoot, rootMinimalDependencies: false, reason: reason); } } catch (TypeSystemException) { // Individual methods can fail to load types referenced in their signatures. // Skip them in library mode since they're not going to be callable. continue; } } } /// <summary> /// Validates that it will be possible to generate '<paramref name="method"/>' based on the types /// in its signature. Unresolvable types in a method's signature prevent RyuJIT from generating /// even a stubbed out throwing implementation. /// </summary> public static void CheckCanGenerateMethod(MethodDesc method) { // Ensure the method is loadable ((CompilerTypeSystemContext)method.Context).EnsureLoadableMethod(method); MethodSignature signature = method.Signature; // Vararg methods are not supported in .NET Core if ((signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask) == MethodSignatureFlags.CallingConventionVarargs) ThrowHelper.ThrowBadImageFormatException(); CheckTypeCanBeUsedInSignature(signature.ReturnType); for (int i = 0; i < signature.Length; i++) { CheckTypeCanBeUsedInSignature(signature[i]); } } private static void CheckTypeCanBeUsedInSignature(TypeDesc type) { DefType defType = type as DefType; if (defType != null) { defType.ComputeTypeContainsGCPointers(); if (defType.InstanceFieldSize.IsIndeterminate) { // // If a method's signature refers to a type with an indeterminate size, // the compilation will eventually fail when we generate the GCRefMap. // // Therefore we need to avoid adding these method into the graph // ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } } ((CompilerTypeSystemContext)type.Context).EnsureLoadableType(type); } private static Instantiation GetInstantiationThatMeetsConstraints(Instantiation definition) { TypeDesc[] args = new TypeDesc[definition.Length]; for (int i = 0; i < definition.Length; i++) { GenericParameterDesc genericParameter = (GenericParameterDesc)definition[i]; // If the parameter is not constrained to be a valuetype, we can instantiate over __Canon if (genericParameter.HasNotNullableValueTypeConstraint) { return default; } args[i] = genericParameter.Context.CanonType; } return new Instantiation(args); } public static InstantiatedType InstantiateIfPossible(MetadataType type) { Instantiation inst = GetInstantiationThatMeetsConstraints(type.Instantiation); if (inst.IsNull) { return null; } return type.MakeInstantiatedType(inst); } public static MethodDesc InstantiateIfPossible(MethodDesc method) { Instantiation inst = GetInstantiationThatMeetsConstraints(method.Instantiation); if (inst.IsNull) { return null; } return method.MakeInstantiatedMethod(inst); } } }