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

InterfaceDispatchCellNode.cs « DependencyAnalysis « Compiler « src « ILCompiler.Compiler « src - github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 4bcd902153173d588598cae8abfb758afd3c589c (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
127
128
129
130
131
132
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections.Generic;
using System.Diagnostics;

using Internal.Runtime;
using Internal.Text;
using Internal.TypeSystem;

namespace ILCompiler.DependencyAnalysis
{
    public class InterfaceDispatchCellNode : EmbeddedObjectNode, ISymbolDefinitionNode
    {
        private readonly MethodDesc _targetMethod;
        private readonly string _callSiteIdentifier;

        internal MethodDesc TargetMethod => _targetMethod;

        internal string CallSiteIdentifier => _callSiteIdentifier;

        public InterfaceDispatchCellNode(MethodDesc targetMethod, string callSiteIdentifier)
        {
            Debug.Assert(targetMethod.OwningType.IsInterface);
            Debug.Assert(!targetMethod.IsSharedByGenericInstantiations);
            _targetMethod = targetMethod;
            _callSiteIdentifier = callSiteIdentifier;
        }

        public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
        {
            sb.Append(GetMangledName(nameMangler, _targetMethod, _callSiteIdentifier));
        }

        int ISymbolDefinitionNode.Offset => OffsetFromBeginningOfArray;

        int ISymbolNode.Offset => 0;

        public override bool IsShareable => false;

        public static string GetMangledName(NameMangler nameMangler, MethodDesc method, string callSiteIdentifier)
        {
            string name = nameMangler.CompilationUnitPrefix + "__InterfaceDispatchCell_" + nameMangler.GetMangledMethodName(method);

            if (!string.IsNullOrEmpty(callSiteIdentifier))
            {
                name += "_" + callSiteIdentifier;
            }

            return name;
        }

        protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);

        public override bool StaticDependenciesAreComputed => true;

        public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
        {
            DependencyList result = new DependencyList();

            if (!factory.VTable(_targetMethod.OwningType).HasFixedSlots)
            {
                result.Add(factory.VirtualMethodUse(_targetMethod), "Interface method use");
            }

            factory.MetadataManager.GetDependenciesDueToVirtualMethodReflectability(ref result, factory, _targetMethod);

            TargetArchitecture targetArchitecture = factory.Target.Architecture;
            if (targetArchitecture == TargetArchitecture.ARM ||
                targetArchitecture == TargetArchitecture.ARMEL)
            {
                result.Add(factory.InitialInterfaceDispatchStub, "Initial interface dispatch stub");
            }
            else
            {
                result.Add(factory.ExternSymbol("RhpInitialDynamicInterfaceDispatch"), "Initial interface dispatch stub");
            }

            result.Add(factory.NecessaryTypeSymbol(_targetMethod.OwningType), "Interface type");

            return result;
        }

        public override void EncodeData(ref ObjectDataBuilder objData, NodeFactory factory, bool relocsOnly)
        {
            TargetArchitecture targetArchitecture = factory.Target.Architecture;
            if (targetArchitecture == TargetArchitecture.ARM ||
                targetArchitecture == TargetArchitecture.ARMEL)
            {
                objData.EmitPointerReloc(factory.InitialInterfaceDispatchStub);
            }
            else
            {
                objData.EmitPointerReloc(factory.ExternSymbol("RhpInitialDynamicInterfaceDispatch"));
            }

            IEETypeNode interfaceType = factory.NecessaryTypeSymbol(_targetMethod.OwningType);
            if (interfaceType.RepresentsIndirectionCell)
            {
                objData.EmitReloc(interfaceType, RelocType.IMAGE_REL_BASED_RELPTR32,
                    (int)InterfaceDispatchCellCachePointerFlags.CachePointerIsIndirectedInterfaceRelativePointer);
            }
            else
            {
                objData.EmitReloc(interfaceType, RelocType.IMAGE_REL_BASED_RELPTR32,
                    (int)InterfaceDispatchCellCachePointerFlags.CachePointerIsInterfaceRelativePointer);
            }

            if (objData.TargetPointerSize == 8)
            {
                // IMAGE_REL_BASED_RELPTR is a 32-bit relocation. However, the cell needs a full pointer 
                // width there since a pointer to the cache will be written into the cell. Emit additional
                // 32 bits on targets whose pointer size is 64 bit. 
                objData.EmitInt(0);
            }
        }

        protected override void OnMarked(NodeFactory factory)
        {
            factory.InterfaceDispatchCellSection.AddEmbeddedObject(this);
        }

        public override int ClassCode => -2023802120;

        public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
        {
            var compare = comparer.Compare(_targetMethod, ((InterfaceDispatchCellNode)other)._targetMethod);
            return compare != 0 ? compare : string.Compare(_callSiteIdentifier, ((InterfaceDispatchCellNode)other)._callSiteIdentifier);
        }
    }
}