Merge pull request #4051 from sejongoh/fix_singlinkgen_test
[platform/upstream/coreclr.git] / src / zap / zapimport.h
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 // ZapImport.h
6 //
7
8 //
9 // Import is soft bound references to elements outside the current module
10 // 
11 // ======================================================================================
12
13 #ifndef __ZAPIMPORT_H__
14 #define __ZAPIMPORT_H__
15
16 class ZapImportTable;
17 class ZapGCRefMapTable;
18 class NibbleWriter;
19
20 //---------------------------------------------------------------------------------------
21 //
22 // ZapImport is the import cell itself
23 //
24 // Every import cell is uniquely identified by its ZapNodeType and two handles 
25 // (the second handle is optional and is often NULL)
26 //
27 // Actual implementations inherits from this abstract base class.
28 //
29 class ZapImport : public ZapNode
30 {
31     COUNT_T m_index;
32     DWORD m_offset;
33
34     PVOID m_handle;
35     PVOID m_handle2;
36
37     ZapBlob * m_pBlob;
38
39 public:
40     void SetHandle(PVOID handle)
41     {
42         _ASSERTE(m_handle == NULL);
43         m_handle = handle;
44     }
45
46     void SetHandle2(PVOID handle2)
47     {
48         _ASSERTE(m_handle2 == NULL);
49         m_handle2 = handle2;
50     }
51
52     PVOID GetHandle()
53     {
54         return m_handle;
55     }
56
57     PVOID GetHandle2()
58     {
59         return m_handle2;
60     }
61
62     void SetBlob(ZapBlob * pBlob)
63     {
64         _ASSERTE(m_pBlob == NULL);
65         m_pBlob = pBlob;
66     }
67
68     ZapBlob * GetBlob()
69     {
70         _ASSERTE(m_pBlob != NULL);
71         return m_pBlob;
72     }
73
74     BOOL HasBlob()
75     {
76         return m_pBlob != NULL;
77     }
78
79     virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature)
80     {
81         *pfIsEager = FALSE;
82         *pfNeedsSignature = TRUE;
83         return ZapImportSectionType_Handle;
84     }
85
86     // All subtypes have to override
87     virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) = 0;
88
89     virtual DWORD GetSize()
90     {
91         return sizeof(TADDR);
92     }
93
94     virtual UINT GetAlignment()
95     {
96         return sizeof(TADDR);
97     }
98
99     virtual void Save(ZapWriter * pZapWriter);
100     
101     //
102     // Offset of the fixup cell within its section
103     //
104
105     void SetSectionIndexAndOffset(COUNT_T index, DWORD offset)
106     {
107         m_index = index;
108         m_offset = offset;
109     }
110
111     DWORD GetSectionIndex()
112     {
113         return m_index;
114     }
115
116     DWORD GetOffset()
117     {
118         return m_offset;
119     }
120 };
121
122 //---------------------------------------------------------------------------------------
123 //
124 // ZapGenericSignature is signature of generic dictionary entry.
125 //
126 class ZapGenericSignature : public ZapBlob
127 {
128 public:
129     ZapGenericSignature(SIZE_T cbSize)
130         : ZapBlob(cbSize)
131     {
132     }
133
134     virtual ZapNodeType GetType()
135     {
136         return ZapNodeType_GenericSignature;
137     }
138 };
139
140 //---------------------------------------------------------------------------------------
141 //
142 // ZapImportTable is the main class that keeps track of all ZapImports.
143 //
144 // There is a single instance of it per image.
145 //
146 class ZapImportTable : public ZapNode
147 {
148     //
149     // Hashtable key of the import
150     // The same key is used for both ZapImport and ZapImportBlob
151     //
152     struct ImportKey
153     {
154         FORCEINLINE ImportKey(PVOID handle, ZapNodeType type)
155             : m_handle(handle), m_handle2(NULL), m_type(type)
156         {
157         }
158
159         FORCEINLINE ImportKey(PVOID handle, PVOID handle2, ZapNodeType type)
160             : m_handle(handle), m_handle2(handle2), m_type(type)
161         {
162         }
163
164         PVOID m_handle;
165         PVOID m_handle2;
166         ZapNodeType m_type;
167     };
168
169     //
170     // Hashtable of ZapImports
171     //
172     class ImportTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ZapImport *> >
173     {
174     public:
175         typedef ImportKey key_t;
176
177         static FORCEINLINE key_t GetKey(element_t e)
178         { 
179             LIMITED_METHOD_CONTRACT;
180             return ImportKey(e->GetHandle(), e->GetHandle2(), e->GetType());
181         }
182         static FORCEINLINE BOOL Equals(key_t k1, key_t k2)
183         { 
184             LIMITED_METHOD_CONTRACT;
185             return (k1.m_handle == k2.m_handle) && (k1.m_handle2 == k2.m_handle2) && (k1.m_type == k2.m_type);
186         }
187         static FORCEINLINE count_t Hash(key_t k) 
188         {
189             LIMITED_METHOD_CONTRACT;
190             return (count_t)(size_t)k.m_handle ^ ((count_t)(size_t)k.m_handle2 << 1) ^ k.m_type;
191         }
192
193         static const element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; }
194         static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; }
195     };
196
197     typedef SHash< ImportTraits > ImportTable;
198
199     //
200     // Hashtable of module indices
201     //
202     struct ModuleReferenceEntry
203     {
204         CORINFO_MODULE_HANDLE m_module;
205         DWORD m_index;
206
207         USHORT m_wAssemblyRid;
208         USHORT m_wModuleRid;
209     };
210
211     class ModuleReferenceTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ModuleReferenceEntry *> >
212     {
213     public:
214         typedef CORINFO_MODULE_HANDLE key_t;
215
216         static key_t GetKey(element_t e)
217         { 
218             LIMITED_METHOD_CONTRACT;
219             return e->m_module;
220         }
221         static BOOL Equals(key_t k1, key_t k2) 
222         { 
223             LIMITED_METHOD_CONTRACT;
224             return (k1 == k2);
225         }
226         static count_t Hash(key_t k) 
227         {
228             LIMITED_METHOD_CONTRACT;
229             return (count_t)(size_t)k;
230         }
231
232         static const element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; }
233         static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; }
234     };
235
236     typedef SHash< ModuleReferenceTraits > ModuleReferenceTable;
237
238     //
239     // Helpers for inserting actual implementations of ZapImports into hashtable
240     //
241     template < typename impl, ZapNodeType type >
242     ZapImport * GetImport(PVOID handle)
243     {
244         ZapImport * pImport = m_imports.Lookup(ImportKey(handle, type));
245
246         if (pImport != NULL)
247         {
248             return pImport;
249         }
250
251         pImport = new (m_pImage->GetHeap()) impl();
252         _ASSERTE(pImport->GetType() == type);
253         pImport->SetHandle(handle);
254         m_imports.Add(pImport);
255         return pImport;
256     }
257
258     template < typename impl, ZapNodeType type >
259     ZapImport * GetImport(PVOID handle, PVOID handle2)
260     {
261         ZapImport * pImport = m_imports.Lookup(ImportKey(handle, handle2, type));
262
263         if (pImport != NULL)
264         {
265             return pImport;
266         }
267
268         pImport = new (m_pImage->GetHeap()) impl();
269         _ASSERTE(pImport->GetType() == type);
270         pImport->SetHandle(handle);
271         pImport->SetHandle2(handle2);
272         m_imports.Add(pImport);
273         return pImport;
274     }
275
276     template < typename impl, ZapNodeType type >
277     ZapImport * GetImportForSignature(PVOID handle, SigBuilder * pSigBuilder)
278     {
279         ZapBlob * pBlob = GetBlob(pSigBuilder);
280
281         ZapImport * pImport = m_imports.Lookup(ImportKey(handle, pBlob, type));
282
283         if (pImport != NULL)
284         {
285             return pImport;
286         }
287
288         pImport = new (m_pImage->GetHeap()) impl();
289         _ASSERTE(pImport->GetType() == type);
290         pImport->SetHandle(handle);
291         pImport->SetHandle2(pBlob);
292         pImport->SetBlob(pBlob);
293         m_imports.Add(pImport);
294         return pImport;
295     }
296
297     ZapImport * GetExistingImport(ZapNodeType type, PVOID handle)
298     {
299         return m_imports.Lookup(ImportKey(handle, type));
300     }
301
302     ModuleReferenceEntry * GetModuleReference(CORINFO_MODULE_HANDLE handle);
303
304     static DWORD __stdcall EncodeModuleHelper(LPVOID referencingModule, CORINFO_MODULE_HANDLE referencedModule);
305
306     ImportTable m_imports;          // Interned ZapImport *
307     SHash< NoRemoveSHashTraits < ZapBlob::SHashTraits > > m_blobs; // Interned ZapBlos for signatures and fixups
308
309     ModuleReferenceTable m_moduleReferences;
310     SArray<ModuleReferenceEntry *> m_modules;   // Secondary table of ModuleReferences to allow fast index based lookup
311
312     SHash< NoRemoveSHashTraits < ZapBlob::SHashTraits > > m_genericSignatures;
313
314     DWORD   m_nImportSectionSizes[ZapImportSectionType_Total];
315     COUNT_T m_nImportSectionIndices[ZapImportSectionType_Total];
316
317     ZapImage * m_pImage;
318
319 public:
320     ZapImportTable(ZapImage * pImage)
321         : m_pImage(pImage)
322     {
323          // Everything else is zero initialized by the allocator
324     }
325
326     void Preallocate(COUNT_T cbILImage)
327     {
328         PREALLOCATE_HASHTABLE(ZapImportTable::m_imports, 0.0030, cbILImage);
329         PREALLOCATE_HASHTABLE(ZapImportTable::m_blobs, 0.0025, cbILImage);
330
331         PREALLOCATE_HASHTABLE_NOT_NEEDED(ZapImportTable::m_moduleReferences, cbILImage);
332     }
333
334     //
335     // Helpers for encoding import blobs
336     //
337
338     void EncodeModule(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_MODULE_HANDLE module, SigBuilder * pSigBuilder);
339     void EncodeClass(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_CLASS_HANDLE handle, SigBuilder * pSigBuilder);
340     void EncodeClassInContext(CORINFO_MODULE_HANDLE context, CORINFO_CLASS_HANDLE handle, SigBuilder * pSigBuilder);
341     void EncodeField(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, SigBuilder * pSigBuilder,
342             CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL);
343     void EncodeMethod(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, SigBuilder * pSigBuilder, 
344             CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken = NULL);
345
346     // Encode module if the reference is within current version bubble. If not, return a suitable module within current version bubble.
347     CORINFO_MODULE_HANDLE TryEncodeModule(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_MODULE_HANDLE module, SigBuilder * pSigBuilder);
348
349     ICorDynamicInfo * GetJitInfo()
350     {
351         return m_pImage->GetJitInfo();
352     }
353
354     ICorCompileInfo * GetCompileInfo()
355     {
356         return m_pImage->GetCompileInfo();
357     }
358
359     ZapImage * GetImage()
360     {
361         return m_pImage;
362     }
363
364     // Returns index of module in the import table for encoding module fixups in EE datastructures.
365     DWORD GetIndexOfModule(CORINFO_MODULE_HANDLE handle)
366     {
367         ZapImportTable::ModuleReferenceEntry * pModuleReference = GetModuleReference(handle);
368         _ASSERTE(pModuleReference != NULL);
369         return pModuleReference->m_index;
370     }
371
372     // Get the import blob for given signature
373     ZapBlob * GetBlob(SigBuilder * pSigBuilder, BOOL fEager = FALSE);
374
375     // Place give import blob
376     void PlaceBlob(ZapBlob * pBlob, BOOL fEager = FALSE);
377
378     // Encodes the import blob and places it into the image
379     ZapBlob * PlaceImportBlob(ZapImport * pImport, BOOL fEager = FALSE);
380
381     // Places import cell into the image.
382     // This also encoded and places all the import blobs if they are not placed yet.
383     void PlaceImport(ZapImport * pImport);
384
385     // Encodes list of fixups and places it into the image. 
386     // This also places all the import cells if they are not placed yet.
387     ZapFixupInfo * PlaceFixups(ZapImport ** pImports);
388     void PlaceFixups(ZapImport ** pImports, NibbleWriter& writer);
389
390     ZapGenericSignature * GetGenericSignature(PVOID signature, BOOL fMethod);
391
392     //
393     // The actual implementations of import cells
394     //
395     ZapImport * GetFunctionEntryImport(CORINFO_METHOD_HANDLE handle);
396     ZapImport * GetModuleHandleImport(CORINFO_MODULE_HANDLE handle);
397     ZapImport * GetClassHandleImport(CORINFO_CLASS_HANDLE handle, PVOID pUniqueId = NULL);
398     ZapImport * GetMethodHandleImport(CORINFO_METHOD_HANDLE handle);
399     ZapImport * GetFieldHandleImport(CORINFO_FIELD_HANDLE handle);
400     ZapImport * GetStringHandleImport(CORINFO_MODULE_HANDLE tokenScope, mdString metaTok);
401     ZapImport * GetStaticFieldAddressImport(CORINFO_FIELD_HANDLE handle);
402     ZapImport * GetClassDomainIdImport(CORINFO_CLASS_HANDLE handle);
403     ZapImport * GetModuleDomainIdImport(CORINFO_MODULE_HANDLE handleToModule, CORINFO_CLASS_HANDLE handleToClass);
404     ZapImport * GetSyncLockImport(CORINFO_CLASS_HANDLE handle); 
405     ZapImport * GetIndirectPInvokeTargetImport(CORINFO_METHOD_HANDLE handle);
406     ZapImport * GetProfilingHandleImport(CORINFO_METHOD_HANDLE handle);
407     ZapImport * GetVarArgImport(CORINFO_MODULE_HANDLE handle, mdToken sigOrMemberRefOrDef);
408     ZapImport * GetActiveDependencyImport(CORINFO_MODULE_HANDLE moduleFrom, CORINFO_MODULE_HANDLE moduleTo);
409
410     ZapImport * GetExistingClassHandleImport(CORINFO_CLASS_HANDLE handle);
411     ZapImport * GetExistingMethodHandleImport(CORINFO_METHOD_HANDLE handle);
412     ZapImport * GetExistingFieldHandleImport(CORINFO_FIELD_HANDLE handle);
413
414     ZapImport * GetVirtualImportThunk(CORINFO_METHOD_HANDLE handle, int slot);
415     void        PlaceVirtualImportThunk(ZapImport * pImportThunk);
416
417     ZapImport * GetExternalMethodThunk(CORINFO_METHOD_HANDLE handle);
418     ZapImport * GetExternalMethodCell(CORINFO_METHOD_HANDLE handle);
419     ZapImport * GetStubDispatchCell(CORINFO_CLASS_HANDLE typeHnd, CORINFO_METHOD_HANDLE methHnd);
420
421     //
422     // Ready-to-run imports
423     //
424     ZapImport * GetClassImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_RESOLVED_TOKEN * pResolvedToken);
425     ZapImport * GetMethodImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken = NULL);
426     ZapImport * GetFieldImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken);
427
428     ZapImport * GetCheckTypeLayoutImport(CORINFO_CLASS_HANDLE handle);
429     ZapImport * GetCheckFieldOffsetImport(CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, DWORD offset);
430
431     ZapImport * GetStubDispatchCell(CORINFO_RESOLVED_TOKEN * pResolvedToken);
432     ZapImport * GetExternalMethodCell(CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken);
433
434     ZapImport * GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_CLASS_HANDLE handle);
435     ZapImport * GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, 
436                     CORINFO_CLASS_HANDLE delegateType = NULL);
437     ZapImport * GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken);
438
439 #ifdef FEATURE_READYTORUN_COMPILER
440     ZapNode * GetPlacedIndirectHelperThunk(ReadyToRunHelper helperNum, PVOID pArg = NULL, ZapNode * pCell = NULL);
441     ZapNode * GetIndirectHelperThunk(ReadyToRunHelper helperNum, PVOID pArg = NULL);
442     void PlaceIndirectHelperThunk(ZapNode * pImport);
443
444     ZapImport * GetPlacedHelperImport(ReadyToRunHelper helperNum);
445     ZapImport * GetHelperImport(ReadyToRunHelper helperNum);
446 #endif
447
448     virtual DWORD GetSize()
449     {
450         return m_modules.GetCount() * sizeof(CORCOMPILE_IMPORT_TABLE_ENTRY);
451     }
452
453     virtual UINT GetAlignment()
454     {
455         return sizeof(DWORD);
456     }
457
458     virtual ZapNodeType GetType()
459     {
460         return ZapNodeType_ImportTable;
461     }
462
463     virtual void Save(ZapWriter * pZapWriter);
464 };
465
466 //
467 // CORCOMPILE_CODE_IMPORT_SECTION
468 //
469 class ZapImportSectionsTable : public ZapNode
470 {
471     struct ImportSection
472     {
473         ZapVirtualSection * m_pSection;
474         ZapNode * m_pSignatures;
475         ZapNode * m_pAuxiliaryData;
476         USHORT    m_Flags;
477         BYTE      m_Type;
478         BYTE      m_EntrySize;
479     };
480
481     SArray<ImportSection> m_ImportSectionsTable;
482
483 public:
484     ZapImportSectionsTable(ZapImage * pImage)
485     {
486     }
487
488     COUNT_T Append(BYTE Type, USHORT Flags, BYTE EntrySize, ZapVirtualSection * pSection, ZapNode * pSignatures = NULL, ZapNode * pAuxiliaryData = NULL);
489
490     virtual UINT GetAlignment()
491     {
492         return sizeof(DWORD);
493     }
494
495     virtual DWORD GetSize();
496
497     virtual ZapNodeType GetType()
498     {
499         return ZapNodeType_ImportSectionsTable;
500     }
501
502     virtual void Save(ZapWriter * pZapWriter);
503 };
504
505 //
506 // ZapImportSectionSignatures contains an array of signature RVAs for given import section.
507 //
508 class ZapImportSectionSignatures : public ZapNode
509 {
510     ZapVirtualSection * m_pImportSection;
511     ZapGCRefMapTable * m_pGCRefMapTable;
512
513     DWORD m_dwIndex;
514
515     ZapImage * m_pImage;
516
517 public:
518     ZapImportSectionSignatures(ZapImage * pImage, ZapVirtualSection * pImportSection, ZapVirtualSection * pGCSection = NULL);
519     ~ZapImportSectionSignatures();
520
521     void PlaceExternalMethodThunk(ZapImport * pImport);
522     void PlaceExternalMethodCell(ZapImport * pImport);
523     void PlaceStubDispatchCell(ZapImport * pImport);
524     void PlaceDynamicHelperCell(ZapImport * pImport);
525
526     virtual DWORD GetSize();
527
528     virtual UINT GetAlignment()
529     {
530         return sizeof(DWORD);
531     }
532
533     virtual ZapNodeType GetType()
534     {
535         return ZapNodeType_ImportSectionSignatures;
536     }
537
538     virtual void Save(ZapWriter * pZapWriter);
539 };
540
541 #include "gcrefmap.h"
542
543 class ZapGCRefMapTable : public ZapNode
544 {
545     ZapImage * m_pImage;
546     GCRefMapBuilder m_GCRefMapBuilder;
547     COUNT_T m_nCount;
548
549 public:
550     ZapGCRefMapTable(ZapImage * pImage)
551         : m_pImage(pImage)
552     {
553     }
554
555     void Append(CORINFO_METHOD_HANDLE handle);
556
557     virtual DWORD GetSize();
558
559     virtual UINT GetAlignment()
560     {
561         return sizeof(DWORD);
562     }
563
564     virtual ZapNodeType GetType()
565     {
566         return ZapNodeType_GCRefMapTable;
567     }
568
569     virtual void Save(ZapWriter * pZapWriter);
570 };
571
572 #endif // __ZAPIMPORT_H__