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