Merge pull request #1668 from Dmitry-Me/assignmentOpReturningUnsuitableType
[platform/upstream/coreclr.git] / src / ilasm / assem.cpp
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 // File: assem.cpp
6 //
7
8 //
9 // COM+ IL assembler
10 //
11 #include "ilasmpch.h"
12
13 #define INITGUID
14
15 #define DECLARE_DATA
16
17 #include "assembler.h"
18 #ifdef FEATURE_CORECLR
19 #ifdef FEATURE_PAL
20 #include "coreclrloader.h"
21 CoreCLRLoader *g_loader;
22 #endif // FEATURE_PAL
23 MetaDataGetDispenserFunc metaDataGetDispenser;
24 #else
25 #include "MscorpeSxS.h"
26 #endif // FEATURE_CORECLR
27
28 void indexKeywords(Indx* indx); // defined in asmparse.y
29
30 unsigned int g_uCodePage = CP_ACP;
31 unsigned int g_uConsoleCP = CP_ACP;
32
33 char g_szSourceFileName[MAX_FILENAME_LENGTH*3];
34
35 WCHAR wzUniBuf[dwUniBuf];      // Unicode conversion global buffer
36
37 Assembler::Assembler()
38 {
39     m_pDisp = NULL;
40     m_pEmitter = NULL;
41     m_pImporter = NULL;
42
43     m_fCPlusPlus = FALSE;
44     m_fWindowsCE = FALSE;
45     char* pszFQN = new char[16];
46     strcpy_s(pszFQN,16,"<Module>");
47     m_pModuleClass = new Class(pszFQN);
48     m_lstClass.PUSH(m_pModuleClass);
49     m_hshClass.PUSH(m_pModuleClass);
50     m_pModuleClass->m_cl = mdTokenNil;
51     m_pModuleClass->m_bIsMaster = FALSE;
52
53     m_fStdMapping   = FALSE;
54     m_fDisplayTraceOutput= FALSE;
55     m_fENCMode = FALSE;
56     m_fTolerateDupMethods = FALSE;
57
58     m_pCurOutputPos = NULL;
59
60     m_CurPC             = 0;    // PC offset in method
61     m_pCurMethod        = NULL;
62     m_pCurClass         = NULL;
63     m_pCurEvent         = NULL;
64     m_pCurProp          = NULL;
65
66     m_wzMetadataVersion = NULL;
67     m_wMSVmajor = 0xFFFF;
68     m_wMSVminor = 0xFFFF;
69
70     m_wSSVersionMajor = 4;
71     m_wSSVersionMinor = 0;
72     m_fAppContainer = FALSE;
73     m_fHighEntropyVA = FALSE;
74
75     m_pCeeFileGen            = NULL;
76     m_pCeeFile               = 0;
77
78     m_pManifest         = NULL;
79
80     m_pCustomDescrList  = NULL;
81
82     m_pGlobalDataSection = NULL;
83     m_pILSection = NULL;
84     m_pTLSSection = NULL;
85
86     m_fDidCoInitialise = FALSE;
87
88     m_fDLL = FALSE;
89     m_fEntryPointPresent = FALSE;
90     m_fHaveFieldsWithRvas = FALSE;
91     m_fFoldCode = FALSE;
92     m_dwMethodsFolded = 0;
93
94     m_szScopeName[0] = 0;
95     m_crExtends = mdTypeDefNil;
96
97     m_nImplList = 0;
98     m_TyParList = NULL;
99
100     m_SEHD = NULL;
101     m_firstArgName = NULL;
102     m_lastArgName = NULL;
103     m_szNamespace = new char[2];
104     m_szNamespace[0] = 0;
105     m_NSstack.PUSH(m_szNamespace);
106
107     m_szFullNS = new char[MAX_NAMESPACE_LENGTH];
108     memset(m_szFullNS,0,MAX_NAMESPACE_LENGTH);
109     m_ulFullNSLen = MAX_NAMESPACE_LENGTH;
110
111     m_State             = STATE_OK;
112     m_fInitialisedMetaData = FALSE;
113     m_fAutoInheritFromObject = TRUE;
114
115     m_ulLastDebugLine = 0xFFFFFFFF;
116     m_ulLastDebugColumn = 0xFFFFFFFF;
117     m_ulLastDebugLineEnd = 0xFFFFFFFF;
118     m_ulLastDebugColumnEnd = 0xFFFFFFFF;
119     m_pSymWriter = NULL;
120     m_pSymDocument = NULL;
121     m_dwIncludeDebugInfo = 0;
122     m_fGeneratePDB = FALSE;
123     m_fIsMscorlib = FALSE;
124     m_fOptimize = FALSE;
125     m_tkSysObject = 0;
126     m_tkSysString = 0;
127     m_tkSysValue = 0;
128     m_tkSysEnum = 0;
129
130     m_pVTable = NULL;
131     m_pMarshal = NULL;
132     m_pPInvoke = NULL;
133
134     m_fReportProgress = TRUE;
135     m_tkCurrentCVOwner = 1; // module
136     m_pOutputBuffer = NULL;
137
138     m_dwSubsystem = (DWORD)-1;
139     m_dwComImageFlags = COMIMAGE_FLAGS_ILONLY;
140     m_dwFileAlignment = 0;
141     m_stBaseAddress = 0;
142     m_stSizeOfStackReserve = 0;
143     m_dwCeeFileFlags = ICEE_CREATE_FILE_PURE_IL;
144
145     g_szSourceFileName[0] = 0;
146
147     m_guidLang = CorSym_LanguageType_ILAssembly;
148     m_guidLangVendor = CorSym_LanguageVendor_Microsoft;
149     m_guidDoc = CorSym_DocumentType_Text;
150     for(int i=0; i<INSTR_POOL_SIZE; i++) m_Instr[i].opcode = -1;
151     m_wzResourceFile = NULL;
152     m_wzKeySourceName = NULL;
153     OnErrGo = false;
154     bClock = NULL;
155
156     m_pbsMD = NULL;
157
158     m_pOutputBuffer = new BYTE[OUTPUT_BUFFER_SIZE];
159
160     m_pCurOutputPos = m_pOutputBuffer;
161     m_pEndOutputPos = m_pOutputBuffer + OUTPUT_BUFFER_SIZE;
162
163     m_crImplList = new mdTypeRef[MAX_INTERFACES_IMPLEMENTED];
164     m_nImplListSize = MAX_INTERFACES_IMPLEMENTED;
165
166     m_pManifest = new AsmMan((void*)this);
167
168     dummyClass = new Class(NULL);
169     indexKeywords(&indxKeywords);
170 }
171
172
173 Assembler::~Assembler()
174 {
175     if(m_pbsMD) delete m_pbsMD;
176
177     if(m_pMarshal) delete m_pMarshal;
178     if(m_pManifest) delete m_pManifest;
179     if(m_pPInvoke) delete m_pPInvoke;
180
181     if(m_pVTable) delete m_pVTable;
182
183     m_lstGlobalLabel.RESET(true);
184     m_lstGlobalFixup.RESET(true);
185     m_hshClass.RESET(false);
186     m_lstClass.RESET(true);
187     while((m_ClassStack.POP()));
188     while(m_CustomDescrListStack.POP());
189     m_pCurClass = NULL;
190     dummyClass->m_szFQN = NULL;
191     delete dummyClass;
192
193     if (m_pOutputBuffer)    delete [] m_pOutputBuffer;
194     if (m_crImplList)       delete [] m_crImplList;
195     if (m_TyParList)        delete m_TyParList;
196
197     if (m_pCeeFileGen != NULL) {
198         if (m_pCeeFile)
199             m_pCeeFileGen->DestroyCeeFile(&m_pCeeFile);
200 #ifdef FEATURE_CORECLR
201         DestroyICeeFileGen(&m_pCeeFileGen);
202 #else
203         MscorpeSxS::DestroyICeeFileGen(&m_pCeeFileGen);
204 #endif
205         m_pCeeFileGen = NULL;
206     }
207
208     while((m_szNamespace = m_NSstack.POP())) ;
209     delete [] m_szFullNS;
210
211     m_DocWriterList.RESET(true);
212
213     m_MethodBodyList.RESET(true);
214     
215     m_TypeDefDList.RESET(true);
216
217     if (m_pSymWriter != NULL)
218     {
219         m_pSymWriter->Close();
220         m_pSymWriter->Release();
221         m_pSymWriter = NULL;
222     }
223     if (m_pImporter != NULL)
224     {
225         m_pImporter->Release();
226         m_pImporter = NULL;
227     }
228     if (m_pEmitter != NULL)
229     {
230         m_pEmitter->Release();
231         m_pEmitter = NULL;
232     }
233
234     if (m_pDisp != NULL)
235     {
236         m_pDisp->Release();
237         m_pDisp = NULL;
238     }
239
240 #ifdef FEATURE_CORECLR
241 #ifdef FEATURE_PAL
242     if (g_loader != NULL)
243     {
244         g_loader->Finish();
245     }
246 #endif
247 #else
248     if (m_fDidCoInitialise)
249         CoUninitialize();
250 #endif // FEATURE_CORECLR
251
252 }
253
254
255 BOOL Assembler::Init()
256 {
257 #ifdef FEATURE_CORECLR
258 #ifdef FEATURE_PAL
259     g_loader = CoreCLRLoader::Create(g_pszExeFile);
260     if (g_loader == NULL)
261     {
262         return FALSE;
263     }
264     metaDataGetDispenser = (MetaDataGetDispenserFunc)g_loader->LoadFunction("MetaDataGetDispenser");
265 #else
266     metaDataGetDispenser = (MetaDataGetDispenserFunc)MetaDataGetDispenser;
267 #endif // FEATURE_PAL
268 #else
269     if(!m_fDidCoInitialise)
270     {
271         if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
272             return FALSE;
273         m_fDidCoInitialise = TRUE;
274     }
275 #endif // FEATURE_CORECLR
276     if (m_pCeeFileGen != NULL) {
277         if (m_pCeeFile)
278             m_pCeeFileGen->DestroyCeeFile(&m_pCeeFile);
279 #ifdef FEATURE_CORECLR
280         DestroyICeeFileGen(&m_pCeeFileGen);
281 #else
282         MscorpeSxS::DestroyICeeFileGen(&m_pCeeFileGen);
283 #endif
284         m_pCeeFileGen = NULL;
285     }
286 #ifdef FEATURE_CORECLR
287     if (FAILED(CreateICeeFileGen(&m_pCeeFileGen))) return FALSE;
288 #else
289     if (FAILED(MscorpeSxS::CreateICeeFileGen(&m_pCeeFileGen))) return FALSE;
290 #endif
291     if (FAILED(m_pCeeFileGen->CreateCeeFileEx(&m_pCeeFile,(ULONG)m_dwCeeFileFlags))) return FALSE;
292
293     if (FAILED(m_pCeeFileGen->GetSectionCreate(m_pCeeFile, ".il", sdReadOnly, &m_pILSection))) return FALSE;
294     if (FAILED(m_pCeeFileGen->GetSectionCreate (m_pCeeFile, ".sdata", sdReadWrite, &m_pGlobalDataSection))) return FALSE;
295     if (FAILED(m_pCeeFileGen->GetSectionCreate (m_pCeeFile, ".tls", sdReadWrite, &m_pTLSSection))) return FALSE;
296
297     return TRUE;
298 }
299
300 void Assembler::SetDLL(BOOL IsDll)
301 {
302     HRESULT OK;
303     OK = m_pCeeFileGen->SetDllSwitch(m_pCeeFile, IsDll);
304     _ASSERTE(SUCCEEDED(OK));
305
306     m_fDLL = IsDll;
307 }
308
309 void Assembler::SetOBJ(BOOL IsObj)
310 {
311     HRESULT OK;
312     OK = m_pCeeFileGen->SetObjSwitch(m_pCeeFile, IsObj);
313     _ASSERTE(SUCCEEDED(OK));
314
315     m_fOBJ = IsObj;
316 }
317
318
319 void Assembler::ResetArgNameList()
320 {
321     if(m_firstArgName) delArgNameList(m_firstArgName);
322     m_firstArgName = NULL;
323     m_lastArgName = NULL;
324 }
325
326 void Assembler::ResetForNextMethod()
327 {
328
329     ResetArgNameList();
330
331     m_CurPC         = 0;
332     m_pCurOutputPos = m_pOutputBuffer;
333     m_State         = STATE_OK;
334     m_pCurMethod = NULL;
335 }
336
337 void Assembler::ResetLineNumbers()
338 {
339     // reset line number information
340     m_ulLastDebugLine = 0xFFFFFFFF;
341     m_ulLastDebugColumn = 0xFFFFFFFF;
342     m_ulLastDebugLineEnd = 0xFFFFFFFF;
343     m_ulLastDebugColumnEnd = 0xFFFFFFFF;
344 }
345
346 BOOL Assembler::AddMethod(Method *pMethod)
347 {
348     BOOL                     fIsInterface=FALSE, fIsImport=FALSE;
349     ULONG                    PEFileOffset=0;
350
351     _ASSERTE(m_pCeeFileGen != NULL);
352     if (pMethod == NULL)
353     {
354         report->error("pMethod == NULL");
355         return FALSE;
356     }
357     if(pMethod->m_pClass != NULL)
358     {
359         fIsInterface = IsTdInterface(pMethod->m_pClass->m_Attr);
360         fIsImport = IsTdImport(pMethod->m_pClass->m_Attr);
361     }
362     if(m_CurPC)
363     {
364         char sz[1024];
365         sz[0] = 0;
366         if(fIsInterface  && (!IsMdStatic(pMethod->m_Attr))) strcat_s(sz,1024," non-static declared in interface");
367         if(fIsImport) strcat_s(sz,1024," imported");
368         if(IsMdAbstract(pMethod->m_Attr)) strcat_s(sz,1024," abstract");
369         if(IsMdPinvokeImpl(pMethod->m_Attr)) strcat_s(sz,1024," pinvoke");
370         if(!IsMiIL(pMethod->m_wImplAttr)) strcat_s(sz,1024," non-IL");
371         if(IsMiRuntime(pMethod->m_wImplAttr)) strcat_s(sz,1024," runtime-supplied");
372         if(IsMiInternalCall(pMethod->m_wImplAttr)) strcat_s(sz,1024," an internal call");
373         if(strlen(sz))
374         {
375             report->error("Method cannot have body if it is%s\n",sz);
376         }
377     }
378     else // method has no body
379     {
380         if(fIsImport || IsMdAbstract(pMethod->m_Attr) || IsMdPinvokeImpl(pMethod->m_Attr)
381            || IsMiRuntime(pMethod->m_wImplAttr) || IsMiInternalCall(pMethod->m_wImplAttr)) return TRUE;
382         if(OnErrGo)
383         {
384             report->error("Method has no body\n");
385             return TRUE;
386         }
387         else
388         {
389             report->warn("Method has no body, 'ret' emitted\n");
390             Instr* pIns = GetInstr();
391             if(pIns)
392             {
393                 memset(pIns,0,sizeof(Instr));
394                 pIns->opcode = CEE_RET;
395                 EmitOpcode(pIns);
396             }
397         }
398     }
399
400     if(pMethod->m_Locals.COUNT()) pMethod->m_LocalsSig=0x11000001; // placeholder, the real token 2b defined in EmitMethod
401
402     COR_ILMETHOD_FAT fatHeader;
403     fatHeader.SetFlags(pMethod->m_Flags);
404     fatHeader.SetMaxStack(pMethod->m_MaxStack);
405     fatHeader.SetLocalVarSigTok(pMethod->m_LocalsSig);
406     fatHeader.SetCodeSize(m_CurPC);
407     bool moreSections = (pMethod->m_dwNumExceptions != 0);
408
409     // if max stack is specified <8, force fat header, otherwise (with tiny header) it will default to 8
410     if((fatHeader.GetMaxStack() < 8)&&(fatHeader.GetLocalVarSigTok()==0)&&(fatHeader.GetCodeSize()<64)&&(!moreSections))
411         fatHeader.SetFlags(fatHeader.GetFlags() | CorILMethod_InitLocals); //forces fat header but does nothing else, since LocalVarSigTok==0
412
413     unsigned codeSize = m_CurPC;
414     unsigned codeSizeAligned = codeSize;
415     if (moreSections)
416         codeSizeAligned = (codeSizeAligned + 3) & ~3;    // to insure EH section aligned
417
418     unsigned headerSize = COR_ILMETHOD::Size(&fatHeader, moreSections);
419     unsigned ehSize     = COR_ILMETHOD_SECT_EH::Size(pMethod->m_dwNumExceptions, pMethod->m_ExceptionList);
420     unsigned totalSize  = headerSize + codeSizeAligned + ehSize;
421
422     BYTE* outBuff;
423     BYTE* endbuf;
424     BinStr* pbsBody;
425     if((pbsBody = new BinStr())==NULL) return FALSE;
426     if((outBuff = pbsBody->getBuff(totalSize))==NULL) return FALSE;
427     endbuf = &outBuff[totalSize];
428
429     // Emit the header
430     outBuff += COR_ILMETHOD::Emit(headerSize, &fatHeader, moreSections, outBuff);
431
432     pMethod->m_pCode = outBuff;
433     pMethod->m_headerOffset= PEFileOffset;
434     pMethod->m_methodOffset= PEFileOffset + headerSize;
435     pMethod->m_CodeSize = codeSize;
436
437     // Emit the code
438     if (codeSizeAligned)
439     {
440         memset(outBuff,0,codeSizeAligned);
441         memcpy(outBuff, m_pOutputBuffer, codeSize);
442         outBuff += codeSizeAligned;
443     }
444
445     if(pMethod->m_dwNumExceptions)
446     {
447         // Validate the eh
448         COR_ILMETHOD_SECT_EH_CLAUSE_FAT* pEx;
449         DWORD   TryEnd,HandlerEnd, dwEx, dwEf;
450         for(dwEx = 0, pEx = pMethod->m_ExceptionList; dwEx < pMethod->m_dwNumExceptions; dwEx++, pEx++)
451         {
452             if(pEx->GetTryOffset() > m_CurPC) // i.e., pMethod->m_CodeSize
453             {
454                 report->error("Invalid SEH clause #%d: Try block starts beyond code size\n",dwEx+1);
455             }
456             TryEnd = pEx->GetTryOffset()+pEx->GetTryLength();
457             if(TryEnd > m_CurPC)
458             {
459                 report->error("Invalid SEH clause #%d: Try block ends beyond code size\n",dwEx+1);
460             }
461             if(pEx->GetHandlerOffset() > m_CurPC)
462             {
463                 report->error("Invalid SEH clause #%d: Handler block starts beyond code size\n",dwEx+1);
464             }
465             HandlerEnd = pEx->GetHandlerOffset()+pEx->GetHandlerLength();
466             if(HandlerEnd > m_CurPC)
467             {
468                 report->error("Invalid SEH clause #%d: Handler block ends beyond code size\n",dwEx+1);
469             }
470             if(pEx->Flags & COR_ILEXCEPTION_CLAUSE_FILTER)
471             {
472                 if(!((pEx->GetFilterOffset() >= TryEnd)||(pEx->GetTryOffset() >= HandlerEnd)))
473                 {
474                     report->error("Invalid SEH clause #%d: Try and Filter/Handler blocks overlap\n",dwEx+1);
475                 }
476                 for(dwEf = 0; dwEf < pMethod->m_dwNumEndfilters; dwEf++)
477                 {
478                     if(pMethod->m_EndfilterOffsetList[dwEf] == pEx->GetHandlerOffset()) break;
479                 }
480                 if(dwEf >= pMethod->m_dwNumEndfilters)
481                 {
482                     report->error("Invalid SEH clause #%d: Filter block separated from Handler, or not ending with endfilter\n",dwEx+1);
483                 }
484             }
485             else
486             if(!((pEx->GetHandlerOffset() >= TryEnd)||(pEx->GetTryOffset() >= HandlerEnd)))
487             {
488                 report->error("Invalid SEH clause #%d: Try and Handler blocks overlap\n",dwEx+1);
489             }
490
491         }
492         // Emit the eh
493         outBuff += COR_ILMETHOD_SECT_EH::Emit(ehSize, pMethod->m_dwNumExceptions,
494                                     pMethod->m_ExceptionList, false, outBuff);
495     }
496     _ASSERTE(outBuff == endbuf);
497
498     pMethod->m_pbsBody = pbsBody;
499
500     LocalMemberRefFixup*             pMRF;
501     while((pMRF = pMethod->m_LocalMemberRefFixupList.POP()))
502     {
503         pMRF->offset += (size_t)(pMethod->m_pCode);
504         m_LocalMemberRefFixupList.PUSH(pMRF); // transfer MRF to assembler's list
505     }
506
507     if(m_fReportProgress)
508     {
509         if (pMethod->IsGlobalMethod())
510             report->msg("Assembled global method %s\n", pMethod->m_szName);
511         else report->msg("Assembled method %s::%s\n", pMethod->m_pClass->m_szFQN,
512                   pMethod->m_szName);
513     }
514     return TRUE;
515 }
516
517
518 BOOL Assembler::EmitMethodBody(Method* pMethod, BinStr* pbsOut)
519 {
520     if(pMethod)
521     {
522         BinStr* pbsBody = pMethod->m_pbsBody;
523         unsigned totalSize;
524         if(pbsBody && (totalSize = pbsBody->length()))
525         {
526             unsigned headerSize = pMethod->m_methodOffset-pMethod->m_headerOffset;
527             MethodBody* pMB = NULL;
528             // ----------emit locals signature-------------------
529             unsigned uLocals;
530             if((uLocals = pMethod->m_Locals.COUNT()))
531             {
532                 VarDescr* pVD;
533                 BinStr*   pbsSig = new BinStr();
534                 unsigned cnt;
535                 HRESULT hr;
536                 DWORD   cSig;
537                 const COR_SIGNATURE* mySig;
538
539                 pbsSig->appendInt8(IMAGE_CEE_CS_CALLCONV_LOCAL_SIG);
540                 cnt = CorSigCompressData(uLocals,pbsSig->getBuff(5));
541                 pbsSig->remove(5-cnt);
542                 for(cnt = 0; (pVD = pMethod->m_Locals.PEEK(cnt)); cnt++)
543                 {
544                     if(pVD->pbsSig) pbsSig->append(pVD->pbsSig);
545                     else
546                     {
547                         report->error("Undefined type of local var slot %d in method %s\n",cnt,pMethod->m_szName);
548                         pbsSig->appendInt8(ELEMENT_TYPE_I4);
549                     }
550                 }
551
552                 cSig = pbsSig->length();
553                 mySig = (const COR_SIGNATURE *)(pbsSig->ptr());
554
555                 if (cSig > 1)    // non-empty signature
556                 {
557                     hr = m_pEmitter->GetTokenFromSig(mySig, cSig, &pMethod->m_LocalsSig);
558                     _ASSERTE(SUCCEEDED(hr));
559                 }
560                 delete pbsSig;
561                 COR_ILMETHOD_FAT* pFH; // Fat header guaranteed, because there are local vars
562                 pFH = (COR_ILMETHOD_FAT*)(pMethod->m_pbsBody->ptr());
563                 pFH->SetLocalVarSigTok(pMethod->m_LocalsSig);
564             }
565             //--------------------------------------------------------------------------------
566             if(m_fGeneratePDB && (m_pSymWriter != NULL))
567             {
568                 m_pSymWriter->OpenMethod(pMethod->m_Tok);
569                 ULONG N = pMethod->m_LinePCList.COUNT();
570                 if(pMethod->m_fEntryPoint) m_pSymWriter->SetUserEntryPoint(pMethod->m_Tok);
571                 if(N)
572                 {
573                     LinePC  *pLPC;
574                     ULONG32  *offsets=new ULONG32[N], *lines = new ULONG32[N], *columns = new ULONG32[N];
575                     ULONG32  *endlines=new ULONG32[N], *endcolumns=new ULONG32[N];
576                     if(offsets && lines && columns && endlines && endcolumns)
577                     {
578                         DocWriter* pDW;
579                         unsigned j=0;
580                         while((pDW = m_DocWriterList.PEEK(j++)))
581                         {
582                             if((m_pSymDocument = pDW->pWriter))
583                             {
584                                 int i, n;
585                                 for(i=0, n=0; (pLPC = pMethod->m_LinePCList.PEEK(i)); i++)
586                                 {
587                                     if(pLPC->pWriter == m_pSymDocument)
588                                     {
589                                         offsets[n] = pLPC->PC;
590                                         lines[n] = pLPC->Line;
591                                         columns[n] = pLPC->Column;
592                                         endlines[n] = pLPC->LineEnd;
593                                         endcolumns[n] = pLPC->ColumnEnd;
594                                         n++;
595                                     }
596                                 }
597                                 if(n) m_pSymWriter->DefineSequencePoints(m_pSymDocument,n,
598                                                                    offsets,lines,columns,endlines,endcolumns);
599                             } // end if(pSymDocument)
600                         } // end while(pDW = next doc.writer)
601                         pMethod->m_LinePCList.RESET(true);
602                     }
603                     else report->error("\nOutOfMemory!\n");
604                     delete [] offsets;
605                     delete [] lines;
606                     delete [] columns;
607                     delete [] endlines;
608                     delete [] endcolumns;
609                 }//enf if(N)
610                 HRESULT hrr;
611                 if(pMethod->m_ulLines[1])
612                     hrr = m_pSymWriter->SetMethodSourceRange(m_pSymDocument,pMethod->m_ulLines[0], pMethod->m_ulColumns[0],
613                                                        m_pSymDocument,pMethod->m_ulLines[1], pMethod->m_ulColumns[1]);
614                 EmitScope(&(pMethod->m_MainScope)); // recursively emits all nested scopes
615
616                 m_pSymWriter->CloseMethod();
617             } // end if(fIncludeDebugInfo)
618             //-----------------------------------------------------
619
620             if(m_fFoldCode)
621             {
622                 for(int k=0; (pMB = m_MethodBodyList.PEEK(k)) != NULL; k++)
623                 {
624                     if((pMB->pbsBody->length() == totalSize)
625                       && (memcmp(pMB->pbsBody->ptr(), pbsBody->ptr(),totalSize)==0))
626                     break;
627                 }
628                 if(pMB)
629                 {
630                     pMethod->m_headerOffset= pMB->RVA;
631                     pMethod->m_methodOffset= pMB->RVA + headerSize;
632                     pMethod->m_pCode = pMB->pCode;
633                     delete pbsBody;
634                     pMethod->m_pbsBody = NULL;
635                     m_dwMethodsFolded++;
636                 }
637             }
638             if(pMB == NULL)
639             {
640                 BYTE* outBuff;
641                 unsigned align = (headerSize == 1)? 1 : 4;
642                 ULONG    PEFileOffset, methodRVA;
643                 if(m_fENCMode)
644                 {
645                     if(pbsOut)
646                     {
647                         PEFileOffset = pbsOut->length();
648                         align--;
649                         while(PEFileOffset & align)
650                         {
651                             pbsOut->appendInt8(0);
652                             PEFileOffset++;
653                         }
654                         pbsOut->append(pbsBody);
655                         outBuff = (BYTE*)(pbsOut->ptr()) + (pbsOut->length() - pbsBody->length());
656                     }
657                     else return FALSE;
658
659                 }
660                 else
661                 {
662                     if (FAILED(m_pCeeFileGen->GetSectionBlock (m_pILSection, totalSize,
663                             align, (void **) &outBuff)))    return FALSE;
664                     memcpy(outBuff,pbsBody->ptr(),totalSize);
665                     // The offset where we start, (not where the alignment bytes start!
666                     if (FAILED(m_pCeeFileGen->GetSectionDataLen (m_pILSection, &PEFileOffset)))
667                         return FALSE;
668                     PEFileOffset -= totalSize;
669                 }
670
671                 pMethod->m_pCode = outBuff + headerSize;
672                 pMethod->m_headerOffset= PEFileOffset;
673                 pMethod->m_methodOffset= PEFileOffset + headerSize;
674                 DoDeferredILFixups(pMethod);
675
676                 if(m_fENCMode) methodRVA = PEFileOffset;
677                 else m_pCeeFileGen->GetMethodRVA(m_pCeeFile, PEFileOffset,&methodRVA);
678
679                 pMethod->m_headerOffset= methodRVA;
680                 pMethod->m_methodOffset= methodRVA + headerSize;
681                 if(m_fFoldCode)
682                 {
683                     if((pMB = new MethodBody)==NULL) return FALSE;
684                     pMB->pbsBody = pbsBody;
685                     pMB->RVA = methodRVA;
686                     pMB->pCode = pMethod->m_pCode;
687                     m_MethodBodyList.PUSH(pMB);
688                 }
689                 //else
690                 //    delete pbsBody;
691                 //pMethod->m_pbsBody = NULL;
692             }
693             m_pEmitter->SetRVA(pMethod->m_Tok,pMethod->m_headerOffset);
694         }
695         return TRUE;
696     }
697     else return FALSE;
698 }
699
700 ImportDescriptor* Assembler::EmitImport(BinStr* DllName)
701 {
702     int i = 0, l = 0;
703     ImportDescriptor*   pID;
704     char* sz=NULL;
705
706     if(DllName) l = DllName->length();  // No zero terminator here!
707     if(l)
708     {
709         sz = (char*)DllName->ptr();
710         while((pID=m_ImportList.PEEK(i++)))
711         {
712             if((pID->dwDllName== (DWORD) l)&& !memcmp(pID->szDllName,sz,l)) return pID;
713         }
714     }
715     else
716     {
717         while((pID=m_ImportList.PEEK(i++)))
718         {
719             if(pID->dwDllName==0) return pID;
720         }
721     }
722     if((pID = new ImportDescriptor(sz,l)))
723     {
724         m_ImportList.PUSH(pID);
725         pID->mrDll = TokenFromRid(m_ImportList.COUNT(),mdtModuleRef);
726         return pID;
727     }
728     else report->error("Failed to allocate import descriptor\n");
729     return NULL;
730 }
731
732 void Assembler::EmitImports()
733 {
734     WCHAR*               wzDllName=&wzUniBuf[0];
735     ImportDescriptor*   pID;
736     int i;
737     mdToken tk;
738     for(i=0; (pID = m_ImportList.PEEK(i)); i++)
739     {
740         WszMultiByteToWideChar(g_uCodePage,0,pID->szDllName,-1,wzDllName,dwUniBuf-1);
741         if(FAILED(m_pEmitter->DefineModuleRef(             // S_OK or error.
742                             wzDllName,            // [IN] DLL name
743                             &tk)))      // [OUT] returned
744             report->error("Failed to define module ref '%s'\n",pID->szDllName);
745         else
746             _ASSERTE(tk == pID->mrDll);
747     }
748 }
749
750 HRESULT Assembler::EmitPinvokeMap(mdToken tk, PInvokeDescriptor* pDescr)
751 {
752     WCHAR*               wzAlias=&wzUniBuf[0];
753
754     if(pDescr->szAlias) WszMultiByteToWideChar(g_uCodePage,0,pDescr->szAlias,-1,wzAlias,dwUniBuf-1);
755
756     return m_pEmitter->DefinePinvokeMap(        // Return code.
757                         tk,                     // [IN] FieldDef, MethodDef or MethodImpl.
758                         pDescr->dwAttrs,        // [IN] Flags used for mapping.
759                         (LPCWSTR)wzAlias,       // [IN] Import name.
760                         pDescr->mrDll);         // [IN] ModuleRef token for the target DLL.
761 }
762
763 void Assembler::EmitScope(Scope* pSCroot)
764 {
765     static ULONG32          scopeID;
766     static ARG_NAME_LIST    *pVarList;
767     int                     i;
768     WCHAR*                  wzVarName=&wzUniBuf[0];
769     char*                   szPhonyName=(char*)&wzUniBuf[dwUniBuf >> 1];
770     Scope*                  pSC = pSCroot;
771     if(pSC && m_pSymWriter)
772     {
773         if(SUCCEEDED(m_pSymWriter->OpenScope(pSC->dwStart,&scopeID)))
774         {
775             if(pSC->pLocals)
776             {
777                 for(pVarList = pSC->pLocals; pVarList; pVarList = pVarList->pNext)
778                 {
779                     if(pVarList->pSig)
780                     {
781                         if((pVarList->szName)&&(*(pVarList->szName))) strcpy_s(szPhonyName,dwUniBuf >> 1,pVarList->szName);
782                         else sprintf_s(szPhonyName,(dwUniBuf >> 1),"V_%d",pVarList->dwAttr);
783
784                         WszMultiByteToWideChar(g_uCodePage,0,szPhonyName,-1,wzVarName,dwUniBuf >> 1);
785
786                         m_pSymWriter->DefineLocalVariable(wzVarName,0,pVarList->pSig->length(),
787                             (BYTE*)pVarList->pSig->ptr(),ADDR_IL_OFFSET,pVarList->dwAttr,0,0,0,0);
788                     }
789                     else
790                     {
791                         report->error("Local Var '%s' has no signature\n",pVarList->szName);
792                     }
793                 }
794             }
795             for(i = 0; (pSC = pSCroot->SubScope.PEEK(i)); i++) EmitScope(pSC);
796             m_pSymWriter->CloseScope(pSCroot->dwEnd);
797         }
798     }
799 }
800
801 BOOL Assembler::EmitMethod(Method *pMethod)
802 {
803 // Emit the metadata for a method definition
804     BOOL                fSuccess = FALSE;
805     WCHAR*              wzMemberName=&wzUniBuf[0];
806     BOOL                fIsInterface;
807     DWORD               cSig;
808     ULONG               methodRVA = 0;
809     mdMethodDef         MethodToken;
810     mdTypeDef           ClassToken = mdTypeDefNil;
811     char                *pszMethodName;
812     COR_SIGNATURE       *mySig;
813
814     _ASSERTE((m_pCeeFileGen != NULL) && (pMethod != NULL));
815     fIsInterface = ((pMethod->m_pClass != NULL) && IsTdInterface(pMethod->m_pClass->m_Attr));
816
817
818     pszMethodName = pMethod->m_szName;
819     mySig = pMethod->m_pMethodSig;
820     cSig = pMethod->m_dwMethodCSig;
821
822     // If  this is an instance method, make certain the signature says so
823
824     if (!(pMethod->m_Attr & mdStatic))
825         *mySig |= IMAGE_CEE_CS_CALLCONV_HASTHIS;
826
827     ClassToken = (pMethod->IsGlobalMethod())? mdTokenNil
828                                     : pMethod->m_pClass->m_cl;
829     // Convert name to UNICODE
830     WszMultiByteToWideChar(g_uCodePage,0,pszMethodName,-1,wzMemberName,dwUniBuf-1);
831
832     if(IsMdPrivateScope(pMethod->m_Attr))
833     {
834         WCHAR* p = wcsstr(wzMemberName,W("$PST06"));
835         if(p) *p = 0;
836     }
837
838     if (FAILED(m_pEmitter->DefineMethod(ClassToken,       // parent class
839                                       wzMemberName,     // member name
840                                       pMethod->m_Attr & ~mdReservedMask,  // member attributes
841                                       mySig, // member signature
842                                       cSig,
843                                       methodRVA,                // RVA
844                                       pMethod->m_wImplAttr,                // implflags
845                                       &MethodToken)))
846     {
847         report->error("Failed to define method '%s'\n",pszMethodName);
848         goto exit;
849     }
850     pMethod->m_Tok = MethodToken;
851     //--------------------------------------------------------------------------------
852     // the only way to set mdRequireSecObject:
853     if(pMethod->m_Attr & mdRequireSecObject)
854     {
855         mdToken tkPseudoClass;
856         if(FAILED(m_pEmitter->DefineTypeRefByName(1, COR_REQUIRES_SECOBJ_ATTRIBUTE, &tkPseudoClass)))
857             report->error("Unable to define type reference '%s'\n", COR_REQUIRES_SECOBJ_ATTRIBUTE_ANSI);
858         else
859         {
860             mdToken tkPseudoCtor;
861             BYTE bSig[3] = {IMAGE_CEE_CS_CALLCONV_HASTHIS,0,ELEMENT_TYPE_VOID};
862             if(FAILED(m_pEmitter->DefineMemberRef(tkPseudoClass, W(".ctor"), (PCCOR_SIGNATURE)bSig, 3, &tkPseudoCtor)))
863                 report->error("Unable to define member reference '%s::.ctor'\n", COR_REQUIRES_SECOBJ_ATTRIBUTE_ANSI);
864             else DefineCV(new CustomDescr(MethodToken,tkPseudoCtor,NULL));
865         }
866     }
867
868     if (pMethod->m_NumTyPars)
869     {
870         ULONG i;
871         mdToken* ptk;
872         mdToken tk;
873         for(i = 0; i < pMethod->m_NumTyPars; i++)
874         {
875             //ptk = (pMethod->m_TyParBounds[i] == NULL)? NULL :  (mdToken*)(pMethod->m_TyParBounds[i]->ptr());
876             //if(FAILED(m_pEmitter->DefineGenericParam(MethodToken,i,0,pMethod->m_TyParNames[i],0,ptk,&tk)))
877             ptk = (pMethod->m_TyPars[i].Bounds() == NULL)? NULL :  (mdToken*)(pMethod->m_TyPars[i].Bounds()->ptr());
878             if(FAILED(m_pEmitter->DefineGenericParam(MethodToken,i,pMethod->m_TyPars[i].Attrs(),pMethod->m_TyPars[i].Name(),0,ptk,&tk)))
879                 report->error("Unable to define generic param'\n");
880             else
881                 EmitCustomAttributes(tk, pMethod->m_TyPars[i].CAList());
882         }
883     }
884     //--------------------------------------------------------------------------------
885     EmitSecurityInfo(MethodToken,
886                      pMethod->m_pPermissions,
887                      pMethod->m_pPermissionSets);
888     //--------------------------------------------------------------------------------
889     if (pMethod->m_fEntryPoint)
890     {
891         if(fIsInterface) report->error("Entrypoint in Interface: Method '%s'\n",pszMethodName);
892
893         if (FAILED(m_pCeeFileGen->SetEntryPoint(m_pCeeFile, MethodToken)))
894         {
895             report->error("Failed to set entry point for method '%s'\n",pszMethodName);
896             goto exit;
897         }
898
899     }
900     //--------------------------------------------------------------------------------
901     if(IsMdPinvokeImpl(pMethod->m_Attr))
902     {
903         if(pMethod->m_pPInvoke)
904         {
905             HRESULT hr;
906             if(pMethod->m_pPInvoke->szAlias == NULL) pMethod->m_pPInvoke->szAlias = pszMethodName;
907             hr = EmitPinvokeMap(MethodToken,pMethod->m_pPInvoke);
908             if(pMethod->m_pPInvoke->szAlias == pszMethodName) pMethod->m_pPInvoke->szAlias = NULL;
909
910             if(FAILED(hr))
911             {
912                 report->error("Failed to set PInvoke map for method '%s'\n",pszMethodName);
913                 goto exit;
914             }
915         }
916     }
917
918     { // add parameters to metadata
919         void const *pValue=NULL;
920         ULONG       cbValue;
921         DWORD dwCPlusTypeFlag=0;
922         mdParamDef pdef;
923         WCHAR* wzParName=&wzUniBuf[0];
924         char*  szPhonyName=(char*)&wzUniBuf[dwUniBuf >> 1];
925         if(pMethod->m_dwRetAttr || pMethod->m_pRetMarshal || pMethod->m_RetCustDList.COUNT())
926         {
927             if(pMethod->m_pRetValue)
928             {
929                 dwCPlusTypeFlag= (DWORD)*(pMethod->m_pRetValue->ptr());
930                 pValue = (void const *)(pMethod->m_pRetValue->ptr()+1);
931                 cbValue = pMethod->m_pRetValue->length()-1;
932                 if(dwCPlusTypeFlag == ELEMENT_TYPE_STRING) cbValue /= sizeof(WCHAR);
933             }
934             else
935             {
936                 pValue = NULL;
937                 cbValue = (ULONG)-1;
938                 dwCPlusTypeFlag=0;
939             }
940             m_pEmitter->DefineParam(MethodToken,0,NULL,pMethod->m_dwRetAttr,dwCPlusTypeFlag,pValue,cbValue,&pdef);
941
942             if(pMethod->m_pRetMarshal)
943             {
944                 if(FAILED(m_pEmitter->SetFieldMarshal (
945                                             pdef,                       // [IN] given a fieldDef or paramDef token
946                             (PCCOR_SIGNATURE)(pMethod->m_pRetMarshal->ptr()),   // [IN] native type specification
947                                             pMethod->m_pRetMarshal->length())))  // [IN] count of bytes of pvNativeType
948                     report->error("Failed to set param marshaling for return\n");
949
950             }
951             EmitCustomAttributes(pdef, &(pMethod->m_RetCustDList));
952         }
953         for(ARG_NAME_LIST *pAN=pMethod->m_firstArgName; pAN; pAN = pAN->pNext)
954         {
955             if(pAN->nNum >= 65535)
956             {
957                 report->error("Method '%s': Param.sequence number (%d) exceeds 65535, unable to define parameter\n",pszMethodName,pAN->nNum+1);
958                 continue;
959             }
960             if(pAN->dwName) strcpy_s(szPhonyName,dwUniBuf >> 1,pAN->szName);
961             else sprintf_s(szPhonyName,(dwUniBuf >> 1),"A_%d",pAN->nNum);
962
963             WszMultiByteToWideChar(g_uCodePage,0,szPhonyName,-1,wzParName,dwUniBuf >> 1);
964
965             if(pAN->pValue)
966             {
967                 dwCPlusTypeFlag= (DWORD)*(pAN->pValue->ptr());
968                 pValue = (void const *)(pAN->pValue->ptr()+1);
969                 cbValue = pAN->pValue->length()-1;
970                 if(dwCPlusTypeFlag == ELEMENT_TYPE_STRING) cbValue /= sizeof(WCHAR);
971             }
972             else
973             {
974                 pValue = NULL;
975                 cbValue = (ULONG)-1;
976                 dwCPlusTypeFlag=0;
977             }
978             m_pEmitter->DefineParam(MethodToken,pAN->nNum+1,wzParName,pAN->dwAttr,dwCPlusTypeFlag,pValue,cbValue,&pdef);
979             if(pAN->pMarshal)
980             {
981                 if(FAILED(m_pEmitter->SetFieldMarshal (
982                                             pdef,                       // [IN] given a fieldDef or paramDef token
983                             (PCCOR_SIGNATURE)(pAN->pMarshal->ptr()),   // [IN] native type specification
984                                             pAN->pMarshal->length())))  // [IN] count of bytes of pvNativeType
985                     report->error("Failed to set param marshaling for '%s'\n",pAN->szName);
986             }
987             EmitCustomAttributes(pdef, &(pAN->CustDList));
988         }
989     }
990     fSuccess = TRUE;
991     //--------------------------------------------------------------------------------
992     // Update method implementations for this method
993     {
994         MethodImplDescriptor*   pMID;
995         int i;
996         for(i=0;(pMID = pMethod->m_MethodImplDList.PEEK(i));i++)
997         {
998             pMID->m_tkImplementingMethod = MethodToken;
999             // don't delete it here, it's still in the general list
1000         }
1001     }
1002     //--------------------------------------------------------------------------------
1003     EmitCustomAttributes(MethodToken, &(pMethod->m_CustomDescrList));
1004 exit:
1005     if (fSuccess == FALSE) m_State = STATE_FAIL;
1006     return fSuccess;
1007 }
1008
1009 BOOL Assembler::EmitMethodImpls()
1010 {
1011     MethodImplDescriptor*   pMID;
1012     BOOL ret = TRUE;
1013     int i;
1014     for(i=0; (pMID = m_MethodImplDList.PEEK(i)); i++)
1015     {
1016         if(m_fENCMode && (!pMID->m_fNew)) continue;
1017         pMID->m_tkImplementingMethod = ResolveLocalMemberRef(pMID->m_tkImplementingMethod);
1018         pMID->m_tkImplementedMethod = ResolveLocalMemberRef(pMID->m_tkImplementedMethod);
1019         if(FAILED(m_pEmitter->DefineMethodImpl( pMID->m_tkDefiningClass,
1020                                                 pMID->m_tkImplementingMethod,
1021                                                 pMID->m_tkImplementedMethod)))
1022         {
1023             report->error("Failed to define Method Implementation");
1024             ret = FALSE;
1025         }
1026         pMID->m_fNew = FALSE;
1027     }// end while
1028     return ret;
1029 }
1030
1031 mdToken Assembler::ResolveLocalMemberRef(mdToken tok)
1032 {
1033     if(TypeFromToken(tok) == 0x99000000)
1034     {
1035         tok = RidFromToken(tok);
1036         if(tok) tok = m_LocalMethodRefDList.PEEK(tok-1)->m_tkResolved;
1037     }
1038     else if(TypeFromToken(tok) == 0x98000000)
1039     {
1040         tok = RidFromToken(tok);
1041         if(tok) tok = m_LocalFieldRefDList.PEEK(tok-1)->m_tkResolved;
1042     }
1043     return tok;
1044 }
1045
1046 BOOL Assembler::EmitEvent(EventDescriptor* pED)
1047 {
1048     mdMethodDef mdAddOn=mdMethodDefNil,
1049                 mdRemoveOn=mdMethodDefNil,
1050                 mdFire=mdMethodDefNil,
1051                 *mdOthers;
1052     int                 nOthers;
1053     WCHAR*              wzMemberName=&wzUniBuf[0];
1054
1055     if(!pED) return FALSE;
1056
1057     WszMultiByteToWideChar(g_uCodePage,0,pED->m_szName,-1,wzMemberName,dwUniBuf-1);
1058
1059     mdAddOn = ResolveLocalMemberRef(pED->m_tkAddOn);
1060     if(TypeFromToken(mdAddOn) != mdtMethodDef)
1061     {
1062         report->error("Invalid Add method of event '%s'\n",pED->m_szName);
1063         return FALSE;
1064     }
1065     mdRemoveOn = ResolveLocalMemberRef(pED->m_tkRemoveOn);
1066     if(TypeFromToken(mdRemoveOn) != mdtMethodDef)
1067     {
1068         report->error("Invalid Remove method of event '%s'\n",pED->m_szName);
1069         return FALSE;
1070     }
1071     mdFire = ResolveLocalMemberRef(pED->m_tkFire);
1072     if((RidFromToken(mdFire)!=0)&&(TypeFromToken(mdFire) != mdtMethodDef))
1073     {
1074         report->error("Invalid Fire method of event '%s'\n",pED->m_szName);
1075         return FALSE;
1076     }
1077
1078     nOthers = pED->m_tklOthers.COUNT();
1079     mdOthers = new mdMethodDef[nOthers+1];
1080     if(mdOthers == NULL)
1081     {
1082         report->error("Failed to allocate Others array for event descriptor\n");
1083         nOthers = 0;
1084     }
1085     for(int j=0; j < nOthers; j++)
1086     {
1087         mdOthers[j] = ResolveLocalMemberRef((mdToken)(UINT_PTR)(pED->m_tklOthers.PEEK(j)));     // @WARNING: casting down from 'mdToken*' to 'mdToken'
1088     }
1089     mdOthers[nOthers] = mdMethodDefNil; // like null-terminator
1090
1091     if(FAILED(m_pEmitter->DefineEvent(  pED->m_tdClass,
1092                                         wzMemberName,
1093                                         pED->m_dwAttr,
1094                                         pED->m_tkEventType,
1095                                         mdAddOn,
1096                                         mdRemoveOn,
1097                                         mdFire,
1098                                         mdOthers,
1099                                         &(pED->m_edEventTok))))
1100     {
1101         report->error("Failed to define event '%s'.\n",pED->m_szName);
1102         delete [] mdOthers;
1103         return FALSE;
1104     }
1105     EmitCustomAttributes(pED->m_edEventTok, &(pED->m_CustomDescrList));
1106     return TRUE;
1107 }
1108
1109 BOOL Assembler::EmitProp(PropDescriptor* pPD)
1110 {
1111     mdMethodDef mdSet, mdGet, *mdOthers;
1112     int nOthers;
1113     WCHAR*              wzMemberName=&wzUniBuf[0];
1114
1115     if(!pPD) return FALSE;
1116
1117     WszMultiByteToWideChar(g_uCodePage,0,pPD->m_szName,-1,wzMemberName,dwUniBuf-1);
1118
1119     mdSet = ResolveLocalMemberRef(pPD->m_tkSet);
1120     if((RidFromToken(mdSet)!=0)&&(TypeFromToken(mdSet) != mdtMethodDef))
1121     {
1122         report->error("Invalid Set method of property '%s'\n",pPD->m_szName);
1123         return FALSE;
1124     }
1125     mdGet = ResolveLocalMemberRef(pPD->m_tkGet);
1126     if((RidFromToken(mdGet)!=0)&&(TypeFromToken(mdGet) != mdtMethodDef))
1127     {
1128         report->error("Invalid Get method of property '%s'\n",pPD->m_szName);
1129         return FALSE;
1130     }
1131
1132     nOthers = pPD->m_tklOthers.COUNT();
1133     mdOthers = new mdMethodDef[nOthers+1];
1134     if(mdOthers == NULL)
1135     {
1136         report->error("Failed to allocate Others array for prop descriptor\n");
1137         nOthers = 0;
1138     }
1139     for(int j=0; j < nOthers; j++)
1140     {
1141         mdOthers[j] = ResolveLocalMemberRef((mdToken)(UINT_PTR)(pPD->m_tklOthers.PEEK(j)));     // @WARNING: casting down from 'mdToken*' to 'mdToken'
1142         
1143         if((RidFromToken(mdOthers[j])!=0)&&(TypeFromToken(mdOthers[j]) != mdtMethodDef))
1144         {
1145             report->error("Invalid Other method of property '%s'\n",pPD->m_szName);
1146             delete [] mdOthers;
1147             return FALSE;
1148         }
1149         
1150     }
1151     mdOthers[nOthers] = mdMethodDefNil; // like null-terminator
1152
1153     if(FAILED(m_pEmitter->DefineProperty(   pPD->m_tdClass,
1154                                             wzMemberName,
1155                                             pPD->m_dwAttr,
1156                                             pPD->m_pSig,
1157                                             pPD->m_dwCSig,
1158                                             pPD->m_dwCPlusTypeFlag,
1159                                             pPD->m_pValue,
1160                                             pPD->m_cbValue,
1161                                             mdSet,
1162                                             mdGet,
1163                                             mdOthers,
1164                                             &(pPD->m_pdPropTok))))
1165     {
1166         report->error("Failed to define property '%s'.\n",pPD->m_szName);
1167         delete [] mdOthers;
1168         return FALSE;
1169     }
1170     EmitCustomAttributes(pPD->m_pdPropTok, &(pPD->m_CustomDescrList));
1171     return TRUE;
1172 }
1173
1174 Class *Assembler::FindCreateClass(__in __nullterminated const char *pszFQN)
1175 {
1176     Class *pSearch = NULL;
1177
1178     if(pszFQN)
1179     {
1180         dummyClass->m_szFQN = pszFQN;
1181         dummyClass->m_Hash = hash((BYTE*)pszFQN, (unsigned)strlen(pszFQN), 10);
1182         pSearch = m_hshClass.FIND(dummyClass);
1183         dummyClass->m_szFQN = NULL;
1184         dummyClass->m_Hash = 0;
1185
1186         if(!pSearch)
1187         {
1188             char* pch;
1189             DWORD dwFQN = (DWORD)strlen(pszFQN);
1190
1191             Class *pEncloser = NULL;
1192             char* pszNewFQN = new char[dwFQN+1];
1193             strcpy_s(pszNewFQN,dwFQN+1,pszFQN);
1194             if((pch = strrchr(pszNewFQN, NESTING_SEP)) != NULL)
1195             {
1196                 *pch = 0;
1197                 pEncloser = FindCreateClass(pszNewFQN);
1198                 *pch = NESTING_SEP;
1199             }
1200             pSearch = new Class(pszNewFQN);
1201             if (pSearch == NULL)
1202                 report->error("Failed to create class '%s'\n",pszNewFQN);
1203             else
1204             {
1205                 pSearch->m_pEncloser = pEncloser;
1206                 m_lstClass.PUSH(pSearch);
1207                 pSearch->m_cl = mdtTypeDef | m_lstClass.COUNT();
1208                 m_hshClass.PUSH(pSearch);
1209             }
1210         }
1211     }
1212
1213     return pSearch;
1214 }
1215
1216
1217 BOOL Assembler::EmitClass(Class *pClass)
1218 {
1219     LPCUTF8              szFullName;
1220     WCHAR*              wzFullName=&wzUniBuf[0];
1221     HRESULT             hr = E_FAIL;
1222     GUID                guid;
1223     size_t              L;
1224     mdToken             tok;
1225
1226     if(pClass == NULL) return FALSE;
1227
1228     hr = CoCreateGuid(&guid);
1229     if (FAILED(hr))
1230     {
1231         printf("Unable to create GUID\n");
1232         m_State = STATE_FAIL;
1233         return FALSE;
1234     }
1235
1236     if(pClass->m_pEncloser)
1237         szFullName = strrchr(pClass->m_szFQN,NESTING_SEP) + 1;
1238     else
1239         szFullName = pClass->m_szFQN;
1240
1241     WszMultiByteToWideChar(g_uCodePage,0,szFullName,-1,wzFullName,dwUniBuf);
1242
1243     L = wcslen(wzFullName);
1244     if((L==0)||(wzFullName[L-1]==L'.')) // Missing class name!
1245     {
1246         wcscat_s(wzFullName,dwUniBuf,W("$UNNAMED_TYPE$"));
1247     }
1248
1249     pClass->m_Attr = CheckClassFlagsIfNested(pClass->m_pEncloser, pClass->m_Attr);
1250
1251     if (pClass->m_pEncloser)
1252     {
1253         hr = m_pEmitter->DefineNestedType( wzFullName,
1254                                         pClass->m_Attr,      // attributes
1255                                         pClass->m_crExtends,  // CR extends class
1256                                         pClass->m_crImplements,// implements
1257                                         pClass->m_pEncloser->m_cl,  // Enclosing class.
1258                                         &tok);
1259     }
1260     else
1261     {
1262         hr = m_pEmitter->DefineTypeDef( wzFullName,
1263                                         pClass->m_Attr,      // attributes
1264                                         pClass->m_crExtends,  // CR extends class
1265                                         pClass->m_crImplements,// implements
1266                                         &tok);
1267     }
1268     _ASSERTE(tok == pClass->m_cl);
1269     if (FAILED(hr)) goto exit;
1270     if (pClass->m_NumTyPars)
1271     {
1272         ULONG i;
1273         mdToken* ptk;
1274         mdToken tk;
1275         for(i = 0; i < pClass->m_NumTyPars; i++)
1276         {
1277             //ptk = (pClass->m_TyParBounds[i] == NULL)? NULL :  (mdToken*)(pClass->m_TyParBounds[i]->ptr());
1278             //if(FAILED(m_pEmitter->DefineGenericParam(pClass->m_cl,i,pClass->m_TyParAttrs[i],pClass->m_TyParNames[i],0,ptk,&tk)))
1279             ptk = (pClass->m_TyPars[i].Bounds() == NULL)? NULL :  (mdToken*)(pClass->m_TyPars[i].Bounds()->ptr());
1280             if(FAILED(m_pEmitter->DefineGenericParam(pClass->m_cl,i,pClass->m_TyPars[i].Attrs(),pClass->m_TyPars[i].Name(),0,ptk,&tk)))
1281                 report->error("Unable to define generic param'\n");
1282             else
1283                 EmitCustomAttributes(tk, pClass->m_TyPars[i].CAList());
1284         }
1285     }
1286     
1287     
1288     EmitCustomAttributes(pClass->m_cl, &(pClass->m_CustDList));
1289     hr = S_OK;
1290
1291 exit:
1292     return SUCCEEDED(hr);
1293 }
1294
1295 BOOL Assembler::DoGlobalFixups()
1296 {
1297     GlobalFixup *pSearch;
1298
1299     for (int i=0; (pSearch = m_lstGlobalFixup.PEEK(i)); i++)
1300     {
1301         GlobalLabel *   pLabel = FindGlobalLabel(pSearch->m_szLabel);
1302         if (pLabel == NULL)
1303         {
1304             report->error("Unable to find forward reference global label '%s'\n",
1305                 pSearch->m_szLabel);
1306
1307             m_State = STATE_FAIL;
1308             return FALSE;
1309         }
1310         //BYTE * pReference = pSearch->m_pReference;
1311         //DWORD  GlobalOffset = pLabel->m_GlobalOffset;
1312         //memcpy(pReference,&GlobalOffset,4);
1313         SET_UNALIGNED_VAL32(pSearch->m_pReference,pLabel->m_GlobalOffset);
1314     }
1315
1316     return TRUE;
1317 }
1318
1319 state_t Assembler::AddGlobalLabel(__in __nullterminated char *pszName, HCEESECTION section)
1320 {
1321     if (FindGlobalLabel(pszName) != NULL)
1322     {
1323         report->error("Duplicate global label '%s'\n", pszName);
1324         m_State = STATE_FAIL;
1325         return m_State;
1326     }
1327
1328     ULONG GlobalOffset;
1329
1330     HRESULT hr;
1331     hr = m_pCeeFileGen->GetSectionDataLen(section, &GlobalOffset);
1332     _ASSERTE(SUCCEEDED(hr));
1333
1334     GlobalLabel *pNew = new GlobalLabel(pszName, GlobalOffset, section);
1335     if (pNew == 0)
1336     {
1337         report->error("Failed to allocate global label '%s'\n",pszName);
1338         m_State = STATE_FAIL;
1339         return m_State;
1340     }
1341
1342     m_lstGlobalLabel.PUSH(pNew);
1343     return m_State;
1344 }
1345
1346 void Assembler::AddLabel(DWORD CurPC, __in __nullterminated char *pszName)
1347 {
1348     if (m_pCurMethod->FindLabel(pszName) != NULL)
1349     {
1350         report->error("Duplicate label: '%s'\n", pszName);
1351
1352         m_State = STATE_FAIL;
1353     }
1354     else
1355     {
1356         Label *pNew = new Label(pszName, CurPC);
1357
1358         if (pNew != NULL)
1359             //m_pCurMethod->m_lstLabel.PUSH(pNew);
1360             m_lstLabel.PUSH(pNew);
1361         else
1362         {
1363             report->error("Failed to allocate label '%s'\n",pszName);
1364             m_State = STATE_FAIL;
1365         }
1366     }
1367 }
1368
1369 void Assembler::DoDeferredILFixups(Method* pMethod)
1370 { // Now that we know where in the file the code bytes will wind up,
1371   // we can update the RVAs and offsets.
1372     ILFixup *pSearch;
1373     HRESULT hr;
1374     GlobalFixup *Fix = NULL;
1375     int i;
1376     for (i=0;(pSearch = pMethod->m_lstILFixup.PEEK(i));i++)
1377     {
1378         switch(pSearch->m_Kind)
1379         {
1380             case ilGlobal:
1381                 Fix = pSearch->m_Fixup;
1382                 _ASSERTE(Fix != NULL);
1383                 Fix->m_pReference = pMethod->m_pCode+pSearch->m_OffsetInMethod;
1384                 break;
1385
1386             case ilToken:
1387                 hr = m_pCeeFileGen->AddSectionReloc(m_pILSection,
1388                                     pSearch->m_OffsetInMethod+pMethod->m_methodOffset,
1389                                     m_pILSection,
1390                                     srRelocMapToken);
1391                 _ASSERTE(SUCCEEDED(hr));
1392                 break;
1393
1394             case ilRVA:
1395                 hr = m_pCeeFileGen->AddSectionReloc(m_pILSection,
1396                                     pSearch->m_OffsetInMethod+pMethod->m_methodOffset,
1397                                     m_pGlobalDataSection,
1398                                     srRelocAbsolute);
1399                 _ASSERTE(SUCCEEDED(hr));
1400                 break;
1401
1402             default:
1403                 ;
1404         }
1405     }
1406 }
1407 /**************************************************************************/
1408 BOOL Assembler::DoFixups(Method* pMethod)
1409 {
1410     Fixup *pSearch;
1411
1412     for (int i=0; (pSearch = pMethod->m_lstFixup.PEEK(i)); i++)
1413     {
1414         Label * pLabel = pMethod->FindLabel(pSearch->m_szLabel);
1415         long    offset;
1416
1417         if (pLabel == NULL)
1418         {
1419             report->error("Unable to find forward reference label '%s' called from PC=%d\n",
1420                 pSearch->m_szLabel, pSearch->m_RelativeToPC);
1421
1422             //m_State = STATE_FAIL;
1423             return FALSE;
1424         }
1425
1426         offset = pLabel->m_PC - pSearch->m_RelativeToPC;
1427
1428         if (pSearch->m_FixupSize == 1)
1429         {
1430             if (offset > 127 || offset < -128)
1431             {
1432                 report->error("Offset of forward reference label '%s' called from PC=%d is too large for 1 byte pcrel\n",
1433                     pLabel->m_szName, pSearch->m_RelativeToPC);
1434
1435                 //m_State = STATE_FAIL;
1436                 return FALSE;
1437             }
1438
1439             *pSearch->m_pBytes = (BYTE) offset;
1440         }
1441         else if (pSearch->m_FixupSize == 4)
1442         {
1443             SET_UNALIGNED_VAL32(pSearch->m_pBytes,offset);
1444         }
1445     }
1446
1447     return TRUE;
1448 }
1449
1450
1451 OPCODE Assembler::DecodeOpcode(const BYTE *pCode, DWORD *pdwLen)
1452 {
1453     OPCODE opcode;
1454
1455     *pdwLen = 1;
1456     opcode = OPCODE(pCode[0]);
1457     switch(opcode) {
1458         case CEE_PREFIX1:
1459             opcode = OPCODE(pCode[1] + 256);
1460             if (opcode < 0 || opcode >= CEE_COUNT)
1461                 return CEE_COUNT;
1462             *pdwLen = 2;
1463             break;
1464
1465         case CEE_PREFIXREF:
1466         case CEE_PREFIX2:
1467         case CEE_PREFIX3:
1468         case CEE_PREFIX4:
1469         case CEE_PREFIX5:
1470         case CEE_PREFIX6:
1471         case CEE_PREFIX7:
1472             return CEE_COUNT;
1473         default:
1474             break;
1475     }
1476     return opcode;
1477 }
1478
1479 char* Assembler::ReflectionNotation(mdToken tk)
1480 {
1481     char *sz = (char*)&wzUniBuf[dwUniBuf>>1], *pc;
1482     *sz=0;
1483     switch(TypeFromToken(tk))
1484     {
1485         case mdtTypeDef:
1486             {
1487                 Class *pClass = m_lstClass.PEEK(RidFromToken(tk)-1);
1488                 if(pClass)
1489                 {
1490                     strcpy_s(sz,dwUniBuf>>1,pClass->m_szFQN);
1491                     pc = sz;
1492                     while((pc = strchr(pc,NESTING_SEP)) != NULL)
1493                     {
1494                         *pc = '+';
1495                         pc++;
1496                     }
1497                 }
1498             }
1499             break;
1500
1501         case mdtTypeRef:
1502             {
1503                 ULONG   N;
1504                 mdToken tkResScope;
1505                 if(SUCCEEDED(m_pImporter->GetTypeRefProps(tk,&tkResScope,wzUniBuf,dwUniBuf>>1,&N)))
1506                 {
1507                     WszWideCharToMultiByte(CP_UTF8,0,wzUniBuf,-1,sz,dwUniBuf>>1,NULL,NULL);
1508                     if(TypeFromToken(tkResScope)==mdtAssemblyRef)
1509                     {
1510                         AsmManAssembly *pAsmRef = m_pManifest->m_AsmRefLst.PEEK(RidFromToken(tkResScope)-1);
1511                         if(pAsmRef)
1512                         {
1513                             pc = &sz[strlen(sz)];
1514                             pc+=sprintf_s(pc,(dwUniBuf >> 1),", %s, Version=%d.%d.%d.%d, Culture=",pAsmRef->szName,
1515                                     pAsmRef->usVerMajor,pAsmRef->usVerMinor,pAsmRef->usBuild,pAsmRef->usRevision);
1516                             ULONG L=0;
1517                             if(pAsmRef->pLocale && (L=pAsmRef->pLocale->length()))
1518                             {
1519                                 memcpy(wzUniBuf,pAsmRef->pLocale->ptr(),L);
1520                                 wzUniBuf[L>>1] = 0;
1521                                 WszWideCharToMultiByte(CP_UTF8,0,wzUniBuf,-1,pc,dwUniBuf>>1,NULL,NULL);
1522                             }
1523                             else pc+=sprintf_s(pc,(dwUniBuf >> 1),"neutral");
1524                             pc = &sz[strlen(sz)];
1525                             if(pAsmRef->pPublicKeyToken && (L=pAsmRef->pPublicKeyToken->length()))
1526                             {
1527                                 pc+=sprintf_s(pc,(dwUniBuf >> 1),", Publickeytoken=");
1528                                 BYTE* pb = (BYTE*)(pAsmRef->pPublicKeyToken->ptr());
1529                                 for(N=0; N<L; N++,pb++) pc+=sprintf_s(pc,(dwUniBuf >> 1),"%2.2x",*pb);
1530                             }
1531                         }
1532                     }
1533                 }
1534             }
1535             break;
1536
1537         default:
1538             break;
1539     }
1540     return sz;
1541 }
1542
1543 /*
1544 --------------------------------------------------------------------
1545 mix -- mix 3 32-bit values reversibly.
1546 For every delta with one or two bits set, and the deltas of all three
1547   high bits or all three low bits, whether the original value of a,b,c
1548   is almost all zero or is uniformly distributed,
1549 * If mix() is run forward or backward, at least 32 bits in a,b,c
1550   have at least 1/4 probability of changing.
1551 * If mix() is run forward, every bit of c will change between 1/3 and
1552   2/3 of the time.  (Well, 22/100 and 78/100 for some 2-bit deltas.)
1553 mix() was built out of 36 single-cycle latency instructions in a 
1554   structure that could supported 2x parallelism, like so:
1555       a -= b; 
1556       a -= c; x = (c>>13);
1557       b -= c; a ^= x;
1558       b -= a; x = (a<<8);
1559       c -= a; b ^= x;
1560       c -= b; x = (b>>13);
1561       ...
1562   Unfortunately, superscalar Pentiums and Sparcs can't take advantage 
1563   of that parallelism.  They've also turned some of those single-cycle
1564   latency instructions into multi-cycle latency instructions.  Still,
1565   this is the fastest good hash I could find.  There were about 2^^68
1566   to choose from.  I only looked at a billion or so.
1567 --------------------------------------------------------------------
1568 */
1569 #define mix(a,b,c) \
1570 { \
1571   a -= b; a -= c; a ^= (c >> 13); \
1572   b -= c; b -= a; b ^= (a << 8);  \
1573   c -= a; c -= b; c ^= (b >> 13); \
1574   a -= b; a -= c; a ^= (c >> 12); \
1575   b -= c; b -= a; b ^= (a << 16); \
1576   c -= a; c -= b; c ^= (b >> 5);  \
1577   a -= b; a -= c; a ^= (c >> 3);  \
1578   b -= c; b -= a; b ^= (a << 10); \
1579   c -= a; c -= b; c ^= (b >> 15); \
1580 }
1581
1582 /*
1583 --------------------------------------------------------------------
1584 hash() -- hash a variable-length key into a 32-bit value
1585   k       : the key (the unaligned variable-length array of bytes)
1586   len     : the length of the key, counting by bytes
1587   initval : can be any 4-byte value
1588 Returns a 32-bit value.  Every bit of the key affects every bit of
1589 the return value.  Every 1-bit and 2-bit delta achieves avalanche.
1590 About 6*len+35 instructions.
1591
1592 The best hash table sizes are powers of 2.  There is no need to do
1593 mod a prime (mod is sooo slow!).  If you need less than 32 bits,
1594 use a bitmask.  For example, if you need only 10 bits, do
1595   h = (h & hashmask(10));
1596 In which case, the hash table should have hashsize(10) elements.
1597
1598 If you are hashing n strings (ub1 **)k, do it like this:
1599   for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
1600
1601 By Bob Jenkins, 1996.  bob_jenkins@burtleburtle.net.  You may use this
1602 code any way you wish, private, educational, or commercial.  It's free.
1603
1604 See http://burtleburtle.net/bob/hash/evahash.html
1605 Use for hash table lookup, or anything where one collision in 2^^32 is
1606 acceptable.  Do NOT use for cryptographic purposes.
1607 --------------------------------------------------------------------
1608 */
1609
1610 unsigned hash( 
1611      __in_ecount(length) const BYTE *k,        /* the key */
1612      unsigned  length,   /* the length of the key */
1613      unsigned  initval)  /* the previous hash, or an arbitrary value */
1614 {
1615    register unsigned a,b,c,len;
1616
1617    /* Set up the internal state */
1618    len = length;
1619    a = b = 0x9e3779b9;  /* the golden ratio; an arbitrary value */
1620    c = initval;         /* the previous hash value */
1621
1622    /*---------------------------------------- handle most of the key */
1623    while (len >= 12)
1624    {
1625       a += (k[0] + ((unsigned)k[1] << 8) + ((unsigned)k[2]  << 16) + ((unsigned)k[3]  << 24));
1626       b += (k[4] + ((unsigned)k[5] << 8) + ((unsigned)k[6]  << 16) + ((unsigned)k[7]  << 24));
1627       c += (k[8] + ((unsigned)k[9] << 8) + ((unsigned)k[10] << 16) + ((unsigned)k[11] << 24));
1628       mix(a,b,c);
1629       k += 12; len -= 12;
1630    }
1631
1632    /*------------------------------------- handle the last 11 bytes */
1633    c += length;
1634    switch(len)              /* all the case statements fall through */
1635    {
1636        case 11: c+=((unsigned)k[10] << 24);
1637        case 10: c+=((unsigned)k[9] << 16);
1638        case 9 : c+=((unsigned)k[8] << 8);
1639           /* the first byte of c is reserved for the length */
1640        case 8 : b+=((unsigned)k[7] << 24);
1641        case 7 : b+=((unsigned)k[6] << 16);
1642        case 6 : b+=((unsigned)k[5] << 8);
1643        case 5 : b+=k[4];
1644        case 4 : a+=((unsigned)k[3] << 24);
1645        case 3 : a+=((unsigned)k[2] << 16);
1646        case 2 : a+=((unsigned)k[1] << 8);
1647        case 1 : a+=k[0];
1648      /* case 0: nothing left to add */
1649    }
1650    mix(a,b,c);
1651    /*-------------------------------------------- report the result */
1652    return c;
1653 }
1654