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