summaryrefslogtreecommitdiff
path: root/src/vm/zapsig.h
blob: 68f8f3c5059a02aa38e5de99ad05ef1b105dd937 (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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
//

// ---------------------------------------------------------------------------
// zapsig.h
// 
// Copyright (c) Microsoft 2002
// ---------------------------------------------------------------------------
//
// This module contains helper functions used to encode and manipulate
// signatures for the zapper (ngen).
//

// ---------------------------------------------------------------------------


#ifndef ZAPSIG_H
#define ZAPSIG_H

#include "common.h"

#ifdef BINDER
#include "typehandle.h"
#endif

//define function pointer type: EncodeModuleCallback
//
#ifdef BINDER
typedef DWORD (*EncodeModuleCallback)(void* pModuleContext, MdilModule *pReferencedModule);
#else
typedef DWORD (*EncodeModuleCallback)(void* pModuleContext, Module *pReferencedModule);
#endif
enum {
    // return value when EncodeModule fails
    ENCODE_MODULE_FAILED         = 0xffffffff,
};

//define function pointer type: TokenDefinitionCallback
//
#ifdef BINDER
typedef void (*TokenDefinitionCallback)(void* pModuleContext, MdilModule *pReferencedModule, DWORD index, mdToken* refToken);
#else
typedef void (*TokenDefinitionCallback)(void* pModuleContext, Module *pReferencedModule, DWORD index, mdToken* refToken);
#endif

class ZapSig
{
public:
    enum ExternalTokens
    {
        IllegalValue,
        NormalTokens,
        IbcTokens
    };
    
    struct Context
    {
#ifdef BINDER
        MdilModule *   pInfoModule;              // The tokens in this ZapSig are expressed relative to context.pInfoModule         
#else
        Module *        pInfoModule;              // The tokens in this ZapSig are expressed relative to context.pInfoModule         
#endif
        void *          pModuleContext;           // This is a code:Module* when we are resolving Ngen fixups or doing an Ibc Profiling run
                                                  // and is a code:ZapImportTable* when we are running ngen      
        ExternalTokens  externalTokens;           // When we see a ELEMENT_TYPE_MODULE_ZAPSIG this tells us what type of token follows.

        Module * GetZapSigModule() const        { return (Module*) pModuleContext; }
        
        Context(
#ifdef BINDER
                MdilModule* _pInfoModule,
#else
                Module* _pInfoModule,
#endif
                void* _pModuleContext, ExternalTokens _externalTokens)
            : pInfoModule(_pInfoModule),
              pModuleContext(_pModuleContext),
              externalTokens(_externalTokens)
        { LIMITED_METHOD_CONTRACT; _ASSERTE(externalTokens != IllegalValue); }

        Context(
#ifdef BINDER
                MdilModule* _pInfoModule,
#else
                Module* _pInfoModule,
#endif
                Module* _pZapSigModule)
            : pInfoModule(_pInfoModule),
              pModuleContext((void*) _pZapSigModule),
              externalTokens(NormalTokens)
        { }
    };

public:

    ZapSig(
#ifdef BINDER
           MdilModule *            _pInfoModule, 
#else
           Module *                _pInfoModule, 
#endif
           void *                  _pModuleContext,
           ExternalTokens          _externalTokens,
           EncodeModuleCallback    _pfnEncodeModule,
           TokenDefinitionCallback _pfnTokenDefinition)

        : context(_pInfoModule, _pModuleContext, _externalTokens),
          pfnEncodeModule(_pfnEncodeModule),
          pfnTokenDefinition(_pfnTokenDefinition)
    {}

#ifdef FEATURE_PREJIT

    // Instance methods

    // Create a signature for a typeHandle 
    // It can be decoded using MetaSig::GetTypeHandleThrowing
    // The tokens are espressed relative to this->pInfoModule
    // When (handle.GetModule() != this->pInfoModule), we escape
    // the signature with ELEMENT_TYPE_MODULE_ZAPSIG <id-num>
    // followed by a <token> to encode a temporary change of module 
    // For Ibc Signatures the <token> is one of the ibc defined tokens
    // For Ngen Fixup signatures the <token> is for the external module
    //
    BOOL GetSignatureForTypeHandle(TypeHandle typeHandle,
                                   SigBuilder * pSigBuilder);

    // Static methods

    // Compare a type handle with a signature whose tokens are resolved with respect to pModule
    // pZapSigContext is used to resolve ELEMENT_TYPE_MODULE_ZAPSIG encodings
    static BOOL CompareSignatureToTypeHandle(PCCOR_SIGNATURE  pSig,   
#ifdef BINDER
                                             MdilModule*      pModule, 
#else
                                             Module*          pModule, 
#endif
                                             TypeHandle       handle,
                                     const ZapSig::Context *  pZapSigContext);

    // Compare a type handle with a tagged pointer. Ensure that the common path is inlined into the caller.
    static FORCEINLINE BOOL CompareTaggedPointerToTypeHandle(Module * pModule, TADDR addr, TypeHandle handle)
    {
        WRAPPER_NO_CONTRACT;
        if (handle.AsTAddr() == addr)
            return TRUE;
        if (!CORCOMPILE_IS_POINTER_TAGGED(addr))
            return FALSE;
        return CompareFixupToTypeHandle(pModule, addr, handle);
    }

    static BOOL CompareFixupToTypeHandle(Module * pModule, TADDR fixup, TypeHandle handle);

    static BOOL CompareTypeHandleFieldToTypeHandle(TypeHandle *pTypeHnd, TypeHandle typeHnd2);

private:
    BOOL GetSignatureForTypeDesc(TypeDesc * desc, SigBuilder * pSigBuilder);

    // Returns element type when the typeHandle can be encoded using
    // using a single CorElementType value 
    // This includes using ELEMENT_TYPE_CANON_ZAPSIG for the System.__Canon type
    //
    static CorElementType TryEncodeUsingShortcut(/* in  */ MethodTable * pMT);

#endif // FEATURE_PREJIT

private:

    ZapSig::Context           context;  
  
    EncodeModuleCallback      pfnEncodeModule;    // Function Pointer to the EncodeModuleHelper
    TokenDefinitionCallback   pfnTokenDefinition; // Function Pointer to the DefineTokenHelper

public:
    //--------------------------------------------------------------------
    // Static helper encode/decode helper methods

    static Module *DecodeModuleFromIndexes(Module *fromModule,
        DWORD assemblyIndex,
        DWORD moduleIndex);

    static Module *DecodeModuleFromIndexesIfLoaded(Module *fromModule,
        DWORD assemblyIndex,
        DWORD moduleIndex);

    // referencingModule is the module that references the type.
    // fromModule is the module in which the type is defined.
    // pBuffer contains the signature encoding for the type.
    // level is the class load level (see classloadlevel.h) to which the type should be loaded
    static TypeHandle DecodeType(Module *referencingModule,
        Module *fromModule,
        PCCOR_SIGNATURE pBuffer,
        ClassLoadLevel level = CLASS_LOADED);

    static MethodDesc *DecodeMethod(Module *referencingModule,
        Module *fromModule,
        PCCOR_SIGNATURE pBuffer,
        TypeHandle * ppTH = NULL);

    static FieldDesc *DecodeField(Module *referencingModule,
        Module *fromModule,
        PCCOR_SIGNATURE pBuffer,
        TypeHandle * ppTH = NULL);

    static BOOL EncodeMethod(
        MethodDesc             *pMethod,
        Module                 *pInfoModule,
        SigBuilder             *pSigBuilder,
        LPVOID                 pReferencingModule,
        ENCODEMODULE_CALLBACK  pfnEncodeModule,
        DEFINETOKEN_CALLBACK   pfnDefineToken,
        CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL,
        CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken = NULL);

    static void EncodeField(
        FieldDesc              *pField,
        Module                 *pInfoModule,
        SigBuilder             *pSigBuilder,
        LPVOID                 pReferencingModule,
        ENCODEMODULE_CALLBACK  pfnEncodeModule,
        CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL);

};

#endif // ZAPGSIG_H