summaryrefslogtreecommitdiff
path: root/src/md/compiler/newmerger.h
blob: fc89ab7f61887a2b4c319a56a980a4dfad4aab76 (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
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
// 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.
//*****************************************************************************
// NewMerger.h
// 

//
// Contains utility code for MD directory
//
//*****************************************************************************
#ifndef __NEWMERGER__h__
#define __NEWMERGER__h__

class RegMeta;

class MDTOKENMAP;

// module-level awareness of Security critical annotions
typedef BYTE InputScopeSecurityCriticalStatus;
#define ISSCS_Unknown 0x0
#define ISSCS_SecurityCritical 0x1
#define ISSCS_SecurityCriticalEverything (ISSCS_SecurityCritical | 0x2)
#define ISSCS_SecurityCriticalExplicit (ISSCS_SecurityCritical)
#define ISSCS_SecurityTransparent 0x4
#define ISSCS_SecurityTreatAsSafe 0x8
#define ISSCS_SECURITYCRITICAL_LEGACY (ISSCS_SecurityCriticalEverything | ISSCS_SecurityTreatAsSafe)
#define ISSCS_SECURITYCRITICAL_FLAGS (ISSCS_SecurityCriticalEverything | ISSCS_SecurityTransparent)

//*********************************************************************
// MergeImportData
//*********************************************************************
class MergeImportData
{
public:
    RegMeta         *m_pRegMetaImport;
    IUnknown        *m_pHandler;
    IMapToken       *m_pHostMapToken;
    MDTOKENMAP      *m_pMDTokenMap;
    MergeImportData *m_pNextImportData;
    
    mdMemberRef     m_tkSuppressMergeCheckCtor;     // caches the SuppressMergeCheckAttribute's .ctor token
    mdMemberRef     m_tkHandleProcessCorruptedStateCtor;     // caches the memberRef token to HandleProcessCorruptedStateExceptionsAttribute's .ctor token

        // import contains assembly-level SecurityTransparent or SecurityCritical
    InputScopeSecurityCriticalStatus m_isscsSecurityCriticalStatus;
#if _DEBUG
    int             m_iImport;          // debug only. This is the ith import for merge.
#endif // _DEBUG
};

//*********************************************************************
// MergeTypeData
//*********************************************************************
struct MergeTypeData 
{
    ULONG m_cMethods;
    ULONG m_cFields;
    ULONG m_cEvents;
    ULONG m_cProperties;
    BOOL  m_bSuppressMergeCheck;
};


//*********************************************************************
// Class to handle merge
//*********************************************************************
class NEWMERGER
{
    friend class RegMeta;
public:
    NEWMERGER();
    ~NEWMERGER();

    HRESULT Init(RegMeta *pRegMetaDest);
    
    HRESULT AddImport(
        IMetaDataImport2 *pImport,          // [IN] The scope to be merged.
        IMapToken   *pHostMapToken,         // [IN] Host IMapToken interface to receive token remap notification
        IUnknown    *pHandler);             // [IN] An object to receive to receive error notification.
    
    HRESULT Merge(MergeFlags flags, CorRefToDefCheck optimizeRefToDef);

protected:
    
    CMiniMdRW *GetMiniMdEmit();

    HRESULT InitMergeTypeData();

    HRESULT MergeTypeDefNamesOnly();
    HRESULT MergeModuleRefs();
    HRESULT MergeAssemblyRefs();
    HRESULT MergeTypeRefs();
    HRESULT CompleteMergeTypeDefs();

    HRESULT CopyTypeDefPartially( 
        TypeDefRec  *pRecEmit,                  // [IN] the emit record to fill
        CMiniMdRW   *pMiniMdImport,             // [IN] the importing scope
        TypeDefRec  *pRecImp);                  // [IN] the record to import

    // helpers for merging tables
    HRESULT MergeModule( );
    HRESULT MergeTypeDefChildren();
    HRESULT MergeInterfaceImpls( );
    HRESULT MergeMemberRefs( );
    HRESULT MergePinvoke();

    HRESULT MergeConstants( );
    HRESULT MergeCustomAttributes( );
    HRESULT MergeFieldMarshals( );
    HRESULT MergeDeclSecuritys( );
    HRESULT MergeClassLayouts( );
    HRESULT MergeFieldLayouts( );
    HRESULT MergeFieldRVAs();
    HRESULT MergeMethodImpls( );
    HRESULT MergeStandAloneSigs();
    HRESULT MergeMethodSpecs();
    HRESULT MergeTypeSpecs();
    HRESULT MergeSourceFiles( );
    HRESULT MergeBlocks( );
    HRESULT MergeScopes( );
    HRESULT MergeLocalVariables( );
    HRESULT MergeStrings( );

    HRESULT MergeAssembly();
    HRESULT MergeFiles();
    HRESULT MergeExportedTypes();
    HRESULT MergeManifestResources();

		// helpers for SecurityCritical-related merging
    InputScopeSecurityCriticalStatus CheckInputScopeIsCritical(MergeImportData* pImportData, HRESULT& hr);
	HRESULT RetrieveStandardSecurityCriticalMetaData(
		    mdAssemblyRef& tkMscorlib,
		    mdTypeRef& securityEnum,
	        BYTE*& rgSigBytesSecurityCriticalEverythingCtor,
	        DWORD& dwSigEverythingSize,
	        BYTE*& rgSigBytesSecurityCriticalExplicitCtor,
	        DWORD& dwSigExplicitSize);

	HRESULT MergeSecurityCriticalModuleLevelAttributes(
	    MergeImportData* pImportData,
	    mdToken tkParentImp, TOKENREC* pTypeRec,
	    mdToken mrSecurityTreatAsSafeAttributeCtor,
	    mdToken mrSecurityTransparentAttributeCtor,
	    mdToken mrSecurityCriticalExplicitAttributeCtor,
	    mdToken mrSecurityCriticalEverythingAttributeCtor);
    HRESULT MergeSecurityCriticalAttributes();

        // copy over a interfaceimpl record
    HRESULT CopyInterfaceImpl(
        InterfaceImplRec    *pRecEmit,          // [IN] the emit record to fill
        MergeImportData     *pImportData,       // [IN] the importing context
        InterfaceImplRec    *pRecImp);          // [IN] the record to import

    // verification helpers
    HRESULT VerifyMethods(MergeImportData *pImportData, mdTypeDef tdImp, mdTypeDef tdEmit);
    HRESULT VerifyFields(MergeImportData *pImportData, mdTypeDef tdImp, mdTypeDef tdEmit);
    HRESULT VerifyEvents(MergeImportData *pImportData, mdTypeDef tdImp, mdTypeDef tdEmit);
    HRESULT VerifyProperties(MergeImportData *pImportData, mdTypeDef tdImp, mdTypeDef tdEmit);
    HRESULT VerifyParams(MergeImportData *pImportData, mdMethodDef mdImp,   mdMethodDef mdEmit);
    HRESULT VerifyGenericParams(MergeImportData *pImportData, mdTypeDef tdImp, mdTypeDef tdEmit);
    HRESULT VerifyGenericParamConstraints(MergeImportData *pImportData, mdGenericParam gpImp, mdGenericParam gpEmit);

    // Copy helpers
    HRESULT CopyMethods(MergeImportData *pImportData, mdTypeDef tdImp, mdTypeDef tdEmit);
    HRESULT CopyFields(MergeImportData *pImportData, mdTypeDef tdImp, mdTypeDef tdEmit);
    HRESULT CopyEvents(MergeImportData *pImportData, mdTypeDef tdImp, mdTypeDef tdEmit);
    HRESULT CopyProperties(MergeImportData *pImportData, mdTypeDef tdImp, mdTypeDef tdEmit);
    HRESULT CopyParams(MergeImportData *pImportData, mdMethodDef mdImp, mdMethodDef mdEmit);
    HRESULT CopyGenericParams(MergeImportData *pImportData, mdToken tkImp, mdToken tkEmit);
    HRESULT CopyGenericParamConstraints(MergeImportData *pImportData, mdGenericParam gpImp, mdGenericParam gpEmit);

    HRESULT CopyMethod(
        MergeImportData *pImportData,           // [IN] import scope
        MethodRec   *pRecImp,                   // [IN] the record to import
        MethodRec   *pRecEmit);                 // [IN] the emit record to fill

    HRESULT CopyField(
        MergeImportData *pImportData,           // [IN] import scope
        FieldRec    *pRecImp,                   // [IN] the record to import
        FieldRec    *pRecEmit);                 // [IN] the emit record to fill

    HRESULT CopyEvent(
        MergeImportData *pImportData,           // [IN] import scope
        EventRec    *pRecImp,                   // [IN] the record to import
        EventRec    *pRecEmit);                 // [IN] the emit record to fill

    HRESULT CopyProperty(
        MergeImportData *pImportData,           // [IN] import scope
        PropertyRec *pRecImp,                   // [IN] the record to import
        PropertyRec *pRecEmit);                 // [IN] the emit record to fill

    HRESULT CopyParam(
        MergeImportData *pImportData,           // [IN] import scope
        ParamRec    *pRecImp,                   // [IN] the record to import
        ParamRec    *pRecEmit);                 // [IN] the emit record to fill

    HRESULT CopyMethodSemantics(
        MergeImportData *pImportData, 
        mdToken     tkImport,                   // Event or property in the import scope
        mdToken     tkEmit);                    // corresponding event or property in the emitting scope

    HRESULT VerifyMethod(
        MergeImportData *pImportData, 
        mdMethodDef mdImp,                      // [IN] the emit record to fill
        mdMethodDef mdEmit);                    // [IN] the record to import

    HRESULT OnError(HRESULT hr, MergeImportData *pImportData, mdToken token);

private:
    RegMeta         *m_pRegMetaEmit;
    MergeImportData *m_pImportDataList;
    MergeImportData **m_pImportDataTail;
    MergeFlags      m_dwMergeFlags;
    BOOL            m_fDupCheck;
    CorRefToDefCheck m_optimizeRefToDef;
        // the combined value of the Security Critical input scopes (e.g. UNION of each scope's attributes)
            // if ANY of the scopes have a bit set, then we must do some merging
    InputScopeSecurityCriticalStatus m_isscsSecurityCritical;
        // the common values of the Security Critical input scopes (e.g. INTERSECTION of each scope's attributes)
            // if all scopes have the same bit set, then we can emit one bit at the final output scope
    InputScopeSecurityCriticalStatus m_isscsSecurityCriticalAllScopes;

    CDynArray<MergeTypeData> m_rMTDs;
#if _DEBUG
    int             m_iImport;          // debug only. To count how many import scopes to be merged.
#endif // _DEBUG
};


#define CheckContinuableErrorEx(EXPR, HANDLER, TOKEN) \
{ \
    HRESULT hrOnErr, hrExpr; \
    hrExpr  = EXPR; \
    \
    hrOnErr = OnError(hrExpr, HANDLER, TOKEN); \
    if (hrOnErr != S_OK) \
    { \
        if (hrOnErr == S_FALSE) \
        { \
            hr = hrExpr; \
        } \
        else if (SUCCEEDED(hrOnErr)) \
        { \
            hr = E_UNEXPECTED; \
        } \
        else if (FAILED(hrOnErr)) \
        { \
            hr = hrOnErr; \
        } \
        IfFailGo(hr); \
    } \
}


#endif // __NEWMERGER__h__