1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using Cts = Internal.TypeSystem;
6 using Debug = System.Diagnostics.Debug;
7 
8 namespace ILCompiler.Metadata
9 {
10     /// <summary>
11     /// Provides implementation of the <see cref="MetadataTransform"/> contract.
12     /// This class is generic over the policy to make policy lookups cheap (policy being
13     /// a struct means all the interface calls end up being constrained over the type
14     /// and therefore fully inlineable).
15     /// </summary>
16     internal sealed partial class Transform<TPolicy> : MetadataTransform
17         where TPolicy : struct, IMetadataPolicy
18     {
19         private TPolicy _policy;
20 
Transform(TPolicy policy)21         public Transform(TPolicy policy)
22         {
23             _policy = policy;
24         }
25 
IsBlocked(Cts.TypeDesc type)26         private bool IsBlocked(Cts.TypeDesc type)
27         {
28             switch (type.Category)
29             {
30                 case Cts.TypeFlags.SzArray:
31                 case Cts.TypeFlags.Array:
32                 case Cts.TypeFlags.Pointer:
33                 case Cts.TypeFlags.ByRef:
34                     return IsBlocked(((Cts.ParameterizedType)type).ParameterType);
35 
36                 case Cts.TypeFlags.SignatureMethodVariable:
37                 case Cts.TypeFlags.SignatureTypeVariable:
38                     return false;
39 
40                 case Cts.TypeFlags.FunctionPointer:
41                     {
42                         Cts.MethodSignature pointerSignature = ((Cts.FunctionPointerType)type).Signature;
43                         if (IsBlocked(pointerSignature.ReturnType))
44                             return true;
45 
46                         for (int i = 0; i < pointerSignature.Length; i++)
47                             if (IsBlocked(pointerSignature[i]))
48                                 return true;
49 
50                         return false;
51                     }
52                 default:
53                     Debug.Assert(type.IsDefType);
54 
55                     if (!type.IsTypeDefinition)
56                     {
57                         if (IsBlocked(type.GetTypeDefinition()))
58                             return true;
59 
60                         foreach (var arg in type.Instantiation)
61                             if (IsBlocked(arg))
62                                 return true;
63 
64                         return false;
65                     }
66 
67                     return _policy.IsBlocked((Cts.MetadataType)type);
68             }
69         }
70     }
71 }
72