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