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 | 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 | |
118 | class StubSigBuilder |
119 | { |
120 | public: |
121 | StubSigBuilder(); |
122 | |
123 | DWORD Append(LocalDesc* pLoc); |
124 | |
125 | protected: |
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 | // |
138 | class LocalSigBuilder : protected StubSigBuilder |
139 | { |
140 | public: |
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 | // |
162 | class FunctionSigBuilder : protected StubSigBuilder |
163 | { |
164 | public: |
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 | |
215 | protected: |
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 | // |
229 | class TokenLookupMap |
230 | { |
231 | public: |
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 | |
283 | protected: |
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 | |
329 | struct 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 | |
342 | class ILCodeLabel; |
343 | class ILCodeStream; |
344 | //--------------------------------------------------------------------------------------- |
345 | // |
346 | class ILStubLinker |
347 | { |
348 | friend class ILCodeLabel; |
349 | friend class ILCodeStream; |
350 | |
351 | public: |
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 | |
360 | protected: |
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 | |
379 | public: |
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); |
435 | protected: |
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 | |
439 | private: |
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 | |
462 | protected: |
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 | // |
500 | class ILCodeLabel |
501 | { |
502 | friend class ILStubLinker; |
503 | friend class ILCodeStream; |
504 | |
505 | public: |
506 | ILCodeLabel(); |
507 | ~ILCodeLabel(); |
508 | |
509 | size_t GetCodeOffset(); |
510 | |
511 | private: |
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 | |
521 | class ILCodeStream |
522 | { |
523 | friend class ILStubLinker; |
524 | |
525 | public: |
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 | |
535 | private: |
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 | |
549 | public: |
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 ); |
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 | |
713 | protected: |
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 | |