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