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.
612 case 1: typ = ELEMENT_TYPE_U1; break;
613 case 2: typ = ELEMENT_TYPE_U2; break;
614 case 4: typ = ELEMENT_TYPE_U4; break;
615 case 8: typ = ELEMENT_TYPE_U8; break;
616 default: byrefNativeReturn = true; break;
621 if (IsHresultSwap(dwMarshalFlags) || (byrefNativeReturn && IsCLRToNative(dwMarshalFlags)))
623 LocalDesc extraParamType = nativeType;
624 extraParamType.MakeByRef();
626 m_pcsMarshal->SetStubTargetArgType(&extraParamType, false);
628 if (IsHresultSwap(dwMarshalFlags))
630 // HRESULT swapping: the original return value is transformed into an extra
631 // byref parameter and the target is expected to return an HRESULT
632 m_pcsMarshal->SetStubTargetReturnType(ELEMENT_TYPE_I4); // native method returns an HRESULT
636 // byref structure return: the original return value is transformed into an
637 // extra byref parameter and the target is not expected to return anything
639 // note: we do this only for forward calls because [unmanaged calling conv.
640 // uses byref return] implies [managed calling conv. uses byref return]
641 m_pcsMarshal->SetStubTargetReturnType(ELEMENT_TYPE_VOID);
646 if (typ != ELEMENT_TYPE_VOID)
648 // small structure return: the original return value is transformed into
649 // ELEMENT_TYPE_U1, ELEMENT_TYPE_U2, ELEMENT_TYPE_U4, or ELEMENT_TYPE_U8
650 m_pcsMarshal->SetStubTargetReturnType(typ);
654 m_pcsMarshal->SetStubTargetReturnType(&nativeType);
658 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(managedType));
659 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(nativeType));
661 EmitCreateMngdMarshaler(m_pcsMarshal);
663 if (IsCLRToNative(dwMarshalFlags))
665 if (IsHresultSwap(dwMarshalFlags) || byrefNativeReturn)
667 EmitReInitNative(m_pcsMarshal);
668 EmitLoadNativeHomeAddr(pcsDispatch); // load up the byref native type as an extra arg
672 if (typ != ELEMENT_TYPE_VOID)
674 // small structure forward: the returned integer is memcpy'd into native home
677 DWORD dwTempLocalNum = m_pcsUnmarshal->NewLocal(typ);
678 m_pcsUnmarshal->EmitSTLOC(dwTempLocalNum);
681 m_nativeHome.EmitLoadHomeAddr(m_pcsUnmarshal);
682 m_pcsUnmarshal->EmitLDLOCA(dwTempLocalNum);
683 m_pcsUnmarshal->EmitLDC(nativeSize);
684 m_pcsUnmarshal->EmitCPBLK();
688 EmitStoreNativeValue(m_pcsUnmarshal);
692 if (NeedsMarshalCleanupIndex())
694 m_pslNDirect->EmitSetArgMarshalIndex(m_pcsUnmarshal, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx);
697 EmitConvertSpaceAndContentsNativeToCLR(m_pcsUnmarshal);
699 EmitCleanupCLRToNative();
701 EmitLoadManagedValue(m_pcsUnmarshal);
705 EmitStoreManagedValue(m_pcsUnmarshal);
707 if (NeedsMarshalCleanupIndex())
709 m_pslNDirect->EmitSetArgMarshalIndex(m_pcsUnmarshal, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx);
712 if (IsHresultSwap(dwMarshalFlags))
714 // we have to skip unmarshaling return value into the HRESULT-swapped argument
715 // if the argument came as NULL (otherwise we would leak unmanaged resources as
716 // we have no way of passing them back to the caller)
717 ILCodeLabel *pSkipConversionLabel = m_pcsUnmarshal->NewCodeLabel();
719 m_pcsUnmarshal->EmitLDARG(argidx);
720 m_pcsUnmarshal->EmitBRFALSE(pSkipConversionLabel);
721 EmitConvertSpaceAndContentsCLRToNative(m_pcsUnmarshal);
722 m_pcsUnmarshal->EmitLabel(pSkipConversionLabel);
726 EmitConvertSpaceAndContentsCLRToNative(m_pcsUnmarshal);
729 if (NeedsUnmarshalCleanupIndex())
731 // if an exception is thrown after this point, we will clean up the unmarshaled retval
732 m_pslNDirect->EmitSetArgMarshalIndex(m_pcsUnmarshal, NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL);
735 EmitCleanupNativeToCLR();
737 if (IsHresultSwap(dwMarshalFlags))
739 // we tolerate NULL here mainly for backward compatibility reasons
740 m_nativeHome.EmitCopyToByrefArgWithNullCheck(m_pcsUnmarshal, &nativeType, argidx);
741 m_pcsUnmarshal->EmitLDC(S_OK);
745 if (typ != ELEMENT_TYPE_VOID)
747 // small structure return (reverse): native home of the structure is memcpy'd
748 // into the integer to be returned from the stub
750 DWORD dwTempLocalNum = m_pcsUnmarshal->NewLocal(typ);
753 m_pcsUnmarshal->EmitLDLOCA(dwTempLocalNum);
754 m_nativeHome.EmitLoadHomeAddr(m_pcsUnmarshal);
755 m_pcsUnmarshal->EmitLDC(nativeSize);
756 m_pcsUnmarshal->EmitCPBLK();
758 m_pcsUnmarshal->EmitLDLOC(dwTempLocalNum);
762 EmitLoadNativeValue(m_pcsUnmarshal);
766 // make sure we free (and zero) the return value if an exception is thrown
767 EmitExceptionCleanupNativeToCLR();
774 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
776 LIMITED_METHOD_CONTRACT;
779 virtual void EmitLoadMngdMarshaler(ILCodeStream* pslILEmit)
789 CONSISTENCY_CHECK((DWORD)-1 != m_dwMngdMarshalerLocalNum);
790 pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
793 void EmitSetupSigAndDefaultHomesCLRToNative()
798 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
802 LocalDesc nativeArgType = GetNativeType();
803 DWORD dwNativeHomeLocalNum = m_pcsMarshal->NewLocal(nativeArgType);
804 m_pcsMarshal->SetStubTargetArgType(&nativeArgType);
806 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILArgument, m_argidx);
807 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, dwNativeHomeLocalNum);
810 void EmitCleanupCLRToNativeTemp()
812 STANDARD_VM_CONTRACT;
814 if (NeedsClearNative())
816 CONSISTENCY_CHECK(NeedsMarshalCleanupIndex());
818 ILCodeStream* pcsCleanup = m_pslNDirect->GetCleanupCodeStream();
819 ILCodeLabel* pSkipClearNativeLabel = pcsCleanup->NewCodeLabel();
821 m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
822 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx,
823 NDirectStubLinker::BranchIfNotMarshaled,
824 pSkipClearNativeLabel);
826 EmitClearNativeTemp(pcsCleanup);
827 pcsCleanup->EmitLabel(pSkipClearNativeLabel);
831 void EmitCleanupCLRToNative()
833 STANDARD_VM_CONTRACT;
835 if (NeedsClearNative())
837 CONSISTENCY_CHECK(NeedsMarshalCleanupIndex());
839 ILCodeStream* pcsCleanup = m_pslNDirect->GetCleanupCodeStream();
840 ILCodeLabel* pSkipClearNativeLabel = pcsCleanup->NewCodeLabel();
842 m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
843 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx,
844 NDirectStubLinker::BranchIfNotMarshaled,
845 pSkipClearNativeLabel);
847 EmitClearNative(pcsCleanup);
848 pcsCleanup->EmitLabel(pSkipClearNativeLabel);
852 virtual void EmitMarshalArgumentCLRToNative()
857 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
861 EmitSetupSigAndDefaultHomesCLRToNative();
862 EmitMarshalArgumentContentsCLRToNative();
865 void EmitMarshalArgumentContentsCLRToNative()
870 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
877 if (IsIn(m_dwMarshalFlags))
879 EmitConvertSpaceAndContentsCLRToNativeTemp(m_pcsMarshal);
883 EmitConvertSpaceCLRToNativeTemp(m_pcsMarshal);
889 if (IsOut(m_dwMarshalFlags))
891 if (IsIn(m_dwMarshalFlags))
893 EmitClearCLRContents(m_pcsUnmarshal);
895 EmitConvertContentsNativeToCLR(m_pcsUnmarshal);
898 EmitCleanupCLRToNativeTemp();
901 void EmitSetupSigAndDefaultHomesCLRToNativeByref(bool fBlittable = false)
906 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
910 LocalDesc nativeType = GetNativeType();
911 LocalDesc managedType = GetManagedType();
913 LocalDesc nativeArgType = nativeType;
914 nativeArgType.MakeByRef();
915 m_pcsMarshal->SetStubTargetArgType(&nativeArgType);
919 // we will not work with the actual data but only with a pointer to that data
920 // (the managed and native type had better be the same if it's blittable)
921 _ASSERTE(nativeType.ElementType[0] == managedType.ElementType[0]);
923 // native home will keep the containing object pinned
924 nativeType.MakeByRef();
925 nativeType.MakePinned();
927 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILByrefArgument, m_argidx);
928 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILByrefLocal, m_pcsMarshal->NewLocal(nativeType));
932 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(managedType));
933 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(nativeType));
937 virtual void EmitMarshalArgumentCLRToNativeByref()
942 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
946 EmitSetupSigAndDefaultHomesCLRToNativeByref();
947 EmitMarshalArgumentContentsCLRToNativeByref(false);
950 void EmitMarshalArgumentContentsCLRToNativeByref(bool managedHomeAlreadyInitialized)
955 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
959 LocalDesc managedType = GetManagedType();
964 if (IsIn(m_dwMarshalFlags) && ! IsOut(m_dwMarshalFlags))
966 if (!managedHomeAlreadyInitialized)
968 m_managedHome.EmitCopyFromByrefArg(m_pcsMarshal, &managedType, m_argidx);
971 EmitConvertSpaceAndContentsCLRToNativeTemp(m_pcsMarshal);
973 else if (IsIn(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags))
975 if (!managedHomeAlreadyInitialized)
977 m_managedHome.EmitCopyFromByrefArg(m_pcsMarshal, &managedType, m_argidx);
980 EmitConvertSpaceAndContentsCLRToNative(m_pcsMarshal);
984 EmitReInitNative(m_pcsMarshal);
990 if (IsOut(m_dwMarshalFlags))
992 EmitClearCLR(m_pcsUnmarshal);
994 EmitConvertSpaceAndContentsNativeToCLR(m_pcsUnmarshal);
996 if (!managedHomeAlreadyInitialized)
998 m_managedHome.EmitCopyToByrefArg(m_pcsUnmarshal, &managedType, m_argidx);
1001 EmitCleanupCLRToNative();
1005 EmitCleanupCLRToNativeTemp();
1008 // @TODO: ensure ReInitNative is called on [in,out] byref args when an exception occurs
1012 void EmitSetupSigAndDefaultHomesNativeToCLR()
1017 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
1021 LocalDesc nativeArgType = GetNativeType();
1022 m_pcsMarshal->SetStubTargetArgType(&nativeArgType);
1024 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(GetManagedType()));
1025 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILArgument, m_argidx);
1028 void EmitCleanupNativeToCLR()
1030 STANDARD_VM_CONTRACT;
1032 if (NeedsClearCLR())
1034 CONSISTENCY_CHECK(NeedsMarshalCleanupIndex());
1036 ILCodeStream* pcsCleanup = m_pslNDirect->GetCleanupCodeStream();
1037 ILCodeLabel* pSkipClearCLRLabel = pcsCleanup->NewCodeLabel();
1039 m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
1040 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx,
1041 NDirectStubLinker::BranchIfNotMarshaled,
1042 pSkipClearCLRLabel);
1044 EmitClearCLR(pcsCleanup);
1045 pcsCleanup->EmitLabel(pSkipClearCLRLabel);
1049 // Emits cleanup code that runs only if an exception is thrown during execution of an IL stub (its try
1050 // block to be precise). The goal is to roll back allocations of native resources that may have already
1051 // happened to prevent leaks, and also clear output arguments to prevent passing out invalid data - most
1052 // importantly dangling pointers. The canonical example is an exception thrown during unmarshaling of
1053 // an argument at which point other arguments have already been unmarshaled.
1054 void EmitExceptionCleanupNativeToCLR()
1056 STANDARD_VM_CONTRACT;
1058 _ASSERTE(IsRetval(m_dwMarshalFlags) || IsOut(m_dwMarshalFlags));
1060 LocalDesc nativeType = GetNativeType();
1061 ILCodeStream *pcsCleanup = m_pslNDirect->GetExceptionCleanupCodeStream();
1063 if (NeedsClearNative())
1065 m_pslNDirect->SetExceptionCleanupNeeded();
1067 ILCodeLabel *pSkipCleanupLabel = pcsCleanup->NewCodeLabel();
1069 // if this is byref in/out and we have not marshaled this argument
1070 // yet, we need to populate the native home with the incoming value
1071 if (IsIn(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags))
1073 ILCodeLabel *pSkipCopyLabel = pcsCleanup->NewCodeLabel();
1075 CONSISTENCY_CHECK(NeedsMarshalCleanupIndex());
1076 m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
1077 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_argidx,
1078 NDirectStubLinker::BranchIfMarshaled,
1081 pcsCleanup->EmitLDARG(m_argidx);
1082 pcsCleanup->EmitBRFALSE(pSkipCleanupLabel); // if the argument is NULL, skip cleanup completely
1084 m_nativeHome.EmitCopyFromByrefArg(pcsCleanup, &nativeType, m_argidx);
1086 pcsCleanup->EmitLabel(pSkipCopyLabel);
1089 // if this is retval or out-only, the native home does not get initialized until we unmarshal it
1090 if (IsRetval(m_dwMarshalFlags) || !IsIn(m_dwMarshalFlags))
1092 CONSISTENCY_CHECK(NeedsUnmarshalCleanupIndex());
1094 UINT uArgIdx = (IsRetval(m_dwMarshalFlags) ?
1095 NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL :
1096 NDirectStubLinker::CLEANUP_INDEX_ARG0_UNMARSHAL + m_argidx);
1098 m_pslNDirect->EmitCheckForArgCleanup(pcsCleanup,
1100 NDirectStubLinker::BranchIfNotMarshaled,
1104 // we know that native home needs to be cleaned up at this point
1105 if (IsRetval(m_dwMarshalFlags) || (IsOut(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags)))
1107 // we own the buffer - clear everything
1108 EmitClearNative(pcsCleanup);
1112 // this is a caller supplied buffer - clear only its contents
1113 EmitClearNativeContents(pcsCleanup);
1116 pcsCleanup->EmitLabel(pSkipCleanupLabel);
1119 // if there is an output buffer, zero it out so the caller does not get pointer to already freed data
1120 if (!IsHiddenLengthParam(m_dwMarshalFlags))
1122 if (IsRetval(m_dwMarshalFlags) || (IsOut(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags)))
1124 m_pslNDirect->SetExceptionCleanupNeeded();
1126 EmitReInitNative(pcsCleanup);
1127 if (IsHresultSwap(m_dwMarshalFlags) || IsOut(m_dwMarshalFlags))
1129 m_nativeHome.EmitCopyToByrefArgWithNullCheck(pcsCleanup, &nativeType, m_argidx);
1135 virtual void EmitMarshalArgumentNativeToCLR()
1140 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
1144 EmitSetupSigAndDefaultHomesNativeToCLR();
1145 EmitMarshalArgumentContentsNativeToCLR();
1148 void EmitMarshalArgumentContentsNativeToCLR()
1153 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
1160 if (IsIn(m_dwMarshalFlags))
1162 EmitConvertSpaceAndContentsNativeToCLR(m_pcsMarshal);
1166 EmitConvertSpaceNativeToCLR(m_pcsMarshal);
1172 if (IsOut(m_dwMarshalFlags))
1174 if (IsIn(m_dwMarshalFlags))
1176 EmitClearNativeContents(m_pcsUnmarshal);
1178 EmitConvertContentsCLRToNative(m_pcsUnmarshal);
1180 // make sure we free the argument if an exception is thrown
1181 EmitExceptionCleanupNativeToCLR();
1183 EmitCleanupNativeToCLR();
1186 void EmitSetupSigAndDefaultHomesNativeToCLRByref(bool fBlittable = false)
1191 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1195 LocalDesc nativeType = GetNativeType();
1196 LocalDesc managedType = GetManagedType();
1197 LocalDesc nativeArgType = nativeType;
1198 nativeArgType.MakeByRef();
1199 m_pcsMarshal->SetStubTargetArgType(&nativeArgType);
1203 // we will not work with the actual data but only with a pointer to that data
1204 // (the managed and native type had better be the same if it's blittable)
1205 _ASSERTE(nativeType.ElementType[0] == managedType.ElementType[0]);
1207 managedType.MakeByRef();
1209 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILByrefLocal, m_pcsMarshal->NewLocal(managedType));
1210 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILByrefArgument, m_argidx);
1214 m_managedHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(managedType));
1215 m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILLocal, m_pcsMarshal->NewLocal(nativeType));
1219 virtual void EmitMarshalArgumentNativeToCLRByref()
1224 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1228 EmitSetupSigAndDefaultHomesNativeToCLRByref();
1229 EmitMarshalArgumentContentsNativeToCLRByref(false);
1232 void EmitMarshalArgumentContentsNativeToCLRByref(bool nativeHomeAlreadyInitialized)
1237 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1241 LocalDesc nativeType = GetNativeType();
1246 if (IsIn(m_dwMarshalFlags))
1248 if (!nativeHomeAlreadyInitialized)
1250 m_nativeHome.EmitCopyFromByrefArg(m_pcsMarshal, &nativeType, m_argidx);
1253 EmitConvertSpaceAndContentsNativeToCLR(m_pcsMarshal);
1257 // dereference the argument so we throw before calling the managed target - this is the fastest way
1258 // to check for NULL (we can still throw later if the pointer is invalid yet non-NULL but we cannot
1259 // detect this realiably - the memory may get unmapped etc., NULL check is the best we can do here)
1260 m_pcsMarshal->EmitLDARG(m_argidx);
1261 m_pcsMarshal->EmitLDIND_I1();
1262 m_pcsMarshal->EmitPOP();
1268 if (IsOut(m_dwMarshalFlags))
1270 if (IsIn(m_dwMarshalFlags))
1272 EmitClearNative(m_pcsUnmarshal);
1273 EmitReInitNative(m_pcsUnmarshal);
1276 EmitConvertSpaceAndContentsCLRToNative(m_pcsUnmarshal);
1278 if (!nativeHomeAlreadyInitialized)
1280 m_nativeHome.EmitCopyToByrefArg(m_pcsUnmarshal, &nativeType, m_argidx);
1283 // make sure we free and zero the by-ref argument if an exception is thrown
1284 EmitExceptionCleanupNativeToCLR();
1287 EmitCleanupNativeToCLR();
1290 virtual LocalDesc GetNativeType() = 0;
1291 virtual LocalDesc GetManagedType() = 0;
1296 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
1298 LIMITED_METHOD_CONTRACT;
1301 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1303 LIMITED_METHOD_CONTRACT;
1306 virtual void EmitConvertSpaceAndContentsNativeToCLR(ILCodeStream* pslILEmit)
1308 WRAPPER_NO_CONTRACT;
1309 EmitConvertSpaceNativeToCLR(pslILEmit);
1310 EmitConvertContentsNativeToCLR(pslILEmit);
1317 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
1319 LIMITED_METHOD_CONTRACT;
1322 virtual void EmitConvertSpaceCLRToNativeTemp(ILCodeStream* pslILEmit)
1324 LIMITED_METHOD_CONTRACT;
1325 EmitConvertSpaceCLRToNative(pslILEmit);
1328 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1330 LIMITED_METHOD_CONTRACT;
1333 virtual void EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslILEmit)
1335 STANDARD_VM_CONTRACT;
1336 EmitConvertSpaceCLRToNative(pslILEmit);
1337 EmitConvertContentsCLRToNative(pslILEmit);
1340 virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
1342 WRAPPER_NO_CONTRACT;
1343 EmitConvertSpaceAndContentsCLRToNative(pslILEmit);
1349 virtual void EmitClearCLRContents(ILCodeStream* pslILEmit)
1351 LIMITED_METHOD_CONTRACT;
1354 virtual bool NeedsClearNative()
1356 LIMITED_METHOD_CONTRACT;
1360 virtual void EmitClearNative(ILCodeStream* pslILEmit)
1362 LIMITED_METHOD_CONTRACT;
1365 virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit)
1367 LIMITED_METHOD_CONTRACT;
1368 EmitClearNative(pslILEmit);
1371 virtual void EmitClearNativeContents(ILCodeStream* pslILEmit)
1373 LIMITED_METHOD_CONTRACT;
1376 virtual bool NeedsClearCLR()
1378 LIMITED_METHOD_CONTRACT;
1382 virtual void EmitClearCLR(ILCodeStream* pslILEmit)
1384 LIMITED_METHOD_CONTRACT;
1387 virtual void EmitReInitNative(ILCodeStream* pslILEmit)
1389 STANDARD_VM_CONTRACT;
1391 // Friendly Reminder:
1392 // You should implement your own EmitReInitNative if your native type is a struct,
1393 // as the following instructions apparently won't work on value types and will trigger
1395 _ASSERTE(!GetNativeType().IsValueClass());
1397 pslILEmit->EmitLDC(0);
1398 pslILEmit->EmitCONV_T(static_cast<CorElementType>(GetNativeType().ElementType[0]));
1400 EmitStoreNativeValue(pslILEmit);
1403 virtual bool IsManagedPassedByRef()
1405 LIMITED_METHOD_CONTRACT;
1406 return IsByref(m_dwMarshalFlags);
1409 virtual bool IsNativePassedByRef()
1411 LIMITED_METHOD_CONTRACT;
1412 return IsByref(m_dwMarshalFlags);
1415 void EmitInterfaceClearNative(ILCodeStream* pslILEmit);
1418 static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
1422 BOOL fManagedToNative,
1423 OverrideProcArgs* pargs,
1426 UINT nativeStackOffset)
1428 LIMITED_METHOD_CONTRACT;
1429 return HANDLEASNORMAL;
1432 static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker* psl,
1433 BOOL fManagedToNative,
1435 OverrideProcArgs* pargs,
1438 LIMITED_METHOD_CONTRACT;
1439 return HANDLEASNORMAL;
1444 class ILCopyMarshalerBase : public ILMarshaler
1446 virtual LocalDesc GetManagedType()
1448 WRAPPER_NO_CONTRACT;
1449 return GetNativeType();
1452 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1454 STANDARD_VM_CONTRACT;
1456 EmitLoadManagedValue(pslILEmit);
1457 EmitStoreNativeValue(pslILEmit);
1460 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1462 STANDARD_VM_CONTRACT;
1464 EmitLoadNativeValue(pslILEmit);
1465 EmitStoreManagedValue(pslILEmit);
1469 // It's very unforunate that x86 used ML_COPYPINNEDGCREF for byref args.
1470 // The result is that developers can get away with being lazy about their
1471 // in/out semantics and often times in/out byref params are marked out-
1472 // only, but because of ML_COPYPINNEDGCREF, they get in/out behavior.
1474 // There are even lazier developers who use byref params to pass arrays.
1475 // Pinning ensures that the native side 'sees' the entire array even when
1476 // only reference to one element was passed.
1478 // This method was changed to pin instead of copy in Dev10 in order
1479 // to match the original ML behavior.
1481 virtual void EmitMarshalArgumentCLRToNativeByref()
1486 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1490 EmitSetupSigAndDefaultHomesCLRToNativeByref(true);
1495 EmitLoadManagedHomeAddr(m_pcsMarshal);
1496 EmitStoreNativeHomeAddr(m_pcsMarshal);
1499 // no unmarshaling is necessary since we directly passed the pinned byref to native,
1500 // the argument is therefore automatically in/out
1505 // Similarly to the other direction, ML used ML_COPYPINNEDGCREF on x86 to
1506 // directly pass the unmanaged pointer as a byref argument to managed code.
1507 // This also makes an observable difference (allows passing NULL, changes
1508 // made to the original value during the call are visible in managed).
1510 // This method was changed to pass pointer instead of copy in Dev10 in order
1511 // to match the original ML behavior. Note that in this direction we don't
1512 // need to pin the pointer - if it is pointing to GC heap, it must have been
1513 // pinned on the way to unmanaged.
1515 virtual void EmitMarshalArgumentNativeToCLRByref()
1520 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags));
1524 EmitSetupSigAndDefaultHomesNativeToCLRByref(true);
1529 EmitLoadNativeHomeAddr(m_pcsMarshal);
1530 EmitStoreManagedHomeAddr(m_pcsMarshal);
1533 // no unmarshaling is necessary since we directly passed the pointer to managed
1534 // as a byref, the argument is therefore automatically in/out
1539 template <CorElementType ELEMENT_TYPE, class PROMOTED_ELEMENT>
1540 class ILCopyMarshalerSimple : public ILCopyMarshalerBase
1546 c_nativeSize = sizeof(PROMOTED_ELEMENT),
1547 c_CLRSize = sizeof(PROMOTED_ELEMENT),
1550 bool IsSmallValueTypeSpecialCase()
1553 // Special case for small value types that get
1554 // mapped to MARSHAL_TYPE_GENERIC_8 -- use the
1555 // valuetype type so the JIT is happy.
1558 return (ELEMENT_TYPE ==
1564 ) && (NULL != m_pargs->m_pMT);
1567 bool NeedToPromoteTo8Bytes()
1569 WRAPPER_NO_CONTRACT;
1571 #if defined(_TARGET_AMD64_)
1572 // If the argument is passed by value,
1573 if (!IsByref(m_dwMarshalFlags) && !IsRetval(m_dwMarshalFlags))
1575 // and it is an I4 or an U4,
1576 if ( (ELEMENT_TYPE == ELEMENT_TYPE_I4) ||
1577 (ELEMENT_TYPE == ELEMENT_TYPE_U4) )
1579 // and we are doing a managed-to-unmanaged call,
1580 if (IsCLRToNative(m_dwMarshalFlags))
1582 // then we have to promote the native argument type to an I8 or an U8.
1587 #endif // _TARGET_AMD64_
1592 CorElementType GetConversionType(CorElementType type)
1594 LIMITED_METHOD_CONTRACT;
1596 // I4 <-> I8; U4 <-> U8
1597 if (type == ELEMENT_TYPE_I4)
1599 return ELEMENT_TYPE_I8;
1601 else if (type == ELEMENT_TYPE_U4)
1603 return ELEMENT_TYPE_U8;
1607 return ELEMENT_TYPE_END;
1611 void EmitTypePromotion(ILCodeStream* pslILEmit)
1613 WRAPPER_NO_CONTRACT;
1615 CorElementType promotedType = GetConversionType(ELEMENT_TYPE);
1616 if (promotedType == ELEMENT_TYPE_I8)
1618 pslILEmit->EmitCONV_I8();
1620 else if (promotedType == ELEMENT_TYPE_U8)
1622 pslILEmit->EmitCONV_U8();
1626 virtual LocalDesc GetNativeType()
1628 WRAPPER_NO_CONTRACT;
1630 if (NeedToPromoteTo8Bytes())
1632 return LocalDesc(GetConversionType(ELEMENT_TYPE));
1636 return GetManagedType();
1640 virtual LocalDesc GetManagedType()
1642 WRAPPER_NO_CONTRACT;
1644 if (IsSmallValueTypeSpecialCase())
1646 return LocalDesc(m_pargs->m_pMT);
1650 return LocalDesc(ELEMENT_TYPE);
1654 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1656 STANDARD_VM_CONTRACT;
1658 EmitLoadManagedValue(pslILEmit);
1659 if (NeedToPromoteTo8Bytes())
1661 EmitTypePromotion(pslILEmit);
1663 EmitStoreNativeValue(pslILEmit);
1666 virtual void EmitReInitNative(ILCodeStream* pslILEmit)
1668 STANDARD_VM_CONTRACT;
1670 if (IsSmallValueTypeSpecialCase())
1672 EmitLoadNativeHomeAddr(pslILEmit);
1673 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(m_pargs->m_pMT));
1677 // ldc.i4.0, conv.i8/u8/r4/r8 is shorter than ldc.i8/r4/r8 0
1678 pslILEmit->EmitLDC(0);
1679 pslILEmit->EmitCONV_T(ELEMENT_TYPE);
1681 EmitStoreNativeValue(pslILEmit);
1686 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_I1, INT_PTR> ILCopyMarshaler1;
1687 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_U1, UINT_PTR> ILCopyMarshalerU1;
1688 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_I2, INT_PTR> ILCopyMarshaler2;
1689 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_U2, UINT_PTR> ILCopyMarshalerU2;
1690 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_I4, INT_PTR> ILCopyMarshaler4;
1691 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_U4, UINT_PTR> ILCopyMarshalerU4;
1692 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_I8, INT64> ILCopyMarshaler8;
1693 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_R4, float> ILFloatMarshaler;
1694 typedef ILCopyMarshalerSimple<ELEMENT_TYPE_R8, double> ILDoubleMarshaler;
1696 template <BinderClassID CLASS__ID, class PROMOTED_ELEMENT>
1697 class ILCopyMarshalerKnownStruct : public ILCopyMarshalerBase
1703 c_nativeSize = sizeof(PROMOTED_ELEMENT),
1704 c_CLRSize = sizeof(PROMOTED_ELEMENT),
1707 virtual void EmitReInitNative(ILCodeStream* pslILEmit)
1709 STANDARD_VM_CONTRACT;
1711 EmitLoadNativeHomeAddr(pslILEmit);
1712 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__ID)));
1715 virtual LocalDesc GetNativeType()
1717 STANDARD_VM_CONTRACT;
1719 return LocalDesc(MscorlibBinder::GetClass(CLASS__ID));
1723 typedef ILCopyMarshalerKnownStruct<CLASS__DECIMAL, DECIMAL> ILDecimalMarshaler;
1724 typedef ILCopyMarshalerKnownStruct<CLASS__GUID, GUID> ILGuidMarshaler;
1726 class ILBlittableValueClassMarshaler : public ILCopyMarshalerBase
1732 c_nativeSize = VARIABLESIZE,
1733 c_CLRSize = VARIABLESIZE,
1736 virtual void EmitReInitNative(ILCodeStream* pslILEmit)
1738 STANDARD_VM_CONTRACT;
1740 EmitLoadNativeHomeAddr(pslILEmit);
1741 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(m_pargs->m_pMT));
1744 virtual LocalDesc GetNativeType()
1746 LIMITED_METHOD_CONTRACT;
1748 return LocalDesc(m_pargs->m_pMT);
1753 class ILDelegateMarshaler : public ILMarshaler
1759 c_nativeSize = sizeof(void *),
1760 c_CLRSize = sizeof(OBJECTREF),
1764 virtual LocalDesc GetNativeType();
1765 virtual LocalDesc GetManagedType();
1766 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
1767 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
1770 class ILReflectionObjectMarshaler : public ILMarshaler
1776 c_nativeSize = sizeof(void *),
1777 c_CLRSize = sizeof(OBJECTREF),
1781 virtual LocalDesc GetManagedType();
1782 virtual LocalDesc GetNativeType();
1783 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
1784 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
1785 virtual BinderFieldID GetStructureFieldID() {LIMITED_METHOD_CONTRACT; return (BinderFieldID)0;}
1786 virtual BinderFieldID GetObjectFieldID() = 0;
1787 virtual BinderClassID GetManagedTypeBinderID() = 0;
1790 class ILIRuntimeMethodInfoMarshaler : public ILReflectionObjectMarshaler
1793 virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__STUBMETHODINFO__HANDLE; }
1794 virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__STUBMETHODINFO; }
1797 class ILRuntimeModuleMarshaler : public ILReflectionObjectMarshaler
1800 virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__MODULE__DATA; }
1801 virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__MODULE; }
1804 class ILRuntimeAssemblyMarshaler : public ILReflectionObjectMarshaler
1807 virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__ASSEMBLY__HANDLE; }
1808 virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__ASSEMBLY; }
1811 class ILRuntimeTypeHandleMarshaler : public ILReflectionObjectMarshaler
1814 virtual BinderFieldID GetStructureFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__RT_TYPE_HANDLE__M_TYPE; }
1815 virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__CLASS__TYPEHANDLE; }
1816 virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__RT_TYPE_HANDLE; }
1819 class ILRuntimeMethodHandleMarshaler : public ILReflectionObjectMarshaler
1822 virtual BinderFieldID GetStructureFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__METHOD_HANDLE__METHOD; }
1823 virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__STUBMETHODINFO__HANDLE; }
1824 virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__METHOD_HANDLE; }
1827 class ILRuntimeFieldHandleMarshaler : public ILReflectionObjectMarshaler
1830 virtual BinderFieldID GetStructureFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__FIELD_HANDLE__M_FIELD; }
1831 virtual BinderFieldID GetObjectFieldID() { LIMITED_METHOD_CONTRACT; return FIELD__RT_FIELD_INFO__HANDLE; }
1832 virtual BinderClassID GetManagedTypeBinderID() { LIMITED_METHOD_CONTRACT; return CLASS__FIELD_HANDLE; }
1835 class ILBoolMarshaler : public ILMarshaler
1839 virtual CorElementType GetNativeBoolElementType() = 0;
1840 virtual int GetNativeTrueValue() = 0;
1841 virtual int GetNativeFalseValue() = 0;
1844 virtual LocalDesc GetNativeType();
1845 virtual LocalDesc GetManagedType();
1846 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
1847 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
1850 class ILWinBoolMarshaler : public ILBoolMarshaler
1856 c_nativeSize = sizeof(BOOL),
1857 c_CLRSize = sizeof(INT8),
1861 virtual CorElementType GetNativeBoolElementType()
1863 LIMITED_METHOD_CONTRACT;
1864 return ELEMENT_TYPE_I4;
1867 virtual int GetNativeTrueValue()
1869 LIMITED_METHOD_CONTRACT;
1873 virtual int GetNativeFalseValue()
1875 LIMITED_METHOD_CONTRACT;
1880 class ILCBoolMarshaler : public ILBoolMarshaler
1886 c_nativeSize = sizeof(BYTE),
1887 c_CLRSize = sizeof(INT8),
1891 virtual CorElementType GetNativeBoolElementType()
1893 LIMITED_METHOD_CONTRACT;
1894 return ELEMENT_TYPE_I1;
1897 virtual int GetNativeTrueValue()
1899 LIMITED_METHOD_CONTRACT;
1903 virtual int GetNativeFalseValue()
1905 LIMITED_METHOD_CONTRACT;
1910 #ifdef FEATURE_COMINTEROP
1911 class ILVtBoolMarshaler : public ILBoolMarshaler
1917 c_nativeSize = sizeof(VARIANT_BOOL),
1918 c_CLRSize = sizeof(INT8),
1922 virtual CorElementType GetNativeBoolElementType()
1924 LIMITED_METHOD_CONTRACT;
1925 return ELEMENT_TYPE_I2;
1928 virtual int GetNativeTrueValue()
1930 LIMITED_METHOD_CONTRACT;
1931 return VARIANT_TRUE;
1934 virtual int GetNativeFalseValue()
1936 LIMITED_METHOD_CONTRACT;
1937 return VARIANT_FALSE;
1940 #endif // FEATURE_COMINTEROP
1942 class ILWSTRMarshaler : public ILMarshaler
1948 c_nativeSize = sizeof(void *),
1949 c_CLRSize = sizeof(OBJECTREF),
1953 bool m_fCoMemoryAllocated;
1957 LIMITED_METHOD_CONTRACT;
1958 m_fCoMemoryAllocated = false;
1963 virtual LocalDesc GetNativeType();
1964 virtual LocalDesc GetManagedType();
1966 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
1967 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
1968 virtual void EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslILEmit);
1969 virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit);
1971 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
1972 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
1973 virtual void EmitConvertSpaceAndContentsNativeToCLR(ILCodeStream* pslILEmit);
1975 virtual bool NeedsClearNative();
1976 virtual void EmitClearNative(ILCodeStream* pslILEmit);
1977 virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit);
1979 static bool CanUsePinnedManagedString(DWORD dwMarshalFlags);
1980 static void EmitCheckManagedStringLength(ILCodeStream* pslILEmit);
1981 static void EmitCheckNativeStringLength(ILCodeStream* pslILEmit);
1984 // A marshaler that makes run-time decision based on argument size whether native space will
1985 // be allocated using localloc or on the heap. The ctor argument is a heap free function.
1986 class ILOptimizedAllocMarshaler : public ILMarshaler
1989 ILOptimizedAllocMarshaler(BinderMethodID clearNat) :
1990 m_idClearNative(clearNat),
1991 m_dwLocalBuffer((DWORD)-1)
1993 LIMITED_METHOD_CONTRACT;
1996 virtual LocalDesc GetNativeType();
1997 virtual bool NeedsClearNative();
1998 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2001 const BinderMethodID m_idClearNative;
2002 DWORD m_dwLocalBuffer; // localloc'ed temp buffer variable or -1 if not used
2005 class ILUTF8BufferMarshaler : public ILOptimizedAllocMarshaler
2011 c_nativeSize = sizeof(void *),
2012 c_CLRSize = sizeof(OBJECTREF),
2017 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2018 MAX_LOCAL_BUFFER_LENGTH = MAX_PATH_FNAME + 1
2021 ILUTF8BufferMarshaler() :
2022 ILOptimizedAllocMarshaler(METHOD__WIN32NATIVE__COTASKMEMFREE)
2024 LIMITED_METHOD_CONTRACT;
2027 virtual LocalDesc GetManagedType();
2028 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
2029 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2030 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
2031 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2034 class ILWSTRBufferMarshaler : public ILOptimizedAllocMarshaler
2040 c_nativeSize = sizeof(void *),
2041 c_CLRSize = sizeof(OBJECTREF),
2046 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2047 MAX_LOCAL_BUFFER_LENGTH = (MAX_PATH_FNAME + 1) * 2
2050 ILWSTRBufferMarshaler() :
2051 ILOptimizedAllocMarshaler(METHOD__WIN32NATIVE__COTASKMEMFREE)
2053 LIMITED_METHOD_CONTRACT;
2056 virtual LocalDesc GetManagedType();
2057 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
2058 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2059 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
2060 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2063 class ILCSTRBufferMarshaler : public ILOptimizedAllocMarshaler
2069 c_nativeSize = sizeof(void *),
2070 c_CLRSize = sizeof(OBJECTREF),
2075 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2076 MAX_LOCAL_BUFFER_LENGTH = MAX_PATH_FNAME + 1
2079 ILCSTRBufferMarshaler() :
2080 ILOptimizedAllocMarshaler(METHOD__WIN32NATIVE__COTASKMEMFREE)
2082 LIMITED_METHOD_CONTRACT;
2085 virtual LocalDesc GetManagedType();
2086 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
2087 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2088 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
2089 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2093 class ILHandleRefMarshaler : public ILMarshaler
2095 // Managed layout for SRI.HandleRef class
2098 OBJECTREF m_wrapper;
2106 c_nativeSize = sizeof(LPVOID),
2107 c_CLRSize = sizeof(HANDLEREF),
2110 LocalDesc GetManagedType()
2112 LIMITED_METHOD_CONTRACT;
2116 LocalDesc GetNativeType()
2118 LIMITED_METHOD_CONTRACT;
2122 static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
2126 BOOL fManagedToNative,
2127 OverrideProcArgs* pargs,
2130 UINT nativeStackOffset);
2132 static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker* psl,
2133 BOOL fManagedToNative,
2135 OverrideProcArgs* pargs,
2139 class ILSafeHandleMarshaler : public ILMarshaler
2145 c_nativeSize = sizeof(LPVOID),
2146 c_CLRSize = sizeof(SAFEHANDLE),
2149 virtual LocalDesc GetManagedType();
2150 virtual LocalDesc GetNativeType();
2152 virtual bool NeedsClearNative();
2153 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2155 virtual void EmitMarshalArgumentCLRToNative();
2157 static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
2161 BOOL fManagedToNative,
2162 OverrideProcArgs* pargs,
2165 UINT nativeStackOffset);
2167 static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker *psl,
2168 BOOL fManagedToNative,
2170 OverrideProcArgs *pargs,
2175 class ILCriticalHandleMarshaler : public ILMarshaler
2181 c_nativeSize = sizeof(LPVOID),
2182 c_CLRSize = sizeof(CRITICALHANDLE),
2187 LocalDesc GetManagedType()
2189 LIMITED_METHOD_CONTRACT;
2193 LocalDesc GetNativeType()
2195 LIMITED_METHOD_CONTRACT;
2199 static MarshalerOverrideStatus ArgumentOverride(NDirectStubLinker* psl,
2203 BOOL fManagedToNative,
2204 OverrideProcArgs* pargs,
2207 UINT nativeStackOffset);
2209 static MarshalerOverrideStatus ReturnOverride(NDirectStubLinker *psl,
2210 BOOL fManagedToNative,
2212 OverrideProcArgs *pargs,
2217 class ILValueClassMarshaler : public ILMarshaler
2223 c_nativeSize = VARIABLESIZE,
2224 c_CLRSize = VARIABLESIZE,
2228 virtual LocalDesc GetNativeType();
2229 virtual LocalDesc GetManagedType();
2230 virtual void EmitReInitNative(ILCodeStream* pslILEmit);
2231 virtual bool NeedsClearNative();
2232 virtual void EmitClearNative(ILCodeStream * pslILEmit);
2233 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2234 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2237 #ifdef FEATURE_COMINTEROP
2238 class ILObjectMarshaler : public ILMarshaler
2244 c_CLRSize = sizeof(OBJECTREF),
2245 c_nativeSize = sizeof(VARIANT),
2249 virtual LocalDesc GetNativeType();
2250 virtual LocalDesc GetManagedType();
2251 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2252 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2253 virtual bool NeedsClearNative();
2254 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2255 virtual void EmitReInitNative(ILCodeStream* pslILEmit);
2257 #endif // FEATURE_COMINTEROP
2259 class ILDateMarshaler : public ILMarshaler
2265 c_nativeSize = sizeof(DATE),
2266 c_CLRSize = sizeof(INT64),
2270 virtual LocalDesc GetNativeType();
2271 virtual LocalDesc GetManagedType();
2272 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2273 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2274 virtual void EmitReInitNative(ILCodeStream* pslILEmit);
2278 class ILCurrencyMarshaler : public ILMarshaler
2284 c_nativeSize = sizeof(CURRENCY),
2285 c_CLRSize = sizeof(DECIMAL),
2289 virtual LocalDesc GetNativeType();
2290 virtual LocalDesc GetManagedType();
2291 virtual void EmitReInitNative(ILCodeStream* pslILEmit);
2292 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2293 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2297 #ifdef FEATURE_COMINTEROP
2298 class ILInterfaceMarshaler : public ILMarshaler
2304 c_nativeSize = sizeof(void *),
2305 c_CLRSize = sizeof(OBJECTREF),
2309 virtual LocalDesc GetNativeType();
2310 virtual LocalDesc GetManagedType();
2311 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2312 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2313 virtual bool NeedsClearNative();
2314 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2316 #endif // FEATURE_COMINTEROP
2319 class ILAnsiCharMarshaler : public ILMarshaler
2325 c_nativeSize = sizeof(UINT8),
2326 c_CLRSize = sizeof(UINT16),
2330 virtual LocalDesc GetNativeType();
2331 virtual LocalDesc GetManagedType();
2332 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2333 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2337 template <BinderClassID CLASS__ID, class ELEMENT>
2338 class ILValueClassPtrMarshaler : public ILMarshaler
2344 c_nativeSize = sizeof(ELEMENT *),
2345 c_CLRSize = sizeof(ELEMENT),
2349 virtual LocalDesc GetNativeType()
2351 LIMITED_METHOD_CONTRACT;
2354 // pointer to value class
2356 return LocalDesc(ELEMENT_TYPE_I);
2359 virtual LocalDesc GetManagedType()
2361 STANDARD_VM_CONTRACT;
2366 return LocalDesc(MscorlibBinder::GetClass(CLASS__ID));
2369 virtual bool NeedsClearNative()
2371 LIMITED_METHOD_CONTRACT;
2372 return (IsByref(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags));
2375 virtual void EmitClearNative(ILCodeStream* pslILEmit)
2377 STANDARD_VM_CONTRACT;
2379 EmitLoadNativeValue(pslILEmit);
2380 // static void CoTaskMemFree(IntPtr ptr)
2381 pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
2384 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
2386 STANDARD_VM_CONTRACT;
2388 if (NeedsClearNative())
2390 pslILEmit->EmitLDC(sizeof(ELEMENT));
2391 pslILEmit->EmitCONV_U();
2392 // static IntPtr CoTaskMemAlloc(UIntPtr cb)
2393 pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMALLOC, 1, 1);
2394 EmitStoreNativeValue(pslILEmit);
2398 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2400 STANDARD_VM_CONTRACT;
2402 if (NeedsClearNative())
2404 EmitLoadNativeValue(pslILEmit); // dest
2405 EmitLoadManagedHomeAddr(pslILEmit); // src
2406 pslILEmit->EmitCPOBJ(pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__ID)));
2410 EmitLoadManagedHomeAddr(pslILEmit);
2411 EmitStoreNativeValue(pslILEmit);
2415 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2417 STANDARD_VM_CONTRACT;
2419 int tokType = pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__ID));
2420 ILCodeLabel *pNullLabel = pslILEmit->NewCodeLabel();
2421 ILCodeLabel *pJoinLabel = pslILEmit->NewCodeLabel();
2423 EmitLoadNativeValue(pslILEmit);
2424 pslILEmit->EmitBRFALSE(pNullLabel);
2426 // the incoming pointer is non-null -> dereference it and copy the struct
2427 EmitLoadManagedHomeAddr(pslILEmit); // dest
2428 EmitLoadNativeValue(pslILEmit); // src
2429 pslILEmit->EmitCPOBJ(tokType);
2431 pslILEmit->EmitBR(pJoinLabel);
2433 // the incoming pointer is null -> just initobj (i.e. zero) the struct
2434 pslILEmit->EmitLabel(pNullLabel);
2436 EmitLoadManagedHomeAddr(pslILEmit);
2437 pslILEmit->EmitINITOBJ(tokType);
2439 pslILEmit->EmitLabel(pJoinLabel);
2443 typedef ILValueClassPtrMarshaler<CLASS__GUID, GUID> ILGuidPtrMarshaler;
2444 typedef ILValueClassPtrMarshaler<CLASS__DECIMAL, DECIMAL> ILDecimalPtrMarshaler;
2446 #ifdef FEATURE_COMINTEROP
2447 class ILOleColorMarshaler : public ILMarshaler
2453 c_nativeSize = sizeof(OLE_COLOR),
2454 c_CLRSize = sizeof(SYSTEMCOLOR),
2458 virtual LocalDesc GetNativeType();
2459 virtual LocalDesc GetManagedType();
2460 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2461 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2464 class ILVBByValStrWMarshaler : public ILMarshaler
2470 c_nativeSize = sizeof(BSTR),
2471 c_CLRSize = sizeof(OBJECTREF*),
2476 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2477 MAX_LOCAL_BUFFER_LENGTH = (MAX_PATH_FNAME + 1) * 2 + sizeof(DWORD)
2481 ILVBByValStrWMarshaler() :
2483 ,m_dwLocalBuffer(-1)
2485 LIMITED_METHOD_CONTRACT;
2488 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2489 virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2492 virtual LocalDesc GetNativeType();
2493 virtual LocalDesc GetManagedType();
2494 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2495 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2496 virtual bool NeedsClearNative();
2497 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2498 virtual bool IsNativePassedByRef();
2501 DWORD m_dwLocalBuffer;
2504 class ILVBByValStrMarshaler : public ILMarshaler
2510 c_nativeSize = sizeof(LPSTR),
2511 c_CLRSize = sizeof(OBJECTREF *),
2514 ILVBByValStrMarshaler() :
2517 LIMITED_METHOD_CONTRACT;
2520 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2521 virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2524 virtual LocalDesc GetNativeType();
2525 virtual LocalDesc GetManagedType();
2526 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2527 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2528 virtual bool NeedsClearNative();
2529 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2530 virtual bool IsNativePassedByRef();
2535 class ILHSTRINGMarshaler : public ILMarshaler
2541 c_nativeSize = sizeof(HSTRING),
2542 c_CLRSize = sizeof(OBJECTREF),
2546 virtual LocalDesc GetNativeType();
2547 virtual LocalDesc GetManagedType();
2549 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2550 void EmitConvertCLRToHSTRINGReference(ILCodeStream* pslILEmit);
2551 void EmitConvertCLRToHSTRING(ILCodeStream* pslILEmit);
2553 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2555 virtual bool NeedsClearNative();
2556 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2558 #endif // FEATURE_COMINTEROP
2561 class ILCUTF8Marshaler : public ILOptimizedAllocMarshaler
2567 c_nativeSize = sizeof(void *),
2568 c_CLRSize = sizeof(OBJECTREF),
2573 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2574 MAX_LOCAL_BUFFER_LENGTH = MAX_PATH_FNAME + 1
2577 ILCUTF8Marshaler() :
2578 ILOptimizedAllocMarshaler(METHOD__CSTRMARSHALER__CLEAR_NATIVE)
2580 LIMITED_METHOD_CONTRACT;
2584 virtual LocalDesc GetManagedType();
2585 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2586 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2591 class ILCSTRMarshaler : public ILOptimizedAllocMarshaler
2597 c_nativeSize = sizeof(void *),
2598 c_CLRSize = sizeof(OBJECTREF),
2603 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2604 MAX_LOCAL_BUFFER_LENGTH = MAX_PATH_FNAME + 1
2608 ILOptimizedAllocMarshaler(METHOD__CSTRMARSHALER__CLEAR_NATIVE)
2610 LIMITED_METHOD_CONTRACT;
2614 virtual LocalDesc GetManagedType();
2615 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2616 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2619 #ifdef FEATURE_COMINTEROP
2620 class ILBSTRMarshaler : public ILOptimizedAllocMarshaler
2626 c_nativeSize = sizeof(void *),
2627 c_CLRSize = sizeof(OBJECTREF),
2632 // If required buffer length > MAX_LOCAL_BUFFER_LENGTH, don't optimize by allocating memory on stack
2633 MAX_LOCAL_BUFFER_LENGTH = (MAX_PATH_FNAME + 1) * 2 + 4
2637 ILOptimizedAllocMarshaler(METHOD__BSTRMARSHALER__CLEAR_NATIVE)
2639 LIMITED_METHOD_CONTRACT;
2643 virtual LocalDesc GetManagedType();
2644 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2645 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2649 class ILAnsiBSTRMarshaler : public ILMarshaler
2655 c_nativeSize = sizeof(void *),
2656 c_CLRSize = sizeof(OBJECTREF),
2660 virtual LocalDesc GetNativeType();
2661 virtual LocalDesc GetManagedType();
2662 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2663 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2664 virtual bool NeedsClearNative();
2665 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2667 #endif // FEATURE_COMINTEROP
2669 class ILLayoutClassPtrMarshalerBase : public ILMarshaler
2674 c_nativeSize = sizeof(void *),
2675 c_CLRSize = sizeof(OBJECTREF),
2679 virtual LocalDesc GetNativeType();
2680 virtual LocalDesc GetManagedType();
2681 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
2682 virtual void EmitConvertSpaceCLRToNativeTemp(ILCodeStream* pslILEmit);
2683 virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit);
2684 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
2685 virtual bool NeedsClearNative();
2686 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2687 virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit);
2690 class ILLayoutClassPtrMarshaler : public ILLayoutClassPtrMarshalerBase
2699 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2700 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2701 virtual void EmitClearNativeContents(ILCodeStream * pslILEmit);
2704 class ILBlittablePtrMarshaler : public ILLayoutClassPtrMarshalerBase
2713 virtual void EmitMarshalArgumentCLRToNative();
2714 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
2715 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2721 class ILArgIteratorMarshaler : public ILMarshaler
2727 c_nativeSize = sizeof(va_list),
2728 c_CLRSize = sizeof(VARARGS),
2732 virtual LocalDesc GetNativeType();
2733 virtual LocalDesc GetManagedType();
2734 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2735 virtual void EmitMarshalArgumentCLRToNative();
2736 virtual void EmitMarshalArgumentNativeToCLR();
2739 class ILArrayWithOffsetMarshaler : public ILMarshaler
2745 c_nativeSize = sizeof(LPVOID),
2746 c_CLRSize = sizeof(ArrayWithOffsetData),
2749 ILArrayWithOffsetMarshaler() :
2750 m_dwCountLocalNum(-1),
2751 m_dwOffsetLocalNum(-1),
2752 m_dwPinnedLocalNum(-1)
2754 LIMITED_METHOD_CONTRACT;
2758 virtual LocalDesc GetNativeType();
2759 virtual LocalDesc GetManagedType();
2760 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2762 virtual void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit);
2763 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
2764 virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit);
2767 DWORD m_dwCountLocalNum;
2768 DWORD m_dwOffsetLocalNum;
2769 DWORD m_dwPinnedLocalNum;
2772 class ILAsAnyMarshalerBase : public ILMarshaler
2777 c_nativeSize = sizeof(void *),
2778 c_CLRSize = sizeof(OBJECTREF),
2781 ILAsAnyMarshalerBase() :
2782 m_dwMarshalerLocalNum(-1)
2784 LIMITED_METHOD_CONTRACT;
2788 static const BYTE ML_IN = 0x10;
2789 static const BYTE ML_OUT = 0x20;
2791 virtual bool IsAnsi() = 0;
2792 virtual LocalDesc GetNativeType();
2793 virtual LocalDesc GetManagedType();
2794 virtual bool SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2795 virtual bool SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID);
2796 virtual void EmitMarshalArgumentCLRToNative();
2797 virtual bool NeedsClearNative();
2798 virtual void EmitClearNativeTemp(ILCodeStream* pslILEmit);
2800 DWORD m_dwMarshalerLocalNum;
2803 class ILAsAnyWMarshaler : public ILAsAnyMarshalerBase
2812 virtual bool IsAnsi()
2818 class ILAsAnyAMarshaler : public ILAsAnyMarshalerBase
2827 virtual bool IsAnsi()
2834 class ILMngdMarshaler : public ILMarshaler
2839 c_nativeSize = sizeof(void *),
2840 c_CLRSize = sizeof(OBJECTREF),
2843 ILMngdMarshaler(BinderMethodID space2Man,
2844 BinderMethodID contents2Man,
2845 BinderMethodID space2Nat,
2846 BinderMethodID contents2Nat,
2847 BinderMethodID clearNat,
2848 BinderMethodID clearNatContents,
2849 BinderMethodID clearMan) :
2850 m_idConvertSpaceToManaged(space2Man),
2851 m_idConvertContentsToManaged(contents2Man),
2852 m_idConvertSpaceToNative(space2Nat),
2853 m_idConvertContentsToNative(contents2Nat),
2854 m_idClearNative(clearNat),
2855 m_idClearNativeContents(clearNatContents),
2856 m_idClearManaged(clearMan)
2858 LIMITED_METHOD_CONTRACT;
2862 virtual LocalDesc GetNativeType();
2863 virtual LocalDesc GetManagedType();
2865 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit) = 0;
2867 virtual void EmitCallMngdMarshalerMethod(ILCodeStream* pslILEmit, MethodDesc *pMD);
2869 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
2871 WRAPPER_NO_CONTRACT;
2872 EmitCallMngdMarshalerMethod(pslILEmit, GetConvertSpaceToManagedMethod());
2875 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2877 WRAPPER_NO_CONTRACT;
2878 EmitCallMngdMarshalerMethod(pslILEmit, GetConvertContentsToManagedMethod());
2881 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
2883 WRAPPER_NO_CONTRACT;
2884 EmitCallMngdMarshalerMethod(pslILEmit, GetConvertSpaceToNativeMethod());
2887 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2889 WRAPPER_NO_CONTRACT;
2890 EmitCallMngdMarshalerMethod(pslILEmit, GetConvertContentsToNativeMethod());
2893 virtual bool NeedsClearNative()
2895 LIMITED_METHOD_CONTRACT;
2897 if (NULL != GetClearNativeMethod())
2905 virtual void EmitClearNative(ILCodeStream* pslILEmit)
2907 WRAPPER_NO_CONTRACT;
2908 EmitCallMngdMarshalerMethod(pslILEmit, GetClearNativeMethod());
2911 virtual void EmitClearNativeContents(ILCodeStream* pslILEmit)
2913 WRAPPER_NO_CONTRACT;
2914 EmitCallMngdMarshalerMethod(pslILEmit, GetClearNativeContentsMethod());
2918 virtual bool NeedsClearCLR()
2920 LIMITED_METHOD_CONTRACT;
2922 if (NULL != GetClearManagedMethod())
2930 virtual void EmitClearCLR(ILCodeStream* pslILEmit)
2932 WRAPPER_NO_CONTRACT;
2933 EmitCallMngdMarshalerMethod(pslILEmit, GetClearManagedMethod());
2936 virtual MethodDesc *GetConvertSpaceToManagedMethod() { WRAPPER_NO_CONTRACT; return (m_idConvertSpaceToManaged == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idConvertSpaceToManaged)); }
2937 virtual MethodDesc *GetConvertContentsToManagedMethod() { WRAPPER_NO_CONTRACT; return (m_idConvertContentsToManaged == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idConvertContentsToManaged)); }
2938 virtual MethodDesc *GetConvertSpaceToNativeMethod() { WRAPPER_NO_CONTRACT; return (m_idConvertSpaceToNative == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idConvertSpaceToNative)); }
2939 virtual MethodDesc *GetConvertContentsToNativeMethod() { WRAPPER_NO_CONTRACT; return (m_idConvertContentsToNative == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idConvertContentsToNative)); }
2940 virtual MethodDesc *GetClearNativeMethod() { WRAPPER_NO_CONTRACT; return (m_idClearNative == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idClearNative)); }
2941 virtual MethodDesc *GetClearNativeContentsMethod() { WRAPPER_NO_CONTRACT; return (m_idClearNativeContents == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idClearNativeContents)); }
2942 virtual MethodDesc *GetClearManagedMethod() { WRAPPER_NO_CONTRACT; return (m_idClearManaged == METHOD__NIL ? NULL : MscorlibBinder::GetMethod(m_idClearManaged)); }
2944 const BinderMethodID m_idConvertSpaceToManaged;
2945 const BinderMethodID m_idConvertContentsToManaged;
2946 const BinderMethodID m_idConvertSpaceToNative;
2947 const BinderMethodID m_idConvertContentsToNative;
2948 const BinderMethodID m_idClearNative;
2949 const BinderMethodID m_idClearNativeContents;
2950 const BinderMethodID m_idClearManaged;
2953 class ILNativeArrayMarshaler : public ILMngdMarshaler
2961 ILNativeArrayMarshaler() :
2963 METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CONVERT_SPACE_TO_MANAGED,
2964 METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED,
2965 METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CONVERT_SPACE_TO_NATIVE,
2966 METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE,
2967 METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CLEAR_NATIVE,
2968 METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CLEAR_NATIVE_CONTENTS,
2972 LIMITED_METHOD_CONTRACT;
2973 m_dwSavedSizeArg = LOCAL_NUM_UNUSED;
2976 virtual void EmitMarshalArgumentCLRToNative();
2977 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
2978 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
2979 virtual void EmitClearNative(ILCodeStream* pslILEmit);
2980 virtual void EmitClearNativeContents(ILCodeStream* pslILEmit);
2981 virtual void EmitMarshalArgumentNativeToCLRByref();
2982 virtual void EmitMarshalArgumentCLRToNativeByref();
2986 bool UsePinnedArraySpecialCase();
2988 BOOL CheckSizeParamIndexArg(const CREATE_MARSHALER_CARRAY_OPERANDS &mops, CorElementType *pElementType);
2990 // Calculate element count and load it on evaluation stack
2991 void EmitLoadElementCount(ILCodeStream* pslILEmit);
2993 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
2995 void EmitLoadNativeSize(ILCodeStream* pslILEmit);
2996 void EmitNewSavedSizeArgLocal();
2999 DWORD m_dwSavedSizeArg;
3002 class MngdNativeArrayMarshaler
3005 static FCDECL3(void, CreateMarshaler, MngdNativeArrayMarshaler* pThis, MethodTable* pMT, UINT32 dwFlags);
3006 static FCDECL3(void, ConvertSpaceToNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3007 static FCDECL3(void, ConvertContentsToNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3008 static FCDECL4(void, ConvertSpaceToManaged, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements);
3009 static FCDECL3(void, ConvertContentsToManaged, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3010 static FCDECL3(void, ClearNative, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
3011 static FCDECL3(void, ClearNativeContents, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
3013 static void DoClearNativeContents(MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
3017 FLAG_NATIVE_DATA_VALID = 0x40000000
3020 MethodTable* m_pElementMT;
3022 BOOL m_NativeDataValid;
3024 BOOL m_ThrowOnUnmappableChar;
3029 #ifdef FEATURE_COMINTEROP
3030 class ILSafeArrayMarshaler : public ILMngdMarshaler
3038 ILSafeArrayMarshaler() :
3040 METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_SPACE_TO_MANAGED,
3041 METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED,
3042 METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_SPACE_TO_NATIVE,
3043 METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE,
3044 METHOD__MNGD_SAFE_ARRAY_MARSHALER__CLEAR_NATIVE,
3048 m_dwOriginalManagedLocalNum(-1)
3050 LIMITED_METHOD_CONTRACT;
3055 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
3056 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3057 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3059 virtual void EmitReInitNative(ILCodeStream* pslILEmit)
3068 if (NeedsCheckForStatic() && pslILEmit->GetStreamType() != ILStubLinker::kExceptionCleanup)
3070 // Keep the original value in native home as we are not going to allocate a new
3071 // one. If we cleared it here, we wouldn't be able to ConvertContentsToNative.
3072 // Always perform the real re-init in the ExceptionCleanup stream so the caller
3073 // doesn't get back garbage.
3077 ILMngdMarshaler::EmitReInitNative(pslILEmit);
3081 bool NeedsCheckForStatic()
3083 WRAPPER_NO_CONTRACT;
3084 return IsByref(m_dwMarshalFlags) && !IsCLRToNative(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags);
3087 DWORD m_dwOriginalManagedLocalNum;
3090 class MngdSafeArrayMarshaler
3093 static FCDECL4(void, CreateMarshaler, MngdSafeArrayMarshaler* pThis, MethodTable* pMT, UINT32 iRank, UINT32 dwFlags);
3094 static FCDECL3(void, ConvertSpaceToNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3095 static FCDECL4(void, ConvertContentsToNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, Object* pOriginalManagedUNSAFE);
3096 static FCDECL3(void, ConvertSpaceToManaged, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3097 static FCDECL3(void, ConvertContentsToManaged, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3098 static FCDECL3(void, ClearNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3100 enum StaticCheckStateFlags
3102 SCSF_CheckForStatic = 1,
3104 SCSF_NativeDataValid = 4
3107 MethodTable* m_pElementMT;
3110 BYTE m_fStatic; // StaticCheckStateFlags
3111 BYTE m_nolowerbounds;
3114 class ILHiddenLengthArrayMarshaler : public ILMngdMarshaler
3116 friend class MngdHiddenLengthArrayMarshaler;
3121 c_nativeSize = sizeof(LPVOID),
3122 c_CLRSize = sizeof(OBJECTREF),
3126 ILHiddenLengthArrayMarshaler() :
3127 ILMngdMarshaler(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_SPACE_TO_MANAGED,
3128 METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED,
3129 METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_SPACE_TO_NATIVE,
3130 METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE,
3131 METHOD__WIN32NATIVE__COTASKMEMFREE,
3132 METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CLEAR_NATIVE_CONTENTS,
3135 LIMITED_METHOD_CONTRACT;
3136 m_dwMngdMarshalerLocalNum = -1;
3140 virtual LocalDesc GetNativeType();
3141 virtual LocalDesc GetManagedType();
3143 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
3144 virtual void EmitMarshalArgumentCLRToNative();
3145 virtual void EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit);
3146 virtual void EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit);
3147 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3148 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3149 virtual void EmitClearNative(ILCodeStream* pslILEmit);
3150 virtual void EmitClearNativeContents(ILCodeStream* pslILEmit);
3153 bool CanUsePinnedArray();
3154 void EmitLoadNativeArrayLength(ILCodeStream *pslILEmit);
3156 virtual MethodDesc *GetConvertContentsToManagedMethod();
3157 virtual MethodDesc *GetConvertContentsToNativeMethod();
3158 virtual MethodDesc *GetClearNativeContentsMethod();
3160 MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD);
3163 class MngdHiddenLengthArrayMarshaler
3166 static FCDECL4(void, CreateMarshaler, MngdHiddenLengthArrayMarshaler* pThis, MethodTable* pMT, SIZE_T cbElement, UINT16 vt);
3167 static FCDECL3(void, ConvertSpaceToNative, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3168 static FCDECL3(void, ConvertContentsToNative, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3169 static FCDECL4(void, ConvertSpaceToManaged, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements);
3170 static FCDECL3(void, ConvertContentsToManaged, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3171 static FCDECL3(void, ClearNativeContents, MngdHiddenLengthArrayMarshaler* pThis, void** pNativeHome, INT32 cElements);
3175 SIZE_T GetArraySize(SIZE_T elements);
3176 void DoClearNativeContents(void** pNativeHome, INT32 cElements);
3179 MethodTable *m_pElementMT;
3180 SIZE_T m_cbElementSize;
3183 #endif // FEATURE_COMINTEROP
3186 class ILReferenceCustomMarshaler : public ILMngdMarshaler
3194 ILReferenceCustomMarshaler() :
3197 METHOD__MNGD_REF_CUSTOM_MARSHALER__CONVERT_CONTENTS_TO_MANAGED,
3199 METHOD__MNGD_REF_CUSTOM_MARSHALER__CONVERT_CONTENTS_TO_NATIVE,
3200 METHOD__MNGD_REF_CUSTOM_MARSHALER__CLEAR_NATIVE,
3202 METHOD__MNGD_REF_CUSTOM_MARSHALER__CLEAR_MANAGED
3205 LIMITED_METHOD_CONTRACT;
3209 virtual void EmitCreateMngdMarshaler(ILCodeStream* pslILEmit);
3212 class MngdRefCustomMarshaler
3215 static FCDECL2(void, CreateMarshaler, MngdRefCustomMarshaler* pThis, void* pCMHelper);
3216 static FCDECL3(void, ConvertContentsToNative, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3217 static FCDECL3(void, ConvertContentsToManaged, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3218 static FCDECL3(void, ClearNative, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3219 static FCDECL3(void, ClearManaged, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3221 static void DoClearNativeContents(MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome);
3223 CustomMarshalerHelper* m_pCMHelper;
3227 #ifdef FEATURE_COMINTEROP
3228 class ILUriMarshaler : public ILMarshaler
3234 c_nativeSize = sizeof(LPVOID),
3235 c_CLRSize = sizeof(OBJECTREF),
3238 static void EmitConvertCLRUriToWinRTUri(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3239 static void EmitConvertWinRTUriToCLRUri(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3242 virtual LocalDesc GetNativeType();
3243 virtual LocalDesc GetManagedType();
3245 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3246 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3248 virtual bool NeedsClearNative();
3249 void EmitClearNative(ILCodeStream* pslILEmit);
3252 class ILNCCEventArgsMarshaler : public ILMarshaler
3258 c_nativeSize = sizeof(LPVOID),
3259 c_CLRSize = sizeof(OBJECTREF),
3262 static void EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3263 static void EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3266 virtual LocalDesc GetNativeType();
3267 virtual LocalDesc GetManagedType();
3269 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3270 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3272 virtual bool NeedsClearNative();
3273 void EmitClearNative(ILCodeStream* pslILEmit);
3276 class ILPCEventArgsMarshaler : public ILMarshaler
3282 c_nativeSize = sizeof(LPVOID),
3283 c_CLRSize = sizeof(OBJECTREF),
3286 static void EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3287 static void EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain);
3290 virtual LocalDesc GetNativeType();
3291 virtual LocalDesc GetManagedType();
3293 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3294 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3296 virtual bool NeedsClearNative();
3297 void EmitClearNative(ILCodeStream* pslILEmit);
3300 class ILDateTimeMarshaler : public ILMarshaler
3306 c_nativeSize = sizeof(INT64), // = sizeof(Windows::Foundation::DateTime)
3307 c_CLRSize = VARIABLESIZE,
3311 virtual LocalDesc GetNativeType();
3312 virtual LocalDesc GetManagedType();
3314 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3315 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3317 virtual bool NeedsClearNative();
3318 virtual void EmitReInitNative(ILCodeStream* pslILEmit);
3321 class ILNullableMarshaler : public ILMarshaler
3327 c_nativeSize = sizeof(LPVOID),
3328 c_CLRSize = VARIABLESIZE,
3332 virtual LocalDesc GetNativeType();
3333 virtual LocalDesc GetManagedType();
3334 virtual bool NeedsClearNative();
3335 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3336 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3337 virtual void EmitClearNative(ILCodeStream* pslILEmit);
3340 MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD);
3343 class ILSystemTypeMarshaler : public ILMarshaler
3349 c_nativeSize = sizeof(TypeNameNative),
3350 c_CLRSize = sizeof(OBJECTREF)
3354 virtual LocalDesc GetNativeType();
3355 virtual LocalDesc GetManagedType();
3357 virtual void EmitConvertContentsCLRToNative(ILCodeStream * pslILEmit);
3358 virtual void EmitConvertContentsNativeToCLR(ILCodeStream * pslILEmit);
3360 virtual bool NeedsClearNative();
3361 virtual void EmitClearNative(ILCodeStream * pslILEmit);
3362 virtual void EmitReInitNative(ILCodeStream * pslILEmit);
3365 class ILHResultExceptionMarshaler : public ILMarshaler
3371 c_nativeSize = sizeof(INT32), // = sizeof(Windows::Foundation::HResult)
3372 c_CLRSize = sizeof(OBJECTREF),
3376 virtual LocalDesc GetNativeType();
3377 virtual LocalDesc GetManagedType();
3379 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3380 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3382 virtual bool NeedsClearNative();
3385 class ILKeyValuePairMarshaler : public ILMarshaler
3391 c_nativeSize = sizeof(LPVOID),
3392 c_CLRSize = VARIABLESIZE,
3396 virtual LocalDesc GetNativeType();
3397 virtual LocalDesc GetManagedType();
3398 virtual bool NeedsClearNative();
3399 virtual void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit);
3400 virtual void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit);
3401 virtual void EmitClearNative(ILCodeStream* pslILEmit);
3404 MethodDesc *GetExactMarshalerMethod(MethodDesc *pGenericMD);
3407 #endif // FEATURE_COMINTEROP