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 | /* Assembler.h */ |
6 | /************************************************************************/ |
7 | |
8 | #ifndef Assember_h |
9 | #define Assember_h |
10 | |
11 | #define NEW_INLINE_NAMES |
12 | |
13 | #include "binstr.h" |
14 | |
15 | #include "specstrings.h" |
16 | |
17 | #include "asmenum.h" |
18 | #include "asmtemplates.h" |
19 | |
20 | // Disable the "initialization of static local vars is no thread safe" error |
21 | #ifdef _MSC_VER |
22 | #pragma warning(disable : 4640) |
23 | #endif |
24 | |
25 | #ifdef ResetEvent |
26 | #undef ResetEvent |
27 | #endif |
28 | |
29 | #define OUTPUT_BUFFER_SIZE 8192 // initial size of asm code for a single method |
30 | #define OUTPUT_BUFFER_INCREMENT 1024 // size of code buffer increment when it's full |
31 | #define MAX_FILENAME_LENGTH 2048 //256 |
32 | #define MAX_SIGNATURE_LENGTH 256 // unused |
33 | #define MAX_LABEL_SIZE 256 //64 |
34 | #define MAX_CALL_SIG_SIZE 32 // unused |
35 | #define MAX_SCOPE_LENGTH _MAX_PATH // follow the RegMeta::SetModuleProps limitation |
36 | |
37 | #define MAX_NAMESPACE_LENGTH 1024 //256 //64 |
38 | #define MAX_MEMBER_NAME_LENGTH 1024 //256 //64 |
39 | |
40 | #define MAX_INTERFACES_IMPLEMENTED 16 // initial number; extended by 16 when needed |
41 | #define GLOBAL_DATA_SIZE 8192 // initial size of global data buffer |
42 | #define GLOBAL_DATA_INCREMENT 1024 // size of global data buffer increment when it's full |
43 | #define MAX_METHODS 1024 // unused |
44 | #define MAX_INPUT_LINE_LEN 1024 // unused |
45 | #define MAX_TYPAR 8 |
46 | #define BASE_OBJECT_CLASSNAME "System.Object" |
47 | #define MAX_MANIFEST_RESOURCES 1024 |
48 | |
49 | // Fully-qualified class name separators: |
50 | #define NESTING_SEP ((char)0xF8) |
51 | |
52 | #define dwUniBuf 16384 |
53 | |
54 | #ifdef FEATURE_PAL |
55 | #include "coreclrloader.h" |
56 | extern CoreCLRLoader *g_loader; |
57 | extern char *g_pszExeFile; |
58 | #endif |
59 | typedef int(STDAPICALLTYPE *MetaDataGetDispenserFunc) ( |
60 | REFCLSID rclsid, // The class to desired. |
61 | REFIID riid, // Interface wanted on class factory. |
62 | LPVOID FAR *ppv); // Return interface pointer here. |
63 | |
64 | extern MetaDataGetDispenserFunc metaDataGetDispenser; |
65 | |
66 | extern WCHAR wzUniBuf[]; // Unicode conversion global buffer (assem.cpp) |
67 | |
68 | class Class; |
69 | class Method; |
70 | class PermissionDecl; |
71 | class PermissionSetDecl; |
72 | |
73 | unsigned hash( // defined in assem.cpp |
74 | __in_ecount(length) const BYTE *k, /* the key */ |
75 | unsigned length, /* the length of the key */ |
76 | unsigned initval); /* the previous hash, or an arbitrary value */ |
77 | |
78 | struct MemberRefDescriptor |
79 | { |
80 | mdToken m_tdClass; |
81 | Class* m_pClass; |
82 | char* m_szName; |
83 | DWORD m_dwName; |
84 | BinStr* m_pSigBinStr; |
85 | mdToken m_tkResolved; |
86 | }; |
87 | typedef FIFO<MemberRefDescriptor> MemberRefDList; |
88 | |
89 | |
90 | struct MethodImplDescriptor |
91 | { |
92 | mdToken m_tkImplementedMethod; |
93 | mdToken m_tkImplementingMethod; |
94 | mdToken m_tkDefiningClass; |
95 | BOOL m_fNew; |
96 | }; |
97 | typedef FIFO<MethodImplDescriptor> MethodImplDList; |
98 | |
99 | struct LocalMemberRefFixup |
100 | { |
101 | mdToken tk; |
102 | size_t offset; |
103 | BOOL m_fNew; |
104 | LocalMemberRefFixup(mdToken TK, size_t Offset) |
105 | { |
106 | tk = TK; |
107 | offset = Offset; |
108 | m_fNew = TRUE; |
109 | } |
110 | }; |
111 | typedef FIFO<LocalMemberRefFixup> LocalMemberRefFixupList; |
112 | |
113 | struct CustomDescr |
114 | { |
115 | mdToken tkType; |
116 | mdToken tkOwner; |
117 | mdToken tkInterfacePair; // Needed for InterfaceImpl CA's |
118 | BinStr* pBlob; |
119 | CustomDescr(mdToken tko, mdToken tk, BinStr* pblob) { tkType = tk; pBlob = pblob; tkOwner = tko; tkInterfacePair = 0; }; |
120 | CustomDescr(mdToken tk, BinStr* pblob) { tkType = tk; pBlob = pblob; tkOwner = 0; tkInterfacePair = 0;}; |
121 | CustomDescr(CustomDescr* pOrig) { tkType = pOrig->tkType; pBlob = new BinStr(); pBlob->append(pOrig->pBlob); tkOwner = pOrig->tkOwner; tkInterfacePair = pOrig->tkInterfacePair; }; |
122 | ~CustomDescr() { if(pBlob) delete pBlob; }; |
123 | }; |
124 | typedef FIFO<CustomDescr> CustomDescrList; |
125 | typedef LIFO<CustomDescrList> CustomDescrListStack; |
126 | /**************************************************************************/ |
127 | #include "typar.hpp" |
128 | #include "method.hpp" |
129 | #include "iceefilegen.h" |
130 | #include "asmman.hpp" |
131 | |
132 | #include "nvpair.h" |
133 | |
134 | |
135 | typedef enum |
136 | { |
137 | STATE_OK, |
138 | STATE_FAIL, |
139 | STATE_ENDMETHOD, |
140 | STATE_ENDFILE |
141 | } state_t; |
142 | |
143 | |
144 | class GlobalLabel |
145 | { |
146 | public: |
147 | LPCUTF8 m_szName; |
148 | DWORD m_GlobalOffset; |
149 | HCEESECTION m_Section; |
150 | unsigned m_Hash; |
151 | |
152 | GlobalLabel(LPCUTF8 pszName, DWORD GlobalOffset, HCEESECTION section) |
153 | { |
154 | m_GlobalOffset = GlobalOffset; |
155 | m_Section = section; |
156 | m_szName = pszName; |
157 | m_Hash = hash((const BYTE*)pszName, (unsigned)strlen(pszName),10); |
158 | } |
159 | |
160 | ~GlobalLabel(){ delete [] m_szName; } |
161 | |
162 | int ComparedTo(GlobalLabel* L) |
163 | { |
164 | return (m_Hash == L->m_Hash) ? strcmp(m_szName, L->m_szName) |
165 | : ((m_Hash > L->m_Hash) ? 1 : -1); |
166 | } |
167 | |
168 | //int ComparedTo(GlobalLabel* L) { return strcmp(m_szName,L->m_szName); }; |
169 | //int Compare(char* L) { return strcmp(L, m_szNam); }; |
170 | //char* NameOf() { return m_szName; }; |
171 | }; |
172 | //typedef SORTEDARRAY<GlobalLabel> GlobalLabelList; |
173 | typedef RBTREE<GlobalLabel> GlobalLabelList; |
174 | //typedef FIFO_INDEXED<GlobalLabel> GlobalLabelList; |
175 | |
176 | class CeeFileGenWriter; |
177 | class CeeSection; |
178 | |
179 | class BinStr; |
180 | |
181 | /************************************************************************/ |
182 | /* represents an object that knows how to report errors back to the user */ |
183 | |
184 | class ErrorReporter |
185 | { |
186 | public: |
187 | virtual void error(const char* fmt, ...) = 0; |
188 | virtual void warn(const char* fmt, ...) = 0; |
189 | virtual void msg(const char* fmt, ...) = 0; |
190 | }; |
191 | |
192 | /**************************************************************************/ |
193 | /* represents a switch table before the lables are bound */ |
194 | |
195 | struct Labels { |
196 | Labels(__in __nullterminated char* aLabel, Labels* aNext, bool aIsLabel) : Label(aLabel), Next(aNext), isLabel(aIsLabel) {} |
197 | ~Labels() { if(isLabel && Label) delete [] Label; delete Next; } |
198 | |
199 | char* Label; |
200 | Labels* Next; |
201 | bool isLabel; |
202 | }; |
203 | |
204 | /**************************************************************************/ |
205 | /* descriptor of the structured exception handling construct */ |
206 | struct SEH_Descriptor |
207 | { |
208 | DWORD sehClause; // catch/filter/finally |
209 | DWORD tryFrom; // start of try block |
210 | DWORD tryTo; // end of try block |
211 | DWORD sehHandler; // start of exception handler |
212 | DWORD sehHandlerTo; // end of exception handler |
213 | union { |
214 | DWORD sehFilter; // start of filter block |
215 | mdTypeRef cException; // what to catch |
216 | }; |
217 | |
218 | SEH_Descriptor() |
219 | { |
220 | memset(this, 0, sizeof(*this)); |
221 | } |
222 | }; |
223 | |
224 | |
225 | typedef LIFO<char> StringStack; |
226 | typedef LIFO<SEH_Descriptor> SEHD_Stack; |
227 | |
228 | typedef FIFO<Method> MethodList; |
229 | //typedef SORTEDARRAY<Method> MethodSortedList; |
230 | typedef FIFO<mdToken> TokenList; |
231 | /**************************************************************************/ |
232 | /* The field, event and property descriptor structures */ |
233 | |
234 | struct FieldDescriptor |
235 | { |
236 | mdTypeDef m_tdClass; |
237 | char* m_szName; |
238 | DWORD m_dwName; |
239 | mdFieldDef m_fdFieldTok; |
240 | ULONG m_ulOffset; |
241 | char* m_rvaLabel; // if field has RVA associated with it, label for it goes here. |
242 | BinStr* m_pbsSig; |
243 | Class* m_pClass; |
244 | BinStr* m_pbsValue; |
245 | BinStr* m_pbsMarshal; |
246 | PInvokeDescriptor* m_pPInvoke; |
247 | CustomDescrList m_CustomDescrList; |
248 | DWORD m_dwAttr; |
249 | BOOL m_fNew; |
250 | // Security attributes |
251 | PermissionDecl* m_pPermissions; |
252 | PermissionSetDecl* m_pPermissionSets; |
253 | FieldDescriptor() { m_szName = NULL; m_pbsSig = NULL; m_fNew = TRUE; }; |
254 | ~FieldDescriptor() { if(m_szName) delete [] m_szName; if(m_pbsSig) delete m_pbsSig; }; |
255 | }; |
256 | typedef FIFO<FieldDescriptor> FieldDList; |
257 | |
258 | struct EventDescriptor |
259 | { |
260 | mdTypeDef m_tdClass; |
261 | char* m_szName; |
262 | DWORD m_dwAttr; |
263 | mdToken m_tkEventType; |
264 | mdToken m_tkAddOn; |
265 | mdToken m_tkRemoveOn; |
266 | mdToken m_tkFire; |
267 | TokenList m_tklOthers; |
268 | mdEvent m_edEventTok; |
269 | BOOL m_fNew; |
270 | CustomDescrList m_CustomDescrList; |
271 | ~EventDescriptor() { m_tklOthers.RESET(false); }; |
272 | }; |
273 | typedef FIFO<EventDescriptor> EventDList; |
274 | |
275 | struct PropDescriptor |
276 | { |
277 | mdTypeDef m_tdClass; |
278 | char* m_szName; |
279 | DWORD m_dwAttr; |
280 | COR_SIGNATURE* m_pSig; |
281 | DWORD m_dwCSig; |
282 | DWORD m_dwCPlusTypeFlag; |
283 | PVOID m_pValue; |
284 | DWORD m_cbValue; |
285 | mdToken m_tkSet; |
286 | mdToken m_tkGet; |
287 | TokenList m_tklOthers; |
288 | mdProperty m_pdPropTok; |
289 | BOOL m_fNew; |
290 | CustomDescrList m_CustomDescrList; |
291 | ~PropDescriptor() { m_tklOthers.RESET(false); }; |
292 | }; |
293 | typedef FIFO<PropDescriptor> PropDList; |
294 | |
295 | struct ImportDescriptor |
296 | { |
297 | char* szDllName; |
298 | // char szDllName[MAX_FILENAME_LENGTH]; |
299 | DWORD dwDllName; |
300 | mdModuleRef mrDll; |
301 | ImportDescriptor(__in __nullterminated char* sz, DWORD l) |
302 | { |
303 | if((sz != NULL)&&(l > 0)) |
304 | { |
305 | szDllName = new char[l+1]; |
306 | if(szDllName != NULL) |
307 | { |
308 | memcpy(szDllName,sz,l); |
309 | szDllName[l] = 0; |
310 | dwDllName = l; |
311 | } |
312 | } |
313 | else |
314 | { |
315 | szDllName = NULL; |
316 | dwDllName = 0; |
317 | } |
318 | }; |
319 | ~ImportDescriptor() { delete [] szDllName; }; |
320 | }; |
321 | typedef FIFO<ImportDescriptor> ImportList; |
322 | |
323 | |
324 | /**************************************************************************/ |
325 | #include "class.hpp" |
326 | typedef LIFO<Class> ClassStack; |
327 | typedef FIFO<Class> ClassList; |
328 | //typedef SORTEDARRAY<Class> ClassHash; |
329 | typedef RBTREE<Class> ClassHash; |
330 | //typedef FIFO_INDEXED<Class> ClassHash; |
331 | |
332 | /**************************************************************************/ |
333 | /* Classes to hold lists of security permissions and permission sets. We build |
334 | these lists as we find security directives in the input stream and drain |
335 | them every time we see a class or method declaration (to which the |
336 | security info is attached). */ |
337 | |
338 | class PermissionDecl |
339 | { |
340 | public: |
341 | PermissionDecl(CorDeclSecurity action, mdToken type, NVPair *pairs) |
342 | { |
343 | m_Action = action; |
344 | m_TypeSpec = type; |
345 | m_pbsBlob = NULL; |
346 | BuildConstructorBlob(action, pairs); |
347 | m_Next = NULL; |
348 | } |
349 | |
350 | PermissionDecl(CorDeclSecurity action, mdToken type, BinStr* pbsPairs) |
351 | { |
352 | m_Action = action; |
353 | m_TypeSpec = type; |
354 | |
355 | m_pbsBlob = new BinStr(); |
356 | m_pbsBlob->appendInt16(VAL16(1)); // prolog 0x01 0x00 |
357 | m_pbsBlob->appendInt32((int)action); // 4-byte action |
358 | if(pbsPairs) // name-value pairs if any |
359 | { |
360 | if(pbsPairs->length() > 2) |
361 | m_pbsBlob->appendFrom(pbsPairs,2); |
362 | delete pbsPairs; |
363 | } |
364 | if(m_pbsBlob->length() == 6) // no pairs added |
365 | m_pbsBlob->appendInt16(0); |
366 | m_Blob = m_pbsBlob->ptr(); |
367 | m_BlobLength = m_pbsBlob->length(); |
368 | m_Next = NULL; |
369 | } |
370 | |
371 | ~PermissionDecl() |
372 | { |
373 | if(m_pbsBlob) delete m_pbsBlob; |
374 | else delete [] m_Blob; |
375 | } |
376 | |
377 | CorDeclSecurity m_Action; |
378 | mdToken m_TypeSpec; |
379 | BYTE *m_Blob; |
380 | BinStr *m_pbsBlob; |
381 | long m_BlobLength; |
382 | PermissionDecl *m_Next; |
383 | |
384 | private: |
385 | void BuildConstructorBlob(CorDeclSecurity action, NVPair *pairs) |
386 | { |
387 | NVPair *p = pairs; |
388 | int count = 0; |
389 | int bytes = 8; |
390 | int length; |
391 | int i; |
392 | BYTE *pBlob; |
393 | |
394 | // Calculate number of name/value pairs and the memory required for the |
395 | // custom attribute blob. |
396 | while (p) { |
397 | BYTE *pVal = (BYTE*)p->Value()->ptr(); |
398 | count++; |
399 | bytes += 2; // One byte field/property specifier, one byte type code |
400 | |
401 | length = (int)strlen((const char *)p->Name()->ptr()); |
402 | bytes += CPackedLen::Size(length) + length; |
403 | |
404 | switch (pVal[0]) { |
405 | case SERIALIZATION_TYPE_BOOLEAN: |
406 | bytes += 1; |
407 | break; |
408 | case SERIALIZATION_TYPE_I4: |
409 | bytes += 4; |
410 | break; |
411 | case SERIALIZATION_TYPE_STRING: |
412 | length = (int)strlen((const char *)&pVal[1]); |
413 | bytes += CPackedLen::Size(length) + length; |
414 | break; |
415 | case SERIALIZATION_TYPE_ENUM: |
416 | length = (int)strlen((const char *)&pVal[1]); |
417 | bytes += CPackedLen::Size((ULONG)length) + length; |
418 | bytes += 4; |
419 | break; |
420 | } |
421 | p = p->Next(); |
422 | } |
423 | |
424 | m_Blob = new BYTE[bytes]; |
425 | if(m_Blob==NULL) |
426 | { |
427 | fprintf(stderr,"\nOut of memory!\n" ); |
428 | return; |
429 | } |
430 | |
431 | m_Blob[0] = 0x01; // Version |
432 | m_Blob[1] = 0x00; |
433 | m_Blob[2] = (BYTE)action; // Constructor arg (security action code) |
434 | m_Blob[3] = 0x00; |
435 | m_Blob[4] = 0x00; |
436 | m_Blob[5] = 0x00; |
437 | m_Blob[6] = (BYTE)count; // Property/field count |
438 | m_Blob[7] = (BYTE)(count >> 8); |
439 | |
440 | for (i = 0, pBlob = &m_Blob[8], p = pairs; i < count; i++, p = p->Next()) { |
441 | BYTE *pVal = (BYTE*)p->Value()->ptr(); |
442 | char *szType; |
443 | |
444 | // Set field/property setter type. |
445 | *pBlob++ = SERIALIZATION_TYPE_PROPERTY; |
446 | |
447 | // Set type code. There's additional info for enums (the enum class |
448 | // name). |
449 | *pBlob++ = pVal[0]; |
450 | if (pVal[0] == SERIALIZATION_TYPE_ENUM) { |
451 | szType = (char *)&pVal[1]; |
452 | length = (int)strlen(szType); |
453 | pBlob = (BYTE*)CPackedLen::PutLength(pBlob, length); |
454 | strcpy_s((char *)pBlob, bytes, szType); |
455 | pBlob += length; |
456 | } |
457 | |
458 | // Record the field/property name. |
459 | length = (int)strlen((const char *)p->Name()->ptr()); |
460 | pBlob = (BYTE*)CPackedLen::PutLength(pBlob, length); |
461 | strcpy_s((char *)pBlob, bytes-(pBlob-m_Blob), (const char *)p->Name()->ptr()); |
462 | pBlob += length; |
463 | |
464 | // Record the serialized value. |
465 | switch (pVal[0]) { |
466 | case SERIALIZATION_TYPE_BOOLEAN: |
467 | *pBlob++ = pVal[1]; |
468 | break; |
469 | case SERIALIZATION_TYPE_I4: |
470 | *(__int32*)pBlob = *(__int32*)&pVal[1]; |
471 | pBlob += 4; |
472 | break; |
473 | case SERIALIZATION_TYPE_STRING: |
474 | length = (int)strlen((const char *)&pVal[1]); |
475 | pBlob = (BYTE*)CPackedLen::PutLength(pBlob, length); |
476 | strcpy_s((char *)pBlob, bytes-(pBlob-m_Blob), (const char *)&pVal[1]); |
477 | pBlob += length; |
478 | break; |
479 | case SERIALIZATION_TYPE_ENUM: |
480 | length = (int)strlen((const char *)&pVal[1]); |
481 | // We can have enums with base type of I1, I2 and I4. |
482 | switch (pVal[1 + length + 1]) { |
483 | case 1: |
484 | *(__int8*)pBlob = *(__int8*)&pVal[1 + length + 2]; |
485 | pBlob += 1; |
486 | break; |
487 | case 2: |
488 | *(__int16*)pBlob = *(__int16*)&pVal[1 + length + 2]; |
489 | pBlob += 2; |
490 | break; |
491 | case 4: |
492 | *(__int32*)pBlob = *(__int32*)&pVal[1 + length + 2]; |
493 | pBlob += 4; |
494 | break; |
495 | default: |
496 | _ASSERTE(!"Invalid enum size" ); |
497 | } |
498 | break; |
499 | } |
500 | |
501 | } |
502 | |
503 | _ASSERTE((pBlob - m_Blob) == bytes); |
504 | |
505 | m_BlobLength = (long)bytes; |
506 | } |
507 | }; |
508 | |
509 | class PermissionSetDecl |
510 | { |
511 | public: |
512 | PermissionSetDecl(CorDeclSecurity action, BinStr *value) |
513 | { |
514 | m_Action = action; |
515 | m_Value = value; |
516 | m_Next = NULL; |
517 | } |
518 | |
519 | ~PermissionSetDecl() |
520 | { |
521 | delete m_Value; |
522 | } |
523 | |
524 | CorDeclSecurity m_Action; |
525 | BinStr *m_Value; |
526 | PermissionSetDecl *m_Next; |
527 | }; |
528 | |
529 | struct VTFEntry |
530 | { |
531 | char* m_szLabel; |
532 | WORD m_wCount; |
533 | WORD m_wType; |
534 | VTFEntry(WORD wCount, WORD wType, __in __nullterminated char* szLabel) { m_wCount = wCount; m_wType = wType; m_szLabel = szLabel; } |
535 | ~VTFEntry() { delete m_szLabel; } |
536 | }; |
537 | typedef FIFO<VTFEntry> VTFList; |
538 | |
539 | struct EATEntry |
540 | { |
541 | DWORD dwStubRVA; |
542 | DWORD dwOrdinal; |
543 | char* szAlias; |
544 | }; |
545 | typedef FIFO<EATEntry> EATList; |
546 | |
547 | struct DocWriter |
548 | { |
549 | char* Name; |
550 | ISymUnmanagedDocumentWriter* pWriter; |
551 | DocWriter() { Name=NULL; pWriter=NULL; }; |
552 | ~DocWriter() { delete [] Name; if(pWriter) pWriter->Release();}; |
553 | }; |
554 | typedef FIFO<DocWriter> DocWriterList; |
555 | /**************************************************************************/ |
556 | /* The assembler object does all the code generation (dealing with meta-data) |
557 | writing a PE file etc etc. But does NOT deal with syntax (that is what |
558 | AsmParse is for). Thus the API below is how AsmParse 'controls' the |
559 | Assember. Note that the Assembler object does know about the |
560 | AsmParse object (that is Assember is more fundamental than AsmParse) */ |
561 | struct Instr |
562 | { |
563 | int opcode; |
564 | unsigned linenum; |
565 | unsigned column; |
566 | unsigned linenum_end; |
567 | unsigned column_end; |
568 | unsigned pc; |
569 | ISymUnmanagedDocumentWriter* pWriter; |
570 | }; |
571 | #define INSTR_POOL_SIZE 16 |
572 | |
573 | // For code folding: |
574 | struct MethodBody |
575 | { |
576 | BinStr* pbsBody; |
577 | unsigned RVA; |
578 | BYTE* pCode; |
579 | }; |
580 | typedef FIFO<MethodBody> MethodBodyList; |
581 | |
582 | struct Clockwork |
583 | { |
584 | DWORD cBegin; |
585 | DWORD cEnd; |
586 | DWORD cParsBegin; |
587 | DWORD cParsEnd; |
588 | DWORD cMDInitBegin; |
589 | DWORD cMDInitEnd; |
590 | DWORD cMDEmitBegin; |
591 | DWORD cMDEmitEnd; |
592 | DWORD cMDEmit1; |
593 | DWORD cMDEmit2; |
594 | DWORD cMDEmit3; |
595 | DWORD cMDEmit4; |
596 | DWORD cRef2DefBegin; |
597 | DWORD cRef2DefEnd; |
598 | DWORD cFilegenBegin; |
599 | DWORD cFilegenEnd; |
600 | }; |
601 | |
602 | struct TypeDefDescr |
603 | { |
604 | char* m_szName; |
605 | union |
606 | { |
607 | BinStr* m_pbsTypeSpec; |
608 | CustomDescr* m_pCA; |
609 | }; |
610 | mdToken m_tkTypeSpec; |
611 | TypeDefDescr(__in_opt __nullterminated char *pszName, BinStr* pbsTypeSpec, mdToken tkTypeSpec) |
612 | { |
613 | m_szName = pszName; |
614 | m_pbsTypeSpec = pbsTypeSpec; |
615 | m_tkTypeSpec = tkTypeSpec; |
616 | }; |
617 | ~TypeDefDescr() { delete [] m_szName; delete m_pbsTypeSpec; }; |
618 | int ComparedTo(TypeDefDescr* T) { return strcmp(m_szName,T->m_szName); }; |
619 | //int Compare(char* T) { return strcmp(T,m_szName); }; |
620 | }; |
621 | typedef SORTEDARRAY<TypeDefDescr> TypeDefDList; |
622 | |
623 | struct Indx |
624 | { |
625 | void* table[128]; |
626 | Indx() { memset(table,0,sizeof(table)); }; |
627 | ~Indx() |
628 | { |
629 | for(int i = 1; i < 128; i++) delete ((Indx*)(table[i])); |
630 | }; |
631 | void IndexString(__in_z __in char* psz, void* pkywd) |
632 | { |
633 | int i = (int) *psz; |
634 | if(i == 0) |
635 | table[0] = pkywd; |
636 | else |
637 | { |
638 | _ASSERTE((i > 0)&&(i <= 127)); |
639 | Indx* pInd = (Indx*)(table[i]); |
640 | if(pInd == NULL) |
641 | { |
642 | pInd = new Indx; |
643 | _ASSERTE(pInd); |
644 | table[i] = pInd; |
645 | } |
646 | pInd->IndexString(psz+1,pkywd); |
647 | } |
648 | } |
649 | void* FindString(__in __nullterminated char* psz) |
650 | { |
651 | if(*psz > 0) |
652 | { |
653 | unsigned char uch = (unsigned char) *psz; |
654 | if(table[uch] != NULL) |
655 | return ((Indx*)(table[uch]))->FindString(psz+1); |
656 | } |
657 | else if(*psz == 0) return table[0]; |
658 | return NULL; |
659 | } |
660 | }; |
661 | |
662 | class Assembler { |
663 | public: |
664 | Assembler(); |
665 | ~Assembler(); |
666 | //-------------------------------------------------------- |
667 | GlobalLabelList m_lstGlobalLabel; |
668 | GlobalFixupList m_lstGlobalFixup; |
669 | |
670 | LabelList m_lstLabel; |
671 | |
672 | Class * m_pModuleClass; |
673 | ClassList m_lstClass; |
674 | ClassHash m_hshClass; |
675 | |
676 | Indx indxKeywords; |
677 | |
678 | BYTE * m_pOutputBuffer; |
679 | BYTE * m_pCurOutputPos; |
680 | BYTE * m_pEndOutputPos; |
681 | |
682 | |
683 | DWORD m_CurPC; |
684 | BOOL m_fStdMapping; |
685 | BOOL m_fDisplayTraceOutput; |
686 | BOOL m_fInitialisedMetaData; |
687 | BOOL m_fAutoInheritFromObject; |
688 | BOOL m_fReportProgress; |
689 | BOOL m_fIsMscorlib; |
690 | BOOL m_fTolerateDupMethods; |
691 | BOOL m_fENCMode; |
692 | BOOL m_fOptimize; |
693 | mdToken m_tkSysObject; |
694 | mdToken m_tkSysString; |
695 | mdToken m_tkSysValue; |
696 | mdToken m_tkSysEnum; |
697 | BOOL m_fDidCoInitialise; |
698 | |
699 | IMetaDataDispenserEx *m_pDisp; |
700 | IMetaDataEmit2 *m_pEmitter; |
701 | ICeeFileGen *m_pCeeFileGen; |
702 | IMetaDataImport2 *m_pImporter; // Import interface. |
703 | HCEEFILE m_pCeeFile; |
704 | HCEESECTION m_pGlobalDataSection; |
705 | HCEESECTION m_pILSection; |
706 | HCEESECTION m_pTLSSection; |
707 | HCEESECTION m_pCurSection; // The section EmitData* things go to |
708 | |
709 | AsmMan* m_pManifest; |
710 | |
711 | char m_szScopeName[MAX_SCOPE_LENGTH]; |
712 | char *m_szNamespace; //[MAX_NAMESPACE_LENGTH]; |
713 | char *m_szFullNS; //[MAX_NAMESPACE_LENGTH]; |
714 | unsigned m_ulFullNSLen; |
715 | |
716 | WCHAR *m_wzMetadataVersion; |
717 | |
718 | StringStack m_NSstack; |
719 | mdTypeSpec m_crExtends; |
720 | |
721 | // char m_szExtendsClause[MAX_CLASSNAME_LENGTH]; |
722 | |
723 | // The (resizable) array of "implements" types |
724 | mdToken *m_crImplList; |
725 | int m_nImplList; |
726 | int m_nImplListSize; |
727 | |
728 | TyParList *m_TyParList; |
729 | |
730 | Method *m_pCurMethod; |
731 | Class *m_pCurClass; |
732 | ClassStack m_ClassStack; // for nested classes |
733 | Class *dummyClass; // for FindCreateClass |
734 | |
735 | // moved to Class |
736 | //MethodList m_MethodList; |
737 | |
738 | BOOL m_fCPlusPlus; |
739 | BOOL m_fWindowsCE; |
740 | BOOL m_fDLL; |
741 | BOOL m_fOBJ; |
742 | BOOL m_fEntryPointPresent; |
743 | BOOL m_fHaveFieldsWithRvas; |
744 | BOOL m_fFoldCode; |
745 | DWORD m_dwMethodsFolded; |
746 | |
747 | state_t m_State; |
748 | |
749 | BinStr* m_pbsMD; |
750 | |
751 | Instr m_Instr[INSTR_POOL_SIZE]; // 16 |
752 | inline Instr* GetInstr() |
753 | { |
754 | int i; |
755 | for(i=0; (i<INSTR_POOL_SIZE)&&(m_Instr[i].opcode != -1); i++); |
756 | if(i<INSTR_POOL_SIZE) return &m_Instr[i]; |
757 | report->error("Instruction pool exhausted: source contains invalid instructions\n" ); |
758 | return NULL; |
759 | } |
760 | // Labels, fixups and IL fixups are defined in Method.hpp,.cpp |
761 | void AddLabel(DWORD CurPC, __in __nullterminated char *pszName); |
762 | void AddDeferredFixup(__in __nullterminated char *pszLabel, BYTE *pBytes, DWORD RelativeToPC, BYTE FixupSize); |
763 | void AddDeferredILFixup(ILFixupType Kind); |
764 | void AddDeferredILFixup(ILFixupType Kind, GlobalFixup *GFixup); |
765 | void DoDeferredILFixups(Method* pMethod); |
766 | BOOL DoFixups(Method* pMethod); |
767 | //-------------------------------------------------------------------------------- |
768 | void ClearImplList(void); |
769 | void AddToImplList(mdToken); |
770 | void ClearBoundList(void); |
771 | //-------------------------------------------------------------------------------- |
772 | BOOL Init(); |
773 | void ProcessLabel(__in_z __in char *pszName); |
774 | GlobalLabel *FindGlobalLabel(LPCUTF8 pszName); |
775 | GlobalFixup *AddDeferredGlobalFixup(__in __nullterminated char *pszLabel, BYTE* reference); |
776 | //void AddDeferredDescrFixup(__in __nullterminated char *pszLabel); |
777 | BOOL DoGlobalFixups(); |
778 | BOOL DoDescrFixups(); |
779 | OPCODE DecodeOpcode(const BYTE *pCode, DWORD *pdwLen); |
780 | BOOL AddMethod(Method *pMethod); |
781 | void SetTLSSection() { m_pCurSection = m_pTLSSection; } |
782 | void SetILSection() { m_pCurSection = m_pILSection; } |
783 | void SetDataSection() { m_pCurSection = m_pGlobalDataSection; } |
784 | BOOL EmitMethod(Method *pMethod); |
785 | BOOL EmitMethodBody(Method* pMethod, BinStr* pbsOut); |
786 | BOOL EmitClass(Class *pClass); |
787 | HRESULT CreatePEFile(__in __nullterminated WCHAR *pwzOutputFilename); |
788 | HRESULT CreateTLSDirectory(); |
789 | HRESULT CreateDebugDirectory(); |
790 | HRESULT InitMetaData(); |
791 | Class *FindCreateClass(__in __nullterminated const char *pszFQN); |
792 | BOOL EmitFieldRef(__in_z __in char *pszArg, int opcode); |
793 | BOOL EmitSwitchData(__in_z __in char *pszArg); |
794 | mdToken ResolveClassRef(mdToken tkResScope, __in __nullterminated const char *pszClassName, Class** ppClass); |
795 | mdToken ResolveTypeSpec(BinStr* typeSpec); |
796 | mdToken GetBaseAsmRef(); |
797 | mdToken GetAsmRef(__in __nullterminated const char* szName); |
798 | mdToken GetModRef(__in __nullterminated char* szName); |
799 | mdToken GetInterfaceImpl(mdToken tsClass, mdToken tsInterface); |
800 | char* ReflectionNotation(mdToken tk); |
801 | HRESULT ConvLocalSig(__in char* localsSig, CQuickBytes* corSig, DWORD* corSigLen, BYTE*& localTypes); |
802 | DWORD GetCurrentILSectionOffset(); |
803 | BOOL EmitCALLISig(__in char *p); |
804 | void AddException(DWORD pcStart, DWORD pcEnd, DWORD pcHandler, DWORD pcHandlerTo, mdTypeRef crException, BOOL isFilter, BOOL isFault, BOOL isFinally); |
805 | state_t CheckLocalTypeConsistancy(int instr, unsigned arg); |
806 | state_t AddGlobalLabel(__in __nullterminated char *pszName, HCEESECTION section); |
807 | void SetDLL(BOOL); |
808 | void SetOBJ(BOOL); |
809 | void ResetForNextMethod(); |
810 | void ResetLineNumbers(); |
811 | void SetStdMapping(BOOL val = TRUE) { m_fStdMapping = val; }; |
812 | |
813 | //-------------------------------------------------------------------------------- |
814 | BOOL isShort(unsigned instr) { return ((OpcodeInfo[instr].Type & 16) != 0); }; |
815 | unsigned ShortOf(unsigned opcode); |
816 | void SetErrorReporter(ErrorReporter* aReport) { report = aReport; if(m_pManifest) m_pManifest->SetErrorReporter(aReport); } |
817 | |
818 | void StartNameSpace(__in __nullterminated char* name); |
819 | void EndNameSpace(); |
820 | void StartClass(__in __nullterminated char* name, DWORD attr, TyParList *typars); |
821 | DWORD CheckClassFlagsIfNested(Class* pEncloser, DWORD attr); |
822 | void AddClass(); |
823 | void EndClass(); |
824 | void StartMethod(__in __nullterminated char* name, BinStr* sig, CorMethodAttr flags, BinStr* retMarshal, DWORD retAttr, TyParList *typars = NULL); |
825 | void EndMethod(); |
826 | |
827 | void AddField(__inout_z __inout char* name, BinStr* sig, CorFieldAttr flags, __in __nullterminated char* rvaLabel, BinStr* pVal, ULONG ulOffset); |
828 | BOOL EmitField(FieldDescriptor* pFD); |
829 | void EmitByte(int val); |
830 | //void EmitTry(enum CorExceptionFlag kind, char* beginLabel, char* endLabel, char* handleLabel, char* filterOrClass); |
831 | void EmitMaxStack(unsigned val); |
832 | void EmitLocals(BinStr* sig); |
833 | void EmitEntryPoint(); |
834 | void EmitZeroInit(); |
835 | void SetImplAttr(unsigned short attrval); |
836 | |
837 | // Emits zeros if the buffer parameter is NULL. |
838 | void EmitData(__in_opt void *buffer, unsigned len); |
839 | |
840 | void EmitDD(__in __nullterminated char *str); |
841 | void EmitDataString(BinStr* str); |
842 | |
843 | void EmitInstrVar(Instr* instr, int var); |
844 | void EmitInstrVarByName(Instr* instr, __in __nullterminated char* label); |
845 | void EmitInstrI(Instr* instr, int val); |
846 | void EmitInstrI8(Instr* instr, __int64* val); |
847 | void EmitInstrR(Instr* instr, double* val); |
848 | void EmitInstrBrOffset(Instr* instr, int offset); |
849 | void EmitInstrBrTarget(Instr* instr, __in __nullterminated char* label); |
850 | mdToken MakeMemberRef(mdToken typeSpec, __in __nullterminated char* name, BinStr* sig); |
851 | mdToken MakeMethodSpec(mdToken tkParent, BinStr* sig); |
852 | void SetMemberRefFixup(mdToken tk, unsigned opcode_len); |
853 | mdToken MakeTypeRef(mdToken tkResScope, LPCUTF8 szFullName); |
854 | void EmitInstrStringLiteral(Instr* instr, BinStr* literal, BOOL ConvertToUnicode, BOOL Swap = FALSE); |
855 | void EmitInstrSig(Instr* instr, BinStr* sig); |
856 | void EmitInstrSwitch(Instr* instr, Labels* targets); |
857 | void EmitLabel(__in __nullterminated char* label); |
858 | void EmitDataLabel(__in __nullterminated char* label); |
859 | |
860 | unsigned OpcodeLen(Instr* instr); //returns opcode length |
861 | // Emit just the opcode (no parameters to the instruction stream. |
862 | void EmitOpcode(Instr* instr); |
863 | |
864 | // Emit primitive types to the instruction stream. |
865 | void EmitBytes(BYTE*, unsigned len); |
866 | |
867 | ErrorReporter* report; |
868 | |
869 | BOOL EmitFieldsMethods(Class* pClass); |
870 | BOOL EmitEventsProps(Class* pClass); |
871 | |
872 | // named args/vars paraphernalia: |
873 | public: |
874 | void addArgName(__in_opt __nullterminated char *szNewName, BinStr* pbSig, BinStr* pbMarsh, DWORD dwAttr) |
875 | { |
876 | if(pbSig && (*(pbSig->ptr()) == ELEMENT_TYPE_VOID)) |
877 | report->error("Illegal use of type 'void'\n" ); |
878 | if(m_lastArgName) |
879 | { |
880 | m_lastArgName->pNext = new ARG_NAME_LIST(m_lastArgName->nNum+1,szNewName,pbSig,pbMarsh,dwAttr); |
881 | m_lastArgName = m_lastArgName->pNext; |
882 | } |
883 | else |
884 | { |
885 | m_lastArgName = new ARG_NAME_LIST(0,szNewName,pbSig,pbMarsh,dwAttr); |
886 | m_firstArgName = m_lastArgName; |
887 | } |
888 | }; |
889 | ARG_NAME_LIST *getArgNameList(void) |
890 | { ARG_NAME_LIST *pRet = m_firstArgName; m_firstArgName=NULL; m_lastArgName=NULL; return pRet;}; |
891 | // Added because recursive destructor of ARG_NAME_LIST may overflow the system stack |
892 | void delArgNameList(ARG_NAME_LIST *pFirst) |
893 | { |
894 | ARG_NAME_LIST *pArgList=pFirst, *pArgListNext; |
895 | for(; pArgList; pArgListNext=pArgList->pNext, |
896 | delete pArgList, |
897 | pArgList=pArgListNext); |
898 | }; |
899 | |
900 | ARG_NAME_LIST *findArg(ARG_NAME_LIST *pFirst, int num) |
901 | { |
902 | ARG_NAME_LIST *pAN; |
903 | for(pAN=pFirst; pAN; pAN = pAN->pNext) |
904 | { |
905 | if(pAN->nNum == num) return pAN; |
906 | } |
907 | return NULL; |
908 | }; |
909 | ARG_NAME_LIST *m_firstArgName; |
910 | ARG_NAME_LIST *m_lastArgName; |
911 | void ResetArgNameList(); |
912 | |
913 | // Structured exception handling paraphernalia: |
914 | public: |
915 | SEH_Descriptor *m_SEHD; // current descriptor ptr |
916 | void NewSEHDescriptor(void); //sets m_SEHD |
917 | void SetTryLabels(__in __nullterminated char * szFrom, __in __nullterminated char *szTo); |
918 | void SetFilterLabel(__in __nullterminated char *szFilter); |
919 | void SetCatchClass(mdToken catchClass); |
920 | void SetHandlerLabels(__in __nullterminated char *szHandlerFrom, __in __nullterminated char *szHandlerTo); |
921 | void EmitTry(void); //uses m_SEHD |
922 | |
923 | //private: |
924 | SEHD_Stack m_SEHDstack; |
925 | |
926 | // Events and Properties paraphernalia: |
927 | public: |
928 | void EndEvent(void); //emits event definition |
929 | void EndProp(void); //emits property definition |
930 | void ResetEvent(__inout_z __inout char * szName, mdToken typeSpec, DWORD dwAttr); |
931 | void ResetProp(__inout_z __inout char * szName, BinStr* bsType, DWORD dwAttr, BinStr* bsValue); |
932 | void SetEventMethod(int MethodCode, mdToken tk); |
933 | void SetPropMethod(int MethodCode, mdToken tk); |
934 | BOOL EmitEvent(EventDescriptor* pED); // impl. in ASSEM.CPP |
935 | BOOL EmitProp(PropDescriptor* pPD); // impl. in ASSEM.CPP |
936 | EventDescriptor* m_pCurEvent; |
937 | PropDescriptor* m_pCurProp; |
938 | |
939 | private: |
940 | MemberRefDList m_LocalMethodRefDList; |
941 | MemberRefDList m_LocalFieldRefDList; |
942 | LocalMemberRefFixupList m_LocalMemberRefFixupList; |
943 | MethodBodyList m_MethodBodyList; |
944 | MemberRefDList m_MethodSpecList; |
945 | public: |
946 | HRESULT ResolveLocalMemberRefs(); |
947 | HRESULT DoLocalMemberRefFixups(); |
948 | mdToken ResolveLocalMemberRef(mdToken tok); |
949 | |
950 | // PInvoke paraphernalia |
951 | public: |
952 | PInvokeDescriptor* m_pPInvoke; |
953 | ImportList m_ImportList; |
954 | void SetPinvoke(BinStr* DllName, int Ordinal, BinStr* Alias, int Attrs); |
955 | HRESULT EmitPinvokeMap(mdToken tk, PInvokeDescriptor* pDescr); |
956 | ImportDescriptor* EmitImport(BinStr* DllName); |
957 | void EmitImports(); |
958 | |
959 | // Debug metadata paraphernalia |
960 | public: |
961 | ISymUnmanagedWriter* m_pSymWriter; |
962 | ISymUnmanagedDocumentWriter* m_pSymDocument; |
963 | DocWriterList m_DocWriterList; |
964 | ULONG m_ulCurLine; // set by Parser |
965 | ULONG m_ulCurColumn; // set by Parser |
966 | ULONG m_ulLastDebugLine; |
967 | ULONG m_ulLastDebugColumn; |
968 | ULONG m_ulLastDebugLineEnd; |
969 | ULONG m_ulLastDebugColumnEnd; |
970 | DWORD m_dwIncludeDebugInfo; |
971 | BOOL m_fGeneratePDB; |
972 | char m_szSourceFileName[MAX_FILENAME_LENGTH*3+1]; |
973 | WCHAR m_wzOutputFileName[MAX_FILENAME_LENGTH]; |
974 | WCHAR m_wzSourceFileName[MAX_FILENAME_LENGTH]; |
975 | GUID m_guidLang; |
976 | GUID m_guidLangVendor; |
977 | GUID m_guidDoc; |
978 | |
979 | // Security paraphernalia |
980 | public: |
981 | void AddPermissionDecl(CorDeclSecurity action, mdToken type, NVPair *pairs) |
982 | { |
983 | PermissionDecl *decl = new PermissionDecl(action, type, pairs); |
984 | if(decl==NULL) |
985 | { |
986 | report->error("\nOut of memory!\n" ); |
987 | return; |
988 | } |
989 | if (m_pCurMethod) { |
990 | decl->m_Next = m_pCurMethod->m_pPermissions; |
991 | m_pCurMethod->m_pPermissions = decl; |
992 | } else if (m_pCurClass) { |
993 | decl->m_Next = m_pCurClass->m_pPermissions; |
994 | m_pCurClass->m_pPermissions = decl; |
995 | } else if (m_pManifest && m_pManifest->m_pAssembly) { |
996 | decl->m_Next = m_pManifest->m_pAssembly->m_pPermissions; |
997 | m_pManifest->m_pAssembly->m_pPermissions = decl; |
998 | } else { |
999 | report->error("Cannot declare security permissions without the owner\n" ); |
1000 | delete decl; |
1001 | } |
1002 | }; |
1003 | |
1004 | void AddPermissionDecl(CorDeclSecurity action, mdToken type, BinStr *pbsPairs) |
1005 | { |
1006 | PermissionDecl *decl = new PermissionDecl(action, type, pbsPairs); |
1007 | if(decl==NULL) |
1008 | { |
1009 | report->error("\nOut of memory!\n" ); |
1010 | return; |
1011 | } |
1012 | if (m_pCurMethod) { |
1013 | decl->m_Next = m_pCurMethod->m_pPermissions; |
1014 | m_pCurMethod->m_pPermissions = decl; |
1015 | } else if (m_pCurClass) { |
1016 | decl->m_Next = m_pCurClass->m_pPermissions; |
1017 | m_pCurClass->m_pPermissions = decl; |
1018 | } else if (m_pManifest && m_pManifest->m_pAssembly) { |
1019 | decl->m_Next = m_pManifest->m_pAssembly->m_pPermissions; |
1020 | m_pManifest->m_pAssembly->m_pPermissions = decl; |
1021 | } else { |
1022 | report->error("Cannot declare security permissions without the owner\n" ); |
1023 | delete decl; |
1024 | } |
1025 | }; |
1026 | |
1027 | void AddPermissionSetDecl(CorDeclSecurity action, BinStr *value) |
1028 | { |
1029 | PermissionSetDecl *decl = new PermissionSetDecl(action, value); |
1030 | if(decl==NULL) |
1031 | { |
1032 | report->error("\nOut of memory!\n" ); |
1033 | return; |
1034 | } |
1035 | if (m_pCurMethod) { |
1036 | decl->m_Next = m_pCurMethod->m_pPermissionSets; |
1037 | m_pCurMethod->m_pPermissionSets = decl; |
1038 | } else if (m_pCurClass) { |
1039 | decl->m_Next = m_pCurClass->m_pPermissionSets; |
1040 | m_pCurClass->m_pPermissionSets = decl; |
1041 | } else if (m_pManifest && m_pManifest->m_pAssembly) { |
1042 | decl->m_Next = m_pManifest->m_pAssembly->m_pPermissionSets; |
1043 | m_pManifest->m_pAssembly->m_pPermissionSets = decl; |
1044 | } else { |
1045 | report->error("Cannot declare security permission sets without the owner\n" ); |
1046 | delete decl; |
1047 | } |
1048 | }; |
1049 | void EmitSecurityInfo(mdToken token, |
1050 | PermissionDecl* pPermissions, |
1051 | PermissionSetDecl*pPermissionSets); |
1052 | BinStr* EncodeSecAttr(__in __nullterminated char* szReflName, BinStr* pbsSecAttrBlob, unsigned nProps); |
1053 | |
1054 | HRESULT AllocateStrongNameSignature(); |
1055 | |
1056 | // Custom values paraphernalia: |
1057 | public: |
1058 | mdToken m_tkCurrentCVOwner; |
1059 | CustomDescrList* m_pCustomDescrList; |
1060 | CustomDescrListStack m_CustomDescrListStack; |
1061 | CustomDescrList m_CustomDescrList; |
1062 | |
1063 | void DefineCV(CustomDescr* pCD) |
1064 | { |
1065 | if(pCD) |
1066 | { |
1067 | ULONG cTemp = 0; |
1068 | void * pBlobBody = NULL; |
1069 | mdToken cv; |
1070 | mdToken tkOwnerType, tkTypeType = TypeFromToken(pCD->tkType); |
1071 | |
1072 | if((tkTypeType != 0x99000000)&&(tkTypeType != 0x98000000)) |
1073 | { |
1074 | tkOwnerType = TypeFromToken(pCD->tkOwner); |
1075 | if((tkOwnerType != 0x99000000)&&(tkOwnerType != 0x98000000)) |
1076 | { |
1077 | if(pCD->pBlob) |
1078 | { |
1079 | pBlobBody = (void *)(pCD->pBlob->ptr()); |
1080 | cTemp = pCD->pBlob->length(); |
1081 | } |
1082 | if (pCD->tkInterfacePair) |
1083 | { |
1084 | pCD->tkOwner = GetInterfaceImpl(pCD->tkOwner, pCD->tkInterfacePair); |
1085 | } |
1086 | m_pEmitter->DefineCustomAttribute(pCD->tkOwner,pCD->tkType,pBlobBody,cTemp,&cv); |
1087 | |
1088 | delete pCD; |
1089 | return; |
1090 | } |
1091 | } |
1092 | m_CustomDescrList.PUSH(pCD); |
1093 | } |
1094 | }; |
1095 | void EmitCustomAttributes(mdToken tok, CustomDescrList* pCDL) |
1096 | { |
1097 | CustomDescr *pCD; |
1098 | if(pCDL == NULL || RidFromToken(tok)==0) return; |
1099 | while((pCD = pCDL->POP())) |
1100 | { |
1101 | pCD->tkOwner = tok; |
1102 | DefineCV(pCD); |
1103 | } |
1104 | }; |
1105 | |
1106 | void EmitUnresolvedCustomAttributes(); // implementation: writer.cpp |
1107 | // VTable blob (if any) |
1108 | public: |
1109 | BinStr *m_pVTable; |
1110 | // Field marshaling |
1111 | BinStr *m_pMarshal; |
1112 | // VTable fixup list |
1113 | VTFList m_VTFList; |
1114 | // Export Address Table entries list |
1115 | EATList m_EATList; |
1116 | HRESULT CreateExportDirectory(); |
1117 | DWORD EmitExportStub(DWORD dwVTFSlotRVA); |
1118 | |
1119 | // Method implementation paraphernalia: |
1120 | private: |
1121 | MethodImplDList m_MethodImplDList; |
1122 | public: |
1123 | void AddMethodImpl(mdToken tkImplementedTypeSpec, __in __nullterminated char* szImplementedName, BinStr* pImplementedSig, |
1124 | mdToken tkImplementingTypeSpec, __in_opt __nullterminated char* szImplementingName, BinStr* pImplementingSig); |
1125 | BOOL EmitMethodImpls(); |
1126 | // lexical scope handling paraphernalia: |
1127 | void EmitScope(Scope* pSCroot); // struct Scope - see Method.hpp |
1128 | // source file name paraphernalia |
1129 | BOOL m_fSourceFileSet; |
1130 | void SetSourceFileName(__in __nullterminated char* szName); |
1131 | void SetSourceFileName(BinStr* pbsName); |
1132 | // header flags |
1133 | DWORD m_dwSubsystem; |
1134 | WORD m_wSSVersionMajor; |
1135 | WORD m_wSSVersionMinor; |
1136 | DWORD m_dwComImageFlags; |
1137 | DWORD m_dwFileAlignment; |
1138 | ULONGLONG m_stBaseAddress; |
1139 | size_t m_stSizeOfStackReserve; |
1140 | DWORD m_dwCeeFileFlags; |
1141 | WORD m_wMSVmajor; |
1142 | WORD m_wMSVminor; |
1143 | BOOL m_fAppContainer; |
1144 | BOOL m_fHighEntropyVA; |
1145 | |
1146 | // Former globals |
1147 | WCHAR *m_wzResourceFile; |
1148 | WCHAR *m_wzKeySourceName; |
1149 | bool OnErrGo; |
1150 | void SetCodePage(unsigned val) { g_uCodePage = val; }; |
1151 | Clockwork* bClock; |
1152 | void SetClock(Clockwork* val) { bClock = val; }; |
1153 | // ENC paraphernalia |
1154 | HRESULT InitMetaDataForENC(__in __nullterminated WCHAR* wzOrigFileName); |
1155 | BOOL EmitFieldsMethodsENC(Class* pClass); |
1156 | BOOL EmitEventsPropsENC(Class* pClass); |
1157 | HRESULT CreateDeltaFiles(__in __nullterminated WCHAR *pwzOutputFilename); |
1158 | |
1159 | // Syntactic sugar paraphernalia |
1160 | private: |
1161 | TypeDefDList m_TypeDefDList; |
1162 | public: |
1163 | void AddTypeDef(BinStr* pbsTypeSpec, __in_z __in char* szName) |
1164 | { |
1165 | m_TypeDefDList.PUSH(new TypeDefDescr(szName, pbsTypeSpec, ResolveTypeSpec(pbsTypeSpec))); |
1166 | }; |
1167 | void AddTypeDef(mdToken tkTypeSpec, __in_z __in char* szName) |
1168 | { |
1169 | m_TypeDefDList.PUSH(new TypeDefDescr(szName, NULL, tkTypeSpec)); |
1170 | }; |
1171 | void AddTypeDef(CustomDescr* pCA, __in_z __in char* szName) |
1172 | { |
1173 | TypeDefDescr* pNew = new TypeDefDescr(szName,NULL,mdtCustomAttribute); |
1174 | pNew->m_pCA = pCA; |
1175 | m_TypeDefDList.PUSH(pNew); |
1176 | }; |
1177 | TypeDefDescr* FindTypeDef(__in_z __in char* szName) |
1178 | { |
1179 | CHECK_LOCAL_STATIC_VAR(static TypeDefDescr X(NULL, NULL, 0)); |
1180 | |
1181 | X.m_szName = szName; |
1182 | TypeDefDescr* Y = m_TypeDefDList.FIND(&X); |
1183 | X.m_szName = NULL; // to avoid deletion when X goes out of scope |
1184 | return Y; |
1185 | //return m_TypeDefDList.FIND(szName); |
1186 | }; |
1187 | unsigned NumTypeDefs() {return m_TypeDefDList.COUNT();}; |
1188 | private: |
1189 | HRESULT GetCAName(mdToken tkCA, __out LPWSTR *ppszName); |
1190 | }; |
1191 | |
1192 | #endif // Assember_h |
1193 | |
1194 | #ifdef _MSC_VER |
1195 | #pragma warning(default : 4640) |
1196 | #endif |
1197 | |
1198 | |
1199 | |