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