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