Merge pull request #20173 from fiigii/retest
[platform/upstream/coreclr.git] / src / vm / ilmarshalers.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: ILMarshalers.h
6 // 
7
8 //
9
10
11 #include "common.h"
12 #ifdef FEATURE_COMINTEROP
13 #include "winstring.h"
14 #endif //FEATURE_COMINTEROP
15 #include "stubgen.h"
16 #include "binder.h"
17 #include "marshalnative.h"
18 #include "clrvarargs.h"
19 #ifdef FEATURE_COMINTEROP
20 #include "stdinterfaces.h"
21 #endif
22
23 #define LOCAL_NUM_UNUSED ((DWORD)-1)
24
25 class ILStubMarshalHome
26 {
27 public:
28     typedef enum 
29     {
30         HomeType_Unspecified     = 0,
31         HomeType_ILLocal         = 1,
32         HomeType_ILArgument      = 2,
33         HomeType_ILByrefLocal    = 3,
34         HomeType_ILByrefArgument = 4
35     } MarshalHomeType;
36
37 private:
38     MarshalHomeType     m_homeType;
39     DWORD               m_dwHomeIndex;
40     
41 public:
42     void InitHome(MarshalHomeType homeType, DWORD dwHomeIndex)
43     {
44         LIMITED_METHOD_CONTRACT;
45         m_homeType = homeType;
46         m_dwHomeIndex = dwHomeIndex;
47     }
48         
49     void EmitLoadHome(ILCodeStream* pslILEmit)
50     {
51         CONTRACTL
52         {
53             THROWS;
54             GC_TRIGGERS;
55             MODE_ANY;
56         }
57         CONTRACTL_END;
58
59         switch (m_homeType)
60         {
61             case HomeType_ILLocal:      pslILEmit->EmitLDLOC(m_dwHomeIndex); break;
62             case HomeType_ILArgument:   pslILEmit->EmitLDARG(m_dwHomeIndex); break;
63         
64             default:
65                 UNREACHABLE_MSG("unexpected homeType passed to EmitLoadHome");
66                 break;
67         }
68     }
69
70     void EmitLoadHomeAddr(ILCodeStream* pslILEmit)
71     {
72         CONTRACTL
73         {
74             THROWS;
75             GC_TRIGGERS;
76             MODE_ANY;
77         }
78         CONTRACTL_END;
79         
80         switch (m_homeType)
81         {
82             case HomeType_ILLocal:         pslILEmit->EmitLDLOCA(m_dwHomeIndex); break;
83             case HomeType_ILArgument:      pslILEmit->EmitLDARGA(m_dwHomeIndex); break;
84             case HomeType_ILByrefLocal:    pslILEmit->EmitLDLOC(m_dwHomeIndex);  break;
85             case HomeType_ILByrefArgument: pslILEmit->EmitLDARG(m_dwHomeIndex);  break;
86
87             default:
88                 UNREACHABLE_MSG("unexpected homeType passed to EmitLoadHomeAddr");
89                 break;
90         }
91     }        
92
93     void EmitStoreHome(ILCodeStream* pslILEmit)
94     {
95         CONTRACTL
96         {
97             THROWS;
98             GC_TRIGGERS;
99             MODE_ANY;
100         }
101         CONTRACTL_END;
102         
103         switch (m_homeType)
104         {
105             case HomeType_ILLocal:      pslILEmit->EmitSTLOC(m_dwHomeIndex); break;
106             case HomeType_ILArgument:   pslILEmit->EmitSTARG(m_dwHomeIndex); break;
107
108             default:
109                 UNREACHABLE_MSG("unexpected homeType passed to EmitStoreHome");
110                 break;
111         }
112     }
113
114     void EmitStoreHomeAddr(ILCodeStream* pslILEmit)
115     {
116         CONTRACTL
117         {
118             THROWS;
119             GC_TRIGGERS;
120             MODE_ANY;
121         }
122         CONTRACTL_END;
123         
124         switch (m_homeType)
125         {
126             case HomeType_ILByrefLocal:    pslILEmit->EmitSTLOC(m_dwHomeIndex); break;
127             case HomeType_ILByrefArgument: pslILEmit->EmitSTARG(m_dwHomeIndex); break;
128
129             default:
130                 UNREACHABLE_MSG("unexpected homeType passed to EmitStoreHomeAddr");
131                 break;
132         }
133     }
134
135     void EmitCopyFromByrefArg(ILCodeStream* pslILEmit, LocalDesc* pManagedType, DWORD argidx)
136     {
137         CONTRACTL
138         {
139             THROWS;
140             GC_TRIGGERS;
141             MODE_ANY;
142         }
143         CONTRACTL_END;
144         
145         CONSISTENCY_CHECK(pManagedType->cbType == 1);
146         if (pManagedType->IsValueClass())
147         {
148             EmitLoadHomeAddr(pslILEmit);    // dest
149             pslILEmit->EmitLDARG(argidx);   // src
150             pslILEmit->EmitCPOBJ(pslILEmit->GetToken(pManagedType->InternalToken));
151         }
152         else
153         {
154             pslILEmit->EmitLDARG(argidx);
155             pslILEmit->EmitLDIND_T(pManagedType);
156             EmitStoreHome(pslILEmit);
157         }
158     }
159
160     void EmitCopyToByrefArg(ILCodeStream* pslILEmit, LocalDesc* pManagedType, DWORD argidx)
161     {
162         CONTRACTL
163         {
164             THROWS;
165             GC_TRIGGERS;
166             MODE_ANY;
167         }
168         CONTRACTL_END;
169
170         if (pManagedType->IsValueClass())
171         {
172             pslILEmit->EmitLDARG(argidx);   // dest
173             EmitLoadHomeAddr(pslILEmit);    // src
174             pslILEmit->EmitCPOBJ(pslILEmit->GetToken(pManagedType->InternalToken));
175         }
176         else
177         {
178             pslILEmit->EmitLDARG(argidx);
179             EmitLoadHome(pslILEmit);
180             pslILEmit->EmitSTIND_T(pManagedType);
181         }
182     }
183
184     void EmitCopyToByrefArgWithNullCheck(ILCodeStream* pslILEmit, LocalDesc* pManagedType, DWORD argidx)
185     {
186         CONTRACTL
187         {
188             THROWS;
189             GC_TRIGGERS;
190             MODE_ANY;
191         }
192         CONTRACTL_END;
193
194         ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
195
196         // prevent null-ref exception by an explicit check
197         pslILEmit->EmitLDARG(argidx);
198         pslILEmit->EmitBRFALSE(pNullRefLabel);
199
200         EmitCopyToByrefArg(pslILEmit, pManagedType, argidx);
201
202         pslILEmit->EmitLabel(pNullRefLabel);
203     }
204 };
205         
206
207 class ILMarshaler 
208 {
209 protected:
210
211 #ifdef _DEBUG
212     const static UINT   s_cbStackAllocThreshold = 128;
213 #else
214     const static UINT   s_cbStackAllocThreshold = 2048;
215 #endif // _DEBUG
216
217     OverrideProcArgs*   m_pargs;
218     NDirectStubLinker*  m_pslNDirect;
219     ILCodeStream*       m_pcsMarshal;
220     ILCodeStream*       m_pcsUnmarshal;
221     UINT                m_argidx;
222
223     DWORD               m_dwMarshalFlags;
224
225     ILStubMarshalHome   m_nativeHome;
226     ILStubMarshalHome   m_managedHome;
227
228     DWORD               m_dwMngdMarshalerLocalNum;
229
230 public:
231
232     ILMarshaler() : 
233         m_pslNDirect(NULL)
234     {
235     }
236
237     virtual ~ILMarshaler()
238     {
239         LIMITED_METHOD_CONTRACT;
240     }
241
242     void SetNDirectStubLinker(NDirectStubLinker* pslNDirect)
243     {
244         LIMITED_METHOD_CONTRACT;
245         CONSISTENCY_CHECK(NULL == m_pslNDirect);
246         m_pslNDirect = pslNDirect;
247     }
248
249     void Init(ILCodeStream* pcsMarshal, 
250             ILCodeStream* pcsUnmarshal,
251             UINT argidx,
252             DWORD dwMarshalFlags, 
253             OverrideProcArgs* pargs)
254     {
255         LIMITED_METHOD_CONTRACT;
256         CONSISTENCY_CHECK_MSG(m_pslNDirect != NULL, "please call SetNDirectStubLinker() before EmitMarshalArgument or EmitMarshalReturnValue");
257         m_pcsMarshal = pcsMarshal;
258         m_pcsUnmarshal = pcsUnmarshal;
259         m_pargs = pargs;
260         m_dwMarshalFlags = dwMarshalFlags;
261         m_argidx = argidx;
262         m_dwMngdMarshalerLocalNum = -1;
263     }
264
265 protected:
266     static inline bool IsCLRToNative(DWORD dwMarshalFlags)
267     {
268         LIMITED_METHOD_CONTRACT;
269         return (0 != (dwMarshalFlags & MARSHAL_FLAG_CLR_TO_NATIVE));
270     }
271         
272     static inline bool IsIn(DWORD dwMarshalFlags)
273     {
274         LIMITED_METHOD_CONTRACT;
275         return (0 != (dwMarshalFlags & MARSHAL_FLAG_IN));
276     }
277
278     static inline bool IsOut(DWORD dwMarshalFlags)
279     {
280         LIMITED_METHOD_CONTRACT;
281         return (0 != (dwMarshalFlags & MARSHAL_FLAG_OUT));
282     }
283
284     static inline bool IsByref(DWORD dwMarshalFlags)
285     {
286         LIMITED_METHOD_CONTRACT;
287         return (0 != (dwMarshalFlags & MARSHAL_FLAG_BYREF));
288     }
289
290     static inline bool IsHresultSwap(DWORD dwMarshalFlags)
291     {
292         LIMITED_METHOD_CONTRACT;
293         return (0 != (dwMarshalFlags & MARSHAL_FLAG_HRESULT_SWAP));
294     }
295
296     static inline bool IsRetval(DWORD dwMarshalFlags)
297     {
298         LIMITED_METHOD_CONTRACT;
299         return (0 != (dwMarshalFlags & MARSHAL_FLAG_RETVAL));
300     }
301
302     static inline bool IsHiddenLengthParam(DWORD dwMarshalFlags)
303     {
304         LIMITED_METHOD_CONTRACT;
305         return (0 != (dwMarshalFlags & MARSHAL_FLAG_HIDDENLENPARAM));
306     }
307
308     void EmitLoadManagedValue(ILCodeStream* pslILEmit)
309     {
310         WRAPPER_NO_CONTRACT;
311         m_managedHome.EmitLoadHome(pslILEmit);
312     }
313
314     void EmitLoadNativeValue(ILCodeStream* pslILEmit)
315     {
316         WRAPPER_NO_CONTRACT;
317         m_nativeHome.EmitLoadHome(pslILEmit);
318     }
319
320     void EmitLoadManagedHomeAddr(ILCodeStream* pslILEmit)
321     {
322         WRAPPER_NO_CONTRACT;
323         m_managedHome.EmitLoadHomeAddr(pslILEmit);
324     }
325
326     void EmitLoadNativeHomeAddr(ILCodeStream* pslILEmit)
327     {
328         WRAPPER_NO_CONTRACT;
329         m_nativeHome.EmitLoadHomeAddr(pslILEmit);
330     }
331         
332     void EmitStoreManagedValue(ILCodeStream* pslILEmit)
333     {
334         WRAPPER_NO_CONTRACT;
335         m_managedHome.EmitStoreHome(pslILEmit);
336     }
337
338     void EmitStoreManagedHomeAddr(ILCodeStream* pslILEmit)
339     {
340         WRAPPER_NO_CONTRACT;
341         m_managedHome.EmitStoreHomeAddr(pslILEmit);
342     }
343
344     void EmitStoreNativeValue(ILCodeStream* pslILEmit)
345     {
346         WRAPPER_NO_CONTRACT;
347         m_nativeHome.EmitStoreHome(pslILEmit);
348     }
349
350     void EmitStoreNativeHomeAddr(ILCodeStream* pslILEmit)
351     {
352         WRAPPER_NO_CONTRACT;
353         m_nativeHome.EmitStoreHomeAddr(pslILEmit);
354     }
355
356 public:
357
358     virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
359     {
360         LIMITED_METHOD_CONTRACT;
361         return true;
362     }
363
364     virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
365     {
366         LIMITED_METHOD_CONTRACT;
367         return true;
368     }
369
370     // True if marshaling creates data that could need cleanup.
371     bool NeedsMarshalCleanupIndex()
372     {
373         WRAPPER_NO_CONTRACT;
374         return (NeedsClearNative() || NeedsClearCLR());
375     }
376
377     // True if unmarshaling creates data that could need exception cleanup ("rollback").
378     bool NeedsUnmarshalCleanupIndex()
379     {
380         WRAPPER_NO_CONTRACT;
381         return (NeedsClearNative() && !IsCLRToNative(m_dwMarshalFlags));
382     }
383
384     void EmitMarshalArgument(
385                 ILCodeStream*   pcsMarshal, 
386                 ILCodeStream*   pcsUnmarshal, 
387                 UINT            argidx, 
388                 DWORD           dwMarshalFlags,
389                 OverrideProcArgs*  pargs)
390     {
391         STANDARD_VM_CONTRACT;
392
393         Init(pcsMarshal, pcsUnmarshal, argidx, dwMarshalFlags, pargs);
394
395         // We could create the marshaler in the marshal stream right before it's needed (i.e. within the try block),
396         // or in the setup stream (outside of the try block). For managed-to-unmanaged marshaling it does not actually
397         // make much difference except that using setup stream saves us from cleaning up already-marshaled arguments
398         // in case of an exception. For unmanaged-to-managed, we may need to perform cleanup of the incoming arguments
399         // before we were able to marshal them. Therefore this must not happen within the try block so we don't try
400         // to use marshalers that have not been initialized. Potentially leaking unmanaged resources is by-design and
401         // there's not much we can do about it (we cannot do cleanup if we cannot create the marshaler).
402         EmitCreateMngdMarshaler(m_pslNDirect->GetSetupCodeStream());
403
404         if (IsCLRToNative(dwMarshalFlags))
405         {
406             if (IsByref(dwMarshalFlags))
407             {
408                 EmitMarshalArgumentCLRToNativeByref();
409             }
410             else
411             {
412                 EmitMarshalArgumentCLRToNative();
413             }
414         }
415         else
416         {
417             if (IsByref(dwMarshalFlags))
418             {
419                 EmitMarshalArgumentNativeToCLRByref();
420             }
421             else
422             {
423                 EmitMarshalArgumentNativeToCLR();
424             }
425         }
426     }
427
428 #ifdef FEATURE_COMINTEROP
429     void EmitMarshalHiddenLengthArgument(ILCodeStream *pcsMarshal,
430                                          ILCodeStream *pcsUnmarshal,
431                                          MarshalInfo *pArrayInfo,
432                                          UINT arrayIndex,
433                                          DWORD dwMarshalFlags,
434                                          UINT hiddenArgIndex,
435                                          OverrideProcArgs *pargs,
436                                          __out DWORD *pdwHiddenLengthManagedHomeLocal,
437                                          __out DWORD *pdwHiddenLengthNativeHomeLocal)
438     {
439         CONTRACTL
440         {
441             STANDARD_VM_CHECK;
442             PRECONDITION(IsHiddenLengthParam(dwMarshalFlags));
443         }
444         CONTRACTL_END;
445
446         Init(pcsMarshal, pcsUnmarshal, hiddenArgIndex, dwMarshalFlags, pargs);
447         EmitCreateMngdMarshaler(m_pslNDirect->GetSetupCodeStream());
448
449         // Create a local to be the home of the length parameter
450         DWORD dwManagedLocalHome = m_pcsMarshal->NewLocal(GetManagedType());
451         m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, dwManagedLocalHome);
452         *pdwHiddenLengthManagedHomeLocal = dwManagedLocalHome;
453
454         // managed length = 0
455         m_pcsMarshal->EmitLDC(0);
456         m_pcsMarshal->EmitCONV_T(pArrayInfo->GetHiddenLengthParamElementType());
457         m_pcsMarshal->EmitSTLOC(dwManagedLocalHome);
458
459         // And a local to be the home of the marshaled length
460         LocalDesc nativeArgType(GetNativeType());
461         DWORD dwNativeHomeLocal = m_pcsMarshal->NewLocal(nativeArgType);
462         if (IsByref(dwMarshalFlags))
463         {
464             nativeArgType.MakeByRef();
465         }
466         m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, dwNativeHomeLocal);
467         *pdwHiddenLengthNativeHomeLocal = dwNativeHomeLocal;
468
469         // Update the native signature to contain the new native parameter
470         m_pcsMarshal->SetStubTargetArgType(&nativeArgType, false);
471
472         if (IsCLRToNative(dwMarshalFlags))
473         {
474             // Load the length of the array into the local
475             if (IsIn(dwMarshalFlags))
476             {
477                 ILCodeLabel *pSkipGetLengthLabel = m_pcsMarshal->NewCodeLabel();
478                 m_pcsMarshal->EmitLDARG(arrayIndex);
479                 m_pcsMarshal->EmitBRFALSE(pSkipGetLengthLabel);
480
481                 m_pcsMarshal->EmitLDARG(arrayIndex);
482
483                 if (IsByref(dwMarshalFlags))
484                 {
485                     // if (*array == null) goto pSkipGetLengthLabel
486                     m_pcsMarshal->EmitLDIND_REF();
487                     m_pcsMarshal->EmitBRFALSE(pSkipGetLengthLabel);
488                     
489                     // array = *array
490                     m_pcsMarshal->EmitLDARG(arrayIndex);
491                     m_pcsMarshal->EmitLDIND_REF();
492                 }
493
494                 m_pcsMarshal->EmitLDLEN();
495                 m_pcsMarshal->EmitCONV_T(pArrayInfo->GetHiddenLengthParamElementType());
496                 m_pcsMarshal->EmitSTLOC(dwManagedLocalHome);
497                 m_pcsMarshal->EmitLabel(pSkipGetLengthLabel);
498             }
499
500             if (IsByref(dwMarshalFlags))
501             {
502                 EmitMarshalArgumentContentsCLRToNativeByref(true);
503             }
504             else
505             {
506                 EmitMarshalArgumentContentsCLRToNative();
507             }
508         }
509         else
510         {
511             // Load the length of the array into the local
512             if (IsIn(dwMarshalFlags))
513             {
514                 m_pcsMarshal->EmitLDARG(hiddenArgIndex);
515                 if (IsByref(dwMarshalFlags))
516                 {
517                     LocalDesc nativeParamType(GetNativeType());
518                     m_pcsMarshal->EmitLDIND_T(&nativeParamType);
519                 }
520                 m_pcsMarshal->EmitSTLOC(dwNativeHomeLocal);
521             }
522
523             if (IsByref(dwMarshalFlags))
524             {
525                 EmitMarshalArgumentContentsNativeToCLRByref(true);
526             }
527             else
528             {
529                 EmitMarshalArgumentContentsNativeToCLR();
530             }
531
532             // We can't copy the final length back to the parameter just yet, since we don't know what
533             // local the array lives in.  Instead, we rely on the hidden length array marshaler to copy
534             // the value into the out parameter for us.
535         }
536     }
537
538 #endif // FEATURE_COMINTEROP
539
540     virtual void EmitSetupArgument(ILCodeStream* pslILEmit)
541     {
542         STANDARD_VM_CONTRACT;
543
544         if (IsCLRToNative(m_dwMarshalFlags))
545         {
546             if (IsNativePassedByRef())
547             {
548                 EmitLoadNativeHomeAddr(pslILEmit);
549             }
550             else
551             {
552                 EmitLoadNativeValue(pslILEmit);
553             }
554         }
555         else
556         {
557             if (IsManagedPassedByRef())
558             {
559                 EmitLoadManagedHomeAddr(pslILEmit);
560             }
561             else
562             {
563                 EmitLoadManagedValue(pslILEmit);
564             }
565         }
566     }
567
568     virtual void EmitMarshalReturnValue(
569                 ILCodeStream* pcsMarshal, 
570                 ILCodeStream* pcsUnmarshal,
571                 ILCodeStream* pcsDispatch,
572                 UINT argidx,
573                 UINT16 wNativeSize,
574                 DWORD dwMarshalFlags,
575                 OverrideProcArgs*  pargs)
576     {
577         STANDARD_VM_CONTRACT;
578
579         Init(pcsMarshal, pcsUnmarshal, argidx, dwMarshalFlags, pargs);
580
581         LocalDesc nativeType = GetNativeType();
582         LocalDesc managedType = GetManagedType();
583         
584         bool byrefNativeReturn = false;
585         CorElementType typ = ELEMENT_TYPE_VOID;
586         UINT32 nativeSize = 0;
587
588         // we need to convert value type return types to primitives as
589         // JIT does not inline P/Invoke calls that return structures
590         if (nativeType.IsValueClass())
591         {
592             if (wNativeSize == VARIABLESIZE)
593             {
594                 // the unmanaged type size is variable
595                 nativeSize = m_pargs->m_pMT->GetNativeSize();
596             }
597             else
598             {
599                 // the unmanaged type size is fixed
600                 nativeSize = wNativeSize;
601             }
602
603 #if defined(_TARGET_X86_)
604             // JIT32 and JIT64 (which is only used on the Windows Desktop CLR) has a problem generating
605             // code for the pinvoke ILStubs which do a return using a struct type.  Therefore, we
606             // change the signature of calli to return void and make the return buffer as first argument. 
607
608             // for X86 and AMD64-Windows we bash the return type from struct to U1, U2, U4 or U8
609             // and use byrefNativeReturn for all other structs.
610             // for UNIX_X86_ABI, we always need a return buffer argument for any size of structs.
611             switch (nativeSize)
612             {
613 #ifndef UNIX_X86_ABI
614                 case 1: typ = ELEMENT_TYPE_U1; break;
615                 case 2: typ = ELEMENT_TYPE_U2; break;
616                 case 4: typ = ELEMENT_TYPE_U4; break;
617                 case 8: typ = ELEMENT_TYPE_U8; break;
618 #endif
619                 default: byrefNativeReturn = true; break;
620             }
621 #endif
622         }
623
624         if (IsHresultSwap(dwMarshalFlags) || (byrefNativeReturn && IsCLRToNative(dwMarshalFlags)))
625         {
626             LocalDesc extraParamType = nativeType;
627             extraParamType.MakeByRef();
628
629             m_pcsMarshal->SetStubTargetArgType(&extraParamType, false);
630             
631             if (IsHresultSwap(dwMarshalFlags))
632             {
633                 // HRESULT swapping: the original return value is transformed into an extra
634                 // byref parameter and the target is expected to return an HRESULT
635                 m_pcsMarshal->SetStubTargetReturnType(ELEMENT_TYPE_I4);    // native method returns an HRESULT
636             }
637             else
638             {
639                 // byref structure return: the original return value is transformed into an
640                 // extra byref parameter and the target is not expected to return anything
641                 //
642                 // note: we do this only for forward calls because [unmanaged calling conv.
643                 // uses byref return] implies [managed calling conv. uses byref return]
644                 m_pcsMarshal->SetStubTargetReturnType(ELEMENT_TYPE_VOID);
645             }
646         }
647         else
648         {
649             if (typ != ELEMENT_TYPE_VOID)
650             {
651                 // small structure return: the original return value is transformed into
652                 // ELEMENT_TYPE_U1, ELEMENT_TYPE_U2, ELEMENT_TYPE_U4, or ELEMENT_TYPE_U8
653                 m_pcsMarshal->SetStubTargetReturnType(typ);
654             }
655             else
656             {
657                 m_pcsMarshal->SetStubTargetReturnType(&nativeType);
658             }
659         }
660         
661         m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(managedType));
662         m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(nativeType));
663
664         EmitCreateMngdMarshaler(m_pcsMarshal);
665
666         if (IsCLRToNative(dwMarshalFlags))
667         {
668             if (IsHresultSwap(dwMarshalFlags) || byrefNativeReturn)
669             {
670                 EmitReInitNative(m_pcsMarshal);
671                 EmitLoadNativeHomeAddr(pcsDispatch);    // load up the byref native type as an extra arg
672             }
673             else
674             {
675                 if (typ != ELEMENT_TYPE_VOID)
676                 {
677                     // small structure forward: the returned integer is memcpy'd into native home
678                     // of the structure
679
680                     DWORD dwTempLocalNum = m_pcsUnmarshal->NewLocal(typ);
681                     m_pcsUnmarshal->EmitSTLOC(dwTempLocalNum);
682                             
683                     // cpblk
684                     m_nativeHome.EmitLoadHomeAddr(m_pcsUnmarshal);
685                     m_pcsUnmarshal->EmitLDLOCA(dwTempLocalNum);
686                     m_pcsUnmarshal->EmitLDC(nativeSize);
687                     m_pcsUnmarshal->EmitCPBLK();
688                 }
689                 else
690                 {
691                     EmitStoreNativeValue(m_pcsUnmarshal);
692                 }
693             }
694
695             if (NeedsMarshalCleanupIndex())
696             {
697                 m_pslNDirect->EmitSetArgMarshalIndex(m_pcsUnmarshal, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx);
698             }
699
700             EmitConvertSpaceAndContentsNativeToCLR(m_pcsUnmarshal);
701
702             EmitCleanupCLRToNative();
703
704             EmitLoadManagedValue(m_pcsUnmarshal);
705         }
706         else
707         {
708             EmitStoreManagedValue(m_pcsUnmarshal);
709
710             if (NeedsMarshalCleanupIndex())
711             {
712                 m_pslNDirect->EmitSetArgMarshalIndex(m_pcsUnmarshal, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx);
713             }
714
715             if (IsHresultSwap(dwMarshalFlags))
716             {
717                 // we have to skip unmarshaling return value into the HRESULT-swapped argument
718                 // if the argument came as NULL (otherwise we would leak unmanaged resources as
719                 // we have no way of passing them back to the caller)
720                 ILCodeLabel *pSkipConversionLabel = m_pcsUnmarshal->NewCodeLabel();
721
722                 m_pcsUnmarshal->EmitLDARG(argidx);
723                 m_pcsUnmarshal->EmitBRFALSE(pSkipConversionLabel);
724                 EmitConvertSpaceAndContentsCLRToNative(m_pcsUnmarshal);
725                 m_pcsUnmarshal->EmitLabel(pSkipConversionLabel);
726             }
727             else
728             {
729                 EmitConvertSpaceAndContentsCLRToNative(m_pcsUnmarshal);
730             }
731
732             if (NeedsUnmarshalCleanupIndex())
733             {
734                 // if an exception is thrown after this point, we will clean up the unmarshaled retval
735                 m_pslNDirect->EmitSetArgMarshalIndex(m_pcsUnmarshal, NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL);
736             }
737
738             EmitCleanupNativeToCLR();
739
740             if (IsHresultSwap(dwMarshalFlags))
741             {
742                 // we tolerate NULL here mainly for backward compatibility reasons
743                 m_nativeHome.EmitCopyToByrefArgWithNullCheck(m_pcsUnmarshal, &nativeType, argidx);
744                 m_pcsUnmarshal->EmitLDC(S_OK);
745             }
746             else
747             {
748                 if (typ != ELEMENT_TYPE_VOID)
749                 {
750                     // small structure return (reverse): native home of the structure is memcpy'd
751                     // into the integer to be returned from the stub
752
753                     DWORD dwTempLocalNum = m_pcsUnmarshal->NewLocal(typ);
754                             
755                     // cpblk
756                     m_pcsUnmarshal->EmitLDLOCA(dwTempLocalNum);
757                     m_nativeHome.EmitLoadHomeAddr(m_pcsUnmarshal);
758                     m_pcsUnmarshal->EmitLDC(nativeSize);
759                     m_pcsUnmarshal->EmitCPBLK();
760
761                     m_pcsUnmarshal->EmitLDLOC(dwTempLocalNum);
762                 }
763                 else
764                 {
765                     EmitLoadNativeValue(m_pcsUnmarshal);
766                 }
767             }
768
769             // make sure we free (and zero) the return value if an exception is thrown
770             EmitExceptionCleanupNativeToCLR();
771         }
772     }        
773
774
775 protected:
776
777     virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
778     {
779         LIMITED_METHOD_CONTRACT;
780     }
781
782     virtual void EmitLoadMngdMarshaler(ILCodeStream* pslILEmit)
783     {
784         CONTRACTL
785         {
786             THROWS;
787             GC_TRIGGERS;
788             MODE_ANY;
789         }
790         CONTRACTL_END;
791
792         CONSISTENCY_CHECK((DWORD)-1 != m_dwMngdMarshalerLocalNum);
793         pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
794     }
795
796     void EmitSetupSigAndDefaultHomesCLRToNative()
797     {
798         CONTRACTL
799         {
800             STANDARD_VM_CHECK;
801             PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
802         }
803         CONTRACTL_END;
804
805         LocalDesc nativeArgType = GetNativeType();
806         DWORD     dwNativeHomeLocalNum = m_pcsMarshal->NewLocal(nativeArgType);
807         m_pcsMarshal->SetStubTargetArgType(&nativeArgType);
808
809         m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILArgument, m_argidx);
810         m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, dwNativeHomeLocalNum);
811     }
812
813     void EmitCleanupCLRToNativeTemp()
814     {
815         STANDARD_VM_CONTRACT;
816
817         if (NeedsClearNative())
818         {
819             CONSISTENCY_CHECK(NeedsMarshalCleanupIndex());
820
821             ILCodeStream* pcsCleanup = m_pslNDirect->GetCleanupCodeStream();
822             ILCodeLabel*  pSkipClearNativeLabel = pcsCleanup->NewCodeLabel();
823
824             m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
825                                                  NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx,
826                                                  NDirectStubLinker::BranchIfNotMarshaled,
827                                                  pSkipClearNativeLabel);
828
829             EmitClearNativeTemp(pcsCleanup);
830             pcsCleanup->EmitLabel(pSkipClearNativeLabel);
831         }
832     }
833
834     void EmitCleanupCLRToNative()
835     {
836         STANDARD_VM_CONTRACT;
837
838         if (NeedsClearNative())
839         {
840             CONSISTENCY_CHECK(NeedsMarshalCleanupIndex());
841
842             ILCodeStream* pcsCleanup = m_pslNDirect->GetCleanupCodeStream();
843             ILCodeLabel*  pSkipClearNativeLabel = pcsCleanup->NewCodeLabel();
844
845             m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
846                                                  NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx,
847                                                  NDirectStubLinker::BranchIfNotMarshaled,
848                                                  pSkipClearNativeLabel);
849
850             EmitClearNative(pcsCleanup);
851             pcsCleanup->EmitLabel(pSkipClearNativeLabel);
852         }
853     }
854
855     virtual void EmitMarshalArgumentCLRToNative()
856     {
857         CONTRACTL
858         {
859             STANDARD_VM_CHECK;
860             PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
861         }
862         CONTRACTL_END;
863
864         EmitSetupSigAndDefaultHomesCLRToNative();
865         EmitMarshalArgumentContentsCLRToNative();
866     }
867
868     void EmitMarshalArgumentContentsCLRToNative()
869     {
870         CONTRACTL
871         {
872             STANDARD_VM_CHECK;
873             PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
874         }
875         CONTRACTL_END;
876
877         //
878         // marshal
879         //
880         if (IsIn(m_dwMarshalFlags))
881         {
882             EmitConvertSpaceAndContentsCLRToNativeTemp(m_pcsMarshal);
883         }
884         else
885         {
886             EmitConvertSpaceCLRToNativeTemp(m_pcsMarshal);
887         }
888
889         //
890         // unmarshal
891         //
892         if (IsOut(m_dwMarshalFlags))
893         {
894             if (IsIn(m_dwMarshalFlags))
895             {
896                 EmitClearCLRContents(m_pcsUnmarshal);
897             }
898             EmitConvertContentsNativeToCLR(m_pcsUnmarshal);
899         }
900
901         EmitCleanupCLRToNativeTemp();
902    }
903
904     void EmitSetupSigAndDefaultHomesCLRToNativeByref(bool fBlittable = false)
905     {
906         CONTRACTL
907         {
908             STANDARD_VM_CHECK;
909             PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
910         }
911         CONTRACTL_END;
912
913         LocalDesc nativeType = GetNativeType();
914         LocalDesc managedType = GetManagedType();
915
916         LocalDesc nativeArgType = nativeType;
917         nativeArgType.MakeByRef();
918         m_pcsMarshal->SetStubTargetArgType(&nativeArgType);
919
920         if (fBlittable)
921         {
922             // we will not work with the actual data but only with a pointer to that data
923             // (the managed and native type had better be the same if it's blittable)
924             _ASSERTE(nativeType.ElementType[0] == managedType.ElementType[0]);
925
926             // native home will keep the containing object pinned
927             nativeType.MakeByRef();
928             nativeType.MakePinned();
929
930             m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILByrefArgument, m_argidx);
931             m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILByrefLocal, m_pcsMarshal->NewLocal(nativeType));
932         }
933         else
934         {
935             m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(managedType));
936             m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(nativeType));
937         }
938     }
939
940     virtual void EmitMarshalArgumentCLRToNativeByref()
941     {
942         CONTRACTL
943         {
944             STANDARD_VM_CHECK;
945             PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
946         }
947         CONTRACTL_END;
948
949         EmitSetupSigAndDefaultHomesCLRToNativeByref();
950         EmitMarshalArgumentContentsCLRToNativeByref(false);
951     }
952
953     void EmitMarshalArgumentContentsCLRToNativeByref(bool managedHomeAlreadyInitialized)
954     {
955         CONTRACTL
956         {
957             STANDARD_VM_CHECK;
958             PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
959         }
960         CONTRACTL_END;
961
962         LocalDesc managedType = GetManagedType();
963
964         //
965         // marshal
966         //
967         if (IsIn(m_dwMarshalFlags) && ! IsOut(m_dwMarshalFlags))
968         {
969             if (!managedHomeAlreadyInitialized)
970             {
971                 m_managedHome.EmitCopyFromByrefArg(m_pcsMarshal, &managedType, m_argidx);
972             }
973
974             EmitConvertSpaceAndContentsCLRToNativeTemp(m_pcsMarshal);
975         }
976         else if (IsIn(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags)) 
977         {
978             if (!managedHomeAlreadyInitialized)
979             {
980                 m_managedHome.EmitCopyFromByrefArg(m_pcsMarshal, &managedType, m_argidx);
981             }
982
983             EmitConvertSpaceAndContentsCLRToNative(m_pcsMarshal);
984         }
985         else
986         {
987             EmitReInitNative(m_pcsMarshal);
988         }
989
990         //
991         // unmarshal
992         //
993         if (IsOut(m_dwMarshalFlags))
994         {
995             EmitClearCLR(m_pcsUnmarshal);
996
997             EmitConvertSpaceAndContentsNativeToCLR(m_pcsUnmarshal);
998             
999             if (!managedHomeAlreadyInitialized)
1000             {
1001                 m_managedHome.EmitCopyToByrefArg(m_pcsUnmarshal, &managedType, m_argidx);
1002             }
1003
1004             EmitCleanupCLRToNative();
1005         }
1006         else
1007         {
1008             EmitCleanupCLRToNativeTemp();
1009         }
1010         //
1011         // @TODO: ensure ReInitNative is called on [in,out] byref args when an exception occurs 
1012         //
1013     }
1014
1015     void EmitSetupSigAndDefaultHomesNativeToCLR()
1016     {
1017         CONTRACTL
1018         {
1019             STANDARD_VM_CHECK;
1020             PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
1021         }
1022         CONTRACTL_END;
1023         
1024         LocalDesc nativeArgType = GetNativeType();
1025         m_pcsMarshal->SetStubTargetArgType(&nativeArgType);
1026
1027         m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(GetManagedType()));
1028         m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILArgument, m_argidx);
1029     }
1030
1031     void EmitCleanupNativeToCLR()
1032     {
1033         STANDARD_VM_CONTRACT;
1034
1035         if (NeedsClearCLR())
1036         {
1037             CONSISTENCY_CHECK(NeedsMarshalCleanupIndex());
1038
1039             ILCodeStream* pcsCleanup = m_pslNDirect->GetCleanupCodeStream();
1040             ILCodeLabel*  pSkipClearCLRLabel = pcsCleanup->NewCodeLabel();
1041
1042             m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
1043                                                  NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx,
1044                                                  NDirectStubLinker::BranchIfNotMarshaled,
1045                                                  pSkipClearCLRLabel);
1046
1047             EmitClearCLR(pcsCleanup);
1048             pcsCleanup->EmitLabel(pSkipClearCLRLabel);
1049         }
1050     }
1051
1052     // Emits cleanup code that runs only if an exception is thrown during execution of an IL stub (its try
1053     // block to be precise). The goal is to roll back allocations of native resources that may have already
1054     // happened to prevent leaks, and also clear output arguments to prevent passing out invalid data - most
1055     // importantly dangling pointers. The canonical example is an exception thrown during unmarshaling of
1056     // an argument at which point other arguments have already been unmarshaled.
1057     void EmitExceptionCleanupNativeToCLR()
1058     {
1059         STANDARD_VM_CONTRACT;
1060
1061         _ASSERTE(IsRetval(m_dwMarshalFlags) || IsOut(m_dwMarshalFlags));
1062
1063         LocalDesc nativeType = GetNativeType();
1064         ILCodeStream *pcsCleanup = m_pslNDirect->GetExceptionCleanupCodeStream();
1065
1066         if (NeedsClearNative())
1067         {
1068             m_pslNDirect->SetExceptionCleanupNeeded();
1069
1070             ILCodeLabel *pSkipCleanupLabel = pcsCleanup->NewCodeLabel();
1071
1072             // if this is byref in/out and we have not marshaled this argument
1073             // yet, we need to populate the native home with the incoming value
1074             if (IsIn(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags))
1075             {
1076                 ILCodeLabel *pSkipCopyLabel = pcsCleanup->NewCodeLabel();
1077
1078                 CONSISTENCY_CHECK(NeedsMarshalCleanupIndex());
1079                 m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
1080                                                      NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx,
1081                                                      NDirectStubLinker::BranchIfMarshaled,
1082                                                      pSkipCopyLabel);
1083
1084                 pcsCleanup->EmitLDARG(m_argidx);
1085                 pcsCleanup->EmitBRFALSE(pSkipCleanupLabel); // if the argument is NULL, skip cleanup completely
1086
1087                 m_nativeHome.EmitCopyFromByrefArg(pcsCleanup, &nativeType, m_argidx);
1088
1089                 pcsCleanup->EmitLabel(pSkipCopyLabel);
1090             }
1091
1092             // if this is retval or out-only, the native home does not get initialized until we unmarshal it
1093             if (IsRetval(m_dwMarshalFlags) || !IsIn(m_dwMarshalFlags))
1094             {
1095                 CONSISTENCY_CHECK(NeedsUnmarshalCleanupIndex());
1096
1097                 UINT uArgIdx = (IsRetval(m_dwMarshalFlags) ?
1098                     NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL :
1099                     NDirectStubLinker::CLEANUP_INDEX_ARG0_UNMARSHAL + m_argidx);
1100
1101                 m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
1102                                                      uArgIdx,
1103                                                      NDirectStubLinker::BranchIfNotMarshaled,
1104                                                      pSkipCleanupLabel);
1105             }
1106
1107             // we know that native home needs to be cleaned up at this point
1108             if (IsRetval(m_dwMarshalFlags) || (IsOut(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags)))
1109             {
1110                 // we own the buffer - clear everything
1111                 EmitClearNative(pcsCleanup);
1112             }
1113             else
1114             {
1115                 // this is a caller supplied buffer - clear only its contents
1116                 EmitClearNativeContents(pcsCleanup);
1117             }
1118
1119             pcsCleanup->EmitLabel(pSkipCleanupLabel);
1120         }
1121
1122         // if there is an output buffer, zero it out so the caller does not get pointer to already freed data
1123         if (!IsHiddenLengthParam(m_dwMarshalFlags))
1124         {
1125             if (IsRetval(m_dwMarshalFlags) || (IsOut(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags)))
1126             {
1127                 m_pslNDirect->SetExceptionCleanupNeeded();
1128
1129                 EmitReInitNative(pcsCleanup);
1130                 if (IsHresultSwap(m_dwMarshalFlags) || IsOut(m_dwMarshalFlags))
1131                 {
1132                     m_nativeHome.EmitCopyToByrefArgWithNullCheck(pcsCleanup, &nativeType, m_argidx);
1133                 }
1134             }
1135         }
1136     }
1137
1138     virtual void EmitMarshalArgumentNativeToCLR()
1139     {
1140         CONTRACTL
1141         {
1142             STANDARD_VM_CHECK;
1143             PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
1144         }
1145         CONTRACTL_END;
1146                     
1147         EmitSetupSigAndDefaultHomesNativeToCLR();
1148         EmitMarshalArgumentContentsNativeToCLR();
1149     }
1150
1151     void EmitMarshalArgumentContentsNativeToCLR()
1152     {
1153         CONTRACTL
1154         {
1155             STANDARD_VM_CHECK;
1156             PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
1157         }
1158         CONTRACTL_END;
1159
1160         //
1161         // marshal
1162         //
1163         if (IsIn(m_dwMarshalFlags))
1164         {
1165             EmitConvertSpaceAndContentsNativeToCLR(m_pcsMarshal);
1166         }
1167         else
1168         {
1169             EmitConvertSpaceNativeToCLR(m_pcsMarshal);
1170         }
1171
1172         //
1173         // unmarshal
1174         //
1175         if (IsOut(m_dwMarshalFlags))
1176         {
1177             if (IsIn(m_dwMarshalFlags))
1178             {
1179                 EmitClearNativeContents(m_pcsUnmarshal);
1180             }
1181             EmitConvertContentsCLRToNative(m_pcsUnmarshal);
1182
1183             // make sure we free the argument if an exception is thrown
1184             EmitExceptionCleanupNativeToCLR();
1185         }
1186         EmitCleanupNativeToCLR();
1187     }
1188
1189     void EmitSetupSigAndDefaultHomesNativeToCLRByref(bool fBlittable = false)
1190     {
1191         CONTRACTL
1192         {
1193             STANDARD_VM_CHECK;
1194             PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1195         }
1196         CONTRACTL_END;
1197     
1198         LocalDesc nativeType = GetNativeType();
1199         LocalDesc managedType = GetManagedType();
1200         LocalDesc nativeArgType = nativeType;
1201         nativeArgType.MakeByRef();
1202         m_pcsMarshal->SetStubTargetArgType(&nativeArgType);
1203
1204         if (fBlittable)
1205         {
1206             // we will not work with the actual data but only with a pointer to that data
1207             // (the managed and native type had better be the same if it's blittable)
1208             _ASSERTE(nativeType.ElementType[0] == managedType.ElementType[0]);
1209
1210             managedType.MakeByRef();
1211
1212             m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILByrefLocal, m_pcsMarshal->NewLocal(managedType));
1213             m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILByrefArgument, m_argidx);
1214         }
1215         else
1216         {
1217             m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(managedType));
1218             m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(nativeType));
1219         }
1220     }
1221
1222     virtual void EmitMarshalArgumentNativeToCLRByref()
1223     {
1224         CONTRACTL
1225         {
1226             STANDARD_VM_CHECK;
1227             PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1228         }
1229         CONTRACTL_END;
1230         
1231         EmitSetupSigAndDefaultHomesNativeToCLRByref();
1232         EmitMarshalArgumentContentsNativeToCLRByref(false);
1233     }
1234
1235     void EmitMarshalArgumentContentsNativeToCLRByref(bool nativeHomeAlreadyInitialized)
1236     {
1237         CONTRACTL
1238         {
1239             STANDARD_VM_CHECK;
1240             PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1241         }
1242         CONTRACTL_END;
1243
1244         LocalDesc nativeType = GetNativeType();
1245
1246         //
1247         // marshal
1248         //
1249         if (IsIn(m_dwMarshalFlags))
1250         {
1251             if (!nativeHomeAlreadyInitialized)
1252             {
1253                 m_nativeHome.EmitCopyFromByrefArg(m_pcsMarshal, &nativeType, m_argidx);
1254             }
1255
1256             EmitConvertSpaceAndContentsNativeToCLR(m_pcsMarshal);
1257         }
1258         else
1259         {
1260             // dereference the argument so we throw before calling the managed target - this is the fastest way
1261             // to check for NULL (we can still throw later if the pointer is invalid yet non-NULL but we cannot
1262             // detect this realiably - the memory may get unmapped etc., NULL check is the best we can do here)
1263             m_pcsMarshal->EmitLDARG(m_argidx);
1264             m_pcsMarshal->EmitLDIND_I1();
1265             m_pcsMarshal->EmitPOP();
1266         }
1267         
1268         //
1269         // unmarshal
1270         //
1271         if (IsOut(m_dwMarshalFlags))
1272         {
1273             if (IsIn(m_dwMarshalFlags))
1274             {
1275                 EmitClearNative(m_pcsUnmarshal);
1276                 EmitReInitNative(m_pcsUnmarshal);
1277             }
1278
1279             EmitConvertSpaceAndContentsCLRToNative(m_pcsUnmarshal);
1280
1281             if (!nativeHomeAlreadyInitialized)
1282             {
1283                 m_nativeHome.EmitCopyToByrefArg(m_pcsUnmarshal, &nativeType, m_argidx);
1284             }
1285
1286             // make sure we free and zero the by-ref argument if an exception is thrown
1287             EmitExceptionCleanupNativeToCLR();
1288         }
1289
1290         EmitCleanupNativeToCLR();
1291     }
1292
1293     virtual LocalDesc GetNativeType() = 0;
1294     virtual LocalDesc GetManagedType() = 0;
1295
1296     //
1297     // Native-to-CLR
1298     //
1299     virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
1300     {
1301         LIMITED_METHOD_CONTRACT;
1302     }
1303         
1304     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1305     {
1306         LIMITED_METHOD_CONTRACT;
1307     }
1308
1309     virtual void EmitConvertSpaceAndContentsNativeToCLR(ILCodeStream* pslILEmit)
1310     {
1311         WRAPPER_NO_CONTRACT;
1312         EmitConvertSpaceNativeToCLR(pslILEmit);
1313         EmitConvertContentsNativeToCLR(pslILEmit);
1314     }
1315
1316
1317     //
1318     // CLR-to-Native
1319     //
1320     virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
1321     {
1322         LIMITED_METHOD_CONTRACT;
1323     }
1324
1325     virtual void EmitConvertSpaceCLRToNativeTemp(ILCodeStream* pslILEmit)
1326     {
1327         LIMITED_METHOD_CONTRACT;
1328         EmitConvertSpaceCLRToNative(pslILEmit);
1329     }
1330
1331     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1332     {
1333         LIMITED_METHOD_CONTRACT;
1334     }
1335     
1336     virtual void EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslILEmit)
1337     {
1338         STANDARD_VM_CONTRACT;
1339         EmitConvertSpaceCLRToNative(pslILEmit);
1340         EmitConvertContentsCLRToNative(pslILEmit);
1341     }
1342         
1343     virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
1344     {
1345         WRAPPER_NO_CONTRACT;
1346         EmitConvertSpaceAndContentsCLRToNative(pslILEmit);
1347     }
1348
1349     //
1350     // Misc
1351     //
1352     virtual void EmitClearCLRContents(ILCodeStream* pslILEmit)
1353     {
1354         LIMITED_METHOD_CONTRACT;
1355     }
1356
1357     virtual bool NeedsClearNative()
1358     {
1359         LIMITED_METHOD_CONTRACT;
1360         return false;
1361     }
1362
1363     virtual void EmitClearNative(ILCodeStream* pslILEmit)
1364     {
1365         LIMITED_METHOD_CONTRACT;
1366     }
1367
1368     virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit)
1369     {
1370         LIMITED_METHOD_CONTRACT;
1371         EmitClearNative(pslILEmit);
1372     }
1373
1374     virtual void EmitClearNativeContents(ILCodeStream* pslILEmit)
1375     {
1376         LIMITED_METHOD_CONTRACT;
1377     }
1378
1379     virtual bool NeedsClearCLR()
1380     {
1381         LIMITED_METHOD_CONTRACT;
1382         return false;
1383     }
1384
1385     virtual void EmitClearCLR(ILCodeStream* pslILEmit)
1386     {
1387         LIMITED_METHOD_CONTRACT;
1388     }
1389
1390     virtual void EmitReInitNative(ILCodeStream* pslILEmit)
1391     {
1392         STANDARD_VM_CONTRACT;
1393
1394         // Friendly Reminder:
1395         // You should implement your own EmitReInitNative if your native type is a struct,
1396         // as the following instructions apparently won't work on value types and will trigger
1397         // an ASSERT in JIT
1398         _ASSERTE(!GetNativeType().IsValueClass());
1399         
1400         pslILEmit->EmitLDC(0);
1401         pslILEmit->EmitCONV_T(static_cast<CorElementType>(GetNativeType().ElementType[0]));
1402
1403         EmitStoreNativeValue(pslILEmit);
1404     }
1405
1406     virtual bool IsManagedPassedByRef()
1407     {
1408         LIMITED_METHOD_CONTRACT;
1409         return IsByref(m_dwMarshalFlags);
1410     }
1411
1412     virtual bool IsNativePassedByRef()
1413     {
1414         LIMITED_METHOD_CONTRACT;
1415         return IsByref(m_dwMarshalFlags);
1416     }
1417
1418     void EmitInterfaceClearNative(ILCodeStream* pslILEmit);
1419
1420 public:
1421     static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
1422                                                     BOOL               byref,
1423                                                     BOOL               fin,
1424                                                     BOOL               fout,
1425                                                     BOOL               fManagedToNative,
1426                                                     OverrideProcArgs*  pargs,
1427                                                     UINT*              pResID,
1428                                                     UINT               argidx,
1429                                                     UINT               nativeStackOffset)
1430     {
1431         LIMITED_METHOD_CONTRACT;
1432         return HANDLEASNORMAL;
1433     }
1434
1435     static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker*  psl,
1436                                                   BOOL                fManagedToNative,
1437                                                   BOOL                fHresultSwap,
1438                                                   OverrideProcArgs*   pargs,
1439                                                   UINT*               pResID)
1440     {
1441         LIMITED_METHOD_CONTRACT;
1442         return HANDLEASNORMAL;
1443     }
1444 };
1445
1446         
1447 class ILCopyMarshalerBase : public ILMarshaler
1448 {
1449     virtual LocalDesc GetManagedType()
1450     {
1451         WRAPPER_NO_CONTRACT;
1452         return GetNativeType();
1453     }
1454
1455     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1456     {
1457         STANDARD_VM_CONTRACT;
1458
1459         EmitLoadManagedValue(pslILEmit);
1460         EmitStoreNativeValue(pslILEmit);
1461     }
1462
1463     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1464     {
1465         STANDARD_VM_CONTRACT;
1466
1467         EmitLoadNativeValue(pslILEmit);
1468         EmitStoreManagedValue(pslILEmit);
1469     }
1470
1471     //
1472     // It's very unforunate that x86 used ML_COPYPINNEDGCREF for byref args.
1473     // The result is that developers can get away with being lazy about their 
1474     // in/out semantics and often times in/out byref params are marked out-
1475     // only, but because of ML_COPYPINNEDGCREF, they get in/out behavior.  
1476     //
1477     // There are even lazier developers who use byref params to pass arrays.
1478     // Pinning ensures that the native side 'sees' the entire array even when
1479     // only reference to one element was passed.
1480     // 
1481     // This method was changed to pin instead of copy in Dev10 in order
1482     // to match the original ML behavior.
1483     //
1484     virtual void EmitMarshalArgumentCLRToNativeByref()
1485     {
1486         CONTRACTL
1487         {
1488             STANDARD_VM_CHECK;
1489             PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1490         }
1491         CONTRACTL_END;
1492
1493         EmitSetupSigAndDefaultHomesCLRToNativeByref(true);
1494             
1495         //
1496         // marshal
1497         //
1498         EmitLoadManagedHomeAddr(m_pcsMarshal);
1499         EmitStoreNativeHomeAddr(m_pcsMarshal);
1500         
1501         //
1502         // no unmarshaling is necessary since we directly passed the pinned byref to native,
1503         // the argument is therefore automatically in/out
1504         //
1505     }
1506
1507     //
1508     // Similarly to the other direction, ML used ML_COPYPINNEDGCREF on x86 to
1509     // directly pass the unmanaged pointer as a byref argument to managed code.
1510     // This also makes an observable difference (allows passing NULL, changes
1511     // made to the original value during the call are visible in managed).
1512     //
1513     // This method was changed to pass pointer instead of copy in Dev10 in order
1514     // to match the original ML behavior. Note that in this direction we don't
1515     // need to pin the pointer - if it is pointing to GC heap, it must have been
1516     // pinned on the way to unmanaged.
1517     //
1518     virtual void EmitMarshalArgumentNativeToCLRByref()
1519     {
1520         CONTRACTL
1521         {
1522             STANDARD_VM_CHECK;
1523             PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1524         }
1525         CONTRACTL_END;
1526
1527         EmitSetupSigAndDefaultHomesNativeToCLRByref(true);
1528             
1529         //
1530         // marshal
1531         //
1532         EmitLoadNativeHomeAddr(m_pcsMarshal);
1533         EmitStoreManagedHomeAddr(m_pcsMarshal);
1534         
1535         //
1536         // no unmarshaling is necessary since we directly passed the pointer to managed
1537         // as a byref, the argument is therefore automatically in/out
1538         //
1539     }
1540 };
1541
1542 template <CorElementType ELEMENT_TYPE, class PROMOTED_ELEMENT>
1543 class ILCopyMarshalerSimple : public ILCopyMarshalerBase
1544 {
1545 public:
1546     enum
1547     {
1548         c_fInOnly               = TRUE,
1549         c_nativeSize            = sizeof(PROMOTED_ELEMENT),
1550         c_CLRSize               = sizeof(PROMOTED_ELEMENT),
1551     };
1552
1553     bool IsSmallValueTypeSpecialCase()
1554     {
1555         //
1556         // Special case for small value types that get
1557         // mapped to MARSHAL_TYPE_GENERIC_8 -- use the 
1558         // valuetype type so the JIT is happy.
1559         //
1560         
1561         return (ELEMENT_TYPE == 
1562 #ifdef _WIN64        
1563                     ELEMENT_TYPE_I8
1564 #else // _WIN64
1565                     ELEMENT_TYPE_I4
1566 #endif // _WIN64
1567                     ) && (NULL != m_pargs->m_pMT);
1568     }
1569     
1570     bool NeedToPromoteTo8Bytes()
1571     {
1572         WRAPPER_NO_CONTRACT;
1573
1574 #if defined(_TARGET_AMD64_)
1575         // If the argument is passed by value, 
1576         if (!IsByref(m_dwMarshalFlags) && !IsRetval(m_dwMarshalFlags))
1577         {
1578             // and it is an I4 or an U4, 
1579             if ( (ELEMENT_TYPE == ELEMENT_TYPE_I4) ||
1580                  (ELEMENT_TYPE == ELEMENT_TYPE_U4) )
1581             {
1582                 // and we are doing a managed-to-unmanaged call,
1583                 if (IsCLRToNative(m_dwMarshalFlags))
1584                 {
1585                     // then we have to promote the native argument type to an I8 or an U8.
1586                     return true;
1587                 }
1588             }
1589         }
1590 #endif // _TARGET_AMD64_
1591
1592         return false;
1593     }
1594
1595     CorElementType GetConversionType(CorElementType type)
1596     {
1597         LIMITED_METHOD_CONTRACT;
1598
1599         // I4 <-> I8; U4 <-> U8
1600         if (type == ELEMENT_TYPE_I4)
1601         {
1602             return ELEMENT_TYPE_I8;
1603         }
1604         else if (type == ELEMENT_TYPE_U4)
1605         {
1606             return ELEMENT_TYPE_U8;
1607         }
1608         else
1609         {
1610             return ELEMENT_TYPE_END;
1611         }
1612     }
1613
1614     void EmitTypePromotion(ILCodeStream* pslILEmit)
1615     {
1616         WRAPPER_NO_CONTRACT;
1617
1618         CorElementType promotedType = GetConversionType(ELEMENT_TYPE);
1619         if (promotedType == ELEMENT_TYPE_I8)
1620         {
1621             pslILEmit->EmitCONV_I8();
1622         }
1623         else if (promotedType == ELEMENT_TYPE_U8)
1624         {
1625             pslILEmit->EmitCONV_U8();
1626         }
1627     }
1628
1629     virtual LocalDesc GetNativeType()
1630     {
1631         WRAPPER_NO_CONTRACT;
1632         
1633         if (NeedToPromoteTo8Bytes())
1634         {
1635             return LocalDesc(GetConversionType(ELEMENT_TYPE));
1636         }
1637         else
1638         {
1639             return GetManagedType();
1640         }
1641     }
1642
1643     virtual LocalDesc GetManagedType()
1644     {
1645         WRAPPER_NO_CONTRACT;
1646
1647         if (IsSmallValueTypeSpecialCase())
1648         {
1649             return LocalDesc(m_pargs->m_pMT);
1650         }
1651         else
1652         {
1653             return LocalDesc(ELEMENT_TYPE);
1654         }
1655     }
1656
1657     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1658     {
1659         STANDARD_VM_CONTRACT;
1660
1661         EmitLoadManagedValue(pslILEmit);
1662         if (NeedToPromoteTo8Bytes())
1663         {
1664             EmitTypePromotion(pslILEmit);
1665         }
1666         EmitStoreNativeValue(pslILEmit);
1667     }
1668
1669     virtual void EmitReInitNative(ILCodeStream* pslILEmit)
1670     {
1671         STANDARD_VM_CONTRACT;
1672
1673         if (IsSmallValueTypeSpecialCase())
1674         {
1675             EmitLoadNativeHomeAddr(pslILEmit);
1676             pslILEmit->EmitINITOBJ(pslILEmit->GetToken(m_pargs->m_pMT));
1677         }
1678         else
1679         {
1680             // ldc.i4.0, conv.i8/u8/r4/r8 is shorter than ldc.i8/r4/r8 0
1681             pslILEmit->EmitLDC(0);
1682             pslILEmit->EmitCONV_T(ELEMENT_TYPE);
1683
1684             EmitStoreNativeValue(pslILEmit);
1685         }
1686     }
1687 };
1688
1689 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_I1, INT_PTR>  ILCopyMarshaler1;
1690 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_U1, UINT_PTR> ILCopyMarshalerU1;
1691 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_I2, INT_PTR>  ILCopyMarshaler2;
1692 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_U2, UINT_PTR> ILCopyMarshalerU2;
1693 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_I4, INT_PTR>  ILCopyMarshaler4;
1694 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_U4, UINT_PTR> ILCopyMarshalerU4;
1695 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_I8, INT64>    ILCopyMarshaler8;
1696 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_R4, float>    ILFloatMarshaler;
1697 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_R8, double>   ILDoubleMarshaler;
1698
1699 template <BinderClassID CLASS__ID, class PROMOTED_ELEMENT>
1700 class ILCopyMarshalerKnownStruct : public ILCopyMarshalerBase
1701 {
1702 public:
1703     enum
1704     {
1705         c_fInOnly               = TRUE,
1706         c_nativeSize            = sizeof(PROMOTED_ELEMENT),
1707         c_CLRSize               = sizeof(PROMOTED_ELEMENT),
1708     };
1709
1710     virtual void EmitReInitNative(ILCodeStream* pslILEmit)
1711     {
1712         STANDARD_VM_CONTRACT;
1713         
1714         EmitLoadNativeHomeAddr(pslILEmit);
1715         pslILEmit->EmitINITOBJ(pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__ID)));
1716     }
1717
1718     virtual LocalDesc GetNativeType()
1719     {
1720         STANDARD_VM_CONTRACT;
1721
1722         return LocalDesc(MscorlibBinder::GetClass(CLASS__ID));
1723     }
1724 };
1725
1726 typedef ILCopyMarshalerKnownStruct<CLASS__DECIMAL, DECIMAL> ILDecimalMarshaler;
1727 typedef ILCopyMarshalerKnownStruct<CLASS__GUID, GUID> ILGuidMarshaler;
1728
1729 class ILBlittableValueClassMarshaler : public ILCopyMarshalerBase
1730 {
1731 public:
1732     enum
1733     {
1734         c_fInOnly               = TRUE,
1735         c_nativeSize            = VARIABLESIZE,
1736         c_CLRSize               = VARIABLESIZE,
1737     };
1738         
1739     virtual void EmitReInitNative(ILCodeStream* pslILEmit)
1740     {
1741         STANDARD_VM_CONTRACT;
1742         
1743         EmitLoadNativeHomeAddr(pslILEmit);
1744         pslILEmit->EmitINITOBJ(pslILEmit->GetToken(m_pargs->m_pMT));
1745     }
1746
1747     virtual LocalDesc GetNativeType()
1748     {
1749         LIMITED_METHOD_CONTRACT;
1750         
1751         return LocalDesc(m_pargs->m_pMT);
1752     }
1753 };
1754
1755
1756 class ILDelegateMarshaler : public ILMarshaler
1757 {
1758 public:
1759     enum
1760     {
1761         c_fInOnly               = TRUE,
1762         c_nativeSize            = sizeof(void *),
1763         c_CLRSize               = sizeof(OBJECTREF),
1764     };
1765
1766 protected:
1767     virtual LocalDesc GetNativeType();
1768     virtual LocalDesc GetManagedType();
1769     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
1770     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
1771 };
1772
1773 class ILReflectionObjectMarshaler : public ILMarshaler
1774 {
1775 public:
1776     enum
1777     {
1778         c_fInOnly               = TRUE,
1779         c_nativeSize            = sizeof(void *),
1780         c_CLRSize               = sizeof(OBJECTREF),
1781     };
1782
1783 protected:
1784     virtual LocalDesc GetManagedType();
1785     virtual LocalDesc GetNativeType();
1786     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
1787     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
1788     virtual BinderFieldID GetStructureFieldID() {LIMITED_METHOD_CONTRACT; return (BinderFieldID)0;}
1789     virtual BinderFieldID GetObjectFieldID() = 0;
1790     virtual BinderClassID GetManagedTypeBinderID() = 0;
1791 };
1792
1793 class ILIRuntimeMethodInfoMarshaler : public ILReflectionObjectMarshaler
1794 {
1795 protected:
1796     virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__STUBMETHODINFO__HANDLE; }
1797     virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__STUBMETHODINFO; }
1798 };
1799
1800 class ILRuntimeModuleMarshaler : public ILReflectionObjectMarshaler
1801 {
1802 protected:
1803     virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__MODULE__DATA; }
1804     virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__MODULE; }
1805 };
1806
1807 class ILRuntimeAssemblyMarshaler : public ILReflectionObjectMarshaler
1808 {
1809 protected:
1810     virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__ASSEMBLY__HANDLE; }
1811     virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__ASSEMBLY; }
1812 };
1813
1814 class ILRuntimeTypeHandleMarshaler : public ILReflectionObjectMarshaler
1815 {
1816 protected:
1817     virtual BinderFieldID GetStructureFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__RT_TYPE_HANDLE__M_TYPE; }
1818     virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__CLASS__TYPEHANDLE; }
1819     virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__RT_TYPE_HANDLE; }
1820 };
1821
1822 class ILRuntimeMethodHandleMarshaler : public ILReflectionObjectMarshaler
1823 {
1824 protected:
1825     virtual BinderFieldID GetStructureFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__METHOD_HANDLE__METHOD; }
1826     virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__STUBMETHODINFO__HANDLE; }
1827     virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__METHOD_HANDLE; }
1828 };
1829
1830 class ILRuntimeFieldHandleMarshaler : public ILReflectionObjectMarshaler
1831 {
1832 protected:
1833     virtual BinderFieldID GetStructureFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__FIELD_HANDLE__M_FIELD; }
1834     virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__RT_FIELD_INFO__HANDLE; }
1835     virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__FIELD_HANDLE; }
1836 };
1837
1838 class ILBoolMarshaler : public ILMarshaler
1839 {
1840 public:
1841
1842     virtual CorElementType GetNativeBoolElementType() = 0;
1843     virtual int GetNativeTrueValue() = 0;
1844     virtual int GetNativeFalseValue() = 0;
1845
1846 protected:
1847     virtual LocalDesc GetNativeType();
1848     virtual LocalDesc GetManagedType();
1849     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
1850     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
1851 };
1852
1853 class ILWinBoolMarshaler : public ILBoolMarshaler
1854 {
1855 public:
1856     enum
1857     {
1858         c_fInOnly               = TRUE,
1859         c_nativeSize            = sizeof(BOOL),
1860         c_CLRSize               = sizeof(INT8),
1861     };
1862         
1863 protected:    
1864     virtual CorElementType GetNativeBoolElementType()
1865     {
1866         LIMITED_METHOD_CONTRACT;
1867         return ELEMENT_TYPE_I4;
1868     }
1869
1870     virtual int GetNativeTrueValue()
1871     {
1872         LIMITED_METHOD_CONTRACT;
1873         return 1;
1874     }
1875         
1876     virtual int GetNativeFalseValue()
1877     {
1878         LIMITED_METHOD_CONTRACT;
1879         return 0;
1880     }
1881 };
1882
1883 class ILCBoolMarshaler : public ILBoolMarshaler
1884 {
1885 public:
1886     enum
1887     {
1888         c_fInOnly               = TRUE,
1889         c_nativeSize            = sizeof(BYTE),
1890         c_CLRSize               = sizeof(INT8),
1891     };
1892
1893 protected:
1894     virtual CorElementType GetNativeBoolElementType()
1895     {
1896         LIMITED_METHOD_CONTRACT;
1897         return ELEMENT_TYPE_I1;
1898     }
1899
1900     virtual int GetNativeTrueValue()
1901     {
1902         LIMITED_METHOD_CONTRACT;
1903         return 1;
1904     }
1905                 
1906     virtual int GetNativeFalseValue()
1907     {
1908         LIMITED_METHOD_CONTRACT;
1909         return 0;
1910     }
1911 };
1912
1913 #ifdef FEATURE_COMINTEROP
1914 class ILVtBoolMarshaler : public ILBoolMarshaler
1915 {
1916 public:    
1917     enum
1918     {
1919         c_fInOnly               = TRUE,
1920         c_nativeSize            = sizeof(VARIANT_BOOL),
1921         c_CLRSize               = sizeof(INT8),
1922     };
1923
1924 protected:    
1925     virtual CorElementType GetNativeBoolElementType()
1926     {
1927         LIMITED_METHOD_CONTRACT;
1928         return ELEMENT_TYPE_I2;
1929     }
1930
1931     virtual int GetNativeTrueValue()
1932     {
1933         LIMITED_METHOD_CONTRACT;
1934         return VARIANT_TRUE;
1935     }
1936
1937     virtual int GetNativeFalseValue()
1938     {
1939         LIMITED_METHOD_CONTRACT;
1940         return VARIANT_FALSE;
1941     }
1942 };
1943 #endif // FEATURE_COMINTEROP
1944
1945 class ILWSTRMarshaler : public ILMarshaler
1946 {
1947 public:
1948     enum
1949     {
1950         c_fInOnly               = TRUE,
1951         c_nativeSize            = sizeof(void *),
1952         c_CLRSize               = sizeof(OBJECTREF),
1953     };
1954
1955 #ifdef _DEBUG
1956     bool m_fCoMemoryAllocated;
1957
1958     ILWSTRMarshaler()
1959     {
1960         LIMITED_METHOD_CONTRACT;
1961         m_fCoMemoryAllocated = false;
1962     }
1963 #endif // _DEBUG
1964
1965 protected:
1966     virtual LocalDesc GetNativeType();
1967     virtual LocalDesc GetManagedType();
1968
1969     virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
1970     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
1971     virtual void EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslILEmit);
1972     virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit);
1973
1974     virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
1975     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
1976     virtual void EmitConvertSpaceAndContentsNativeToCLR(ILCodeStream* pslILEmit);
1977
1978     virtual bool NeedsClearNative();
1979     virtual void EmitClearNative(ILCodeStream* pslILEmit);
1980     virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit);
1981
1982     static bool CanUsePinnedManagedString(DWORD dwMarshalFlags);
1983     static void EmitCheckManagedStringLength(ILCodeStream* pslILEmit);
1984     static void EmitCheckNativeStringLength(ILCodeStream* pslILEmit);
1985 };
1986
1987 // A marshaler that makes run-time decision based on argument size whether native space will
1988 // be allocated using localloc or on the heap. The ctor argument is a heap free function.
1989 class ILOptimizedAllocMarshaler : public ILMarshaler
1990 {
1991 public:
1992     ILOptimizedAllocMarshaler(BinderMethodID clearNat) :
1993         m_idClearNative(clearNat),
1994         m_dwLocalBuffer((DWORD)-1)
1995     {
1996         LIMITED_METHOD_CONTRACT;
1997     }
1998
1999     virtual LocalDesc GetNativeType();
2000     virtual bool NeedsClearNative();
2001     virtual void EmitClearNative(ILCodeStream* pslILEmit);
2002
2003 protected:
2004     const BinderMethodID m_idClearNative;
2005     DWORD m_dwLocalBuffer;      // localloc'ed temp buffer variable or -1 if not used
2006 };
2007
2008 class ILUTF8BufferMarshaler : public ILOptimizedAllocMarshaler
2009 {
2010 public:
2011         enum
2012         {
2013                 c_fInOnly = FALSE,
2014                 c_nativeSize = sizeof(void *),
2015                 c_CLRSize = sizeof(OBJECTREF),
2016         };
2017
2018         enum
2019         {
2020                 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2021                 MAX_LOCAL_BUFFER_LENGTH = MAX_PATH_FNAME + 1
2022         };
2023
2024         ILUTF8BufferMarshaler() :
2025                 ILOptimizedAllocMarshaler(METHOD__WIN32NATIVE__COTASKMEMFREE)
2026         {
2027                 LIMITED_METHOD_CONTRACT;
2028         }
2029
2030         virtual LocalDesc GetManagedType();
2031         virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
2032         virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2033         virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
2034         virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2035 };
2036
2037 class ILWSTRBufferMarshaler : public ILOptimizedAllocMarshaler
2038 {
2039 public:
2040     enum
2041     {
2042         c_fInOnly               = FALSE,
2043         c_nativeSize            = sizeof(void *),
2044         c_CLRSize               = sizeof(OBJECTREF),
2045     };
2046
2047     enum
2048     {
2049         // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2050         MAX_LOCAL_BUFFER_LENGTH = (MAX_PATH_FNAME + 1) * 2
2051     };
2052
2053     ILWSTRBufferMarshaler() :
2054         ILOptimizedAllocMarshaler(METHOD__WIN32NATIVE__COTASKMEMFREE)
2055     {
2056         LIMITED_METHOD_CONTRACT;
2057     }
2058
2059     virtual LocalDesc GetManagedType();
2060     virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
2061     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2062     virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
2063     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2064 };
2065
2066 class ILCSTRBufferMarshaler : public ILOptimizedAllocMarshaler
2067 {
2068 public:
2069     enum
2070     {
2071         c_fInOnly               = FALSE,
2072         c_nativeSize            = sizeof(void *),
2073         c_CLRSize               = sizeof(OBJECTREF),
2074     };
2075
2076     enum
2077     {
2078         // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2079         MAX_LOCAL_BUFFER_LENGTH = MAX_PATH_FNAME + 1
2080     };
2081
2082     ILCSTRBufferMarshaler() :
2083         ILOptimizedAllocMarshaler(METHOD__WIN32NATIVE__COTASKMEMFREE)
2084     {
2085         LIMITED_METHOD_CONTRACT;
2086     }
2087
2088     virtual LocalDesc GetManagedType();
2089     virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
2090     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2091     virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
2092     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2093 };
2094
2095         
2096 class ILHandleRefMarshaler : public ILMarshaler
2097 {
2098     // Managed layout for SRI.HandleRef class
2099     struct HANDLEREF
2100     {
2101         OBJECTREF m_wrapper;
2102         LPVOID    m_handle;
2103     };
2104
2105 public:
2106     enum
2107     {
2108         c_fInOnly               = FALSE,
2109         c_nativeSize            = sizeof(LPVOID),
2110         c_CLRSize               = sizeof(HANDLEREF),
2111     };
2112         
2113     LocalDesc GetManagedType()
2114     {
2115         LIMITED_METHOD_CONTRACT;
2116         return LocalDesc();
2117     }
2118         
2119     LocalDesc GetNativeType()
2120     {
2121         LIMITED_METHOD_CONTRACT;
2122         return LocalDesc();
2123     }
2124
2125     static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
2126                                                     BOOL               byref,
2127                                                     BOOL               fin,
2128                                                     BOOL               fout,
2129                                                     BOOL               fManagedToNative,
2130                                                     OverrideProcArgs*  pargs,
2131                                                     UINT*              pResID,
2132                                                     UINT               argidx,
2133                                                     UINT               nativeStackOffset);
2134
2135     static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker* psl,
2136                                                   BOOL               fManagedToNative,
2137                                                   BOOL               fHresultSwap,
2138                                                   OverrideProcArgs*  pargs,
2139                                                   UINT*              pResID);
2140 };
2141
2142 class ILSafeHandleMarshaler : public ILMarshaler
2143 {
2144 public:
2145     enum
2146     {
2147         c_fInOnly               = FALSE,
2148         c_nativeSize            = sizeof(LPVOID),
2149         c_CLRSize               = sizeof(SAFEHANDLE),
2150     };
2151
2152     virtual LocalDesc GetManagedType();
2153     virtual LocalDesc GetNativeType();
2154
2155     virtual bool NeedsClearNative();
2156     virtual void EmitClearNative(ILCodeStream* pslILEmit);
2157
2158     virtual void EmitMarshalArgumentCLRToNative();
2159
2160     static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
2161                                                     BOOL               byref,
2162                                                     BOOL               fin,
2163                                                     BOOL               fout,
2164                                                     BOOL               fManagedToNative,
2165                                                     OverrideProcArgs*  pargs,
2166                                                     UINT*              pResID,
2167                                                     UINT               argidx,
2168                                                     UINT               nativeStackOffset);
2169         
2170     static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker *psl,
2171                                                   BOOL        fManagedToNative,
2172                                                   BOOL        fHresultSwap,
2173                                                   OverrideProcArgs *pargs,
2174                                                   UINT       *pResID);
2175 };
2176
2177
2178 class ILCriticalHandleMarshaler : public ILMarshaler
2179 {
2180 public:
2181     enum
2182     {
2183         c_fInOnly               = FALSE,
2184         c_nativeSize            = sizeof(LPVOID),
2185         c_CLRSize               = sizeof(CRITICALHANDLE),
2186     };
2187         
2188 public:
2189
2190     LocalDesc GetManagedType()
2191     {
2192         LIMITED_METHOD_CONTRACT;
2193         return LocalDesc();
2194     }
2195     
2196     LocalDesc GetNativeType()
2197     {
2198         LIMITED_METHOD_CONTRACT;
2199         return LocalDesc();
2200     }
2201     
2202     static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
2203                                                     BOOL               byref,
2204                                                     BOOL               fin,
2205                                                     BOOL               fout,
2206                                                     BOOL               fManagedToNative,
2207                                                     OverrideProcArgs*  pargs,
2208                                                     UINT*              pResID,
2209                                                     UINT               argidx,
2210                                                     UINT               nativeStackOffset);
2211
2212     static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker *psl,
2213                                                   BOOL        fManagedToNative,
2214                                                   BOOL        fHresultSwap,
2215                                                   OverrideProcArgs *pargs,
2216                                                   UINT       *pResID);
2217 };
2218
2219
2220 class ILValueClassMarshaler : public ILMarshaler
2221 {
2222 public:
2223     enum
2224     {
2225         c_fInOnly               = TRUE,
2226         c_nativeSize            = VARIABLESIZE,
2227         c_CLRSize               = VARIABLESIZE,
2228     };
2229
2230 protected:
2231     virtual LocalDesc GetNativeType();
2232     virtual LocalDesc GetManagedType();
2233     virtual void EmitReInitNative(ILCodeStream* pslILEmit);
2234     virtual bool NeedsClearNative();
2235     virtual void EmitClearNative(ILCodeStream * pslILEmit);
2236     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2237     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2238 };
2239         
2240 #ifdef FEATURE_COMINTEROP
2241 class ILObjectMarshaler : public ILMarshaler
2242 {
2243 public:
2244     enum
2245     {
2246         c_fInOnly               = TRUE,
2247         c_CLRSize               = sizeof(OBJECTREF),
2248         c_nativeSize            = sizeof(VARIANT),
2249     };
2250
2251 protected:
2252     virtual LocalDesc GetNativeType();
2253     virtual LocalDesc GetManagedType();
2254     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2255     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2256     virtual bool NeedsClearNative();
2257     virtual void EmitClearNative(ILCodeStream* pslILEmit);
2258     virtual void EmitReInitNative(ILCodeStream* pslILEmit);
2259 };
2260 #endif // FEATURE_COMINTEROP
2261
2262 class ILDateMarshaler : public ILMarshaler
2263 {
2264 public:
2265     enum
2266     {
2267         c_fInOnly               = TRUE,
2268         c_nativeSize            = sizeof(DATE),
2269         c_CLRSize               = sizeof(INT64),
2270     };
2271                 
2272 protected:
2273     virtual LocalDesc GetNativeType();
2274     virtual LocalDesc GetManagedType();
2275     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2276     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2277     virtual void EmitReInitNative(ILCodeStream* pslILEmit);
2278 };
2279                 
2280
2281 class ILCurrencyMarshaler : public ILMarshaler
2282 {
2283 public:
2284     enum
2285     {
2286         c_fInOnly               = TRUE,
2287         c_nativeSize            = sizeof(CURRENCY),
2288         c_CLRSize               = sizeof(DECIMAL),
2289     };
2290
2291 protected:    
2292     virtual LocalDesc GetNativeType();
2293     virtual LocalDesc GetManagedType();
2294     virtual void EmitReInitNative(ILCodeStream* pslILEmit);
2295     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2296     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2297 };
2298
2299
2300 #ifdef FEATURE_COMINTEROP
2301 class ILInterfaceMarshaler : public ILMarshaler
2302 {
2303 public:
2304     enum
2305     {
2306         c_fInOnly               = TRUE,
2307         c_nativeSize            = sizeof(void *),
2308         c_CLRSize               = sizeof(OBJECTREF),
2309     };
2310
2311 protected:    
2312     virtual LocalDesc GetNativeType();
2313     virtual LocalDesc GetManagedType();
2314     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2315     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2316     virtual bool NeedsClearNative();
2317     virtual void EmitClearNative(ILCodeStream* pslILEmit);
2318 };
2319 #endif // FEATURE_COMINTEROP
2320
2321
2322 class ILAnsiCharMarshaler : public ILMarshaler
2323 {
2324 public:
2325     enum
2326     {
2327         c_fInOnly               = TRUE,
2328         c_nativeSize            = sizeof(UINT8),
2329         c_CLRSize               = sizeof(UINT16),
2330     };
2331
2332 protected:
2333     virtual LocalDesc GetNativeType();
2334     virtual LocalDesc GetManagedType();
2335     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2336     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2337 };
2338
2339
2340 template <BinderClassID CLASS__ID, class ELEMENT>
2341 class ILValueClassPtrMarshaler : public ILMarshaler
2342 {
2343 public:
2344     enum
2345     {
2346         c_fInOnly               = TRUE,
2347         c_nativeSize            = sizeof(ELEMENT *),
2348         c_CLRSize               = sizeof(ELEMENT),
2349     };
2350
2351 protected:
2352     virtual LocalDesc GetNativeType()
2353     {
2354         LIMITED_METHOD_CONTRACT;
2355
2356         //
2357         // pointer to value class
2358         //
2359         return LocalDesc(ELEMENT_TYPE_I);
2360     }
2361
2362     virtual LocalDesc GetManagedType()
2363     {
2364         STANDARD_VM_CONTRACT;
2365
2366         //
2367         // value class
2368         //
2369         return LocalDesc(MscorlibBinder::GetClass(CLASS__ID));
2370     }
2371
2372     virtual bool NeedsClearNative()
2373     {
2374         LIMITED_METHOD_CONTRACT;
2375         return (IsByref(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags));
2376     }
2377
2378     virtual void EmitClearNative(ILCodeStream* pslILEmit)
2379     {
2380         STANDARD_VM_CONTRACT;
2381
2382         EmitLoadNativeValue(pslILEmit);
2383         // static void CoTaskMemFree(IntPtr ptr)
2384         pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
2385     }
2386
2387     virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
2388     {
2389         STANDARD_VM_CONTRACT;
2390
2391         if (NeedsClearNative())
2392         {
2393             pslILEmit->EmitLDC(sizeof(ELEMENT));
2394             pslILEmit->EmitCONV_U();
2395             // static IntPtr CoTaskMemAlloc(UIntPtr cb)
2396             pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMALLOC, 1, 1);
2397             EmitStoreNativeValue(pslILEmit);
2398         }
2399     }
2400
2401     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2402     {
2403         STANDARD_VM_CONTRACT;
2404
2405         if (NeedsClearNative())
2406         {
2407             EmitLoadNativeValue(pslILEmit);     // dest
2408             EmitLoadManagedHomeAddr(pslILEmit); // src
2409             pslILEmit->EmitCPOBJ(pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__ID)));
2410         }
2411         else
2412         {
2413             EmitLoadManagedHomeAddr(pslILEmit);
2414             EmitStoreNativeValue(pslILEmit);
2415         }
2416     }
2417
2418     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2419     {
2420         STANDARD_VM_CONTRACT;
2421
2422         int tokType = pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__ID));
2423         ILCodeLabel *pNullLabel = pslILEmit->NewCodeLabel();
2424         ILCodeLabel *pJoinLabel = pslILEmit->NewCodeLabel();
2425
2426         EmitLoadNativeValue(pslILEmit);
2427         pslILEmit->EmitBRFALSE(pNullLabel);
2428
2429         // the incoming pointer is non-null -> dereference it and copy the struct
2430         EmitLoadManagedHomeAddr(pslILEmit); // dest
2431         EmitLoadNativeValue(pslILEmit);     // src
2432         pslILEmit->EmitCPOBJ(tokType);
2433
2434         pslILEmit->EmitBR(pJoinLabel);
2435
2436         // the incoming pointer is null -> just initobj (i.e. zero) the struct
2437         pslILEmit->EmitLabel(pNullLabel);
2438         
2439         EmitLoadManagedHomeAddr(pslILEmit);
2440         pslILEmit->EmitINITOBJ(tokType);
2441
2442         pslILEmit->EmitLabel(pJoinLabel);
2443     }
2444 };
2445
2446 typedef ILValueClassPtrMarshaler<CLASS__GUID, GUID> ILGuidPtrMarshaler;
2447 typedef ILValueClassPtrMarshaler<CLASS__DECIMAL, DECIMAL> ILDecimalPtrMarshaler;
2448         
2449 #ifdef FEATURE_COMINTEROP        
2450 class ILOleColorMarshaler : public ILMarshaler
2451 {
2452 public:
2453     enum
2454     {
2455         c_fInOnly               = TRUE,
2456         c_nativeSize            = sizeof(OLE_COLOR),
2457         c_CLRSize               = sizeof(SYSTEMCOLOR),
2458     };
2459
2460 protected:
2461     virtual LocalDesc GetNativeType();
2462     virtual LocalDesc GetManagedType();
2463     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2464     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2465 };
2466
2467 class ILVBByValStrWMarshaler : public ILMarshaler
2468 {
2469 public:
2470     enum
2471     {
2472         c_fInOnly               = FALSE,
2473         c_nativeSize            = sizeof(BSTR),
2474         c_CLRSize               = sizeof(OBJECTREF*),
2475     };
2476
2477     enum
2478     {
2479         // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2480         MAX_LOCAL_BUFFER_LENGTH = (MAX_PATH_FNAME + 1) * 2 + sizeof(DWORD)
2481     };
2482
2483
2484     ILVBByValStrWMarshaler() : 
2485         m_dwCCHLocal(-1)
2486        ,m_dwLocalBuffer(-1)
2487     {
2488         LIMITED_METHOD_CONTRACT;
2489     }
2490
2491     virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2492     virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2493
2494 protected:
2495     virtual LocalDesc GetNativeType();
2496     virtual LocalDesc GetManagedType();
2497     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2498     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2499     virtual bool NeedsClearNative();
2500     virtual void EmitClearNative(ILCodeStream* pslILEmit);
2501     virtual bool IsNativePassedByRef();
2502         
2503     DWORD m_dwCCHLocal;
2504     DWORD m_dwLocalBuffer;
2505 };
2506
2507 class ILVBByValStrMarshaler : public ILMarshaler
2508 {
2509 public:
2510     enum
2511     {
2512         c_fInOnly               = FALSE,
2513         c_nativeSize            = sizeof(LPSTR),
2514         c_CLRSize               = sizeof(OBJECTREF *),
2515     };
2516
2517     ILVBByValStrMarshaler() :
2518         m_dwCCHLocal(-1)
2519     {
2520         LIMITED_METHOD_CONTRACT;
2521     }
2522
2523     virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2524     virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2525
2526 protected:
2527     virtual LocalDesc GetNativeType();
2528     virtual LocalDesc GetManagedType();
2529     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2530     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2531     virtual bool NeedsClearNative();
2532     virtual void EmitClearNative(ILCodeStream* pslILEmit);
2533     virtual bool IsNativePassedByRef();
2534
2535     DWORD m_dwCCHLocal;
2536 };
2537
2538 class ILHSTRINGMarshaler : public ILMarshaler
2539 {
2540 public:
2541     enum
2542     {
2543         c_fInOnly               = FALSE,
2544         c_nativeSize            = sizeof(HSTRING),
2545         c_CLRSize               = sizeof(OBJECTREF),
2546     };
2547
2548 protected:
2549     virtual LocalDesc GetNativeType();
2550     virtual LocalDesc GetManagedType();
2551
2552     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2553     void EmitConvertCLRToHSTRINGReference(ILCodeStream* pslILEmit);
2554     void EmitConvertCLRToHSTRING(ILCodeStream* pslILEmit);
2555
2556     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2557
2558     virtual bool NeedsClearNative();
2559     virtual void EmitClearNative(ILCodeStream* pslILEmit);
2560 };
2561 #endif // FEATURE_COMINTEROP
2562
2563
2564 class ILCUTF8Marshaler : public ILOptimizedAllocMarshaler
2565 {
2566 public:
2567         enum
2568         {
2569                 c_fInOnly = TRUE,
2570                 c_nativeSize = sizeof(void *),
2571                 c_CLRSize = sizeof(OBJECTREF),
2572         };
2573
2574         enum
2575         {
2576                 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2577                 MAX_LOCAL_BUFFER_LENGTH = MAX_PATH_FNAME + 1
2578         };
2579
2580         ILCUTF8Marshaler() :
2581                 ILOptimizedAllocMarshaler(METHOD__CSTRMARSHALER__CLEAR_NATIVE)
2582         {
2583                 LIMITED_METHOD_CONTRACT;
2584         }
2585
2586 protected:
2587         virtual LocalDesc GetManagedType();
2588         virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2589         virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2590 };
2591
2592
2593
2594 class ILCSTRMarshaler : public ILOptimizedAllocMarshaler
2595 {
2596 public:
2597     enum
2598     {
2599         c_fInOnly               = TRUE,
2600         c_nativeSize            = sizeof(void *),
2601         c_CLRSize               = sizeof(OBJECTREF),
2602     };
2603
2604     enum
2605     {
2606         // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2607         MAX_LOCAL_BUFFER_LENGTH = MAX_PATH_FNAME + 1
2608     };
2609
2610     ILCSTRMarshaler() :
2611         ILOptimizedAllocMarshaler(METHOD__CSTRMARSHALER__CLEAR_NATIVE)
2612     {
2613         LIMITED_METHOD_CONTRACT;
2614     }
2615
2616 protected:    
2617     virtual LocalDesc GetManagedType();
2618     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2619     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2620 };
2621
2622 class ILBSTRMarshaler : public ILOptimizedAllocMarshaler
2623 {
2624 public:
2625     enum
2626     {
2627         c_fInOnly               = TRUE,
2628         c_nativeSize            = sizeof(void *),
2629         c_CLRSize               = sizeof(OBJECTREF),
2630     };
2631
2632     enum
2633     {
2634         // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2635         MAX_LOCAL_BUFFER_LENGTH = (MAX_PATH_FNAME + 1) * 2 + 4
2636     };
2637
2638     ILBSTRMarshaler() :
2639         ILOptimizedAllocMarshaler(METHOD__BSTRMARSHALER__CLEAR_NATIVE)
2640     {
2641         LIMITED_METHOD_CONTRACT;
2642     }
2643
2644 protected:    
2645     virtual LocalDesc GetManagedType();
2646     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2647     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2648 };
2649
2650 #ifdef FEATURE_COMINTEROP
2651 class ILAnsiBSTRMarshaler : public ILMarshaler
2652 {
2653 public:
2654     enum
2655     {
2656         c_fInOnly               = TRUE,
2657         c_nativeSize            = sizeof(void *),
2658         c_CLRSize               = sizeof(OBJECTREF),
2659     };
2660
2661 protected:    
2662     virtual LocalDesc GetNativeType();
2663     virtual LocalDesc GetManagedType();
2664     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2665     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2666     virtual bool NeedsClearNative();
2667     virtual void EmitClearNative(ILCodeStream* pslILEmit);
2668 };
2669 #endif // FEATURE_COMINTEROP
2670
2671 class ILLayoutClassPtrMarshalerBase : public ILMarshaler
2672 {
2673 public:
2674     enum
2675     {
2676         c_nativeSize            = sizeof(void *),
2677         c_CLRSize               = sizeof(OBJECTREF),
2678     };
2679
2680 protected:    
2681     virtual LocalDesc GetNativeType();
2682     virtual LocalDesc GetManagedType();
2683     virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
2684     virtual void EmitConvertSpaceCLRToNativeTemp(ILCodeStream* pslILEmit);
2685     virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit);
2686     virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
2687     virtual bool NeedsClearNative();
2688     virtual void EmitClearNative(ILCodeStream* pslILEmit);
2689     virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit);
2690 };
2691
2692 class ILLayoutClassPtrMarshaler : public ILLayoutClassPtrMarshalerBase
2693 {
2694 public:
2695     enum
2696     {
2697         c_fInOnly               = FALSE,
2698     };
2699         
2700 protected:    
2701     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2702     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2703     virtual void EmitClearNativeContents(ILCodeStream * pslILEmit);
2704 };
2705
2706 class ILBlittablePtrMarshaler : public ILLayoutClassPtrMarshalerBase
2707 {
2708 public:
2709     enum
2710     {
2711         c_fInOnly               = FALSE,
2712     };
2713             
2714 protected:    
2715     virtual void EmitMarshalArgumentCLRToNative();
2716     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2717     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2718 };
2719
2720
2721
2722
2723 class ILArgIteratorMarshaler : public ILMarshaler
2724 {
2725 public:
2726     enum
2727     {
2728         c_fInOnly               = TRUE,
2729         c_nativeSize            = sizeof(va_list),
2730         c_CLRSize               = sizeof(VARARGS),
2731     };
2732
2733 protected:
2734     virtual LocalDesc GetNativeType();
2735     virtual LocalDesc GetManagedType();
2736     virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2737     virtual void EmitMarshalArgumentCLRToNative();
2738     virtual void EmitMarshalArgumentNativeToCLR();
2739 };
2740         
2741 class ILArrayWithOffsetMarshaler : public ILMarshaler
2742 {
2743 public:
2744     enum
2745     {
2746         c_fInOnly               = FALSE,
2747         c_nativeSize            = sizeof(LPVOID),
2748         c_CLRSize               = sizeof(ArrayWithOffsetData),
2749     };
2750
2751     ILArrayWithOffsetMarshaler() : 
2752         m_dwCountLocalNum(-1),
2753         m_dwOffsetLocalNum(-1),
2754         m_dwPinnedLocalNum(-1)
2755     {
2756         LIMITED_METHOD_CONTRACT;
2757     }
2758
2759 protected:
2760     virtual LocalDesc GetNativeType();
2761     virtual LocalDesc GetManagedType();
2762     virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2763
2764     virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit);
2765     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2766     virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit);
2767
2768         
2769     DWORD m_dwCountLocalNum;
2770     DWORD m_dwOffsetLocalNum;
2771     DWORD m_dwPinnedLocalNum;
2772 };
2773
2774 class ILAsAnyMarshalerBase : public ILMarshaler
2775 {
2776 public:
2777     enum
2778     {
2779         c_nativeSize            = sizeof(void *),
2780         c_CLRSize               = sizeof(OBJECTREF),
2781     };
2782
2783     ILAsAnyMarshalerBase() :
2784         m_dwMarshalerLocalNum(-1)
2785     {
2786         LIMITED_METHOD_CONTRACT;
2787     }
2788
2789 protected:
2790     static const BYTE ML_IN  = 0x10;
2791     static const BYTE ML_OUT = 0x20;
2792
2793     virtual bool IsAnsi() = 0;
2794     virtual LocalDesc GetNativeType();
2795     virtual LocalDesc GetManagedType();
2796     virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2797     virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2798     virtual void EmitMarshalArgumentCLRToNative();
2799     virtual bool NeedsClearNative();
2800     virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit);
2801
2802     DWORD m_dwMarshalerLocalNum;
2803 };
2804
2805 class ILAsAnyWMarshaler : public ILAsAnyMarshalerBase
2806 {
2807 public:
2808     enum
2809     {
2810         c_fInOnly               = FALSE,
2811     };
2812
2813 protected:
2814     virtual bool IsAnsi() 
2815     {
2816         return false;
2817     }
2818 };
2819
2820 class ILAsAnyAMarshaler : public ILAsAnyMarshalerBase
2821 {
2822 public:
2823     enum
2824     {
2825         c_fInOnly               = FALSE,
2826     };
2827
2828 protected:
2829     virtual bool IsAnsi() 
2830     {
2831         return true;
2832     }
2833 };
2834
2835
2836 class ILMngdMarshaler : public ILMarshaler
2837 {
2838 public:
2839     enum
2840     {
2841         c_nativeSize            = sizeof(void *),
2842         c_CLRSize               = sizeof(OBJECTREF),
2843     };
2844
2845     ILMngdMarshaler(BinderMethodID space2Man, 
2846                     BinderMethodID contents2Man, 
2847                     BinderMethodID space2Nat, 
2848                     BinderMethodID contents2Nat, 
2849                     BinderMethodID clearNat, 
2850                     BinderMethodID clearNatContents,
2851                     BinderMethodID clearMan) :
2852         m_idConvertSpaceToManaged(space2Man),
2853         m_idConvertContentsToManaged(contents2Man),
2854         m_idConvertSpaceToNative(space2Nat),
2855         m_idConvertContentsToNative(contents2Nat),
2856         m_idClearNative(clearNat),
2857         m_idClearNativeContents(clearNatContents),
2858         m_idClearManaged(clearMan)
2859     {
2860         LIMITED_METHOD_CONTRACT;
2861     }
2862     
2863 protected:    
2864     virtual LocalDesc GetNativeType();
2865     virtual LocalDesc GetManagedType();
2866
2867     virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) = 0;
2868
2869     virtual void EmitCallMngdMarshalerMethod(ILCodeStream* pslILEmit, MethodDesc *pMD);
2870
2871     virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
2872     {
2873         WRAPPER_NO_CONTRACT;
2874         EmitCallMngdMarshalerMethod(pslILEmit, GetConvertSpaceToManagedMethod());
2875     }
2876     
2877     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2878     {
2879         WRAPPER_NO_CONTRACT;
2880         EmitCallMngdMarshalerMethod(pslILEmit, GetConvertContentsToManagedMethod());
2881     }
2882     
2883     virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
2884     {
2885         WRAPPER_NO_CONTRACT;
2886         EmitCallMngdMarshalerMethod(pslILEmit, GetConvertSpaceToNativeMethod());
2887     }
2888     
2889     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2890     {
2891         WRAPPER_NO_CONTRACT;
2892         EmitCallMngdMarshalerMethod(pslILEmit, GetConvertContentsToNativeMethod());
2893     }
2894
2895     virtual bool NeedsClearNative()
2896     {
2897         LIMITED_METHOD_CONTRACT;
2898
2899         if (NULL != GetClearNativeMethod())
2900         {
2901             return true;
2902         }
2903             
2904         return false;
2905     }
2906     
2907     virtual void EmitClearNative(ILCodeStream* pslILEmit)
2908     {
2909         WRAPPER_NO_CONTRACT;
2910         EmitCallMngdMarshalerMethod(pslILEmit, GetClearNativeMethod());
2911     }
2912     
2913     virtual void EmitClearNativeContents(ILCodeStream* pslILEmit)
2914     {
2915         WRAPPER_NO_CONTRACT;
2916         EmitCallMngdMarshalerMethod(pslILEmit, GetClearNativeContentsMethod());
2917     }
2918
2919     
2920     virtual bool NeedsClearCLR()
2921     {
2922         LIMITED_METHOD_CONTRACT;
2923
2924         if (NULL != GetClearManagedMethod())
2925         {
2926             return true;
2927         }
2928             
2929         return false;
2930     }
2931
2932     virtual void EmitClearCLR(ILCodeStream* pslILEmit)
2933     {
2934         WRAPPER_NO_CONTRACT;
2935         EmitCallMngdMarshalerMethod(pslILEmit, GetClearManagedMethod());
2936     }
2937
2938     virtual MethodDesc *GetConvertSpaceToManagedMethod()    { WRAPPER_NO_CONTRACT; return (m_idConvertSpaceToManaged    == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idConvertSpaceToManaged));    }
2939     virtual MethodDesc *GetConvertContentsToManagedMethod() { WRAPPER_NO_CONTRACT; return (m_idConvertContentsToManaged == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idConvertContentsToManaged)); }
2940     virtual MethodDesc *GetConvertSpaceToNativeMethod()     { WRAPPER_NO_CONTRACT; return (m_idConvertSpaceToNative     == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idConvertSpaceToNative));     }
2941     virtual MethodDesc *GetConvertContentsToNativeMethod()  { WRAPPER_NO_CONTRACT; return (m_idConvertContentsToNative  == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idConvertContentsToNative));  }
2942     virtual MethodDesc *GetClearNativeMethod()              { WRAPPER_NO_CONTRACT; return (m_idClearNative              == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idClearNative));              }
2943     virtual MethodDesc *GetClearNativeContentsMethod()      { WRAPPER_NO_CONTRACT; return (m_idClearNativeContents      == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idClearNativeContents));      }
2944     virtual MethodDesc *GetClearManagedMethod()             { WRAPPER_NO_CONTRACT; return (m_idClearManaged             == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idClearManaged));             }
2945
2946     const BinderMethodID m_idConvertSpaceToManaged;
2947     const BinderMethodID m_idConvertContentsToManaged;
2948     const BinderMethodID m_idConvertSpaceToNative;
2949     const BinderMethodID m_idConvertContentsToNative;
2950     const BinderMethodID m_idClearNative;
2951     const BinderMethodID m_idClearNativeContents;
2952     const BinderMethodID m_idClearManaged;
2953 };
2954
2955 class ILNativeArrayMarshaler : public ILMngdMarshaler
2956 {
2957 public:    
2958     enum
2959     {
2960         c_fInOnly               = FALSE,
2961     };
2962
2963     ILNativeArrayMarshaler() : 
2964         ILMngdMarshaler(
2965             METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CONVERT_SPACE_TO_MANAGED,
2966             METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED,
2967             METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CONVERT_SPACE_TO_NATIVE,
2968             METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE,
2969             METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CLEAR_NATIVE,
2970             METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CLEAR_NATIVE_CONTENTS,
2971             METHOD__NIL
2972             )
2973     {
2974         LIMITED_METHOD_CONTRACT;
2975         m_dwSavedSizeArg = LOCAL_NUM_UNUSED;
2976     }
2977
2978     virtual void EmitMarshalArgumentCLRToNative();
2979     virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
2980     virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
2981     virtual void EmitClearNative(ILCodeStream* pslILEmit);    
2982     virtual void EmitClearNativeContents(ILCodeStream* pslILEmit);
2983     virtual void EmitMarshalArgumentNativeToCLRByref();
2984     virtual void EmitMarshalArgumentCLRToNativeByref();
2985     
2986 protected:
2987     
2988     bool UsePinnedArraySpecialCase();
2989     
2990     BOOL CheckSizeParamIndexArg(const CREATE_MARSHALER_CARRAY_OPERANDS &mops, CorElementType *pElementType);
2991     
2992     // Calculate element count and load it on evaluation stack
2993     void EmitLoadElementCount(ILCodeStream* pslILEmit);    
2994
2995     virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
2996
2997     void EmitLoadNativeSize(ILCodeStream* pslILEmit);
2998     void EmitNewSavedSizeArgLocal();
2999     
3000 private :
3001     DWORD m_dwSavedSizeArg;                 
3002 };
3003
3004 class MngdNativeArrayMarshaler
3005 {
3006 public:
3007     static FCDECL3(void, CreateMarshaler,           MngdNativeArrayMarshaler* pThis, MethodTable* pMT, UINT32 dwFlags);
3008     static FCDECL3(void, ConvertSpaceToNative,      MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3009     static FCDECL3(void, ConvertContentsToNative,   MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3010     static FCDECL4(void, ConvertSpaceToManaged,     MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements);
3011     static FCDECL3(void, ConvertContentsToManaged,  MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3012     static FCDECL3(void, ClearNative,               MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
3013     static FCDECL3(void, ClearNativeContents,       MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
3014
3015     static void DoClearNativeContents(MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
3016         
3017     enum
3018     {
3019         FLAG_NATIVE_DATA_VALID = 0x40000000
3020     };
3021
3022     MethodTable*            m_pElementMT;
3023     TypeHandle              m_Array;
3024     BOOL                    m_NativeDataValid;
3025     BOOL                    m_BestFitMap;
3026     BOOL                    m_ThrowOnUnmappableChar;
3027     VARTYPE                 m_vt;
3028 };
3029
3030
3031 #ifdef FEATURE_COMINTEROP
3032 class ILSafeArrayMarshaler : public ILMngdMarshaler
3033 {
3034 public:    
3035     enum
3036     {
3037         c_fInOnly               = FALSE,
3038     };
3039
3040     ILSafeArrayMarshaler() : 
3041         ILMngdMarshaler(
3042             METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_SPACE_TO_MANAGED,
3043             METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED,
3044             METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_SPACE_TO_NATIVE,
3045             METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE,
3046             METHOD__MNGD_SAFE_ARRAY_MARSHALER__CLEAR_NATIVE,
3047             METHOD__NIL,
3048             METHOD__NIL
3049             ), 
3050         m_dwOriginalManagedLocalNum(-1)
3051     {
3052         LIMITED_METHOD_CONTRACT;
3053     }
3054     
3055 protected:
3056
3057     virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
3058     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3059     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3060
3061     virtual void EmitReInitNative(ILCodeStream* pslILEmit)
3062     {
3063         CONTRACTL
3064         {
3065             THROWS;
3066             GC_TRIGGERS;
3067             MODE_ANY;
3068         }
3069         CONTRACTL_END;
3070         if (NeedsCheckForStatic() && pslILEmit->GetStreamType() != ILStubLinker::kExceptionCleanup)
3071         {
3072             // Keep the original value in native home as we are not going to allocate a new
3073             // one. If we cleared it here, we wouldn't be able to ConvertContentsToNative.
3074             // Always perform the real re-init in the ExceptionCleanup stream so the caller
3075             // doesn't get back garbage.
3076         }
3077         else
3078         {
3079             ILMngdMarshaler::EmitReInitNative(pslILEmit);
3080         }
3081     }
3082
3083     bool NeedsCheckForStatic()
3084     {
3085         WRAPPER_NO_CONTRACT;
3086         return IsByref(m_dwMarshalFlags) && !IsCLRToNative(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags);
3087     }
3088
3089     DWORD m_dwOriginalManagedLocalNum;
3090 };
3091
3092 class MngdSafeArrayMarshaler
3093 {
3094 public:
3095     static FCDECL4(void, CreateMarshaler,           MngdSafeArrayMarshaler* pThis, MethodTable* pMT, UINT32 iRank, UINT32 dwFlags);
3096     static FCDECL3(void, ConvertSpaceToNative,      MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3097     static FCDECL4(void, ConvertContentsToNative,   MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, Object* pOriginalManagedUNSAFE);
3098     static FCDECL3(void, ConvertSpaceToManaged,     MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3099     static FCDECL3(void, ConvertContentsToManaged,  MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3100     static FCDECL3(void, ClearNative,               MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3101
3102     enum StaticCheckStateFlags
3103     {
3104         SCSF_CheckForStatic = 1,
3105         SCSF_IsStatic = 2,
3106         SCSF_NativeDataValid = 4
3107     };
3108
3109     MethodTable*    m_pElementMT;
3110     int             m_iRank;
3111     VARTYPE         m_vt;
3112     BYTE            m_fStatic;     // StaticCheckStateFlags
3113     BYTE            m_nolowerbounds;
3114 };
3115
3116 class ILHiddenLengthArrayMarshaler : public ILMngdMarshaler
3117 {
3118     friend class MngdHiddenLengthArrayMarshaler;
3119
3120 public:
3121     enum
3122     {
3123         c_nativeSize            = sizeof(LPVOID),
3124         c_CLRSize               = sizeof(OBJECTREF),
3125         c_fInOnly               = FALSE,
3126     };
3127
3128     ILHiddenLengthArrayMarshaler() :
3129         ILMngdMarshaler(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_SPACE_TO_MANAGED,
3130                         METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED,
3131                         METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_SPACE_TO_NATIVE,
3132                         METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE,
3133                         METHOD__WIN32NATIVE__COTASKMEMFREE,
3134                         METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CLEAR_NATIVE_CONTENTS,
3135                         METHOD__NIL)
3136     {
3137         LIMITED_METHOD_CONTRACT;
3138         m_dwMngdMarshalerLocalNum = -1;
3139     }
3140
3141 protected:
3142     virtual LocalDesc GetNativeType();
3143     virtual LocalDesc GetManagedType();
3144
3145     virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
3146     virtual void EmitMarshalArgumentCLRToNative();
3147     virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
3148     virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
3149     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3150     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3151     virtual void EmitClearNative(ILCodeStream* pslILEmit);    
3152     virtual void EmitClearNativeContents(ILCodeStream* pslILEmit);
3153
3154 private:
3155     bool CanUsePinnedArray();
3156     void EmitLoadNativeArrayLength(ILCodeStream *pslILEmit);
3157
3158     virtual MethodDesc *GetConvertContentsToManagedMethod();
3159     virtual MethodDesc *GetConvertContentsToNativeMethod();
3160     virtual MethodDesc *GetClearNativeContentsMethod();
3161
3162     MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD);
3163 };
3164
3165 class MngdHiddenLengthArrayMarshaler
3166 {
3167 public:
3168     static FCDECL4(void, CreateMarshaler,           MngdHiddenLengthArrayMarshaler* pThis, MethodTable* pMT, SIZE_T cbElement, UINT16 vt);
3169     static FCDECL3(void, ConvertSpaceToNative,      MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3170     static FCDECL3(void, ConvertContentsToNative,   MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3171     static FCDECL4(void, ConvertSpaceToManaged,     MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements);
3172     static FCDECL3(void, ConvertContentsToManaged,  MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3173     static FCDECL3(void, ClearNativeContents,       MngdHiddenLengthArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
3174
3175
3176 private:
3177     SIZE_T GetArraySize(SIZE_T elements);
3178     void DoClearNativeContents(void** pNativeHome, INT32 cElements);
3179
3180 private:
3181     MethodTable                         *m_pElementMT;
3182     SIZE_T                               m_cbElementSize;
3183     VARTYPE                              m_vt;
3184 };
3185 #endif // FEATURE_COMINTEROP
3186
3187
3188 class ILReferenceCustomMarshaler : public ILMngdMarshaler
3189 {
3190 public:    
3191     enum
3192     {
3193         c_fInOnly               = FALSE,
3194     };
3195
3196     ILReferenceCustomMarshaler() : 
3197         ILMngdMarshaler(
3198             METHOD__NIL,
3199             METHOD__MNGD_REF_CUSTOM_MARSHALER__CONVERT_CONTENTS_TO_MANAGED,
3200             METHOD__NIL,
3201             METHOD__MNGD_REF_CUSTOM_MARSHALER__CONVERT_CONTENTS_TO_NATIVE,
3202             METHOD__MNGD_REF_CUSTOM_MARSHALER__CLEAR_NATIVE,
3203             METHOD__NIL,
3204             METHOD__MNGD_REF_CUSTOM_MARSHALER__CLEAR_MANAGED
3205             )
3206     {
3207         LIMITED_METHOD_CONTRACT;
3208     }
3209         
3210 protected:
3211     virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
3212 };
3213
3214 class MngdRefCustomMarshaler
3215 {
3216 public:
3217     static FCDECL2(void, CreateMarshaler,           MngdRefCustomMarshaler* pThis, void* pCMHelper);
3218     static FCDECL3(void, ConvertContentsToNative,   MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3219     static FCDECL3(void, ConvertContentsToManaged,  MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3220     static FCDECL3(void, ClearNative,               MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3221     static FCDECL3(void, ClearManaged,              MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3222
3223     static void DoClearNativeContents(MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3224
3225     CustomMarshalerHelper*  m_pCMHelper;
3226 };
3227
3228
3229 #ifdef FEATURE_COMINTEROP
3230 class ILUriMarshaler : public ILMarshaler
3231 {
3232 public:
3233     enum
3234     {
3235         c_fInOnly               = TRUE,
3236         c_nativeSize            = sizeof(LPVOID),
3237         c_CLRSize               = sizeof(OBJECTREF),
3238     };
3239
3240     static void EmitConvertCLRUriToWinRTUri(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3241     static void EmitConvertWinRTUriToCLRUri(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3242
3243 protected:
3244     virtual LocalDesc GetNativeType();
3245     virtual LocalDesc GetManagedType();
3246
3247     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);    
3248     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3249
3250     virtual bool NeedsClearNative();
3251     void EmitClearNative(ILCodeStream* pslILEmit);
3252 };
3253
3254 class ILNCCEventArgsMarshaler : public ILMarshaler
3255 {
3256 public:
3257     enum
3258     {
3259         c_fInOnly               = TRUE,
3260         c_nativeSize            = sizeof(LPVOID),
3261         c_CLRSize               = sizeof(OBJECTREF),
3262     };
3263
3264     static void EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3265     static void EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3266
3267 protected:
3268     virtual LocalDesc GetNativeType();
3269     virtual LocalDesc GetManagedType();
3270
3271     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);    
3272     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3273
3274     virtual bool NeedsClearNative();
3275     void EmitClearNative(ILCodeStream* pslILEmit);
3276 };
3277
3278 class ILPCEventArgsMarshaler : public ILMarshaler
3279 {
3280 public:
3281     enum
3282     {
3283         c_fInOnly               = TRUE,
3284         c_nativeSize            = sizeof(LPVOID),
3285         c_CLRSize               = sizeof(OBJECTREF),
3286     };
3287
3288     static void EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3289     static void EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3290
3291 protected:
3292     virtual LocalDesc GetNativeType();
3293     virtual LocalDesc GetManagedType();
3294
3295     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);    
3296     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3297
3298     virtual bool NeedsClearNative();
3299     void EmitClearNative(ILCodeStream* pslILEmit);
3300 };
3301
3302 class ILDateTimeMarshaler : public ILMarshaler
3303 {
3304 public:
3305     enum
3306     {
3307         c_fInOnly               = FALSE,
3308         c_nativeSize            = sizeof(INT64),  // = sizeof(Windows::Foundation::DateTime)
3309         c_CLRSize               = VARIABLESIZE,
3310     };
3311
3312 protected:
3313     virtual LocalDesc GetNativeType();
3314     virtual LocalDesc GetManagedType();
3315
3316     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);    
3317     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3318
3319     virtual bool NeedsClearNative();
3320     virtual void EmitReInitNative(ILCodeStream* pslILEmit);
3321 };
3322
3323 class ILNullableMarshaler : public ILMarshaler
3324 {
3325 public:
3326     enum
3327     {
3328         c_fInOnly               = FALSE,
3329         c_nativeSize            = sizeof(LPVOID),
3330         c_CLRSize               = VARIABLESIZE,
3331     };
3332                 
3333 protected:
3334     virtual LocalDesc GetNativeType();
3335     virtual LocalDesc GetManagedType();
3336     virtual bool NeedsClearNative();
3337     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3338     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);    
3339     virtual void EmitClearNative(ILCodeStream* pslILEmit);    
3340
3341 private:
3342     MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD);
3343 };
3344
3345 class ILSystemTypeMarshaler : public ILMarshaler
3346 {
3347 public:
3348     enum
3349     {
3350         c_fInOnly           = FALSE, 
3351         c_nativeSize        = sizeof(TypeNameNative),
3352         c_CLRSize           = sizeof(OBJECTREF)
3353     };
3354
3355 protected:
3356     virtual LocalDesc GetNativeType();
3357     virtual LocalDesc GetManagedType();
3358
3359     virtual void EmitConvertContentsCLRToNative(ILCodeStream * pslILEmit);
3360     virtual void EmitConvertContentsNativeToCLR(ILCodeStream * pslILEmit);
3361
3362     virtual bool NeedsClearNative();
3363     virtual void EmitClearNative(ILCodeStream * pslILEmit);
3364     virtual void EmitReInitNative(ILCodeStream * pslILEmit);
3365 };
3366
3367 class ILHResultExceptionMarshaler : public ILMarshaler
3368 {
3369 public:
3370     enum
3371     {
3372         c_fInOnly               = FALSE,
3373         c_nativeSize            = sizeof(INT32),  // = sizeof(Windows::Foundation::HResult)
3374         c_CLRSize               = sizeof(OBJECTREF),
3375     };
3376
3377 protected:
3378     virtual LocalDesc GetNativeType();
3379     virtual LocalDesc GetManagedType();
3380
3381     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);    
3382     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3383
3384     virtual bool NeedsClearNative();
3385 };
3386
3387 class ILKeyValuePairMarshaler : public ILMarshaler
3388 {
3389 public:
3390     enum
3391     {
3392         c_fInOnly               = FALSE,
3393         c_nativeSize            = sizeof(LPVOID),
3394         c_CLRSize               = VARIABLESIZE,
3395     };
3396                 
3397 protected:
3398     virtual LocalDesc GetNativeType();
3399     virtual LocalDesc GetManagedType();
3400     virtual bool NeedsClearNative();
3401     virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3402     virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3403     virtual void EmitClearNative(ILCodeStream* pslILEmit);
3404
3405 private:
3406     MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD);
3407 };
3408
3409 #endif // FEATURE_COMINTEROP