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