Merge pull request #1965 from lasombra/patch-1
[platform/upstream/coreclr.git] / src / ilasm / assembler.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: assembler.cpp
6 //
7
8 //
9
10 #include "ilasmpch.h"
11
12 #include "assembler.h"
13 #include "binstr.h"
14 #include "nvpair.h"
15
16 #define FAIL_UNLESS(x, y) if (!(x)) { report->error y; return; }
17
18 /**************************************************************************/
19 void Assembler::StartNameSpace(__in __nullterminated char* name)
20 {
21     m_NSstack.PUSH(m_szNamespace);
22     m_szNamespace = name;
23     unsigned L = (unsigned)strlen(m_szFullNS);
24     unsigned l = (unsigned)strlen(name);
25     if(L+l+1 >= m_ulFullNSLen)
26     {
27         char* pch = new char[((L+l)/MAX_NAMESPACE_LENGTH + 1)*MAX_NAMESPACE_LENGTH];
28         if(pch)
29         {
30             memcpy(pch,m_szFullNS,L+1);
31             delete [] m_szFullNS;
32             m_szFullNS = pch;
33             m_ulFullNSLen = ((L+l)/MAX_NAMESPACE_LENGTH + 1)*MAX_NAMESPACE_LENGTH;
34         }
35         else report->error("Failed to reallocate the NameSpace buffer\n");
36     }
37     if(L) m_szFullNS[L] = NAMESPACE_SEPARATOR_CHAR;
38     else L = 0xFFFFFFFF;
39     memcpy(&m_szFullNS[L+1],m_szNamespace, l+1);
40 }
41
42 /**************************************************************************/
43 void Assembler::EndNameSpace()
44 {
45     char *p = &m_szFullNS[strlen(m_szFullNS)-strlen(m_szNamespace)];
46     if(p > m_szFullNS) p--;
47     *p = 0;
48     delete [] m_szNamespace;
49     if((m_szNamespace = m_NSstack.POP())==NULL)
50     {
51         m_szNamespace = new char[2];
52         m_szNamespace[0] = 0;
53     }
54 }
55
56 /**************************************************************************/
57 void    Assembler::ClearImplList(void)
58 {
59     while(m_nImplList) m_crImplList[--m_nImplList] = mdTypeRefNil;
60 }
61 /**************************************************************************/
62 #ifdef _PREFAST_
63 #pragma warning(push)
64 #pragma warning(disable:22008) // "Suppress PREfast warnings about integer overflow"
65 #endif
66 void    Assembler::AddToImplList(mdToken tk)
67 {
68     if(m_nImplList+1 >= m_nImplListSize)
69     {
70         mdToken *ptr = new mdToken[m_nImplListSize + MAX_INTERFACES_IMPLEMENTED];
71         if(ptr == NULL)
72         {
73             report->error("Failed to reallocate Impl List from %d to %d bytes\n",
74                 m_nImplListSize*sizeof(mdToken),
75                 (m_nImplListSize+MAX_INTERFACES_IMPLEMENTED)*sizeof(mdToken));
76             return;
77         }
78         memcpy(ptr,m_crImplList,m_nImplList*sizeof(mdToken));
79         delete m_crImplList;
80         m_crImplList = ptr;
81         m_nImplListSize += MAX_INTERFACES_IMPLEMENTED;
82     }
83     m_crImplList[m_nImplList++] = tk;
84     m_crImplList[m_nImplList] = mdTypeRefNil;
85 }
86 #ifdef _PREFAST_
87 #pragma warning(pop)
88 #endif
89
90 void    Assembler::ClearBoundList(void)
91 {
92     m_TyParList = NULL;
93 }
94 /**************************************************************************/
95 mdToken Assembler::ResolveClassRef(mdToken tkResScope, __in __nullterminated const char *pszFullClassName, Class** ppClass)
96 {
97     Class *pClass = NULL;
98     mdToken tkRet = mdTokenNil;
99     mdToken *ptkSpecial = NULL;
100
101     if(pszFullClassName == NULL) return mdTokenNil;
102 #if (0)
103     if (m_fInitialisedMetaData == FALSE)
104     {
105         if (FAILED(InitMetaData())) // impl. see WRITER.CPP
106         {
107             _ASSERTE(0);
108             if(ppClass) *ppClass = NULL;
109             return mdTokenNil;
110         }
111     }
112 #endif
113
114     switch(strlen(pszFullClassName))
115     {
116         case 11:
117             if(strcmp(pszFullClassName,"System.Enum")==0) ptkSpecial = &m_tkSysEnum;
118             break;
119         case 13:
120             if(strcmp(pszFullClassName,"System.Object")==0) ptkSpecial = &m_tkSysObject;
121             else if(strcmp(pszFullClassName,"System.String")==0) ptkSpecial = &m_tkSysString;
122             break;
123         case 16:
124             if(strcmp(pszFullClassName,"System.ValueType")==0) ptkSpecial = &m_tkSysValue;
125             break;
126     }
127     if(ptkSpecial) // special token
128     {
129         if(*ptkSpecial) // already resolved
130         {
131             tkRet = *ptkSpecial;
132             if(ppClass)
133             {
134                 if(TypeFromToken(tkRet)==mdtTypeDef)
135                     *ppClass = m_lstClass.PEEK(RidFromToken(tkRet)-1);
136                 else *ppClass = NULL;
137             }
138             return tkRet;
139         }
140         else  // needs to be resolved
141             if(!m_fIsMscorlib) tkResScope = GetBaseAsmRef();
142     }
143     if(tkResScope == 1)
144     {
145         if((pClass = FindCreateClass(pszFullClassName)) != NULL) tkRet = pClass->m_cl;
146     }
147     else
148     {
149         tkRet = MakeTypeRef(tkResScope, pszFullClassName);
150         pClass = NULL;
151     }
152     if(ppClass) *ppClass = pClass;
153     if(ptkSpecial) *ptkSpecial = tkRet;
154     return tkRet;
155 }
156
157 class TypeSpecContainer
158 {
159 private:
160     // Contain a BinStr
161     unsigned __int8 *ptr_;
162     unsigned len_;
163     // Hash the BinStr, just for speed of lookup
164     unsigned hash_;
165     // The value we're looking for
166     mdToken token_;
167 public:
168     // Constructor for a 'lookup' object
169     TypeSpecContainer(BinStr *typeSpec) :
170         ptr_(typeSpec->ptr()),
171         len_(typeSpec->length()),
172         hash_(typeSpec->length()),
173         token_(mdTokenNil)
174     {        
175         for (unsigned i = 0; i < len_; i++)
176             hash_ = (hash_ * 257) ^ ((i + 1) * (ptr_[i] ^ 0xA5));
177     }
178     // Constructor for a 'permanent' object
179     // Don't bother re-hashing, since we will always have already constructed the lookup object
180     TypeSpecContainer(const TypeSpecContainer &t, mdToken tk) : 
181         ptr_(new unsigned __int8[t.len_]),
182         len_(t.len_),
183         hash_(t.hash_),
184         token_(tk)
185     {
186         _ASSERT(tk != mdTokenNil);
187         _ASSERT(t.token_ == mdTokenNil);
188         memcpy(ptr_, t.ptr_, len_);
189     }
190     ~TypeSpecContainer()
191     {
192         if (token_ != mdTokenNil)
193             // delete any memory for a 'permanent' object
194             delete[] ptr_;
195     }
196     // this is the operator for a RBTREE
197     int ComparedTo(TypeSpecContainer *t) const
198     {
199         // If they don't hash the same, just diff the hashes
200         if (hash_ != t->hash_)
201             return hash_ - t->hash_;
202         if (len_ != t->len_)
203             return len_ - t->len_;
204         return memcmp(ptr_, t->ptr_, len_);
205     }
206     // The only public data we need
207     const mdToken Token() const { return token_; }
208 };
209
210 static RBTREE<TypeSpecContainer> typeSpecCache;
211
212 extern FIFO<char> TyParFixupList;
213
214 /**************************************************************************/
215 mdToken Assembler::ResolveTypeSpec(BinStr* typeSpec)
216 {
217     mdToken tk;
218
219     // It is safe to use the cache only if there are no pending fixups
220     if (TyParFixupList.COUNT() != 0)
221     {
222         if (FAILED(m_pEmitter->GetTokenFromTypeSpec(typeSpec->ptr(), typeSpec->length(), &tk)))
223             return mdTokenNil;
224         return tk;
225     }
226
227     TypeSpecContainer tsc(typeSpec);
228
229     // GetTokenFromTypeSpec is a linear search through an unsorted list
230     // Instead of doing that all the time, look this thing up in a cache
231     TypeSpecContainer *res = typeSpecCache.FIND(&tsc);
232     if (res != NULL)
233     {
234 #ifdef _DEBUG
235         // Verify that the cache is in sync with the master copy in metadata
236         PCOR_SIGNATURE pSig;
237         ULONG cSig;
238         m_pImporter->GetTypeSpecFromToken(res->Token(),(PCCOR_SIGNATURE*)&pSig,&cSig);
239         _ASSERTE(typeSpec->length() == cSig);
240         _ASSERTE(memcmp(typeSpec->ptr(), pSig, cSig) == 0);
241 #endif
242
243         return res->Token();
244     }
245
246     if (FAILED(m_pEmitter->GetTokenFromTypeSpec(typeSpec->ptr(), typeSpec->length(), &tk)))
247         return mdTokenNil;
248
249     typeSpecCache.PUSH(new TypeSpecContainer(tsc, tk));
250     return tk;
251 }
252
253 /**************************************************************************/
254 mdToken Assembler::GetAsmRef(__in __nullterminated const char* szName)
255 {
256     mdToken tkResScope = 0;
257     if(strcmp(szName,"*")==0) tkResScope = mdTokenNil;
258     else
259     {
260         tkResScope = m_pManifest->GetAsmRefTokByName(szName);
261         if(RidFromToken(tkResScope)==0)
262         {
263             // emit the AssemblyRef
264             // if it's not self, try to get attributes with Autodetect
265             unsigned L = (unsigned)strlen(szName)+1;
266             char *sz = new char[L];
267             if(sz)
268             {
269                 memcpy(sz,szName,L);
270                 AsmManAssembly *pAsmRef = m_pManifest->m_pCurAsmRef;
271                 m_pManifest->StartAssembly(sz,NULL,0,TRUE);
272                 if(RidFromToken(m_pManifest->GetAsmTokByName(szName))==0)
273                 {
274                     report->warn("Reference to undeclared extern assembly '%s'. Attempting autodetect\n",szName);
275                     m_pManifest->SetAssemblyAutodetect();
276                 }
277                 m_pManifest->EndAssembly();
278                 tkResScope = m_pManifest->GetAsmRefTokByName(szName);
279                 m_pManifest->m_pCurAsmRef = pAsmRef;
280             }
281             else
282                 report->error("\nOut of memory!\n");
283         }
284     }
285     return tkResScope;
286 }
287
288 mdToken Assembler::GetBaseAsmRef()
289 {
290     if(RidFromToken(m_pManifest->GetAsmRefTokByName("System.Runtime")) != 0)
291     {
292         return GetAsmRef("System.Runtime");
293     }
294
295     return GetAsmRef("mscorlib");
296 }
297
298 mdToken Assembler::GetInterfaceImpl(mdToken tsClass, mdToken tsInterface) 
299 {
300     mdToken result = mdTokenNil;
301     HCORENUM iiEnum = 0;
302     ULONG actualInterfaces;
303     mdInterfaceImpl impls;
304     
305     while (SUCCEEDED(m_pImporter->EnumInterfaceImpls(&iiEnum, tsClass, &impls, 1, &actualInterfaces)))
306     {
307         if (actualInterfaces == 1)
308         {
309             mdToken classToken, interfaceToken;
310             if (FAILED(m_pImporter->GetInterfaceImplProps(impls, &classToken, &interfaceToken)))
311                 break;
312             if (classToken == tsClass && interfaceToken == tsInterface)
313             {
314                 result = impls;
315                 break;
316             }
317         }
318     }
319     m_pImporter->CloseEnum(iiEnum);
320     return result;
321 }
322
323 /**************************************************************************/
324 mdToken Assembler::GetModRef(__in __nullterminated char* szName)
325 {
326     mdToken tkResScope = 0;
327     if(!strcmp(szName,m_szScopeName))
328             tkResScope = 1; // scope is "this module"
329     else
330     {
331         ImportDescriptor*   pID;
332         int i = 0;
333         tkResScope = mdModuleRefNil;
334         DWORD L = (DWORD)strlen(szName);
335         while((pID=m_ImportList.PEEK(i++)))
336         {
337             if(pID->dwDllName != L) continue;
338             if((L > 0) && (strcmp(pID->szDllName,szName)!=0)) continue;
339             tkResScope = pID->mrDll;
340             break;
341         }
342         if(RidFromToken(tkResScope)==0)
343             report->error("Undefined module ref '%s'\n",szName);
344     }
345     return tkResScope;
346 }
347 /**************************************************************************/
348 mdToken Assembler::MakeTypeRef(mdToken tkResScope, LPCUTF8 pszFullClassName)
349 {
350     mdToken tkRet = mdTokenNil;
351     if(pszFullClassName && *pszFullClassName)
352     {
353         LPCUTF8 pc;
354         if((pc = strrchr(pszFullClassName,NESTING_SEP))) // scope: enclosing class
355         {
356             LPUTF8 szScopeName;
357             DWORD L = (DWORD)(pc-pszFullClassName);
358             if((szScopeName = new char[L+1]) != NULL)
359             {
360                 memcpy(szScopeName,pszFullClassName,L);
361                 szScopeName[L] = 0;
362                 tkResScope = MakeTypeRef(tkResScope,szScopeName);
363                 delete [] szScopeName;
364             }
365             else
366                 report->error("\nOut of memory!\n");
367             pc++;
368         }
369         else pc = pszFullClassName;
370         if(*pc)
371         {
372             // convert name to widechar
373             WszMultiByteToWideChar(g_uCodePage,0,pc,-1,wzUniBuf,dwUniBuf);
374             if(FAILED(m_pEmitter->DefineTypeRefByName(tkResScope, wzUniBuf, &tkRet))) tkRet = mdTokenNil;
375         }
376     }
377     return tkRet;
378 }
379 /**************************************************************************/
380
381 DWORD Assembler::CheckClassFlagsIfNested(Class* pEncloser, DWORD attr)
382 {
383     DWORD wasAttr = attr;
384     if(pEncloser && (!IsTdNested(attr)))
385     {
386         if(OnErrGo)
387             report->error("Nested class has non-nested visibility (0x%08X)\n",attr);
388         else
389         {
390             attr &= ~tdVisibilityMask;
391             attr |= (IsTdPublic(wasAttr) ? tdNestedPublic : tdNestedPrivate);
392             report->warn("Nested class has non-nested visibility (0x%08X), changed to nested (0x%08X)\n",wasAttr,attr);
393         }
394     }
395     else if((pEncloser==NULL) && IsTdNested(attr))
396     {
397         if(OnErrGo)
398             report->error("Non-nested class has nested visibility (0x%08X)\n",attr);
399         else
400         {
401             attr &= ~tdVisibilityMask;
402             attr |= (IsTdNestedPublic(wasAttr) ? tdPublic : tdNotPublic);
403             report->warn("Non-nested class has nested visibility (0x%08X), changed to non-nested (0x%08X)\n",wasAttr,attr);
404         }
405     }
406     return attr;
407 }
408
409 /**************************************************************************/
410
411 void Assembler::StartClass(__in __nullterminated char* name, DWORD attr, TyParList *typars)
412 {
413     Class *pEnclosingClass = m_pCurClass;
414     char *szFQN;
415     ULONG LL;
416
417     m_TyParList = typars;
418
419     if (m_pCurMethod != NULL)
420     {
421         report->error("Class cannot be declared within a method scope\n");
422     }
423     if(pEnclosingClass)
424     {
425         LL = pEnclosingClass->m_dwFQN+(ULONG)strlen(name)+2;
426         if((szFQN = new char[LL]))
427             sprintf_s(szFQN,LL,"%s%c%s",pEnclosingClass->m_szFQN,NESTING_SEP,name);
428         else
429             report->error("\nOut of memory!\n");
430     }
431     else
432     {
433         unsigned L = (unsigned)strlen(m_szFullNS);
434         unsigned LLL = (unsigned)strlen(name);
435         LL = L + LLL + (L ? 2 : 1);
436         if((szFQN = new char[LL]))
437         {
438             if(L) sprintf_s(szFQN,LL,"%s.%s",m_szFullNS,name);
439             else memcpy(szFQN,name,LL);
440             if(LL > MAX_CLASSNAME_LENGTH)
441             {
442                 report->error("Full class name too long (%d characters, %d allowed).\n",LL-1,MAX_CLASSNAME_LENGTH-1);
443             }
444         }
445         else
446             report->error("\nOut of memory!\n");
447     }
448     if(szFQN == NULL) return;
449
450     mdToken tkThis;
451     if(m_fIsMscorlib)
452         tkThis = ResolveClassRef(1,szFQN,&m_pCurClass); // boils down to FindCreateClass(szFQN)
453     else
454     {
455         m_pCurClass = FindCreateClass(szFQN);
456         tkThis = m_pCurClass->m_cl;
457     }
458     if(m_pCurClass->m_bIsMaster)
459     {
460         m_pCurClass->m_Attr = CheckClassFlagsIfNested(pEnclosingClass, attr);
461
462         if (m_TyParList)
463         {
464             //m_pCurClass->m_NumTyPars = m_TyParList->ToArray(&m_pCurClass->m_TyParBounds, &m_pCurClass->m_TyParNames, &m_pCurClass->m_TyParAttrs);
465             m_pCurClass->m_NumTyPars = m_TyParList->ToArray(&(m_pCurClass->m_TyPars));
466             delete m_TyParList;
467             m_TyParList = NULL;
468         }
469         else m_pCurClass->m_NumTyPars = 0;
470         m_pCurClass->m_pEncloser = pEnclosingClass;
471     } // end if(old class) else
472     m_tkCurrentCVOwner = 0;
473     m_CustomDescrListStack.PUSH(m_pCustomDescrList);
474     m_pCustomDescrList = &(m_pCurClass->m_CustDList);
475
476     m_ClassStack.PUSH(pEnclosingClass);
477     ClearBoundList();
478 }
479
480 /**************************************************************************/
481
482 void Assembler::AddClass()
483 {
484     mdTypeRef   crExtends = mdTypeRefNil;
485     BOOL bIsEnum = FALSE;
486     BOOL bIsValueType = FALSE;
487
488     if(m_pCurClass->m_bIsMaster)
489     {
490         DWORD attr = m_pCurClass->m_Attr;
491         if(!IsNilToken(m_crExtends))
492         {
493             // has a superclass
494             if(IsTdInterface(attr)) report->error("Base class in interface\n");
495             bIsValueType = (m_crExtends == m_tkSysValue)&&(m_pCurClass->m_cl != m_tkSysEnum);
496             bIsEnum = (m_crExtends == m_tkSysEnum);
497             crExtends = m_crExtends;
498         }
499         else
500         {
501             bIsEnum = ((attr & 0x40000000) != 0);
502             bIsValueType = ((attr & 0x80000000) != 0);
503         }
504         attr &= 0x3FFFFFFF;
505         if (m_fAutoInheritFromObject && (crExtends == mdTypeRefNil) && (!IsTdInterface(attr)))
506         {
507             mdToken tkMscorlib = m_fIsMscorlib ? 1 : GetBaseAsmRef();
508             crExtends = bIsEnum ?
509                 ResolveClassRef(tkMscorlib,"System.Enum",NULL)
510                 :( bIsValueType ?
511                     ResolveClassRef(tkMscorlib,"System.ValueType",NULL)
512                     : ResolveClassRef(tkMscorlib, "System.Object",NULL));
513         }
514         m_pCurClass->m_Attr = attr;
515         m_pCurClass->m_crExtends = (m_pCurClass->m_cl == m_tkSysObject)? mdTypeRefNil : crExtends;
516
517         if ((m_pCurClass->m_dwNumInterfaces = m_nImplList) != NULL)
518         {
519             if(bIsEnum) report->error("Enum implementing interface(s)\n");
520             if((m_pCurClass->m_crImplements = new mdTypeRef[m_nImplList+1]) != NULL)
521                 memcpy(m_pCurClass->m_crImplements, m_crImplList, (m_nImplList+1)*sizeof(mdTypeRef));
522             else
523             {
524                 report->error("Failed to allocate Impl List for class '%s'\n", m_pCurClass->m_szFQN);
525                 m_pCurClass->m_dwNumInterfaces = 0;
526             }
527         }
528         else m_pCurClass->m_crImplements = NULL;
529         if(bIsValueType)
530         {
531             if(!IsTdSealed(attr))
532             {
533                 if(OnErrGo) report->error("Non-sealed value class\n");
534                 else
535                 {
536                     report->warn("Non-sealed value class, made sealed\n");
537                     m_pCurClass->m_Attr |= tdSealed;
538                 }
539             }
540         }
541         m_pCurClass->m_bIsMaster = FALSE;
542     } // end if(old class) else
543     ClearImplList();
544     m_crExtends = mdTypeRefNil;
545 }
546
547 /**************************************************************************/
548 void Assembler::EndClass()
549 {
550     m_pCurClass = m_ClassStack.POP();
551     m_tkCurrentCVOwner = 0;
552     m_pCustomDescrList = m_CustomDescrListStack.POP();
553 }
554
555 /**************************************************************************/
556 void Assembler::SetPinvoke(BinStr* DllName, int Ordinal, BinStr* Alias, int Attrs)
557 {
558     if(m_pPInvoke) delete m_pPInvoke;
559     if(DllName->length())
560     {
561         if((m_pPInvoke = new PInvokeDescriptor))
562         {
563             unsigned l;
564             ImportDescriptor* pID;
565             if((pID = EmitImport(DllName)))
566             {
567                 m_pPInvoke->mrDll = pID->mrDll;
568                 m_pPInvoke->szAlias = NULL;
569                 if(Alias)
570                 {
571                     l = Alias->length();
572                     if((m_pPInvoke->szAlias = new char[l+1]))
573                     {
574                         memcpy(m_pPInvoke->szAlias,Alias->ptr(),l);
575                         m_pPInvoke->szAlias[l] = 0;
576                     }
577                     else report->error("\nOut of memory!\n");
578                 }
579                 m_pPInvoke->dwAttrs = (DWORD)Attrs;
580             }
581             else
582             {
583                 delete m_pPInvoke;
584                 m_pPInvoke = NULL;
585                 report->error("PInvoke refers to undefined imported DLL\n");
586             }
587         }
588         else
589             report->error("Failed to allocate PInvokeDescriptor\n");
590     }
591     else
592     {
593         m_pPInvoke = NULL; // No DLL name, it's "local" (IJW) PInvoke
594         report->error("Local (embedded native) PInvoke method, the resulting PE file is unusable\n");
595     }
596     if(DllName) delete DllName;
597     if(Alias) delete Alias;
598 }
599
600 /**************************************************************************/
601 void Assembler::StartMethod(__in __nullterminated char* name, BinStr* sig, CorMethodAttr flags, BinStr* retMarshal, DWORD retAttr, TyParList *typars)
602 {
603     if (m_pCurMethod != NULL)
604     {
605         report->error("Cannot declare a method '%s' within another method\n",name);
606     }
607     if (!m_fInitialisedMetaData)
608     {
609         if (FAILED(InitMetaData())) // impl. see WRITER.CPP
610         {
611             _ASSERTE(0);
612         }
613     }
614     size_t namelen = strlen(name);
615     if(namelen >= MAX_CLASSNAME_LENGTH)
616     {
617         char c = name[MAX_CLASSNAME_LENGTH-1];
618         name[MAX_CLASSNAME_LENGTH-1] = 0;
619         report->error("Method '%s...' -- name too long (%d characters).\n",name,namelen);
620         name[MAX_CLASSNAME_LENGTH-1] = c;
621     }
622     if (!(flags & mdStatic))
623         *(sig->ptr()) |= IMAGE_CEE_CS_CALLCONV_HASTHIS;
624     else if(*(sig->ptr()) & (IMAGE_CEE_CS_CALLCONV_HASTHIS | IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS))
625     {
626         if(OnErrGo) report->error("Method '%s' -- both static and instance\n", name);
627         else
628         {
629             report->warn("Method '%s' -- both static and instance, set to static\n", name);
630             *(sig->ptr()) &= ~(IMAGE_CEE_CS_CALLCONV_HASTHIS | IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS);
631         }
632     }
633
634     if(!IsMdPrivateScope(flags))
635     {
636         Method* pMethod;
637         Class* pClass = (m_pCurClass ? m_pCurClass : m_pModuleClass);
638         DWORD L = (DWORD)strlen(name);
639         for(int j=0; (pMethod = pClass->m_MethodList.PEEK(j)); j++)
640         {
641             if( (pMethod->m_dwName == L) &&
642                 (!strcmp(pMethod->m_szName,name)) &&
643                 (pMethod->m_dwMethodCSig == sig->length())  &&
644                 (!memcmp(pMethod->m_pMethodSig,sig->ptr(),sig->length()))
645                 &&(!IsMdPrivateScope(pMethod->m_Attr)))
646             {
647                 if(m_fTolerateDupMethods)
648                 {
649                     // reset for new body
650                     pMethod->m_lstFixup.RESET(true);
651                     //pMethod->m_lstLabel.RESET(true);
652                     m_lstLabel.RESET(true);
653                     pMethod->m_Locals.RESET(true);
654                     delArgNameList(pMethod->m_firstArgName);
655                     delArgNameList(pMethod->m_firstVarName);
656                     pMethod->m_pCurrScope = &(pMethod->m_MainScope);
657                     pMethod->m_pCurrScope->Reset();
658                     pMethod->m_firstArgName = getArgNameList();
659                     pMethod->m_dwNumExceptions = 0;
660                     pMethod->m_dwNumEndfilters = 0;
661                     if(pMethod->m_pRetMarshal) delete pMethod->m_pRetMarshal;
662                     if(pMethod->m_pRetValue) delete pMethod->m_pRetValue;
663                     
664                     pMethod->m_MethodImplDList.RESET(false); // ptrs in m_MethodImplDList are dups of those in Assembler
665
666                     pMethod->m_CustomDescrList.RESET(true);
667
668                     if(pMethod->m_fEntryPoint)
669                     {
670                         pMethod->m_fEntryPoint = FALSE;
671                         m_fEntryPointPresent = FALSE;
672                     }
673
674                     if(pMethod->m_pbsBody)
675                     {
676                         // no need to remove relevant MemberRef Fixups from the Assembler list:
677                         // their m_fNew flag is set to FALSE anyway.
678                         // Just get rid of old method body
679                         delete pMethod->m_pbsBody;
680                         pMethod->m_pbsBody = NULL;
681                     }
682
683                     pMethod->m_fNewBody = TRUE;
684                     m_pCurMethod = pMethod;
685                 }
686                 else
687                     report->error("Duplicate method declaration\n");
688                 break;
689             }
690         }
691     }
692     if(m_pCurMethod == NULL)
693     {
694         if(m_pCurClass)
695         { // instance method
696             if(IsMdAbstract(flags) && !IsTdAbstract(m_pCurClass->m_Attr))
697             {
698                 report->error("Abstract method '%s' in non-abstract class '%s'\n",name,m_pCurClass->m_szFQN);
699             }
700             if(m_pCurClass->m_crExtends == m_tkSysEnum) report->error("Method in enum\n");
701
702             if(!strcmp(name,COR_CTOR_METHOD_NAME))
703             {
704                 flags = (CorMethodAttr)(flags | mdSpecialName);
705                 if(IsTdInterface(m_pCurClass->m_Attr)) report->error("Instance constructor in interface\n");
706
707             }
708             if(!IsMdStatic(flags))
709             {
710                 if(IsTdInterface(m_pCurClass->m_Attr))
711                 {
712                     if(!IsMdPublic(flags)) report->error("Non-public instance method in interface\n");
713                     if((!(IsMdVirtual(flags) && IsMdAbstract(flags))))
714                     {
715                         if(OnErrGo) report->error("Non-virtual, non-abstract instance method in interface\n");
716                         else
717                         {
718                             report->warn("Non-virtual, non-abstract instance method in interface, set to such\n");
719                             flags = (CorMethodAttr)(flags |mdVirtual | mdAbstract);
720                         }
721                     }
722     
723                 }
724             }
725             m_pCurMethod = new Method(this, m_pCurClass, name, sig, flags);
726         }
727         else
728         {
729             if(IsMdAbstract(flags))
730             {
731                 if(OnErrGo) report->error("Global method '%s' can't be abstract\n",name);
732                 else
733                 {
734                     report->warn("Global method '%s' can't be abstract, flag removed\n",name);
735                     flags = (CorMethodAttr)(((int) flags) &~mdAbstract);
736                 }
737             }
738             if(!IsMdStatic(flags))
739             {
740                 if(OnErrGo) report->error("Non-static global method '%s'\n",name);
741                 else
742                 {
743                     report->warn("Non-static global method '%s', made static\n",name);
744                     flags = (CorMethodAttr)(flags | mdStatic);
745                     *((BYTE*)(sig->ptr())) &= ~(IMAGE_CEE_CS_CALLCONV_HASTHIS | IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS);
746                 }
747             }
748             m_pCurMethod = new Method(this, m_pCurClass, name, sig, flags);
749             if (m_pCurMethod)
750             {
751                 m_pCurMethod->SetIsGlobalMethod();
752                 if (m_fInitialisedMetaData == FALSE) InitMetaData();
753             }
754         }
755         if(m_pCurMethod)
756         {
757             if(!OnErrGo)
758             {
759                 if(m_pCurMethod->m_firstArgName)
760                 {
761                     for(ARG_NAME_LIST *pAN=m_pCurMethod->m_firstArgName; pAN; pAN = pAN->pNext)
762                     {
763                         if(pAN->dwName)
764                         {
765                             int k = m_pCurMethod->findArgNum(pAN->pNext,pAN->szName,pAN->dwName);
766                             if(k >= 0)
767                                 report->warn("Duplicate param name '%s' in method '%s'\n",pAN->szName,name);
768                         }
769                     }
770                 }
771             }
772             m_pCurMethod->m_pRetMarshal = retMarshal;
773             m_pCurMethod->m_dwRetAttr = retAttr;
774             m_tkCurrentCVOwner = 0;
775             m_CustomDescrListStack.PUSH(m_pCustomDescrList);
776             m_pCustomDescrList = &(m_pCurMethod->m_CustomDescrList);
777             m_pCurMethod->m_MainScope.dwStart = m_CurPC;
778             if (typars)
779             {
780                 //m_pCurMethod->m_NumTyPars = typars->ToArray(&m_pCurMethod->m_TyParBounds,
781                 //&m_pCurMethod->m_TyParNames, NULL);
782                 m_pCurMethod->m_NumTyPars = typars->ToArray(&(m_pCurMethod->m_TyPars));
783                 delete typars;
784                 m_TyParList = NULL;
785             }
786             else m_pCurMethod->m_NumTyPars = 0;
787         }
788         else report->error("Failed to allocate Method class\n");
789     } // end if new method
790 }
791
792 /**************************************************************************/
793 void Assembler::EndMethod()
794 {
795
796     if(m_pCurMethod->m_pCurrScope != &(m_pCurMethod->m_MainScope))
797     {
798         report->error("Invalid lexical scope structure in method %s\n",m_pCurMethod->m_szName);
799     }
800     m_pCurMethod->m_pCurrScope->dwEnd = m_CurPC;
801     if (DoFixups(m_pCurMethod)) AddMethod(m_pCurMethod); //AddMethod - see ASSEM.CPP
802     else
803     {
804         report->error("Method '%s' compilation failed.\n",m_pCurMethod->m_szName);
805     }
806     //m_pCurMethod->m_lstLabel.RESET(true);
807     m_lstLabel.RESET(true);
808     m_tkCurrentCVOwner = 0;
809     m_pCustomDescrList = m_CustomDescrListStack.POP();
810     ResetForNextMethod(); // see ASSEM.CPP
811 }
812 /**************************************************************************/
813 /* rvaLabel is the optional label that indicates this field points at a particular RVA */
814 void Assembler::AddField(__inout_z __inout char* name, BinStr* sig, CorFieldAttr flags, __in __nullterminated char* rvaLabel, BinStr* pVal, ULONG ulOffset)
815 {
816     FieldDescriptor*    pFD;
817     ULONG   i,n;
818     mdToken tkParent = mdTokenNil;
819     Class* pClass;
820
821     if (m_pCurMethod)
822         report->error("Field cannot be declared within a method\n");
823
824     if(strlen(name) >= MAX_CLASSNAME_LENGTH)
825     {
826         char c = name[MAX_CLASSNAME_LENGTH-1];
827         name[MAX_CLASSNAME_LENGTH-1] = 0;
828         report->error("Field '%s...' -- name too long (%d characters).\n",name,strlen(name));
829         name[MAX_CLASSNAME_LENGTH-1] = c;
830     }
831
832     if(sig && (sig->length() >= 2))
833     {
834         if(sig->ptr()[1] == ELEMENT_TYPE_VOID)
835             report->error("Illegal use of type 'void'\n");
836     }
837
838     if (m_pCurClass)
839     {
840         tkParent = m_pCurClass->m_cl;
841
842         if(IsTdInterface(m_pCurClass->m_Attr))
843         {
844             if(!IsFdStatic(flags))
845             { 
846                 report->warn("Instance field in interface (CLS violation)\n");
847                 if(!IsFdPublic(flags)) report->error("Non-public instance field in interface\n");
848             }
849         }
850     }
851     else
852     {
853         if(ulOffset != 0xFFFFFFFF)
854         {
855             report->warn("Offset in global field '%s' is ignored\n",name);
856             ulOffset = 0xFFFFFFFF;
857         }
858         if(!IsFdStatic(flags))
859         {
860             if(OnErrGo) report->error("Non-static global field\n");
861             else
862             {
863                 report->warn("Non-static global field, made static\n");
864                 flags = (CorFieldAttr)(flags | fdStatic);
865             }
866         }
867     }
868     pClass = (m_pCurClass ? m_pCurClass : m_pModuleClass);
869     n = pClass->m_FieldDList.COUNT();
870     DWORD L = (DWORD)strlen(name);
871     for(i = 0; i < n; i++)
872     {
873         pFD = pClass->m_FieldDList.PEEK(i);
874         if((pFD->m_tdClass == tkParent)&&(L==pFD->m_dwName)&&(!strcmp(pFD->m_szName,name))
875             &&(pFD->m_pbsSig->length() == sig->length())
876             &&(memcmp(pFD->m_pbsSig->ptr(),sig->ptr(),sig->length())==0))
877         {
878             report->error("Duplicate field declaration: '%s'\n",name);
879             break;
880         }
881     }
882     if (rvaLabel && !IsFdStatic(flags))
883         report->error("Only static fields can have 'at' clauses\n");
884
885     if(i >= n)
886     {
887         if((pFD = new FieldDescriptor))
888         {
889             pFD->m_tdClass = tkParent;
890             pFD->m_szName = name;
891             pFD->m_dwName = L;
892             pFD->m_fdFieldTok = mdTokenNil;
893             if((pFD->m_ulOffset = ulOffset) != 0xFFFFFFFF) pClass->m_dwNumFieldsWithOffset++;
894             pFD->m_rvaLabel = rvaLabel;
895             pFD->m_pbsSig = sig;
896             pFD->m_pClass = pClass;
897             pFD->m_pbsValue = pVal;
898             pFD->m_pbsMarshal = m_pMarshal;
899             pFD->m_pPInvoke = m_pPInvoke;
900             pFD->m_dwAttr = flags;
901
902             m_tkCurrentCVOwner = 0;
903             m_pCustomDescrList = &(pFD->m_CustomDescrList);
904
905             pClass->m_FieldDList.PUSH(pFD);
906             pClass->m_fNewMembers = TRUE;
907         }
908         else
909             report->error("Failed to allocate Field Descriptor\n");
910     }
911     else
912     {
913         if(pVal) delete pVal;
914         if(m_pPInvoke) delete m_pPInvoke;
915         if(m_pMarshal) delete m_pMarshal;
916         delete name;
917     }
918     m_pPInvoke = NULL;
919     m_pMarshal = NULL;
920 }
921
922 BOOL Assembler::EmitField(FieldDescriptor* pFD)
923 {
924     WCHAR*   wzFieldName=&wzUniBuf[0];
925     HRESULT hr;
926     DWORD   cSig;
927     COR_SIGNATURE* mySig;
928     mdFieldDef mb;
929     BYTE    ValType = ELEMENT_TYPE_VOID;
930     void * pValue = NULL;
931     unsigned lVal = 0;
932     BOOL ret = TRUE;
933
934     cSig = pFD->m_pbsSig->length();
935     mySig = (COR_SIGNATURE*)(pFD->m_pbsSig->ptr());
936
937     WszMultiByteToWideChar(g_uCodePage,0,pFD->m_szName,-1,wzFieldName,dwUniBuf); //int)cFieldNameLength);
938     if(IsFdPrivateScope(pFD->m_dwAttr))
939     {
940         WCHAR* p = wcsstr(wzFieldName,W("$PST04"));
941         if(p) *p = 0;
942     }
943
944     if(pFD->m_pbsValue && pFD->m_pbsValue->length())
945     {
946         ValType = *(pFD->m_pbsValue->ptr());
947         lVal = pFD->m_pbsValue->length() - 1; // 1 is type byte
948         pValue = (void*)(pFD->m_pbsValue->ptr() + 1);
949         if(ValType == ELEMENT_TYPE_STRING)
950         {
951             //while(lVal % sizeof(WCHAR)) { pFD->m_pbsValue->appendInt8(0); lVal++; }
952             lVal /= sizeof(WCHAR);
953
954 #if defined(ALIGN_ACCESS) || BIGENDIAN
955             void* pValueTemp = _alloca(lVal * sizeof(WCHAR));
956             memcpy(pValueTemp, pValue, lVal * sizeof(WCHAR));
957             pValue = pValueTemp;
958
959             SwapStringLength((WCHAR*)pValue, lVal);
960 #endif
961         }
962     }
963
964     hr = m_pEmitter->DefineField(
965         pFD->m_tdClass,
966         wzFieldName,
967         pFD->m_dwAttr,
968         mySig,
969         cSig,
970         ValType,
971         pValue,
972         lVal,
973         &mb
974     );
975     if (FAILED(hr))
976     {
977         report->error("Failed to define field '%s' (HRESULT=0x%08X)\n",pFD->m_szName,hr);
978         ret = FALSE;
979     }
980     else
981     {
982         //--------------------------------------------------------------------------------
983         if(IsFdPinvokeImpl(pFD->m_dwAttr)&&(pFD->m_pPInvoke))
984         {
985             if(pFD->m_pPInvoke->szAlias == NULL) pFD->m_pPInvoke->szAlias = pFD->m_szName;
986             if(FAILED(EmitPinvokeMap(mb,pFD->m_pPInvoke)))
987             {
988                 report->error("Failed to define PInvoke map of .field '%s'\n",pFD->m_szName);
989                 ret = FALSE;
990             }
991         }
992         //--------------------------------------------------------------------------
993         if(pFD->m_pbsMarshal)
994         {
995             if(FAILED(hr = m_pEmitter->SetFieldMarshal (
996                                         mb,                     // [IN] given a fieldDef or paramDef token
997                         (PCCOR_SIGNATURE)(pFD->m_pbsMarshal->ptr()),   // [IN] native type specification
998                                         pFD->m_pbsMarshal->length())))  // [IN] count of bytes of pvNativeType
999             {
1000                 report->error("Failed to set field marshaling for '%s' (HRESULT=0x%08X)\n",pFD->m_szName,hr);
1001                 ret = FALSE;
1002             }
1003         }
1004         //--------------------------------------------------------------------------------
1005         // Set the the RVA to a dummy value.  later it will be fixed
1006         // up to be something correct, but if we don't emit something
1007         // the size of the meta-data will not be correct
1008         if (pFD->m_rvaLabel)
1009         {
1010             m_fHaveFieldsWithRvas = TRUE;
1011             hr = m_pEmitter->SetFieldRVA(mb, 0xCCCCCCCC);
1012             if (FAILED(hr))
1013             {
1014                 report->error("Failed to set RVA for field '%s' (HRESULT=0x%08X)\n",pFD->m_szName,hr);
1015                 ret = FALSE;
1016             }
1017         }
1018         //--------------------------------------------------------------------------------
1019         EmitCustomAttributes(mb, &(pFD->m_CustomDescrList));
1020
1021     }
1022     pFD->m_fdFieldTok = mb;
1023     return ret;
1024 }
1025
1026 /**************************************************************************/
1027 void Assembler::EmitByte(int val)
1028 {
1029     char ch = (char)val;
1030     //if((val < -128)||(val > 127))
1031    //       report->warn("Emitting 0x%X as a byte: data truncated to 0x%X\n",(unsigned)val,(BYTE)ch);
1032     EmitBytes((BYTE *)&ch,1);
1033 }
1034
1035 /**************************************************************************/
1036 void Assembler::NewSEHDescriptor(void) //sets m_SEHD
1037 {
1038     m_SEHDstack.PUSH(m_SEHD);
1039     m_SEHD = new SEH_Descriptor;
1040     if(m_SEHD == NULL) report->error("Failed to allocate SEH descriptor\n");
1041 }
1042 /**************************************************************************/
1043 void Assembler::SetTryLabels(__in __nullterminated char * szFrom, __in __nullterminated char *szTo)
1044 {
1045     if(!m_SEHD) return;
1046     Label *pLbl = m_pCurMethod->FindLabel(szFrom);
1047     if(pLbl)
1048     {
1049         m_SEHD->tryFrom = pLbl->m_PC;
1050         if((pLbl = m_pCurMethod->FindLabel(szTo)))  m_SEHD->tryTo = pLbl->m_PC; //FindLabel: Method.CPP
1051         else report->error("Undefined 2nd label in 'try <label> to <label>'\n");
1052     }
1053     else report->error("Undefined 1st label in 'try <label> to <label>'\n");
1054 }
1055 /**************************************************************************/
1056 void Assembler::SetFilterLabel(__in __nullterminated char *szFilter)
1057 {
1058     if(!m_SEHD) return;
1059     Label *pLbl = m_pCurMethod->FindLabel(szFilter);
1060     if(pLbl)    m_SEHD->sehFilter = pLbl->m_PC;
1061     else report->error("Undefined label in 'filter <label>'\n");
1062 }
1063 /**************************************************************************/
1064 void Assembler::SetCatchClass(mdToken catchClass)
1065 {
1066     if(!m_SEHD) return;
1067     m_SEHD->cException = catchClass;
1068
1069 }
1070 /**************************************************************************/
1071 void Assembler::SetHandlerLabels(__in __nullterminated char *szHandlerFrom, __in __nullterminated char *szHandlerTo)
1072 {
1073     if(!m_SEHD) return;
1074     Label *pLbl = m_pCurMethod->FindLabel(szHandlerFrom);
1075     if(pLbl)
1076     {
1077         m_SEHD->sehHandler = pLbl->m_PC;
1078         if(szHandlerTo)
1079         {
1080             pLbl = m_pCurMethod->FindLabel(szHandlerTo);
1081             if(pLbl)
1082             {
1083                 m_SEHD->sehHandlerTo = pLbl->m_PC;
1084                 return;
1085             }
1086         }
1087         else
1088         {
1089             m_SEHD->sehHandlerTo = m_SEHD->sehHandler - 1;
1090             return;
1091         }
1092     }
1093     report->error("Undefined label in 'handler <label> to <label>'\n");
1094 }
1095 /**************************************************************************/
1096 void Assembler::EmitTry(void) //enum CorExceptionFlag kind, char* beginLabel, char* endLabel, char* handleLabel, char* filterOrClass)
1097 {
1098     if(m_SEHD)
1099     {
1100         bool isFilter=(m_SEHD->sehClause == COR_ILEXCEPTION_CLAUSE_FILTER),
1101              isFault=(m_SEHD->sehClause == COR_ILEXCEPTION_CLAUSE_FAULT),
1102              isFinally=(m_SEHD->sehClause == COR_ILEXCEPTION_CLAUSE_FINALLY);
1103
1104         AddException(m_SEHD->tryFrom, m_SEHD->tryTo, m_SEHD->sehHandler, m_SEHD->sehHandlerTo,
1105             m_SEHD->cException, isFilter, isFault, isFinally);
1106     }
1107     else report->error("Attempt to EmitTry with NULL SEH descriptor\n");
1108 }
1109 /**************************************************************************/
1110
1111 void Assembler::AddException(DWORD pcStart, DWORD pcEnd, DWORD pcHandler, DWORD pcHandlerTo, mdTypeRef crException, BOOL isFilter, BOOL isFault, BOOL isFinally)
1112 {
1113     if (m_pCurMethod == NULL)
1114     {
1115         report->error("Exceptions can be declared only when in a method scope\n");
1116         return;
1117     }
1118
1119     if (m_pCurMethod->m_dwNumExceptions >= m_pCurMethod->m_dwMaxNumExceptions)
1120     {
1121         COR_ILMETHOD_SECT_EH_CLAUSE_FAT *ptr =
1122             new COR_ILMETHOD_SECT_EH_CLAUSE_FAT[m_pCurMethod->m_dwMaxNumExceptions+MAX_EXCEPTIONS];
1123         if(ptr == NULL)
1124         {
1125             report->error("Failed to reallocate SEH buffer\n");
1126             return;
1127         }
1128         memcpy(ptr,m_pCurMethod->m_ExceptionList,m_pCurMethod->m_dwNumExceptions*sizeof(COR_ILMETHOD_SECT_EH_CLAUSE_FAT));
1129         delete [] m_pCurMethod->m_ExceptionList;
1130         m_pCurMethod->m_ExceptionList = ptr;
1131         m_pCurMethod->m_dwMaxNumExceptions += MAX_EXCEPTIONS;
1132     }
1133
1134     COR_ILMETHOD_SECT_EH_CLAUSE_FAT *clause = &m_pCurMethod->m_ExceptionList[m_pCurMethod->m_dwNumExceptions];
1135     clause->SetTryOffset(pcStart);
1136     clause->SetTryLength(pcEnd - pcStart);
1137     clause->SetHandlerOffset(pcHandler);
1138     clause->SetHandlerLength(pcHandlerTo - pcHandler);
1139     clause->SetClassToken(crException);
1140
1141     int flags = COR_ILEXCEPTION_CLAUSE_OFFSETLEN;
1142     if (isFilter) {
1143         flags |= COR_ILEXCEPTION_CLAUSE_FILTER;
1144     }
1145     if (isFault) {
1146         flags |= COR_ILEXCEPTION_CLAUSE_FAULT;
1147     }
1148     if (isFinally) {
1149         flags |= COR_ILEXCEPTION_CLAUSE_FINALLY;
1150     }
1151     clause->SetFlags((CorExceptionFlag)flags);
1152
1153     m_pCurMethod->m_dwNumExceptions++;
1154 }
1155
1156 /**************************************************************************/
1157 void Assembler::EmitMaxStack(unsigned val)
1158 {
1159     if(val > 0xFFFF) report->warn(".maxstack parameter exceeds 65535, truncated to %d\n",val&0xFFFF);
1160     if (m_pCurMethod) m_pCurMethod->m_MaxStack = val&0xFFFF;
1161     else  report->error(".maxstack can be used only within a method scope\n");
1162 }
1163
1164 /**************************************************************************/
1165 void Assembler::EmitLocals(BinStr* sig)
1166 {
1167     if(sig)
1168     {
1169         if (m_pCurMethod)
1170         {
1171             ARG_NAME_LIST   *pAN, *pList= getArgNameList();
1172             if(pList)
1173             {
1174                 VarDescr*       pVD;
1175                 for(pAN=pList; pAN; pAN = pAN->pNext)
1176                 {
1177                     if(pAN->dwAttr == 0) pAN->dwAttr = m_pCurMethod->m_Locals.COUNT() +1;
1178                     (pAN->dwAttr)--;
1179                     if((pVD = m_pCurMethod->m_Locals.PEEK(pAN->dwAttr)))
1180                     {
1181                         if(pVD->bInScope)
1182                         {
1183                             report->warn("Local var slot %d is in use\n",pAN->dwAttr);
1184                         }
1185                         if(pVD->pbsSig && ((pVD->pbsSig->length() != pAN->pSig->length()) ||
1186                             (memcmp(pVD->pbsSig->ptr(),pAN->pSig->ptr(),pVD->pbsSig->length()))))
1187                         {
1188                             report->error("Local var slot %d: type conflict\n",pAN->dwAttr);
1189                         }
1190                     }
1191                     else
1192                     { // create new entry:
1193                         for(unsigned n = m_pCurMethod->m_Locals.COUNT(); n <= pAN->dwAttr; n++)
1194                         {
1195                             pVD = new VarDescr;
1196                             if(pVD != NULL) m_pCurMethod->m_Locals.PUSH(pVD);
1197                             else
1198                             {
1199                                 report->error("Out of memory allocating local var descriptor\n");
1200                                 delete sig;
1201                                 return;
1202                             }
1203                         }
1204                     }
1205                     pVD->dwSlot = pAN->dwAttr;
1206                     pVD->pbsSig = pAN->pSig;
1207                     pVD->bInScope = TRUE;
1208                 }
1209                 if(pVD->pbsSig && (pVD->pbsSig->length() == 1))
1210                 {
1211                     if(pVD->pbsSig->ptr()[0] == ELEMENT_TYPE_VOID)
1212                         report->error("Illegal local var type: 'void'\n");
1213                 }
1214                 m_pCurMethod->m_pCurrScope->pLocals =
1215                     m_pCurMethod->catArgNameList(m_pCurMethod->m_pCurrScope->pLocals, pList);
1216             }
1217         }
1218         else    report->error(".locals can be used only within a method scope\n");
1219         delete sig;
1220     }
1221     else report->error("Attempt to EmitLocals with NULL argument\n");
1222 }
1223
1224 /**************************************************************************/
1225 void Assembler::EmitEntryPoint()
1226 {
1227     if (m_pCurMethod)
1228     {
1229         if(!m_fEntryPointPresent)
1230         {
1231             if(IsMdStatic(m_pCurMethod->m_Attr))
1232             {
1233                 m_pCurMethod->m_fEntryPoint = TRUE;
1234                 m_fEntryPointPresent = TRUE;
1235             }
1236             else report->error("Non-static method as entry point\n");
1237         }
1238         else report->error("Multiple .entrypoint declarations\n");
1239     }
1240     else report->error(".entrypoint can be used only within a method scope\n");
1241 }
1242
1243 /**************************************************************************/
1244 void Assembler::EmitZeroInit()
1245 {
1246     if (m_pCurMethod) m_pCurMethod->m_Flags |= CorILMethod_InitLocals;
1247     else report->error(".zeroinit can be used only within a method scope\n");
1248 }
1249
1250 /**************************************************************************/
1251 void Assembler::SetImplAttr(unsigned short attrval)
1252 {
1253     if (m_pCurMethod)
1254     {
1255         if(IsMiNative(attrval)||IsMiOPTIL(attrval)||IsMiUnmanaged(attrval))
1256             report->error("Cannot compile native/unmanaged method\n");
1257         m_pCurMethod->m_wImplAttr = attrval;
1258     }
1259 }
1260
1261 /**************************************************************************/
1262 void Assembler::EmitData(__in_opt void *buffer, unsigned len)
1263 {
1264     if (len != 0)
1265     {
1266         void* ptr;
1267         HRESULT hr = m_pCeeFileGen->GetSectionBlock(m_pCurSection, len, 1, &ptr);
1268         if (FAILED(hr))
1269         {
1270             report->error("Could not extend data section (out of memory?)");
1271             exit(1);
1272         }
1273         
1274         if (buffer != NULL)
1275         {
1276             memcpy(ptr, buffer, len);
1277         }
1278         else
1279         {
1280             memset(ptr, 0, len);
1281         }
1282     }
1283 }
1284
1285 /**************************************************************************/
1286 void Assembler::EmitDD(__in __nullterminated char *str)
1287 {
1288     DWORD       dwAddr = 0;
1289     GlobalLabel *pLabel = FindGlobalLabel(str);
1290
1291     ULONG loc;
1292     HRESULT hr = m_pCeeFileGen->GetSectionDataLen(m_pCurSection, &loc);
1293     _ASSERTE(SUCCEEDED(hr));
1294
1295     DWORD* ptr;
1296     DWORD sizeofptr = (DWORD)((m_dwCeeFileFlags & ICEE_CREATE_FILE_PE32) ? sizeof(DWORD) : sizeof(__int64));
1297     hr = m_pCeeFileGen->GetSectionBlock(m_pCurSection, sizeofptr, 1, (void**) &ptr);
1298     if (FAILED(hr))
1299     {
1300         report->error("Could not extend data section (out of memory?)");
1301         exit(1);
1302     }
1303
1304     if (pLabel != 0) {
1305         dwAddr = pLabel->m_GlobalOffset;
1306         if (pLabel->m_Section != m_pGlobalDataSection) {
1307             report->error("For '&label', label must be in data section");
1308             m_State = STATE_FAIL;
1309             }
1310         }
1311     else
1312         AddDeferredGlobalFixup(str, (BYTE*) ptr);
1313
1314     hr = m_pCeeFileGen->AddSectionReloc(m_pCurSection, loc, m_pGlobalDataSection, srRelocHighLow);
1315     _ASSERTE(SUCCEEDED(hr));
1316     if(m_dwCeeFileFlags & ICEE_CREATE_FILE_STRIP_RELOCS)
1317     {
1318         report->error("Base relocations are emitted, while /STRIPRELOC option has been specified");
1319     }
1320     if(m_dwCeeFileFlags & ICEE_CREATE_FILE_PE32)
1321     {
1322         m_dwComImageFlags &= ~COMIMAGE_FLAGS_ILONLY;
1323         if (m_dwCeeFileFlags & ICEE_CREATE_MACHINE_I386)
1324             COR_SET_32BIT_REQUIRED(m_dwComImageFlags);
1325         *ptr = dwAddr;
1326     }
1327     else
1328     {
1329         m_dwComImageFlags &= ~COMIMAGE_FLAGS_ILONLY;
1330         *((__int64*)ptr) = (__int64)dwAddr;
1331     }
1332 }
1333
1334 /**************************************************************************/
1335 GlobalLabel *Assembler::FindGlobalLabel(LPCUTF8 pszName)
1336 {
1337     GlobalLabel lSearch(pszName,0,NULL), *pL;
1338     pL =  m_lstGlobalLabel.FIND(&lSearch);
1339     lSearch.m_szName = NULL;
1340     return pL;
1341     //return  m_lstGlobalLabel.FIND(pszName);
1342 }
1343
1344 /**************************************************************************/
1345
1346 GlobalFixup *Assembler::AddDeferredGlobalFixup(__in __nullterminated char *pszLabel, BYTE* pReference)
1347 {
1348     GlobalFixup *pNew = new GlobalFixup(pszLabel, (BYTE*) pReference);
1349     if (pNew == NULL)
1350     {
1351         report->error("Failed to allocate global fixup\n");
1352         m_State = STATE_FAIL;
1353     }
1354     else
1355         m_lstGlobalFixup.PUSH(pNew);
1356
1357     return pNew;
1358 }
1359
1360 /**************************************************************************/
1361 void Assembler::AddDeferredILFixup(ILFixupType Kind)
1362 {
1363     _ASSERTE(Kind != ilGlobal);
1364   AddDeferredILFixup(Kind, NULL);
1365 }
1366 /**************************************************************************/
1367
1368 void Assembler::AddDeferredILFixup(ILFixupType Kind,
1369                                    GlobalFixup *GFixup)
1370 {
1371     ILFixup *pNew = new ILFixup(m_CurPC, Kind, GFixup);
1372
1373     _ASSERTE(m_pCurMethod != NULL);
1374     if (pNew == NULL)
1375     {
1376         report->error("Failed to allocate IL fixup\n");
1377         m_State = STATE_FAIL;
1378     }
1379     else
1380         m_pCurMethod->m_lstILFixup.PUSH(pNew);
1381 }
1382
1383 /**************************************************************************/
1384 void Assembler::EmitDataString(BinStr* str)
1385 {
1386     if(str)
1387     {
1388         str->appendInt8(0);
1389         DWORD   DataLen = str->length();
1390         char    *pb = (char*)(str->ptr());
1391         WCHAR   *UnicodeString = (DataLen >= dwUniBuf) ? new WCHAR[DataLen] : &wzUniBuf[0];
1392
1393         if(UnicodeString)
1394         {
1395             WszMultiByteToWideChar(g_uCodePage,0,pb,-1,UnicodeString,DataLen);
1396             EmitData(UnicodeString,DataLen*sizeof(WCHAR));
1397             if(DataLen >= dwUniBuf) delete [] UnicodeString;
1398         }
1399         else report->error("\nOut of memory!\n");
1400         delete str;
1401     }
1402 }
1403
1404
1405
1406 /**************************************************************************/
1407 unsigned Assembler::OpcodeLen(Instr* instr)
1408 {
1409     return (m_fStdMapping ? OpcodeInfo[instr->opcode].Len : 3);
1410 }
1411 /**************************************************************************/
1412 void Assembler::EmitOpcode(Instr* instr)
1413 {
1414     if(m_fGeneratePDB &&
1415        ((instr->linenum != m_ulLastDebugLine)
1416         ||(instr->column != m_ulLastDebugColumn)
1417         ||(instr->linenum_end != m_ulLastDebugLineEnd)
1418         ||(instr->column_end != m_ulLastDebugColumnEnd)))
1419     {
1420         if(m_pCurMethod)
1421         {
1422             LinePC *pLPC = new LinePC;
1423             if(pLPC)
1424             {
1425                 pLPC->Line = instr->linenum;
1426                 pLPC->Column = instr->column;
1427                 pLPC->LineEnd = instr->linenum_end;
1428                 pLPC->ColumnEnd = instr->column_end;
1429                 pLPC->PC = m_CurPC;
1430                 pLPC->pWriter = instr->pWriter;
1431                 m_pCurMethod->m_LinePCList.PUSH(pLPC);
1432             }
1433             else report->error("\nOut of memory!\n");
1434         }
1435         m_ulLastDebugLine = instr->linenum;
1436         m_ulLastDebugColumn = instr->column;
1437         m_ulLastDebugLineEnd = instr->linenum_end;
1438         m_ulLastDebugColumnEnd = instr->column_end;
1439     }
1440     if(instr->opcode == CEE_ENDFILTER)
1441     {
1442         if(m_pCurMethod)
1443         {
1444             if(m_pCurMethod->m_dwNumEndfilters >= m_pCurMethod->m_dwMaxNumEndfilters)
1445             {
1446                 DWORD *pdw = new DWORD[m_pCurMethod->m_dwMaxNumEndfilters+MAX_EXCEPTIONS];
1447                 if(pdw == NULL)
1448                 {
1449                     report->error("Failed to reallocate auxiliary SEH buffer\n");
1450                     instr->opcode = -1;
1451                     return;
1452                 }
1453                 memcpy(pdw,m_pCurMethod->m_EndfilterOffsetList,m_pCurMethod->m_dwNumEndfilters*sizeof(DWORD));
1454                 delete m_pCurMethod->m_EndfilterOffsetList;
1455                 m_pCurMethod->m_EndfilterOffsetList = pdw;
1456                 m_pCurMethod->m_dwMaxNumEndfilters += MAX_EXCEPTIONS;
1457             }
1458             m_pCurMethod->m_EndfilterOffsetList[m_pCurMethod->m_dwNumEndfilters++] = m_CurPC+2;
1459         }
1460     }
1461     if (m_fStdMapping)
1462     {
1463         if (OpcodeInfo[instr->opcode].Len == 2)
1464             EmitByte(OpcodeInfo[instr->opcode].Std1);
1465         EmitByte(OpcodeInfo[instr->opcode].Std2);
1466     }
1467     else
1468     {
1469         unsigned short us = (unsigned short)instr->opcode;
1470         EmitByte(REFPRE);
1471         EmitBytes((BYTE *)&us,2);
1472     }
1473     instr->opcode = -1;
1474 }
1475
1476 /**************************************************************************/
1477 //void Assembler::OptimizeInstr(Instr* instr, int var)
1478 //{
1479
1480 //}
1481 /**************************************************************************/
1482 unsigned Assembler::ShortOf(unsigned opcode)
1483 {
1484     unsigned retcode;
1485     switch(opcode)
1486     {
1487         case CEE_LDARG:     retcode=CEE_LDARG_S;    break;
1488         case CEE_LDARGA:    retcode=CEE_LDARGA_S;   break;
1489         case CEE_STARG:     retcode=CEE_STARG_S;    break;
1490
1491         case CEE_LDLOC:     retcode=CEE_LDLOC_S;    break;
1492         case CEE_LDLOCA:    retcode=CEE_LDLOCA_S;   break;
1493         case CEE_STLOC:     retcode=CEE_STLOC_S;    break;
1494
1495         case CEE_BR:        retcode=CEE_BR_S;       break;
1496         case CEE_BRFALSE:   retcode=CEE_BRFALSE_S;  break;
1497         case CEE_BRTRUE:    retcode=CEE_BRTRUE_S;   break;
1498         case CEE_BEQ:       retcode=CEE_BEQ_S;      break;
1499         case CEE_BGE:       retcode=CEE_BGE_S;      break;
1500         case CEE_BGT:       retcode=CEE_BGT_S;      break;
1501         case CEE_BLE:       retcode=CEE_BLE_S;      break;
1502         case CEE_BLT:       retcode=CEE_BLT_S;      break;
1503         case CEE_BNE_UN:    retcode=CEE_BNE_UN_S;   break;
1504         case CEE_BGE_UN:    retcode=CEE_BGE_UN_S;   break;
1505         case CEE_BGT_UN:    retcode=CEE_BGT_UN_S;   break;
1506         case CEE_BLE_UN:    retcode=CEE_BLE_UN_S;   break;
1507         case CEE_BLT_UN:    retcode=CEE_BLT_UN_S;   break;
1508         case CEE_LEAVE:     retcode=CEE_LEAVE_S;    break;
1509
1510         case CEE_LDC_I4:    retcode=CEE_LDC_I4_S;   break;
1511         case CEE_LDC_R8:    retcode=CEE_LDC_R4;     break;
1512
1513
1514         default: retcode = opcode;  break;
1515     }
1516     return retcode;
1517 }
1518
1519 /**************************************************************************/
1520 void Assembler::EmitInstrVar(Instr* instr, int var)
1521 {
1522     unsigned opc = instr->opcode;
1523     if(m_fOptimize)
1524     {
1525         if(var < 4)
1526         {
1527             switch(opc)
1528             {
1529                 case CEE_LDARG:
1530                 case CEE_LDARG_S: opc = CEE_LDARG_0 + var; break;
1531
1532                 case CEE_LDLOC:
1533                 case CEE_LDLOC_S: opc = CEE_LDLOC_0 + var; break;
1534
1535                 case CEE_STLOC:
1536                 case CEE_STLOC_S: opc = CEE_STLOC_0 + var; break;
1537
1538                 default: break;
1539             }
1540             if(opc != (unsigned) instr->opcode)
1541             {
1542                 instr->opcode = opc;
1543                 EmitOpcode(instr);
1544                 return;
1545             }
1546         }
1547         if(var <= 0xFF)
1548         {
1549             opc = instr->opcode = ShortOf(opc);
1550         }
1551     }
1552     EmitOpcode(instr);
1553     if (isShort(opc))
1554     {
1555         EmitByte(var);
1556     }
1557     else
1558     {
1559         short sh = (short)var;
1560         EmitBytes((BYTE *)&sh,2);
1561     }
1562 }
1563
1564 /**************************************************************************/
1565 void Assembler::EmitInstrVarByName(Instr* instr, __in __nullterminated char* label)
1566 {
1567     int idx = -1, nArgVarFlag=0;
1568     switch(instr->opcode)
1569     {
1570         case CEE_LDARGA:
1571         case CEE_LDARGA_S:
1572         case CEE_LDARG:
1573         case CEE_LDARG_S:
1574         case CEE_STARG:
1575         case CEE_STARG_S:
1576             nArgVarFlag++;
1577         case CEE_LDLOCA:
1578         case CEE_LDLOCA_S:
1579         case CEE_LDLOC:
1580         case CEE_LDLOC_S:
1581         case CEE_STLOC:
1582         case CEE_STLOC_S:
1583
1584             if(m_pCurMethod)
1585             {
1586                 DWORD L = (DWORD)strlen(label);
1587                 if(nArgVarFlag == 1)
1588                 {
1589                     idx = m_pCurMethod->findArgNum(m_pCurMethod->m_firstArgName,label,L);
1590                 }
1591                 else
1592                 {
1593                     for(Scope* pSC = m_pCurMethod->m_pCurrScope; pSC; pSC=pSC->pSuperScope)
1594                     {
1595                         idx = m_pCurMethod->findLocSlot(pSC->pLocals,label,L);
1596                         if(idx >= 0) break;
1597                     }
1598                 }
1599                 if(idx >= 0) EmitInstrVar(instr,
1600                     ((nArgVarFlag==0)||(m_pCurMethod->m_Attr & mdStatic))? idx : idx+1);
1601                 else    report->error("Undeclared identifier %s\n",label);
1602             }
1603             else
1604                 report->error("Instructions can be used only when in a method scope\n");
1605             break;
1606         default:
1607             report->error("Named argument illegal for this instruction\n");
1608     }
1609     instr->opcode = -1; // in case we got here with error
1610 }
1611
1612 /**************************************************************************/
1613 void Assembler::EmitInstrI(Instr* instr, int val)
1614 {
1615     int opc = instr->opcode;
1616     if(m_fOptimize)
1617     {
1618         if((val >= -1)&&(val <= 8))
1619         {
1620             switch(opc)
1621             {
1622                 case CEE_LDC_I4:
1623                 case CEE_LDC_I4_S: opc = CEE_LDC_I4_M1 + (val+1); break;
1624
1625                 default: break;
1626             }
1627             if(opc != instr->opcode)
1628             {
1629                 instr->opcode = opc;
1630                 EmitOpcode(instr);
1631                 return;
1632             }
1633         }
1634         if((-128 <= val)&&(val <= 127))
1635         {
1636             opc = instr->opcode = ShortOf(opc);
1637         }
1638     }
1639     EmitOpcode(instr);
1640     if (isShort(opc))
1641     {
1642         EmitByte(val);
1643     }
1644     else
1645     {
1646         int i = val;
1647         EmitBytes((BYTE *)&i,sizeof(int));
1648     }
1649 }
1650
1651 /**************************************************************************/
1652 void Assembler::EmitInstrI8(Instr* instr, __int64* val)
1653 {
1654     EmitOpcode(instr);
1655     EmitBytes((BYTE *)val, sizeof(__int64));
1656     delete val;
1657 }
1658
1659 /**************************************************************************/
1660 void Assembler::EmitInstrR(Instr* instr, double* pval)
1661 {
1662     unsigned opc = instr->opcode;
1663     EmitOpcode(instr);
1664     if (isShort(opc))
1665     {
1666         float val = (float)*pval;
1667         EmitBytes((BYTE *)&val, sizeof(float));
1668     }
1669     else
1670         EmitBytes((BYTE *)pval, sizeof(double));
1671 }
1672
1673 /**************************************************************************/
1674 void Assembler::EmitInstrBrTarget(Instr* instr, __in __nullterminated char* label)
1675 {
1676     Label * pLabel = m_pCurMethod->FindLabel(label);
1677     int offset=0;
1678     if (pLabel == NULL) // branching forward -- no optimization
1679     {
1680         int pcrelsize = 1+(isShort(instr->opcode) ? 1 : 4); //size of the instruction plus argument
1681         AddDeferredFixup(label, m_pCurOutputPos+1,
1682                                        (m_CurPC + pcrelsize), pcrelsize-1);
1683     }
1684     else
1685     {
1686         offset = pLabel->m_PC - m_CurPC;
1687         if(m_fOptimize)
1688         {
1689             if((-128 <= offset-5)&&(offset-2 <= 127)) //need to take into account the argument size (worst cases)
1690             {
1691                 instr->opcode = ShortOf(instr->opcode);
1692             }
1693         }
1694         if(isShort(instr->opcode))
1695         {
1696             offset -= 2;
1697             if((-128 > offset)||(offset > 127))
1698                 report->error("Offset too large for short branching instruction, truncated\n");
1699         }
1700         else
1701             offset -= 5;
1702         delete [] label;
1703     }
1704     int opc = instr->opcode;
1705     EmitOpcode(instr);
1706     if(isShort(opc))  EmitByte(offset);
1707     else              EmitBytes((BYTE *)&offset,4);
1708 }
1709 /**************************************************************************/
1710 void Assembler::AddDeferredFixup(__in __nullterminated char *pszLabel, BYTE *pBytes, DWORD RelativeToPC, BYTE FixupSize)
1711 {
1712     Fixup *pNew = new Fixup(pszLabel, pBytes, RelativeToPC, FixupSize);
1713
1714     if (pNew == NULL)
1715     {
1716         report->error("Failed to allocate deferred fixup\n");
1717         m_State = STATE_FAIL;
1718     }
1719     else
1720         m_pCurMethod->m_lstFixup.PUSH(pNew);
1721 }
1722 /**************************************************************************/
1723 void Assembler::EmitInstrBrOffset(Instr* instr, int offset)
1724 {
1725     unsigned opc=instr->opcode;
1726     if(m_fOptimize)
1727     {
1728         if((-128 >= offset)&&(offset <= 127))
1729         {
1730             opc = instr->opcode = ShortOf(opc);
1731         }
1732     }
1733     EmitOpcode(instr);
1734     if(isShort(opc))    EmitByte(offset);
1735     else
1736     {
1737         int i = offset;
1738         EmitBytes((BYTE *)&i,4);
1739     }
1740 }
1741
1742 /**************************************************************************/
1743 mdToken Assembler::MakeMemberRef(mdToken cr, __in __nullterminated char* pszMemberName, BinStr* sig)
1744 {
1745     DWORD           cSig = sig->length();
1746     COR_SIGNATURE*  mySig = (COR_SIGNATURE *)(sig->ptr());
1747     mdToken         mr = mdMemberRefNil;
1748     Class*          pClass = NULL;
1749     if(cr == 0x00000001) cr = mdTokenNil; // Module -> nil for globals
1750     if(TypeFromToken(cr) == mdtTypeDef) pClass = m_lstClass.PEEK(RidFromToken(cr)-1);
1751     if((TypeFromToken(cr) == mdtTypeDef)||(cr == mdTokenNil))
1752     {
1753         MemberRefDescriptor* pMRD = new MemberRefDescriptor;
1754         if(pMRD)
1755         {
1756             pMRD->m_tdClass = cr;
1757             pMRD->m_pClass = pClass;
1758             pMRD->m_szName = pszMemberName;
1759             pMRD->m_dwName = (DWORD)strlen(pszMemberName);
1760             pMRD->m_pSigBinStr = sig;
1761             pMRD->m_tkResolved = 0;
1762             if(*(sig->ptr())== IMAGE_CEE_CS_CALLCONV_FIELD)
1763             {
1764                 m_LocalFieldRefDList.PUSH(pMRD);
1765                 mr = 0x98000000 | m_LocalFieldRefDList.COUNT();
1766             }
1767             else
1768             {
1769                 m_LocalMethodRefDList.PUSH(pMRD);
1770                 mr = 0x99000000 | m_LocalMethodRefDList.COUNT();
1771             }
1772         }
1773         else
1774         {
1775             report->error("Failed to allocate MemberRef Descriptor\n");
1776             return 0;
1777         }
1778     }
1779     else
1780     {
1781         WszMultiByteToWideChar(g_uCodePage,0,pszMemberName,-1,wzUniBuf,dwUniBuf);
1782
1783         if(cr == mdTokenNil) cr = mdTypeRefNil;
1784         if(TypeFromToken(cr) == mdtAssemblyRef)
1785         {
1786             report->error("Cross-assembly global references are not supported ('%s')\n", pszMemberName);
1787             mr = 0;
1788         }
1789         else
1790         {
1791             HRESULT hr = m_pEmitter->DefineMemberRef(cr, wzUniBuf, mySig, cSig, &mr);
1792             if(FAILED(hr))
1793             {
1794                 report->error("Unable to define member reference '%s'\n", pszMemberName);
1795                 mr = 0;
1796             }
1797         }
1798         //if(m_fOBJ)    m_pCurMethod->m_TRDList.PUSH(new TokenRelocDescr(m_CurPC,mr));
1799         delete pszMemberName;
1800         delete sig;
1801     }
1802     return mr;
1803 }
1804 /**************************************************************************/
1805 void Assembler::SetMemberRefFixup(mdToken tk, unsigned opcode_len)
1806 {
1807     if(opcode_len)
1808     {
1809         switch(TypeFromToken(tk))
1810         {
1811             case 0x98000000:
1812             case 0x99000000:
1813             case 0x9A000000:
1814                 if(m_pCurMethod != NULL)
1815                     m_pCurMethod->m_LocalMemberRefFixupList.PUSH(
1816                             new LocalMemberRefFixup(tk,(size_t)(m_CurPC + opcode_len)));
1817                 break;
1818         }
1819     }
1820 }
1821
1822 /**************************************************************************/
1823 mdToken Assembler::MakeMethodSpec(mdToken tkParent, BinStr* sig)
1824 {
1825     DWORD           cSig = sig->length();
1826     COR_SIGNATURE*  mySig = (COR_SIGNATURE *)(sig->ptr());
1827     mdMethodSpec mi = mdMethodSpecNil;
1828     if(TypeFromToken(tkParent) == 0x99000000) // Local MemberRef: postpone until resolved
1829     {
1830         MemberRefDescriptor* pMRD = new MemberRefDescriptor;
1831         if(pMRD)
1832         {
1833             memset(pMRD,0,sizeof(MemberRefDescriptor));
1834             pMRD->m_tdClass = tkParent;
1835             pMRD->m_pSigBinStr = sig;
1836             m_MethodSpecList.PUSH(pMRD);
1837             mi = 0x9A000000 | m_MethodSpecList.COUNT();
1838         }
1839         else
1840         {
1841             report->error("Failed to allocate MemberRef Descriptor\n");
1842             return 0;
1843         }
1844     }
1845     else
1846     {
1847         HRESULT hr = m_pEmitter->DefineMethodSpec(tkParent, mySig, cSig, &mi);
1848         if(FAILED(hr))
1849         {
1850             report->error("Unable to define method instantiation");
1851             return 0;
1852         }
1853     }
1854     return mi;
1855 }
1856
1857 /**************************************************************************/
1858 void Assembler::EndEvent(void)
1859 {
1860     Class* pClass = (m_pCurClass ? m_pCurClass : m_pModuleClass);
1861     if(m_pCurEvent->m_tkAddOn == 0)
1862         report->error("Event %s of class %s has no Add method. Event not emitted.",
1863                       m_pCurEvent->m_szName,pClass->m_szFQN);
1864     else if(m_pCurEvent->m_tkRemoveOn == 0)
1865         report->error("Event %s of class %s has no Remove method. Event not emitted.",
1866                       m_pCurEvent->m_szName,pClass->m_szFQN);
1867     else
1868     {
1869         pClass->m_EventDList.PUSH(m_pCurEvent);
1870         pClass->m_fNewMembers = TRUE;
1871     }
1872     m_pCurEvent = NULL;
1873     m_tkCurrentCVOwner = 0;
1874     m_pCustomDescrList = m_CustomDescrListStack.POP();
1875 }
1876
1877 void Assembler::ResetEvent(__inout_z __inout char* szName, mdToken typeSpec, DWORD dwAttr)
1878 {
1879     if(strlen(szName) >= MAX_CLASSNAME_LENGTH)
1880     {
1881         char c = szName[MAX_CLASSNAME_LENGTH-1];
1882         szName[MAX_CLASSNAME_LENGTH-1] = 0;
1883         report->error("Event '%s...' -- name too long (%d characters).\n",szName,strlen(szName));
1884         szName[MAX_CLASSNAME_LENGTH-1] = c;
1885     }
1886     if((m_pCurEvent = new EventDescriptor))
1887     {
1888         memset(m_pCurEvent,0,sizeof(EventDescriptor));
1889         m_pCurEvent->m_tdClass = m_pCurClass->m_cl;
1890         m_pCurEvent->m_szName = szName;
1891         m_pCurEvent->m_dwAttr = dwAttr;
1892         m_pCurEvent->m_tkEventType = typeSpec;
1893         m_pCurEvent->m_fNew = TRUE;
1894         m_tkCurrentCVOwner = 0;
1895         m_CustomDescrListStack.PUSH(m_pCustomDescrList);
1896         m_pCustomDescrList = &(m_pCurEvent->m_CustomDescrList);
1897     }
1898     else report->error("Failed to allocate Event Descriptor\n");
1899 }
1900
1901 void Assembler::SetEventMethod(int MethodCode, mdToken tk)
1902 {
1903     switch(MethodCode)
1904     {
1905         case 0:
1906             m_pCurEvent->m_tkAddOn = tk;
1907             break;
1908         case 1:
1909             m_pCurEvent->m_tkRemoveOn = tk;
1910             break;
1911         case 2:
1912             m_pCurEvent->m_tkFire = tk;
1913             break;
1914         case 3:
1915             m_pCurEvent->m_tklOthers.PUSH((mdToken*)(UINT_PTR)tk);
1916             break;
1917     }
1918 }
1919 /**************************************************************************/
1920
1921 void Assembler::EndProp(void)
1922 {
1923     Class* pClass = (m_pCurClass ? m_pCurClass : m_pModuleClass);
1924     pClass->m_PropDList.PUSH(m_pCurProp);
1925     pClass->m_fNewMembers = TRUE;
1926     m_pCurProp = NULL;
1927     m_tkCurrentCVOwner = 0;
1928     m_pCustomDescrList = m_CustomDescrListStack.POP();
1929 }
1930
1931 void Assembler::ResetProp(__inout_z __inout char * szName, BinStr* bsType, DWORD dwAttr, BinStr* pValue)
1932 {
1933     DWORD           cSig = bsType->length();
1934     COR_SIGNATURE*  mySig = (COR_SIGNATURE *)(bsType->ptr());
1935
1936     if(strlen(szName) >= MAX_CLASSNAME_LENGTH)
1937     {
1938         char c = szName[MAX_CLASSNAME_LENGTH-1];
1939         szName[MAX_CLASSNAME_LENGTH-1] = 0;
1940         report->error("Property '%s...' -- name too long (%d characters).\n",szName,strlen(szName));
1941         szName[MAX_CLASSNAME_LENGTH-1] = c;
1942     }
1943     m_pCurProp = new PropDescriptor;
1944     if(m_pCurProp == NULL)
1945     {
1946         report->error("Failed to allocate Property Descriptor\n");
1947         return;
1948     }
1949     memset(m_pCurProp,0,sizeof(PropDescriptor));
1950     m_pCurProp->m_tdClass = m_pCurClass->m_cl;
1951     m_pCurProp->m_szName = szName;
1952     m_pCurProp->m_dwAttr = dwAttr;
1953     m_pCurProp->m_fNew = TRUE;
1954
1955     m_pCurProp->m_pSig = new COR_SIGNATURE[cSig];
1956     if(m_pCurProp->m_pSig == NULL)
1957     {
1958         report->error("\nOut of memory!\n");
1959         return;
1960     }
1961     memcpy(m_pCurProp->m_pSig,mySig,cSig);
1962     m_pCurProp->m_dwCSig = cSig;
1963
1964     if(pValue && pValue->length())
1965     {
1966         BYTE* pch = pValue->ptr();
1967         m_pCurProp->m_dwCPlusTypeFlag = (DWORD)(*pch);
1968         m_pCurProp->m_cbValue = pValue->length() - 1;
1969         m_pCurProp->m_pValue = (PVOID)(pch+1);
1970         if(m_pCurProp->m_dwCPlusTypeFlag == ELEMENT_TYPE_STRING) m_pCurProp->m_cbValue /= sizeof(WCHAR);
1971         m_pCurProp->m_dwAttr |= prHasDefault;
1972     }
1973     else
1974     {
1975         m_pCurProp->m_dwCPlusTypeFlag = ELEMENT_TYPE_VOID;
1976         m_pCurProp->m_pValue = NULL;
1977         m_pCurProp->m_cbValue = 0;
1978     }
1979     m_tkCurrentCVOwner = 0;
1980     m_CustomDescrListStack.PUSH(m_pCustomDescrList);
1981     m_pCustomDescrList = &(m_pCurProp->m_CustomDescrList);
1982 }
1983
1984 void Assembler::SetPropMethod(int MethodCode, mdToken tk)
1985 {
1986     switch(MethodCode)
1987     {
1988         case 0:
1989             m_pCurProp->m_tkSet = tk;
1990             break;
1991         case 1:
1992             m_pCurProp->m_tkGet = tk;
1993             break;
1994         case 2:
1995             m_pCurProp->m_tklOthers.PUSH((mdToken*)(UINT_PTR)tk);
1996             break;
1997     }
1998 }
1999
2000 /**************************************************************************/
2001 void Assembler::EmitInstrStringLiteral(Instr* instr, BinStr* literal, BOOL ConvertToUnicode, BOOL Swap /*=FALSE*/)
2002 {
2003     DWORD   DataLen = literal->length(),L;
2004     unsigned __int8 *pb = literal->ptr();
2005     HRESULT hr = S_OK;
2006     mdToken tk;
2007     WCHAR   *UnicodeString;
2008     if(DataLen == 0)
2009     {
2010         //report->warn("Zero length string emitted\n");
2011         ConvertToUnicode = FALSE;
2012     }
2013     if(ConvertToUnicode)
2014     {
2015         UnicodeString = (DataLen >= dwUniBuf) ? new WCHAR[DataLen+1] : &wzUniBuf[0];
2016         literal->appendInt8(0);
2017         pb = literal->ptr();
2018         // convert string to Unicode
2019         L = UnicodeString ? WszMultiByteToWideChar(g_uCodePage,0,(char*)pb,-1,UnicodeString,DataLen+1) : 0;
2020         if(L == 0)
2021         {
2022             const char* sz=NULL;
2023             DWORD dw;
2024             switch(dw=GetLastError())
2025             {
2026                 case ERROR_INSUFFICIENT_BUFFER: sz = "ERROR_INSUFFICIENT_BUFFER"; break;
2027                 case ERROR_INVALID_FLAGS:       sz = "ERROR_INVALID_FLAGS"; break;
2028                 case ERROR_INVALID_PARAMETER:   sz = "ERROR_INVALID_PARAMETER"; break;
2029                 case ERROR_NO_UNICODE_TRANSLATION: sz = "ERROR_NO_UNICODE_TRANSLATION"; break;
2030             }
2031             if(sz)  report->error("Failed to convert string '%s' to Unicode: %s\n",(char*)pb,sz);
2032             else    report->error("Failed to convert string '%s' to Unicode: error 0x%08X\n",(char*)pb,dw);
2033             delete instr;
2034             goto OuttaHere;
2035         }
2036         L--;
2037     }
2038     else
2039     {
2040         if(DataLen & 1)
2041         {
2042             literal->appendInt8(0);
2043             pb = literal->ptr();
2044             DataLen++;
2045         }
2046         UnicodeString = (WCHAR*)pb;
2047         L = DataLen/sizeof(WCHAR);
2048
2049 #if BIGENDIAN
2050         if (Swap)
2051             SwapStringLength(UnicodeString, L);
2052 #endif
2053     }
2054     // Add the string data to the metadata, which will fold dupes.
2055     hr = m_pEmitter->DefineUserString(
2056         UnicodeString,
2057         L,
2058         &tk
2059     );
2060     if (FAILED(hr))
2061     {
2062         report->error("Failed to add user string using DefineUserString, hr=0x%08x, data: '%S'\n",
2063                hr, UnicodeString);
2064         delete instr;
2065     }
2066     else
2067     {
2068         EmitOpcode(instr);
2069         if(m_fOBJ)  m_pCurMethod->m_TRDList.PUSH(new TokenRelocDescr(m_CurPC,tk));
2070
2071         EmitBytes((BYTE *)&tk,sizeof(mdToken));
2072     }
2073 OuttaHere:
2074     delete literal;
2075     if(((void*)UnicodeString != (void*)pb)&&(DataLen >= dwUniBuf)) delete [] UnicodeString;
2076     instr->opcode = -1; // in case we got here with error
2077 }
2078
2079 /**************************************************************************/
2080 void Assembler::EmitInstrSig(Instr* instr, BinStr* sig)
2081 {
2082     mdSignature MetadataToken;
2083     DWORD       cSig = sig->length();
2084     COR_SIGNATURE* mySig = (COR_SIGNATURE *)(sig->ptr());
2085
2086     if (FAILED(m_pEmitter->GetTokenFromSig(mySig, cSig, &MetadataToken)))
2087     {
2088         report->error("Unable to convert signature to metadata token.\n");
2089         delete instr;
2090     }
2091     else
2092     {
2093         EmitOpcode(instr);
2094         if(m_fOBJ)  m_pCurMethod->m_TRDList.PUSH(new TokenRelocDescr(m_CurPC,MetadataToken));
2095         EmitBytes((BYTE *)&MetadataToken, sizeof(mdSignature));
2096     }
2097     delete sig;
2098     instr->opcode = -1; // in case we got here with error
2099 }
2100
2101 /**************************************************************************/
2102 void Assembler::EmitInstrSwitch(Instr* instr, Labels* targets)
2103 {
2104     Labels  *pLbls;
2105     int     NumLabels;
2106     Label   *pLabel;
2107     UINT    offset;
2108
2109     EmitOpcode(instr);
2110
2111     // count # labels
2112     for(pLbls = targets, NumLabels = 0; pLbls; pLbls = pLbls->Next, NumLabels++);
2113
2114     EmitBytes((BYTE *)&NumLabels,sizeof(int));
2115     DWORD PC_nextInstr = m_CurPC + 4*NumLabels;
2116     for(pLbls = targets; pLbls; pLbls = pLbls->Next)
2117     {
2118         if(pLbls->isLabel)
2119         {
2120             if((pLabel = m_pCurMethod->FindLabel(pLbls->Label)))
2121             {
2122                 offset = pLabel->m_PC - PC_nextInstr;
2123                 if (m_fDisplayTraceOutput) report->msg("%d\n", offset);
2124             }
2125             else
2126             {
2127                 // defer until we find the label
2128                 AddDeferredFixup(pLbls->Label, m_pCurOutputPos, PC_nextInstr, 4 /* pcrelsize */ );
2129                 offset = 0;
2130                 pLbls->Label = NULL;
2131                 if (m_fDisplayTraceOutput) report->msg("forward label %s\n", pLbls->Label);
2132             }
2133         }
2134         else
2135         {
2136             offset = (UINT)(UINT_PTR)pLbls->Label;
2137             if (m_fDisplayTraceOutput) report->msg("%d\n", offset);
2138         }
2139         EmitBytes((BYTE *)&offset, sizeof(UINT));
2140     }
2141     delete targets;
2142 }
2143
2144 /**************************************************************************/
2145 void Assembler::EmitLabel(__in __nullterminated char* label)
2146 {
2147     _ASSERTE(m_pCurMethod);
2148     AddLabel(m_CurPC, label);
2149 }
2150 /**************************************************************************/
2151 void Assembler::EmitDataLabel(__in __nullterminated char* label)
2152 {
2153     AddGlobalLabel(label, m_pCurSection);
2154 }
2155
2156 /**************************************************************************/
2157 void Assembler::EmitBytes(BYTE *p, unsigned len)
2158 {
2159     if(m_pCurOutputPos + len >= m_pEndOutputPos)
2160     {
2161         size_t buflen = m_pEndOutputPos - m_pOutputBuffer;
2162         size_t newlen = buflen+(len/OUTPUT_BUFFER_INCREMENT + 1)*OUTPUT_BUFFER_INCREMENT;
2163         BYTE *pb = new BYTE[newlen];
2164         if(pb == NULL)
2165         {
2166             report->error("Failed to extend output buffer from %d to %d bytes. Aborting\n",
2167                 buflen, newlen);
2168             exit(1);
2169         }
2170         size_t delta = pb - m_pOutputBuffer;
2171         int i;
2172         Fixup* pSearch;
2173         GlobalFixup *pGSearch;
2174         for (i=0; (pSearch = m_pCurMethod->m_lstFixup.PEEK(i)); i++) pSearch->m_pBytes += delta;
2175         for (i=0; (pGSearch = m_lstGlobalFixup.PEEK(i)); i++) //need to move only those pointing to output buffer
2176         {
2177             if((pGSearch->m_pReference >= m_pOutputBuffer)&&(pGSearch->m_pReference <= m_pEndOutputPos))
2178                 pGSearch->m_pReference += delta;
2179         }
2180
2181
2182         memcpy(pb,m_pOutputBuffer,m_CurPC);
2183         delete m_pOutputBuffer;
2184         m_pOutputBuffer = pb;
2185         m_pCurOutputPos = &m_pOutputBuffer[m_CurPC];
2186         m_pEndOutputPos = &m_pOutputBuffer[newlen];
2187
2188     }
2189
2190     switch (len)
2191     {
2192     case 1:
2193         *m_pCurOutputPos = *p;
2194         break;
2195     case 2:
2196         SET_UNALIGNED_VAL16(m_pCurOutputPos, GET_UNALIGNED_16(p));
2197         break;
2198     case 4:
2199         SET_UNALIGNED_VAL32(m_pCurOutputPos, GET_UNALIGNED_32(p));
2200         break;
2201     case 8:
2202         SET_UNALIGNED_VAL64(m_pCurOutputPos, GET_UNALIGNED_64(p));
2203         break;
2204     default:
2205         _ASSERTE(!"NYI");
2206         break;
2207     }
2208
2209     m_pCurOutputPos += len;
2210     m_CurPC += len;
2211 }
2212 /**************************************************************************/
2213 BinStr* Assembler::EncodeSecAttr(__in __nullterminated char* szReflName, BinStr* pbsSecAttrBlob, unsigned nProps)
2214 {
2215     unsigned cnt;
2216 #if (0)
2217     // Emit MemberRef for .ctor
2218     mdToken tkMscorlib = m_fIsMscorlib ? 1 : GetAsmRef("mscorlib");
2219     char buffer[64];
2220     BinStr  *pbsSig = new BinStr();
2221
2222     strcpy(buffer,"System.Security.Permissions.SecurityAction");
2223     mdToken tkSecAction = ResolveClassRef(tkMscorlib,buffer, NULL);
2224
2225     pbsSig->appendInt8(IMAGE_CEE_CS_CALLCONV_HASTHIS);
2226     pbsSig->appendInt8(1); //corEmitInt(pbsSig,1);
2227     pbsSig->appendInt8(ELEMENT_TYPE_VOID);
2228     pbsSig->appendInt8(ELEMENT_TYPE_VALUETYPE);
2229     cnt = CorSigCompressToken(tkSecAction, pbsSig->getBuff(5));
2230     pbsSig->remove(5 - cnt);
2231     
2232     char* szName = new char[16];
2233     strcpy(szName,".ctor");
2234     MakeMemberRef(tkSecAttr,szName,pbsSig);
2235 #endif
2236
2237     // build the blob As BinStr
2238     unsigned L = (unsigned) strlen(szReflName);
2239     BYTE* pb = NULL;
2240     BinStr* pbsRet = new BinStr();
2241     // encode the Reflection name length
2242     cnt = CorSigCompressData(L, pbsRet->getBuff(5));
2243     pbsRet->remove(5 - cnt);
2244     //put the name in
2245     if((pb = pbsRet->getBuff(L)) != NULL)
2246         memcpy(pb,szReflName,L);
2247     // find out the size of compressed nProps
2248     cnt = CorSigCompressData(nProps, pbsRet->getBuff(5)); 
2249     pbsRet->remove(5);
2250     // encode blob size
2251     unsigned nSize = cnt + pbsSecAttrBlob->length();
2252     cnt = CorSigCompressData(nSize, pbsRet->getBuff(5));  
2253     pbsRet->remove(5 - cnt);
2254     // actually encode nProps
2255     cnt = CorSigCompressData(nProps, pbsRet->getBuff(5));  
2256     pbsRet->remove(5 - cnt);
2257     // append the props/values blob
2258     pbsRet->append(pbsSecAttrBlob);
2259     delete pbsSecAttrBlob;
2260     return pbsRet;
2261 }
2262 /**************************************************************************/
2263 void Assembler::EmitSecurityInfo(mdToken            token,
2264                                  PermissionDecl*    pPermissions,
2265                                  PermissionSetDecl* pPermissionSets)
2266 {
2267     PermissionDecl     *pPerm, *pPermNext;
2268     PermissionSetDecl  *pPset, *pPsetNext;
2269     unsigned            uCount = 0;
2270     COR_SECATTR        *pAttrs;
2271     unsigned            i;
2272     unsigned            uLength;
2273     mdTypeRef           tkTypeRef;
2274     BinStr             *pSig;
2275     char               *szMemberName;
2276     DWORD               dwErrorIndex = 0;
2277
2278     if (pPermissions) {
2279
2280         for (pPerm = pPermissions; pPerm; pPerm = pPerm->m_Next)
2281             uCount++;
2282
2283         _ASSERTE(uCount > 0);
2284         // uCount is expected to be positive all the time. The if statement is here to please prefast.
2285         if (uCount > 0)
2286         {
2287             if((pAttrs = new COR_SECATTR[uCount])==NULL)
2288             {
2289                 report->error("\nOut of memory!\n");
2290                 return;
2291             }
2292
2293             mdToken tkMscorlib = m_fIsMscorlib ? 1 : GetAsmRef("mscorlib");
2294             tkTypeRef = ResolveClassRef(tkMscorlib,"System.Security.Permissions.SecurityAction", NULL);
2295             for (pPerm = pPermissions, i = 0; pPerm; pPerm = pPermNext, i++) {
2296                 pPermNext = pPerm->m_Next;
2297
2298                 pSig = new BinStr();
2299                 pSig->appendInt8(IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS);
2300                 pSig->appendInt8(1);
2301                 pSig->appendInt8(ELEMENT_TYPE_VOID);
2302                 pSig->appendInt8(ELEMENT_TYPE_VALUETYPE);
2303                 uLength = CorSigCompressToken(tkTypeRef, pSig->getBuff(5));
2304                 pSig->remove(5 - uLength);
2305
2306                 uLength = (unsigned)strlen(COR_CTOR_METHOD_NAME) + 1;
2307                 if((szMemberName = new char[uLength]))
2308                 {
2309                     memcpy(szMemberName, COR_CTOR_METHOD_NAME, uLength);
2310                     pAttrs[i].tkCtor = MakeMemberRef(pPerm->m_TypeSpec, szMemberName, pSig);
2311                     pAttrs[i].pCustomAttribute = (const void *)pPerm->m_Blob;
2312                     pAttrs[i].cbCustomAttribute = pPerm->m_BlobLength;
2313                 }
2314                 else report->error("\nOut of memory!\n");
2315             }
2316
2317             if (FAILED(m_pEmitter->DefineSecurityAttributeSet(token,
2318                                                        pAttrs,
2319                                                        uCount,
2320                                                        &dwErrorIndex)))
2321             {
2322                 _ASSERT(uCount >= dwErrorIndex);
2323                 if (dwErrorIndex == uCount)
2324                 {
2325                     report->error("Failed to define security attribute set for 0x%08X\n", token);
2326                 }
2327                 else
2328                 {
2329                     report->error("Failed to define security attribute set for 0x%08X\n  (error in permission %u)\n",
2330                                   token, uCount - dwErrorIndex);
2331                 }
2332             }
2333             delete [] pAttrs;
2334             for (pPerm = pPermissions, i = 0; pPerm; pPerm = pPermNext, i++) {
2335                 pPermNext = pPerm->m_Next;
2336                 delete pPerm;
2337             }
2338         }
2339     }
2340
2341     for (pPset = pPermissionSets; pPset; pPset = pPsetNext) {
2342         pPsetNext = pPset->m_Next;
2343         if(FAILED(m_pEmitter->DefinePermissionSet(token,
2344                                            pPset->m_Action,
2345                                            pPset->m_Value->ptr(),
2346                                            pPset->m_Value->length(),
2347                                            NULL)))
2348             report->error("Failed to define security permission set for 0x%08X\n", token);
2349         delete pPset;
2350     }
2351 }
2352
2353 void Assembler::AddMethodImpl(mdToken tkImplementedTypeSpec, __in __nullterminated char* szImplementedName, BinStr* pImplementedSig,
2354                   mdToken tkImplementingTypeSpec, __in_opt __nullterminated char* szImplementingName, BinStr* pImplementingSig)
2355 {
2356     if(m_pCurClass)
2357     {
2358         MethodImplDescriptor*   pMID = new MethodImplDescriptor;
2359         pMID->m_fNew = TRUE;
2360         if(pMID == NULL)
2361         {
2362             report->error("Failed to allocate MethodImpl Descriptor\n");
2363             return;
2364         }
2365         pMID->m_tkDefiningClass = m_pCurClass->m_cl;
2366         if(szImplementingName) //called from class scope, overriding method specified
2367         {
2368             pMID->m_tkImplementedMethod = MakeMemberRef(tkImplementedTypeSpec,szImplementedName,pImplementedSig);
2369             pMID->m_tkImplementingMethod = MakeMemberRef(tkImplementingTypeSpec,szImplementingName,pImplementingSig);
2370         }
2371         else    //called from method scope, use current method as overriding
2372         {
2373             if(m_pCurMethod)
2374             {
2375                 if (pImplementedSig == NULL)
2376                 {
2377                     pImplementedSig = new BinStr();
2378                     memcpy(pImplementedSig->getBuff(m_pCurMethod->m_dwMethodCSig), m_pCurMethod->m_pMethodSig,m_pCurMethod->m_dwMethodCSig);
2379                 }
2380                 pMID->m_tkImplementedMethod = MakeMemberRef(tkImplementedTypeSpec,szImplementedName,pImplementedSig);
2381                 pMID->m_tkImplementingMethod = 0;
2382
2383                 m_pCurMethod->m_MethodImplDList.PUSH(pMID); // copy goes to method's own list (ptr only)
2384             }
2385             else
2386             {
2387                 report->error("No overriding method specified");
2388                 delete pMID;
2389                 return;
2390             }
2391         }
2392         m_MethodImplDList.PUSH(pMID);
2393     }
2394     else
2395         report->error(".override directive outside class scope");
2396 }
2397 // source file name paraphernalia
2398 void Assembler::SetSourceFileName(__in __nullterminated char* szName)
2399 {
2400     if(szName)
2401     {
2402         if(*szName)
2403         {
2404             if(strcmp(m_szSourceFileName,szName))
2405             {
2406                 strcpy_s(m_szSourceFileName,MAX_FILENAME_LENGTH*3+1,szName);
2407                 WszMultiByteToWideChar(g_uCodePage,0,szName,-1,m_wzSourceFileName,MAX_FILENAME_LENGTH);
2408             }
2409             if(m_fGeneratePDB)
2410             {
2411                 DocWriter* pDW;
2412                 unsigned i=0;
2413                 while((pDW = m_DocWriterList.PEEK(i++)) != NULL)
2414                 {
2415                     if(!strcmp(szName,pDW->Name)) break;
2416                 }
2417                 if(pDW)
2418                 {
2419                      m_pSymDocument = pDW->pWriter;
2420                      delete [] szName;
2421                 }
2422                 else if(m_pSymWriter)
2423                 {
2424                     HRESULT hr;
2425                     WszMultiByteToWideChar(g_uCodePage,0,szName,-1,wzUniBuf,dwUniBuf);
2426                     if(FAILED(hr=m_pSymWriter->DefineDocument(wzUniBuf,&m_guidLang,
2427                         &m_guidLangVendor,&m_guidDoc,&m_pSymDocument)))
2428                     {
2429                         m_pSymDocument = NULL;
2430                         report->error("Failed to define a document writer");
2431                     }
2432                     if((pDW = new DocWriter()) != NULL)
2433                     {
2434                         pDW->Name = szName;
2435                         pDW->pWriter = m_pSymDocument;
2436                         m_DocWriterList.PUSH(pDW);
2437                     }
2438                     else
2439                     {
2440                         report->error("Out of memory");
2441                         delete [] szName;
2442                     }
2443                 }
2444                 else delete [] szName;
2445             }
2446             else delete [] szName;
2447         }
2448         else delete [] szName;
2449     }
2450 }
2451 void Assembler::SetSourceFileName(BinStr* pbsName)
2452 {
2453     ULONG L;
2454     if(pbsName && (L = (ULONG)(pbsName->length())))
2455     {
2456         pbsName->appendInt8(0);
2457         char* sz = new char[L+1];
2458         memcpy(sz,pbsName->ptr(),L+1);
2459         SetSourceFileName(sz);
2460         delete pbsName;
2461     }
2462 }