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 ILUTF8BufferMarshaler : 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
2015 ILUTF8BufferMarshaler() :
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 ILWSTRBufferMarshaler : 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) * 2
2044 ILWSTRBufferMarshaler() :
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);
2057 class ILCSTRBufferMarshaler : public ILOptimizedAllocMarshaler
2063 c_nativeSize = sizeof(void *),
2064 c_CLRSize = sizeof(OBJECTREF),
2069 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2070 MAX_LOCAL_BUFFER_LENGTH = MAX_PATH_FNAME + 1
2073 ILCSTRBufferMarshaler() :
2074 ILOptimizedAllocMarshaler(METHOD__WIN32NATIVE__COTASKMEMFREE)
2076 LIMITED_METHOD_CONTRACT;
2079 virtual LocalDesc GetManagedType();
2080 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
2081 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2082 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
2083 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2087 class ILHandleRefMarshaler : public ILMarshaler
2089 // Managed layout for SRI.HandleRef class
2092 OBJECTREF m_wrapper;
2100 c_nativeSize = sizeof(LPVOID),
2101 c_CLRSize = sizeof(HANDLEREF),
2104 LocalDesc GetManagedType()
2106 LIMITED_METHOD_CONTRACT;
2110 LocalDesc GetNativeType()
2112 LIMITED_METHOD_CONTRACT;
2116 static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
2120 BOOL fManagedToNative,
2121 OverrideProcArgs* pargs,
2124 UINT nativeStackOffset);
2126 static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker* psl,
2127 BOOL fManagedToNative,
2129 OverrideProcArgs* pargs,
2133 class ILSafeHandleMarshaler : public ILMarshaler
2139 c_nativeSize = sizeof(LPVOID),
2140 c_CLRSize = sizeof(SAFEHANDLE),
2143 virtual LocalDesc GetManagedType();
2144 virtual LocalDesc GetNativeType();
2146 virtual bool NeedsClearNative();
2147 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2149 virtual void EmitMarshalArgumentCLRToNative();
2151 static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
2155 BOOL fManagedToNative,
2156 OverrideProcArgs* pargs,
2159 UINT nativeStackOffset);
2161 static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker *psl,
2162 BOOL fManagedToNative,
2164 OverrideProcArgs *pargs,
2169 class ILCriticalHandleMarshaler : public ILMarshaler
2175 c_nativeSize = sizeof(LPVOID),
2176 c_CLRSize = sizeof(CRITICALHANDLE),
2181 LocalDesc GetManagedType()
2183 LIMITED_METHOD_CONTRACT;
2187 LocalDesc GetNativeType()
2189 LIMITED_METHOD_CONTRACT;
2193 static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
2197 BOOL fManagedToNative,
2198 OverrideProcArgs* pargs,
2201 UINT nativeStackOffset);
2203 static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker *psl,
2204 BOOL fManagedToNative,
2206 OverrideProcArgs *pargs,
2211 class ILValueClassMarshaler : public ILMarshaler
2217 c_nativeSize = VARIABLESIZE,
2218 c_CLRSize = VARIABLESIZE,
2222 virtual LocalDesc GetNativeType();
2223 virtual LocalDesc GetManagedType();
2224 virtual void EmitReInitNative(ILCodeStream* pslILEmit);
2225 virtual bool NeedsClearNative();
2226 virtual void EmitClearNative(ILCodeStream * pslILEmit);
2227 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2228 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2231 #ifdef FEATURE_COMINTEROP
2232 class ILObjectMarshaler : public ILMarshaler
2238 c_CLRSize = sizeof(OBJECTREF),
2239 c_nativeSize = sizeof(VARIANT),
2243 virtual LocalDesc GetNativeType();
2244 virtual LocalDesc GetManagedType();
2245 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2246 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2247 virtual bool NeedsClearNative();
2248 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2249 virtual void EmitReInitNative(ILCodeStream* pslILEmit);
2251 #endif // FEATURE_COMINTEROP
2253 class ILDateMarshaler : public ILMarshaler
2259 c_nativeSize = sizeof(DATE),
2260 c_CLRSize = sizeof(INT64),
2264 virtual LocalDesc GetNativeType();
2265 virtual LocalDesc GetManagedType();
2266 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2267 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2268 virtual void EmitReInitNative(ILCodeStream* pslILEmit);
2272 class ILCurrencyMarshaler : public ILMarshaler
2278 c_nativeSize = sizeof(CURRENCY),
2279 c_CLRSize = sizeof(DECIMAL),
2283 virtual LocalDesc GetNativeType();
2284 virtual LocalDesc GetManagedType();
2285 virtual void EmitReInitNative(ILCodeStream* pslILEmit);
2286 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2287 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2291 #ifdef FEATURE_COMINTEROP
2292 class ILInterfaceMarshaler : public ILMarshaler
2298 c_nativeSize = sizeof(void *),
2299 c_CLRSize = sizeof(OBJECTREF),
2303 virtual LocalDesc GetNativeType();
2304 virtual LocalDesc GetManagedType();
2305 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2306 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2307 virtual bool NeedsClearNative();
2308 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2310 #endif // FEATURE_COMINTEROP
2313 class ILAnsiCharMarshaler : public ILMarshaler
2319 c_nativeSize = sizeof(UINT8),
2320 c_CLRSize = sizeof(UINT16),
2324 virtual LocalDesc GetNativeType();
2325 virtual LocalDesc GetManagedType();
2326 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2327 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2331 template <BinderClassID CLASS__ID, class ELEMENT>
2332 class ILValueClassPtrMarshaler : public ILMarshaler
2338 c_nativeSize = sizeof(ELEMENT *),
2339 c_CLRSize = sizeof(ELEMENT),
2343 virtual LocalDesc GetNativeType()
2345 LIMITED_METHOD_CONTRACT;
2348 // pointer to value class
2350 return LocalDesc(ELEMENT_TYPE_I);
2353 virtual LocalDesc GetManagedType()
2355 STANDARD_VM_CONTRACT;
2360 return LocalDesc(MscorlibBinder::GetClass(CLASS__ID));
2363 virtual bool NeedsClearNative()
2365 LIMITED_METHOD_CONTRACT;
2366 return (IsByref(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags));
2369 virtual void EmitClearNative(ILCodeStream* pslILEmit)
2371 STANDARD_VM_CONTRACT;
2373 EmitLoadNativeValue(pslILEmit);
2374 // static void CoTaskMemFree(IntPtr ptr)
2375 pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
2378 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
2380 STANDARD_VM_CONTRACT;
2382 if (NeedsClearNative())
2384 pslILEmit->EmitLDC(sizeof(ELEMENT));
2385 pslILEmit->EmitCONV_U();
2386 // static IntPtr CoTaskMemAlloc(UIntPtr cb)
2387 pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMALLOC, 1, 1);
2388 EmitStoreNativeValue(pslILEmit);
2392 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2394 STANDARD_VM_CONTRACT;
2396 if (NeedsClearNative())
2398 EmitLoadNativeValue(pslILEmit); // dest
2399 EmitLoadManagedHomeAddr(pslILEmit); // src
2400 pslILEmit->EmitCPOBJ(pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__ID)));
2404 EmitLoadManagedHomeAddr(pslILEmit);
2405 EmitStoreNativeValue(pslILEmit);
2409 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2411 STANDARD_VM_CONTRACT;
2413 int tokType = pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__ID));
2414 ILCodeLabel *pNullLabel = pslILEmit->NewCodeLabel();
2415 ILCodeLabel *pJoinLabel = pslILEmit->NewCodeLabel();
2417 EmitLoadNativeValue(pslILEmit);
2418 pslILEmit->EmitBRFALSE(pNullLabel);
2420 // the incoming pointer is non-null -> dereference it and copy the struct
2421 EmitLoadManagedHomeAddr(pslILEmit); // dest
2422 EmitLoadNativeValue(pslILEmit); // src
2423 pslILEmit->EmitCPOBJ(tokType);
2425 pslILEmit->EmitBR(pJoinLabel);
2427 // the incoming pointer is null -> just initobj (i.e. zero) the struct
2428 pslILEmit->EmitLabel(pNullLabel);
2430 EmitLoadManagedHomeAddr(pslILEmit);
2431 pslILEmit->EmitINITOBJ(tokType);
2433 pslILEmit->EmitLabel(pJoinLabel);
2437 typedef ILValueClassPtrMarshaler<CLASS__GUID, GUID> ILGuidPtrMarshaler;
2438 typedef ILValueClassPtrMarshaler<CLASS__DECIMAL, DECIMAL> ILDecimalPtrMarshaler;
2440 #ifdef FEATURE_COMINTEROP
2441 class ILOleColorMarshaler : public ILMarshaler
2447 c_nativeSize = sizeof(OLE_COLOR),
2448 c_CLRSize = sizeof(SYSTEMCOLOR),
2452 virtual LocalDesc GetNativeType();
2453 virtual LocalDesc GetManagedType();
2454 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2455 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2458 class ILVBByValStrWMarshaler : public ILMarshaler
2464 c_nativeSize = sizeof(BSTR),
2465 c_CLRSize = sizeof(OBJECTREF*),
2470 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2471 MAX_LOCAL_BUFFER_LENGTH = (MAX_PATH_FNAME + 1) * 2 + sizeof(DWORD)
2475 ILVBByValStrWMarshaler() :
2477 ,m_dwLocalBuffer(-1)
2479 LIMITED_METHOD_CONTRACT;
2482 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2483 virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2486 virtual LocalDesc GetNativeType();
2487 virtual LocalDesc GetManagedType();
2488 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2489 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2490 virtual bool NeedsClearNative();
2491 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2492 virtual bool IsNativePassedByRef();
2495 DWORD m_dwLocalBuffer;
2498 class ILVBByValStrMarshaler : public ILMarshaler
2504 c_nativeSize = sizeof(LPSTR),
2505 c_CLRSize = sizeof(OBJECTREF *),
2508 ILVBByValStrMarshaler() :
2511 LIMITED_METHOD_CONTRACT;
2514 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2515 virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2518 virtual LocalDesc GetNativeType();
2519 virtual LocalDesc GetManagedType();
2520 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2521 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2522 virtual bool NeedsClearNative();
2523 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2524 virtual bool IsNativePassedByRef();
2529 class ILHSTRINGMarshaler : public ILMarshaler
2535 c_nativeSize = sizeof(HSTRING),
2536 c_CLRSize = sizeof(OBJECTREF),
2540 virtual LocalDesc GetNativeType();
2541 virtual LocalDesc GetManagedType();
2543 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2544 void EmitConvertCLRToHSTRINGReference(ILCodeStream* pslILEmit);
2545 void EmitConvertCLRToHSTRING(ILCodeStream* pslILEmit);
2547 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2549 virtual bool NeedsClearNative();
2550 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2552 #endif // FEATURE_COMINTEROP
2555 class ILCUTF8Marshaler : public ILOptimizedAllocMarshaler
2561 c_nativeSize = sizeof(void *),
2562 c_CLRSize = sizeof(OBJECTREF),
2567 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2568 MAX_LOCAL_BUFFER_LENGTH = MAX_PATH_FNAME + 1
2571 ILCUTF8Marshaler() :
2572 ILOptimizedAllocMarshaler(METHOD__CSTRMARSHALER__CLEAR_NATIVE)
2574 LIMITED_METHOD_CONTRACT;
2578 virtual LocalDesc GetManagedType();
2579 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2580 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2585 class ILCSTRMarshaler : public ILOptimizedAllocMarshaler
2591 c_nativeSize = sizeof(void *),
2592 c_CLRSize = sizeof(OBJECTREF),
2597 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2598 MAX_LOCAL_BUFFER_LENGTH = MAX_PATH_FNAME + 1
2602 ILOptimizedAllocMarshaler(METHOD__CSTRMARSHALER__CLEAR_NATIVE)
2604 LIMITED_METHOD_CONTRACT;
2608 virtual LocalDesc GetManagedType();
2609 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2610 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2613 #ifdef FEATURE_COMINTEROP
2614 class ILBSTRMarshaler : public ILOptimizedAllocMarshaler
2620 c_nativeSize = sizeof(void *),
2621 c_CLRSize = sizeof(OBJECTREF),
2626 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2627 MAX_LOCAL_BUFFER_LENGTH = (MAX_PATH_FNAME + 1) * 2 + 4
2631 ILOptimizedAllocMarshaler(METHOD__BSTRMARSHALER__CLEAR_NATIVE)
2633 LIMITED_METHOD_CONTRACT;
2637 virtual LocalDesc GetManagedType();
2638 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2639 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2643 class ILAnsiBSTRMarshaler : public ILMarshaler
2649 c_nativeSize = sizeof(void *),
2650 c_CLRSize = sizeof(OBJECTREF),
2654 virtual LocalDesc GetNativeType();
2655 virtual LocalDesc GetManagedType();
2656 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2657 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2658 virtual bool NeedsClearNative();
2659 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2661 #endif // FEATURE_COMINTEROP
2663 class ILLayoutClassPtrMarshalerBase : public ILMarshaler
2668 c_nativeSize = sizeof(void *),
2669 c_CLRSize = sizeof(OBJECTREF),
2673 virtual LocalDesc GetNativeType();
2674 virtual LocalDesc GetManagedType();
2675 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
2676 virtual void EmitConvertSpaceCLRToNativeTemp(ILCodeStream* pslILEmit);
2677 virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit);
2678 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
2679 virtual bool NeedsClearNative();
2680 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2681 virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit);
2684 class ILLayoutClassPtrMarshaler : public ILLayoutClassPtrMarshalerBase
2693 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2694 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2695 virtual void EmitClearNativeContents(ILCodeStream * pslILEmit);
2698 class ILBlittablePtrMarshaler : public ILLayoutClassPtrMarshalerBase
2707 virtual void EmitMarshalArgumentCLRToNative();
2708 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2709 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2713 #ifndef FEATURE_CORECLR
2714 class ILBlittableValueClassWithCopyCtorMarshaler : public ILMarshaler
2720 c_nativeSize = VARIABLESIZE,
2721 c_CLRSize = sizeof(OBJECTREF),
2724 LocalDesc GetManagedType()
2726 LIMITED_METHOD_CONTRACT;
2730 LocalDesc GetNativeType()
2732 LIMITED_METHOD_CONTRACT;
2736 static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
2740 BOOL fManagedToNative,
2741 OverrideProcArgs* pargs,
2744 UINT nativeStackOffset);
2748 #endif // !FEATURE_CORECLR
2751 class ILArgIteratorMarshaler : public ILMarshaler
2757 c_nativeSize = sizeof(va_list),
2758 c_CLRSize = sizeof(VARARGS),
2762 virtual LocalDesc GetNativeType();
2763 virtual LocalDesc GetManagedType();
2764 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2765 virtual void EmitMarshalArgumentCLRToNative();
2766 virtual void EmitMarshalArgumentNativeToCLR();
2769 class ILArrayWithOffsetMarshaler : public ILMarshaler
2775 c_nativeSize = sizeof(LPVOID),
2776 c_CLRSize = sizeof(ArrayWithOffsetData),
2779 ILArrayWithOffsetMarshaler() :
2780 m_dwCountLocalNum(-1),
2781 m_dwOffsetLocalNum(-1),
2782 m_dwPinnedLocalNum(-1)
2784 LIMITED_METHOD_CONTRACT;
2788 virtual LocalDesc GetNativeType();
2789 virtual LocalDesc GetManagedType();
2790 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2792 virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit);
2793 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2794 virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit);
2797 DWORD m_dwCountLocalNum;
2798 DWORD m_dwOffsetLocalNum;
2799 DWORD m_dwPinnedLocalNum;
2802 class ILAsAnyMarshalerBase : public ILMarshaler
2807 c_nativeSize = sizeof(void *),
2808 c_CLRSize = sizeof(OBJECTREF),
2811 ILAsAnyMarshalerBase() :
2812 m_dwMarshalerLocalNum(-1)
2814 LIMITED_METHOD_CONTRACT;
2818 static const BYTE ML_IN = 0x10;
2819 static const BYTE ML_OUT = 0x20;
2821 virtual bool IsAnsi() = 0;
2822 virtual LocalDesc GetNativeType();
2823 virtual LocalDesc GetManagedType();
2824 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2825 virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2826 virtual void EmitMarshalArgumentCLRToNative();
2827 virtual bool NeedsClearNative();
2828 virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit);
2830 DWORD m_dwMarshalerLocalNum;
2833 class ILAsAnyWMarshaler : public ILAsAnyMarshalerBase
2842 virtual bool IsAnsi()
2848 class ILAsAnyAMarshaler : public ILAsAnyMarshalerBase
2857 virtual bool IsAnsi()
2864 class ILMngdMarshaler : public ILMarshaler
2869 c_nativeSize = sizeof(void *),
2870 c_CLRSize = sizeof(OBJECTREF),
2873 ILMngdMarshaler(BinderMethodID space2Man,
2874 BinderMethodID contents2Man,
2875 BinderMethodID space2Nat,
2876 BinderMethodID contents2Nat,
2877 BinderMethodID clearNat,
2878 BinderMethodID clearNatContents,
2879 BinderMethodID clearMan) :
2880 m_idConvertSpaceToManaged(space2Man),
2881 m_idConvertContentsToManaged(contents2Man),
2882 m_idConvertSpaceToNative(space2Nat),
2883 m_idConvertContentsToNative(contents2Nat),
2884 m_idClearNative(clearNat),
2885 m_idClearNativeContents(clearNatContents),
2886 m_idClearManaged(clearMan)
2888 LIMITED_METHOD_CONTRACT;
2892 virtual LocalDesc GetNativeType();
2893 virtual LocalDesc GetManagedType();
2895 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) = 0;
2897 virtual void EmitCallMngdMarshalerMethod(ILCodeStream* pslILEmit, MethodDesc *pMD);
2899 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
2901 WRAPPER_NO_CONTRACT;
2902 EmitCallMngdMarshalerMethod(pslILEmit, GetConvertSpaceToManagedMethod());
2905 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2907 WRAPPER_NO_CONTRACT;
2908 EmitCallMngdMarshalerMethod(pslILEmit, GetConvertContentsToManagedMethod());
2911 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
2913 WRAPPER_NO_CONTRACT;
2914 EmitCallMngdMarshalerMethod(pslILEmit, GetConvertSpaceToNativeMethod());
2917 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2919 WRAPPER_NO_CONTRACT;
2920 EmitCallMngdMarshalerMethod(pslILEmit, GetConvertContentsToNativeMethod());
2923 virtual bool NeedsClearNative()
2925 LIMITED_METHOD_CONTRACT;
2927 if (NULL != GetClearNativeMethod())
2935 virtual void EmitClearNative(ILCodeStream* pslILEmit)
2937 WRAPPER_NO_CONTRACT;
2938 EmitCallMngdMarshalerMethod(pslILEmit, GetClearNativeMethod());
2941 virtual void EmitClearNativeContents(ILCodeStream* pslILEmit)
2943 WRAPPER_NO_CONTRACT;
2944 EmitCallMngdMarshalerMethod(pslILEmit, GetClearNativeContentsMethod());
2948 virtual bool NeedsClearCLR()
2950 LIMITED_METHOD_CONTRACT;
2952 if (NULL != GetClearManagedMethod())
2960 virtual void EmitClearCLR(ILCodeStream* pslILEmit)
2962 WRAPPER_NO_CONTRACT;
2963 EmitCallMngdMarshalerMethod(pslILEmit, GetClearManagedMethod());
2966 virtual MethodDesc *GetConvertSpaceToManagedMethod() { WRAPPER_NO_CONTRACT; return (m_idConvertSpaceToManaged == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idConvertSpaceToManaged)); }
2967 virtual MethodDesc *GetConvertContentsToManagedMethod() { WRAPPER_NO_CONTRACT; return (m_idConvertContentsToManaged == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idConvertContentsToManaged)); }
2968 virtual MethodDesc *GetConvertSpaceToNativeMethod() { WRAPPER_NO_CONTRACT; return (m_idConvertSpaceToNative == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idConvertSpaceToNative)); }
2969 virtual MethodDesc *GetConvertContentsToNativeMethod() { WRAPPER_NO_CONTRACT; return (m_idConvertContentsToNative == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idConvertContentsToNative)); }
2970 virtual MethodDesc *GetClearNativeMethod() { WRAPPER_NO_CONTRACT; return (m_idClearNative == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idClearNative)); }
2971 virtual MethodDesc *GetClearNativeContentsMethod() { WRAPPER_NO_CONTRACT; return (m_idClearNativeContents == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idClearNativeContents)); }
2972 virtual MethodDesc *GetClearManagedMethod() { WRAPPER_NO_CONTRACT; return (m_idClearManaged == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idClearManaged)); }
2974 const BinderMethodID m_idConvertSpaceToManaged;
2975 const BinderMethodID m_idConvertContentsToManaged;
2976 const BinderMethodID m_idConvertSpaceToNative;
2977 const BinderMethodID m_idConvertContentsToNative;
2978 const BinderMethodID m_idClearNative;
2979 const BinderMethodID m_idClearNativeContents;
2980 const BinderMethodID m_idClearManaged;
2983 class ILNativeArrayMarshaler : public ILMngdMarshaler
2991 ILNativeArrayMarshaler() :
2993 METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CONVERT_SPACE_TO_MANAGED,
2994 METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED,
2995 METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CONVERT_SPACE_TO_NATIVE,
2996 METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE,
2997 METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CLEAR_NATIVE,
2998 METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CLEAR_NATIVE_CONTENTS,
3002 LIMITED_METHOD_CONTRACT;
3003 m_dwSavedSizeArg = LOCAL_NUM_UNUSED;
3006 virtual void EmitMarshalArgumentCLRToNative();
3007 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
3008 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
3009 virtual void EmitClearNative(ILCodeStream* pslILEmit);
3010 virtual void EmitClearNativeContents(ILCodeStream* pslILEmit);
3011 virtual void EmitMarshalArgumentNativeToCLRByref();
3012 virtual void EmitMarshalArgumentCLRToNativeByref();
3016 bool UsePinnedArraySpecialCase();
3018 BOOL CheckSizeParamIndexArg(const CREATE_MARSHALER_CARRAY_OPERANDS &mops, CorElementType *pElementType);
3020 // Calculate element count and load it on evaluation stack
3021 void EmitLoadElementCount(ILCodeStream* pslILEmit);
3023 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
3025 void EmitLoadNativeSize(ILCodeStream* pslILEmit);
3026 void EmitNewSavedSizeArgLocal();
3029 DWORD m_dwSavedSizeArg;
3032 class MngdNativeArrayMarshaler
3035 static FCDECL3(void, CreateMarshaler, MngdNativeArrayMarshaler* pThis, MethodTable* pMT, UINT32 dwFlags);
3036 static FCDECL3(void, ConvertSpaceToNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3037 static FCDECL3(void, ConvertContentsToNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3038 static FCDECL4(void, ConvertSpaceToManaged, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements);
3039 static FCDECL3(void, ConvertContentsToManaged, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3040 static FCDECL3(void, ClearNative, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
3041 static FCDECL3(void, ClearNativeContents, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
3043 static void DoClearNativeContents(MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
3047 FLAG_NATIVE_DATA_VALID = 0x40000000
3050 MethodTable* m_pElementMT;
3052 BOOL m_NativeDataValid;
3054 BOOL m_ThrowOnUnmappableChar;
3059 #ifdef FEATURE_COMINTEROP
3060 class ILSafeArrayMarshaler : public ILMngdMarshaler
3068 ILSafeArrayMarshaler() :
3070 METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_SPACE_TO_MANAGED,
3071 METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED,
3072 METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_SPACE_TO_NATIVE,
3073 METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE,
3074 METHOD__MNGD_SAFE_ARRAY_MARSHALER__CLEAR_NATIVE,
3078 m_dwOriginalManagedLocalNum(-1)
3080 LIMITED_METHOD_CONTRACT;
3085 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
3086 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3087 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3089 virtual void EmitReInitNative(ILCodeStream* pslILEmit)
3098 if (NeedsCheckForStatic() && pslILEmit->GetStreamType() != ILStubLinker::kExceptionCleanup)
3100 // Keep the original value in native home as we are not going to allocate a new
3101 // one. If we cleared it here, we wouldn't be able to ConvertContentsToNative.
3102 // Always perform the real re-init in the ExceptionCleanup stream so the caller
3103 // doesn't get back garbage.
3107 ILMngdMarshaler::EmitReInitNative(pslILEmit);
3111 bool NeedsCheckForStatic()
3113 WRAPPER_NO_CONTRACT;
3114 return IsByref(m_dwMarshalFlags) && !IsCLRToNative(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags);
3117 DWORD m_dwOriginalManagedLocalNum;
3120 class MngdSafeArrayMarshaler
3123 static FCDECL4(void, CreateMarshaler, MngdSafeArrayMarshaler* pThis, MethodTable* pMT, UINT32 iRank, UINT32 dwFlags);
3124 static FCDECL3(void, ConvertSpaceToNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3125 static FCDECL4(void, ConvertContentsToNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, Object* pOriginalManagedUNSAFE);
3126 static FCDECL3(void, ConvertSpaceToManaged, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3127 static FCDECL3(void, ConvertContentsToManaged, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3128 static FCDECL3(void, ClearNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3130 enum StaticCheckStateFlags
3132 SCSF_CheckForStatic = 1,
3134 SCSF_NativeDataValid = 4
3137 MethodTable* m_pElementMT;
3140 BYTE m_fStatic; // StaticCheckStateFlags
3141 BYTE m_nolowerbounds;
3144 class ILHiddenLengthArrayMarshaler : public ILMngdMarshaler
3146 friend class MngdHiddenLengthArrayMarshaler;
3151 c_nativeSize = sizeof(LPVOID),
3152 c_CLRSize = sizeof(OBJECTREF),
3156 ILHiddenLengthArrayMarshaler() :
3157 ILMngdMarshaler(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_SPACE_TO_MANAGED,
3158 METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED,
3159 METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_SPACE_TO_NATIVE,
3160 METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE,
3161 METHOD__WIN32NATIVE__COTASKMEMFREE,
3162 METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CLEAR_NATIVE_CONTENTS,
3165 LIMITED_METHOD_CONTRACT;
3166 m_dwMngdMarshalerLocalNum = -1;
3170 virtual LocalDesc GetNativeType();
3171 virtual LocalDesc GetManagedType();
3173 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
3174 virtual void EmitMarshalArgumentCLRToNative();
3175 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
3176 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
3177 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3178 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3179 virtual void EmitClearNative(ILCodeStream* pslILEmit);
3180 virtual void EmitClearNativeContents(ILCodeStream* pslILEmit);
3183 bool CanUsePinnedArray();
3184 void EmitLoadNativeArrayLength(ILCodeStream *pslILEmit);
3186 virtual MethodDesc *GetConvertContentsToManagedMethod();
3187 virtual MethodDesc *GetConvertContentsToNativeMethod();
3188 virtual MethodDesc *GetClearNativeContentsMethod();
3190 MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD);
3193 class MngdHiddenLengthArrayMarshaler
3196 static FCDECL4(void, CreateMarshaler, MngdHiddenLengthArrayMarshaler* pThis, MethodTable* pMT, SIZE_T cbElement, UINT16 vt);
3197 static FCDECL3(void, ConvertSpaceToNative, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3198 static FCDECL3(void, ConvertContentsToNative, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3199 static FCDECL4(void, ConvertSpaceToManaged, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements);
3200 static FCDECL3(void, ConvertContentsToManaged, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3201 static FCDECL3(void, ClearNativeContents, MngdHiddenLengthArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
3205 SIZE_T GetArraySize(SIZE_T elements);
3206 void DoClearNativeContents(void** pNativeHome, INT32 cElements);
3209 MethodTable *m_pElementMT;
3210 SIZE_T m_cbElementSize;
3213 #endif // FEATURE_COMINTEROP
3216 class ILReferenceCustomMarshaler : public ILMngdMarshaler
3224 ILReferenceCustomMarshaler() :
3227 METHOD__MNGD_REF_CUSTOM_MARSHALER__CONVERT_CONTENTS_TO_MANAGED,
3229 METHOD__MNGD_REF_CUSTOM_MARSHALER__CONVERT_CONTENTS_TO_NATIVE,
3230 METHOD__MNGD_REF_CUSTOM_MARSHALER__CLEAR_NATIVE,
3232 METHOD__MNGD_REF_CUSTOM_MARSHALER__CLEAR_MANAGED
3235 LIMITED_METHOD_CONTRACT;
3239 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
3242 class MngdRefCustomMarshaler
3245 static FCDECL2(void, CreateMarshaler, MngdRefCustomMarshaler* pThis, void* pCMHelper);
3246 static FCDECL3(void, ConvertContentsToNative, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3247 static FCDECL3(void, ConvertContentsToManaged, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3248 static FCDECL3(void, ClearNative, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3249 static FCDECL3(void, ClearManaged, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3251 static void DoClearNativeContents(MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3253 CustomMarshalerHelper* m_pCMHelper;
3257 #ifdef FEATURE_COMINTEROP
3258 class ILUriMarshaler : public ILMarshaler
3264 c_nativeSize = sizeof(LPVOID),
3265 c_CLRSize = sizeof(OBJECTREF),
3268 static void EmitConvertCLRUriToWinRTUri(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3269 static void EmitConvertWinRTUriToCLRUri(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3272 virtual LocalDesc GetNativeType();
3273 virtual LocalDesc GetManagedType();
3275 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3276 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3278 virtual bool NeedsClearNative();
3279 void EmitClearNative(ILCodeStream* pslILEmit);
3282 class ILNCCEventArgsMarshaler : public ILMarshaler
3288 c_nativeSize = sizeof(LPVOID),
3289 c_CLRSize = sizeof(OBJECTREF),
3292 static void EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3293 static void EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3296 virtual LocalDesc GetNativeType();
3297 virtual LocalDesc GetManagedType();
3299 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3300 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3302 virtual bool NeedsClearNative();
3303 void EmitClearNative(ILCodeStream* pslILEmit);
3306 class ILPCEventArgsMarshaler : public ILMarshaler
3312 c_nativeSize = sizeof(LPVOID),
3313 c_CLRSize = sizeof(OBJECTREF),
3316 static void EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3317 static void EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3320 virtual LocalDesc GetNativeType();
3321 virtual LocalDesc GetManagedType();
3323 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3324 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3326 virtual bool NeedsClearNative();
3327 void EmitClearNative(ILCodeStream* pslILEmit);
3330 class ILDateTimeMarshaler : public ILMarshaler
3336 c_nativeSize = sizeof(INT64), // = sizeof(Windows::Foundation::DateTime)
3337 c_CLRSize = VARIABLESIZE,
3341 virtual LocalDesc GetNativeType();
3342 virtual LocalDesc GetManagedType();
3344 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3345 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3347 virtual bool NeedsClearNative();
3348 virtual void EmitReInitNative(ILCodeStream* pslILEmit);
3351 class ILNullableMarshaler : public ILMarshaler
3357 c_nativeSize = sizeof(LPVOID),
3358 c_CLRSize = VARIABLESIZE,
3362 virtual LocalDesc GetNativeType();
3363 virtual LocalDesc GetManagedType();
3364 virtual bool NeedsClearNative();
3365 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3366 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3367 virtual void EmitClearNative(ILCodeStream* pslILEmit);
3370 MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD);
3373 class ILSystemTypeMarshaler : public ILMarshaler
3379 c_nativeSize = sizeof(TypeNameNative),
3380 c_CLRSize = sizeof(OBJECTREF)
3384 virtual LocalDesc GetNativeType();
3385 virtual LocalDesc GetManagedType();
3387 virtual void EmitConvertContentsCLRToNative(ILCodeStream * pslILEmit);
3388 virtual void EmitConvertContentsNativeToCLR(ILCodeStream * pslILEmit);
3390 virtual bool NeedsClearNative();
3391 virtual void EmitClearNative(ILCodeStream * pslILEmit);
3392 virtual void EmitReInitNative(ILCodeStream * pslILEmit);
3395 class ILHResultExceptionMarshaler : public ILMarshaler
3401 c_nativeSize = sizeof(INT32), // = sizeof(Windows::Foundation::HResult)
3402 c_CLRSize = sizeof(OBJECTREF),
3406 virtual LocalDesc GetNativeType();
3407 virtual LocalDesc GetManagedType();
3409 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3410 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3412 virtual bool NeedsClearNative();
3415 class ILKeyValuePairMarshaler : public ILMarshaler
3421 c_nativeSize = sizeof(LPVOID),
3422 c_CLRSize = VARIABLESIZE,
3426 virtual LocalDesc GetNativeType();
3427 virtual LocalDesc GetManagedType();
3428 virtual bool NeedsClearNative();
3429 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3430 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3431 virtual void EmitClearNative(ILCodeStream* pslILEmit);
3434 MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD);
3437 #endif // FEATURE_COMINTEROP