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.
5 // File: ILMarshalers.h
12 #ifdef FEATURE_COMINTEROP
13 #include "winstring.h"
14 #endif //FEATURE_COMINTEROP
17 #include "marshalnative.h"
18 #include "clrvarargs.h"
19 #ifdef FEATURE_COMINTEROP
20 #include "stdinterfaces.h"
23 #define LOCAL_NUM_UNUSED ((DWORD)-1)
25 class ILStubMarshalHome
30 HomeType_Unspecified = 0,
32 HomeType_ILArgument = 2,
33 HomeType_ILByrefLocal = 3,
34 HomeType_ILByrefArgument = 4
38 MarshalHomeType m_homeType;
42 void InitHome(MarshalHomeType homeType, DWORD dwHomeIndex)
44 LIMITED_METHOD_CONTRACT;
45 m_homeType = homeType;
46 m_dwHomeIndex = dwHomeIndex;
49 void EmitLoadHome(ILCodeStream* pslILEmit)
61 case HomeType_ILLocal: pslILEmit->EmitLDLOC(m_dwHomeIndex); break;
62 case HomeType_ILArgument: pslILEmit->EmitLDARG(m_dwHomeIndex); break;
65 UNREACHABLE_MSG("unexpected homeType passed to EmitLoadHome");
70 void EmitLoadHomeAddr(ILCodeStream* pslILEmit)
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;
88 UNREACHABLE_MSG("unexpected homeType passed to EmitLoadHomeAddr");
93 void EmitStoreHome(ILCodeStream* pslILEmit)
105 case HomeType_ILLocal: pslILEmit->EmitSTLOC(m_dwHomeIndex); break;
106 case HomeType_ILArgument: pslILEmit->EmitSTARG(m_dwHomeIndex); break;
109 UNREACHABLE_MSG("unexpected homeType passed to EmitStoreHome");
114 void EmitStoreHomeAddr(ILCodeStream* pslILEmit)
126 case HomeType_ILByrefLocal: pslILEmit->EmitSTLOC(m_dwHomeIndex); break;
127 case HomeType_ILByrefArgument: pslILEmit->EmitSTARG(m_dwHomeIndex); break;
130 UNREACHABLE_MSG("unexpected homeType passed to EmitStoreHomeAddr");
135 void EmitCopyFromByrefArg(ILCodeStream* pslILEmit, LocalDesc* pManagedType, DWORD argidx)
145 CONSISTENCY_CHECK(pManagedType->cbType == 1);
146 if (pManagedType->IsValueClass())
148 EmitLoadHomeAddr(pslILEmit); // dest
149 pslILEmit->EmitLDARG(argidx); // src
150 pslILEmit->EmitCPOBJ(pslILEmit->GetToken(pManagedType->InternalToken));
154 pslILEmit->EmitLDARG(argidx);
155 pslILEmit->EmitLDIND_T(pManagedType);
156 EmitStoreHome(pslILEmit);
160 void EmitCopyToByrefArg(ILCodeStream* pslILEmit, LocalDesc* pManagedType, DWORD argidx)
170 if (pManagedType->IsValueClass())
172 pslILEmit->EmitLDARG(argidx); // dest
173 EmitLoadHomeAddr(pslILEmit); // src
174 pslILEmit->EmitCPOBJ(pslILEmit->GetToken(pManagedType->InternalToken));
178 pslILEmit->EmitLDARG(argidx);
179 EmitLoadHome(pslILEmit);
180 pslILEmit->EmitSTIND_T(pManagedType);
184 void EmitCopyToByrefArgWithNullCheck(ILCodeStream* pslILEmit, LocalDesc* pManagedType, DWORD argidx)
194 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
196 // prevent null-ref exception by an explicit check
197 pslILEmit->EmitLDARG(argidx);
198 pslILEmit->EmitBRFALSE(pNullRefLabel);
200 EmitCopyToByrefArg(pslILEmit, pManagedType, argidx);
202 pslILEmit->EmitLabel(pNullRefLabel);
212 const static UINT s_cbStackAllocThreshold = 128;
214 const static UINT s_cbStackAllocThreshold = 2048;
217 OverrideProcArgs* m_pargs;
218 NDirectStubLinker* m_pslNDirect;
219 ILCodeStream* m_pcsMarshal;
220 ILCodeStream* m_pcsUnmarshal;
223 DWORD m_dwMarshalFlags;
225 ILStubMarshalHome m_nativeHome;
226 ILStubMarshalHome m_managedHome;
228 DWORD m_dwMngdMarshalerLocalNum;
237 virtual ~ILMarshaler()
239 LIMITED_METHOD_CONTRACT;
242 void SetNDirectStubLinker(NDirectStubLinker* pslNDirect)
244 LIMITED_METHOD_CONTRACT;
245 CONSISTENCY_CHECK(NULL == m_pslNDirect);
246 m_pslNDirect = pslNDirect;
249 void Init(ILCodeStream* pcsMarshal,
250 ILCodeStream* pcsUnmarshal,
252 DWORD dwMarshalFlags,
253 OverrideProcArgs* pargs)
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;
260 m_dwMarshalFlags = dwMarshalFlags;
262 m_dwMngdMarshalerLocalNum = -1;
266 static inline bool IsCLRToNative(DWORD dwMarshalFlags)
268 LIMITED_METHOD_CONTRACT;
269 return (0 != (dwMarshalFlags & MARSHAL_FLAG_CLR_TO_NATIVE));
272 static inline bool IsIn(DWORD dwMarshalFlags)
274 LIMITED_METHOD_CONTRACT;
275 return (0 != (dwMarshalFlags & MARSHAL_FLAG_IN));
278 static inline bool IsOut(DWORD dwMarshalFlags)
280 LIMITED_METHOD_CONTRACT;
281 return (0 != (dwMarshalFlags & MARSHAL_FLAG_OUT));
284 static inline bool IsByref(DWORD dwMarshalFlags)
286 LIMITED_METHOD_CONTRACT;
287 return (0 != (dwMarshalFlags & MARSHAL_FLAG_BYREF));
290 static inline bool IsHresultSwap(DWORD dwMarshalFlags)
292 LIMITED_METHOD_CONTRACT;
293 return (0 != (dwMarshalFlags & MARSHAL_FLAG_HRESULT_SWAP));
296 static inline bool IsRetval(DWORD dwMarshalFlags)
298 LIMITED_METHOD_CONTRACT;
299 return (0 != (dwMarshalFlags & MARSHAL_FLAG_RETVAL));
302 static inline bool IsHiddenLengthParam(DWORD dwMarshalFlags)
304 LIMITED_METHOD_CONTRACT;
305 return (0 != (dwMarshalFlags & MARSHAL_FLAG_HIDDENLENPARAM));
308 void EmitLoadManagedValue(ILCodeStream* pslILEmit)
311 m_managedHome.EmitLoadHome(pslILEmit);
314 void EmitLoadNativeValue(ILCodeStream* pslILEmit)
317 m_nativeHome.EmitLoadHome(pslILEmit);
320 void EmitLoadManagedHomeAddr(ILCodeStream* pslILEmit)
323 m_managedHome.EmitLoadHomeAddr(pslILEmit);
326 void EmitLoadNativeHomeAddr(ILCodeStream* pslILEmit)
329 m_nativeHome.EmitLoadHomeAddr(pslILEmit);
332 void EmitStoreManagedValue(ILCodeStream* pslILEmit)
335 m_managedHome.EmitStoreHome(pslILEmit);
338 void EmitStoreManagedHomeAddr(ILCodeStream* pslILEmit)
341 m_managedHome.EmitStoreHomeAddr(pslILEmit);
344 void EmitStoreNativeValue(ILCodeStream* pslILEmit)
347 m_nativeHome.EmitStoreHome(pslILEmit);
350 void EmitStoreNativeHomeAddr(ILCodeStream* pslILEmit)
353 m_nativeHome.EmitStoreHomeAddr(pslILEmit);
358 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
360 LIMITED_METHOD_CONTRACT;
364 virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
366 LIMITED_METHOD_CONTRACT;
370 // True if marshaling creates data that could need cleanup.
371 bool NeedsMarshalCleanupIndex()
374 return (NeedsClearNative() || NeedsClearCLR());
377 // True if unmarshaling creates data that could need exception cleanup ("rollback").
378 bool NeedsUnmarshalCleanupIndex()
381 return (NeedsClearNative() && !IsCLRToNative(m_dwMarshalFlags));
384 void EmitMarshalArgument(
385 ILCodeStream* pcsMarshal,
386 ILCodeStream* pcsUnmarshal,
388 DWORD dwMarshalFlags,
389 OverrideProcArgs* pargs)
391 STANDARD_VM_CONTRACT;
393 Init(pcsMarshal, pcsUnmarshal, argidx, dwMarshalFlags, pargs);
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());
404 if (IsCLRToNative(dwMarshalFlags))
406 if (IsByref(dwMarshalFlags))
408 EmitMarshalArgumentCLRToNativeByref();
412 EmitMarshalArgumentCLRToNative();
417 if (IsByref(dwMarshalFlags))
419 EmitMarshalArgumentNativeToCLRByref();
423 EmitMarshalArgumentNativeToCLR();
428 #ifdef FEATURE_COMINTEROP
429 void EmitMarshalHiddenLengthArgument(ILCodeStream *pcsMarshal,
430 ILCodeStream *pcsUnmarshal,
431 MarshalInfo *pArrayInfo,
433 DWORD dwMarshalFlags,
435 OverrideProcArgs *pargs,
436 __out DWORD *pdwHiddenLengthManagedHomeLocal,
437 __out DWORD *pdwHiddenLengthNativeHomeLocal)
442 PRECONDITION(IsHiddenLengthParam(dwMarshalFlags));
446 Init(pcsMarshal, pcsUnmarshal, hiddenArgIndex, dwMarshalFlags, pargs);
447 EmitCreateMngdMarshaler(m_pslNDirect->GetSetupCodeStream());
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;
454 // managed length = 0
455 m_pcsMarshal->EmitLDC(0);
456 m_pcsMarshal->EmitCONV_T(pArrayInfo->GetHiddenLengthParamElementType());
457 m_pcsMarshal->EmitSTLOC(dwManagedLocalHome);
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))
464 nativeArgType.MakeByRef();
466 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, dwNativeHomeLocal);
467 *pdwHiddenLengthNativeHomeLocal = dwNativeHomeLocal;
469 // Update the native signature to contain the new native parameter
470 m_pcsMarshal->SetStubTargetArgType(&nativeArgType, false);
472 if (IsCLRToNative(dwMarshalFlags))
474 // Load the length of the array into the local
475 if (IsIn(dwMarshalFlags))
477 ILCodeLabel *pSkipGetLengthLabel = m_pcsMarshal->NewCodeLabel();
478 m_pcsMarshal->EmitLDARG(arrayIndex);
479 m_pcsMarshal->EmitBRFALSE(pSkipGetLengthLabel);
481 m_pcsMarshal->EmitLDARG(arrayIndex);
483 if (IsByref(dwMarshalFlags))
485 // if (*array == null) goto pSkipGetLengthLabel
486 m_pcsMarshal->EmitLDIND_REF();
487 m_pcsMarshal->EmitBRFALSE(pSkipGetLengthLabel);
490 m_pcsMarshal->EmitLDARG(arrayIndex);
491 m_pcsMarshal->EmitLDIND_REF();
494 m_pcsMarshal->EmitLDLEN();
495 m_pcsMarshal->EmitCONV_T(pArrayInfo->GetHiddenLengthParamElementType());
496 m_pcsMarshal->EmitSTLOC(dwManagedLocalHome);
497 m_pcsMarshal->EmitLabel(pSkipGetLengthLabel);
500 if (IsByref(dwMarshalFlags))
502 EmitMarshalArgumentContentsCLRToNativeByref(true);
506 EmitMarshalArgumentContentsCLRToNative();
511 // Load the length of the array into the local
512 if (IsIn(dwMarshalFlags))
514 m_pcsMarshal->EmitLDARG(hiddenArgIndex);
515 if (IsByref(dwMarshalFlags))
517 LocalDesc nativeParamType(GetNativeType());
518 m_pcsMarshal->EmitLDIND_T(&nativeParamType);
520 m_pcsMarshal->EmitSTLOC(dwNativeHomeLocal);
523 if (IsByref(dwMarshalFlags))
525 EmitMarshalArgumentContentsNativeToCLRByref(true);
529 EmitMarshalArgumentContentsNativeToCLR();
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.
538 #endif // FEATURE_COMINTEROP
540 virtual void EmitSetupArgument(ILCodeStream* pslILEmit)
542 STANDARD_VM_CONTRACT;
544 if (IsCLRToNative(m_dwMarshalFlags))
546 if (IsNativePassedByRef())
548 EmitLoadNativeHomeAddr(pslILEmit);
552 EmitLoadNativeValue(pslILEmit);
557 if (IsManagedPassedByRef())
559 EmitLoadManagedHomeAddr(pslILEmit);
563 EmitLoadManagedValue(pslILEmit);
568 virtual void EmitMarshalReturnValue(
569 ILCodeStream* pcsMarshal,
570 ILCodeStream* pcsUnmarshal,
571 ILCodeStream* pcsDispatch,
574 DWORD dwMarshalFlags,
575 OverrideProcArgs* pargs)
577 STANDARD_VM_CONTRACT;
579 Init(pcsMarshal, pcsUnmarshal, argidx, dwMarshalFlags, pargs);
581 LocalDesc nativeType = GetNativeType();
582 LocalDesc managedType = GetManagedType();
584 bool byrefNativeReturn = false;
585 CorElementType typ = ELEMENT_TYPE_VOID;
586 UINT32 nativeSize = 0;
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())
592 if (wNativeSize == VARIABLESIZE)
594 // the unmanaged type size is variable
595 nativeSize = m_pargs->m_pMT->GetNativeSize();
599 // the unmanaged type size is fixed
600 nativeSize = wNativeSize;
603 #if !defined(_TARGET_ARM) && !(defined(UNIX_AMD64_ABI) && defined(FEATURE_UNIX_AMD64_STRUCT_PASSING))
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;
615 if (IsHresultSwap(dwMarshalFlags) || (byrefNativeReturn && IsCLRToNative(dwMarshalFlags)))
617 LocalDesc extraParamType = nativeType;
618 extraParamType.MakeByRef();
620 m_pcsMarshal->SetStubTargetArgType(&extraParamType, false);
622 if (IsHresultSwap(dwMarshalFlags))
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
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
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);
640 if (typ != ELEMENT_TYPE_VOID)
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);
648 m_pcsMarshal->SetStubTargetReturnType(&nativeType);
652 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(managedType));
653 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(nativeType));
655 EmitCreateMngdMarshaler(m_pcsMarshal);
657 if (IsCLRToNative(dwMarshalFlags))
659 if (IsHresultSwap(dwMarshalFlags) || byrefNativeReturn)
661 EmitReInitNative(m_pcsMarshal);
662 EmitLoadNativeHomeAddr(pcsDispatch); // load up the byref native type as an extra arg
666 if (typ != ELEMENT_TYPE_VOID)
668 // small structure forward: the returned integer is memcpy'd into native home
671 DWORD dwTempLocalNum = m_pcsUnmarshal->NewLocal(typ);
672 m_pcsUnmarshal->EmitSTLOC(dwTempLocalNum);
675 m_nativeHome.EmitLoadHomeAddr(m_pcsUnmarshal);
676 m_pcsUnmarshal->EmitLDLOCA(dwTempLocalNum);
677 m_pcsUnmarshal->EmitLDC(nativeSize);
678 m_pcsUnmarshal->EmitCPBLK();
682 EmitStoreNativeValue(m_pcsUnmarshal);
686 if (NeedsMarshalCleanupIndex())
688 m_pslNDirect->EmitSetArgMarshalIndex(m_pcsUnmarshal, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx);
691 EmitConvertSpaceAndContentsNativeToCLR(m_pcsUnmarshal);
693 EmitCleanupCLRToNative();
695 EmitLoadManagedValue(m_pcsUnmarshal);
699 EmitStoreManagedValue(m_pcsUnmarshal);
701 if (NeedsMarshalCleanupIndex())
703 m_pslNDirect->EmitSetArgMarshalIndex(m_pcsUnmarshal, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx);
706 if (IsHresultSwap(dwMarshalFlags))
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();
713 m_pcsUnmarshal->EmitLDARG(argidx);
714 m_pcsUnmarshal->EmitBRFALSE(pSkipConversionLabel);
715 EmitConvertSpaceAndContentsCLRToNative(m_pcsUnmarshal);
716 m_pcsUnmarshal->EmitLabel(pSkipConversionLabel);
720 EmitConvertSpaceAndContentsCLRToNative(m_pcsUnmarshal);
723 if (NeedsUnmarshalCleanupIndex())
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);
729 EmitCleanupNativeToCLR();
731 if (IsHresultSwap(dwMarshalFlags))
733 // we tolerate NULL here mainly for backward compatibility reasons
734 m_nativeHome.EmitCopyToByrefArgWithNullCheck(m_pcsUnmarshal, &nativeType, argidx);
735 m_pcsUnmarshal->EmitLDC(S_OK);
739 if (typ != ELEMENT_TYPE_VOID)
741 // small structure return (reverse): native home of the structure is memcpy'd
742 // into the integer to be returned from the stub
744 DWORD dwTempLocalNum = m_pcsUnmarshal->NewLocal(typ);
747 m_pcsUnmarshal->EmitLDLOCA(dwTempLocalNum);
748 m_nativeHome.EmitLoadHomeAddr(m_pcsUnmarshal);
749 m_pcsUnmarshal->EmitLDC(nativeSize);
750 m_pcsUnmarshal->EmitCPBLK();
752 m_pcsUnmarshal->EmitLDLOC(dwTempLocalNum);
756 EmitLoadNativeValue(m_pcsUnmarshal);
760 // make sure we free (and zero) the return value if an exception is thrown
761 EmitExceptionCleanupNativeToCLR();
768 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
770 LIMITED_METHOD_CONTRACT;
773 virtual void EmitLoadMngdMarshaler(ILCodeStream* pslILEmit)
783 CONSISTENCY_CHECK((DWORD)-1 != m_dwMngdMarshalerLocalNum);
784 pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
787 void EmitSetupSigAndDefaultHomesCLRToNative()
792 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
796 LocalDesc nativeArgType = GetNativeType();
797 DWORD dwNativeHomeLocalNum = m_pcsMarshal->NewLocal(nativeArgType);
798 m_pcsMarshal->SetStubTargetArgType(&nativeArgType);
800 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILArgument, m_argidx);
801 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, dwNativeHomeLocalNum);
804 void EmitCleanupCLRToNativeTemp()
806 STANDARD_VM_CONTRACT;
808 if (NeedsClearNative())
810 CONSISTENCY_CHECK(NeedsMarshalCleanupIndex());
812 ILCodeStream* pcsCleanup = m_pslNDirect->GetCleanupCodeStream();
813 ILCodeLabel* pSkipClearNativeLabel = pcsCleanup->NewCodeLabel();
815 m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
816 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx,
817 NDirectStubLinker::BranchIfNotMarshaled,
818 pSkipClearNativeLabel);
820 EmitClearNativeTemp(pcsCleanup);
821 pcsCleanup->EmitLabel(pSkipClearNativeLabel);
825 void EmitCleanupCLRToNative()
827 STANDARD_VM_CONTRACT;
829 if (NeedsClearNative())
831 CONSISTENCY_CHECK(NeedsMarshalCleanupIndex());
833 ILCodeStream* pcsCleanup = m_pslNDirect->GetCleanupCodeStream();
834 ILCodeLabel* pSkipClearNativeLabel = pcsCleanup->NewCodeLabel();
836 m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
837 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx,
838 NDirectStubLinker::BranchIfNotMarshaled,
839 pSkipClearNativeLabel);
841 EmitClearNative(pcsCleanup);
842 pcsCleanup->EmitLabel(pSkipClearNativeLabel);
846 virtual void EmitMarshalArgumentCLRToNative()
851 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
855 EmitSetupSigAndDefaultHomesCLRToNative();
856 EmitMarshalArgumentContentsCLRToNative();
859 void EmitMarshalArgumentContentsCLRToNative()
864 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
871 if (IsIn(m_dwMarshalFlags))
873 EmitConvertSpaceAndContentsCLRToNativeTemp(m_pcsMarshal);
877 EmitConvertSpaceCLRToNativeTemp(m_pcsMarshal);
883 if (IsOut(m_dwMarshalFlags))
885 if (IsIn(m_dwMarshalFlags))
887 EmitClearCLRContents(m_pcsUnmarshal);
889 EmitConvertContentsNativeToCLR(m_pcsUnmarshal);
892 EmitCleanupCLRToNativeTemp();
895 void EmitSetupSigAndDefaultHomesCLRToNativeByref(bool fBlittable = false)
900 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
904 LocalDesc nativeType = GetNativeType();
905 LocalDesc managedType = GetManagedType();
907 LocalDesc nativeArgType = nativeType;
908 nativeArgType.MakeByRef();
909 m_pcsMarshal->SetStubTargetArgType(&nativeArgType);
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]);
917 // native home will keep the containing object pinned
918 nativeType.MakeByRef();
919 nativeType.MakePinned();
921 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILByrefArgument, m_argidx);
922 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILByrefLocal, m_pcsMarshal->NewLocal(nativeType));
926 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(managedType));
927 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(nativeType));
931 virtual void EmitMarshalArgumentCLRToNativeByref()
936 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
940 EmitSetupSigAndDefaultHomesCLRToNativeByref();
941 EmitMarshalArgumentContentsCLRToNativeByref(false);
944 void EmitMarshalArgumentContentsCLRToNativeByref(bool managedHomeAlreadyInitialized)
949 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
953 LocalDesc managedType = GetManagedType();
958 if (IsIn(m_dwMarshalFlags) && ! IsOut(m_dwMarshalFlags))
960 if (!managedHomeAlreadyInitialized)
962 m_managedHome.EmitCopyFromByrefArg(m_pcsMarshal, &managedType, m_argidx);
965 EmitConvertSpaceAndContentsCLRToNativeTemp(m_pcsMarshal);
967 else if (IsIn(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags))
969 if (!managedHomeAlreadyInitialized)
971 m_managedHome.EmitCopyFromByrefArg(m_pcsMarshal, &managedType, m_argidx);
974 EmitConvertSpaceAndContentsCLRToNative(m_pcsMarshal);
978 EmitReInitNative(m_pcsMarshal);
984 if (IsOut(m_dwMarshalFlags))
986 EmitClearCLR(m_pcsUnmarshal);
988 EmitConvertSpaceAndContentsNativeToCLR(m_pcsUnmarshal);
990 if (!managedHomeAlreadyInitialized)
992 m_managedHome.EmitCopyToByrefArg(m_pcsUnmarshal, &managedType, m_argidx);
995 EmitCleanupCLRToNative();
999 EmitCleanupCLRToNativeTemp();
1002 // @TODO: ensure ReInitNative is called on [in,out] byref args when an exception occurs
1006 void EmitSetupSigAndDefaultHomesNativeToCLR()
1011 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
1015 LocalDesc nativeArgType = GetNativeType();
1016 m_pcsMarshal->SetStubTargetArgType(&nativeArgType);
1018 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(GetManagedType()));
1019 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILArgument, m_argidx);
1022 void EmitCleanupNativeToCLR()
1024 STANDARD_VM_CONTRACT;
1026 if (NeedsClearCLR())
1028 CONSISTENCY_CHECK(NeedsMarshalCleanupIndex());
1030 ILCodeStream* pcsCleanup = m_pslNDirect->GetCleanupCodeStream();
1031 ILCodeLabel* pSkipClearCLRLabel = pcsCleanup->NewCodeLabel();
1033 m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
1034 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx,
1035 NDirectStubLinker::BranchIfNotMarshaled,
1036 pSkipClearCLRLabel);
1038 EmitClearCLR(pcsCleanup);
1039 pcsCleanup->EmitLabel(pSkipClearCLRLabel);
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()
1050 STANDARD_VM_CONTRACT;
1052 _ASSERTE(IsRetval(m_dwMarshalFlags) || IsOut(m_dwMarshalFlags));
1054 LocalDesc nativeType = GetNativeType();
1055 ILCodeStream *pcsCleanup = m_pslNDirect->GetExceptionCleanupCodeStream();
1057 if (NeedsClearNative())
1059 m_pslNDirect->SetExceptionCleanupNeeded();
1061 ILCodeLabel *pSkipCleanupLabel = pcsCleanup->NewCodeLabel();
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))
1067 ILCodeLabel *pSkipCopyLabel = pcsCleanup->NewCodeLabel();
1069 CONSISTENCY_CHECK(NeedsMarshalCleanupIndex());
1070 m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
1071 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx,
1072 NDirectStubLinker::BranchIfMarshaled,
1075 pcsCleanup->EmitLDARG(m_argidx);
1076 pcsCleanup->EmitBRFALSE(pSkipCleanupLabel); // if the argument is NULL, skip cleanup completely
1078 m_nativeHome.EmitCopyFromByrefArg(pcsCleanup, &nativeType, m_argidx);
1080 pcsCleanup->EmitLabel(pSkipCopyLabel);
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))
1086 CONSISTENCY_CHECK(NeedsUnmarshalCleanupIndex());
1088 UINT uArgIdx = (IsRetval(m_dwMarshalFlags) ?
1089 NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL :
1090 NDirectStubLinker::CLEANUP_INDEX_ARG0_UNMARSHAL + m_argidx);
1092 m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
1094 NDirectStubLinker::BranchIfNotMarshaled,
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)))
1101 // we own the buffer - clear everything
1102 EmitClearNative(pcsCleanup);
1106 // this is a caller supplied buffer - clear only its contents
1107 EmitClearNativeContents(pcsCleanup);
1110 pcsCleanup->EmitLabel(pSkipCleanupLabel);
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))
1116 if (IsRetval(m_dwMarshalFlags) || (IsOut(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags)))
1118 m_pslNDirect->SetExceptionCleanupNeeded();
1120 EmitReInitNative(pcsCleanup);
1121 if (IsHresultSwap(m_dwMarshalFlags) || IsOut(m_dwMarshalFlags))
1123 m_nativeHome.EmitCopyToByrefArgWithNullCheck(pcsCleanup, &nativeType, m_argidx);
1129 virtual void EmitMarshalArgumentNativeToCLR()
1134 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
1138 EmitSetupSigAndDefaultHomesNativeToCLR();
1139 EmitMarshalArgumentContentsNativeToCLR();
1142 void EmitMarshalArgumentContentsNativeToCLR()
1147 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
1154 if (IsIn(m_dwMarshalFlags))
1156 EmitConvertSpaceAndContentsNativeToCLR(m_pcsMarshal);
1160 EmitConvertSpaceNativeToCLR(m_pcsMarshal);
1166 if (IsOut(m_dwMarshalFlags))
1168 if (IsIn(m_dwMarshalFlags))
1170 EmitClearNativeContents(m_pcsUnmarshal);
1172 EmitConvertContentsCLRToNative(m_pcsUnmarshal);
1174 // make sure we free the argument if an exception is thrown
1175 EmitExceptionCleanupNativeToCLR();
1177 EmitCleanupNativeToCLR();
1180 void EmitSetupSigAndDefaultHomesNativeToCLRByref(bool fBlittable = false)
1185 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1189 LocalDesc nativeType = GetNativeType();
1190 LocalDesc managedType = GetManagedType();
1191 LocalDesc nativeArgType = nativeType;
1192 nativeArgType.MakeByRef();
1193 m_pcsMarshal->SetStubTargetArgType(&nativeArgType);
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]);
1201 managedType.MakeByRef();
1203 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILByrefLocal, m_pcsMarshal->NewLocal(managedType));
1204 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILByrefArgument, m_argidx);
1208 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(managedType));
1209 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(nativeType));
1213 virtual void EmitMarshalArgumentNativeToCLRByref()
1218 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1222 EmitSetupSigAndDefaultHomesNativeToCLRByref();
1223 EmitMarshalArgumentContentsNativeToCLRByref(false);
1226 void EmitMarshalArgumentContentsNativeToCLRByref(bool nativeHomeAlreadyInitialized)
1231 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1235 LocalDesc nativeType = GetNativeType();
1240 if (IsIn(m_dwMarshalFlags))
1242 if (!nativeHomeAlreadyInitialized)
1244 m_nativeHome.EmitCopyFromByrefArg(m_pcsMarshal, &nativeType, m_argidx);
1247 EmitConvertSpaceAndContentsNativeToCLR(m_pcsMarshal);
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();
1262 if (IsOut(m_dwMarshalFlags))
1264 if (IsIn(m_dwMarshalFlags))
1266 EmitClearNative(m_pcsUnmarshal);
1267 EmitReInitNative(m_pcsUnmarshal);
1270 EmitConvertSpaceAndContentsCLRToNative(m_pcsUnmarshal);
1272 if (!nativeHomeAlreadyInitialized)
1274 m_nativeHome.EmitCopyToByrefArg(m_pcsUnmarshal, &nativeType, m_argidx);
1277 // make sure we free and zero the by-ref argument if an exception is thrown
1278 EmitExceptionCleanupNativeToCLR();
1281 EmitCleanupNativeToCLR();
1284 virtual LocalDesc GetNativeType() = 0;
1285 virtual LocalDesc GetManagedType() = 0;
1290 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
1292 LIMITED_METHOD_CONTRACT;
1295 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1297 LIMITED_METHOD_CONTRACT;
1300 virtual void EmitConvertSpaceAndContentsNativeToCLR(ILCodeStream* pslILEmit)
1302 WRAPPER_NO_CONTRACT;
1303 EmitConvertSpaceNativeToCLR(pslILEmit);
1304 EmitConvertContentsNativeToCLR(pslILEmit);
1311 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
1313 LIMITED_METHOD_CONTRACT;
1316 virtual void EmitConvertSpaceCLRToNativeTemp(ILCodeStream* pslILEmit)
1318 LIMITED_METHOD_CONTRACT;
1319 EmitConvertSpaceCLRToNative(pslILEmit);
1322 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1324 LIMITED_METHOD_CONTRACT;
1327 virtual void EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslILEmit)
1329 STANDARD_VM_CONTRACT;
1330 EmitConvertSpaceCLRToNative(pslILEmit);
1331 EmitConvertContentsCLRToNative(pslILEmit);
1334 virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
1336 WRAPPER_NO_CONTRACT;
1337 EmitConvertSpaceAndContentsCLRToNative(pslILEmit);
1343 virtual void EmitClearCLRContents(ILCodeStream* pslILEmit)
1345 LIMITED_METHOD_CONTRACT;
1348 virtual bool NeedsClearNative()
1350 LIMITED_METHOD_CONTRACT;
1354 virtual void EmitClearNative(ILCodeStream* pslILEmit)
1356 LIMITED_METHOD_CONTRACT;
1359 virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit)
1361 LIMITED_METHOD_CONTRACT;
1362 EmitClearNative(pslILEmit);
1365 virtual void EmitClearNativeContents(ILCodeStream* pslILEmit)
1367 LIMITED_METHOD_CONTRACT;
1370 virtual bool NeedsClearCLR()
1372 LIMITED_METHOD_CONTRACT;
1376 virtual void EmitClearCLR(ILCodeStream* pslILEmit)
1378 LIMITED_METHOD_CONTRACT;
1381 virtual void EmitReInitNative(ILCodeStream* pslILEmit)
1383 STANDARD_VM_CONTRACT;
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
1389 _ASSERTE(!GetNativeType().IsValueClass());
1391 pslILEmit->EmitLDC(0);
1392 pslILEmit->EmitCONV_T(static_cast<CorElementType>(GetNativeType().ElementType[0]));
1394 EmitStoreNativeValue(pslILEmit);
1397 virtual bool IsManagedPassedByRef()
1399 LIMITED_METHOD_CONTRACT;
1400 return IsByref(m_dwMarshalFlags);
1403 virtual bool IsNativePassedByRef()
1405 LIMITED_METHOD_CONTRACT;
1406 return IsByref(m_dwMarshalFlags);
1409 void EmitInterfaceClearNative(ILCodeStream* pslILEmit);
1412 static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
1416 BOOL fManagedToNative,
1417 OverrideProcArgs* pargs,
1420 UINT nativeStackOffset)
1422 LIMITED_METHOD_CONTRACT;
1423 return HANDLEASNORMAL;
1426 static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker* psl,
1427 BOOL fManagedToNative,
1429 OverrideProcArgs* pargs,
1432 LIMITED_METHOD_CONTRACT;
1433 return HANDLEASNORMAL;
1438 class ILCopyMarshalerBase : public ILMarshaler
1440 virtual LocalDesc GetManagedType()
1442 WRAPPER_NO_CONTRACT;
1443 return GetNativeType();
1446 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1448 STANDARD_VM_CONTRACT;
1450 EmitLoadManagedValue(pslILEmit);
1451 EmitStoreNativeValue(pslILEmit);
1454 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1456 STANDARD_VM_CONTRACT;
1458 EmitLoadNativeValue(pslILEmit);
1459 EmitStoreManagedValue(pslILEmit);
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.
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.
1472 // This method was changed to pin instead of copy in Dev10 in order
1473 // to match the original ML behavior.
1475 virtual void EmitMarshalArgumentCLRToNativeByref()
1480 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1484 EmitSetupSigAndDefaultHomesCLRToNativeByref(true);
1489 EmitLoadManagedHomeAddr(m_pcsMarshal);
1490 EmitStoreNativeHomeAddr(m_pcsMarshal);
1493 // no unmarshaling is necessary since we directly passed the pinned byref to native,
1494 // the argument is therefore automatically in/out
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).
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.
1509 virtual void EmitMarshalArgumentNativeToCLRByref()
1514 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1518 EmitSetupSigAndDefaultHomesNativeToCLRByref(true);
1523 EmitLoadNativeHomeAddr(m_pcsMarshal);
1524 EmitStoreManagedHomeAddr(m_pcsMarshal);
1527 // no unmarshaling is necessary since we directly passed the pointer to managed
1528 // as a byref, the argument is therefore automatically in/out
1533 template <CorElementType ELEMENT_TYPE, class PROMOTED_ELEMENT>
1534 class ILCopyMarshalerSimple : public ILCopyMarshalerBase
1540 c_nativeSize = sizeof(PROMOTED_ELEMENT),
1541 c_CLRSize = sizeof(PROMOTED_ELEMENT),
1544 bool IsSmallValueTypeSpecialCase()
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.
1552 return (ELEMENT_TYPE ==
1558 ) && (NULL != m_pargs->m_pMT);
1561 bool NeedToPromoteTo8Bytes()
1563 WRAPPER_NO_CONTRACT;
1565 #if defined(_TARGET_AMD64_)
1566 // If the argument is passed by value,
1567 if (!IsByref(m_dwMarshalFlags) && !IsRetval(m_dwMarshalFlags))
1569 // and it is an I4 or an U4,
1570 if ( (ELEMENT_TYPE == ELEMENT_TYPE_I4) ||
1571 (ELEMENT_TYPE == ELEMENT_TYPE_U4) )
1573 // and we are doing a managed-to-unmanaged call,
1574 if (IsCLRToNative(m_dwMarshalFlags))
1576 // then we have to promote the native argument type to an I8 or an U8.
1581 #endif // _TARGET_AMD64_
1586 CorElementType GetConversionType(CorElementType type)
1588 LIMITED_METHOD_CONTRACT;
1590 // I4 <-> I8; U4 <-> U8
1591 if (type == ELEMENT_TYPE_I4)
1593 return ELEMENT_TYPE_I8;
1595 else if (type == ELEMENT_TYPE_U4)
1597 return ELEMENT_TYPE_U8;
1601 return ELEMENT_TYPE_END;
1605 void EmitTypePromotion(ILCodeStream* pslILEmit)
1607 WRAPPER_NO_CONTRACT;
1609 CorElementType promotedType = GetConversionType(ELEMENT_TYPE);
1610 if (promotedType == ELEMENT_TYPE_I8)
1612 pslILEmit->EmitCONV_I8();
1614 else if (promotedType == ELEMENT_TYPE_U8)
1616 pslILEmit->EmitCONV_U8();
1620 virtual LocalDesc GetNativeType()
1622 WRAPPER_NO_CONTRACT;
1624 if (NeedToPromoteTo8Bytes())
1626 return LocalDesc(GetConversionType(ELEMENT_TYPE));
1630 return GetManagedType();
1634 virtual LocalDesc GetManagedType()
1636 WRAPPER_NO_CONTRACT;
1638 if (IsSmallValueTypeSpecialCase())
1640 return LocalDesc(m_pargs->m_pMT);
1644 return LocalDesc(ELEMENT_TYPE);
1648 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1650 STANDARD_VM_CONTRACT;
1652 EmitLoadManagedValue(pslILEmit);
1653 if (NeedToPromoteTo8Bytes())
1655 EmitTypePromotion(pslILEmit);
1657 EmitStoreNativeValue(pslILEmit);
1660 virtual void EmitReInitNative(ILCodeStream* pslILEmit)
1662 STANDARD_VM_CONTRACT;
1664 if (IsSmallValueTypeSpecialCase())
1666 EmitLoadNativeHomeAddr(pslILEmit);
1667 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(m_pargs->m_pMT));
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);
1675 EmitStoreNativeValue(pslILEmit);
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;
1690 template <BinderClassID CLASS__ID, class PROMOTED_ELEMENT>
1691 class ILCopyMarshalerKnownStruct : public ILCopyMarshalerBase
1697 c_nativeSize = sizeof(PROMOTED_ELEMENT),
1698 c_CLRSize = sizeof(PROMOTED_ELEMENT),
1701 virtual void EmitReInitNative(ILCodeStream* pslILEmit)
1703 STANDARD_VM_CONTRACT;
1705 EmitLoadNativeHomeAddr(pslILEmit);
1706 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__ID)));
1709 virtual LocalDesc GetNativeType()
1711 STANDARD_VM_CONTRACT;
1713 return LocalDesc(MscorlibBinder::GetClass(CLASS__ID));
1717 typedef ILCopyMarshalerKnownStruct<CLASS__DECIMAL, DECIMAL> ILDecimalMarshaler;
1718 typedef ILCopyMarshalerKnownStruct<CLASS__GUID, GUID> ILGuidMarshaler;
1720 class ILBlittableValueClassMarshaler : public ILCopyMarshalerBase
1726 c_nativeSize = VARIABLESIZE,
1727 c_CLRSize = VARIABLESIZE,
1730 virtual void EmitReInitNative(ILCodeStream* pslILEmit)
1732 STANDARD_VM_CONTRACT;
1734 EmitLoadNativeHomeAddr(pslILEmit);
1735 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(m_pargs->m_pMT));
1738 virtual LocalDesc GetNativeType()
1740 LIMITED_METHOD_CONTRACT;
1742 return LocalDesc(m_pargs->m_pMT);
1747 class ILDelegateMarshaler : public ILMarshaler
1753 c_nativeSize = sizeof(void *),
1754 c_CLRSize = sizeof(OBJECTREF),
1758 virtual LocalDesc GetNativeType();
1759 virtual LocalDesc GetManagedType();
1760 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
1761 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
1764 class ILReflectionObjectMarshaler : public ILMarshaler
1770 c_nativeSize = sizeof(void *),
1771 c_CLRSize = sizeof(OBJECTREF),
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;
1784 class ILIRuntimeMethodInfoMarshaler : public ILReflectionObjectMarshaler
1787 virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__STUBMETHODINFO__HANDLE; }
1788 virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__STUBMETHODINFO; }
1791 class ILRuntimeModuleMarshaler : public ILReflectionObjectMarshaler
1794 virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__MODULE__DATA; }
1795 virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__MODULE; }
1798 class ILRuntimeAssemblyMarshaler : public ILReflectionObjectMarshaler
1801 virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__ASSEMBLY__HANDLE; }
1802 virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__ASSEMBLY; }
1805 class ILRuntimeTypeHandleMarshaler : public ILReflectionObjectMarshaler
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; }
1813 class ILRuntimeMethodHandleMarshaler : public ILReflectionObjectMarshaler
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; }
1821 class ILRuntimeFieldHandleMarshaler : public ILReflectionObjectMarshaler
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; }
1829 class ILBoolMarshaler : public ILMarshaler
1833 virtual CorElementType GetNativeBoolElementType() = 0;
1834 virtual int GetNativeTrueValue() = 0;
1835 virtual int GetNativeFalseValue() = 0;
1838 virtual LocalDesc GetNativeType();
1839 virtual LocalDesc GetManagedType();
1840 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
1841 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
1844 class ILWinBoolMarshaler : public ILBoolMarshaler
1850 c_nativeSize = sizeof(BOOL),
1851 c_CLRSize = sizeof(INT8),
1855 virtual CorElementType GetNativeBoolElementType()
1857 LIMITED_METHOD_CONTRACT;
1858 return ELEMENT_TYPE_I4;
1861 virtual int GetNativeTrueValue()
1863 LIMITED_METHOD_CONTRACT;
1867 virtual int GetNativeFalseValue()
1869 LIMITED_METHOD_CONTRACT;
1874 class ILCBoolMarshaler : public ILBoolMarshaler
1880 c_nativeSize = sizeof(BYTE),
1881 c_CLRSize = sizeof(INT8),
1885 virtual CorElementType GetNativeBoolElementType()
1887 LIMITED_METHOD_CONTRACT;
1888 return ELEMENT_TYPE_I1;
1891 virtual int GetNativeTrueValue()
1893 LIMITED_METHOD_CONTRACT;
1897 virtual int GetNativeFalseValue()
1899 LIMITED_METHOD_CONTRACT;
1904 #ifdef FEATURE_COMINTEROP
1905 class ILVtBoolMarshaler : public ILBoolMarshaler
1911 c_nativeSize = sizeof(VARIANT_BOOL),
1912 c_CLRSize = sizeof(INT8),
1916 virtual CorElementType GetNativeBoolElementType()
1918 LIMITED_METHOD_CONTRACT;
1919 return ELEMENT_TYPE_I2;
1922 virtual int GetNativeTrueValue()
1924 LIMITED_METHOD_CONTRACT;
1925 return VARIANT_TRUE;
1928 virtual int GetNativeFalseValue()
1930 LIMITED_METHOD_CONTRACT;
1931 return VARIANT_FALSE;
1934 #endif // FEATURE_COMINTEROP
1936 class ILWSTRMarshaler : public ILMarshaler
1942 c_nativeSize = sizeof(void *),
1943 c_CLRSize = sizeof(OBJECTREF),
1947 bool m_fCoMemoryAllocated;
1951 LIMITED_METHOD_CONTRACT;
1952 m_fCoMemoryAllocated = false;
1957 virtual LocalDesc GetNativeType();
1958 virtual LocalDesc GetManagedType();
1960 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
1961 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
1962 virtual void EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslILEmit);
1963 virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit);
1965 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
1966 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
1967 virtual void EmitConvertSpaceAndContentsNativeToCLR(ILCodeStream* pslILEmit);
1969 virtual bool NeedsClearNative();
1970 virtual void EmitClearNative(ILCodeStream* pslILEmit);
1971 virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit);
1973 static bool CanUsePinnedManagedString(DWORD dwMarshalFlags);
1974 static void EmitCheckManagedStringLength(ILCodeStream* pslILEmit);
1975 static void EmitCheckNativeStringLength(ILCodeStream* pslILEmit);
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
1983 ILOptimizedAllocMarshaler(BinderMethodID clearNat) :
1984 m_idClearNative(clearNat),
1985 m_dwLocalBuffer((DWORD)-1)
1987 LIMITED_METHOD_CONTRACT;
1990 virtual LocalDesc GetNativeType();
1991 virtual bool NeedsClearNative();
1992 virtual void EmitClearNative(ILCodeStream* pslILEmit);
1995 const BinderMethodID m_idClearNative;
1996 DWORD m_dwLocalBuffer; // localloc'ed temp buffer variable or -1 if not used
1999 class ILWSTRBufferMarshaler : public ILOptimizedAllocMarshaler
2005 c_nativeSize = sizeof(void *),
2006 c_CLRSize = sizeof(OBJECTREF),
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
2015 ILWSTRBufferMarshaler() :
2016 ILOptimizedAllocMarshaler(METHOD__WIN32NATIVE__COTASKMEMFREE)
2018 LIMITED_METHOD_CONTRACT;
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);
2028 class ILCSTRBufferMarshaler : public ILOptimizedAllocMarshaler
2034 c_nativeSize = sizeof(void *),
2035 c_CLRSize = sizeof(OBJECTREF),
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
2044 ILCSTRBufferMarshaler() :
2045 ILOptimizedAllocMarshaler(METHOD__WIN32NATIVE__COTASKMEMFREE)
2047 LIMITED_METHOD_CONTRACT;
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);
2058 class ILHandleRefMarshaler : public ILMarshaler
2060 // Managed layout for SRI.HandleRef class
2063 OBJECTREF m_wrapper;
2071 c_nativeSize = sizeof(LPVOID),
2072 c_CLRSize = sizeof(HANDLEREF),
2075 LocalDesc GetManagedType()
2077 LIMITED_METHOD_CONTRACT;
2081 LocalDesc GetNativeType()
2083 LIMITED_METHOD_CONTRACT;
2087 static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
2091 BOOL fManagedToNative,
2092 OverrideProcArgs* pargs,
2095 UINT nativeStackOffset);
2097 static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker* psl,
2098 BOOL fManagedToNative,
2100 OverrideProcArgs* pargs,
2104 class ILSafeHandleMarshaler : public ILMarshaler
2110 c_nativeSize = sizeof(LPVOID),
2111 c_CLRSize = sizeof(SAFEHANDLE),
2114 virtual LocalDesc GetManagedType();
2115 virtual LocalDesc GetNativeType();
2117 virtual bool NeedsClearNative();
2118 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2120 virtual void EmitMarshalArgumentCLRToNative();
2122 static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
2126 BOOL fManagedToNative,
2127 OverrideProcArgs* pargs,
2130 UINT nativeStackOffset);
2132 static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker *psl,
2133 BOOL fManagedToNative,
2135 OverrideProcArgs *pargs,
2140 class ILCriticalHandleMarshaler : public ILMarshaler
2146 c_nativeSize = sizeof(LPVOID),
2147 c_CLRSize = sizeof(CRITICALHANDLE),
2152 LocalDesc GetManagedType()
2154 LIMITED_METHOD_CONTRACT;
2158 LocalDesc GetNativeType()
2160 LIMITED_METHOD_CONTRACT;
2164 static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
2168 BOOL fManagedToNative,
2169 OverrideProcArgs* pargs,
2172 UINT nativeStackOffset);
2174 static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker *psl,
2175 BOOL fManagedToNative,
2177 OverrideProcArgs *pargs,
2182 class ILValueClassMarshaler : public ILMarshaler
2188 c_nativeSize = VARIABLESIZE,
2189 c_CLRSize = VARIABLESIZE,
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);
2202 #ifdef FEATURE_COMINTEROP
2203 class ILObjectMarshaler : public ILMarshaler
2209 c_CLRSize = sizeof(OBJECTREF),
2210 c_nativeSize = sizeof(VARIANT),
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);
2222 #endif // FEATURE_COMINTEROP
2224 class ILDateMarshaler : public ILMarshaler
2230 c_nativeSize = sizeof(DATE),
2231 c_CLRSize = sizeof(INT64),
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);
2243 class ILCurrencyMarshaler : public ILMarshaler
2249 c_nativeSize = sizeof(CURRENCY),
2250 c_CLRSize = sizeof(DECIMAL),
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);
2262 #ifdef FEATURE_COMINTEROP
2263 class ILInterfaceMarshaler : public ILMarshaler
2269 c_nativeSize = sizeof(void *),
2270 c_CLRSize = sizeof(OBJECTREF),
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);
2281 #endif // FEATURE_COMINTEROP
2284 class ILAnsiCharMarshaler : public ILMarshaler
2290 c_nativeSize = sizeof(UINT8),
2291 c_CLRSize = sizeof(UINT16),
2295 virtual LocalDesc GetNativeType();
2296 virtual LocalDesc GetManagedType();
2297 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2298 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2302 template <BinderClassID CLASS__ID, class ELEMENT>
2303 class ILValueClassPtrMarshaler : public ILMarshaler
2309 c_nativeSize = sizeof(ELEMENT *),
2310 c_CLRSize = sizeof(ELEMENT),
2314 virtual LocalDesc GetNativeType()
2316 LIMITED_METHOD_CONTRACT;
2319 // pointer to value class
2321 return LocalDesc(ELEMENT_TYPE_I);
2324 virtual LocalDesc GetManagedType()
2326 STANDARD_VM_CONTRACT;
2331 return LocalDesc(MscorlibBinder::GetClass(CLASS__ID));
2334 virtual bool NeedsClearNative()
2336 LIMITED_METHOD_CONTRACT;
2337 return (IsByref(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags));
2340 virtual void EmitClearNative(ILCodeStream* pslILEmit)
2342 STANDARD_VM_CONTRACT;
2344 EmitLoadNativeValue(pslILEmit);
2345 // static void CoTaskMemFree(IntPtr ptr)
2346 pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
2349 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
2351 STANDARD_VM_CONTRACT;
2353 if (NeedsClearNative())
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);
2363 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2365 STANDARD_VM_CONTRACT;
2367 if (NeedsClearNative())
2369 EmitLoadNativeValue(pslILEmit); // dest
2370 EmitLoadManagedHomeAddr(pslILEmit); // src
2371 pslILEmit->EmitCPOBJ(pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__ID)));
2375 EmitLoadManagedHomeAddr(pslILEmit);
2376 EmitStoreNativeValue(pslILEmit);
2380 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2382 STANDARD_VM_CONTRACT;
2384 int tokType = pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__ID));
2385 ILCodeLabel *pNullLabel = pslILEmit->NewCodeLabel();
2386 ILCodeLabel *pJoinLabel = pslILEmit->NewCodeLabel();
2388 EmitLoadNativeValue(pslILEmit);
2389 pslILEmit->EmitBRFALSE(pNullLabel);
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);
2396 pslILEmit->EmitBR(pJoinLabel);
2398 // the incoming pointer is null -> just initobj (i.e. zero) the struct
2399 pslILEmit->EmitLabel(pNullLabel);
2401 EmitLoadManagedHomeAddr(pslILEmit);
2402 pslILEmit->EmitINITOBJ(tokType);
2404 pslILEmit->EmitLabel(pJoinLabel);
2408 typedef ILValueClassPtrMarshaler<CLASS__GUID, GUID> ILGuidPtrMarshaler;
2409 typedef ILValueClassPtrMarshaler<CLASS__DECIMAL, DECIMAL> ILDecimalPtrMarshaler;
2411 #ifdef FEATURE_COMINTEROP
2412 class ILOleColorMarshaler : public ILMarshaler
2418 c_nativeSize = sizeof(OLE_COLOR),
2419 c_CLRSize = sizeof(SYSTEMCOLOR),
2423 virtual LocalDesc GetNativeType();
2424 virtual LocalDesc GetManagedType();
2425 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2426 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2429 class ILVBByValStrWMarshaler : public ILMarshaler
2435 c_nativeSize = sizeof(BSTR),
2436 c_CLRSize = sizeof(OBJECTREF*),
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)
2446 ILVBByValStrWMarshaler() :
2448 ,m_dwLocalBuffer(-1)
2450 LIMITED_METHOD_CONTRACT;
2453 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2454 virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
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();
2466 DWORD m_dwLocalBuffer;
2469 class ILVBByValStrMarshaler : public ILMarshaler
2475 c_nativeSize = sizeof(LPSTR),
2476 c_CLRSize = sizeof(OBJECTREF *),
2479 ILVBByValStrMarshaler() :
2482 LIMITED_METHOD_CONTRACT;
2485 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2486 virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
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();
2500 class ILHSTRINGMarshaler : public ILMarshaler
2506 c_nativeSize = sizeof(HSTRING),
2507 c_CLRSize = sizeof(OBJECTREF),
2511 virtual LocalDesc GetNativeType();
2512 virtual LocalDesc GetManagedType();
2514 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2515 void EmitConvertCLRToHSTRINGReference(ILCodeStream* pslILEmit);
2516 void EmitConvertCLRToHSTRING(ILCodeStream* pslILEmit);
2518 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2520 virtual bool NeedsClearNative();
2521 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2523 #endif // FEATURE_COMINTEROP
2525 class ILCSTRMarshaler : public ILOptimizedAllocMarshaler
2531 c_nativeSize = sizeof(void *),
2532 c_CLRSize = sizeof(OBJECTREF),
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
2542 ILOptimizedAllocMarshaler(METHOD__CSTRMARSHALER__CLEAR_NATIVE)
2544 LIMITED_METHOD_CONTRACT;
2548 virtual LocalDesc GetManagedType();
2549 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2550 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2553 #ifdef FEATURE_COMINTEROP
2554 class ILBSTRMarshaler : public ILOptimizedAllocMarshaler
2560 c_nativeSize = sizeof(void *),
2561 c_CLRSize = sizeof(OBJECTREF),
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
2571 ILOptimizedAllocMarshaler(METHOD__BSTRMARSHALER__CLEAR_NATIVE)
2573 LIMITED_METHOD_CONTRACT;
2577 virtual LocalDesc GetManagedType();
2578 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2579 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2583 class ILAnsiBSTRMarshaler : public ILMarshaler
2589 c_nativeSize = sizeof(void *),
2590 c_CLRSize = sizeof(OBJECTREF),
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);
2601 #endif // FEATURE_COMINTEROP
2603 class ILLayoutClassPtrMarshalerBase : public ILMarshaler
2608 c_nativeSize = sizeof(void *),
2609 c_CLRSize = sizeof(OBJECTREF),
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);
2624 class ILLayoutClassPtrMarshaler : public ILLayoutClassPtrMarshalerBase
2633 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2634 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2635 virtual void EmitClearNativeContents(ILCodeStream * pslILEmit);
2638 class ILBlittablePtrMarshaler : public ILLayoutClassPtrMarshalerBase
2647 virtual void EmitMarshalArgumentCLRToNative();
2648 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2649 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2653 #ifndef FEATURE_CORECLR
2654 class ILBlittableValueClassWithCopyCtorMarshaler : public ILMarshaler
2660 c_nativeSize = VARIABLESIZE,
2661 c_CLRSize = sizeof(OBJECTREF),
2664 LocalDesc GetManagedType()
2666 LIMITED_METHOD_CONTRACT;
2670 LocalDesc GetNativeType()
2672 LIMITED_METHOD_CONTRACT;
2676 static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
2680 BOOL fManagedToNative,
2681 OverrideProcArgs* pargs,
2684 UINT nativeStackOffset);
2688 #endif // !FEATURE_CORECLR
2691 class ILArgIteratorMarshaler : public ILMarshaler
2697 c_nativeSize = sizeof(va_list),
2698 c_CLRSize = sizeof(VARARGS),
2702 virtual LocalDesc GetNativeType();
2703 virtual LocalDesc GetManagedType();
2704 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2705 virtual void EmitMarshalArgumentCLRToNative();
2706 virtual void EmitMarshalArgumentNativeToCLR();
2709 class ILArrayWithOffsetMarshaler : public ILMarshaler
2715 c_nativeSize = sizeof(LPVOID),
2716 c_CLRSize = sizeof(ArrayWithOffsetData),
2719 ILArrayWithOffsetMarshaler() :
2720 m_dwCountLocalNum(-1),
2721 m_dwOffsetLocalNum(-1),
2722 m_dwPinnedLocalNum(-1)
2724 LIMITED_METHOD_CONTRACT;
2728 virtual LocalDesc GetNativeType();
2729 virtual LocalDesc GetManagedType();
2730 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2732 virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit);
2733 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2734 virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit);
2737 DWORD m_dwCountLocalNum;
2738 DWORD m_dwOffsetLocalNum;
2739 DWORD m_dwPinnedLocalNum;
2742 class ILAsAnyMarshalerBase : public ILMarshaler
2747 c_nativeSize = sizeof(void *),
2748 c_CLRSize = sizeof(OBJECTREF),
2751 ILAsAnyMarshalerBase() :
2752 m_dwMarshalerLocalNum(-1)
2754 LIMITED_METHOD_CONTRACT;
2758 static const BYTE ML_IN = 0x10;
2759 static const BYTE ML_OUT = 0x20;
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);
2770 DWORD m_dwMarshalerLocalNum;
2773 class ILAsAnyWMarshaler : public ILAsAnyMarshalerBase
2782 virtual bool IsAnsi()
2788 class ILAsAnyAMarshaler : public ILAsAnyMarshalerBase
2797 virtual bool IsAnsi()
2804 class ILMngdMarshaler : public ILMarshaler
2809 c_nativeSize = sizeof(void *),
2810 c_CLRSize = sizeof(OBJECTREF),
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)
2828 LIMITED_METHOD_CONTRACT;
2832 virtual LocalDesc GetNativeType();
2833 virtual LocalDesc GetManagedType();
2835 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) = 0;
2837 virtual void EmitCallMngdMarshalerMethod(ILCodeStream* pslILEmit, MethodDesc *pMD);
2839 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
2841 WRAPPER_NO_CONTRACT;
2842 EmitCallMngdMarshalerMethod(pslILEmit, GetConvertSpaceToManagedMethod());
2845 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2847 WRAPPER_NO_CONTRACT;
2848 EmitCallMngdMarshalerMethod(pslILEmit, GetConvertContentsToManagedMethod());
2851 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
2853 WRAPPER_NO_CONTRACT;
2854 EmitCallMngdMarshalerMethod(pslILEmit, GetConvertSpaceToNativeMethod());
2857 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2859 WRAPPER_NO_CONTRACT;
2860 EmitCallMngdMarshalerMethod(pslILEmit, GetConvertContentsToNativeMethod());
2863 virtual bool NeedsClearNative()
2865 LIMITED_METHOD_CONTRACT;
2867 if (NULL != GetClearNativeMethod())
2875 virtual void EmitClearNative(ILCodeStream* pslILEmit)
2877 WRAPPER_NO_CONTRACT;
2878 EmitCallMngdMarshalerMethod(pslILEmit, GetClearNativeMethod());
2881 virtual void EmitClearNativeContents(ILCodeStream* pslILEmit)
2883 WRAPPER_NO_CONTRACT;
2884 EmitCallMngdMarshalerMethod(pslILEmit, GetClearNativeContentsMethod());
2888 virtual bool NeedsClearCLR()
2890 LIMITED_METHOD_CONTRACT;
2892 if (NULL != GetClearManagedMethod())
2900 virtual void EmitClearCLR(ILCodeStream* pslILEmit)
2902 WRAPPER_NO_CONTRACT;
2903 EmitCallMngdMarshalerMethod(pslILEmit, GetClearManagedMethod());
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)); }
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;
2923 class ILNativeArrayMarshaler : public ILMngdMarshaler
2931 ILNativeArrayMarshaler() :
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,
2942 LIMITED_METHOD_CONTRACT;
2943 m_dwSavedSizeArg = LOCAL_NUM_UNUSED;
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();
2956 bool UsePinnedArraySpecialCase();
2958 BOOL CheckSizeParamIndexArg(const CREATE_MARSHALER_CARRAY_OPERANDS &mops, CorElementType *pElementType);
2960 // Calculate element count and load it on evaluation stack
2961 void EmitLoadElementCount(ILCodeStream* pslILEmit);
2963 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
2965 void EmitLoadNativeSize(ILCodeStream* pslILEmit);
2966 void EmitNewSavedSizeArgLocal();
2969 DWORD m_dwSavedSizeArg;
2972 class MngdNativeArrayMarshaler
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);
2983 static void DoClearNativeContents(MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
2987 FLAG_NATIVE_DATA_VALID = 0x40000000
2990 MethodTable* m_pElementMT;
2992 BOOL m_NativeDataValid;
2994 BOOL m_ThrowOnUnmappableChar;
2999 #ifdef FEATURE_COMINTEROP
3000 class ILSafeArrayMarshaler : public ILMngdMarshaler
3008 ILSafeArrayMarshaler() :
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,
3018 m_dwOriginalManagedLocalNum(-1)
3020 LIMITED_METHOD_CONTRACT;
3025 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
3026 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3027 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3029 virtual void EmitReInitNative(ILCodeStream* pslILEmit)
3038 if (NeedsCheckForStatic() && pslILEmit->GetStreamType() != ILStubLinker::kExceptionCleanup)
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.
3047 ILMngdMarshaler::EmitReInitNative(pslILEmit);
3051 bool NeedsCheckForStatic()
3053 WRAPPER_NO_CONTRACT;
3054 return IsByref(m_dwMarshalFlags) && !IsCLRToNative(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags);
3057 DWORD m_dwOriginalManagedLocalNum;
3060 class MngdSafeArrayMarshaler
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);
3070 enum StaticCheckStateFlags
3072 SCSF_CheckForStatic = 1,
3074 SCSF_NativeDataValid = 4
3077 MethodTable* m_pElementMT;
3080 BYTE m_fStatic; // StaticCheckStateFlags
3081 BYTE m_nolowerbounds;
3084 class ILHiddenLengthArrayMarshaler : public ILMngdMarshaler
3086 friend class MngdHiddenLengthArrayMarshaler;
3091 c_nativeSize = sizeof(LPVOID),
3092 c_CLRSize = sizeof(OBJECTREF),
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,
3105 LIMITED_METHOD_CONTRACT;
3106 m_dwMngdMarshalerLocalNum = -1;
3110 virtual LocalDesc GetNativeType();
3111 virtual LocalDesc GetManagedType();
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);
3123 bool CanUsePinnedArray();
3124 void EmitLoadNativeArrayLength(ILCodeStream *pslILEmit);
3126 virtual MethodDesc *GetConvertContentsToManagedMethod();
3127 virtual MethodDesc *GetConvertContentsToNativeMethod();
3128 virtual MethodDesc *GetClearNativeContentsMethod();
3130 MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD);
3133 class MngdHiddenLengthArrayMarshaler
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);
3145 SIZE_T GetArraySize(SIZE_T elements);
3146 void DoClearNativeContents(void** pNativeHome, INT32 cElements);
3149 MethodTable *m_pElementMT;
3150 SIZE_T m_cbElementSize;
3153 #endif // FEATURE_COMINTEROP
3156 class ILReferenceCustomMarshaler : public ILMngdMarshaler
3164 ILReferenceCustomMarshaler() :
3167 METHOD__MNGD_REF_CUSTOM_MARSHALER__CONVERT_CONTENTS_TO_MANAGED,
3169 METHOD__MNGD_REF_CUSTOM_MARSHALER__CONVERT_CONTENTS_TO_NATIVE,
3170 METHOD__MNGD_REF_CUSTOM_MARSHALER__CLEAR_NATIVE,
3172 METHOD__MNGD_REF_CUSTOM_MARSHALER__CLEAR_MANAGED
3175 LIMITED_METHOD_CONTRACT;
3179 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
3182 class MngdRefCustomMarshaler
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);
3191 static void DoClearNativeContents(MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3193 CustomMarshalerHelper* m_pCMHelper;
3197 #ifdef FEATURE_COMINTEROP
3198 class ILUriMarshaler : public ILMarshaler
3204 c_nativeSize = sizeof(LPVOID),
3205 c_CLRSize = sizeof(OBJECTREF),
3208 static void EmitConvertCLRUriToWinRTUri(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3209 static void EmitConvertWinRTUriToCLRUri(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3212 virtual LocalDesc GetNativeType();
3213 virtual LocalDesc GetManagedType();
3215 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3216 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3218 virtual bool NeedsClearNative();
3219 void EmitClearNative(ILCodeStream* pslILEmit);
3222 class ILNCCEventArgsMarshaler : public ILMarshaler
3228 c_nativeSize = sizeof(LPVOID),
3229 c_CLRSize = sizeof(OBJECTREF),
3232 static void EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3233 static void EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3236 virtual LocalDesc GetNativeType();
3237 virtual LocalDesc GetManagedType();
3239 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3240 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3242 virtual bool NeedsClearNative();
3243 void EmitClearNative(ILCodeStream* pslILEmit);
3246 class ILPCEventArgsMarshaler : public ILMarshaler
3252 c_nativeSize = sizeof(LPVOID),
3253 c_CLRSize = sizeof(OBJECTREF),
3256 static void EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3257 static void EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3260 virtual LocalDesc GetNativeType();
3261 virtual LocalDesc GetManagedType();
3263 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3264 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3266 virtual bool NeedsClearNative();
3267 void EmitClearNative(ILCodeStream* pslILEmit);
3270 class ILDateTimeMarshaler : public ILMarshaler
3276 c_nativeSize = sizeof(INT64), // = sizeof(Windows::Foundation::DateTime)
3277 c_CLRSize = VARIABLESIZE,
3281 virtual LocalDesc GetNativeType();
3282 virtual LocalDesc GetManagedType();
3284 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3285 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3287 virtual bool NeedsClearNative();
3288 virtual void EmitReInitNative(ILCodeStream* pslILEmit);
3291 class ILNullableMarshaler : public ILMarshaler
3297 c_nativeSize = sizeof(LPVOID),
3298 c_CLRSize = VARIABLESIZE,
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);
3310 MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD);
3313 class ILSystemTypeMarshaler : public ILMarshaler
3319 c_nativeSize = sizeof(TypeNameNative),
3320 c_CLRSize = sizeof(OBJECTREF)
3324 virtual LocalDesc GetNativeType();
3325 virtual LocalDesc GetManagedType();
3327 virtual void EmitConvertContentsCLRToNative(ILCodeStream * pslILEmit);
3328 virtual void EmitConvertContentsNativeToCLR(ILCodeStream * pslILEmit);
3330 virtual bool NeedsClearNative();
3331 virtual void EmitClearNative(ILCodeStream * pslILEmit);
3332 virtual void EmitReInitNative(ILCodeStream * pslILEmit);
3335 class ILHResultExceptionMarshaler : public ILMarshaler
3341 c_nativeSize = sizeof(INT32), // = sizeof(Windows::Foundation::HResult)
3342 c_CLRSize = sizeof(OBJECTREF),
3346 virtual LocalDesc GetNativeType();
3347 virtual LocalDesc GetManagedType();
3349 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3350 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3352 virtual bool NeedsClearNative();
3355 class ILKeyValuePairMarshaler : public ILMarshaler
3361 c_nativeSize = sizeof(LPVOID),
3362 c_CLRSize = VARIABLESIZE,
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);
3374 MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD);
3377 #endif // FEATURE_COMINTEROP