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: StubGen.h
6//
7
8//
9
10
11#ifndef __STUBGEN_H__
12#define __STUBGEN_H__
13
14#include "stublink.h"
15
16struct LocalDesc
17{
18 const static size_t MAX_LOCALDESC_ELEMENTS = 8;
19
20 BYTE ElementType[MAX_LOCALDESC_ELEMENTS];
21 size_t cbType;
22 TypeHandle InternalToken; // only valid with ELEMENT_TYPE_INTERNAL
23
24 // used only for E_T_FNPTR and E_T_ARRAY
25 PCCOR_SIGNATURE pSig;
26 union
27 {
28 Module* pSigModule;
29 size_t cbArrayBoundsInfo;
30 BOOL bIsCopyConstructed; // used for E_T_PTR
31 };
32
33 LocalDesc()
34 {
35 }
36
37 inline LocalDesc(CorElementType elemType)
38 {
39 ElementType[0] = static_cast<BYTE>(elemType);
40 cbType = 1;
41 bIsCopyConstructed = FALSE;
42 }
43
44 inline LocalDesc(TypeHandle thType)
45 {
46 ElementType[0] = ELEMENT_TYPE_INTERNAL;
47 cbType = 1;
48 InternalToken = thType;
49 bIsCopyConstructed = FALSE;
50 }
51
52 inline LocalDesc(MethodTable *pMT)
53 {
54 WRAPPER_NO_CONTRACT;
55 ElementType[0] = ELEMENT_TYPE_INTERNAL;
56 cbType = 1;
57 InternalToken = TypeHandle(pMT);
58 bIsCopyConstructed = FALSE;
59 }
60
61 void MakeByRef()
62 {
63 ChangeType(ELEMENT_TYPE_BYREF);
64 }
65
66 void MakePinned()
67 {
68 ChangeType(ELEMENT_TYPE_PINNED);
69 }
70
71 // makes the LocalDesc semantically equivalent to ET_TYPE_CMOD_REQD<IsCopyConstructed>/ET_TYPE_CMOD_REQD<NeedsCopyConstructorModifier>
72 void MakeCopyConstructedPointer()
73 {
74 ChangeType(ELEMENT_TYPE_PTR);
75 bIsCopyConstructed = TRUE;
76 }
77
78 void ChangeType(CorElementType elemType)
79 {
80 LIMITED_METHOD_CONTRACT;
81 PREFIX_ASSUME((MAX_LOCALDESC_ELEMENTS-1) >= cbType);
82
83 for (size_t i = cbType; i >= 1; i--)
84 {
85 ElementType[i] = ElementType[i-1];
86 }
87
88 ElementType[0] = static_cast<BYTE>(elemType);
89 cbType += 1;
90 }
91
92 bool IsValueClass()
93 {
94 CONTRACTL
95 {
96 THROWS;
97 GC_TRIGGERS;
98 MODE_ANY;
99 PRECONDITION(cbType == 1); // this only works on 1-element types for now
100 }
101 CONTRACTL_END;
102
103 if (ElementType[0] == ELEMENT_TYPE_VALUETYPE)
104 {
105 return true;
106 }
107 else if ((ElementType[0] == ELEMENT_TYPE_INTERNAL) &&
108 (InternalToken.IsNativeValueType() ||
109 InternalToken.GetMethodTable()->IsValueType()))
110 {
111 return true;
112 }
113
114 return false;
115 }
116};
117
118class StubSigBuilder
119{
120public:
121 StubSigBuilder();
122
123 DWORD Append(LocalDesc* pLoc);
124
125protected:
126 CQuickBytes m_qbSigBuffer;
127 DWORD m_nItems;
128 BYTE* m_pbSigCursor;
129 size_t m_cbSig;
130
131 enum Constants { INITIAL_BUFFER_SIZE = 256 };
132
133 void EnsureEnoughQuickBytes(size_t cbToAppend);
134};
135
136//---------------------------------------------------------------------------------------
137//
138class LocalSigBuilder : protected StubSigBuilder
139{
140public:
141 DWORD NewLocal(LocalDesc * pLoc)
142 {
143 CONTRACTL
144 {
145 THROWS;
146 GC_TRIGGERS;
147 MODE_ANY;
148 PRECONDITION(CheckPointer(pLoc));
149 }
150 CONTRACTL_END;
151
152 return Append(pLoc);
153 }
154
155 DWORD GetSigSize();
156 DWORD GetSig(BYTE * pbSig, DWORD cbBuffer);
157
158}; // class LocalSigBuilder
159
160//---------------------------------------------------------------------------------------
161//
162class FunctionSigBuilder : protected StubSigBuilder
163{
164public:
165 FunctionSigBuilder();
166
167 DWORD NewArg(LocalDesc * pArg)
168 {
169 WRAPPER_NO_CONTRACT;
170
171 return Append(pArg);
172 }
173
174 DWORD GetNumArgs()
175 {
176 LIMITED_METHOD_CONTRACT;
177 return m_nItems;
178 }
179
180 void SetCallingConv(CorCallingConvention callingConv)
181 {
182 LIMITED_METHOD_CONTRACT;
183 m_callingConv = callingConv;
184 }
185
186 CorCallingConvention GetCallingConv()
187 {
188 LIMITED_METHOD_CONTRACT;
189 return m_callingConv;
190 }
191
192 void SetSig(PCCOR_SIGNATURE pSig, DWORD cSig);
193
194 DWORD GetSigSize();
195 DWORD GetSig(BYTE * pbSig, DWORD cbBuffer);
196
197 void SetReturnType(LocalDesc* pLoc);
198
199 CorElementType GetReturnElementType()
200 {
201 LIMITED_METHOD_CONTRACT;
202
203 CONSISTENCY_CHECK(m_qbReturnSig.Size() > 0);
204 return *(CorElementType *)m_qbReturnSig.Ptr();
205 }
206
207 PCCOR_SIGNATURE GetReturnSig()
208 {
209 LIMITED_METHOD_CONTRACT;
210
211 CONSISTENCY_CHECK(m_qbReturnSig.Size() > 0);
212 return (PCCOR_SIGNATURE)m_qbReturnSig.Ptr();
213 }
214
215protected:
216 CorCallingConvention m_callingConv;
217 CQuickBytes m_qbReturnSig;
218}; // class FunctionSigBuilder
219
220#ifdef _DEBUG
221// exercise the resize code
222#define TOKEN_LOOKUP_MAP_SIZE (8*sizeof(void*))
223#else // _DEBUG
224#define TOKEN_LOOKUP_MAP_SIZE (64*sizeof(void*))
225#endif // _DEBUG
226
227//---------------------------------------------------------------------------------------
228//
229class TokenLookupMap
230{
231public:
232 TokenLookupMap()
233 {
234 STANDARD_VM_CONTRACT;
235
236 m_qbEntries.AllocThrows(TOKEN_LOOKUP_MAP_SIZE);
237 m_nextAvailableRid = 0;
238 }
239
240 // copy ctor
241 TokenLookupMap(TokenLookupMap* pSrc)
242 {
243 STANDARD_VM_CONTRACT;
244
245 m_nextAvailableRid = pSrc->m_nextAvailableRid;
246 size_t size = pSrc->m_qbEntries.Size();
247 m_qbEntries.AllocThrows(size);
248 memcpy(m_qbEntries.Ptr(), pSrc->m_qbEntries.Ptr(), size);
249 }
250
251 TypeHandle LookupTypeDef(mdToken token)
252 {
253 WRAPPER_NO_CONTRACT;
254 return LookupTokenWorker<mdtTypeDef, MethodTable*>(token);
255 }
256 MethodDesc* LookupMethodDef(mdToken token)
257 {
258 WRAPPER_NO_CONTRACT;
259 return LookupTokenWorker<mdtMethodDef, MethodDesc*>(token);
260 }
261 FieldDesc* LookupFieldDef(mdToken token)
262 {
263 WRAPPER_NO_CONTRACT;
264 return LookupTokenWorker<mdtFieldDef, FieldDesc*>(token);
265 }
266
267 mdToken GetToken(TypeHandle pMT)
268 {
269 WRAPPER_NO_CONTRACT;
270 return GetTokenWorker<mdtTypeDef, TypeHandle>(pMT);
271 }
272 mdToken GetToken(MethodDesc* pMD)
273 {
274 WRAPPER_NO_CONTRACT;
275 return GetTokenWorker<mdtMethodDef, MethodDesc*>(pMD);
276 }
277 mdToken GetToken(FieldDesc* pFieldDesc)
278 {
279 WRAPPER_NO_CONTRACT;
280 return GetTokenWorker<mdtFieldDef, FieldDesc*>(pFieldDesc);
281 }
282
283protected:
284 template<mdToken TokenType, typename HandleType>
285 HandleType LookupTokenWorker(mdToken token)
286 {
287 CONTRACTL
288 {
289 THROWS;
290 MODE_ANY;
291 GC_NOTRIGGER;
292 PRECONDITION(RidFromToken(token)-1 < m_nextAvailableRid);
293 PRECONDITION(RidFromToken(token) != 0);
294 PRECONDITION(TypeFromToken(token) == TokenType);
295 }
296 CONTRACTL_END;
297
298 return ((HandleType*)m_qbEntries.Ptr())[RidFromToken(token)-1];
299 }
300
301 template<mdToken TokenType, typename HandleType>
302 mdToken GetTokenWorker(HandleType handle)
303 {
304 CONTRACTL
305 {
306 THROWS;
307 MODE_ANY;
308 GC_NOTRIGGER;
309 PRECONDITION(handle != NULL);
310 }
311 CONTRACTL_END;
312
313 if (m_qbEntries.Size() <= (sizeof(handle) * m_nextAvailableRid))
314 {
315 m_qbEntries.ReSizeThrows(2 * m_qbEntries.Size());
316 }
317
318 mdToken token = TokenFromRid(m_nextAvailableRid++, TokenType)+1;
319
320 ((HandleType*)m_qbEntries.Ptr())[RidFromToken(token)-1] = handle;
321
322 return token;
323 }
324
325 unsigned int m_nextAvailableRid;
326 CQuickBytesSpecifySize<TOKEN_LOOKUP_MAP_SIZE> m_qbEntries;
327};
328
329struct ILStubEHClause
330{
331 enum Kind { kNone, kTypedCatch, kFinally };
332
333 DWORD kind;
334 DWORD dwTryBeginOffset;
335 DWORD cbTryLength;
336 DWORD dwHandlerBeginOffset;
337 DWORD cbHandlerLength;
338 DWORD dwTypeToken;
339};
340
341
342class ILCodeLabel;
343class ILCodeStream;
344//---------------------------------------------------------------------------------------
345//
346class ILStubLinker
347{
348 friend class ILCodeLabel;
349 friend class ILCodeStream;
350
351public:
352
353 ILStubLinker(Module* pModule, const Signature &signature, SigTypeContext *pTypeContext, MethodDesc *pMD,
354 BOOL fTargetHasThis, BOOL fStubHasThis, BOOL fIsNDirectStub = FALSE);
355 ~ILStubLinker();
356
357 void GenerateCode(BYTE* pbBuffer, size_t cbBufferSize);
358 void ClearCode();
359
360protected:
361
362 void DeleteCodeLabels();
363 void DeleteCodeStreams();
364
365 struct ILInstruction
366 {
367 UINT16 uInstruction;
368 INT16 iStackDelta;
369 UINT_PTR uArg;
370 };
371
372 static void PatchInstructionArgument(ILCodeLabel* pLabel, UINT_PTR uNewArg
373 DEBUG_ARG(UINT16 uExpectedInstruction));
374
375#ifdef _DEBUG
376 bool IsInCodeStreamList(ILCodeStream* pcs);
377#endif // _DEBUG
378
379public:
380
381 void SetHasThis (bool fHasThis);
382 bool HasThis () { LIMITED_METHOD_CONTRACT; return m_fHasThis; }
383
384 DWORD GetLocalSigSize();
385 DWORD GetLocalSig(BYTE * pbLocalSig, DWORD cbBuffer);
386
387 DWORD GetStubTargetMethodSigSize();
388 DWORD GetStubTargetMethodSig(BYTE * pbLocalSig, DWORD cbBuffer);
389
390 void SetStubTargetMethodSig(PCCOR_SIGNATURE pSig, DWORD cSig);
391
392 void GetStubTargetReturnType(LocalDesc * pLoc);
393 void GetStubTargetReturnType(LocalDesc * pLoc, Module * pModule);
394
395 void GetStubArgType(LocalDesc * pLoc);
396 void GetStubArgType(LocalDesc * pLoc, Module * pModule);
397 void GetStubReturnType(LocalDesc * pLoc);
398 void GetStubReturnType(LocalDesc * pLoc, Module * pModule);
399 CorCallingConvention GetStubTargetCallingConv();
400
401
402 CorElementType GetStubTargetReturnElementType() { WRAPPER_NO_CONTRACT; return m_nativeFnSigBuilder.GetReturnElementType(); }
403
404 static void GetManagedTypeHelper(LocalDesc* pLoc, Module* pModule, PCCOR_SIGNATURE pSig, SigTypeContext *pTypeContext, MethodDesc *pMD);
405
406 BOOL StubHasVoidReturnType();
407
408 Stub *Link(LoaderHeap *pHeap, UINT *pcbSize /* = NULL*/, BOOL fMC);
409
410 size_t Link(UINT* puMaxStack);
411
412
413 TokenLookupMap* GetTokenLookupMap() { LIMITED_METHOD_CONTRACT; return &m_tokenMap; }
414
415 enum CodeStreamType
416 {
417 kSetup,
418 kMarshal,
419 kDispatch,
420 kReturnUnmarshal,
421 kUnmarshal,
422 kExceptionCleanup,
423 kCleanup,
424 kExceptionHandler,
425 };
426
427 ILCodeStream* NewCodeStream(CodeStreamType codeStreamType);
428
429 MethodDesc *GetTargetMD() { LIMITED_METHOD_CONTRACT; return m_pMD; }
430 Signature GetStubSignature() { LIMITED_METHOD_CONTRACT; return m_stubSig; }
431
432 void ClearCodeStreams();
433
434 void LogILStub(CORJIT_FLAGS jitFlags, SString *pDumpILStubCode = NULL);
435protected:
436 void LogILStubWorker(ILInstruction* pInstrBuffer, UINT numInstr, size_t* pcbCode, INT* piCurStack, SString *pDumpILStubCode = NULL);
437 void LogILInstruction(size_t curOffset, bool isLabeled, INT iCurStack, ILInstruction* pInstruction, SString *pDumpILStubCode = NULL);
438
439private:
440 ILCodeStream* m_pCodeStreamList;
441
442 TokenLookupMap m_tokenMap;
443 LocalSigBuilder m_localSigBuilder;
444 FunctionSigBuilder m_nativeFnSigBuilder;
445 BYTE m_rgbBuffer[sizeof(COR_ILMETHOD_DECODER)];
446
447 Signature m_stubSig; // managed sig of stub
448 SigTypeContext* m_pTypeContext; // type context for m_stubSig
449
450 SigPointer m_managedSigPtr;
451 void* m_pCode;
452 Module* m_pStubSigModule;
453 ILCodeLabel* m_pLabelList;
454
455 bool FirstPassLink(ILInstruction* pInstrBuffer, UINT numInstr, size_t* pcbCode, INT* piCurStack, UINT* puMaxStack);
456 void SecondPassLink(ILInstruction* pInstrBuffer, UINT numInstr, size_t* pCurCodeOffset);
457
458 BYTE* GenerateCodeWorker(BYTE* pbBuffer, ILInstruction* pInstrBuffer, UINT numInstr, size_t* pcbCode);
459
460 static ILCodeStream* FindLastCodeStream(ILCodeStream* pList);
461
462protected:
463 //
464 // the public entrypoints for these methods are in ILCodeStream
465 //
466 ILCodeLabel* NewCodeLabel();
467 int GetToken(MethodDesc* pMD);
468 int GetToken(MethodTable* pMT);
469 int GetToken(TypeHandle th);
470 int GetToken(FieldDesc* pFD);
471 DWORD NewLocal(CorElementType typ = ELEMENT_TYPE_I);
472 DWORD NewLocal(LocalDesc loc);
473
474 DWORD SetStubTargetArgType(CorElementType typ, bool fConsumeStubArg = true);
475 DWORD SetStubTargetArgType(LocalDesc* pLoc = NULL, bool fConsumeStubArg = true); // passing pLoc = NULL means "use stub arg type"
476 void SetStubTargetReturnType(CorElementType typ);
477 void SetStubTargetReturnType(LocalDesc* pLoc);
478 void SetStubTargetCallingConv(CorCallingConvention uNativeCallingConv);
479
480 void TransformArgForJIT(LocalDesc *pLoc);
481
482 Module * GetStubSigModule();
483 SigTypeContext *GetStubSigTypeContext();
484
485 BOOL m_StubHasVoidReturnType;
486 INT m_iTargetStackDelta;
487 DWORD m_cbCurrentCompressedSigLen;
488 DWORD m_nLocals;
489
490 bool m_fHasThis;
491
492 // We need this MethodDesc so we can reconstruct the generics
493 // SigTypeContext info, if needed.
494 MethodDesc * m_pMD;
495}; // class ILStubLinker
496
497
498//---------------------------------------------------------------------------------------
499//
500class ILCodeLabel
501{
502 friend class ILStubLinker;
503 friend class ILCodeStream;
504
505public:
506 ILCodeLabel();
507 ~ILCodeLabel();
508
509 size_t GetCodeOffset();
510
511private:
512 void SetCodeOffset(size_t codeOffset);
513
514 ILCodeLabel* m_pNext;
515 ILStubLinker* m_pOwningStubLinker;
516 ILCodeStream* m_pCodeStreamOfLabel; // this is the ILCodeStream that the index is relative to
517 size_t m_codeOffset; // this is the absolute resolved IL offset after linking
518 UINT m_idxLabeledInstruction; // this is the index within the instruction buffer of the owning ILCodeStream
519};
520
521class ILCodeStream
522{
523 friend class ILStubLinker;
524
525public:
526 enum ILInstrEnum
527 {
528#define OPDEF(name,string,pop,push,oprType,opcType,l,s1,s2,ctrl) \
529 name,
530
531#include "opcode.def"
532#undef OPDEF
533 };
534
535private:
536 static ILInstrEnum LowerOpcode(ILInstrEnum instr, ILStubLinker::ILInstruction* pInstr);
537
538#ifdef _DEBUG
539 static bool IsSupportedInstruction(ILInstrEnum instr);
540#endif // _DEBUG
541
542 static bool IsBranchInstruction(ILInstrEnum instr)
543 {
544 LIMITED_METHOD_CONTRACT;
545 return ((instr >= CEE_BR) && (instr <= CEE_BLT_UN)) || (instr == CEE_LEAVE);
546 }
547
548
549public:
550 void EmitADD ();
551 void EmitADD_OVF ();
552 void EmitAND ();
553 void EmitARGLIST ();
554 void EmitBEQ (ILCodeLabel* pCodeLabel);
555 void EmitBGE (ILCodeLabel* pCodeLabel);
556 void EmitBGE_UN(ILCodeLabel* pCodeLabel);
557 void EmitBGT (ILCodeLabel* pCodeLabel);
558 void EmitBLE (ILCodeLabel* pCodeLabel);
559 void EmitBLE_UN (ILCodeLabel* pCodeLabel);
560 void EmitBLT (ILCodeLabel* pCodeLabel);
561 void EmitBR (ILCodeLabel* pCodeLabel);
562 void EmitBREAK ();
563 void EmitBRFALSE (ILCodeLabel* pCodeLabel);
564 void EmitBRTRUE (ILCodeLabel* pCodeLabel);
565 void EmitCALL (int token, int numInArgs, int numRetArgs);
566 void EmitCALLI (int token, int numInArgs, int numRetArgs);
567 void EmitCEQ ();
568 void EmitCGT ();
569 void EmitCGT_UN ();
570 void EmitCLT ();
571 void EmitCLT_UN ();
572 void EmitCONV_I ();
573 void EmitCONV_I1 ();
574 void EmitCONV_I2 ();
575 void EmitCONV_I4 ();
576 void EmitCONV_I8 ();
577 void EmitCONV_U ();
578 void EmitCONV_U1 ();
579 void EmitCONV_U2 ();
580 void EmitCONV_U4 ();
581 void EmitCONV_U8 ();
582 void EmitCONV_R4 ();
583 void EmitCONV_R8 ();
584 void EmitCONV_OVF_I4();
585 void EmitCONV_T (CorElementType type);
586 void EmitCPBLK ();
587 void EmitCPOBJ (int token);
588 void EmitDUP ();
589 void EmitENDFINALLY ();
590 void EmitINITBLK ();
591 void EmitINITOBJ (int token);
592 void EmitJMP (int token);
593 void EmitLDARG (unsigned uArgIdx);
594 void EmitLDARGA (unsigned uArgIdx);
595 void EmitLDC (DWORD_PTR uConst);
596 void EmitLDC_R4 (UINT32 uConst);
597 void EmitLDC_R8 (UINT64 uConst);
598 void EmitLDELEM_REF ();
599 void EmitLDFLD (int token);
600 void EmitLDFLDA (int token);
601 void EmitLDFTN (int token);
602 void EmitLDIND_I ();
603 void EmitLDIND_I1 ();
604 void EmitLDIND_I2 ();
605 void EmitLDIND_I4 ();
606 void EmitLDIND_I8 ();
607 void EmitLDIND_R4 ();
608 void EmitLDIND_R8 ();
609 void EmitLDIND_REF ();
610 void EmitLDIND_T (LocalDesc* pType);
611 void EmitLDIND_U1 ();
612 void EmitLDIND_U2 ();
613 void EmitLDIND_U4 ();
614 void EmitLDLEN ();
615 void EmitLDLOC (DWORD dwLocalNum);
616 void EmitLDLOCA (DWORD dwLocalNum);
617 void EmitLDNULL ();
618 void EmitLDOBJ (int token);
619 void EmitLDSFLD (int token);
620 void EmitLDSFLDA (int token);
621 void EmitLDTOKEN (int token);
622 void EmitLEAVE (ILCodeLabel* pCodeLabel);
623 void EmitLOCALLOC ();
624 void EmitMUL ();
625 void EmitMUL_OVF ();
626 void EmitNEWOBJ (int token, int numInArgs);
627 void EmitNOP (LPCSTR pszNopComment);
628 void EmitPOP ();
629 void EmitRET ();
630 void EmitSHR_UN ();
631 void EmitSTARG (unsigned uArgIdx);
632 void EmitSTELEM_REF ();
633 void EmitSTIND_I ();
634 void EmitSTIND_I1 ();
635 void EmitSTIND_I2 ();
636 void EmitSTIND_I4 ();
637 void EmitSTIND_I8 ();
638 void EmitSTIND_R4 ();
639 void EmitSTIND_R8 ();
640 void EmitSTIND_REF ();
641 void EmitSTIND_T (LocalDesc* pType);
642 void EmitSTFLD (int token);
643 void EmitSTLOC (DWORD dwLocalNum);
644 void EmitSTOBJ (int token);
645 void EmitSTSFLD (int token);
646 void EmitSUB ();
647 void EmitTHROW ();
648
649 // Overloads to simplify common usage patterns
650 void EmitNEWOBJ (BinderMethodID id, int numInArgs);
651 void EmitCALL (BinderMethodID id, int numInArgs, int numRetArgs);
652
653 void EmitLabel(ILCodeLabel* pLabel);
654 void EmitLoadThis ();
655 void EmitLoadNullPtr();
656 void EmitArgIteratorCreateAndLoad();
657
658 ILCodeLabel* NewCodeLabel();
659
660 void ClearCode();
661
662 //
663 // these functions just forward to the owning ILStubLinker
664 //
665
666 int GetToken(MethodDesc* pMD);
667 int GetToken(MethodTable* pMT);
668 int GetToken(TypeHandle th);
669 int GetToken(FieldDesc* pFD);
670
671 DWORD NewLocal(CorElementType typ = ELEMENT_TYPE_I);
672 DWORD NewLocal(LocalDesc loc);
673 DWORD SetStubTargetArgType(CorElementType typ, bool fConsumeStubArg = true);
674 DWORD SetStubTargetArgType(LocalDesc* pLoc = NULL, bool fConsumeStubArg = true); // passing pLoc = NULL means "use stub arg type"
675 void SetStubTargetReturnType(CorElementType typ);
676 void SetStubTargetReturnType(LocalDesc* pLoc);
677
678
679 //
680 // ctors/dtor
681 //
682
683 ILCodeStream(ILStubLinker* pOwner, ILStubLinker::CodeStreamType codeStreamType) :
684 m_pNextStream(NULL),
685 m_pOwner(pOwner),
686 m_pqbILInstructions(NULL),
687 m_uCurInstrIdx(0),
688 m_codeStreamType(codeStreamType)
689 {
690 }
691
692 ~ILCodeStream()
693 {
694 CONTRACTL
695 {
696 MODE_ANY;
697 NOTHROW;
698 GC_TRIGGERS;
699 }
700 CONTRACTL_END;
701
702 if (NULL != m_pqbILInstructions)
703 {
704 delete m_pqbILInstructions;
705 m_pqbILInstructions = NULL;
706 }
707 }
708
709 ILStubLinker::CodeStreamType GetStreamType() { return m_codeStreamType; }
710
711 LPCSTR GetStreamDescription(ILStubLinker::CodeStreamType streamType);
712
713protected:
714
715 void Emit(ILInstrEnum instr, INT16 iStackDelta, UINT_PTR uArg);
716
717 enum Constants
718 {
719 INITIAL_NUM_IL_INSTRUCTIONS = 64,
720 INITIAL_IL_INSTRUCTION_BUFFER_SIZE = INITIAL_NUM_IL_INSTRUCTIONS * sizeof(ILStubLinker::ILInstruction),
721 };
722
723 typedef CQuickBytesSpecifySize<INITIAL_IL_INSTRUCTION_BUFFER_SIZE> ILCodeStreamBuffer;
724
725 ILCodeStream* m_pNextStream;
726 ILStubLinker* m_pOwner;
727 ILCodeStreamBuffer* m_pqbILInstructions;
728 UINT m_uCurInstrIdx;
729 ILStubLinker::CodeStreamType m_codeStreamType; // Type of the ILCodeStream
730
731#ifndef _WIN64
732 const static UINT32 SPECIAL_VALUE_NAN_64_ON_32 = 0xFFFFFFFF;
733#endif // _WIN64
734};
735
736#define TOKEN_ILSTUB_TARGET_SIG (TokenFromRid(0xFFFFFF, mdtSignature))
737
738#endif // __STUBGEN_H__
739