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: zapsig.cpp
6//
7// Signature encoding for zapper (ngen)
8//
9
10// ===========================================================================
11
12
13#include "common.h"
14#ifdef FEATURE_PREJIT
15#include "zapsig.h"
16#include "typedesc.h"
17#include "compile.h"
18#include "sigbuilder.h"
19
20#ifndef DACCESS_COMPILE
21
22BOOL ZapSig::GetSignatureForTypeDesc(TypeDesc * desc, SigBuilder * pSigBuilder)
23{
24 CONTRACTL
25 {
26 THROWS;
27 GC_TRIGGERS;
28 }
29 CONTRACTL_END
30
31 CorElementType elemType = desc->GetInternalCorElementType();
32
33 if (elemType == ELEMENT_TYPE_VALUETYPE)
34 {
35 // convert to ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG so that the right
36 // thing will happen in code:SigPointer.GetTypeHandleThrowing
37 elemType = (CorElementType) ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG;
38 }
39 else if (elemType == ELEMENT_TYPE_VAR || elemType == ELEMENT_TYPE_MVAR)
40 {
41 // Enable encoding of type variables for NGen signature only. IBC toolchain is not aware of them yet.
42 if (context.externalTokens == ZapSig::NormalTokens)
43 elemType = (CorElementType) ELEMENT_TYPE_VAR_ZAPSIG;
44 }
45
46 pSigBuilder->AppendElementType(elemType);
47
48 if (desc->HasTypeParam())
49 {
50 if (!this->GetSignatureForTypeHandle(desc->GetTypeParam(), pSigBuilder))
51 return FALSE;
52
53 if (elemType == ELEMENT_TYPE_ARRAY)
54 {
55 ArrayTypeDesc *pArrayDesc = dac_cast<PTR_ArrayTypeDesc>(desc);
56 _ASSERTE(pArrayDesc->GetRank() != 0);
57 pSigBuilder->AppendData(pArrayDesc->GetRank());
58 pSigBuilder->AppendData(0);
59 pSigBuilder->AppendData(0);
60 }
61 }
62 else
63 {
64 switch ((DWORD)elemType)
65 {
66 case ELEMENT_TYPE_FNPTR:
67 {
68 FnPtrTypeDesc *pTD = dac_cast<PTR_FnPtrTypeDesc>(desc);
69
70 // Emit calling convention
71 pSigBuilder->AppendByte(pTD->GetCallConv());
72
73 // number of args
74 unsigned numArgs = pTD->GetNumArgs();
75 pSigBuilder->AppendData(numArgs);
76
77 // return type and args
78 TypeHandle *retAndArgTypes = pTD->GetRetAndArgTypesPointer();
79 for (DWORD i = 0; i <= numArgs; i++)
80 {
81 TypeHandle th = retAndArgTypes[i];
82 // This should be a consequence of the type key being restored
83 CONSISTENCY_CHECK(!th.IsNull() && !th.IsEncodedFixup());
84 if (!this->GetSignatureForTypeHandle(th, pSigBuilder))
85 return FALSE;
86 }
87 }
88 break;
89
90 case ELEMENT_TYPE_MVAR:
91 // _ASSERTE(!"Cannot encode ET_MVAR in a ZapSig");
92 return FALSE;
93
94 case ELEMENT_TYPE_VAR:
95 // _ASSERTE(!"Cannot encode ET_VAR in a ZapSig");
96 return FALSE;
97
98 case ELEMENT_TYPE_VAR_ZAPSIG:
99 {
100 TypeVarTypeDesc * pTypeVarDesc = dac_cast<PTR_TypeVarTypeDesc>(desc);
101 Module * pVarTypeModule = pTypeVarDesc->GetModule();
102 if (pVarTypeModule != this->context.pInfoModule)
103 {
104 DWORD index = (*this->pfnEncodeModule)(this->context.pModuleContext, pVarTypeModule);
105
106 if (index == ENCODE_MODULE_FAILED)
107 return FALSE;
108
109 // emit the ET_MODULE_ZAPSIG escape
110 pSigBuilder->AppendElementType((CorElementType) ELEMENT_TYPE_MODULE_ZAPSIG);
111 // emit the module index
112 pSigBuilder->AppendData(index);
113 }
114 pSigBuilder->AppendData(RidFromToken(pTypeVarDesc->GetToken()));
115 break;
116 }
117
118 default:
119 _ASSERTE(!"Bad type");
120 return FALSE;
121 }
122 }
123
124 return TRUE;
125}
126
127
128// Create a signature for a typeHandle
129// It can be decoded using MetaSig::GetTypeHandleThrowing
130// The tokens are espressed relative to this->pInfoModule
131// When handle.GetModule() != this->pInfoModule), we escape the signature
132// with an ELEMENT_TYPE_MODULE_ZAPSIG <id-num> <token> to encode
133// a temporary change of module
134//
135// Returns the number of characters written into the buffer.
136// If buffer and bufferMax are NULL, it returns the number of
137// characters that would have been written.
138// If the buffer isn't big enough it doesn't write past bufferMax
139// A return value of 0 indidates a failure to encode the signature
140//
141BOOL ZapSig::GetSignatureForTypeHandle(TypeHandle handle,
142 SigBuilder * pSigBuilder)
143{
144 CONTRACTL
145 {
146 THROWS;
147 GC_TRIGGERS;
148
149 PRECONDITION(CheckPointer(handle));
150 PRECONDITION(CheckPointer(this->context.pInfoModule));
151 PRECONDITION(!handle.HasUnrestoredTypeKey());
152 MODE_ANY;
153 }
154 CONTRACTL_END
155
156 if (handle.IsTypeDesc())
157 return GetSignatureForTypeDesc(handle.AsTypeDesc(), pSigBuilder);
158
159 MethodTable *pMT = handle.AsMethodTable();
160
161 // Can we encode the type using a short ET encoding?
162 //
163 CorElementType elemType = TryEncodeUsingShortcut(pMT);
164 if (elemType != ELEMENT_TYPE_END)
165 {
166 _ASSERTE(pMT->IsTypicalTypeDefinition());
167
168 // Check for an array type and encode that we are dealing with a MethodTable representation
169 if (elemType == ELEMENT_TYPE_SZARRAY || elemType == ELEMENT_TYPE_ARRAY)
170 {
171 pSigBuilder->AppendElementType((CorElementType)ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG);
172 pSigBuilder->AppendElementType(elemType);
173
174 TypeHandle elementType = pMT->GetApproxArrayElementTypeHandle();
175 if (!this->GetSignatureForTypeHandle(elementType, pSigBuilder))
176 return FALSE;
177
178 if (elemType == ELEMENT_TYPE_ARRAY)
179 {
180 pSigBuilder->AppendData(pMT->GetRank());
181 pSigBuilder->AppendData(0);
182 pSigBuilder->AppendData(0);
183 }
184 }
185 else
186 {
187 pSigBuilder->AppendElementType(elemType);
188 }
189
190 return TRUE;
191 }
192
193 // We could not encode the type using a short encoding
194 // and we have a handle that represents a Class or ValueType
195
196 // We may need to emit an out-of-module escape sequence
197 //
198 Module *pTypeHandleModule = pMT->GetModule_NoLogging();
199
200 // If the type handle's module is different that the this->pInfoModule
201 // we will need to add an out-of-module escape for the type
202 //
203 DWORD index = 0;
204 mdToken token = pMT->GetCl_NoLogging();
205#ifdef FEATURE_NATIVE_IMAGE_GENERATION
206 if (pTypeHandleModule != this->context.pInfoModule && !pTypeHandleModule->IsInCurrentVersionBubble())
207 {
208 pTypeHandleModule = GetAppDomain()->ToCompilationDomain()->GetTargetModule();
209 token = pTypeHandleModule->LookupTypeRefByMethodTable(pMT);
210 }
211#endif
212 if (pTypeHandleModule != this->context.pInfoModule)
213 {
214 // During IBC profiling this calls
215 // code:Module.EncodeModuleHelper
216 // During ngen this calls
217 // code:ZapImportTable.EncodeModuleHelper)
218 //
219 index = (*this->pfnEncodeModule)(this->context.pModuleContext, pTypeHandleModule);
220
221 if (index == ENCODE_MODULE_FAILED)
222 return FALSE;
223
224 // emit the ET_MODULE_ZAPSIG escape
225 pSigBuilder->AppendElementType((CorElementType) ELEMENT_TYPE_MODULE_ZAPSIG);
226 // emit the module index
227 pSigBuilder->AppendData(index);
228 }
229
230 // Remember if we have an instantiated generic type
231 bool fNeedsInstantiation = pMT->HasInstantiation() && !pMT->IsGenericTypeDefinition();
232
233 // We possibly have an instantiated generic type
234 if (fNeedsInstantiation)
235 {
236 pSigBuilder->AppendElementType(ELEMENT_TYPE_GENERICINST);
237 }
238
239 // Beware of enums! Can't use GetInternalCorElementType() here.
240 pSigBuilder->AppendElementType(pMT->IsValueType() ? ELEMENT_TYPE_VALUETYPE : ELEMENT_TYPE_CLASS);
241
242 _ASSERTE(!IsNilToken(token));
243 if (IsNilToken(token))
244 return FALSE;
245
246 if ((index != 0) && (this->pfnTokenDefinition != NULL))
247 {
248 //
249 // We do not want to log the metadata lookups that we perform here
250 //
251 IBCLoggingDisabler disableLogging;
252
253 // During IBC profiling this calls
254 // code:Module::TokenDefinitionHelper
255 (*this->pfnTokenDefinition)(this->context.pModuleContext, pTypeHandleModule, index, &token);
256
257 // ibcExternalType tokens are actually encoded as mdtTypeDef tokens in the signature
258 _ASSERT(TypeFromToken(token) == ibcExternalType);
259 token = TokenFromRid(RidFromToken(token), mdtTypeDef);
260 }
261
262 pSigBuilder->AppendToken(token);
263
264 if (fNeedsInstantiation)
265 {
266 pSigBuilder->AppendData(pMT->GetNumGenericArgs());
267 Instantiation inst = pMT->GetInstantiation();
268 for (DWORD i = 0; i < inst.GetNumArgs(); i++)
269 {
270 TypeHandle t = inst[i];
271 CONSISTENCY_CHECK(!t.IsNull() && !t.IsEncodedFixup());
272 if (!this->GetSignatureForTypeHandle(t, pSigBuilder))
273 return FALSE;
274 }
275 }
276 return TRUE;
277}
278
279#endif // #ifndef DACCESS_COMPILE
280
281//
282// Returns element type when the typeHandle can be encoded using
283// using a single CorElementType value
284// This includes using ELEMENT_TYPE_CANON_ZAPSIG for the System.__Canon type
285//
286/*static */ CorElementType ZapSig::TryEncodeUsingShortcut(/* in */ MethodTable * pMT)
287{
288 LIMITED_METHOD_CONTRACT;
289
290 CorElementType elemType = ELEMENT_TYPE_END; // An illegal value that we check for later
291
292 // Set elemType to a shortcut encoding whenever possible
293 //
294 if (pMT->IsTruePrimitive())
295 elemType = pMT->GetInternalCorElementType();
296 else if (pMT == g_pObjectClass)
297 elemType = ELEMENT_TYPE_OBJECT;
298 else if (pMT == g_pStringClass)
299 elemType = ELEMENT_TYPE_STRING;
300 else if (pMT == g_pCanonMethodTableClass)
301 elemType = (CorElementType) ELEMENT_TYPE_CANON_ZAPSIG;
302 else if (pMT->IsArray())
303 elemType = pMT->GetInternalCorElementType(); // either ELEMENT_TYPE_SZARRAY or ELEMENT_TYPE_ARRAY
304
305 return elemType;
306}
307
308//
309// Compare a metadata signature element with a type handle
310// The type handle must have a fully restored type key, which in turn means that modules for all of its
311// components are loaded (e.g. type arguments to an instantiated type).
312//
313// Hence we can do the signature comparison without incurring any loads or restores.
314//
315/*static*/ BOOL ZapSig::CompareSignatureToTypeHandle(PCCOR_SIGNATURE pSig,
316 Module* pModule,
317 TypeHandle handle,
318 const ZapSig::Context * pZapSigContext)
319{
320 CONTRACT(BOOL)
321 {
322 NOTHROW;
323 GC_NOTRIGGER;
324 MODE_ANY;
325 FORBID_FAULT;
326 PRECONDITION(CheckPointer(pModule));
327 PRECONDITION(CheckPointer(pZapSigContext));
328 PRECONDITION(CheckPointer(pZapSigContext->pModuleContext));
329 PRECONDITION(CheckPointer(pZapSigContext->pInfoModule));
330 PRECONDITION(CheckPointer(handle));
331 PRECONDITION(CheckPointer(pSig));
332 PRECONDITION(!handle.HasUnrestoredTypeKey());
333 }
334 CONTRACT_END
335
336 mdToken tk;
337
338 //
339 // pOrigModule is the original module that contained this ZapSig
340 //
341 Module * pOrigModule = pZapSigContext->pInfoModule;
342 CorElementType sigType = CorSigUncompressElementType(pSig);
343 CorElementType handleType = handle.GetSignatureCorElementType();
344
345 switch ((DWORD)sigType)
346 {
347 default:
348 {
349 // Unknown type!
350 _ASSERTE(!"Unknown type in ZapSig::CompareSignatureToTypeHandle");
351 RETURN(FALSE);
352 }
353
354 case ELEMENT_TYPE_MODULE_ZAPSIG:
355 {
356 DWORD ix = CorSigUncompressData(pSig);
357 CONTRACT_VIOLATION(ThrowsViolation|GCViolation);
358 pModule = pZapSigContext->GetZapSigModule()->GetModuleFromIndexIfLoaded(ix);
359 if (pModule == NULL)
360 RETURN FALSE;
361 else
362 RETURN(CompareSignatureToTypeHandle(pSig, pModule, handle, pZapSigContext));
363 }
364
365 case ELEMENT_TYPE_U:
366 case ELEMENT_TYPE_I:
367 case ELEMENT_TYPE_VOID:
368 case ELEMENT_TYPE_I1:
369 case ELEMENT_TYPE_U1:
370 case ELEMENT_TYPE_I2:
371 case ELEMENT_TYPE_U2:
372 case ELEMENT_TYPE_I4:
373 case ELEMENT_TYPE_U4:
374 case ELEMENT_TYPE_I8:
375 case ELEMENT_TYPE_U8:
376 case ELEMENT_TYPE_R4:
377 case ELEMENT_TYPE_R8:
378 case ELEMENT_TYPE_BOOLEAN:
379 case ELEMENT_TYPE_CHAR:
380 case ELEMENT_TYPE_TYPEDBYREF:
381 RETURN(sigType == handleType);
382
383 case ELEMENT_TYPE_STRING:
384 RETURN(handle == TypeHandle(g_pStringClass));
385
386 case ELEMENT_TYPE_OBJECT:
387 RETURN(handle == TypeHandle(g_pObjectClass));
388
389 case ELEMENT_TYPE_CANON_ZAPSIG:
390 RETURN(handle == TypeHandle(g_pCanonMethodTableClass));
391
392 case ELEMENT_TYPE_VAR:
393 case ELEMENT_TYPE_MVAR:
394 {
395 if (sigType != handleType)
396 RETURN(FALSE);
397
398 unsigned varNum = CorSigUncompressData(pSig);
399 RETURN(varNum == (dac_cast<PTR_TypeVarTypeDesc>(handle.AsTypeDesc())->GetIndex()));
400 }
401
402 case ELEMENT_TYPE_VAR_ZAPSIG:
403 {
404 if (!handle.IsGenericVariable())
405 RETURN(FALSE);
406
407 TypeVarTypeDesc *pTypeVarTypeDesc = handle.AsGenericVariable();
408
409 unsigned rid = CorSigUncompressData(pSig);
410 RETURN(TokenFromRid(rid, mdtGenericParam) == pTypeVarTypeDesc->GetToken() && pModule == pTypeVarTypeDesc->GetModule());
411 }
412
413 // These take an additional argument, which is the element type
414 case ELEMENT_TYPE_SZARRAY:
415 case ELEMENT_TYPE_PTR:
416 case ELEMENT_TYPE_BYREF:
417 {
418 if (sigType != handleType)
419 RETURN(FALSE);
420
421 RETURN (CompareSignatureToTypeHandle(pSig, pModule, handle.GetTypeParam(), pZapSigContext));
422 }
423
424 case ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG:
425 {
426 if (handle.IsTypeDesc() || !handle.AsMethodTable()->IsArray())
427 RETURN(FALSE);
428
429 RETURN (CompareSignatureToTypeHandle(pSig, pModule, handle, pZapSigContext));
430 }
431
432 case ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG:
433 {
434 sigType = CorSigUncompressElementType(pSig);
435 _ASSERTE(sigType == ELEMENT_TYPE_VALUETYPE);
436
437 if (!handle.IsNativeValueType()) RETURN(FALSE);
438 } // fall-through
439
440 case ELEMENT_TYPE_VALUETYPE:
441 case ELEMENT_TYPE_CLASS:
442 {
443 CorSigUncompressToken(pSig, &tk);
444 if (TypeFromToken(tk) == mdtTypeRef)
445 {
446 BOOL resolved = FALSE;
447 EX_TRY
448 {
449 ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
450 resolved = ClassLoader::ResolveTokenToTypeDefThrowing(pModule, tk, &pModule, &tk, Loader::DontLoad);
451 }
452 EX_CATCH
453 {
454 }
455 EX_END_CATCH(SwallowAllExceptions);
456 if (!resolved)
457 RETURN(FALSE);
458 }
459 _ASSERTE(TypeFromToken(tk) == mdtTypeDef);
460 RETURN (sigType == handleType && !handle.HasInstantiation() && pModule == handle.GetModule() && handle.GetCl() == tk);
461 }
462
463 case ELEMENT_TYPE_FNPTR:
464 {
465 if (sigType != handleType)
466 RETURN(FALSE);
467
468 FnPtrTypeDesc *pTD = handle.AsFnPtrType();
469 DWORD callConv = CorSigUncompressData(pSig);
470 if (callConv != pTD->GetCallConv())
471 RETURN(FALSE);
472
473 DWORD numArgs = CorSigUncompressData(pSig);
474 if (numArgs != pTD->GetNumArgs())
475 RETURN(FALSE);
476
477 {
478 CONTRACT_VIOLATION(ThrowsViolation|GCViolation);
479
480 for (DWORD i = 0; i <= numArgs; i++)
481 {
482 SigPointer sp(pSig);
483 if (!CompareSignatureToTypeHandle(pSig, pOrigModule, pTD->GetRetAndArgTypes()[i], pZapSigContext))
484 RETURN(FALSE);
485 if (FAILED(sp.SkipExactlyOne()))
486 {
487 RETURN(FALSE);
488 }
489 pSig = sp.GetPtr();
490 }
491 }
492 break;
493 }
494
495 case ELEMENT_TYPE_GENERICINST:
496 {
497 if (!handle.HasInstantiation())
498 RETURN(FALSE);
499
500 sigType = CorSigUncompressElementType(pSig);
501 if (sigType != handleType)
502 RETURN(FALSE);
503
504 pSig += CorSigUncompressToken(pSig, &tk);
505 if (TypeFromToken(tk) == mdtTypeRef)
506 {
507 BOOL resolved = FALSE;
508 EX_TRY
509 {
510 ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
511 resolved = ClassLoader::ResolveTokenToTypeDefThrowing(pModule, tk, &pModule, &tk, Loader::DontLoad);
512 }
513 EX_CATCH
514 {
515 }
516 EX_END_CATCH(SwallowAllExceptions);
517 if (!resolved)
518 RETURN(FALSE);
519 }
520 _ASSERTE(TypeFromToken(tk) == mdtTypeDef);
521 if (pModule != handle.GetModule() || tk != handle.GetCl())
522 RETURN(FALSE);
523
524 DWORD numGenericArgs = CorSigUncompressData(pSig);
525
526 if (numGenericArgs != handle.GetNumGenericArgs())
527 RETURN(FALSE);
528
529 Instantiation inst = handle.GetInstantiation();
530 for (DWORD i = 0; i < inst.GetNumArgs(); i++)
531 {
532 SigPointer sp(pSig);
533 if (!CompareSignatureToTypeHandle(pSig, pOrigModule, inst[i], pZapSigContext))
534 RETURN(FALSE);
535 if (FAILED(sp.SkipExactlyOne()))
536 {
537 RETURN(FALSE);
538 }
539 pSig = sp.GetPtr();
540 }
541 break;
542 }
543
544 case ELEMENT_TYPE_ARRAY:
545 {
546 if (sigType != handleType)
547 RETURN(FALSE);
548
549 if (!CompareSignatureToTypeHandle(pSig, pModule, handle.GetTypeParam(), pZapSigContext))
550 RETURN(FALSE);
551 SigPointer sp(pSig);
552 if (FAILED(sp.SkipExactlyOne()))
553 RETURN(FALSE);
554
555 DWORD rank;
556 if (FAILED(sp.GetData(&rank)))
557 RETURN(FALSE);
558
559 if (rank != handle.AsArray()->GetRank())
560 RETURN(FALSE);
561
562 break;
563 }
564 }
565
566 RETURN(TRUE);
567}
568
569/*static*/
570BOOL ZapSig::CompareFixupToTypeHandle(Module * pModule, TADDR fixup, TypeHandle handle)
571{
572 CONTRACTL
573 {
574 NOTHROW;
575 GC_NOTRIGGER;
576 MODE_ANY;
577 FORBID_FAULT;
578 PRECONDITION(CORCOMPILE_IS_POINTER_TAGGED(fixup));
579 PRECONDITION(CheckPointer(pModule));
580 }
581 CONTRACTL_END
582
583 Module *pDefiningModule;
584 PCCOR_SIGNATURE pSig = pModule->GetEncodedSigIfLoaded(CORCOMPILE_UNTAG_TOKEN(fixup), &pDefiningModule);
585 if (pDefiningModule == NULL)
586 return FALSE;
587
588 ZapSig::Context zapSigContext(pDefiningModule, pModule);
589 return ZapSig::CompareSignatureToTypeHandle(pSig, pDefiningModule, handle, &zapSigContext);
590}
591
592/*static*/
593BOOL ZapSig::CompareTypeHandleFieldToTypeHandle(TypeHandle *pTypeHnd, TypeHandle typeHnd2)
594{
595 CONTRACTL
596 {
597 NOTHROW;
598 GC_NOTRIGGER;
599 MODE_ANY;
600 FORBID_FAULT;
601 PRECONDITION(CheckPointer(pTypeHnd));
602 PRECONDITION(CheckPointer(typeHnd2));
603 PRECONDITION(!CORCOMPILE_IS_POINTER_TAGGED((SIZE_T) typeHnd2.AsPtr()));
604 }
605 CONTRACTL_END
606
607 // Ensure that the compiler won't fetch the value twice
608 SIZE_T fixup = VolatileLoadWithoutBarrier((SIZE_T *)pTypeHnd);
609
610 if (CORCOMPILE_IS_POINTER_TAGGED(fixup))
611 {
612 Module *pContainingModule = ExecutionManager::FindZapModule(dac_cast<TADDR>(pTypeHnd));
613 CONSISTENCY_CHECK(pContainingModule != NULL);
614
615 Module *pDefiningModule;
616 PCCOR_SIGNATURE pSig = pContainingModule->GetEncodedSigIfLoaded(CORCOMPILE_UNTAG_TOKEN(fixup), &pDefiningModule);
617 if (pDefiningModule == NULL)
618 return FALSE;
619 else
620 {
621 ZapSig::Context zapSigContext(pDefiningModule, pContainingModule);
622 ZapSig::Context * pZapSigContext = &zapSigContext;
623 return CompareSignatureToTypeHandle(pSig, pDefiningModule, typeHnd2, pZapSigContext);
624 }
625 }
626 else
627 return TypeHandle::FromTAddr(fixup) == typeHnd2;
628}
629
630#ifndef DACCESS_COMPILE
631Module *ZapSig::DecodeModuleFromIndex(Module *fromModule,
632 DWORD index)
633{
634 CONTRACTL
635 {
636 THROWS;
637 GC_TRIGGERS;
638 MODE_ANY;
639 }
640 CONTRACTL_END;
641
642 Assembly *pAssembly = NULL;
643
644 if (index == 0)
645 {
646 pAssembly = fromModule->GetAssembly();
647 }
648 else
649 {
650 if (index < fromModule->GetAssemblyRefMax())
651 {
652 pAssembly = fromModule->LoadAssembly(GetAppDomain(), RidToToken(index, mdtAssemblyRef))->GetAssembly();
653 }
654 else
655 {
656 index -= fromModule->GetAssemblyRefMax();
657
658 pAssembly = fromModule->GetNativeMetadataAssemblyRefFromCache(index);
659
660 if(pAssembly == NULL)
661 {
662 AssemblySpec spec;
663 spec.InitializeSpec(TokenFromRid(index, mdtAssemblyRef),
664 fromModule->GetNativeAssemblyImport(),
665 NULL);
666
667 pAssembly = spec.LoadAssembly(FILE_LOADED);
668
669 fromModule->SetNativeMetadataAssemblyRefInCache(index, pAssembly);
670 }
671 }
672 }
673
674 return pAssembly->GetManifestModule();
675}
676
677Module *ZapSig::DecodeModuleFromIndexIfLoaded(Module *fromModule,
678 DWORD index)
679{
680 CONTRACTL
681 {
682 NOTHROW;
683 GC_NOTRIGGER;
684 FORBID_FAULT;
685 SO_INTOLERANT;
686 }
687 CONTRACTL_END;
688
689 Assembly *pAssembly = NULL;
690 mdAssemblyRef tkAssemblyRef;
691
692 if (index == 0)
693 pAssembly = fromModule->GetAssembly();
694 else
695 {
696 if (index < fromModule->GetAssemblyRefMax())
697 {
698 tkAssemblyRef = RidToToken(index, mdtAssemblyRef);
699 pAssembly = fromModule->GetAssemblyIfLoaded(tkAssemblyRef);
700 }
701 else
702 {
703 index -= fromModule->GetAssemblyRefMax();
704 tkAssemblyRef = RidToToken(index, mdtAssemblyRef);
705 IMDInternalImport * pMDImportOverride = fromModule->GetNativeAssemblyImport(FALSE);
706 if (pMDImportOverride != NULL)
707 {
708 CHAR szFullName[MAX_CLASS_NAME + 1];
709 LPCSTR szWinRtNamespace = NULL;
710 LPCSTR szWinRtClassName = NULL;
711
712 BOOL fValidAssemblyRef = TRUE;
713 LPCSTR pAssemblyName;
714 DWORD dwFlags;
715 if (FAILED(pMDImportOverride->GetAssemblyRefProps(tkAssemblyRef,
716 NULL,
717 NULL,
718 &pAssemblyName,
719 NULL,
720 NULL,
721 NULL,
722 &dwFlags)))
723 { // Unexpected failure reading MetaData
724 fValidAssemblyRef = FALSE;
725 }
726
727 if (fValidAssemblyRef && IsAfContentType_WindowsRuntime(dwFlags))
728 {
729 // Find the encoded type name
730 LPCSTR pTypeName = NULL;
731 if (pAssemblyName != NULL)
732 pTypeName = strchr(pAssemblyName, '!');
733
734 if (pTypeName != NULL)
735 {
736 pTypeName++;
737 // pTypeName now contains the full type name (namespace + name)
738
739 strcpy_s(szFullName, _countof(szFullName), pTypeName);
740 LPSTR pszName = strrchr(szFullName, '.');
741
742 // WinRT types must have a namespace
743 if (pszName != NULL)
744 {
745 // Replace . between namespace and name with null terminator.
746 // This breaks the string into a namespace and name pair.
747 *pszName = '\0';
748 pszName++;
749
750 szWinRtNamespace = szFullName;
751 szWinRtClassName = pszName;
752 }
753 else
754 { // Namespace '.' separator not found - invalid type name (namespace has to be always present)
755 fValidAssemblyRef = FALSE;
756 }
757 }
758 else
759 { // Type name separator in assembly name '!' not found
760 fValidAssemblyRef = FALSE;
761 }
762 }
763
764 if (fValidAssemblyRef)
765 {
766 pAssembly = fromModule->GetAssemblyIfLoaded(
767 tkAssemblyRef,
768 szWinRtNamespace,
769 szWinRtClassName,
770 pMDImportOverride);
771 }
772 }
773 }
774 }
775
776 if (pAssembly == NULL)
777 return NULL;
778
779 return pAssembly->GetManifestModule();
780}
781
782
783TypeHandle ZapSig::DecodeType(Module *pEncodeModuleContext,
784 Module *pInfoModule,
785 PCCOR_SIGNATURE pBuffer,
786 ClassLoadLevel level)
787{
788 CONTRACTL
789 {
790 THROWS;
791 GC_TRIGGERS;
792 MODE_ANY;
793 }
794 CONTRACTL_END;
795
796 SigPointer p(pBuffer);
797
798 ZapSig::Context zapSigContext(pInfoModule, pEncodeModuleContext);
799 ZapSig::Context * pZapSigContext = &zapSigContext;
800
801 SigTypeContext typeContext; // empty context is OK: encoding should not contain type variables.
802
803 TypeHandle th = p.GetTypeHandleThrowing(pInfoModule,
804 &typeContext,
805 ClassLoader::LoadTypes,
806 level,
807 level < CLASS_LOADED, // For non-full loads, drop a level when loading generic arguments
808 NULL,
809 pZapSigContext);
810
811 return th;
812}
813
814MethodDesc *ZapSig::DecodeMethod(Module *pReferencingModule,
815 Module *pInfoModule,
816 PCCOR_SIGNATURE pBuffer,
817 TypeHandle * ppTH /*=NULL*/)
818{
819 STANDARD_VM_CONTRACT;
820
821 SigTypeContext typeContext; // empty context is OK: encoding should not contain type variables.
822
823 return DecodeMethod(pReferencingModule, pInfoModule, pBuffer, &typeContext, ppTH);
824}
825
826MethodDesc *ZapSig::DecodeMethod(Module *pReferencingModule,
827 Module *pInfoModule,
828 PCCOR_SIGNATURE pBuffer,
829 SigTypeContext *pContext,
830 TypeHandle *ppTH, /*=NULL*/
831 PCCOR_SIGNATURE *ppOwnerTypeSpecWithVars, /*=NULL*/
832 PCCOR_SIGNATURE *ppMethodSpecWithVars /*=NULL*/)
833{
834 STANDARD_VM_CONTRACT;
835
836 MethodDesc *pMethod = NULL;
837
838 SigPointer sig(pBuffer);
839
840 ZapSig::Context zapSigContext(pInfoModule, (void *)pReferencingModule, ZapSig::NormalTokens);
841 ZapSig::Context * pZapSigContext = &zapSigContext;
842
843 // decode flags
844 DWORD methodFlags;
845 IfFailThrow(sig.GetData(&methodFlags));
846
847 TypeHandle thOwner = NULL;
848
849 if ( methodFlags & ENCODE_METHOD_SIG_OwnerType )
850 {
851 if (ppOwnerTypeSpecWithVars != NULL)
852 *ppOwnerTypeSpecWithVars = sig.GetPtr();
853
854 thOwner = sig.GetTypeHandleThrowing(pInfoModule,
855 pContext,
856 ClassLoader::LoadTypes,
857 CLASS_LOADED,
858 FALSE,
859 NULL,
860 pZapSigContext);
861
862 IfFailThrow(sig.SkipExactlyOne());
863 }
864
865 if ( methodFlags & ENCODE_METHOD_SIG_SlotInsteadOfToken )
866 {
867 // get the method desc using slot number
868 DWORD slot;
869 IfFailThrow(sig.GetData(&slot));
870
871 _ASSERTE(!thOwner.IsNull());
872
873 pMethod = thOwner.GetMethodTable()->GetMethodDescForSlot(slot);
874 }
875 else
876 {
877 //
878 // decode method token
879 //
880 RID rid;
881 IfFailThrow(sig.GetData(&rid));
882
883 if (methodFlags & ENCODE_METHOD_SIG_MemberRefToken)
884 {
885 if (thOwner.IsNull())
886 {
887 TypeHandle th;
888 MethodDesc * pMD = NULL;
889 FieldDesc * pFD = NULL;
890
891 MemberLoader::GetDescFromMemberRef(pInfoModule, TokenFromRid(rid, mdtMemberRef), &pMD, &pFD, NULL, FALSE, &th);
892 _ASSERTE(pMD != NULL);
893
894 thOwner = th;
895 pMethod = pMD;
896 }
897 else
898 {
899 pMethod = MemberLoader::GetMethodDescFromMemberRefAndType(pInfoModule, TokenFromRid(rid, mdtMemberRef), thOwner.GetMethodTable());
900 }
901 }
902 else
903 {
904 pMethod = MemberLoader::GetMethodDescFromMethodDef(pInfoModule, TokenFromRid(rid, mdtMethodDef), FALSE);
905 }
906 }
907
908 if (thOwner.IsNull())
909 thOwner = pMethod->GetMethodTable();
910
911 if (ppTH != NULL)
912 *ppTH = thOwner;
913
914 // Ensure that the methoddescs dependencies have been walked sufficiently for type forwarders to be resolved.
915 // This method is actually basically a nop for dependencies which are ngen'd, but is real work for jitted
916 // dependencies. (However, this shouldn't be meaningful work that wouldn't happen in any case very soon.)
917 pMethod->PrepareForUseAsADependencyOfANativeImage();
918
919 Instantiation inst;
920
921 // Instantiate the method if needed, or create a stub to a static method in a generic class.
922 if (methodFlags & ENCODE_METHOD_SIG_MethodInstantiation)
923 {
924 if (ppMethodSpecWithVars != NULL)
925 *ppMethodSpecWithVars = sig.GetPtr();
926
927 DWORD nargs;
928 IfFailThrow(sig.GetData(&nargs));
929 _ASSERTE(nargs > 0);
930
931 SIZE_T cbMem;
932
933 if (!ClrSafeInt<SIZE_T>::multiply(nargs, sizeof(TypeHandle), cbMem/* passed by ref */))
934 ThrowHR(COR_E_OVERFLOW);
935
936 TypeHandle * pInst = (TypeHandle*) _alloca(cbMem);
937
938 for (DWORD i = 0; i < nargs; i++)
939 {
940 pInst[i] = sig.GetTypeHandleThrowing(pInfoModule,
941 pContext,
942 ClassLoader::LoadTypes,
943 CLASS_LOADED,
944 FALSE,
945 NULL,
946 pZapSigContext);
947 IfFailThrow(sig.SkipExactlyOne());
948 }
949
950 inst = Instantiation(pInst, nargs);
951 }
952 else
953 {
954 inst = pMethod->GetMethodInstantiation();
955 }
956
957
958 // This must be called even if nargs == 0, in order to create an instantiating
959 // stub for static methods in generic classees if needed, also for BoxedEntryPointStubs
960 // in non-generic structs.
961 BOOL isInstantiatingStub = (methodFlags & ENCODE_METHOD_SIG_InstantiatingStub);
962 BOOL isUnboxingStub = (methodFlags & ENCODE_METHOD_SIG_UnboxingStub);
963
964 pMethod = MethodDesc::FindOrCreateAssociatedMethodDesc(pMethod, thOwner.GetMethodTable(),
965 isUnboxingStub,
966 inst,
967 !(isInstantiatingStub || isUnboxingStub));
968
969 g_IBCLogger.LogMethodDescAccess(pMethod);
970
971 if (methodFlags & ENCODE_METHOD_SIG_Constrained)
972 {
973 TypeHandle constrainedType = sig.GetTypeHandleThrowing(pInfoModule,
974 pContext,
975 ClassLoader::LoadTypes,
976 CLASS_LOADED,
977 FALSE,
978 NULL,
979 pZapSigContext);
980
981 MethodDesc * directMethod = constrainedType.GetMethodTable()->TryResolveConstraintMethodApprox(thOwner.GetMethodTable(), pMethod);
982 if (directMethod == NULL)
983 {
984 // Method on value type was removed. Boxing stub would need to be generated to handle this case.
985 _ASSERTE(!"Constrained method resolution failed");
986
987 MemberLoader::ThrowMissingMethodException(constrainedType.GetMethodTable(), NULL, NULL, NULL, 0, NULL);
988 }
989
990 // Strip the instantiating stub if the signature did not ask for one
991 if (directMethod->IsInstantiatingStub() && !isInstantiatingStub)
992 {
993 pMethod = directMethod->GetWrappedMethodDesc();
994 }
995 else
996 {
997 pMethod = directMethod;
998 }
999 }
1000
1001 return pMethod;
1002}
1003
1004FieldDesc * ZapSig::DecodeField(Module *pReferencingModule,
1005 Module *pInfoModule,
1006 PCCOR_SIGNATURE pBuffer,
1007 TypeHandle *ppTH /*=NULL*/)
1008{
1009 CONTRACTL
1010 {
1011 THROWS;
1012 GC_TRIGGERS;
1013 MODE_ANY;
1014 }
1015 CONTRACTL_END;
1016
1017 SigTypeContext typeContext; // empty context is OK: encoding should not contain type variables.
1018
1019 return DecodeField(pReferencingModule, pInfoModule, pBuffer, &typeContext, ppTH);
1020}
1021
1022FieldDesc * ZapSig::DecodeField(Module *pReferencingModule,
1023 Module *pInfoModule,
1024 PCCOR_SIGNATURE pBuffer,
1025 SigTypeContext *pContext,
1026 TypeHandle *ppTH /*=NULL*/)
1027{
1028 CONTRACTL
1029 {
1030 THROWS;
1031 GC_TRIGGERS;
1032 MODE_ANY;
1033 }
1034 CONTRACTL_END;
1035
1036 FieldDesc *pField = NULL;
1037
1038 SigPointer sig(pBuffer);
1039
1040 DWORD fieldFlags;
1041 IfFailThrow(sig.GetData(&fieldFlags));
1042
1043 MethodTable *pOwnerMT = NULL;
1044
1045 if (fieldFlags & ENCODE_FIELD_SIG_OwnerType)
1046 {
1047 ZapSig::Context zapSigContext(pInfoModule, pReferencingModule);
1048 ZapSig::Context * pZapSigContext = &zapSigContext;
1049
1050 pOwnerMT = sig.GetTypeHandleThrowing(pInfoModule,
1051 pContext,
1052 ClassLoader::LoadTypes,
1053 CLASS_LOADED,
1054 FALSE,
1055 NULL,
1056 pZapSigContext).GetMethodTable();
1057
1058 IfFailThrow(sig.SkipExactlyOne());
1059 }
1060
1061 if (fieldFlags & ENCODE_FIELD_SIG_IndexInsteadOfToken)
1062 {
1063 // get the field desc using index
1064 DWORD fieldIndex;
1065 IfFailThrow(sig.GetData(&fieldIndex));
1066
1067 _ASSERTE(pOwnerMT != NULL);
1068
1069 pField = pOwnerMT->GetFieldDescByIndex(fieldIndex);
1070 _ASSERTE(pOwnerMT == pField->GetApproxEnclosingMethodTable());
1071 }
1072 else
1073 {
1074 RID rid;
1075 IfFailThrow(sig.GetData(&rid));
1076
1077 if (fieldFlags & ENCODE_FIELD_SIG_MemberRefToken)
1078 {
1079 if (pOwnerMT == NULL)
1080 {
1081 TypeHandle th;
1082 MethodDesc * pMD = NULL;
1083 FieldDesc * pFD = NULL;
1084
1085 MemberLoader::GetDescFromMemberRef(pInfoModule, TokenFromRid(rid, mdtMemberRef), &pMD, &pFD, NULL, FALSE, &th);
1086 _ASSERTE(pFD != NULL);
1087
1088 pField = pFD;
1089 }
1090 else
1091 {
1092 pField = MemberLoader::GetFieldDescFromMemberRefAndType(pInfoModule, TokenFromRid(rid, mdtMemberRef), pOwnerMT);
1093 }
1094 }
1095 else
1096 {
1097 pField = MemberLoader::GetFieldDescFromFieldDef(pInfoModule, TokenFromRid(rid, mdtFieldDef), FALSE);
1098 }
1099 }
1100
1101 if (ppTH != NULL)
1102 *ppTH = (pOwnerMT != NULL) ? pOwnerMT : pField->GetApproxEnclosingMethodTable();
1103
1104 return pField;
1105}
1106
1107/* static */
1108BOOL ZapSig::EncodeMethod(
1109 MethodDesc * pMethod,
1110 Module * pInfoModule,
1111 SigBuilder * pSigBuilder,
1112 LPVOID pEncodeModuleContext,
1113 ENCODEMODULE_CALLBACK pfnEncodeModule,
1114 DEFINETOKEN_CALLBACK pfnDefineToken,
1115 CORINFO_RESOLVED_TOKEN * pResolvedToken,
1116 CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken,
1117 BOOL fEncodeUsingResolvedTokenSpecStreams)
1118{
1119 CONTRACTL
1120 {
1121 THROWS;
1122 GC_TRIGGERS;
1123 MODE_ANY;
1124 }
1125 CONTRACTL_END;
1126
1127 TypeHandle ownerType;
1128
1129#ifdef FEATURE_READYTORUN_COMPILER
1130 if (IsReadyToRunCompilation())
1131 {
1132 if (pResolvedToken == NULL)
1133 {
1134 _ASSERTE(!"CORINFO_RESOLVED_TOKEN required to encode method!");
1135 ThrowHR(E_FAIL);
1136 }
1137
1138 // Encode the referencing method type
1139 ownerType = TypeHandle(pResolvedToken->hClass);
1140 }
1141 else
1142#endif
1143 {
1144 ownerType = pMethod->GetMethodTable_NoLogging();
1145 }
1146
1147 ZapSig::ExternalTokens externalTokens = ZapSig::NormalTokens;
1148 if (pfnDefineToken != NULL)
1149 {
1150 externalTokens = ZapSig::IbcTokens;
1151 }
1152
1153 ZapSig zapSig(pInfoModule, pEncodeModuleContext, externalTokens,
1154 (EncodeModuleCallback) pfnEncodeModule,
1155 (TokenDefinitionCallback) pfnDefineToken);
1156
1157 //
1158 // output the sequence that represents the token for the method
1159 //
1160 mdMethodDef methodToken = pMethod->GetMemberDef_NoLogging();
1161 DWORD methodFlags = 0;
1162 BOOL fMethodNeedsInstantiation = pMethod->HasMethodInstantiation() && !pMethod->IsGenericMethodDefinition();
1163
1164 if (pMethod->IsUnboxingStub())
1165 methodFlags |= ENCODE_METHOD_SIG_UnboxingStub;
1166 if (pMethod->IsInstantiatingStub())
1167 methodFlags |= ENCODE_METHOD_SIG_InstantiatingStub;
1168 if (fMethodNeedsInstantiation)
1169 methodFlags |= ENCODE_METHOD_SIG_MethodInstantiation;
1170
1171 //
1172 // For backward compatibility, IBC tokens use slightly different encoding:
1173 // - Owning type is uncoditionally encoded
1174 // - Number of method instantiation arguments is not encoded
1175 //
1176 if (externalTokens == ZapSig::IbcTokens)
1177 {
1178 // The type is always encoded before flags for IBC
1179 if (!zapSig.GetSignatureForTypeHandle(ownerType, pSigBuilder))
1180 return FALSE;
1181 }
1182 else
1183 {
1184 // Assume that the owner type is going to be needed
1185 methodFlags |= ENCODE_METHOD_SIG_OwnerType;
1186 }
1187
1188#ifdef FEATURE_READYTORUN_COMPILER
1189 if (IsReadyToRunCompilation())
1190 {
1191 if (pConstrainedResolvedToken != NULL)
1192 {
1193 methodFlags |= ENCODE_METHOD_SIG_Constrained;
1194 }
1195
1196 Module * pReferencingModule = (Module *)pResolvedToken->tokenScope;
1197
1198 if (!pReferencingModule->IsInCurrentVersionBubble())
1199 {
1200 // FUTURE: Encoding of new cross-module references for ReadyToRun
1201 // This warning is hit for recursive cross-module inlining. It is commented out to avoid noise.
1202 // GetSvcLogger()->Printf(W("ReadyToRun: Method reference outside of current version bubble cannot be encoded\n"));
1203 ThrowHR(E_FAIL);
1204 }
1205 _ASSERTE(pReferencingModule == GetAppDomain()->ToCompilationDomain()->GetTargetModule());
1206
1207 methodToken = pResolvedToken->token;
1208
1209 if (TypeFromToken(methodToken) == mdtMethodSpec)
1210 {
1211 IfFailThrow(pReferencingModule->GetMDImport()->GetMethodSpecProps(methodToken, &methodToken, NULL, NULL));
1212 }
1213
1214 switch (TypeFromToken(methodToken))
1215 {
1216 case mdtMethodDef:
1217 _ASSERTE(pResolvedToken->pTypeSpec == NULL);
1218 if (!ownerType.HasInstantiation() || ownerType.IsTypicalTypeDefinition())
1219 {
1220 methodFlags &= ~ENCODE_METHOD_SIG_OwnerType;
1221 }
1222 break;
1223
1224 case mdtMemberRef:
1225 methodFlags |= ENCODE_METHOD_SIG_MemberRefToken;
1226
1227 if (pResolvedToken->pTypeSpec == NULL)
1228 {
1229 methodFlags &= ~ENCODE_METHOD_SIG_OwnerType;
1230 }
1231 else
1232 if (!(methodFlags & ENCODE_METHOD_SIG_InstantiatingStub))
1233 {
1234 if (SigPointer(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec).IsPolyType(NULL) == hasNoVars)
1235 methodFlags &= ~ENCODE_METHOD_SIG_OwnerType;
1236 }
1237 break;
1238
1239 default:
1240 _ASSERTE(!"Unexpected method token type!");
1241 ThrowHR(E_NOTIMPL);
1242 }
1243 }
1244 else
1245#endif
1246 if (IsNilToken(methodToken))
1247 {
1248 methodFlags |= ENCODE_METHOD_SIG_SlotInsteadOfToken;
1249 }
1250 else
1251 if (!pMethod->GetModule()->IsInCurrentVersionBubble())
1252 {
1253 // Using a method defined in another version bubble. We can assume the slot number is stable only for real interface methods.
1254 if (!ownerType.IsInterface() || pMethod->IsStatic() || pMethod->HasMethodInstantiation())
1255 {
1256 // FUTURE TODO: Version resilience
1257 _ASSERTE(!"References to non-interface methods not yet supported in version resilient images");
1258 IfFailThrow(E_FAIL);
1259 }
1260 methodFlags |= ENCODE_METHOD_SIG_SlotInsteadOfToken;
1261 }
1262 else
1263 {
1264 Module * pTypeHandleModule = pMethod->GetModule();
1265
1266 if (pTypeHandleModule != pInfoModule)
1267 {
1268 // During IBC profiling this calls
1269 // code:Module.EncodeModuleHelper
1270 // During ngen this calls
1271 // code:ZapImportTable.EncodeModuleHelper)
1272 //
1273 DWORD index = (*((EncodeModuleCallback) pfnEncodeModule))(pEncodeModuleContext, pTypeHandleModule);
1274
1275 if (index == ENCODE_MODULE_FAILED)
1276 {
1277 return FALSE;
1278 }
1279
1280 // If the method handle's module is different that the pInfoModule
1281 // we need to call the TokenDefinitionCallback function
1282 // to record the names for the external module tokens
1283 //
1284 if ((index != 0) && (pfnDefineToken != NULL))
1285 {
1286 //
1287 // We do not want to log the metadata lookups that we perform here
1288 //
1289 IBCLoggingDisabler disableLogging;
1290
1291 // During IBC profiling this calls
1292 // code:Module::TokenDefinitionHelper()
1293 (*((TokenDefinitionCallback) pfnDefineToken))(pEncodeModuleContext, pTypeHandleModule, index, &methodToken);
1294 }
1295 }
1296 else
1297 {
1298 _ASSERTE(pInfoModule = pMethod->GetModule());
1299 }
1300
1301 if (!ownerType.HasInstantiation())
1302 methodFlags &= ~ENCODE_METHOD_SIG_OwnerType;
1303 }
1304
1305 //
1306 // output the flags
1307 //
1308 pSigBuilder->AppendData(methodFlags);
1309
1310 if (methodFlags & ENCODE_METHOD_SIG_OwnerType)
1311 {
1312 if (fEncodeUsingResolvedTokenSpecStreams && pResolvedToken != NULL && pResolvedToken->pTypeSpec != NULL)
1313 {
1314 _ASSERTE(pResolvedToken->cbTypeSpec > 0);
1315 pSigBuilder->AppendBlob((PVOID)pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec);
1316 }
1317 else
1318 {
1319 if (!zapSig.GetSignatureForTypeHandle(ownerType, pSigBuilder))
1320 return FALSE;
1321 }
1322 }
1323
1324 if ((methodFlags & ENCODE_METHOD_SIG_SlotInsteadOfToken) == 0)
1325 {
1326 // emit the rid
1327 pSigBuilder->AppendData(RidFromToken(methodToken));
1328 }
1329 else
1330 {
1331 // have no token (e.g. it could be an array), encode slot number
1332 pSigBuilder->AppendData(pMethod->GetSlot());
1333 }
1334
1335 if ((methodFlags & ENCODE_METHOD_SIG_MethodInstantiation) != 0)
1336 {
1337 if (fEncodeUsingResolvedTokenSpecStreams && pResolvedToken != NULL && pResolvedToken->pMethodSpec != NULL)
1338 {
1339 _ASSERTE(pResolvedToken->cbMethodSpec > 1);
1340
1341 if (*(BYTE*)pResolvedToken->pMethodSpec != (BYTE)IMAGE_CEE_CS_CALLCONV_GENERICINST)
1342 ThrowHR(COR_E_BADIMAGEFORMAT);
1343
1344 pSigBuilder->AppendBlob((PVOID)(((BYTE*)pResolvedToken->pMethodSpec) + 1), pResolvedToken->cbMethodSpec - 1);
1345 }
1346 else
1347 {
1348 Instantiation inst = pMethod->GetMethodInstantiation();
1349
1350 // Number of method instantiation arguments is not encoded in IBC tokens - see comment above
1351 if (externalTokens != ZapSig::IbcTokens)
1352 pSigBuilder->AppendData(inst.GetNumArgs());
1353
1354 for (DWORD i = 0; i < inst.GetNumArgs(); i++)
1355 {
1356 TypeHandle t = inst[i];
1357 _ASSERTE(!t.IsNull());
1358
1359 if (!zapSig.GetSignatureForTypeHandle(t, pSigBuilder))
1360 return FALSE;
1361 }
1362 }
1363 }
1364
1365#ifdef FEATURE_READYTORUN_COMPILER
1366 if ((methodFlags & ENCODE_METHOD_SIG_Constrained) != 0)
1367 {
1368 if (fEncodeUsingResolvedTokenSpecStreams && pConstrainedResolvedToken->pTypeSpec != NULL)
1369 {
1370 _ASSERTE(pConstrainedResolvedToken->cbTypeSpec > 0);
1371 pSigBuilder->AppendBlob((PVOID)pConstrainedResolvedToken->pTypeSpec, pConstrainedResolvedToken->cbTypeSpec);
1372 }
1373 else
1374 {
1375 if (!zapSig.GetSignatureForTypeHandle(TypeHandle(pConstrainedResolvedToken->hClass), pSigBuilder))
1376 return FALSE;
1377 }
1378 }
1379#endif
1380
1381 return TRUE;
1382}
1383
1384void ZapSig::EncodeField(
1385 FieldDesc *pField,
1386 Module *pInfoModule,
1387 SigBuilder *pSigBuilder,
1388 LPVOID pEncodeModuleContext,
1389 ENCODEMODULE_CALLBACK pfnEncodeModule,
1390 CORINFO_RESOLVED_TOKEN *pResolvedToken,
1391 BOOL fEncodeUsingResolvedTokenSpecStreams)
1392{
1393 CONTRACTL
1394 {
1395 THROWS;
1396 GC_TRIGGERS;
1397 MODE_ANY;
1398 }
1399 CONTRACTL_END;
1400
1401 MethodTable * pMT;
1402
1403 mdMethodDef fieldToken = pField->GetMemberDef();
1404 DWORD fieldFlags = ENCODE_FIELD_SIG_OwnerType;
1405
1406#ifdef FEATURE_READYTORUN_COMPILER
1407 if (IsReadyToRunCompilation())
1408 {
1409 if (pResolvedToken == NULL)
1410 {
1411 _ASSERTE(!"CORINFO_RESOLVED_TOKEN required to encode field!");
1412 ThrowHR(E_FAIL);
1413 }
1414
1415 // Encode the referencing field type
1416 pMT = (MethodTable *)(pResolvedToken->hClass);
1417
1418 Module * pReferencingModule = (Module *)pResolvedToken->tokenScope;
1419
1420 if (!pReferencingModule->IsInCurrentVersionBubble())
1421 {
1422 // FUTURE: Encoding of new cross-module references for ReadyToRun
1423 // This warning is hit for recursive cross-module inlining. It is commented out to avoid noise.
1424 // GetSvcLogger()->Printf(W("ReadyToRun: Field reference outside of current version bubble cannot be encoded\n"));
1425 ThrowHR(E_FAIL);
1426 }
1427 _ASSERTE(pReferencingModule == GetAppDomain()->ToCompilationDomain()->GetTargetModule());
1428
1429 fieldToken = pResolvedToken->token;
1430
1431 switch (TypeFromToken(fieldToken))
1432 {
1433 case mdtFieldDef:
1434 _ASSERTE(pResolvedToken->pTypeSpec == NULL);
1435 fieldFlags &= ~ENCODE_FIELD_SIG_OwnerType;
1436 break;
1437
1438 case mdtMemberRef:
1439 fieldFlags |= ENCODE_FIELD_SIG_MemberRefToken;
1440
1441 if (pResolvedToken->pTypeSpec == NULL)
1442 {
1443 fieldFlags &= ~ENCODE_METHOD_SIG_OwnerType;
1444 }
1445 else
1446 {
1447 if (SigPointer(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec).IsPolyType(NULL) == hasNoVars)
1448 fieldFlags &= ~ENCODE_METHOD_SIG_OwnerType;
1449 }
1450 break;
1451
1452 default:
1453 _ASSERTE(!"Unexpected field token type!");
1454 ThrowHR(E_NOTIMPL);
1455 }
1456 }
1457 else
1458#endif
1459 {
1460 pMT = pField->GetApproxEnclosingMethodTable();
1461
1462 fieldFlags |= ENCODE_FIELD_SIG_IndexInsteadOfToken;
1463 }
1464
1465 //
1466 // output the flags
1467 //
1468 pSigBuilder->AppendData(fieldFlags);
1469
1470 if (fieldFlags & ENCODE_FIELD_SIG_OwnerType)
1471 {
1472 if (fEncodeUsingResolvedTokenSpecStreams && pResolvedToken != NULL && pResolvedToken->pTypeSpec != NULL)
1473 {
1474 _ASSERTE(pResolvedToken->cbTypeSpec > 0);
1475 pSigBuilder->AppendBlob((PVOID)pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec);
1476 }
1477 else
1478 {
1479 ZapSig zapSig(pInfoModule, pEncodeModuleContext, ZapSig::NormalTokens,
1480 (EncodeModuleCallback)pfnEncodeModule, NULL);
1481
1482 //
1483 // Write class
1484 //
1485 BOOL fSuccess;
1486 fSuccess = zapSig.GetSignatureForTypeHandle(pMT, pSigBuilder);
1487 _ASSERTE(fSuccess);
1488 }
1489 }
1490
1491 if ((fieldFlags & ENCODE_FIELD_SIG_IndexInsteadOfToken) == 0)
1492 {
1493 // emit the rid
1494 pSigBuilder->AppendData(RidFromToken(fieldToken));
1495 }
1496 else
1497 {
1498 //
1499 // Write field index
1500 //
1501
1502 DWORD fieldIndex = pMT->GetIndexForFieldDesc(pField);
1503 _ASSERTE(fieldIndex < DWORD(pMT->GetNumStaticFields() + pMT->GetNumIntroducedInstanceFields()));
1504
1505 // have no token (e.g. it could be an array), encode slot number
1506 pSigBuilder->AppendData(fieldIndex);
1507 }
1508}
1509
1510#endif // DACCESS_COMPILE
1511
1512#endif // FEATURE_PREJIT
1513