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_X86_)
604 // JIT32 and JIT64 (which is only used on the Windows Desktop CLR) has a problem generating
605 // code for the pinvoke ILStubs which do a return using a struct type. Therefore, we
606 // change the signature of calli to return void and make the return buffer as first argument.
608 // for X86 and AMD64-Windows we bash the return type from struct to U1, U2, U4 or U8
609 // and use byrefNativeReturn for all other structs.
610 // for UNIX_X86_ABI, we always need a return buffer argument for any size of structs.
614 case 1: typ = ELEMENT_TYPE_U1; break;
615 case 2: typ = ELEMENT_TYPE_U2; break;
616 case 4: typ = ELEMENT_TYPE_U4; break;
617 case 8: typ = ELEMENT_TYPE_U8; break;
619 default: byrefNativeReturn = true; break;
624 if (IsHresultSwap(dwMarshalFlags) || (byrefNativeReturn && IsCLRToNative(dwMarshalFlags)))
626 LocalDesc extraParamType = nativeType;
627 extraParamType.MakeByRef();
629 m_pcsMarshal->SetStubTargetArgType(&extraParamType, false);
631 if (IsHresultSwap(dwMarshalFlags))
633 // HRESULT swapping: the original return value is transformed into an extra
634 // byref parameter and the target is expected to return an HRESULT
635 m_pcsMarshal->SetStubTargetReturnType(ELEMENT_TYPE_I4); // native method returns an HRESULT
639 // byref structure return: the original return value is transformed into an
640 // extra byref parameter and the target is not expected to return anything
642 // note: we do this only for forward calls because [unmanaged calling conv.
643 // uses byref return] implies [managed calling conv. uses byref return]
644 m_pcsMarshal->SetStubTargetReturnType(ELEMENT_TYPE_VOID);
649 if (typ != ELEMENT_TYPE_VOID)
651 // small structure return: the original return value is transformed into
652 // ELEMENT_TYPE_U1, ELEMENT_TYPE_U2, ELEMENT_TYPE_U4, or ELEMENT_TYPE_U8
653 m_pcsMarshal->SetStubTargetReturnType(typ);
657 m_pcsMarshal->SetStubTargetReturnType(&nativeType);
661 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(managedType));
662 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(nativeType));
664 EmitCreateMngdMarshaler(m_pcsMarshal);
666 if (IsCLRToNative(dwMarshalFlags))
668 if (IsHresultSwap(dwMarshalFlags) || byrefNativeReturn)
670 EmitReInitNative(m_pcsMarshal);
671 EmitLoadNativeHomeAddr(pcsDispatch); // load up the byref native type as an extra arg
675 if (typ != ELEMENT_TYPE_VOID)
677 // small structure forward: the returned integer is memcpy'd into native home
680 DWORD dwTempLocalNum = m_pcsUnmarshal->NewLocal(typ);
681 m_pcsUnmarshal->EmitSTLOC(dwTempLocalNum);
684 m_nativeHome.EmitLoadHomeAddr(m_pcsUnmarshal);
685 m_pcsUnmarshal->EmitLDLOCA(dwTempLocalNum);
686 m_pcsUnmarshal->EmitLDC(nativeSize);
687 m_pcsUnmarshal->EmitCPBLK();
691 EmitStoreNativeValue(m_pcsUnmarshal);
695 if (NeedsMarshalCleanupIndex())
697 m_pslNDirect->EmitSetArgMarshalIndex(m_pcsUnmarshal, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx);
700 EmitConvertSpaceAndContentsNativeToCLR(m_pcsUnmarshal);
702 EmitCleanupCLRToNative();
704 EmitLoadManagedValue(m_pcsUnmarshal);
708 EmitStoreManagedValue(m_pcsUnmarshal);
710 if (NeedsMarshalCleanupIndex())
712 m_pslNDirect->EmitSetArgMarshalIndex(m_pcsUnmarshal, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx);
715 if (IsHresultSwap(dwMarshalFlags))
717 // we have to skip unmarshaling return value into the HRESULT-swapped argument
718 // if the argument came as NULL (otherwise we would leak unmanaged resources as
719 // we have no way of passing them back to the caller)
720 ILCodeLabel *pSkipConversionLabel = m_pcsUnmarshal->NewCodeLabel();
722 m_pcsUnmarshal->EmitLDARG(argidx);
723 m_pcsUnmarshal->EmitBRFALSE(pSkipConversionLabel);
724 EmitConvertSpaceAndContentsCLRToNative(m_pcsUnmarshal);
725 m_pcsUnmarshal->EmitLabel(pSkipConversionLabel);
729 EmitConvertSpaceAndContentsCLRToNative(m_pcsUnmarshal);
732 if (NeedsUnmarshalCleanupIndex())
734 // if an exception is thrown after this point, we will clean up the unmarshaled retval
735 m_pslNDirect->EmitSetArgMarshalIndex(m_pcsUnmarshal, NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL);
738 EmitCleanupNativeToCLR();
740 if (IsHresultSwap(dwMarshalFlags))
742 // we tolerate NULL here mainly for backward compatibility reasons
743 m_nativeHome.EmitCopyToByrefArgWithNullCheck(m_pcsUnmarshal, &nativeType, argidx);
744 m_pcsUnmarshal->EmitLDC(S_OK);
748 if (typ != ELEMENT_TYPE_VOID)
750 // small structure return (reverse): native home of the structure is memcpy'd
751 // into the integer to be returned from the stub
753 DWORD dwTempLocalNum = m_pcsUnmarshal->NewLocal(typ);
756 m_pcsUnmarshal->EmitLDLOCA(dwTempLocalNum);
757 m_nativeHome.EmitLoadHomeAddr(m_pcsUnmarshal);
758 m_pcsUnmarshal->EmitLDC(nativeSize);
759 m_pcsUnmarshal->EmitCPBLK();
761 m_pcsUnmarshal->EmitLDLOC(dwTempLocalNum);
765 EmitLoadNativeValue(m_pcsUnmarshal);
769 // make sure we free (and zero) the return value if an exception is thrown
770 EmitExceptionCleanupNativeToCLR();
777 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
779 LIMITED_METHOD_CONTRACT;
782 virtual void EmitLoadMngdMarshaler(ILCodeStream* pslILEmit)
792 CONSISTENCY_CHECK((DWORD)-1 != m_dwMngdMarshalerLocalNum);
793 pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
796 void EmitSetupSigAndDefaultHomesCLRToNative()
801 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
805 LocalDesc nativeArgType = GetNativeType();
806 DWORD dwNativeHomeLocalNum = m_pcsMarshal->NewLocal(nativeArgType);
807 m_pcsMarshal->SetStubTargetArgType(&nativeArgType);
809 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILArgument, m_argidx);
810 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, dwNativeHomeLocalNum);
813 void EmitCleanupCLRToNativeTemp()
815 STANDARD_VM_CONTRACT;
817 if (NeedsClearNative())
819 CONSISTENCY_CHECK(NeedsMarshalCleanupIndex());
821 ILCodeStream* pcsCleanup = m_pslNDirect->GetCleanupCodeStream();
822 ILCodeLabel* pSkipClearNativeLabel = pcsCleanup->NewCodeLabel();
824 m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
825 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx,
826 NDirectStubLinker::BranchIfNotMarshaled,
827 pSkipClearNativeLabel);
829 EmitClearNativeTemp(pcsCleanup);
830 pcsCleanup->EmitLabel(pSkipClearNativeLabel);
834 void EmitCleanupCLRToNative()
836 STANDARD_VM_CONTRACT;
838 if (NeedsClearNative())
840 CONSISTENCY_CHECK(NeedsMarshalCleanupIndex());
842 ILCodeStream* pcsCleanup = m_pslNDirect->GetCleanupCodeStream();
843 ILCodeLabel* pSkipClearNativeLabel = pcsCleanup->NewCodeLabel();
845 m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
846 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx,
847 NDirectStubLinker::BranchIfNotMarshaled,
848 pSkipClearNativeLabel);
850 EmitClearNative(pcsCleanup);
851 pcsCleanup->EmitLabel(pSkipClearNativeLabel);
855 virtual void EmitMarshalArgumentCLRToNative()
860 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
864 EmitSetupSigAndDefaultHomesCLRToNative();
865 EmitMarshalArgumentContentsCLRToNative();
868 void EmitMarshalArgumentContentsCLRToNative()
873 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
880 if (IsIn(m_dwMarshalFlags))
882 EmitConvertSpaceAndContentsCLRToNativeTemp(m_pcsMarshal);
886 EmitConvertSpaceCLRToNativeTemp(m_pcsMarshal);
892 if (IsOut(m_dwMarshalFlags))
894 if (IsIn(m_dwMarshalFlags))
896 EmitClearCLRContents(m_pcsUnmarshal);
898 EmitConvertContentsNativeToCLR(m_pcsUnmarshal);
901 EmitCleanupCLRToNativeTemp();
904 void EmitSetupSigAndDefaultHomesCLRToNativeByref(bool fBlittable = false)
909 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
913 LocalDesc nativeType = GetNativeType();
914 LocalDesc managedType = GetManagedType();
916 LocalDesc nativeArgType = nativeType;
917 nativeArgType.MakeByRef();
918 m_pcsMarshal->SetStubTargetArgType(&nativeArgType);
922 // we will not work with the actual data but only with a pointer to that data
923 // (the managed and native type had better be the same if it's blittable)
924 _ASSERTE(nativeType.ElementType[0] == managedType.ElementType[0]);
926 // native home will keep the containing object pinned
927 nativeType.MakeByRef();
928 nativeType.MakePinned();
930 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILByrefArgument, m_argidx);
931 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILByrefLocal, m_pcsMarshal->NewLocal(nativeType));
935 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(managedType));
936 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(nativeType));
940 virtual void EmitMarshalArgumentCLRToNativeByref()
945 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
949 EmitSetupSigAndDefaultHomesCLRToNativeByref();
950 EmitMarshalArgumentContentsCLRToNativeByref(false);
953 void EmitMarshalArgumentContentsCLRToNativeByref(bool managedHomeAlreadyInitialized)
958 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
962 LocalDesc managedType = GetManagedType();
967 if (IsIn(m_dwMarshalFlags) && ! IsOut(m_dwMarshalFlags))
969 if (!managedHomeAlreadyInitialized)
971 m_managedHome.EmitCopyFromByrefArg(m_pcsMarshal, &managedType, m_argidx);
974 EmitConvertSpaceAndContentsCLRToNativeTemp(m_pcsMarshal);
976 else if (IsIn(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags))
978 if (!managedHomeAlreadyInitialized)
980 m_managedHome.EmitCopyFromByrefArg(m_pcsMarshal, &managedType, m_argidx);
983 EmitConvertSpaceAndContentsCLRToNative(m_pcsMarshal);
987 EmitReInitNative(m_pcsMarshal);
993 if (IsOut(m_dwMarshalFlags))
995 EmitClearCLR(m_pcsUnmarshal);
997 EmitConvertSpaceAndContentsNativeToCLR(m_pcsUnmarshal);
999 if (!managedHomeAlreadyInitialized)
1001 m_managedHome.EmitCopyToByrefArg(m_pcsUnmarshal, &managedType, m_argidx);
1004 EmitCleanupCLRToNative();
1008 EmitCleanupCLRToNativeTemp();
1011 // @TODO: ensure ReInitNative is called on [in,out] byref args when an exception occurs
1015 void EmitSetupSigAndDefaultHomesNativeToCLR()
1020 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
1024 LocalDesc nativeArgType = GetNativeType();
1025 m_pcsMarshal->SetStubTargetArgType(&nativeArgType);
1027 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(GetManagedType()));
1028 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILArgument, m_argidx);
1031 void EmitCleanupNativeToCLR()
1033 STANDARD_VM_CONTRACT;
1035 if (NeedsClearCLR())
1037 CONSISTENCY_CHECK(NeedsMarshalCleanupIndex());
1039 ILCodeStream* pcsCleanup = m_pslNDirect->GetCleanupCodeStream();
1040 ILCodeLabel* pSkipClearCLRLabel = pcsCleanup->NewCodeLabel();
1042 m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
1043 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx,
1044 NDirectStubLinker::BranchIfNotMarshaled,
1045 pSkipClearCLRLabel);
1047 EmitClearCLR(pcsCleanup);
1048 pcsCleanup->EmitLabel(pSkipClearCLRLabel);
1052 // Emits cleanup code that runs only if an exception is thrown during execution of an IL stub (its try
1053 // block to be precise). The goal is to roll back allocations of native resources that may have already
1054 // happened to prevent leaks, and also clear output arguments to prevent passing out invalid data - most
1055 // importantly dangling pointers. The canonical example is an exception thrown during unmarshaling of
1056 // an argument at which point other arguments have already been unmarshaled.
1057 void EmitExceptionCleanupNativeToCLR()
1059 STANDARD_VM_CONTRACT;
1061 _ASSERTE(IsRetval(m_dwMarshalFlags) || IsOut(m_dwMarshalFlags));
1063 LocalDesc nativeType = GetNativeType();
1064 ILCodeStream *pcsCleanup = m_pslNDirect->GetExceptionCleanupCodeStream();
1066 if (NeedsClearNative())
1068 m_pslNDirect->SetExceptionCleanupNeeded();
1070 ILCodeLabel *pSkipCleanupLabel = pcsCleanup->NewCodeLabel();
1072 // if this is byref in/out and we have not marshaled this argument
1073 // yet, we need to populate the native home with the incoming value
1074 if (IsIn(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags))
1076 ILCodeLabel *pSkipCopyLabel = pcsCleanup->NewCodeLabel();
1078 CONSISTENCY_CHECK(NeedsMarshalCleanupIndex());
1079 m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
1080 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx,
1081 NDirectStubLinker::BranchIfMarshaled,
1084 pcsCleanup->EmitLDARG(m_argidx);
1085 pcsCleanup->EmitBRFALSE(pSkipCleanupLabel); // if the argument is NULL, skip cleanup completely
1087 m_nativeHome.EmitCopyFromByrefArg(pcsCleanup, &nativeType, m_argidx);
1089 pcsCleanup->EmitLabel(pSkipCopyLabel);
1092 // if this is retval or out-only, the native home does not get initialized until we unmarshal it
1093 if (IsRetval(m_dwMarshalFlags) || !IsIn(m_dwMarshalFlags))
1095 CONSISTENCY_CHECK(NeedsUnmarshalCleanupIndex());
1097 UINT uArgIdx = (IsRetval(m_dwMarshalFlags) ?
1098 NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL :
1099 NDirectStubLinker::CLEANUP_INDEX_ARG0_UNMARSHAL + m_argidx);
1101 m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
1103 NDirectStubLinker::BranchIfNotMarshaled,
1107 // we know that native home needs to be cleaned up at this point
1108 if (IsRetval(m_dwMarshalFlags) || (IsOut(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags)))
1110 // we own the buffer - clear everything
1111 EmitClearNative(pcsCleanup);
1115 // this is a caller supplied buffer - clear only its contents
1116 EmitClearNativeContents(pcsCleanup);
1119 pcsCleanup->EmitLabel(pSkipCleanupLabel);
1122 // if there is an output buffer, zero it out so the caller does not get pointer to already freed data
1123 if (!IsHiddenLengthParam(m_dwMarshalFlags))
1125 if (IsRetval(m_dwMarshalFlags) || (IsOut(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags)))
1127 m_pslNDirect->SetExceptionCleanupNeeded();
1129 EmitReInitNative(pcsCleanup);
1130 if (IsHresultSwap(m_dwMarshalFlags) || IsOut(m_dwMarshalFlags))
1132 m_nativeHome.EmitCopyToByrefArgWithNullCheck(pcsCleanup, &nativeType, m_argidx);
1138 virtual void EmitMarshalArgumentNativeToCLR()
1143 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
1147 EmitSetupSigAndDefaultHomesNativeToCLR();
1148 EmitMarshalArgumentContentsNativeToCLR();
1151 void EmitMarshalArgumentContentsNativeToCLR()
1156 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
1163 if (IsIn(m_dwMarshalFlags))
1165 EmitConvertSpaceAndContentsNativeToCLR(m_pcsMarshal);
1169 EmitConvertSpaceNativeToCLR(m_pcsMarshal);
1175 if (IsOut(m_dwMarshalFlags))
1177 if (IsIn(m_dwMarshalFlags))
1179 EmitClearNativeContents(m_pcsUnmarshal);
1181 EmitConvertContentsCLRToNative(m_pcsUnmarshal);
1183 // make sure we free the argument if an exception is thrown
1184 EmitExceptionCleanupNativeToCLR();
1186 EmitCleanupNativeToCLR();
1189 void EmitSetupSigAndDefaultHomesNativeToCLRByref(bool fBlittable = false)
1194 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1198 LocalDesc nativeType = GetNativeType();
1199 LocalDesc managedType = GetManagedType();
1200 LocalDesc nativeArgType = nativeType;
1201 nativeArgType.MakeByRef();
1202 m_pcsMarshal->SetStubTargetArgType(&nativeArgType);
1206 // we will not work with the actual data but only with a pointer to that data
1207 // (the managed and native type had better be the same if it's blittable)
1208 _ASSERTE(nativeType.ElementType[0] == managedType.ElementType[0]);
1210 managedType.MakeByRef();
1212 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILByrefLocal, m_pcsMarshal->NewLocal(managedType));
1213 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILByrefArgument, m_argidx);
1217 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(managedType));
1218 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(nativeType));
1222 virtual void EmitMarshalArgumentNativeToCLRByref()
1227 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1231 EmitSetupSigAndDefaultHomesNativeToCLRByref();
1232 EmitMarshalArgumentContentsNativeToCLRByref(false);
1235 void EmitMarshalArgumentContentsNativeToCLRByref(bool nativeHomeAlreadyInitialized)
1240 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1244 LocalDesc nativeType = GetNativeType();
1249 if (IsIn(m_dwMarshalFlags))
1251 if (!nativeHomeAlreadyInitialized)
1253 m_nativeHome.EmitCopyFromByrefArg(m_pcsMarshal, &nativeType, m_argidx);
1256 EmitConvertSpaceAndContentsNativeToCLR(m_pcsMarshal);
1260 // dereference the argument so we throw before calling the managed target - this is the fastest way
1261 // to check for NULL (we can still throw later if the pointer is invalid yet non-NULL but we cannot
1262 // detect this realiably - the memory may get unmapped etc., NULL check is the best we can do here)
1263 m_pcsMarshal->EmitLDARG(m_argidx);
1264 m_pcsMarshal->EmitLDIND_I1();
1265 m_pcsMarshal->EmitPOP();
1271 if (IsOut(m_dwMarshalFlags))
1273 if (IsIn(m_dwMarshalFlags))
1275 EmitClearNative(m_pcsUnmarshal);
1276 EmitReInitNative(m_pcsUnmarshal);
1279 EmitConvertSpaceAndContentsCLRToNative(m_pcsUnmarshal);
1281 if (!nativeHomeAlreadyInitialized)
1283 m_nativeHome.EmitCopyToByrefArg(m_pcsUnmarshal, &nativeType, m_argidx);
1286 // make sure we free and zero the by-ref argument if an exception is thrown
1287 EmitExceptionCleanupNativeToCLR();
1290 EmitCleanupNativeToCLR();
1293 virtual LocalDesc GetNativeType() = 0;
1294 virtual LocalDesc GetManagedType() = 0;
1299 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
1301 LIMITED_METHOD_CONTRACT;
1304 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1306 LIMITED_METHOD_CONTRACT;
1309 virtual void EmitConvertSpaceAndContentsNativeToCLR(ILCodeStream* pslILEmit)
1311 WRAPPER_NO_CONTRACT;
1312 EmitConvertSpaceNativeToCLR(pslILEmit);
1313 EmitConvertContentsNativeToCLR(pslILEmit);
1320 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
1322 LIMITED_METHOD_CONTRACT;
1325 virtual void EmitConvertSpaceCLRToNativeTemp(ILCodeStream* pslILEmit)
1327 LIMITED_METHOD_CONTRACT;
1328 EmitConvertSpaceCLRToNative(pslILEmit);
1331 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1333 LIMITED_METHOD_CONTRACT;
1336 virtual void EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslILEmit)
1338 STANDARD_VM_CONTRACT;
1339 EmitConvertSpaceCLRToNative(pslILEmit);
1340 EmitConvertContentsCLRToNative(pslILEmit);
1343 virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
1345 WRAPPER_NO_CONTRACT;
1346 EmitConvertSpaceAndContentsCLRToNative(pslILEmit);
1352 virtual void EmitClearCLRContents(ILCodeStream* pslILEmit)
1354 LIMITED_METHOD_CONTRACT;
1357 virtual bool NeedsClearNative()
1359 LIMITED_METHOD_CONTRACT;
1363 virtual void EmitClearNative(ILCodeStream* pslILEmit)
1365 LIMITED_METHOD_CONTRACT;
1368 virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit)
1370 LIMITED_METHOD_CONTRACT;
1371 EmitClearNative(pslILEmit);
1374 virtual void EmitClearNativeContents(ILCodeStream* pslILEmit)
1376 LIMITED_METHOD_CONTRACT;
1379 virtual bool NeedsClearCLR()
1381 LIMITED_METHOD_CONTRACT;
1385 virtual void EmitClearCLR(ILCodeStream* pslILEmit)
1387 LIMITED_METHOD_CONTRACT;
1390 virtual void EmitReInitNative(ILCodeStream* pslILEmit)
1392 STANDARD_VM_CONTRACT;
1394 // Friendly Reminder:
1395 // You should implement your own EmitReInitNative if your native type is a struct,
1396 // as the following instructions apparently won't work on value types and will trigger
1398 _ASSERTE(!GetNativeType().IsValueClass());
1400 pslILEmit->EmitLDC(0);
1401 pslILEmit->EmitCONV_T(static_cast<CorElementType>(GetNativeType().ElementType[0]));
1403 EmitStoreNativeValue(pslILEmit);
1406 virtual bool IsManagedPassedByRef()
1408 LIMITED_METHOD_CONTRACT;
1409 return IsByref(m_dwMarshalFlags);
1412 virtual bool IsNativePassedByRef()
1414 LIMITED_METHOD_CONTRACT;
1415 return IsByref(m_dwMarshalFlags);
1418 void EmitInterfaceClearNative(ILCodeStream* pslILEmit);
1421 static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
1425 BOOL fManagedToNative,
1426 OverrideProcArgs* pargs,
1429 UINT nativeStackOffset)
1431 LIMITED_METHOD_CONTRACT;
1432 return HANDLEASNORMAL;
1435 static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker* psl,
1436 BOOL fManagedToNative,
1438 OverrideProcArgs* pargs,
1441 LIMITED_METHOD_CONTRACT;
1442 return HANDLEASNORMAL;
1447 class ILCopyMarshalerBase : public ILMarshaler
1449 virtual LocalDesc GetManagedType()
1451 WRAPPER_NO_CONTRACT;
1452 return GetNativeType();
1455 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1457 STANDARD_VM_CONTRACT;
1459 EmitLoadManagedValue(pslILEmit);
1460 EmitStoreNativeValue(pslILEmit);
1463 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1465 STANDARD_VM_CONTRACT;
1467 EmitLoadNativeValue(pslILEmit);
1468 EmitStoreManagedValue(pslILEmit);
1472 // It's very unforunate that x86 used ML_COPYPINNEDGCREF for byref args.
1473 // The result is that developers can get away with being lazy about their
1474 // in/out semantics and often times in/out byref params are marked out-
1475 // only, but because of ML_COPYPINNEDGCREF, they get in/out behavior.
1477 // There are even lazier developers who use byref params to pass arrays.
1478 // Pinning ensures that the native side 'sees' the entire array even when
1479 // only reference to one element was passed.
1481 // This method was changed to pin instead of copy in Dev10 in order
1482 // to match the original ML behavior.
1484 virtual void EmitMarshalArgumentCLRToNativeByref()
1489 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1493 EmitSetupSigAndDefaultHomesCLRToNativeByref(true);
1498 EmitLoadManagedHomeAddr(m_pcsMarshal);
1499 EmitStoreNativeHomeAddr(m_pcsMarshal);
1502 // no unmarshaling is necessary since we directly passed the pinned byref to native,
1503 // the argument is therefore automatically in/out
1508 // Similarly to the other direction, ML used ML_COPYPINNEDGCREF on x86 to
1509 // directly pass the unmanaged pointer as a byref argument to managed code.
1510 // This also makes an observable difference (allows passing NULL, changes
1511 // made to the original value during the call are visible in managed).
1513 // This method was changed to pass pointer instead of copy in Dev10 in order
1514 // to match the original ML behavior. Note that in this direction we don't
1515 // need to pin the pointer - if it is pointing to GC heap, it must have been
1516 // pinned on the way to unmanaged.
1518 virtual void EmitMarshalArgumentNativeToCLRByref()
1523 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1527 EmitSetupSigAndDefaultHomesNativeToCLRByref(true);
1532 EmitLoadNativeHomeAddr(m_pcsMarshal);
1533 EmitStoreManagedHomeAddr(m_pcsMarshal);
1536 // no unmarshaling is necessary since we directly passed the pointer to managed
1537 // as a byref, the argument is therefore automatically in/out
1542 template <CorElementType ELEMENT_TYPE, class PROMOTED_ELEMENT>
1543 class ILCopyMarshalerSimple : public ILCopyMarshalerBase
1549 c_nativeSize = sizeof(PROMOTED_ELEMENT),
1550 c_CLRSize = sizeof(PROMOTED_ELEMENT),
1553 bool IsSmallValueTypeSpecialCase()
1556 // Special case for small value types that get
1557 // mapped to MARSHAL_TYPE_GENERIC_8 -- use the
1558 // valuetype type so the JIT is happy.
1561 return (ELEMENT_TYPE ==
1567 ) && (NULL != m_pargs->m_pMT);
1570 bool NeedToPromoteTo8Bytes()
1572 WRAPPER_NO_CONTRACT;
1574 #if defined(_TARGET_AMD64_)
1575 // If the argument is passed by value,
1576 if (!IsByref(m_dwMarshalFlags) && !IsRetval(m_dwMarshalFlags))
1578 // and it is an I4 or an U4,
1579 if ( (ELEMENT_TYPE == ELEMENT_TYPE_I4) ||
1580 (ELEMENT_TYPE == ELEMENT_TYPE_U4) )
1582 // and we are doing a managed-to-unmanaged call,
1583 if (IsCLRToNative(m_dwMarshalFlags))
1585 // then we have to promote the native argument type to an I8 or an U8.
1590 #endif // _TARGET_AMD64_
1595 CorElementType GetConversionType(CorElementType type)
1597 LIMITED_METHOD_CONTRACT;
1599 // I4 <-> I8; U4 <-> U8
1600 if (type == ELEMENT_TYPE_I4)
1602 return ELEMENT_TYPE_I8;
1604 else if (type == ELEMENT_TYPE_U4)
1606 return ELEMENT_TYPE_U8;
1610 return ELEMENT_TYPE_END;
1614 void EmitTypePromotion(ILCodeStream* pslILEmit)
1616 WRAPPER_NO_CONTRACT;
1618 CorElementType promotedType = GetConversionType(ELEMENT_TYPE);
1619 if (promotedType == ELEMENT_TYPE_I8)
1621 pslILEmit->EmitCONV_I8();
1623 else if (promotedType == ELEMENT_TYPE_U8)
1625 pslILEmit->EmitCONV_U8();
1629 virtual LocalDesc GetNativeType()
1631 WRAPPER_NO_CONTRACT;
1633 if (NeedToPromoteTo8Bytes())
1635 return LocalDesc(GetConversionType(ELEMENT_TYPE));
1639 return GetManagedType();
1643 virtual LocalDesc GetManagedType()
1645 WRAPPER_NO_CONTRACT;
1647 if (IsSmallValueTypeSpecialCase())
1649 return LocalDesc(m_pargs->m_pMT);
1653 return LocalDesc(ELEMENT_TYPE);
1657 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1659 STANDARD_VM_CONTRACT;
1661 EmitLoadManagedValue(pslILEmit);
1662 if (NeedToPromoteTo8Bytes())
1664 EmitTypePromotion(pslILEmit);
1666 EmitStoreNativeValue(pslILEmit);
1669 virtual void EmitReInitNative(ILCodeStream* pslILEmit)
1671 STANDARD_VM_CONTRACT;
1673 if (IsSmallValueTypeSpecialCase())
1675 EmitLoadNativeHomeAddr(pslILEmit);
1676 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(m_pargs->m_pMT));
1680 // ldc.i4.0, conv.i8/u8/r4/r8 is shorter than ldc.i8/r4/r8 0
1681 pslILEmit->EmitLDC(0);
1682 pslILEmit->EmitCONV_T(ELEMENT_TYPE);
1684 EmitStoreNativeValue(pslILEmit);
1689 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_I1, INT_PTR> ILCopyMarshaler1;
1690 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_U1, UINT_PTR> ILCopyMarshalerU1;
1691 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_I2, INT_PTR> ILCopyMarshaler2;
1692 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_U2, UINT_PTR> ILCopyMarshalerU2;
1693 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_I4, INT_PTR> ILCopyMarshaler4;
1694 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_U4, UINT_PTR> ILCopyMarshalerU4;
1695 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_I8, INT64> ILCopyMarshaler8;
1696 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_R4, float> ILFloatMarshaler;
1697 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_R8, double> ILDoubleMarshaler;
1699 template <BinderClassID CLASS__ID, class PROMOTED_ELEMENT>
1700 class ILCopyMarshalerKnownStruct : public ILCopyMarshalerBase
1706 c_nativeSize = sizeof(PROMOTED_ELEMENT),
1707 c_CLRSize = sizeof(PROMOTED_ELEMENT),
1710 virtual void EmitReInitNative(ILCodeStream* pslILEmit)
1712 STANDARD_VM_CONTRACT;
1714 EmitLoadNativeHomeAddr(pslILEmit);
1715 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__ID)));
1718 virtual LocalDesc GetNativeType()
1720 STANDARD_VM_CONTRACT;
1722 return LocalDesc(MscorlibBinder::GetClass(CLASS__ID));
1726 typedef ILCopyMarshalerKnownStruct<CLASS__DECIMAL, DECIMAL> ILDecimalMarshaler;
1727 typedef ILCopyMarshalerKnownStruct<CLASS__GUID, GUID> ILGuidMarshaler;
1729 class ILBlittableValueClassMarshaler : public ILCopyMarshalerBase
1735 c_nativeSize = VARIABLESIZE,
1736 c_CLRSize = VARIABLESIZE,
1739 virtual void EmitReInitNative(ILCodeStream* pslILEmit)
1741 STANDARD_VM_CONTRACT;
1743 EmitLoadNativeHomeAddr(pslILEmit);
1744 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(m_pargs->m_pMT));
1747 virtual LocalDesc GetNativeType()
1749 LIMITED_METHOD_CONTRACT;
1751 return LocalDesc(m_pargs->m_pMT);
1756 class ILDelegateMarshaler : public ILMarshaler
1762 c_nativeSize = sizeof(void *),
1763 c_CLRSize = sizeof(OBJECTREF),
1767 virtual LocalDesc GetNativeType();
1768 virtual LocalDesc GetManagedType();
1769 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
1770 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
1773 class ILReflectionObjectMarshaler : public ILMarshaler
1779 c_nativeSize = sizeof(void *),
1780 c_CLRSize = sizeof(OBJECTREF),
1784 virtual LocalDesc GetManagedType();
1785 virtual LocalDesc GetNativeType();
1786 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
1787 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
1788 virtual BinderFieldID GetStructureFieldID() {LIMITED_METHOD_CONTRACT; return (BinderFieldID)0;}
1789 virtual BinderFieldID GetObjectFieldID() = 0;
1790 virtual BinderClassID GetManagedTypeBinderID() = 0;
1793 class ILIRuntimeMethodInfoMarshaler : public ILReflectionObjectMarshaler
1796 virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__STUBMETHODINFO__HANDLE; }
1797 virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__STUBMETHODINFO; }
1800 class ILRuntimeModuleMarshaler : public ILReflectionObjectMarshaler
1803 virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__MODULE__DATA; }
1804 virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__MODULE; }
1807 class ILRuntimeAssemblyMarshaler : public ILReflectionObjectMarshaler
1810 virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__ASSEMBLY__HANDLE; }
1811 virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__ASSEMBLY; }
1814 class ILRuntimeTypeHandleMarshaler : public ILReflectionObjectMarshaler
1817 virtual BinderFieldID GetStructureFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__RT_TYPE_HANDLE__M_TYPE; }
1818 virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__CLASS__TYPEHANDLE; }
1819 virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__RT_TYPE_HANDLE; }
1822 class ILRuntimeMethodHandleMarshaler : public ILReflectionObjectMarshaler
1825 virtual BinderFieldID GetStructureFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__METHOD_HANDLE__METHOD; }
1826 virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__STUBMETHODINFO__HANDLE; }
1827 virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__METHOD_HANDLE; }
1830 class ILRuntimeFieldHandleMarshaler : public ILReflectionObjectMarshaler
1833 virtual BinderFieldID GetStructureFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__FIELD_HANDLE__M_FIELD; }
1834 virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__RT_FIELD_INFO__HANDLE; }
1835 virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__FIELD_HANDLE; }
1838 class ILBoolMarshaler : public ILMarshaler
1842 virtual CorElementType GetNativeBoolElementType() = 0;
1843 virtual int GetNativeTrueValue() = 0;
1844 virtual int GetNativeFalseValue() = 0;
1847 virtual LocalDesc GetNativeType();
1848 virtual LocalDesc GetManagedType();
1849 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
1850 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
1853 class ILWinBoolMarshaler : public ILBoolMarshaler
1859 c_nativeSize = sizeof(BOOL),
1860 c_CLRSize = sizeof(INT8),
1864 virtual CorElementType GetNativeBoolElementType()
1866 LIMITED_METHOD_CONTRACT;
1867 return ELEMENT_TYPE_I4;
1870 virtual int GetNativeTrueValue()
1872 LIMITED_METHOD_CONTRACT;
1876 virtual int GetNativeFalseValue()
1878 LIMITED_METHOD_CONTRACT;
1883 class ILCBoolMarshaler : public ILBoolMarshaler
1889 c_nativeSize = sizeof(BYTE),
1890 c_CLRSize = sizeof(INT8),
1894 virtual CorElementType GetNativeBoolElementType()
1896 LIMITED_METHOD_CONTRACT;
1897 return ELEMENT_TYPE_I1;
1900 virtual int GetNativeTrueValue()
1902 LIMITED_METHOD_CONTRACT;
1906 virtual int GetNativeFalseValue()
1908 LIMITED_METHOD_CONTRACT;
1913 #ifdef FEATURE_COMINTEROP
1914 class ILVtBoolMarshaler : public ILBoolMarshaler
1920 c_nativeSize = sizeof(VARIANT_BOOL),
1921 c_CLRSize = sizeof(INT8),
1925 virtual CorElementType GetNativeBoolElementType()
1927 LIMITED_METHOD_CONTRACT;
1928 return ELEMENT_TYPE_I2;
1931 virtual int GetNativeTrueValue()
1933 LIMITED_METHOD_CONTRACT;
1934 return VARIANT_TRUE;
1937 virtual int GetNativeFalseValue()
1939 LIMITED_METHOD_CONTRACT;
1940 return VARIANT_FALSE;
1943 #endif // FEATURE_COMINTEROP
1945 class ILWSTRMarshaler : public ILMarshaler
1951 c_nativeSize = sizeof(void *),
1952 c_CLRSize = sizeof(OBJECTREF),
1956 bool m_fCoMemoryAllocated;
1960 LIMITED_METHOD_CONTRACT;
1961 m_fCoMemoryAllocated = false;
1966 virtual LocalDesc GetNativeType();
1967 virtual LocalDesc GetManagedType();
1969 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
1970 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
1971 virtual void EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslILEmit);
1972 virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit);
1974 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
1975 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
1976 virtual void EmitConvertSpaceAndContentsNativeToCLR(ILCodeStream* pslILEmit);
1978 virtual bool NeedsClearNative();
1979 virtual void EmitClearNative(ILCodeStream* pslILEmit);
1980 virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit);
1982 static bool CanUsePinnedManagedString(DWORD dwMarshalFlags);
1983 static void EmitCheckManagedStringLength(ILCodeStream* pslILEmit);
1984 static void EmitCheckNativeStringLength(ILCodeStream* pslILEmit);
1987 // A marshaler that makes run-time decision based on argument size whether native space will
1988 // be allocated using localloc or on the heap. The ctor argument is a heap free function.
1989 class ILOptimizedAllocMarshaler : public ILMarshaler
1992 ILOptimizedAllocMarshaler(BinderMethodID clearNat) :
1993 m_idClearNative(clearNat),
1994 m_dwLocalBuffer((DWORD)-1)
1996 LIMITED_METHOD_CONTRACT;
1999 virtual LocalDesc GetNativeType();
2000 virtual bool NeedsClearNative();
2001 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2004 const BinderMethodID m_idClearNative;
2005 DWORD m_dwLocalBuffer; // localloc'ed temp buffer variable or -1 if not used
2008 class ILUTF8BufferMarshaler : public ILOptimizedAllocMarshaler
2014 c_nativeSize = sizeof(void *),
2015 c_CLRSize = sizeof(OBJECTREF),
2020 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2021 MAX_LOCAL_BUFFER_LENGTH = MAX_PATH_FNAME + 1
2024 ILUTF8BufferMarshaler() :
2025 ILOptimizedAllocMarshaler(METHOD__WIN32NATIVE__COTASKMEMFREE)
2027 LIMITED_METHOD_CONTRACT;
2030 virtual LocalDesc GetManagedType();
2031 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
2032 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2033 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
2034 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2037 class ILWSTRBufferMarshaler : public ILOptimizedAllocMarshaler
2043 c_nativeSize = sizeof(void *),
2044 c_CLRSize = sizeof(OBJECTREF),
2049 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2050 MAX_LOCAL_BUFFER_LENGTH = (MAX_PATH_FNAME + 1) * 2
2053 ILWSTRBufferMarshaler() :
2054 ILOptimizedAllocMarshaler(METHOD__WIN32NATIVE__COTASKMEMFREE)
2056 LIMITED_METHOD_CONTRACT;
2059 virtual LocalDesc GetManagedType();
2060 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
2061 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2062 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
2063 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2066 class ILCSTRBufferMarshaler : public ILOptimizedAllocMarshaler
2072 c_nativeSize = sizeof(void *),
2073 c_CLRSize = sizeof(OBJECTREF),
2078 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2079 MAX_LOCAL_BUFFER_LENGTH = MAX_PATH_FNAME + 1
2082 ILCSTRBufferMarshaler() :
2083 ILOptimizedAllocMarshaler(METHOD__WIN32NATIVE__COTASKMEMFREE)
2085 LIMITED_METHOD_CONTRACT;
2088 virtual LocalDesc GetManagedType();
2089 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
2090 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2091 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
2092 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2096 class ILHandleRefMarshaler : public ILMarshaler
2098 // Managed layout for SRI.HandleRef class
2101 OBJECTREF m_wrapper;
2109 c_nativeSize = sizeof(LPVOID),
2110 c_CLRSize = sizeof(HANDLEREF),
2113 LocalDesc GetManagedType()
2115 LIMITED_METHOD_CONTRACT;
2119 LocalDesc GetNativeType()
2121 LIMITED_METHOD_CONTRACT;
2125 static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
2129 BOOL fManagedToNative,
2130 OverrideProcArgs* pargs,
2133 UINT nativeStackOffset);
2135 static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker* psl,
2136 BOOL fManagedToNative,
2138 OverrideProcArgs* pargs,
2142 class ILSafeHandleMarshaler : public ILMarshaler
2148 c_nativeSize = sizeof(LPVOID),
2149 c_CLRSize = sizeof(SAFEHANDLE),
2152 virtual LocalDesc GetManagedType();
2153 virtual LocalDesc GetNativeType();
2155 virtual bool NeedsClearNative();
2156 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2158 virtual void EmitMarshalArgumentCLRToNative();
2160 static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
2164 BOOL fManagedToNative,
2165 OverrideProcArgs* pargs,
2168 UINT nativeStackOffset);
2170 static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker *psl,
2171 BOOL fManagedToNative,
2173 OverrideProcArgs *pargs,
2178 class ILCriticalHandleMarshaler : public ILMarshaler
2184 c_nativeSize = sizeof(LPVOID),
2185 c_CLRSize = sizeof(CRITICALHANDLE),
2190 LocalDesc GetManagedType()
2192 LIMITED_METHOD_CONTRACT;
2196 LocalDesc GetNativeType()
2198 LIMITED_METHOD_CONTRACT;
2202 static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
2206 BOOL fManagedToNative,
2207 OverrideProcArgs* pargs,
2210 UINT nativeStackOffset);
2212 static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker *psl,
2213 BOOL fManagedToNative,
2215 OverrideProcArgs *pargs,
2220 class ILValueClassMarshaler : public ILMarshaler
2226 c_nativeSize = VARIABLESIZE,
2227 c_CLRSize = VARIABLESIZE,
2231 virtual LocalDesc GetNativeType();
2232 virtual LocalDesc GetManagedType();
2233 virtual void EmitReInitNative(ILCodeStream* pslILEmit);
2234 virtual bool NeedsClearNative();
2235 virtual void EmitClearNative(ILCodeStream * pslILEmit);
2236 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2237 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2240 #ifdef FEATURE_COMINTEROP
2241 class ILObjectMarshaler : public ILMarshaler
2247 c_CLRSize = sizeof(OBJECTREF),
2248 c_nativeSize = sizeof(VARIANT),
2252 virtual LocalDesc GetNativeType();
2253 virtual LocalDesc GetManagedType();
2254 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2255 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2256 virtual bool NeedsClearNative();
2257 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2258 virtual void EmitReInitNative(ILCodeStream* pslILEmit);
2260 #endif // FEATURE_COMINTEROP
2262 class ILDateMarshaler : public ILMarshaler
2268 c_nativeSize = sizeof(DATE),
2269 c_CLRSize = sizeof(INT64),
2273 virtual LocalDesc GetNativeType();
2274 virtual LocalDesc GetManagedType();
2275 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2276 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2277 virtual void EmitReInitNative(ILCodeStream* pslILEmit);
2281 class ILCurrencyMarshaler : public ILMarshaler
2287 c_nativeSize = sizeof(CURRENCY),
2288 c_CLRSize = sizeof(DECIMAL),
2292 virtual LocalDesc GetNativeType();
2293 virtual LocalDesc GetManagedType();
2294 virtual void EmitReInitNative(ILCodeStream* pslILEmit);
2295 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2296 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2300 #ifdef FEATURE_COMINTEROP
2301 class ILInterfaceMarshaler : public ILMarshaler
2307 c_nativeSize = sizeof(void *),
2308 c_CLRSize = sizeof(OBJECTREF),
2312 virtual LocalDesc GetNativeType();
2313 virtual LocalDesc GetManagedType();
2314 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2315 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2316 virtual bool NeedsClearNative();
2317 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2319 #endif // FEATURE_COMINTEROP
2322 class ILAnsiCharMarshaler : public ILMarshaler
2328 c_nativeSize = sizeof(UINT8),
2329 c_CLRSize = sizeof(UINT16),
2333 virtual LocalDesc GetNativeType();
2334 virtual LocalDesc GetManagedType();
2335 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2336 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2340 template <BinderClassID CLASS__ID, class ELEMENT>
2341 class ILValueClassPtrMarshaler : public ILMarshaler
2347 c_nativeSize = sizeof(ELEMENT *),
2348 c_CLRSize = sizeof(ELEMENT),
2352 virtual LocalDesc GetNativeType()
2354 LIMITED_METHOD_CONTRACT;
2357 // pointer to value class
2359 return LocalDesc(ELEMENT_TYPE_I);
2362 virtual LocalDesc GetManagedType()
2364 STANDARD_VM_CONTRACT;
2369 return LocalDesc(MscorlibBinder::GetClass(CLASS__ID));
2372 virtual bool NeedsClearNative()
2374 LIMITED_METHOD_CONTRACT;
2375 return (IsByref(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags));
2378 virtual void EmitClearNative(ILCodeStream* pslILEmit)
2380 STANDARD_VM_CONTRACT;
2382 EmitLoadNativeValue(pslILEmit);
2383 // static void CoTaskMemFree(IntPtr ptr)
2384 pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
2387 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
2389 STANDARD_VM_CONTRACT;
2391 if (NeedsClearNative())
2393 pslILEmit->EmitLDC(sizeof(ELEMENT));
2394 pslILEmit->EmitCONV_U();
2395 // static IntPtr CoTaskMemAlloc(UIntPtr cb)
2396 pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMALLOC, 1, 1);
2397 EmitStoreNativeValue(pslILEmit);
2401 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2403 STANDARD_VM_CONTRACT;
2405 if (NeedsClearNative())
2407 EmitLoadNativeValue(pslILEmit); // dest
2408 EmitLoadManagedHomeAddr(pslILEmit); // src
2409 pslILEmit->EmitCPOBJ(pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__ID)));
2413 EmitLoadManagedHomeAddr(pslILEmit);
2414 EmitStoreNativeValue(pslILEmit);
2418 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2420 STANDARD_VM_CONTRACT;
2422 int tokType = pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__ID));
2423 ILCodeLabel *pNullLabel = pslILEmit->NewCodeLabel();
2424 ILCodeLabel *pJoinLabel = pslILEmit->NewCodeLabel();
2426 EmitLoadNativeValue(pslILEmit);
2427 pslILEmit->EmitBRFALSE(pNullLabel);
2429 // the incoming pointer is non-null -> dereference it and copy the struct
2430 EmitLoadManagedHomeAddr(pslILEmit); // dest
2431 EmitLoadNativeValue(pslILEmit); // src
2432 pslILEmit->EmitCPOBJ(tokType);
2434 pslILEmit->EmitBR(pJoinLabel);
2436 // the incoming pointer is null -> just initobj (i.e. zero) the struct
2437 pslILEmit->EmitLabel(pNullLabel);
2439 EmitLoadManagedHomeAddr(pslILEmit);
2440 pslILEmit->EmitINITOBJ(tokType);
2442 pslILEmit->EmitLabel(pJoinLabel);
2446 typedef ILValueClassPtrMarshaler<CLASS__GUID, GUID> ILGuidPtrMarshaler;
2447 typedef ILValueClassPtrMarshaler<CLASS__DECIMAL, DECIMAL> ILDecimalPtrMarshaler;
2449 #ifdef FEATURE_COMINTEROP
2450 class ILOleColorMarshaler : public ILMarshaler
2456 c_nativeSize = sizeof(OLE_COLOR),
2457 c_CLRSize = sizeof(SYSTEMCOLOR),
2461 virtual LocalDesc GetNativeType();
2462 virtual LocalDesc GetManagedType();
2463 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2464 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2467 class ILVBByValStrWMarshaler : public ILMarshaler
2473 c_nativeSize = sizeof(BSTR),
2474 c_CLRSize = sizeof(OBJECTREF*),
2479 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2480 MAX_LOCAL_BUFFER_LENGTH = (MAX_PATH_FNAME + 1) * 2 + sizeof(DWORD)
2484 ILVBByValStrWMarshaler() :
2486 ,m_dwLocalBuffer(-1)
2488 LIMITED_METHOD_CONTRACT;
2491 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2492 virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2495 virtual LocalDesc GetNativeType();
2496 virtual LocalDesc GetManagedType();
2497 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2498 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2499 virtual bool NeedsClearNative();
2500 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2501 virtual bool IsNativePassedByRef();
2504 DWORD m_dwLocalBuffer;
2507 class ILVBByValStrMarshaler : public ILMarshaler
2513 c_nativeSize = sizeof(LPSTR),
2514 c_CLRSize = sizeof(OBJECTREF *),
2517 ILVBByValStrMarshaler() :
2520 LIMITED_METHOD_CONTRACT;
2523 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2524 virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2527 virtual LocalDesc GetNativeType();
2528 virtual LocalDesc GetManagedType();
2529 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2530 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2531 virtual bool NeedsClearNative();
2532 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2533 virtual bool IsNativePassedByRef();
2538 class ILHSTRINGMarshaler : public ILMarshaler
2544 c_nativeSize = sizeof(HSTRING),
2545 c_CLRSize = sizeof(OBJECTREF),
2549 virtual LocalDesc GetNativeType();
2550 virtual LocalDesc GetManagedType();
2552 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2553 void EmitConvertCLRToHSTRINGReference(ILCodeStream* pslILEmit);
2554 void EmitConvertCLRToHSTRING(ILCodeStream* pslILEmit);
2556 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2558 virtual bool NeedsClearNative();
2559 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2561 #endif // FEATURE_COMINTEROP
2564 class ILCUTF8Marshaler : public ILOptimizedAllocMarshaler
2570 c_nativeSize = sizeof(void *),
2571 c_CLRSize = sizeof(OBJECTREF),
2576 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2577 MAX_LOCAL_BUFFER_LENGTH = MAX_PATH_FNAME + 1
2580 ILCUTF8Marshaler() :
2581 ILOptimizedAllocMarshaler(METHOD__CSTRMARSHALER__CLEAR_NATIVE)
2583 LIMITED_METHOD_CONTRACT;
2587 virtual LocalDesc GetManagedType();
2588 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2589 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2594 class ILCSTRMarshaler : public ILOptimizedAllocMarshaler
2600 c_nativeSize = sizeof(void *),
2601 c_CLRSize = sizeof(OBJECTREF),
2606 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2607 MAX_LOCAL_BUFFER_LENGTH = MAX_PATH_FNAME + 1
2611 ILOptimizedAllocMarshaler(METHOD__CSTRMARSHALER__CLEAR_NATIVE)
2613 LIMITED_METHOD_CONTRACT;
2617 virtual LocalDesc GetManagedType();
2618 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2619 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2622 #ifdef FEATURE_COMINTEROP
2623 class ILBSTRMarshaler : public ILOptimizedAllocMarshaler
2629 c_nativeSize = sizeof(void *),
2630 c_CLRSize = sizeof(OBJECTREF),
2635 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2636 MAX_LOCAL_BUFFER_LENGTH = (MAX_PATH_FNAME + 1) * 2 + 4
2640 ILOptimizedAllocMarshaler(METHOD__BSTRMARSHALER__CLEAR_NATIVE)
2642 LIMITED_METHOD_CONTRACT;
2646 virtual LocalDesc GetManagedType();
2647 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2648 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2652 class ILAnsiBSTRMarshaler : public ILMarshaler
2658 c_nativeSize = sizeof(void *),
2659 c_CLRSize = sizeof(OBJECTREF),
2663 virtual LocalDesc GetNativeType();
2664 virtual LocalDesc GetManagedType();
2665 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2666 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2667 virtual bool NeedsClearNative();
2668 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2670 #endif // FEATURE_COMINTEROP
2672 class ILLayoutClassPtrMarshalerBase : public ILMarshaler
2677 c_nativeSize = sizeof(void *),
2678 c_CLRSize = sizeof(OBJECTREF),
2682 virtual LocalDesc GetNativeType();
2683 virtual LocalDesc GetManagedType();
2684 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
2685 virtual void EmitConvertSpaceCLRToNativeTemp(ILCodeStream* pslILEmit);
2686 virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit);
2687 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
2688 virtual bool NeedsClearNative();
2689 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2690 virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit);
2693 class ILLayoutClassPtrMarshaler : public ILLayoutClassPtrMarshalerBase
2702 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2703 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2704 virtual void EmitClearNativeContents(ILCodeStream * pslILEmit);
2707 class ILBlittablePtrMarshaler : public ILLayoutClassPtrMarshalerBase
2716 virtual void EmitMarshalArgumentCLRToNative();
2717 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2718 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2724 class ILArgIteratorMarshaler : public ILMarshaler
2730 c_nativeSize = sizeof(va_list),
2731 c_CLRSize = sizeof(VARARGS),
2735 virtual LocalDesc GetNativeType();
2736 virtual LocalDesc GetManagedType();
2737 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2738 virtual void EmitMarshalArgumentCLRToNative();
2739 virtual void EmitMarshalArgumentNativeToCLR();
2742 class ILArrayWithOffsetMarshaler : public ILMarshaler
2748 c_nativeSize = sizeof(LPVOID),
2749 c_CLRSize = sizeof(ArrayWithOffsetData),
2752 ILArrayWithOffsetMarshaler() :
2753 m_dwCountLocalNum(-1),
2754 m_dwOffsetLocalNum(-1),
2755 m_dwPinnedLocalNum(-1)
2757 LIMITED_METHOD_CONTRACT;
2761 virtual LocalDesc GetNativeType();
2762 virtual LocalDesc GetManagedType();
2763 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2765 virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit);
2766 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2767 virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit);
2770 DWORD m_dwCountLocalNum;
2771 DWORD m_dwOffsetLocalNum;
2772 DWORD m_dwPinnedLocalNum;
2775 class ILAsAnyMarshalerBase : public ILMarshaler
2780 c_nativeSize = sizeof(void *),
2781 c_CLRSize = sizeof(OBJECTREF),
2784 ILAsAnyMarshalerBase() :
2785 m_dwMarshalerLocalNum(-1)
2787 LIMITED_METHOD_CONTRACT;
2791 static const BYTE ML_IN = 0x10;
2792 static const BYTE ML_OUT = 0x20;
2794 virtual bool IsAnsi() = 0;
2795 virtual LocalDesc GetNativeType();
2796 virtual LocalDesc GetManagedType();
2797 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2798 virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2799 virtual void EmitMarshalArgumentCLRToNative();
2800 virtual bool NeedsClearNative();
2801 virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit);
2803 DWORD m_dwMarshalerLocalNum;
2806 class ILAsAnyWMarshaler : public ILAsAnyMarshalerBase
2815 virtual bool IsAnsi()
2821 class ILAsAnyAMarshaler : public ILAsAnyMarshalerBase
2830 virtual bool IsAnsi()
2837 class ILMngdMarshaler : public ILMarshaler
2842 c_nativeSize = sizeof(void *),
2843 c_CLRSize = sizeof(OBJECTREF),
2846 ILMngdMarshaler(BinderMethodID space2Man,
2847 BinderMethodID contents2Man,
2848 BinderMethodID space2Nat,
2849 BinderMethodID contents2Nat,
2850 BinderMethodID clearNat,
2851 BinderMethodID clearNatContents,
2852 BinderMethodID clearMan) :
2853 m_idConvertSpaceToManaged(space2Man),
2854 m_idConvertContentsToManaged(contents2Man),
2855 m_idConvertSpaceToNative(space2Nat),
2856 m_idConvertContentsToNative(contents2Nat),
2857 m_idClearNative(clearNat),
2858 m_idClearNativeContents(clearNatContents),
2859 m_idClearManaged(clearMan)
2861 LIMITED_METHOD_CONTRACT;
2865 virtual LocalDesc GetNativeType();
2866 virtual LocalDesc GetManagedType();
2868 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) = 0;
2870 virtual void EmitCallMngdMarshalerMethod(ILCodeStream* pslILEmit, MethodDesc *pMD);
2872 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
2874 WRAPPER_NO_CONTRACT;
2875 EmitCallMngdMarshalerMethod(pslILEmit, GetConvertSpaceToManagedMethod());
2878 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2880 WRAPPER_NO_CONTRACT;
2881 EmitCallMngdMarshalerMethod(pslILEmit, GetConvertContentsToManagedMethod());
2884 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
2886 WRAPPER_NO_CONTRACT;
2887 EmitCallMngdMarshalerMethod(pslILEmit, GetConvertSpaceToNativeMethod());
2890 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2892 WRAPPER_NO_CONTRACT;
2893 EmitCallMngdMarshalerMethod(pslILEmit, GetConvertContentsToNativeMethod());
2896 virtual bool NeedsClearNative()
2898 LIMITED_METHOD_CONTRACT;
2900 if (NULL != GetClearNativeMethod())
2908 virtual void EmitClearNative(ILCodeStream* pslILEmit)
2910 WRAPPER_NO_CONTRACT;
2911 EmitCallMngdMarshalerMethod(pslILEmit, GetClearNativeMethod());
2914 virtual void EmitClearNativeContents(ILCodeStream* pslILEmit)
2916 WRAPPER_NO_CONTRACT;
2917 EmitCallMngdMarshalerMethod(pslILEmit, GetClearNativeContentsMethod());
2921 virtual bool NeedsClearCLR()
2923 LIMITED_METHOD_CONTRACT;
2925 if (NULL != GetClearManagedMethod())
2933 virtual void EmitClearCLR(ILCodeStream* pslILEmit)
2935 WRAPPER_NO_CONTRACT;
2936 EmitCallMngdMarshalerMethod(pslILEmit, GetClearManagedMethod());
2939 virtual MethodDesc *GetConvertSpaceToManagedMethod() { WRAPPER_NO_CONTRACT; return (m_idConvertSpaceToManaged == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idConvertSpaceToManaged)); }
2940 virtual MethodDesc *GetConvertContentsToManagedMethod() { WRAPPER_NO_CONTRACT; return (m_idConvertContentsToManaged == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idConvertContentsToManaged)); }
2941 virtual MethodDesc *GetConvertSpaceToNativeMethod() { WRAPPER_NO_CONTRACT; return (m_idConvertSpaceToNative == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idConvertSpaceToNative)); }
2942 virtual MethodDesc *GetConvertContentsToNativeMethod() { WRAPPER_NO_CONTRACT; return (m_idConvertContentsToNative == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idConvertContentsToNative)); }
2943 virtual MethodDesc *GetClearNativeMethod() { WRAPPER_NO_CONTRACT; return (m_idClearNative == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idClearNative)); }
2944 virtual MethodDesc *GetClearNativeContentsMethod() { WRAPPER_NO_CONTRACT; return (m_idClearNativeContents == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idClearNativeContents)); }
2945 virtual MethodDesc *GetClearManagedMethod() { WRAPPER_NO_CONTRACT; return (m_idClearManaged == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idClearManaged)); }
2947 const BinderMethodID m_idConvertSpaceToManaged;
2948 const BinderMethodID m_idConvertContentsToManaged;
2949 const BinderMethodID m_idConvertSpaceToNative;
2950 const BinderMethodID m_idConvertContentsToNative;
2951 const BinderMethodID m_idClearNative;
2952 const BinderMethodID m_idClearNativeContents;
2953 const BinderMethodID m_idClearManaged;
2956 class ILNativeArrayMarshaler : public ILMngdMarshaler
2964 ILNativeArrayMarshaler() :
2966 METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CONVERT_SPACE_TO_MANAGED,
2967 METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED,
2968 METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CONVERT_SPACE_TO_NATIVE,
2969 METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE,
2970 METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CLEAR_NATIVE,
2971 METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CLEAR_NATIVE_CONTENTS,
2975 LIMITED_METHOD_CONTRACT;
2976 m_dwSavedSizeArg = LOCAL_NUM_UNUSED;
2979 virtual void EmitMarshalArgumentCLRToNative();
2980 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
2981 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
2982 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2983 virtual void EmitClearNativeContents(ILCodeStream* pslILEmit);
2984 virtual void EmitMarshalArgumentNativeToCLRByref();
2985 virtual void EmitMarshalArgumentCLRToNativeByref();
2989 bool UsePinnedArraySpecialCase();
2991 BOOL CheckSizeParamIndexArg(const CREATE_MARSHALER_CARRAY_OPERANDS &mops, CorElementType *pElementType);
2993 // Calculate element count and load it on evaluation stack
2994 void EmitLoadElementCount(ILCodeStream* pslILEmit);
2996 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
2998 void EmitLoadNativeSize(ILCodeStream* pslILEmit);
2999 void EmitNewSavedSizeArgLocal();
3002 DWORD m_dwSavedSizeArg;
3005 class MngdNativeArrayMarshaler
3008 static FCDECL3(void, CreateMarshaler, MngdNativeArrayMarshaler* pThis, MethodTable* pMT, UINT32 dwFlags);
3009 static FCDECL3(void, ConvertSpaceToNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3010 static FCDECL3(void, ConvertContentsToNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3011 static FCDECL4(void, ConvertSpaceToManaged, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements);
3012 static FCDECL3(void, ConvertContentsToManaged, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3013 static FCDECL3(void, ClearNative, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
3014 static FCDECL3(void, ClearNativeContents, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
3016 static void DoClearNativeContents(MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
3020 FLAG_NATIVE_DATA_VALID = 0x40000000
3023 MethodTable* m_pElementMT;
3025 BOOL m_NativeDataValid;
3027 BOOL m_ThrowOnUnmappableChar;
3032 #ifdef FEATURE_COMINTEROP
3033 class ILSafeArrayMarshaler : public ILMngdMarshaler
3041 ILSafeArrayMarshaler() :
3043 METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_SPACE_TO_MANAGED,
3044 METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED,
3045 METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_SPACE_TO_NATIVE,
3046 METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE,
3047 METHOD__MNGD_SAFE_ARRAY_MARSHALER__CLEAR_NATIVE,
3051 m_dwOriginalManagedLocalNum(-1)
3053 LIMITED_METHOD_CONTRACT;
3058 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
3059 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3060 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3062 virtual void EmitReInitNative(ILCodeStream* pslILEmit)
3071 if (NeedsCheckForStatic() && pslILEmit->GetStreamType() != ILStubLinker::kExceptionCleanup)
3073 // Keep the original value in native home as we are not going to allocate a new
3074 // one. If we cleared it here, we wouldn't be able to ConvertContentsToNative.
3075 // Always perform the real re-init in the ExceptionCleanup stream so the caller
3076 // doesn't get back garbage.
3080 ILMngdMarshaler::EmitReInitNative(pslILEmit);
3084 bool NeedsCheckForStatic()
3086 WRAPPER_NO_CONTRACT;
3087 return IsByref(m_dwMarshalFlags) && !IsCLRToNative(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags);
3090 DWORD m_dwOriginalManagedLocalNum;
3093 class MngdSafeArrayMarshaler
3096 static FCDECL4(void, CreateMarshaler, MngdSafeArrayMarshaler* pThis, MethodTable* pMT, UINT32 iRank, UINT32 dwFlags);
3097 static FCDECL3(void, ConvertSpaceToNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3098 static FCDECL4(void, ConvertContentsToNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, Object* pOriginalManagedUNSAFE);
3099 static FCDECL3(void, ConvertSpaceToManaged, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3100 static FCDECL3(void, ConvertContentsToManaged, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3101 static FCDECL3(void, ClearNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3103 enum StaticCheckStateFlags
3105 SCSF_CheckForStatic = 1,
3107 SCSF_NativeDataValid = 4
3110 MethodTable* m_pElementMT;
3113 BYTE m_fStatic; // StaticCheckStateFlags
3114 BYTE m_nolowerbounds;
3117 class ILHiddenLengthArrayMarshaler : public ILMngdMarshaler
3119 friend class MngdHiddenLengthArrayMarshaler;
3124 c_nativeSize = sizeof(LPVOID),
3125 c_CLRSize = sizeof(OBJECTREF),
3129 ILHiddenLengthArrayMarshaler() :
3130 ILMngdMarshaler(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_SPACE_TO_MANAGED,
3131 METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED,
3132 METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_SPACE_TO_NATIVE,
3133 METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE,
3134 METHOD__WIN32NATIVE__COTASKMEMFREE,
3135 METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CLEAR_NATIVE_CONTENTS,
3138 LIMITED_METHOD_CONTRACT;
3139 m_dwMngdMarshalerLocalNum = -1;
3143 virtual LocalDesc GetNativeType();
3144 virtual LocalDesc GetManagedType();
3146 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
3147 virtual void EmitMarshalArgumentCLRToNative();
3148 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
3149 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
3150 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3151 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3152 virtual void EmitClearNative(ILCodeStream* pslILEmit);
3153 virtual void EmitClearNativeContents(ILCodeStream* pslILEmit);
3156 bool CanUsePinnedArray();
3157 void EmitLoadNativeArrayLength(ILCodeStream *pslILEmit);
3159 virtual MethodDesc *GetConvertContentsToManagedMethod();
3160 virtual MethodDesc *GetConvertContentsToNativeMethod();
3161 virtual MethodDesc *GetClearNativeContentsMethod();
3163 MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD);
3166 class MngdHiddenLengthArrayMarshaler
3169 static FCDECL4(void, CreateMarshaler, MngdHiddenLengthArrayMarshaler* pThis, MethodTable* pMT, SIZE_T cbElement, UINT16 vt);
3170 static FCDECL3(void, ConvertSpaceToNative, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3171 static FCDECL3(void, ConvertContentsToNative, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3172 static FCDECL4(void, ConvertSpaceToManaged, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements);
3173 static FCDECL3(void, ConvertContentsToManaged, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3174 static FCDECL3(void, ClearNativeContents, MngdHiddenLengthArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
3178 SIZE_T GetArraySize(SIZE_T elements);
3179 void DoClearNativeContents(void** pNativeHome, INT32 cElements);
3182 MethodTable *m_pElementMT;
3183 SIZE_T m_cbElementSize;
3186 #endif // FEATURE_COMINTEROP
3189 class ILReferenceCustomMarshaler : public ILMngdMarshaler
3197 ILReferenceCustomMarshaler() :
3200 METHOD__MNGD_REF_CUSTOM_MARSHALER__CONVERT_CONTENTS_TO_MANAGED,
3202 METHOD__MNGD_REF_CUSTOM_MARSHALER__CONVERT_CONTENTS_TO_NATIVE,
3203 METHOD__MNGD_REF_CUSTOM_MARSHALER__CLEAR_NATIVE,
3205 METHOD__MNGD_REF_CUSTOM_MARSHALER__CLEAR_MANAGED
3208 LIMITED_METHOD_CONTRACT;
3212 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
3215 class MngdRefCustomMarshaler
3218 static FCDECL2(void, CreateMarshaler, MngdRefCustomMarshaler* pThis, void* pCMHelper);
3219 static FCDECL3(void, ConvertContentsToNative, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3220 static FCDECL3(void, ConvertContentsToManaged, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3221 static FCDECL3(void, ClearNative, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3222 static FCDECL3(void, ClearManaged, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3224 static void DoClearNativeContents(MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3226 CustomMarshalerHelper* m_pCMHelper;
3230 #ifdef FEATURE_COMINTEROP
3231 class ILUriMarshaler : public ILMarshaler
3237 c_nativeSize = sizeof(LPVOID),
3238 c_CLRSize = sizeof(OBJECTREF),
3241 static void EmitConvertCLRUriToWinRTUri(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3242 static void EmitConvertWinRTUriToCLRUri(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3245 virtual LocalDesc GetNativeType();
3246 virtual LocalDesc GetManagedType();
3248 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3249 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3251 virtual bool NeedsClearNative();
3252 void EmitClearNative(ILCodeStream* pslILEmit);
3255 class ILNCCEventArgsMarshaler : public ILMarshaler
3261 c_nativeSize = sizeof(LPVOID),
3262 c_CLRSize = sizeof(OBJECTREF),
3265 static void EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3266 static void EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3269 virtual LocalDesc GetNativeType();
3270 virtual LocalDesc GetManagedType();
3272 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3273 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3275 virtual bool NeedsClearNative();
3276 void EmitClearNative(ILCodeStream* pslILEmit);
3279 class ILPCEventArgsMarshaler : public ILMarshaler
3285 c_nativeSize = sizeof(LPVOID),
3286 c_CLRSize = sizeof(OBJECTREF),
3289 static void EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3290 static void EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3293 virtual LocalDesc GetNativeType();
3294 virtual LocalDesc GetManagedType();
3296 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3297 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3299 virtual bool NeedsClearNative();
3300 void EmitClearNative(ILCodeStream* pslILEmit);
3303 class ILDateTimeMarshaler : public ILMarshaler
3309 c_nativeSize = sizeof(INT64), // = sizeof(Windows::Foundation::DateTime)
3310 c_CLRSize = VARIABLESIZE,
3314 virtual LocalDesc GetNativeType();
3315 virtual LocalDesc GetManagedType();
3317 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3318 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3320 virtual bool NeedsClearNative();
3321 virtual void EmitReInitNative(ILCodeStream* pslILEmit);
3324 class ILNullableMarshaler : public ILMarshaler
3330 c_nativeSize = sizeof(LPVOID),
3331 c_CLRSize = VARIABLESIZE,
3335 virtual LocalDesc GetNativeType();
3336 virtual LocalDesc GetManagedType();
3337 virtual bool NeedsClearNative();
3338 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3339 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3340 virtual void EmitClearNative(ILCodeStream* pslILEmit);
3343 MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD);
3346 class ILSystemTypeMarshaler : public ILMarshaler
3352 c_nativeSize = sizeof(TypeNameNative),
3353 c_CLRSize = sizeof(OBJECTREF)
3357 virtual LocalDesc GetNativeType();
3358 virtual LocalDesc GetManagedType();
3360 virtual void EmitConvertContentsCLRToNative(ILCodeStream * pslILEmit);
3361 virtual void EmitConvertContentsNativeToCLR(ILCodeStream * pslILEmit);
3363 virtual bool NeedsClearNative();
3364 virtual void EmitClearNative(ILCodeStream * pslILEmit);
3365 virtual void EmitReInitNative(ILCodeStream * pslILEmit);
3368 class ILHResultExceptionMarshaler : public ILMarshaler
3374 c_nativeSize = sizeof(INT32), // = sizeof(Windows::Foundation::HResult)
3375 c_CLRSize = sizeof(OBJECTREF),
3379 virtual LocalDesc GetNativeType();
3380 virtual LocalDesc GetManagedType();
3382 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3383 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3385 virtual bool NeedsClearNative();
3388 class ILKeyValuePairMarshaler : public ILMarshaler
3394 c_nativeSize = sizeof(LPVOID),
3395 c_CLRSize = VARIABLESIZE,
3399 virtual LocalDesc GetNativeType();
3400 virtual LocalDesc GetManagedType();
3401 virtual bool NeedsClearNative();
3402 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3403 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3404 virtual void EmitClearNative(ILCodeStream* pslILEmit);
3407 MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD);
3410 #endif // FEATURE_COMINTEROP