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.
12 #include "assembler.h"
16 #define FAIL_UNLESS(x, y) if (!(x)) { report->error y; return; }
18 /**************************************************************************/
19 void Assembler::StartNameSpace(__in __nullterminated char* name)
21 m_NSstack.PUSH(m_szNamespace);
23 unsigned L = (unsigned)strlen(m_szFullNS);
24 unsigned l = (unsigned)strlen(name);
25 if(L+l+1 >= m_ulFullNSLen)
27 char* pch = new char[((L+l)/MAX_NAMESPACE_LENGTH + 1)*MAX_NAMESPACE_LENGTH];
30 memcpy(pch,m_szFullNS,L+1);
33 m_ulFullNSLen = ((L+l)/MAX_NAMESPACE_LENGTH + 1)*MAX_NAMESPACE_LENGTH;
35 else report->error("Failed to reallocate the NameSpace buffer\n");
37 if(L) m_szFullNS[L] = NAMESPACE_SEPARATOR_CHAR;
39 memcpy(&m_szFullNS[L+1],m_szNamespace, l+1);
42 /**************************************************************************/
43 void Assembler::EndNameSpace()
45 char *p = &m_szFullNS[strlen(m_szFullNS)-strlen(m_szNamespace)];
46 if(p > m_szFullNS) p--;
48 delete [] m_szNamespace;
49 if((m_szNamespace = m_NSstack.POP())==NULL)
51 m_szNamespace = new char[2];
56 /**************************************************************************/
57 void Assembler::ClearImplList(void)
59 while(m_nImplList) m_crImplList[--m_nImplList] = mdTypeRefNil;
61 /**************************************************************************/
64 #pragma warning(disable:22008) // "Suppress PREfast warnings about integer overflow"
66 void Assembler::AddToImplList(mdToken tk)
68 if(m_nImplList+1 >= m_nImplListSize)
70 mdToken *ptr = new mdToken[m_nImplListSize + MAX_INTERFACES_IMPLEMENTED];
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));
78 memcpy(ptr,m_crImplList,m_nImplList*sizeof(mdToken));
81 m_nImplListSize += MAX_INTERFACES_IMPLEMENTED;
83 m_crImplList[m_nImplList++] = tk;
84 m_crImplList[m_nImplList] = mdTypeRefNil;
90 void Assembler::ClearBoundList(void)
94 /**************************************************************************/
95 mdToken Assembler::ResolveClassRef(mdToken tkResScope, __in __nullterminated const char *pszFullClassName, Class** ppClass)
98 mdToken tkRet = mdTokenNil;
99 mdToken *ptkSpecial = NULL;
101 if(pszFullClassName == NULL) return mdTokenNil;
103 if (m_fInitialisedMetaData == FALSE)
105 if (FAILED(InitMetaData())) // impl. see WRITER.CPP
108 if(ppClass) *ppClass = NULL;
114 switch(strlen(pszFullClassName))
117 if(strcmp(pszFullClassName,"System.Enum")==0) ptkSpecial = &m_tkSysEnum;
120 if(strcmp(pszFullClassName,"System.Object")==0) ptkSpecial = &m_tkSysObject;
121 else if(strcmp(pszFullClassName,"System.String")==0) ptkSpecial = &m_tkSysString;
124 if(strcmp(pszFullClassName,"System.ValueType")==0) ptkSpecial = &m_tkSysValue;
127 if(ptkSpecial) // special token
129 if(*ptkSpecial) // already resolved
134 if(TypeFromToken(tkRet)==mdtTypeDef)
135 *ppClass = m_lstClass.PEEK(RidFromToken(tkRet)-1);
136 else *ppClass = NULL;
140 else // needs to be resolved
141 if(!m_fIsMscorlib) tkResScope = GetBaseAsmRef();
145 if((pClass = FindCreateClass(pszFullClassName)) != NULL) tkRet = pClass->m_cl;
149 tkRet = MakeTypeRef(tkResScope, pszFullClassName);
152 if(ppClass) *ppClass = pClass;
153 if(ptkSpecial) *ptkSpecial = tkRet;
157 class TypeSpecContainer
161 unsigned __int8 *ptr_;
163 // Hash the BinStr, just for speed of lookup
165 // The value we're looking for
168 // Constructor for a 'lookup' object
169 TypeSpecContainer(BinStr *typeSpec) :
170 ptr_(typeSpec->ptr()),
171 len_(typeSpec->length()),
172 hash_(typeSpec->length()),
175 for (unsigned i = 0; i < len_; i++)
176 hash_ = (hash_ * 257) ^ ((i + 1) * (ptr_[i] ^ 0xA5));
178 // Constructor for a 'permanent' object
179 // Don't bother re-hashing, since we will always have already constructed the lookup object
180 TypeSpecContainer(const TypeSpecContainer &t, mdToken tk) :
181 ptr_(new unsigned __int8[t.len_]),
186 _ASSERT(tk != mdTokenNil);
187 _ASSERT(t.token_ == mdTokenNil);
188 memcpy(ptr_, t.ptr_, len_);
192 if (token_ != mdTokenNil)
193 // delete any memory for a 'permanent' object
196 // this is the operator for a RBTREE
197 int ComparedTo(TypeSpecContainer *t) const
199 // If they don't hash the same, just diff the hashes
200 if (hash_ != t->hash_)
201 return hash_ - t->hash_;
203 return len_ - t->len_;
204 return memcmp(ptr_, t->ptr_, len_);
206 // The only public data we need
207 const mdToken Token() const { return token_; }
210 static RBTREE<TypeSpecContainer> typeSpecCache;
212 extern FIFO<char> TyParFixupList;
214 /**************************************************************************/
215 mdToken Assembler::ResolveTypeSpec(BinStr* typeSpec)
219 // It is safe to use the cache only if there are no pending fixups
220 if (TyParFixupList.COUNT() != 0)
222 if (FAILED(m_pEmitter->GetTokenFromTypeSpec(typeSpec->ptr(), typeSpec->length(), &tk)))
227 TypeSpecContainer tsc(typeSpec);
229 // GetTokenFromTypeSpec is a linear search through an unsorted list
230 // Instead of doing that all the time, look this thing up in a cache
231 TypeSpecContainer *res = typeSpecCache.FIND(&tsc);
235 // Verify that the cache is in sync with the master copy in metadata
238 m_pImporter->GetTypeSpecFromToken(res->Token(),(PCCOR_SIGNATURE*)&pSig,&cSig);
239 _ASSERTE(typeSpec->length() == cSig);
240 _ASSERTE(memcmp(typeSpec->ptr(), pSig, cSig) == 0);
246 if (FAILED(m_pEmitter->GetTokenFromTypeSpec(typeSpec->ptr(), typeSpec->length(), &tk)))
249 typeSpecCache.PUSH(new TypeSpecContainer(tsc, tk));
253 /**************************************************************************/
254 mdToken Assembler::GetAsmRef(__in __nullterminated const char* szName)
256 mdToken tkResScope = 0;
257 if(strcmp(szName,"*")==0) tkResScope = mdTokenNil;
260 tkResScope = m_pManifest->GetAsmRefTokByName(szName);
261 if(RidFromToken(tkResScope)==0)
263 // emit the AssemblyRef
264 // if it's not self, try to get attributes with Autodetect
265 unsigned L = (unsigned)strlen(szName)+1;
266 char *sz = new char[L];
270 AsmManAssembly *pAsmRef = m_pManifest->m_pCurAsmRef;
271 m_pManifest->StartAssembly(sz,NULL,0,TRUE);
272 if(RidFromToken(m_pManifest->GetAsmTokByName(szName))==0)
274 report->warn("Reference to undeclared extern assembly '%s'. Attempting autodetect\n",szName);
275 m_pManifest->SetAssemblyAutodetect();
277 m_pManifest->EndAssembly();
278 tkResScope = m_pManifest->GetAsmRefTokByName(szName);
279 m_pManifest->m_pCurAsmRef = pAsmRef;
282 report->error("\nOut of memory!\n");
288 mdToken Assembler::GetBaseAsmRef()
290 if(RidFromToken(m_pManifest->GetAsmRefTokByName("System.Runtime")) != 0)
292 return GetAsmRef("System.Runtime");
295 return GetAsmRef("mscorlib");
298 mdToken Assembler::GetInterfaceImpl(mdToken tsClass, mdToken tsInterface)
300 mdToken result = mdTokenNil;
302 ULONG actualInterfaces;
303 mdInterfaceImpl impls;
305 while (SUCCEEDED(m_pImporter->EnumInterfaceImpls(&iiEnum, tsClass, &impls, 1, &actualInterfaces)))
307 if (actualInterfaces == 1)
309 mdToken classToken, interfaceToken;
310 if (FAILED(m_pImporter->GetInterfaceImplProps(impls, &classToken, &interfaceToken)))
312 if (classToken == tsClass && interfaceToken == tsInterface)
319 m_pImporter->CloseEnum(iiEnum);
323 /**************************************************************************/
324 mdToken Assembler::GetModRef(__in __nullterminated char* szName)
326 mdToken tkResScope = 0;
327 if(!strcmp(szName,m_szScopeName))
328 tkResScope = 1; // scope is "this module"
331 ImportDescriptor* pID;
333 tkResScope = mdModuleRefNil;
334 DWORD L = (DWORD)strlen(szName);
335 while((pID=m_ImportList.PEEK(i++)))
337 if(pID->dwDllName != L) continue;
338 if((L > 0) && (strcmp(pID->szDllName,szName)!=0)) continue;
339 tkResScope = pID->mrDll;
342 if(RidFromToken(tkResScope)==0)
343 report->error("Undefined module ref '%s'\n",szName);
347 /**************************************************************************/
348 mdToken Assembler::MakeTypeRef(mdToken tkResScope, LPCUTF8 pszFullClassName)
350 mdToken tkRet = mdTokenNil;
351 if(pszFullClassName && *pszFullClassName)
354 if((pc = strrchr(pszFullClassName,NESTING_SEP))) // scope: enclosing class
357 DWORD L = (DWORD)(pc-pszFullClassName);
358 if((szScopeName = new char[L+1]) != NULL)
360 memcpy(szScopeName,pszFullClassName,L);
362 tkResScope = MakeTypeRef(tkResScope,szScopeName);
363 delete [] szScopeName;
366 report->error("\nOut of memory!\n");
369 else pc = pszFullClassName;
372 // convert name to widechar
373 WszMultiByteToWideChar(g_uCodePage,0,pc,-1,wzUniBuf,dwUniBuf);
374 if(FAILED(m_pEmitter->DefineTypeRefByName(tkResScope, wzUniBuf, &tkRet))) tkRet = mdTokenNil;
379 /**************************************************************************/
381 DWORD Assembler::CheckClassFlagsIfNested(Class* pEncloser, DWORD attr)
383 DWORD wasAttr = attr;
384 if(pEncloser && (!IsTdNested(attr)))
387 report->error("Nested class has non-nested visibility (0x%08X)\n",attr);
390 attr &= ~tdVisibilityMask;
391 attr |= (IsTdPublic(wasAttr) ? tdNestedPublic : tdNestedPrivate);
392 report->warn("Nested class has non-nested visibility (0x%08X), changed to nested (0x%08X)\n",wasAttr,attr);
395 else if((pEncloser==NULL) && IsTdNested(attr))
398 report->error("Non-nested class has nested visibility (0x%08X)\n",attr);
401 attr &= ~tdVisibilityMask;
402 attr |= (IsTdNestedPublic(wasAttr) ? tdPublic : tdNotPublic);
403 report->warn("Non-nested class has nested visibility (0x%08X), changed to non-nested (0x%08X)\n",wasAttr,attr);
409 /**************************************************************************/
411 void Assembler::StartClass(__in __nullterminated char* name, DWORD attr, TyParList *typars)
413 Class *pEnclosingClass = m_pCurClass;
417 m_TyParList = typars;
419 if (m_pCurMethod != NULL)
421 report->error("Class cannot be declared within a method scope\n");
425 LL = pEnclosingClass->m_dwFQN+(ULONG)strlen(name)+2;
426 if((szFQN = new char[LL]))
427 sprintf_s(szFQN,LL,"%s%c%s",pEnclosingClass->m_szFQN,NESTING_SEP,name);
429 report->error("\nOut of memory!\n");
433 unsigned L = (unsigned)strlen(m_szFullNS);
434 unsigned LLL = (unsigned)strlen(name);
435 LL = L + LLL + (L ? 2 : 1);
436 if((szFQN = new char[LL]))
438 if(L) sprintf_s(szFQN,LL,"%s.%s",m_szFullNS,name);
439 else memcpy(szFQN,name,LL);
440 if(LL > MAX_CLASSNAME_LENGTH)
442 report->error("Full class name too long (%d characters, %d allowed).\n",LL-1,MAX_CLASSNAME_LENGTH-1);
446 report->error("\nOut of memory!\n");
448 if(szFQN == NULL) return;
452 tkThis = ResolveClassRef(1,szFQN,&m_pCurClass); // boils down to FindCreateClass(szFQN)
455 m_pCurClass = FindCreateClass(szFQN);
456 tkThis = m_pCurClass->m_cl;
458 if(m_pCurClass->m_bIsMaster)
460 m_pCurClass->m_Attr = CheckClassFlagsIfNested(pEnclosingClass, attr);
464 //m_pCurClass->m_NumTyPars = m_TyParList->ToArray(&m_pCurClass->m_TyParBounds, &m_pCurClass->m_TyParNames, &m_pCurClass->m_TyParAttrs);
465 m_pCurClass->m_NumTyPars = m_TyParList->ToArray(&(m_pCurClass->m_TyPars));
469 else m_pCurClass->m_NumTyPars = 0;
470 m_pCurClass->m_pEncloser = pEnclosingClass;
471 } // end if(old class) else
472 m_tkCurrentCVOwner = 0;
473 m_CustomDescrListStack.PUSH(m_pCustomDescrList);
474 m_pCustomDescrList = &(m_pCurClass->m_CustDList);
476 m_ClassStack.PUSH(pEnclosingClass);
480 /**************************************************************************/
482 void Assembler::AddClass()
484 mdTypeRef crExtends = mdTypeRefNil;
485 BOOL bIsEnum = FALSE;
486 BOOL bIsValueType = FALSE;
488 if(m_pCurClass->m_bIsMaster)
490 DWORD attr = m_pCurClass->m_Attr;
491 if(!IsNilToken(m_crExtends))
494 if(IsTdInterface(attr)) report->error("Base class in interface\n");
495 bIsValueType = (m_crExtends == m_tkSysValue)&&(m_pCurClass->m_cl != m_tkSysEnum);
496 bIsEnum = (m_crExtends == m_tkSysEnum);
497 crExtends = m_crExtends;
501 bIsEnum = ((attr & 0x40000000) != 0);
502 bIsValueType = ((attr & 0x80000000) != 0);
505 if (m_fAutoInheritFromObject && (crExtends == mdTypeRefNil) && (!IsTdInterface(attr)))
507 mdToken tkMscorlib = m_fIsMscorlib ? 1 : GetBaseAsmRef();
508 crExtends = bIsEnum ?
509 ResolveClassRef(tkMscorlib,"System.Enum",NULL)
511 ResolveClassRef(tkMscorlib,"System.ValueType",NULL)
512 : ResolveClassRef(tkMscorlib, "System.Object",NULL));
514 m_pCurClass->m_Attr = attr;
515 m_pCurClass->m_crExtends = (m_pCurClass->m_cl == m_tkSysObject)? mdTypeRefNil : crExtends;
517 if ((m_pCurClass->m_dwNumInterfaces = m_nImplList) != NULL)
519 if(bIsEnum) report->error("Enum implementing interface(s)\n");
520 if((m_pCurClass->m_crImplements = new mdTypeRef[m_nImplList+1]) != NULL)
521 memcpy(m_pCurClass->m_crImplements, m_crImplList, (m_nImplList+1)*sizeof(mdTypeRef));
524 report->error("Failed to allocate Impl List for class '%s'\n", m_pCurClass->m_szFQN);
525 m_pCurClass->m_dwNumInterfaces = 0;
528 else m_pCurClass->m_crImplements = NULL;
531 if(!IsTdSealed(attr))
533 if(OnErrGo) report->error("Non-sealed value class\n");
536 report->warn("Non-sealed value class, made sealed\n");
537 m_pCurClass->m_Attr |= tdSealed;
541 m_pCurClass->m_bIsMaster = FALSE;
542 } // end if(old class) else
544 m_crExtends = mdTypeRefNil;
547 /**************************************************************************/
548 void Assembler::EndClass()
550 m_pCurClass = m_ClassStack.POP();
551 m_tkCurrentCVOwner = 0;
552 m_pCustomDescrList = m_CustomDescrListStack.POP();
555 /**************************************************************************/
556 void Assembler::SetPinvoke(BinStr* DllName, int Ordinal, BinStr* Alias, int Attrs)
558 if(m_pPInvoke) delete m_pPInvoke;
559 if(DllName->length())
561 if((m_pPInvoke = new PInvokeDescriptor))
564 ImportDescriptor* pID;
565 if((pID = EmitImport(DllName)))
567 m_pPInvoke->mrDll = pID->mrDll;
568 m_pPInvoke->szAlias = NULL;
572 if((m_pPInvoke->szAlias = new char[l+1]))
574 memcpy(m_pPInvoke->szAlias,Alias->ptr(),l);
575 m_pPInvoke->szAlias[l] = 0;
577 else report->error("\nOut of memory!\n");
579 m_pPInvoke->dwAttrs = (DWORD)Attrs;
585 report->error("PInvoke refers to undefined imported DLL\n");
589 report->error("Failed to allocate PInvokeDescriptor\n");
593 m_pPInvoke = NULL; // No DLL name, it's "local" (IJW) PInvoke
594 report->error("Local (embedded native) PInvoke method, the resulting PE file is unusable\n");
596 if(DllName) delete DllName;
597 if(Alias) delete Alias;
600 /**************************************************************************/
601 void Assembler::StartMethod(__in __nullterminated char* name, BinStr* sig, CorMethodAttr flags, BinStr* retMarshal, DWORD retAttr, TyParList *typars)
603 if (m_pCurMethod != NULL)
605 report->error("Cannot declare a method '%s' within another method\n",name);
607 if (!m_fInitialisedMetaData)
609 if (FAILED(InitMetaData())) // impl. see WRITER.CPP
614 size_t namelen = strlen(name);
615 if(namelen >= MAX_CLASSNAME_LENGTH)
617 char c = name[MAX_CLASSNAME_LENGTH-1];
618 name[MAX_CLASSNAME_LENGTH-1] = 0;
619 report->error("Method '%s...' -- name too long (%d characters).\n",name,namelen);
620 name[MAX_CLASSNAME_LENGTH-1] = c;
622 if (!(flags & mdStatic))
623 *(sig->ptr()) |= IMAGE_CEE_CS_CALLCONV_HASTHIS;
624 else if(*(sig->ptr()) & (IMAGE_CEE_CS_CALLCONV_HASTHIS | IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS))
626 if(OnErrGo) report->error("Method '%s' -- both static and instance\n", name);
629 report->warn("Method '%s' -- both static and instance, set to static\n", name);
630 *(sig->ptr()) &= ~(IMAGE_CEE_CS_CALLCONV_HASTHIS | IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS);
634 if(!IsMdPrivateScope(flags))
637 Class* pClass = (m_pCurClass ? m_pCurClass : m_pModuleClass);
638 DWORD L = (DWORD)strlen(name);
639 for(int j=0; (pMethod = pClass->m_MethodList.PEEK(j)); j++)
641 if( (pMethod->m_dwName == L) &&
642 (!strcmp(pMethod->m_szName,name)) &&
643 (pMethod->m_dwMethodCSig == sig->length()) &&
644 (!memcmp(pMethod->m_pMethodSig,sig->ptr(),sig->length()))
645 &&(!IsMdPrivateScope(pMethod->m_Attr)))
647 if(m_fTolerateDupMethods)
649 // reset for new body
650 pMethod->m_lstFixup.RESET(true);
651 //pMethod->m_lstLabel.RESET(true);
652 m_lstLabel.RESET(true);
653 pMethod->m_Locals.RESET(true);
654 delArgNameList(pMethod->m_firstArgName);
655 delArgNameList(pMethod->m_firstVarName);
656 pMethod->m_pCurrScope = &(pMethod->m_MainScope);
657 pMethod->m_pCurrScope->Reset();
658 pMethod->m_firstArgName = getArgNameList();
659 pMethod->m_dwNumExceptions = 0;
660 pMethod->m_dwNumEndfilters = 0;
661 if(pMethod->m_pRetMarshal) delete pMethod->m_pRetMarshal;
662 if(pMethod->m_pRetValue) delete pMethod->m_pRetValue;
664 pMethod->m_MethodImplDList.RESET(false); // ptrs in m_MethodImplDList are dups of those in Assembler
666 pMethod->m_CustomDescrList.RESET(true);
668 if(pMethod->m_fEntryPoint)
670 pMethod->m_fEntryPoint = FALSE;
671 m_fEntryPointPresent = FALSE;
674 if(pMethod->m_pbsBody)
676 // no need to remove relevant MemberRef Fixups from the Assembler list:
677 // their m_fNew flag is set to FALSE anyway.
678 // Just get rid of old method body
679 delete pMethod->m_pbsBody;
680 pMethod->m_pbsBody = NULL;
683 pMethod->m_fNewBody = TRUE;
684 m_pCurMethod = pMethod;
687 report->error("Duplicate method declaration\n");
692 if(m_pCurMethod == NULL)
696 if(IsMdAbstract(flags) && !IsTdAbstract(m_pCurClass->m_Attr))
698 report->error("Abstract method '%s' in non-abstract class '%s'\n",name,m_pCurClass->m_szFQN);
700 if(m_pCurClass->m_crExtends == m_tkSysEnum) report->error("Method in enum\n");
702 if(!strcmp(name,COR_CTOR_METHOD_NAME))
704 flags = (CorMethodAttr)(flags | mdSpecialName);
705 if(IsTdInterface(m_pCurClass->m_Attr)) report->error("Instance constructor in interface\n");
708 if(!IsMdStatic(flags))
710 if(IsTdInterface(m_pCurClass->m_Attr))
712 if(!IsMdPublic(flags)) report->error("Non-public instance method in interface\n");
713 if((!(IsMdVirtual(flags) && IsMdAbstract(flags))))
715 if(OnErrGo) report->error("Non-virtual, non-abstract instance method in interface\n");
718 report->warn("Non-virtual, non-abstract instance method in interface, set to such\n");
719 flags = (CorMethodAttr)(flags |mdVirtual | mdAbstract);
725 m_pCurMethod = new Method(this, m_pCurClass, name, sig, flags);
729 if(IsMdAbstract(flags))
731 if(OnErrGo) report->error("Global method '%s' can't be abstract\n",name);
734 report->warn("Global method '%s' can't be abstract, flag removed\n",name);
735 flags = (CorMethodAttr)(((int) flags) &~mdAbstract);
738 if(!IsMdStatic(flags))
740 if(OnErrGo) report->error("Non-static global method '%s'\n",name);
743 report->warn("Non-static global method '%s', made static\n",name);
744 flags = (CorMethodAttr)(flags | mdStatic);
745 *((BYTE*)(sig->ptr())) &= ~(IMAGE_CEE_CS_CALLCONV_HASTHIS | IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS);
748 m_pCurMethod = new Method(this, m_pCurClass, name, sig, flags);
751 m_pCurMethod->SetIsGlobalMethod();
752 if (m_fInitialisedMetaData == FALSE) InitMetaData();
759 if(m_pCurMethod->m_firstArgName)
761 for(ARG_NAME_LIST *pAN=m_pCurMethod->m_firstArgName; pAN; pAN = pAN->pNext)
765 int k = m_pCurMethod->findArgNum(pAN->pNext,pAN->szName,pAN->dwName);
767 report->warn("Duplicate param name '%s' in method '%s'\n",pAN->szName,name);
772 m_pCurMethod->m_pRetMarshal = retMarshal;
773 m_pCurMethod->m_dwRetAttr = retAttr;
774 m_tkCurrentCVOwner = 0;
775 m_CustomDescrListStack.PUSH(m_pCustomDescrList);
776 m_pCustomDescrList = &(m_pCurMethod->m_CustomDescrList);
777 m_pCurMethod->m_MainScope.dwStart = m_CurPC;
780 //m_pCurMethod->m_NumTyPars = typars->ToArray(&m_pCurMethod->m_TyParBounds,
781 //&m_pCurMethod->m_TyParNames, NULL);
782 m_pCurMethod->m_NumTyPars = typars->ToArray(&(m_pCurMethod->m_TyPars));
786 else m_pCurMethod->m_NumTyPars = 0;
788 else report->error("Failed to allocate Method class\n");
789 } // end if new method
792 /**************************************************************************/
793 void Assembler::EndMethod()
796 if(m_pCurMethod->m_pCurrScope != &(m_pCurMethod->m_MainScope))
798 report->error("Invalid lexical scope structure in method %s\n",m_pCurMethod->m_szName);
800 m_pCurMethod->m_pCurrScope->dwEnd = m_CurPC;
801 if (DoFixups(m_pCurMethod)) AddMethod(m_pCurMethod); //AddMethod - see ASSEM.CPP
804 report->error("Method '%s' compilation failed.\n",m_pCurMethod->m_szName);
806 //m_pCurMethod->m_lstLabel.RESET(true);
807 m_lstLabel.RESET(true);
808 m_tkCurrentCVOwner = 0;
809 m_pCustomDescrList = m_CustomDescrListStack.POP();
810 ResetForNextMethod(); // see ASSEM.CPP
812 /**************************************************************************/
813 /* rvaLabel is the optional label that indicates this field points at a particular RVA */
814 void Assembler::AddField(__inout_z __inout char* name, BinStr* sig, CorFieldAttr flags, __in __nullterminated char* rvaLabel, BinStr* pVal, ULONG ulOffset)
816 FieldDescriptor* pFD;
818 mdToken tkParent = mdTokenNil;
822 report->error("Field cannot be declared within a method\n");
824 if(strlen(name) >= MAX_CLASSNAME_LENGTH)
826 char c = name[MAX_CLASSNAME_LENGTH-1];
827 name[MAX_CLASSNAME_LENGTH-1] = 0;
828 report->error("Field '%s...' -- name too long (%d characters).\n",name,strlen(name));
829 name[MAX_CLASSNAME_LENGTH-1] = c;
832 if(sig && (sig->length() >= 2))
834 if(sig->ptr()[1] == ELEMENT_TYPE_VOID)
835 report->error("Illegal use of type 'void'\n");
840 tkParent = m_pCurClass->m_cl;
842 if(IsTdInterface(m_pCurClass->m_Attr))
844 if(!IsFdStatic(flags))
846 report->warn("Instance field in interface (CLS violation)\n");
847 if(!IsFdPublic(flags)) report->error("Non-public instance field in interface\n");
853 if(ulOffset != 0xFFFFFFFF)
855 report->warn("Offset in global field '%s' is ignored\n",name);
856 ulOffset = 0xFFFFFFFF;
858 if(!IsFdStatic(flags))
860 if(OnErrGo) report->error("Non-static global field\n");
863 report->warn("Non-static global field, made static\n");
864 flags = (CorFieldAttr)(flags | fdStatic);
868 pClass = (m_pCurClass ? m_pCurClass : m_pModuleClass);
869 n = pClass->m_FieldDList.COUNT();
870 DWORD L = (DWORD)strlen(name);
871 for(i = 0; i < n; i++)
873 pFD = pClass->m_FieldDList.PEEK(i);
874 if((pFD->m_tdClass == tkParent)&&(L==pFD->m_dwName)&&(!strcmp(pFD->m_szName,name))
875 &&(pFD->m_pbsSig->length() == sig->length())
876 &&(memcmp(pFD->m_pbsSig->ptr(),sig->ptr(),sig->length())==0))
878 report->error("Duplicate field declaration: '%s'\n",name);
882 if (rvaLabel && !IsFdStatic(flags))
883 report->error("Only static fields can have 'at' clauses\n");
887 if((pFD = new FieldDescriptor))
889 pFD->m_tdClass = tkParent;
890 pFD->m_szName = name;
892 pFD->m_fdFieldTok = mdTokenNil;
893 if((pFD->m_ulOffset = ulOffset) != 0xFFFFFFFF) pClass->m_dwNumFieldsWithOffset++;
894 pFD->m_rvaLabel = rvaLabel;
896 pFD->m_pClass = pClass;
897 pFD->m_pbsValue = pVal;
898 pFD->m_pbsMarshal = m_pMarshal;
899 pFD->m_pPInvoke = m_pPInvoke;
900 pFD->m_dwAttr = flags;
902 m_tkCurrentCVOwner = 0;
903 m_pCustomDescrList = &(pFD->m_CustomDescrList);
905 pClass->m_FieldDList.PUSH(pFD);
906 pClass->m_fNewMembers = TRUE;
909 report->error("Failed to allocate Field Descriptor\n");
913 if(pVal) delete pVal;
914 if(m_pPInvoke) delete m_pPInvoke;
915 if(m_pMarshal) delete m_pMarshal;
922 BOOL Assembler::EmitField(FieldDescriptor* pFD)
924 WCHAR* wzFieldName=&wzUniBuf[0];
927 COR_SIGNATURE* mySig;
929 BYTE ValType = ELEMENT_TYPE_VOID;
930 void * pValue = NULL;
934 cSig = pFD->m_pbsSig->length();
935 mySig = (COR_SIGNATURE*)(pFD->m_pbsSig->ptr());
937 WszMultiByteToWideChar(g_uCodePage,0,pFD->m_szName,-1,wzFieldName,dwUniBuf); //int)cFieldNameLength);
938 if(IsFdPrivateScope(pFD->m_dwAttr))
940 WCHAR* p = wcsstr(wzFieldName,W("$PST04"));
944 if(pFD->m_pbsValue && pFD->m_pbsValue->length())
946 ValType = *(pFD->m_pbsValue->ptr());
947 lVal = pFD->m_pbsValue->length() - 1; // 1 is type byte
948 pValue = (void*)(pFD->m_pbsValue->ptr() + 1);
949 if(ValType == ELEMENT_TYPE_STRING)
951 //while(lVal % sizeof(WCHAR)) { pFD->m_pbsValue->appendInt8(0); lVal++; }
952 lVal /= sizeof(WCHAR);
954 #if defined(ALIGN_ACCESS) || BIGENDIAN
955 void* pValueTemp = _alloca(lVal * sizeof(WCHAR));
956 memcpy(pValueTemp, pValue, lVal * sizeof(WCHAR));
959 SwapStringLength((WCHAR*)pValue, lVal);
964 hr = m_pEmitter->DefineField(
977 report->error("Failed to define field '%s' (HRESULT=0x%08X)\n",pFD->m_szName,hr);
982 //--------------------------------------------------------------------------------
983 if(IsFdPinvokeImpl(pFD->m_dwAttr)&&(pFD->m_pPInvoke))
985 if(pFD->m_pPInvoke->szAlias == NULL) pFD->m_pPInvoke->szAlias = pFD->m_szName;
986 if(FAILED(EmitPinvokeMap(mb,pFD->m_pPInvoke)))
988 report->error("Failed to define PInvoke map of .field '%s'\n",pFD->m_szName);
992 //--------------------------------------------------------------------------
993 if(pFD->m_pbsMarshal)
995 if(FAILED(hr = m_pEmitter->SetFieldMarshal (
996 mb, // [IN] given a fieldDef or paramDef token
997 (PCCOR_SIGNATURE)(pFD->m_pbsMarshal->ptr()), // [IN] native type specification
998 pFD->m_pbsMarshal->length()))) // [IN] count of bytes of pvNativeType
1000 report->error("Failed to set field marshaling for '%s' (HRESULT=0x%08X)\n",pFD->m_szName,hr);
1004 //--------------------------------------------------------------------------------
1005 // Set the the RVA to a dummy value. later it will be fixed
1006 // up to be something correct, but if we don't emit something
1007 // the size of the meta-data will not be correct
1008 if (pFD->m_rvaLabel)
1010 m_fHaveFieldsWithRvas = TRUE;
1011 hr = m_pEmitter->SetFieldRVA(mb, 0xCCCCCCCC);
1014 report->error("Failed to set RVA for field '%s' (HRESULT=0x%08X)\n",pFD->m_szName,hr);
1018 //--------------------------------------------------------------------------------
1019 EmitCustomAttributes(mb, &(pFD->m_CustomDescrList));
1022 pFD->m_fdFieldTok = mb;
1026 /**************************************************************************/
1027 void Assembler::EmitByte(int val)
1029 char ch = (char)val;
1030 //if((val < -128)||(val > 127))
1031 // report->warn("Emitting 0x%X as a byte: data truncated to 0x%X\n",(unsigned)val,(BYTE)ch);
1032 EmitBytes((BYTE *)&ch,1);
1035 /**************************************************************************/
1036 void Assembler::NewSEHDescriptor(void) //sets m_SEHD
1038 m_SEHDstack.PUSH(m_SEHD);
1039 m_SEHD = new SEH_Descriptor;
1040 if(m_SEHD == NULL) report->error("Failed to allocate SEH descriptor\n");
1042 /**************************************************************************/
1043 void Assembler::SetTryLabels(__in __nullterminated char * szFrom, __in __nullterminated char *szTo)
1046 Label *pLbl = m_pCurMethod->FindLabel(szFrom);
1049 m_SEHD->tryFrom = pLbl->m_PC;
1050 if((pLbl = m_pCurMethod->FindLabel(szTo))) m_SEHD->tryTo = pLbl->m_PC; //FindLabel: Method.CPP
1051 else report->error("Undefined 2nd label in 'try <label> to <label>'\n");
1053 else report->error("Undefined 1st label in 'try <label> to <label>'\n");
1055 /**************************************************************************/
1056 void Assembler::SetFilterLabel(__in __nullterminated char *szFilter)
1059 Label *pLbl = m_pCurMethod->FindLabel(szFilter);
1060 if(pLbl) m_SEHD->sehFilter = pLbl->m_PC;
1061 else report->error("Undefined label in 'filter <label>'\n");
1063 /**************************************************************************/
1064 void Assembler::SetCatchClass(mdToken catchClass)
1067 m_SEHD->cException = catchClass;
1070 /**************************************************************************/
1071 void Assembler::SetHandlerLabels(__in __nullterminated char *szHandlerFrom, __in __nullterminated char *szHandlerTo)
1074 Label *pLbl = m_pCurMethod->FindLabel(szHandlerFrom);
1077 m_SEHD->sehHandler = pLbl->m_PC;
1080 pLbl = m_pCurMethod->FindLabel(szHandlerTo);
1083 m_SEHD->sehHandlerTo = pLbl->m_PC;
1089 m_SEHD->sehHandlerTo = m_SEHD->sehHandler - 1;
1093 report->error("Undefined label in 'handler <label> to <label>'\n");
1095 /**************************************************************************/
1096 void Assembler::EmitTry(void) //enum CorExceptionFlag kind, char* beginLabel, char* endLabel, char* handleLabel, char* filterOrClass)
1100 bool isFilter=(m_SEHD->sehClause == COR_ILEXCEPTION_CLAUSE_FILTER),
1101 isFault=(m_SEHD->sehClause == COR_ILEXCEPTION_CLAUSE_FAULT),
1102 isFinally=(m_SEHD->sehClause == COR_ILEXCEPTION_CLAUSE_FINALLY);
1104 AddException(m_SEHD->tryFrom, m_SEHD->tryTo, m_SEHD->sehHandler, m_SEHD->sehHandlerTo,
1105 m_SEHD->cException, isFilter, isFault, isFinally);
1107 else report->error("Attempt to EmitTry with NULL SEH descriptor\n");
1109 /**************************************************************************/
1111 void Assembler::AddException(DWORD pcStart, DWORD pcEnd, DWORD pcHandler, DWORD pcHandlerTo, mdTypeRef crException, BOOL isFilter, BOOL isFault, BOOL isFinally)
1113 if (m_pCurMethod == NULL)
1115 report->error("Exceptions can be declared only when in a method scope\n");
1119 if (m_pCurMethod->m_dwNumExceptions >= m_pCurMethod->m_dwMaxNumExceptions)
1121 COR_ILMETHOD_SECT_EH_CLAUSE_FAT *ptr =
1122 new COR_ILMETHOD_SECT_EH_CLAUSE_FAT[m_pCurMethod->m_dwMaxNumExceptions+MAX_EXCEPTIONS];
1125 report->error("Failed to reallocate SEH buffer\n");
1128 memcpy(ptr,m_pCurMethod->m_ExceptionList,m_pCurMethod->m_dwNumExceptions*sizeof(COR_ILMETHOD_SECT_EH_CLAUSE_FAT));
1129 delete [] m_pCurMethod->m_ExceptionList;
1130 m_pCurMethod->m_ExceptionList = ptr;
1131 m_pCurMethod->m_dwMaxNumExceptions += MAX_EXCEPTIONS;
1134 COR_ILMETHOD_SECT_EH_CLAUSE_FAT *clause = &m_pCurMethod->m_ExceptionList[m_pCurMethod->m_dwNumExceptions];
1135 clause->SetTryOffset(pcStart);
1136 clause->SetTryLength(pcEnd - pcStart);
1137 clause->SetHandlerOffset(pcHandler);
1138 clause->SetHandlerLength(pcHandlerTo - pcHandler);
1139 clause->SetClassToken(crException);
1141 int flags = COR_ILEXCEPTION_CLAUSE_OFFSETLEN;
1143 flags |= COR_ILEXCEPTION_CLAUSE_FILTER;
1146 flags |= COR_ILEXCEPTION_CLAUSE_FAULT;
1149 flags |= COR_ILEXCEPTION_CLAUSE_FINALLY;
1151 clause->SetFlags((CorExceptionFlag)flags);
1153 m_pCurMethod->m_dwNumExceptions++;
1156 /**************************************************************************/
1157 void Assembler::EmitMaxStack(unsigned val)
1159 if(val > 0xFFFF) report->warn(".maxstack parameter exceeds 65535, truncated to %d\n",val&0xFFFF);
1160 if (m_pCurMethod) m_pCurMethod->m_MaxStack = val&0xFFFF;
1161 else report->error(".maxstack can be used only within a method scope\n");
1164 /**************************************************************************/
1165 void Assembler::EmitLocals(BinStr* sig)
1171 ARG_NAME_LIST *pAN, *pList= getArgNameList();
1175 for(pAN=pList; pAN; pAN = pAN->pNext)
1177 if(pAN->dwAttr == 0) pAN->dwAttr = m_pCurMethod->m_Locals.COUNT() +1;
1179 if((pVD = m_pCurMethod->m_Locals.PEEK(pAN->dwAttr)))
1183 report->warn("Local var slot %d is in use\n",pAN->dwAttr);
1185 if(pVD->pbsSig && ((pVD->pbsSig->length() != pAN->pSig->length()) ||
1186 (memcmp(pVD->pbsSig->ptr(),pAN->pSig->ptr(),pVD->pbsSig->length()))))
1188 report->error("Local var slot %d: type conflict\n",pAN->dwAttr);
1192 { // create new entry:
1193 for(unsigned n = m_pCurMethod->m_Locals.COUNT(); n <= pAN->dwAttr; n++)
1196 if(pVD != NULL) m_pCurMethod->m_Locals.PUSH(pVD);
1199 report->error("Out of memory allocating local var descriptor\n");
1205 pVD->dwSlot = pAN->dwAttr;
1206 pVD->pbsSig = pAN->pSig;
1207 pVD->bInScope = TRUE;
1209 if(pVD->pbsSig && (pVD->pbsSig->length() == 1))
1211 if(pVD->pbsSig->ptr()[0] == ELEMENT_TYPE_VOID)
1212 report->error("Illegal local var type: 'void'\n");
1214 m_pCurMethod->m_pCurrScope->pLocals =
1215 m_pCurMethod->catArgNameList(m_pCurMethod->m_pCurrScope->pLocals, pList);
1218 else report->error(".locals can be used only within a method scope\n");
1221 else report->error("Attempt to EmitLocals with NULL argument\n");
1224 /**************************************************************************/
1225 void Assembler::EmitEntryPoint()
1229 if(!m_fEntryPointPresent)
1231 if(IsMdStatic(m_pCurMethod->m_Attr))
1233 m_pCurMethod->m_fEntryPoint = TRUE;
1234 m_fEntryPointPresent = TRUE;
1236 else report->error("Non-static method as entry point\n");
1238 else report->error("Multiple .entrypoint declarations\n");
1240 else report->error(".entrypoint can be used only within a method scope\n");
1243 /**************************************************************************/
1244 void Assembler::EmitZeroInit()
1246 if (m_pCurMethod) m_pCurMethod->m_Flags |= CorILMethod_InitLocals;
1247 else report->error(".zeroinit can be used only within a method scope\n");
1250 /**************************************************************************/
1251 void Assembler::SetImplAttr(unsigned short attrval)
1255 if(IsMiNative(attrval)||IsMiOPTIL(attrval)||IsMiUnmanaged(attrval))
1256 report->error("Cannot compile native/unmanaged method\n");
1257 m_pCurMethod->m_wImplAttr = attrval;
1261 /**************************************************************************/
1262 void Assembler::EmitData(__in_opt void *buffer, unsigned len)
1267 HRESULT hr = m_pCeeFileGen->GetSectionBlock(m_pCurSection, len, 1, &ptr);
1270 report->error("Could not extend data section (out of memory?)");
1276 memcpy(ptr, buffer, len);
1280 memset(ptr, 0, len);
1285 /**************************************************************************/
1286 void Assembler::EmitDD(__in __nullterminated char *str)
1289 GlobalLabel *pLabel = FindGlobalLabel(str);
1292 HRESULT hr = m_pCeeFileGen->GetSectionDataLen(m_pCurSection, &loc);
1293 _ASSERTE(SUCCEEDED(hr));
1296 DWORD sizeofptr = (DWORD)((m_dwCeeFileFlags & ICEE_CREATE_FILE_PE32) ? sizeof(DWORD) : sizeof(__int64));
1297 hr = m_pCeeFileGen->GetSectionBlock(m_pCurSection, sizeofptr, 1, (void**) &ptr);
1300 report->error("Could not extend data section (out of memory?)");
1305 dwAddr = pLabel->m_GlobalOffset;
1306 if (pLabel->m_Section != m_pGlobalDataSection) {
1307 report->error("For '&label', label must be in data section");
1308 m_State = STATE_FAIL;
1312 AddDeferredGlobalFixup(str, (BYTE*) ptr);
1314 hr = m_pCeeFileGen->AddSectionReloc(m_pCurSection, loc, m_pGlobalDataSection, srRelocHighLow);
1315 _ASSERTE(SUCCEEDED(hr));
1316 if(m_dwCeeFileFlags & ICEE_CREATE_FILE_STRIP_RELOCS)
1318 report->error("Base relocations are emitted, while /STRIPRELOC option has been specified");
1320 if(m_dwCeeFileFlags & ICEE_CREATE_FILE_PE32)
1322 m_dwComImageFlags &= ~COMIMAGE_FLAGS_ILONLY;
1323 if (m_dwCeeFileFlags & ICEE_CREATE_MACHINE_I386)
1324 COR_SET_32BIT_REQUIRED(m_dwComImageFlags);
1329 m_dwComImageFlags &= ~COMIMAGE_FLAGS_ILONLY;
1330 *((__int64*)ptr) = (__int64)dwAddr;
1334 /**************************************************************************/
1335 GlobalLabel *Assembler::FindGlobalLabel(LPCUTF8 pszName)
1337 GlobalLabel lSearch(pszName,0,NULL), *pL;
1338 pL = m_lstGlobalLabel.FIND(&lSearch);
1339 lSearch.m_szName = NULL;
1341 //return m_lstGlobalLabel.FIND(pszName);
1344 /**************************************************************************/
1346 GlobalFixup *Assembler::AddDeferredGlobalFixup(__in __nullterminated char *pszLabel, BYTE* pReference)
1348 GlobalFixup *pNew = new GlobalFixup(pszLabel, (BYTE*) pReference);
1351 report->error("Failed to allocate global fixup\n");
1352 m_State = STATE_FAIL;
1355 m_lstGlobalFixup.PUSH(pNew);
1360 /**************************************************************************/
1361 void Assembler::AddDeferredILFixup(ILFixupType Kind)
1363 _ASSERTE(Kind != ilGlobal);
1364 AddDeferredILFixup(Kind, NULL);
1366 /**************************************************************************/
1368 void Assembler::AddDeferredILFixup(ILFixupType Kind,
1369 GlobalFixup *GFixup)
1371 ILFixup *pNew = new ILFixup(m_CurPC, Kind, GFixup);
1373 _ASSERTE(m_pCurMethod != NULL);
1376 report->error("Failed to allocate IL fixup\n");
1377 m_State = STATE_FAIL;
1380 m_pCurMethod->m_lstILFixup.PUSH(pNew);
1383 /**************************************************************************/
1384 void Assembler::EmitDataString(BinStr* str)
1389 DWORD DataLen = str->length();
1390 char *pb = (char*)(str->ptr());
1391 WCHAR *UnicodeString = (DataLen >= dwUniBuf) ? new WCHAR[DataLen] : &wzUniBuf[0];
1395 WszMultiByteToWideChar(g_uCodePage,0,pb,-1,UnicodeString,DataLen);
1396 EmitData(UnicodeString,DataLen*sizeof(WCHAR));
1397 if(DataLen >= dwUniBuf) delete [] UnicodeString;
1399 else report->error("\nOut of memory!\n");
1406 /**************************************************************************/
1407 unsigned Assembler::OpcodeLen(Instr* instr)
1409 return (m_fStdMapping ? OpcodeInfo[instr->opcode].Len : 3);
1411 /**************************************************************************/
1412 void Assembler::EmitOpcode(Instr* instr)
1414 if(m_fGeneratePDB &&
1415 ((instr->linenum != m_ulLastDebugLine)
1416 ||(instr->column != m_ulLastDebugColumn)
1417 ||(instr->linenum_end != m_ulLastDebugLineEnd)
1418 ||(instr->column_end != m_ulLastDebugColumnEnd)))
1422 LinePC *pLPC = new LinePC;
1425 pLPC->Line = instr->linenum;
1426 pLPC->Column = instr->column;
1427 pLPC->LineEnd = instr->linenum_end;
1428 pLPC->ColumnEnd = instr->column_end;
1430 pLPC->pWriter = instr->pWriter;
1431 m_pCurMethod->m_LinePCList.PUSH(pLPC);
1433 else report->error("\nOut of memory!\n");
1435 m_ulLastDebugLine = instr->linenum;
1436 m_ulLastDebugColumn = instr->column;
1437 m_ulLastDebugLineEnd = instr->linenum_end;
1438 m_ulLastDebugColumnEnd = instr->column_end;
1440 if(instr->opcode == CEE_ENDFILTER)
1444 if(m_pCurMethod->m_dwNumEndfilters >= m_pCurMethod->m_dwMaxNumEndfilters)
1446 DWORD *pdw = new DWORD[m_pCurMethod->m_dwMaxNumEndfilters+MAX_EXCEPTIONS];
1449 report->error("Failed to reallocate auxiliary SEH buffer\n");
1453 memcpy(pdw,m_pCurMethod->m_EndfilterOffsetList,m_pCurMethod->m_dwNumEndfilters*sizeof(DWORD));
1454 delete m_pCurMethod->m_EndfilterOffsetList;
1455 m_pCurMethod->m_EndfilterOffsetList = pdw;
1456 m_pCurMethod->m_dwMaxNumEndfilters += MAX_EXCEPTIONS;
1458 m_pCurMethod->m_EndfilterOffsetList[m_pCurMethod->m_dwNumEndfilters++] = m_CurPC+2;
1463 if (OpcodeInfo[instr->opcode].Len == 2)
1464 EmitByte(OpcodeInfo[instr->opcode].Std1);
1465 EmitByte(OpcodeInfo[instr->opcode].Std2);
1469 unsigned short us = (unsigned short)instr->opcode;
1471 EmitBytes((BYTE *)&us,2);
1476 /**************************************************************************/
1477 //void Assembler::OptimizeInstr(Instr* instr, int var)
1481 /**************************************************************************/
1482 unsigned Assembler::ShortOf(unsigned opcode)
1487 case CEE_LDARG: retcode=CEE_LDARG_S; break;
1488 case CEE_LDARGA: retcode=CEE_LDARGA_S; break;
1489 case CEE_STARG: retcode=CEE_STARG_S; break;
1491 case CEE_LDLOC: retcode=CEE_LDLOC_S; break;
1492 case CEE_LDLOCA: retcode=CEE_LDLOCA_S; break;
1493 case CEE_STLOC: retcode=CEE_STLOC_S; break;
1495 case CEE_BR: retcode=CEE_BR_S; break;
1496 case CEE_BRFALSE: retcode=CEE_BRFALSE_S; break;
1497 case CEE_BRTRUE: retcode=CEE_BRTRUE_S; break;
1498 case CEE_BEQ: retcode=CEE_BEQ_S; break;
1499 case CEE_BGE: retcode=CEE_BGE_S; break;
1500 case CEE_BGT: retcode=CEE_BGT_S; break;
1501 case CEE_BLE: retcode=CEE_BLE_S; break;
1502 case CEE_BLT: retcode=CEE_BLT_S; break;
1503 case CEE_BNE_UN: retcode=CEE_BNE_UN_S; break;
1504 case CEE_BGE_UN: retcode=CEE_BGE_UN_S; break;
1505 case CEE_BGT_UN: retcode=CEE_BGT_UN_S; break;
1506 case CEE_BLE_UN: retcode=CEE_BLE_UN_S; break;
1507 case CEE_BLT_UN: retcode=CEE_BLT_UN_S; break;
1508 case CEE_LEAVE: retcode=CEE_LEAVE_S; break;
1510 case CEE_LDC_I4: retcode=CEE_LDC_I4_S; break;
1511 case CEE_LDC_R8: retcode=CEE_LDC_R4; break;
1514 default: retcode = opcode; break;
1519 /**************************************************************************/
1520 void Assembler::EmitInstrVar(Instr* instr, int var)
1522 unsigned opc = instr->opcode;
1530 case CEE_LDARG_S: opc = CEE_LDARG_0 + var; break;
1533 case CEE_LDLOC_S: opc = CEE_LDLOC_0 + var; break;
1536 case CEE_STLOC_S: opc = CEE_STLOC_0 + var; break;
1540 if(opc != (unsigned) instr->opcode)
1542 instr->opcode = opc;
1549 opc = instr->opcode = ShortOf(opc);
1559 short sh = (short)var;
1560 EmitBytes((BYTE *)&sh,2);
1564 /**************************************************************************/
1565 void Assembler::EmitInstrVarByName(Instr* instr, __in __nullterminated char* label)
1567 int idx = -1, nArgVarFlag=0;
1568 switch(instr->opcode)
1586 DWORD L = (DWORD)strlen(label);
1587 if(nArgVarFlag == 1)
1589 idx = m_pCurMethod->findArgNum(m_pCurMethod->m_firstArgName,label,L);
1593 for(Scope* pSC = m_pCurMethod->m_pCurrScope; pSC; pSC=pSC->pSuperScope)
1595 idx = m_pCurMethod->findLocSlot(pSC->pLocals,label,L);
1599 if(idx >= 0) EmitInstrVar(instr,
1600 ((nArgVarFlag==0)||(m_pCurMethod->m_Attr & mdStatic))? idx : idx+1);
1601 else report->error("Undeclared identifier %s\n",label);
1604 report->error("Instructions can be used only when in a method scope\n");
1607 report->error("Named argument illegal for this instruction\n");
1609 instr->opcode = -1; // in case we got here with error
1612 /**************************************************************************/
1613 void Assembler::EmitInstrI(Instr* instr, int val)
1615 int opc = instr->opcode;
1618 if((val >= -1)&&(val <= 8))
1623 case CEE_LDC_I4_S: opc = CEE_LDC_I4_M1 + (val+1); break;
1627 if(opc != instr->opcode)
1629 instr->opcode = opc;
1634 if((-128 <= val)&&(val <= 127))
1636 opc = instr->opcode = ShortOf(opc);
1647 EmitBytes((BYTE *)&i,sizeof(int));
1651 /**************************************************************************/
1652 void Assembler::EmitInstrI8(Instr* instr, __int64* val)
1655 EmitBytes((BYTE *)val, sizeof(__int64));
1659 /**************************************************************************/
1660 void Assembler::EmitInstrR(Instr* instr, double* pval)
1662 unsigned opc = instr->opcode;
1666 float val = (float)*pval;
1667 EmitBytes((BYTE *)&val, sizeof(float));
1670 EmitBytes((BYTE *)pval, sizeof(double));
1673 /**************************************************************************/
1674 void Assembler::EmitInstrBrTarget(Instr* instr, __in __nullterminated char* label)
1676 Label * pLabel = m_pCurMethod->FindLabel(label);
1678 if (pLabel == NULL) // branching forward -- no optimization
1680 int pcrelsize = 1+(isShort(instr->opcode) ? 1 : 4); //size of the instruction plus argument
1681 AddDeferredFixup(label, m_pCurOutputPos+1,
1682 (m_CurPC + pcrelsize), pcrelsize-1);
1686 offset = pLabel->m_PC - m_CurPC;
1689 if((-128 <= offset-5)&&(offset-2 <= 127)) //need to take into account the argument size (worst cases)
1691 instr->opcode = ShortOf(instr->opcode);
1694 if(isShort(instr->opcode))
1697 if((-128 > offset)||(offset > 127))
1698 report->error("Offset too large for short branching instruction, truncated\n");
1704 int opc = instr->opcode;
1706 if(isShort(opc)) EmitByte(offset);
1707 else EmitBytes((BYTE *)&offset,4);
1709 /**************************************************************************/
1710 void Assembler::AddDeferredFixup(__in __nullterminated char *pszLabel, BYTE *pBytes, DWORD RelativeToPC, BYTE FixupSize)
1712 Fixup *pNew = new Fixup(pszLabel, pBytes, RelativeToPC, FixupSize);
1716 report->error("Failed to allocate deferred fixup\n");
1717 m_State = STATE_FAIL;
1720 m_pCurMethod->m_lstFixup.PUSH(pNew);
1722 /**************************************************************************/
1723 void Assembler::EmitInstrBrOffset(Instr* instr, int offset)
1725 unsigned opc=instr->opcode;
1728 if((-128 <= offset)&&(offset <= 127))
1730 opc = instr->opcode = ShortOf(opc);
1734 if(isShort(opc)) EmitByte(offset);
1738 EmitBytes((BYTE *)&i,4);
1742 /**************************************************************************/
1743 mdToken Assembler::MakeMemberRef(mdToken cr, __in __nullterminated char* pszMemberName, BinStr* sig)
1745 DWORD cSig = sig->length();
1746 COR_SIGNATURE* mySig = (COR_SIGNATURE *)(sig->ptr());
1747 mdToken mr = mdMemberRefNil;
1748 Class* pClass = NULL;
1749 if(cr == 0x00000001) cr = mdTokenNil; // Module -> nil for globals
1750 if(TypeFromToken(cr) == mdtTypeDef) pClass = m_lstClass.PEEK(RidFromToken(cr)-1);
1751 if((TypeFromToken(cr) == mdtTypeDef)||(cr == mdTokenNil))
1753 MemberRefDescriptor* pMRD = new MemberRefDescriptor;
1756 pMRD->m_tdClass = cr;
1757 pMRD->m_pClass = pClass;
1758 pMRD->m_szName = pszMemberName;
1759 pMRD->m_dwName = (DWORD)strlen(pszMemberName);
1760 pMRD->m_pSigBinStr = sig;
1761 pMRD->m_tkResolved = 0;
1762 if(*(sig->ptr())== IMAGE_CEE_CS_CALLCONV_FIELD)
1764 m_LocalFieldRefDList.PUSH(pMRD);
1765 mr = 0x98000000 | m_LocalFieldRefDList.COUNT();
1769 m_LocalMethodRefDList.PUSH(pMRD);
1770 mr = 0x99000000 | m_LocalMethodRefDList.COUNT();
1775 report->error("Failed to allocate MemberRef Descriptor\n");
1781 WszMultiByteToWideChar(g_uCodePage,0,pszMemberName,-1,wzUniBuf,dwUniBuf);
1783 if(cr == mdTokenNil) cr = mdTypeRefNil;
1784 if(TypeFromToken(cr) == mdtAssemblyRef)
1786 report->error("Cross-assembly global references are not supported ('%s')\n", pszMemberName);
1791 HRESULT hr = m_pEmitter->DefineMemberRef(cr, wzUniBuf, mySig, cSig, &mr);
1794 report->error("Unable to define member reference '%s'\n", pszMemberName);
1798 //if(m_fOBJ) m_pCurMethod->m_TRDList.PUSH(new TokenRelocDescr(m_CurPC,mr));
1799 delete pszMemberName;
1804 /**************************************************************************/
1805 void Assembler::SetMemberRefFixup(mdToken tk, unsigned opcode_len)
1809 switch(TypeFromToken(tk))
1814 if(m_pCurMethod != NULL)
1815 m_pCurMethod->m_LocalMemberRefFixupList.PUSH(
1816 new LocalMemberRefFixup(tk,(size_t)(m_CurPC + opcode_len)));
1822 /**************************************************************************/
1823 mdToken Assembler::MakeMethodSpec(mdToken tkParent, BinStr* sig)
1825 DWORD cSig = sig->length();
1826 COR_SIGNATURE* mySig = (COR_SIGNATURE *)(sig->ptr());
1827 mdMethodSpec mi = mdMethodSpecNil;
1828 if(TypeFromToken(tkParent) == 0x99000000) // Local MemberRef: postpone until resolved
1830 MemberRefDescriptor* pMRD = new MemberRefDescriptor;
1833 memset(pMRD,0,sizeof(MemberRefDescriptor));
1834 pMRD->m_tdClass = tkParent;
1835 pMRD->m_pSigBinStr = sig;
1836 m_MethodSpecList.PUSH(pMRD);
1837 mi = 0x9A000000 | m_MethodSpecList.COUNT();
1841 report->error("Failed to allocate MemberRef Descriptor\n");
1847 HRESULT hr = m_pEmitter->DefineMethodSpec(tkParent, mySig, cSig, &mi);
1850 report->error("Unable to define method instantiation");
1857 /**************************************************************************/
1858 void Assembler::EndEvent(void)
1860 Class* pClass = (m_pCurClass ? m_pCurClass : m_pModuleClass);
1861 if(m_pCurEvent->m_tkAddOn == 0)
1862 report->error("Event %s of class %s has no Add method. Event not emitted.",
1863 m_pCurEvent->m_szName,pClass->m_szFQN);
1864 else if(m_pCurEvent->m_tkRemoveOn == 0)
1865 report->error("Event %s of class %s has no Remove method. Event not emitted.",
1866 m_pCurEvent->m_szName,pClass->m_szFQN);
1869 pClass->m_EventDList.PUSH(m_pCurEvent);
1870 pClass->m_fNewMembers = TRUE;
1873 m_tkCurrentCVOwner = 0;
1874 m_pCustomDescrList = m_CustomDescrListStack.POP();
1877 void Assembler::ResetEvent(__inout_z __inout char* szName, mdToken typeSpec, DWORD dwAttr)
1879 if(strlen(szName) >= MAX_CLASSNAME_LENGTH)
1881 char c = szName[MAX_CLASSNAME_LENGTH-1];
1882 szName[MAX_CLASSNAME_LENGTH-1] = 0;
1883 report->error("Event '%s...' -- name too long (%d characters).\n",szName,strlen(szName));
1884 szName[MAX_CLASSNAME_LENGTH-1] = c;
1886 if((m_pCurEvent = new EventDescriptor))
1888 memset(m_pCurEvent,0,sizeof(EventDescriptor));
1889 m_pCurEvent->m_tdClass = m_pCurClass->m_cl;
1890 m_pCurEvent->m_szName = szName;
1891 m_pCurEvent->m_dwAttr = dwAttr;
1892 m_pCurEvent->m_tkEventType = typeSpec;
1893 m_pCurEvent->m_fNew = TRUE;
1894 m_tkCurrentCVOwner = 0;
1895 m_CustomDescrListStack.PUSH(m_pCustomDescrList);
1896 m_pCustomDescrList = &(m_pCurEvent->m_CustomDescrList);
1898 else report->error("Failed to allocate Event Descriptor\n");
1901 void Assembler::SetEventMethod(int MethodCode, mdToken tk)
1906 m_pCurEvent->m_tkAddOn = tk;
1909 m_pCurEvent->m_tkRemoveOn = tk;
1912 m_pCurEvent->m_tkFire = tk;
1915 m_pCurEvent->m_tklOthers.PUSH((mdToken*)(UINT_PTR)tk);
1919 /**************************************************************************/
1921 void Assembler::EndProp(void)
1923 Class* pClass = (m_pCurClass ? m_pCurClass : m_pModuleClass);
1924 pClass->m_PropDList.PUSH(m_pCurProp);
1925 pClass->m_fNewMembers = TRUE;
1927 m_tkCurrentCVOwner = 0;
1928 m_pCustomDescrList = m_CustomDescrListStack.POP();
1931 void Assembler::ResetProp(__inout_z __inout char * szName, BinStr* bsType, DWORD dwAttr, BinStr* pValue)
1933 DWORD cSig = bsType->length();
1934 COR_SIGNATURE* mySig = (COR_SIGNATURE *)(bsType->ptr());
1936 if(strlen(szName) >= MAX_CLASSNAME_LENGTH)
1938 char c = szName[MAX_CLASSNAME_LENGTH-1];
1939 szName[MAX_CLASSNAME_LENGTH-1] = 0;
1940 report->error("Property '%s...' -- name too long (%d characters).\n",szName,strlen(szName));
1941 szName[MAX_CLASSNAME_LENGTH-1] = c;
1943 m_pCurProp = new PropDescriptor;
1944 if(m_pCurProp == NULL)
1946 report->error("Failed to allocate Property Descriptor\n");
1949 memset(m_pCurProp,0,sizeof(PropDescriptor));
1950 m_pCurProp->m_tdClass = m_pCurClass->m_cl;
1951 m_pCurProp->m_szName = szName;
1952 m_pCurProp->m_dwAttr = dwAttr;
1953 m_pCurProp->m_fNew = TRUE;
1955 m_pCurProp->m_pSig = new COR_SIGNATURE[cSig];
1956 if(m_pCurProp->m_pSig == NULL)
1958 report->error("\nOut of memory!\n");
1961 memcpy(m_pCurProp->m_pSig,mySig,cSig);
1962 m_pCurProp->m_dwCSig = cSig;
1964 if(pValue && pValue->length())
1966 BYTE* pch = pValue->ptr();
1967 m_pCurProp->m_dwCPlusTypeFlag = (DWORD)(*pch);
1968 m_pCurProp->m_cbValue = pValue->length() - 1;
1969 m_pCurProp->m_pValue = (PVOID)(pch+1);
1970 if(m_pCurProp->m_dwCPlusTypeFlag == ELEMENT_TYPE_STRING) m_pCurProp->m_cbValue /= sizeof(WCHAR);
1971 m_pCurProp->m_dwAttr |= prHasDefault;
1975 m_pCurProp->m_dwCPlusTypeFlag = ELEMENT_TYPE_VOID;
1976 m_pCurProp->m_pValue = NULL;
1977 m_pCurProp->m_cbValue = 0;
1979 m_tkCurrentCVOwner = 0;
1980 m_CustomDescrListStack.PUSH(m_pCustomDescrList);
1981 m_pCustomDescrList = &(m_pCurProp->m_CustomDescrList);
1984 void Assembler::SetPropMethod(int MethodCode, mdToken tk)
1989 m_pCurProp->m_tkSet = tk;
1992 m_pCurProp->m_tkGet = tk;
1995 m_pCurProp->m_tklOthers.PUSH((mdToken*)(UINT_PTR)tk);
2000 /**************************************************************************/
2001 void Assembler::EmitInstrStringLiteral(Instr* instr, BinStr* literal, BOOL ConvertToUnicode, BOOL Swap /*=FALSE*/)
2003 DWORD DataLen = literal->length(),L;
2004 unsigned __int8 *pb = literal->ptr();
2007 WCHAR *UnicodeString;
2010 //report->warn("Zero length string emitted\n");
2011 ConvertToUnicode = FALSE;
2013 if(ConvertToUnicode)
2015 UnicodeString = (DataLen >= dwUniBuf) ? new WCHAR[DataLen+1] : &wzUniBuf[0];
2016 literal->appendInt8(0);
2017 pb = literal->ptr();
2018 // convert string to Unicode
2019 L = UnicodeString ? WszMultiByteToWideChar(g_uCodePage,0,(char*)pb,-1,UnicodeString,DataLen+1) : 0;
2022 const char* sz=NULL;
2024 switch(dw=GetLastError())
2026 case ERROR_INSUFFICIENT_BUFFER: sz = "ERROR_INSUFFICIENT_BUFFER"; break;
2027 case ERROR_INVALID_FLAGS: sz = "ERROR_INVALID_FLAGS"; break;
2028 case ERROR_INVALID_PARAMETER: sz = "ERROR_INVALID_PARAMETER"; break;
2029 case ERROR_NO_UNICODE_TRANSLATION: sz = "ERROR_NO_UNICODE_TRANSLATION"; break;
2031 if(sz) report->error("Failed to convert string '%s' to Unicode: %s\n",(char*)pb,sz);
2032 else report->error("Failed to convert string '%s' to Unicode: error 0x%08X\n",(char*)pb,dw);
2042 literal->appendInt8(0);
2043 pb = literal->ptr();
2046 UnicodeString = (WCHAR*)pb;
2047 L = DataLen/sizeof(WCHAR);
2051 SwapStringLength(UnicodeString, L);
2054 // Add the string data to the metadata, which will fold dupes.
2055 hr = m_pEmitter->DefineUserString(
2062 report->error("Failed to add user string using DefineUserString, hr=0x%08x, data: '%S'\n",
2069 if(m_fOBJ) m_pCurMethod->m_TRDList.PUSH(new TokenRelocDescr(m_CurPC,tk));
2071 EmitBytes((BYTE *)&tk,sizeof(mdToken));
2075 if(((void*)UnicodeString != (void*)pb)&&(DataLen >= dwUniBuf)) delete [] UnicodeString;
2076 instr->opcode = -1; // in case we got here with error
2079 /**************************************************************************/
2080 void Assembler::EmitInstrSig(Instr* instr, BinStr* sig)
2082 mdSignature MetadataToken;
2083 DWORD cSig = sig->length();
2084 COR_SIGNATURE* mySig = (COR_SIGNATURE *)(sig->ptr());
2086 if (FAILED(m_pEmitter->GetTokenFromSig(mySig, cSig, &MetadataToken)))
2088 report->error("Unable to convert signature to metadata token.\n");
2094 if(m_fOBJ) m_pCurMethod->m_TRDList.PUSH(new TokenRelocDescr(m_CurPC,MetadataToken));
2095 EmitBytes((BYTE *)&MetadataToken, sizeof(mdSignature));
2098 instr->opcode = -1; // in case we got here with error
2101 /**************************************************************************/
2102 void Assembler::EmitInstrSwitch(Instr* instr, Labels* targets)
2112 for(pLbls = targets, NumLabels = 0; pLbls; pLbls = pLbls->Next, NumLabels++);
2114 EmitBytes((BYTE *)&NumLabels,sizeof(int));
2115 DWORD PC_nextInstr = m_CurPC + 4*NumLabels;
2116 for(pLbls = targets; pLbls; pLbls = pLbls->Next)
2120 if((pLabel = m_pCurMethod->FindLabel(pLbls->Label)))
2122 offset = pLabel->m_PC - PC_nextInstr;
2123 if (m_fDisplayTraceOutput) report->msg("%d\n", offset);
2127 // defer until we find the label
2128 AddDeferredFixup(pLbls->Label, m_pCurOutputPos, PC_nextInstr, 4 /* pcrelsize */ );
2130 pLbls->Label = NULL;
2131 if (m_fDisplayTraceOutput) report->msg("forward label %s\n", pLbls->Label);
2136 offset = (UINT)(UINT_PTR)pLbls->Label;
2137 if (m_fDisplayTraceOutput) report->msg("%d\n", offset);
2139 EmitBytes((BYTE *)&offset, sizeof(UINT));
2144 /**************************************************************************/
2145 void Assembler::EmitLabel(__in __nullterminated char* label)
2147 _ASSERTE(m_pCurMethod);
2148 AddLabel(m_CurPC, label);
2150 /**************************************************************************/
2151 void Assembler::EmitDataLabel(__in __nullterminated char* label)
2153 AddGlobalLabel(label, m_pCurSection);
2156 /**************************************************************************/
2157 void Assembler::EmitBytes(BYTE *p, unsigned len)
2159 if(m_pCurOutputPos + len >= m_pEndOutputPos)
2161 size_t buflen = m_pEndOutputPos - m_pOutputBuffer;
2162 size_t newlen = buflen+(len/OUTPUT_BUFFER_INCREMENT + 1)*OUTPUT_BUFFER_INCREMENT;
2163 BYTE *pb = new BYTE[newlen];
2166 report->error("Failed to extend output buffer from %d to %d bytes. Aborting\n",
2170 size_t delta = pb - m_pOutputBuffer;
2173 GlobalFixup *pGSearch;
2174 for (i=0; (pSearch = m_pCurMethod->m_lstFixup.PEEK(i)); i++) pSearch->m_pBytes += delta;
2175 for (i=0; (pGSearch = m_lstGlobalFixup.PEEK(i)); i++) //need to move only those pointing to output buffer
2177 if((pGSearch->m_pReference >= m_pOutputBuffer)&&(pGSearch->m_pReference <= m_pEndOutputPos))
2178 pGSearch->m_pReference += delta;
2182 memcpy(pb,m_pOutputBuffer,m_CurPC);
2183 delete m_pOutputBuffer;
2184 m_pOutputBuffer = pb;
2185 m_pCurOutputPos = &m_pOutputBuffer[m_CurPC];
2186 m_pEndOutputPos = &m_pOutputBuffer[newlen];
2193 *m_pCurOutputPos = *p;
2196 SET_UNALIGNED_VAL16(m_pCurOutputPos, GET_UNALIGNED_16(p));
2199 SET_UNALIGNED_VAL32(m_pCurOutputPos, GET_UNALIGNED_32(p));
2202 SET_UNALIGNED_VAL64(m_pCurOutputPos, GET_UNALIGNED_64(p));
2209 m_pCurOutputPos += len;
2212 /**************************************************************************/
2213 BinStr* Assembler::EncodeSecAttr(__in __nullterminated char* szReflName, BinStr* pbsSecAttrBlob, unsigned nProps)
2217 // Emit MemberRef for .ctor
2218 mdToken tkMscorlib = m_fIsMscorlib ? 1 : GetAsmRef("mscorlib");
2220 BinStr *pbsSig = new BinStr();
2222 strcpy(buffer,"System.Security.Permissions.SecurityAction");
2223 mdToken tkSecAction = ResolveClassRef(tkMscorlib,buffer, NULL);
2225 pbsSig->appendInt8(IMAGE_CEE_CS_CALLCONV_HASTHIS);
2226 pbsSig->appendInt8(1); //corEmitInt(pbsSig,1);
2227 pbsSig->appendInt8(ELEMENT_TYPE_VOID);
2228 pbsSig->appendInt8(ELEMENT_TYPE_VALUETYPE);
2229 cnt = CorSigCompressToken(tkSecAction, pbsSig->getBuff(5));
2230 pbsSig->remove(5 - cnt);
2232 char* szName = new char[16];
2233 strcpy(szName,".ctor");
2234 MakeMemberRef(tkSecAttr,szName,pbsSig);
2237 // build the blob As BinStr
2238 unsigned L = (unsigned) strlen(szReflName);
2240 BinStr* pbsRet = new BinStr();
2241 // encode the Reflection name length
2242 cnt = CorSigCompressData(L, pbsRet->getBuff(5));
2243 pbsRet->remove(5 - cnt);
2245 if((pb = pbsRet->getBuff(L)) != NULL)
2246 memcpy(pb,szReflName,L);
2247 // find out the size of compressed nProps
2248 cnt = CorSigCompressData(nProps, pbsRet->getBuff(5));
2251 unsigned nSize = cnt + pbsSecAttrBlob->length();
2252 cnt = CorSigCompressData(nSize, pbsRet->getBuff(5));
2253 pbsRet->remove(5 - cnt);
2254 // actually encode nProps
2255 cnt = CorSigCompressData(nProps, pbsRet->getBuff(5));
2256 pbsRet->remove(5 - cnt);
2257 // append the props/values blob
2258 pbsRet->append(pbsSecAttrBlob);
2259 delete pbsSecAttrBlob;
2262 /**************************************************************************/
2263 void Assembler::EmitSecurityInfo(mdToken token,
2264 PermissionDecl* pPermissions,
2265 PermissionSetDecl* pPermissionSets)
2267 PermissionDecl *pPerm, *pPermNext;
2268 PermissionSetDecl *pPset, *pPsetNext;
2269 unsigned uCount = 0;
2270 COR_SECATTR *pAttrs;
2273 mdTypeRef tkTypeRef;
2276 DWORD dwErrorIndex = 0;
2280 for (pPerm = pPermissions; pPerm; pPerm = pPerm->m_Next)
2283 _ASSERTE(uCount > 0);
2284 // uCount is expected to be positive all the time. The if statement is here to please prefast.
2287 if((pAttrs = new COR_SECATTR[uCount])==NULL)
2289 report->error("\nOut of memory!\n");
2293 mdToken tkMscorlib = m_fIsMscorlib ? 1 : GetAsmRef("mscorlib");
2294 tkTypeRef = ResolveClassRef(tkMscorlib,"System.Security.Permissions.SecurityAction", NULL);
2295 for (pPerm = pPermissions, i = 0; pPerm; pPerm = pPermNext, i++) {
2296 pPermNext = pPerm->m_Next;
2298 pSig = new BinStr();
2299 pSig->appendInt8(IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS);
2300 pSig->appendInt8(1);
2301 pSig->appendInt8(ELEMENT_TYPE_VOID);
2302 pSig->appendInt8(ELEMENT_TYPE_VALUETYPE);
2303 uLength = CorSigCompressToken(tkTypeRef, pSig->getBuff(5));
2304 pSig->remove(5 - uLength);
2306 uLength = (unsigned)strlen(COR_CTOR_METHOD_NAME) + 1;
2307 if((szMemberName = new char[uLength]))
2309 memcpy(szMemberName, COR_CTOR_METHOD_NAME, uLength);
2310 pAttrs[i].tkCtor = MakeMemberRef(pPerm->m_TypeSpec, szMemberName, pSig);
2311 pAttrs[i].pCustomAttribute = (const void *)pPerm->m_Blob;
2312 pAttrs[i].cbCustomAttribute = pPerm->m_BlobLength;
2314 else report->error("\nOut of memory!\n");
2317 if (FAILED(m_pEmitter->DefineSecurityAttributeSet(token,
2322 _ASSERT(uCount >= dwErrorIndex);
2323 if (dwErrorIndex == uCount)
2325 report->error("Failed to define security attribute set for 0x%08X\n", token);
2329 report->error("Failed to define security attribute set for 0x%08X\n (error in permission %u)\n",
2330 token, uCount - dwErrorIndex);
2334 for (pPerm = pPermissions, i = 0; pPerm; pPerm = pPermNext, i++) {
2335 pPermNext = pPerm->m_Next;
2341 for (pPset = pPermissionSets; pPset; pPset = pPsetNext) {
2342 pPsetNext = pPset->m_Next;
2343 if(FAILED(m_pEmitter->DefinePermissionSet(token,
2345 pPset->m_Value->ptr(),
2346 pPset->m_Value->length(),
2348 report->error("Failed to define security permission set for 0x%08X\n", token);
2353 void Assembler::AddMethodImpl(mdToken tkImplementedTypeSpec, __in __nullterminated char* szImplementedName, BinStr* pImplementedSig,
2354 mdToken tkImplementingTypeSpec, __in_opt __nullterminated char* szImplementingName, BinStr* pImplementingSig)
2358 MethodImplDescriptor* pMID = new MethodImplDescriptor;
2359 pMID->m_fNew = TRUE;
2362 report->error("Failed to allocate MethodImpl Descriptor\n");
2365 pMID->m_tkDefiningClass = m_pCurClass->m_cl;
2366 if(szImplementingName) //called from class scope, overriding method specified
2368 pMID->m_tkImplementedMethod = MakeMemberRef(tkImplementedTypeSpec,szImplementedName,pImplementedSig);
2369 pMID->m_tkImplementingMethod = MakeMemberRef(tkImplementingTypeSpec,szImplementingName,pImplementingSig);
2371 else //called from method scope, use current method as overriding
2375 if (pImplementedSig == NULL)
2377 pImplementedSig = new BinStr();
2378 memcpy(pImplementedSig->getBuff(m_pCurMethod->m_dwMethodCSig), m_pCurMethod->m_pMethodSig,m_pCurMethod->m_dwMethodCSig);
2380 pMID->m_tkImplementedMethod = MakeMemberRef(tkImplementedTypeSpec,szImplementedName,pImplementedSig);
2381 pMID->m_tkImplementingMethod = 0;
2383 m_pCurMethod->m_MethodImplDList.PUSH(pMID); // copy goes to method's own list (ptr only)
2387 report->error("No overriding method specified");
2392 m_MethodImplDList.PUSH(pMID);
2395 report->error(".override directive outside class scope");
2397 // source file name paraphernalia
2398 void Assembler::SetSourceFileName(__in __nullterminated char* szName)
2404 if(strcmp(m_szSourceFileName,szName))
2406 strcpy_s(m_szSourceFileName,MAX_FILENAME_LENGTH*3+1,szName);
2407 WszMultiByteToWideChar(g_uCodePage,0,szName,-1,m_wzSourceFileName,MAX_FILENAME_LENGTH);
2413 while((pDW = m_DocWriterList.PEEK(i++)) != NULL)
2415 if(!strcmp(szName,pDW->Name)) break;
2419 m_pSymDocument = pDW->pWriter;
2422 else if(m_pSymWriter)
2425 WszMultiByteToWideChar(g_uCodePage,0,szName,-1,wzUniBuf,dwUniBuf);
2426 if(FAILED(hr=m_pSymWriter->DefineDocument(wzUniBuf,&m_guidLang,
2427 &m_guidLangVendor,&m_guidDoc,&m_pSymDocument)))
2429 m_pSymDocument = NULL;
2430 report->error("Failed to define a document writer");
2432 if((pDW = new DocWriter()) != NULL)
2435 pDW->pWriter = m_pSymDocument;
2436 m_DocWriterList.PUSH(pDW);
2440 report->error("Out of memory");
2444 else delete [] szName;
2446 else delete [] szName;
2448 else delete [] szName;
2451 void Assembler::SetSourceFileName(BinStr* pbsName)
2454 if(pbsName && (L = (ULONG)(pbsName->length())))
2456 pbsName->appendInt8(0);
2457 char* sz = new char[L+1];
2458 memcpy(sz,pbsName->ptr(),L+1);
2459 SetSourceFileName(sz);