Welcome to mirror list, hosted at ThFree Co, Russian Federation.

HelperExtensions.cs « IL « TypeSystem « Common « tools « coreclr « src - github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 66344ff698d1624958ac92b3a9327a8fb7139fc5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;

using Internal.TypeSystem;
using Internal.IL.Stubs;

using Debug = System.Diagnostics.Debug;

namespace Internal.IL
{
    internal static class HelperExtensions
    {
        private const string HelperTypesNamespace = "Internal.Runtime.CompilerHelpers";

        public static MetadataType GetHelperType(this TypeSystemContext context, string name)
        {
            MetadataType helperType = context.SystemModule.GetKnownType(HelperTypesNamespace, name);
            return helperType;
        }

        public static MetadataType GetOptionalHelperType(this TypeSystemContext context, string name)
        {
            MetadataType helperType = context.SystemModule.GetType(HelperTypesNamespace, name, throwIfNotFound: false);
            return helperType;
        }

        public static MethodDesc GetHelperEntryPoint(this TypeSystemContext context, string typeName, string methodName)
        {
            MetadataType helperType = context.GetHelperType(typeName);
            MethodDesc helperMethod = helperType.GetKnownMethod(methodName, null);
            return helperMethod;
        }

        public static MethodDesc GetOptionalHelperEntryPoint(this TypeSystemContext context, string typeName, string methodName)
        {
            MetadataType helperType = context.GetOptionalHelperType(typeName);
            MethodDesc helperMethod = helperType?.GetMethod(methodName, null);
            return helperMethod;
        }

        /// <summary>
        /// Emits a call to a throw helper. Use this to emit calls to static parameterless methods that don't return.
        /// The advantage of using this extension method is that you don't have to deal with what code to emit after
        /// the call (e.g. do you need to make sure the stack is balanced?).
        /// </summary>
        public static void EmitCallThrowHelper(this ILCodeStream codeStream, ILEmitter emitter, MethodDesc method)
        {
            Debug.Assert(method.Signature.Length == 0 && method.Signature.IsStatic);

            // Emit a call followed by a branch to the call.

            // We are emitting this instead of emitting a tight loop that jumps to itself
            // so that the JIT doesn't generate extra GC checks within the loop.

            ILCodeLabel label = emitter.NewCodeLabel();
            codeStream.EmitLabel(label);
            codeStream.Emit(ILOpcode.call, emitter.NewToken(method));
            codeStream.Emit(ILOpcode.br, label);
        }

        /// <summary>
        /// Retrieves a method on <paramref name="type"/> that is well known to the compiler.
        /// Throws an exception if the method doesn't exist.
        /// </summary>
        public static MethodDesc GetKnownMethod(this TypeDesc type, string name, MethodSignature signature)
        {
            MethodDesc method = type.GetMethod(name, signature);
            if (method == null)
            {
                throw new InvalidOperationException(String.Format("Expected method '{0}' not found on type '{1}'", name, type));
            }

            return method;
        }

        /// <summary>
        /// Retrieves a field on <paramref name="type"/> that is well known to the compiler.
        /// Throws an exception if the field doesn't exist.
        /// </summary>
        public static FieldDesc GetKnownField(this TypeDesc type, string name)
        {
            FieldDesc field = type.GetField(name);
            if (field == null)
            {
                throw new InvalidOperationException(String.Format("Expected field '{0}' not found on type '{1}'", name, type));
            }

            return field;
        }

        /// <summary>
        /// Retrieves a nested type on <paramref name="type"/> that is well known to the compiler.
        /// Throws an exception if the nested type doesn't exist.
        /// </summary>
        public static MetadataType GetKnownNestedType(this MetadataType type, string name)
        {
            MetadataType nestedType = type.GetNestedType(name);
            if (nestedType == null)
            {
                throw new InvalidOperationException(String.Format("Expected type '{0}' not found on type '{1}'", name, type));
            }

            return nestedType;
        }

        /// <summary>
        /// Retrieves a namespace type in <paramref name= "module" /> that is well known to the compiler.
        /// Throws an exception if the type doesn't exist.
        /// </summary>
        public static MetadataType GetKnownType(this ModuleDesc module, string @namespace, string name)
        {
            MetadataType type = module.GetType(@namespace, name, throwIfNotFound: false);
            if (type == null)
            {
                throw new InvalidOperationException(
                    String.Format("Expected type '{0}' not found in module '{1}'",
                    @namespace.Length > 0 ? String.Concat(@namespace, ".", name) : name,
                    module));
            }

            return type;
        }
    }
}