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