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 /************************************************************************/
6 /************************************************************************/
11 #define NEW_INLINE_NAMES
15 #include "specstrings.h"
18 #include "asmtemplates.h"
20 // Disable the "initialization of static local vars is no thread safe" error
22 #pragma warning(disable : 4640)
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
37 #define MAX_NAMESPACE_LENGTH 1024 //256 //64
38 #define MAX_MEMBER_NAME_LENGTH 1024 //256 //64
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
46 #define BASE_OBJECT_CLASSNAME "System.Object"
47 #define MAX_MANIFEST_RESOURCES 1024
49 // Fully-qualified class name separators:
50 #define NESTING_SEP ((char)0xF8)
52 #define dwUniBuf 16384
55 #include "coreclrloader.h"
56 extern CoreCLRLoader *g_loader;
57 extern char *g_pszExeFile;
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.
64 extern MetaDataGetDispenserFunc metaDataGetDispenser;
66 extern WCHAR wzUniBuf[]; // Unicode conversion global buffer (assem.cpp)
71 class PermissionSetDecl;
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 */
78 struct MemberRefDescriptor
87 typedef FIFO<MemberRefDescriptor> MemberRefDList;
90 struct MethodImplDescriptor
92 mdToken m_tkImplementedMethod;
93 mdToken m_tkImplementingMethod;
94 mdToken m_tkDefiningClass;
97 typedef FIFO<MethodImplDescriptor> MethodImplDList;
99 struct LocalMemberRefFixup
104 LocalMemberRefFixup(mdToken TK, size_t Offset)
111 typedef FIFO<LocalMemberRefFixup> LocalMemberRefFixupList;
117 mdToken tkInterfacePair; // Needed for InterfaceImpl CA's
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; };
124 typedef FIFO<CustomDescr> CustomDescrList;
125 typedef LIFO<CustomDescrList> CustomDescrListStack;
126 /**************************************************************************/
128 #include "method.hpp"
129 #include "iceefilegen.h"
130 #include "asmman.hpp"
148 DWORD m_GlobalOffset;
149 HCEESECTION m_Section;
152 GlobalLabel(LPCUTF8 pszName, DWORD GlobalOffset, HCEESECTION section)
154 m_GlobalOffset = GlobalOffset;
157 m_Hash = hash((const BYTE*)pszName, (unsigned)strlen(pszName),10);
160 ~GlobalLabel(){ delete [] m_szName; }
162 int ComparedTo(GlobalLabel* L)
164 return (m_Hash == L->m_Hash) ? strcmp(m_szName, L->m_szName)
165 : ((m_Hash > L->m_Hash) ? 1 : -1);
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; };
172 //typedef SORTEDARRAY<GlobalLabel> GlobalLabelList;
173 typedef RBTREE<GlobalLabel> GlobalLabelList;
174 //typedef FIFO_INDEXED<GlobalLabel> GlobalLabelList;
176 class CeeFileGenWriter;
181 /************************************************************************/
182 /* represents an object that knows how to report errors back to the user */
187 virtual void error(const char* fmt, ...) = 0;
188 virtual void warn(const char* fmt, ...) = 0;
189 virtual void msg(const char* fmt, ...) = 0;
192 /**************************************************************************/
193 /* represents a switch table before the lables are bound */
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; }
204 /**************************************************************************/
205 /* descriptor of the structured exception handling construct */
206 struct SEH_Descriptor
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
214 DWORD sehFilter; // start of filter block
215 mdTypeRef cException; // what to catch
220 memset(this, 0, sizeof(*this));
225 typedef LIFO<char> StringStack;
226 typedef LIFO<SEH_Descriptor> SEHD_Stack;
228 typedef FIFO<Method> MethodList;
229 //typedef SORTEDARRAY<Method> MethodSortedList;
230 typedef FIFO<mdToken> TokenList;
231 /**************************************************************************/
232 /* The field, event and property descriptor structures */
234 struct FieldDescriptor
239 mdFieldDef m_fdFieldTok;
241 char* m_rvaLabel; // if field has RVA associated with it, label for it goes here.
245 BinStr* m_pbsMarshal;
246 PInvokeDescriptor* m_pPInvoke;
247 CustomDescrList m_CustomDescrList;
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; };
256 typedef FIFO<FieldDescriptor> FieldDList;
258 struct EventDescriptor
263 mdToken m_tkEventType;
265 mdToken m_tkRemoveOn;
267 TokenList m_tklOthers;
268 mdEvent m_edEventTok;
270 CustomDescrList m_CustomDescrList;
271 ~EventDescriptor() { m_tklOthers.RESET(false); };
273 typedef FIFO<EventDescriptor> EventDList;
275 struct PropDescriptor
280 COR_SIGNATURE* m_pSig;
282 DWORD m_dwCPlusTypeFlag;
287 TokenList m_tklOthers;
288 mdProperty m_pdPropTok;
290 CustomDescrList m_CustomDescrList;
291 ~PropDescriptor() { m_tklOthers.RESET(false); };
293 typedef FIFO<PropDescriptor> PropDList;
295 struct ImportDescriptor
298 // char szDllName[MAX_FILENAME_LENGTH];
301 ImportDescriptor(__in __nullterminated char* sz, DWORD l)
303 if((sz != NULL)&&(l > 0))
305 szDllName = new char[l+1];
306 if(szDllName != NULL)
308 memcpy(szDllName,sz,l);
319 ~ImportDescriptor() { delete [] szDllName; };
321 typedef FIFO<ImportDescriptor> ImportList;
324 /**************************************************************************/
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;
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). */
341 PermissionDecl(CorDeclSecurity action, mdToken type, NVPair *pairs)
346 BuildConstructorBlob(action, pairs);
350 PermissionDecl(CorDeclSecurity action, mdToken type, BinStr* pbsPairs)
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
360 if(pbsPairs->length() > 2)
361 m_pbsBlob->appendFrom(pbsPairs,2);
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();
373 if(m_pbsBlob) delete m_pbsBlob;
374 else delete [] m_Blob;
377 CorDeclSecurity m_Action;
382 PermissionDecl *m_Next;
385 void BuildConstructorBlob(CorDeclSecurity action, NVPair *pairs)
394 // Calculate number of name/value pairs and the memory required for the
395 // custom attribute blob.
397 BYTE *pVal = (BYTE*)p->Value()->ptr();
399 bytes += 2; // One byte field/property specifier, one byte type code
401 length = (int)strlen((const char *)p->Name()->ptr());
402 bytes += CPackedLen::Size(length) + length;
405 case SERIALIZATION_TYPE_BOOLEAN:
408 case SERIALIZATION_TYPE_I4:
411 case SERIALIZATION_TYPE_STRING:
412 length = (int)strlen((const char *)&pVal[1]);
413 bytes += CPackedLen::Size(length) + length;
415 case SERIALIZATION_TYPE_ENUM:
416 length = (int)strlen((const char *)&pVal[1]);
417 bytes += CPackedLen::Size((ULONG)length) + length;
424 m_Blob = new BYTE[bytes];
427 fprintf(stderr,"\nOut of memory!\n");
431 m_Blob[0] = 0x01; // Version
433 m_Blob[2] = (BYTE)action; // Constructor arg (security action code)
437 m_Blob[6] = (BYTE)count; // Property/field count
438 m_Blob[7] = (BYTE)(count >> 8);
440 for (i = 0, pBlob = &m_Blob[8], p = pairs; i < count; i++, p = p->Next()) {
441 BYTE *pVal = (BYTE*)p->Value()->ptr();
444 // Set field/property setter type.
445 *pBlob++ = SERIALIZATION_TYPE_PROPERTY;
447 // Set type code. There's additional info for enums (the enum class
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);
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());
464 // Record the serialized value.
466 case SERIALIZATION_TYPE_BOOLEAN:
469 case SERIALIZATION_TYPE_I4:
470 *(__int32*)pBlob = *(__int32*)&pVal[1];
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]);
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]) {
484 *(__int8*)pBlob = *(__int8*)&pVal[1 + length + 2];
488 *(__int16*)pBlob = *(__int16*)&pVal[1 + length + 2];
492 *(__int32*)pBlob = *(__int32*)&pVal[1 + length + 2];
496 _ASSERTE(!"Invalid enum size");
503 _ASSERTE((pBlob - m_Blob) == bytes);
505 m_BlobLength = (long)bytes;
509 class PermissionSetDecl
512 PermissionSetDecl(CorDeclSecurity action, BinStr *value)
524 CorDeclSecurity m_Action;
526 PermissionSetDecl *m_Next;
534 VTFEntry(WORD wCount, WORD wType, __in __nullterminated char* szLabel) { m_wCount = wCount; m_wType = wType; m_szLabel = szLabel; }
535 ~VTFEntry() { delete m_szLabel; }
537 typedef FIFO<VTFEntry> VTFList;
545 typedef FIFO<EATEntry> EATList;
550 ISymUnmanagedDocumentWriter* pWriter;
551 DocWriter() { Name=NULL; pWriter=NULL; };
552 ~DocWriter() { delete [] Name; if(pWriter) pWriter->Release();};
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) */
566 unsigned linenum_end;
569 ISymUnmanagedDocumentWriter* pWriter;
571 #define INSTR_POOL_SIZE 16
580 typedef FIFO<MethodBody> MethodBodyList;
607 BinStr* m_pbsTypeSpec;
610 mdToken m_tkTypeSpec;
611 TypeDefDescr(__in_opt __nullterminated char *pszName, BinStr* pbsTypeSpec, mdToken tkTypeSpec)
614 m_pbsTypeSpec = pbsTypeSpec;
615 m_tkTypeSpec = tkTypeSpec;
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); };
621 typedef SORTEDARRAY<TypeDefDescr> TypeDefDList;
626 Indx() { memset(table,0,sizeof(table)); };
629 for(int i = 1; i < 128; i++) delete ((Indx*)(table[i]));
631 void IndexString(__in_z __in char* psz, void* pkywd)
638 _ASSERTE((i > 0)&&(i <= 127));
639 Indx* pInd = (Indx*)(table[i]);
646 pInd->IndexString(psz+1,pkywd);
649 void* FindString(__in __nullterminated char* psz)
653 unsigned char uch = (unsigned char) *psz;
654 if(table[uch] != NULL)
655 return ((Indx*)(table[uch]))->FindString(psz+1);
657 else if(*psz == 0) return table[0];
666 //--------------------------------------------------------
667 GlobalLabelList m_lstGlobalLabel;
668 GlobalFixupList m_lstGlobalFixup;
670 LabelList m_lstLabel;
672 Class * m_pModuleClass;
673 ClassList m_lstClass;
674 ClassHash m_hshClass;
678 BYTE * m_pOutputBuffer;
679 BYTE * m_pCurOutputPos;
680 BYTE * m_pEndOutputPos;
685 BOOL m_fDisplayTraceOutput;
686 BOOL m_fInitialisedMetaData;
687 BOOL m_fAutoInheritFromObject;
688 BOOL m_fReportProgress;
690 BOOL m_fTolerateDupMethods;
693 mdToken m_tkSysObject;
694 mdToken m_tkSysString;
695 mdToken m_tkSysValue;
697 BOOL m_fDidCoInitialise;
699 IMetaDataDispenserEx *m_pDisp;
700 IMetaDataEmit2 *m_pEmitter;
701 ICeeFileGen *m_pCeeFileGen;
702 IMetaDataImport2 *m_pImporter; // Import interface.
704 HCEESECTION m_pGlobalDataSection;
705 HCEESECTION m_pILSection;
706 HCEESECTION m_pTLSSection;
707 HCEESECTION m_pCurSection; // The section EmitData* things go to
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;
716 WCHAR *m_wzMetadataVersion;
718 StringStack m_NSstack;
719 mdTypeSpec m_crExtends;
721 // char m_szExtendsClause[MAX_CLASSNAME_LENGTH];
723 // The (resizable) array of "implements" types
724 mdToken *m_crImplList;
728 TyParList *m_TyParList;
730 Method *m_pCurMethod;
732 ClassStack m_ClassStack; // for nested classes
733 Class *dummyClass; // for FindCreateClass
736 //MethodList m_MethodList;
742 BOOL m_fEntryPointPresent;
743 BOOL m_fHaveFieldsWithRvas;
745 DWORD m_dwMethodsFolded;
751 Instr m_Instr[INSTR_POOL_SIZE]; // 16
752 inline Instr* GetInstr()
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");
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 //--------------------------------------------------------------------------------
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);
809 void ResetForNextMethod();
810 void ResetLineNumbers();
811 void SetStdMapping(BOOL val = TRUE) { m_fStdMapping = val; };
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); }
818 void StartNameSpace(__in __nullterminated char* name);
820 void StartClass(__in __nullterminated char* name, DWORD attr, TyParList *typars);
821 DWORD CheckClassFlagsIfNested(Class* pEncloser, DWORD attr);
824 void StartMethod(__in __nullterminated char* name, BinStr* sig, CorMethodAttr flags, BinStr* retMarshal, DWORD retAttr, TyParList *typars = NULL);
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();
835 void SetImplAttr(unsigned short attrval);
837 // Emits zeros if the buffer parameter is NULL.
838 void EmitData(__in_opt void *buffer, unsigned len);
840 void EmitDD(__in __nullterminated char *str);
841 void EmitDataString(BinStr* str);
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);
860 unsigned OpcodeLen(Instr* instr); //returns opcode length
861 // Emit just the opcode (no parameters to the instruction stream.
862 void EmitOpcode(Instr* instr);
864 // Emit primitive types to the instruction stream.
865 void EmitBytes(BYTE*, unsigned len);
867 ErrorReporter* report;
869 BOOL EmitFieldsMethods(Class* pClass);
870 BOOL EmitEventsProps(Class* pClass);
872 // named args/vars paraphernalia:
874 void addArgName(__in_opt __nullterminated char *szNewName, BinStr* pbSig, BinStr* pbMarsh, DWORD dwAttr)
876 if(pbSig && (*(pbSig->ptr()) == ELEMENT_TYPE_VOID))
877 report->error("Illegal use of type 'void'\n");
880 m_lastArgName->pNext = new ARG_NAME_LIST(m_lastArgName->nNum+1,szNewName,pbSig,pbMarsh,dwAttr);
881 m_lastArgName = m_lastArgName->pNext;
885 m_lastArgName = new ARG_NAME_LIST(0,szNewName,pbSig,pbMarsh,dwAttr);
886 m_firstArgName = m_lastArgName;
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)
894 ARG_NAME_LIST *pArgList=pFirst, *pArgListNext;
895 for(; pArgList; pArgListNext=pArgList->pNext,
897 pArgList=pArgListNext);
900 ARG_NAME_LIST *findArg(ARG_NAME_LIST *pFirst, int num)
903 for(pAN=pFirst; pAN; pAN = pAN->pNext)
905 if(pAN->nNum == num) return pAN;
909 ARG_NAME_LIST *m_firstArgName;
910 ARG_NAME_LIST *m_lastArgName;
911 void ResetArgNameList();
913 // Structured exception handling paraphernalia:
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
924 SEHD_Stack m_SEHDstack;
926 // Events and Properties paraphernalia:
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;
940 MemberRefDList m_LocalMethodRefDList;
941 MemberRefDList m_LocalFieldRefDList;
942 LocalMemberRefFixupList m_LocalMemberRefFixupList;
943 MethodBodyList m_MethodBodyList;
944 MemberRefDList m_MethodSpecList;
946 HRESULT ResolveLocalMemberRefs();
947 HRESULT DoLocalMemberRefFixups();
948 mdToken ResolveLocalMemberRef(mdToken tok);
950 // PInvoke paraphernalia
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);
959 // Debug metadata paraphernalia
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;
972 char m_szSourceFileName[MAX_FILENAME_LENGTH*3+1];
973 WCHAR m_wzOutputFileName[MAX_FILENAME_LENGTH];
974 WCHAR m_wzSourceFileName[MAX_FILENAME_LENGTH];
976 GUID m_guidLangVendor;
979 // Security paraphernalia
981 void AddPermissionDecl(CorDeclSecurity action, mdToken type, NVPair *pairs)
983 PermissionDecl *decl = new PermissionDecl(action, type, pairs);
986 report->error("\nOut of memory!\n");
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;
999 report->error("Cannot declare security permissions without the owner\n");
1004 void AddPermissionDecl(CorDeclSecurity action, mdToken type, BinStr *pbsPairs)
1006 PermissionDecl *decl = new PermissionDecl(action, type, pbsPairs);
1009 report->error("\nOut of memory!\n");
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;
1022 report->error("Cannot declare security permissions without the owner\n");
1027 void AddPermissionSetDecl(CorDeclSecurity action, BinStr *value)
1029 PermissionSetDecl *decl = new PermissionSetDecl(action, value);
1032 report->error("\nOut of memory!\n");
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;
1045 report->error("Cannot declare security permission sets without the owner\n");
1049 void EmitSecurityInfo(mdToken token,
1050 PermissionDecl* pPermissions,
1051 PermissionSetDecl*pPermissionSets);
1052 BinStr* EncodeSecAttr(__in __nullterminated char* szReflName, BinStr* pbsSecAttrBlob, unsigned nProps);
1054 HRESULT AllocateStrongNameSignature();
1056 // Custom values paraphernalia:
1058 mdToken m_tkCurrentCVOwner;
1059 CustomDescrList* m_pCustomDescrList;
1060 CustomDescrListStack m_CustomDescrListStack;
1061 CustomDescrList m_CustomDescrList;
1063 void DefineCV(CustomDescr* pCD)
1068 void * pBlobBody = NULL;
1070 mdToken tkOwnerType, tkTypeType = TypeFromToken(pCD->tkType);
1072 if((tkTypeType != 0x99000000)&&(tkTypeType != 0x98000000))
1074 tkOwnerType = TypeFromToken(pCD->tkOwner);
1075 if((tkOwnerType != 0x99000000)&&(tkOwnerType != 0x98000000))
1079 pBlobBody = (void *)(pCD->pBlob->ptr());
1080 cTemp = pCD->pBlob->length();
1082 if (pCD->tkInterfacePair)
1084 pCD->tkOwner = GetInterfaceImpl(pCD->tkOwner, pCD->tkInterfacePair);
1086 m_pEmitter->DefineCustomAttribute(pCD->tkOwner,pCD->tkType,pBlobBody,cTemp,&cv);
1092 m_CustomDescrList.PUSH(pCD);
1095 void EmitCustomAttributes(mdToken tok, CustomDescrList* pCDL)
1098 if(pCDL == NULL || RidFromToken(tok)==0) return;
1099 while((pCD = pCDL->POP()))
1106 void EmitUnresolvedCustomAttributes(); // implementation: writer.cpp
1107 // VTable blob (if any)
1112 // VTable fixup list
1114 // Export Address Table entries list
1116 HRESULT CreateExportDirectory();
1117 DWORD EmitExportStub(DWORD dwVTFSlotRVA);
1119 // Method implementation paraphernalia:
1121 MethodImplDList m_MethodImplDList;
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);
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;
1143 BOOL m_fAppContainer;
1144 BOOL m_fHighEntropyVA;
1147 WCHAR *m_wzResourceFile;
1148 WCHAR *m_wzKeySourceName;
1150 void SetCodePage(unsigned val) { g_uCodePage = val; };
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);
1159 // Syntactic sugar paraphernalia
1161 TypeDefDList m_TypeDefDList;
1163 void AddTypeDef(BinStr* pbsTypeSpec, __in_z __in char* szName)
1165 m_TypeDefDList.PUSH(new TypeDefDescr(szName, pbsTypeSpec, ResolveTypeSpec(pbsTypeSpec)));
1167 void AddTypeDef(mdToken tkTypeSpec, __in_z __in char* szName)
1169 m_TypeDefDList.PUSH(new TypeDefDescr(szName, NULL, tkTypeSpec));
1171 void AddTypeDef(CustomDescr* pCA, __in_z __in char* szName)
1173 TypeDefDescr* pNew = new TypeDefDescr(szName,NULL,mdtCustomAttribute);
1175 m_TypeDefDList.PUSH(pNew);
1177 TypeDefDescr* FindTypeDef(__in_z __in char* szName)
1179 CHECK_LOCAL_STATIC_VAR(static TypeDefDescr X(NULL, NULL, 0));
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
1185 //return m_TypeDefDList.FIND(szName);
1187 unsigned NumTypeDefs() {return m_TypeDefDList.COUNT();};
1189 HRESULT GetCAName(mdToken tkCA, __out LPWSTR *ppszName);
1192 #endif // Assember_h
1195 #pragma warning(default : 4640)