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.cpp
12 #include "dllimport.h"
14 #include "ilmarshalers.h"
15 #include "olevariant.h"
16 #include "comdatetime.h"
17 #include "fieldmarshaler.h"
19 LocalDesc ILReflectionObjectMarshaler::GetManagedType()
23 return LocalDesc(MscorlibBinder::GetClass(GetManagedTypeBinderID()));
26 LocalDesc ILReflectionObjectMarshaler::GetNativeType()
28 LIMITED_METHOD_CONTRACT;
30 return LocalDesc(ELEMENT_TYPE_I);
33 void ILReflectionObjectMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
37 int tokObject__m_handle = pslILEmit->GetToken(MscorlibBinder::GetField(GetObjectFieldID()));
38 int tokStruct__m_object = 0;
39 BinderFieldID structField = GetStructureFieldID();
41 // This marshaler can generate code for marshaling an object containing a handle, and for
42 // marshaling a struct referring to an object containing a handle.
45 tokStruct__m_object = pslILEmit->GetToken(MscorlibBinder::GetField(structField));
48 ILCodeLabel* pNullLabel = pslILEmit->NewCodeLabel();
50 pslILEmit->EmitLoadNullPtr();
51 EmitStoreNativeValue(pslILEmit);
53 if (tokStruct__m_object != 0)
55 EmitLoadManagedHomeAddr(pslILEmit);
56 pslILEmit->EmitLDFLD(tokStruct__m_object);
60 EmitLoadManagedValue(pslILEmit);
62 pslILEmit->EmitBRFALSE(pNullLabel);
64 if (tokStruct__m_object != 0)
66 EmitLoadManagedHomeAddr(pslILEmit);
67 pslILEmit->EmitLDFLD(tokStruct__m_object);
71 EmitLoadManagedValue(pslILEmit);
74 pslILEmit->EmitLDFLD(tokObject__m_handle);
75 EmitStoreNativeValue(pslILEmit);
77 pslILEmit->EmitLabel(pNullLabel);
79 if (IsCLRToNative(m_dwMarshalFlags))
81 // keep the object alive across the call-out to native
82 if (tokStruct__m_object != 0)
84 EmitLoadManagedHomeAddr(m_pcsUnmarshal);
85 m_pcsUnmarshal->EmitLDFLD(tokStruct__m_object);
89 EmitLoadManagedValue(m_pcsUnmarshal);
91 m_pcsUnmarshal->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
95 void ILReflectionObjectMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
99 COMPlusThrow(kTypeLoadException, IDS_EE_COM_UNSUPPORTED_SIG);
102 LocalDesc ILDelegateMarshaler::GetNativeType()
104 LIMITED_METHOD_CONTRACT;
106 return LocalDesc(ELEMENT_TYPE_I);
109 LocalDesc ILDelegateMarshaler::GetManagedType()
111 LIMITED_METHOD_CONTRACT;
113 return LocalDesc(m_pargs->m_pMT);
116 void ILDelegateMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
118 STANDARD_VM_CONTRACT;
120 ILCodeLabel* pNullLabel = pslILEmit->NewCodeLabel();
122 pslILEmit->EmitLoadNullPtr();
123 EmitStoreNativeValue(pslILEmit);
125 EmitLoadManagedValue(pslILEmit);
126 pslILEmit->EmitBRFALSE(pNullLabel);
128 EmitLoadManagedValue(pslILEmit);
129 pslILEmit->EmitCALL(METHOD__MARSHAL__GET_FUNCTION_POINTER_FOR_DELEGATE, 1, 1);
130 EmitStoreNativeValue(pslILEmit);
132 pslILEmit->EmitLabel(pNullLabel);
135 // @TODO: is there a better way to do this?
137 if (IsCLRToNative(m_dwMarshalFlags))
139 // keep the delegate ref alive across the call-out to native
140 EmitLoadManagedValue(m_pcsUnmarshal);
141 m_pcsUnmarshal->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
145 void ILDelegateMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
147 STANDARD_VM_CONTRACT;
149 ILCodeLabel* pNullLabel = pslILEmit->NewCodeLabel();
151 EmitLoadNativeValue(pslILEmit);
152 pslILEmit->EmitBRFALSE(pNullLabel);
154 EmitLoadNativeValue(pslILEmit);
155 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(m_pargs->m_pMT));
156 pslILEmit->EmitCALL(METHOD__TYPE__GET_TYPE_FROM_HANDLE, 1, 1); // Type System.Type.GetTypeFromHandle(RuntimeTypeHandle handle)
157 pslILEmit->EmitCALL(METHOD__MARSHAL__GET_DELEGATE_FOR_FUNCTION_POINTER, 2, 1); // Delegate System.Marshal.GetDelegateForFunctionPointer(IntPtr p, Type t)
158 EmitStoreManagedValue(pslILEmit);
160 pslILEmit->EmitLabel(pNullLabel);
164 LocalDesc ILBoolMarshaler::GetNativeType()
166 LIMITED_METHOD_CONTRACT;
168 return LocalDesc(GetNativeBoolElementType());
171 LocalDesc ILBoolMarshaler::GetManagedType()
173 LIMITED_METHOD_CONTRACT;
175 return LocalDesc(ELEMENT_TYPE_BOOLEAN);
178 void ILBoolMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
180 STANDARD_VM_CONTRACT;
182 ILCodeLabel* pLoadFalseLabel = pslILEmit->NewCodeLabel();
183 ILCodeLabel* pDoneLabel = pslILEmit->NewCodeLabel();
186 int trueValue = GetNativeTrueValue();
187 int falseValue = GetNativeFalseValue();
189 EmitLoadManagedValue(pslILEmit);
191 if (falseValue == 0 && trueValue == 1)
193 // this can be done without jumps
194 pslILEmit->EmitLDC(0);
195 pslILEmit->EmitCEQ();
196 pslILEmit->EmitLDC(0);
197 pslILEmit->EmitCEQ();
201 pslILEmit->EmitBRFALSE(pLoadFalseLabel);
202 pslILEmit->EmitLDC(trueValue);
203 pslILEmit->EmitBR(pDoneLabel);
205 pslILEmit->EmitPOP(); // keep the simple stack level calculator happy
207 pslILEmit->EmitLabel(pLoadFalseLabel);
208 pslILEmit->EmitLDC(falseValue);
209 pslILEmit->EmitLabel(pDoneLabel);
212 EmitStoreNativeValue(pslILEmit);
215 void ILBoolMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
217 STANDARD_VM_CONTRACT;
219 int falseValue = GetNativeFalseValue();
221 EmitLoadNativeValue(pslILEmit);
223 pslILEmit->EmitLDC(falseValue);
224 pslILEmit->EmitCEQ();
225 pslILEmit->EmitLDC(0);
226 pslILEmit->EmitCEQ();
228 EmitStoreManagedValue(pslILEmit);
232 LocalDesc ILWSTRMarshaler::GetNativeType()
234 LIMITED_METHOD_CONTRACT;
237 // pointer to value class
239 return LocalDesc(ELEMENT_TYPE_I);
242 LocalDesc ILWSTRMarshaler::GetManagedType()
244 LIMITED_METHOD_CONTRACT;
249 return LocalDesc(ELEMENT_TYPE_STRING);
252 void ILWSTRMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
254 LIMITED_METHOD_CONTRACT;
255 UNREACHABLE_MSG("Should be in-only and all other paths are covered by the EmitConvertSpaceAndContents* paths");
258 void ILWSTRMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
260 LIMITED_METHOD_CONTRACT;
261 UNREACHABLE_MSG("Should be in-only and all other paths are covered by the EmitConvertSpaceAndContents* paths");
264 void ILWSTRMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
266 LIMITED_METHOD_CONTRACT;
267 UNREACHABLE_MSG("Should be in-only and all other paths are covered by the EmitConvertSpaceAndContents* paths");
270 void ILWSTRMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
272 LIMITED_METHOD_CONTRACT;
273 UNREACHABLE_MSG("Should be in-only and all other paths are covered by the EmitConvertSpaceAndContents* paths");
276 bool ILWSTRMarshaler::NeedsClearNative()
278 LIMITED_METHOD_CONTRACT;
280 // will evaluate to true iff there is something CoTaskMemAlloc'ed that we need to free
281 bool needsClear = (IsByref(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags)) || IsRetval(m_dwMarshalFlags);
283 // m_fCoMemoryAllocated => needsClear
284 // (if we allocated the memory, we will free it; for byref [out] and retval we free memory allocated by the callee)
285 _ASSERTE(!m_fCoMemoryAllocated || needsClear);
290 void ILWSTRMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
292 STANDARD_VM_CONTRACT;
294 EmitLoadNativeValue(pslILEmit);
295 // static void CoTaskMemFree(IntPtr ptr)
296 pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
299 void ILWSTRMarshaler::EmitClearNativeTemp(ILCodeStream* pslILEmit)
301 LIMITED_METHOD_CONTRACT;
302 UNREACHABLE_MSG("The string is either pinned or a copy is stack-allocated, NeedsClearNative should have returned false");
305 bool ILWSTRMarshaler::CanUsePinnedManagedString(DWORD dwMarshalFlags)
307 LIMITED_METHOD_CONTRACT;
308 return IsCLRToNative(dwMarshalFlags) && !IsByref(dwMarshalFlags) && IsIn(dwMarshalFlags) && !IsOut(dwMarshalFlags);
312 // input stack: 0: managed string
313 // output stack: 0: (string_length+1) * sizeof(WCHAR)
315 void ILWSTRMarshaler::EmitCheckManagedStringLength(ILCodeStream* pslILEmit)
317 STANDARD_VM_CONTRACT;
319 // Note: The maximum size of managed string is under 2GB bytes. This cannot overflow.
320 pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
321 pslILEmit->EmitLDC(1);
322 pslILEmit->EmitADD();
323 pslILEmit->EmitDUP();
324 pslILEmit->EmitADD(); // (length+1) * sizeof(WCHAR)
327 void ILWSTRMarshaler::EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslILEmit)
329 STANDARD_VM_CONTRACT;
331 INDEBUG(m_fCoMemoryAllocated = true);
333 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
334 DWORD dwLengthLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
336 pslILEmit->EmitLoadNullPtr();
337 EmitStoreNativeValue(pslILEmit);
339 EmitLoadManagedValue(pslILEmit);
340 pslILEmit->EmitBRFALSE(pNullRefLabel);
342 EmitLoadManagedValue(pslILEmit);
343 EmitCheckManagedStringLength(pslILEmit);
347 pslILEmit->EmitDUP();
348 pslILEmit->EmitSTLOC(dwLengthLocalNum);
352 // static IntPtr AllocCoTaskMem(int cb)
353 pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
354 EmitStoreNativeValue(pslILEmit);
356 EmitLoadManagedValue(pslILEmit);
357 EmitLoadNativeValue(pslILEmit);
361 pslILEmit->EmitLDLOC(dwLengthLocalNum); // length
363 // static void System.String.InternalCopy(String src, IntPtr dest,int len)
364 pslILEmit->EmitCALL(METHOD__STRING__INTERNAL_COPY, 3, 0);
365 pslILEmit->EmitLabel(pNullRefLabel);
368 void ILWSTRMarshaler::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
370 STANDARD_VM_CONTRACT;
372 if (CanUsePinnedManagedString(m_dwMarshalFlags))
374 LocalDesc locDesc = GetManagedType();
375 locDesc.MakePinned();
376 DWORD dwPinnedLocal = pslILEmit->NewLocal(locDesc);
377 int fieldDef = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__STRING__M_FIRST_CHAR));
378 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
380 pslILEmit->EmitLoadNullPtr();
381 EmitStoreNativeValue(pslILEmit);
383 EmitLoadManagedValue(pslILEmit);
384 pslILEmit->EmitBRFALSE(pNullRefLabel);
386 EmitLoadManagedValue(pslILEmit);
387 pslILEmit->EmitSTLOC(dwPinnedLocal);
388 pslILEmit->EmitLDLOC(dwPinnedLocal);
389 pslILEmit->EmitLDFLDA(fieldDef);
390 EmitStoreNativeValue(pslILEmit);
392 if (g_pConfig->InteropLogArguments())
394 m_pslNDirect->EmitLogNativeArgument(pslILEmit, dwPinnedLocal);
397 pslILEmit->EmitLabel(pNullRefLabel);
402 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
403 DWORD dwLengthLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
405 pslILEmit->EmitLoadNullPtr();
406 EmitStoreNativeValue(pslILEmit);
408 EmitLoadManagedValue(pslILEmit);
409 pslILEmit->EmitBRFALSE(pNullRefLabel);
411 EmitLoadManagedValue(pslILEmit);
412 EmitCheckManagedStringLength(pslILEmit);
416 pslILEmit->EmitDUP();
417 pslILEmit->EmitSTLOC(dwLengthLocalNum);
421 pslILEmit->EmitLOCALLOC(); // @TODO: add a non-localloc path for large strings
422 EmitStoreNativeValue(pslILEmit);
424 EmitLoadManagedValue(pslILEmit);
425 EmitLoadNativeValue(pslILEmit);
429 pslILEmit->EmitLDLOC(dwLengthLocalNum); // length
431 // static void System.String.InternalCopy(String src, IntPtr dest,int len)
432 pslILEmit->EmitCALL(METHOD__STRING__INTERNAL_COPY, 3, 0);
433 pslILEmit->EmitLabel(pNullRefLabel);
438 // input stack: 0: native string
439 // output stack: 0: num chars, no null
441 void ILWSTRMarshaler::EmitCheckNativeStringLength(ILCodeStream* pslILEmit)
443 STANDARD_VM_CONTRACT;
445 pslILEmit->EmitCALL(METHOD__STRING__WCSLEN, 1, 1);
446 pslILEmit->EmitDUP();
447 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
450 void ILWSTRMarshaler::EmitConvertSpaceAndContentsNativeToCLR(ILCodeStream* pslILEmit)
452 STANDARD_VM_CONTRACT;
454 ILCodeLabel* pIsNullLabelByref = pslILEmit->NewCodeLabel();
456 EmitLoadNativeValue(pslILEmit);
457 pslILEmit->EmitBRFALSE(pIsNullLabelByref);
459 EmitLoadNativeValue(pslILEmit);
460 pslILEmit->EmitDUP();
461 EmitCheckNativeStringLength(pslILEmit);
462 pslILEmit->EmitPOP(); // pop num chars
464 pslILEmit->EmitNEWOBJ(METHOD__STRING__CTOR_CHARPTR, 1);
465 EmitStoreManagedValue(pslILEmit);
467 pslILEmit->EmitLabel(pIsNullLabelByref);
471 LocalDesc ILOptimizedAllocMarshaler::GetNativeType()
473 LIMITED_METHOD_CONTRACT;
474 return LocalDesc(ELEMENT_TYPE_I);
477 bool ILOptimizedAllocMarshaler::NeedsClearNative()
479 LIMITED_METHOD_CONTRACT;
483 void ILOptimizedAllocMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
485 STANDARD_VM_CONTRACT;
487 ILCodeLabel *pOptimize = NULL;
489 if (m_dwLocalBuffer != LOCAL_NUM_UNUSED)
491 pOptimize = pslILEmit->NewCodeLabel();
493 // if (m_dwLocalBuffer) goto Optimize
494 pslILEmit->EmitLDLOC(m_dwLocalBuffer);
495 pslILEmit->EmitBRTRUE(pOptimize);
498 EmitLoadNativeValue(pslILEmit);
499 // static void m_idClearNative(IntPtr ptr)
500 pslILEmit->EmitCALL(m_idClearNative, 1, 0);
503 if (m_dwLocalBuffer != LOCAL_NUM_UNUSED)
505 pslILEmit->EmitLabel(pOptimize);
509 LocalDesc ILUTF8BufferMarshaler::GetManagedType()
511 STANDARD_VM_CONTRACT;
512 return LocalDesc(MscorlibBinder::GetClass(CLASS__STRING_BUILDER));
515 void ILUTF8BufferMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
517 STANDARD_VM_CONTRACT;
519 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
521 pslILEmit->EmitLoadNullPtr();
522 EmitStoreNativeValue(pslILEmit);
524 EmitLoadManagedValue(pslILEmit);
525 pslILEmit->EmitBRFALSE(pNullRefLabel);
527 EmitLoadManagedValue(pslILEmit);
528 // int System.Text.StringBuilder.get_Capacity()
529 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__GET_CAPACITY, 1, 1);
530 pslILEmit->EmitDUP();
532 // static void StubHelpers.CheckStringLength(int length)
533 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
535 // Max number of bytes for UTF8 string in BMP plane is ( StringBuilder.Capacity + 1 ) * 3 + 1
536 // first +1 if the high surrogate is '?' and second +1 for null byte.
538 // stack: capacity_in_bytes
539 pslILEmit->EmitLDC(1);
540 pslILEmit->EmitADD();
543 pslILEmit->EmitLDC(3);
544 pslILEmit->EmitMUL();
546 // stack: offset_of_null
547 DWORD dwTmpOffsetOfSecretNull = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
548 pslILEmit->EmitDUP();
549 pslILEmit->EmitSTLOC(dwTmpOffsetOfSecretNull); // make sure the stack is empty for localloc
551 // make space for '\0'
552 pslILEmit->EmitLDC(1);
553 pslILEmit->EmitADD();
555 // stack: alloc_size_in_bytes
556 ILCodeLabel *pAllocRejoin = pslILEmit->NewCodeLabel();
557 if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags))
559 ILCodeLabel *pNoOptimize = pslILEmit->NewCodeLabel();
560 m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
563 pslILEmit->EmitLoadNullPtr();
564 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
566 // if (alloc_size_in_bytes > MAX_LOCAL_BUFFER_LENGTH) goto NoOptimize
567 pslILEmit->EmitDUP();
568 pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
569 pslILEmit->EmitCGT_UN();
570 pslILEmit->EmitBRTRUE(pNoOptimize);
572 pslILEmit->EmitLOCALLOC();
573 pslILEmit->EmitDUP();
574 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
575 pslILEmit->EmitBR(pAllocRejoin);
577 pslILEmit->EmitLabel(pNoOptimize);
580 // static IntPtr AllocCoTaskMem(int cb)
581 pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
583 pslILEmit->EmitLabel(pAllocRejoin);
585 // stack: native_addr
587 pslILEmit->EmitDUP();
588 EmitStoreNativeValue(pslILEmit);
590 pslILEmit->EmitLDLOC(dwTmpOffsetOfSecretNull);
592 // stack: native_addr offset_of_null
593 pslILEmit->EmitADD();
595 // stack: addr_of_null0
596 pslILEmit->EmitLDC(0);
597 pslILEmit->EmitSTIND_I1();
599 pslILEmit->EmitLabel(pNullRefLabel);
602 void ILUTF8BufferMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
604 STANDARD_VM_CONTRACT;
605 DWORD dwUtf8MarshalFlags =
606 (m_pargs->m_pMarshalInfo->GetBestFitMapping() & 0xFF) |
607 (m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar() << 8);
609 // setup to call UTF8BufferMarshaler.ConvertToNative
610 EmitLoadManagedValue(pslILEmit);
611 EmitLoadNativeValue(pslILEmit);
612 pslILEmit->EmitLDC(dwUtf8MarshalFlags);
614 //ConvertToNative(StringBuilder sb,IntPtr pNativeBuffer, int flags)
615 pslILEmit->EmitCALL(METHOD__UTF8BUFFERMARSHALER__CONVERT_TO_NATIVE, 3, 1);
616 EmitStoreNativeValue(pslILEmit);
619 void ILUTF8BufferMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
621 STANDARD_VM_CONTRACT;
623 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
625 EmitLoadNativeValue(pslILEmit);
626 pslILEmit->EmitBRFALSE(pNullRefLabel);
628 if (IsIn(m_dwMarshalFlags) || IsCLRToNative(m_dwMarshalFlags))
630 EmitLoadNativeValue(pslILEmit);
631 // static int System.String.strlen(byte* ptr)
632 pslILEmit->EmitCALL(METHOD__STRING__STRLEN, 1, 1);
636 // don't touch the native buffer in the native->CLR out-only case
637 pslILEmit->EmitLDC(0);
639 // Convert to UTF8 and then call
640 // System.Text.StringBuilder..ctor(int capacity)
641 pslILEmit->EmitNEWOBJ(METHOD__STRING_BUILDER__CTOR_INT, 1);
642 EmitStoreManagedValue(pslILEmit);
643 pslILEmit->EmitLabel(pNullRefLabel);
646 void ILUTF8BufferMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
648 STANDARD_VM_CONTRACT;
650 EmitLoadManagedValue(pslILEmit);
651 EmitLoadNativeValue(pslILEmit);
653 //void UTF8BufferMarshaler.ConvertToManaged(StringBuilder sb, IntPtr pNative)
654 pslILEmit->EmitCALL(METHOD__UTF8BUFFERMARSHALER__CONVERT_TO_MANAGED, 2, 0);
658 LocalDesc ILWSTRBufferMarshaler::GetManagedType()
660 STANDARD_VM_CONTRACT;
662 return LocalDesc(MscorlibBinder::GetClass(CLASS__STRING_BUILDER));
665 void ILWSTRBufferMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
667 STANDARD_VM_CONTRACT;
669 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
671 pslILEmit->EmitLoadNullPtr();
672 EmitStoreNativeValue(pslILEmit);
674 EmitLoadManagedValue(pslILEmit);
675 pslILEmit->EmitBRFALSE(pNullRefLabel);
677 EmitLoadManagedValue(pslILEmit);
678 // int System.Text.StringBuilder.get_Capacity()
679 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__GET_CAPACITY, 1, 1);
680 pslILEmit->EmitDUP();
682 // static void StubHelpers.CheckStringLength(int length)
683 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
687 pslILEmit->EmitLDC(2);
688 pslILEmit->EmitMUL();
690 // stack: capacity_in_bytes
692 pslILEmit->EmitLDC(2);
693 pslILEmit->EmitADD();
695 // stack: offset_of_secret_null
697 DWORD dwTmpOffsetOfSecretNull = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
698 pslILEmit->EmitDUP();
699 pslILEmit->EmitSTLOC(dwTmpOffsetOfSecretNull); // make sure the stack is empty for localloc
701 pslILEmit->EmitLDC(2);
702 pslILEmit->EmitADD();
704 // stack: alloc_size_in_bytes
705 ILCodeLabel *pAllocRejoin = pslILEmit->NewCodeLabel();
706 if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags))
708 ILCodeLabel *pNoOptimize = pslILEmit->NewCodeLabel();
709 m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
712 pslILEmit->EmitLoadNullPtr();
713 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
715 // if (alloc_size_in_bytes > MAX_LOCAL_BUFFER_LENGTH) goto NoOptimize
716 pslILEmit->EmitDUP();
717 pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
718 pslILEmit->EmitCGT_UN();
719 pslILEmit->EmitBRTRUE(pNoOptimize);
721 pslILEmit->EmitLOCALLOC();
722 pslILEmit->EmitDUP();
723 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
724 pslILEmit->EmitBR(pAllocRejoin);
726 pslILEmit->EmitLabel(pNoOptimize);
729 // static IntPtr AllocCoTaskMem(int cb)
730 pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
732 pslILEmit->EmitLabel(pAllocRejoin);
734 // stack: native_addr
736 pslILEmit->EmitDUP();
737 EmitStoreNativeValue(pslILEmit);
739 pslILEmit->EmitLDLOC(dwTmpOffsetOfSecretNull);
741 // stack: offset_of_secret_null native_addr
743 pslILEmit->EmitADD();
745 // stack: addr_of_secret_null
747 pslILEmit->EmitLDC(0);
749 // stack: addr_of_secret_null 0
751 pslILEmit->EmitSTIND_I2();
752 pslILEmit->EmitLabel(pNullRefLabel);
755 void ILWSTRBufferMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
757 STANDARD_VM_CONTRACT;
759 DWORD dwTempNumBytesLocal = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
761 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
763 EmitLoadNativeValue(pslILEmit);
764 pslILEmit->EmitBRFALSE(pNullRefLabel);
766 EmitLoadManagedValue(pslILEmit);
767 pslILEmit->EmitDUP();
769 // stack: StringBuilder StringBuilder
771 // int System.Text.StringBuilder.get_Length()
772 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__GET_LENGTH, 1, 1);
774 // stack: StringBuilder length
775 pslILEmit->EmitDUP();
776 // static void StubHelpers.CheckStringLength(int length)
777 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
779 // stack: StringBuilder length
781 pslILEmit->EmitDUP();
782 pslILEmit->EmitADD();
784 // stack: StringBuilder cb
786 pslILEmit->EmitSTLOC(dwTempNumBytesLocal);
788 // stack: StringBuilder
790 EmitLoadNativeValue(pslILEmit);
791 pslILEmit->EmitLDLOC(dwTempNumBytesLocal);
793 // stack: stringbuilder native_buffer cb
795 // void System.Text.StringBuilder.InternalCopy(IntPtr dest,int len)
796 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__INTERNAL_COPY, 3, 0);
799 // null-terminate the native string
801 EmitLoadNativeValue(pslILEmit);
802 pslILEmit->EmitLDLOC(dwTempNumBytesLocal);
803 pslILEmit->EmitADD();
804 pslILEmit->EmitLDC(0);
805 pslILEmit->EmitSTIND_I2();
807 pslILEmit->EmitLabel(pNullRefLabel);
810 void ILWSTRBufferMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
812 STANDARD_VM_CONTRACT;
814 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
816 EmitLoadNativeValue(pslILEmit);
817 pslILEmit->EmitBRFALSE(pNullRefLabel);
819 if (IsIn(m_dwMarshalFlags) || IsCLRToNative(m_dwMarshalFlags))
821 EmitLoadNativeValue(pslILEmit);
822 // static int System.String.wcslen(char *ptr)
823 pslILEmit->EmitCALL(METHOD__STRING__WCSLEN, 1, 1);
827 // don't touch the native buffer in the native->CLR out-only case
828 pslILEmit->EmitLDC(0);
831 // System.Text.StringBuilder..ctor(int capacity)
832 pslILEmit->EmitNEWOBJ(METHOD__STRING_BUILDER__CTOR_INT, 1);
833 EmitStoreManagedValue(pslILEmit);
835 pslILEmit->EmitLabel(pNullRefLabel);
838 void ILWSTRBufferMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
840 STANDARD_VM_CONTRACT;
842 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
844 EmitLoadNativeValue(pslILEmit);
845 pslILEmit->EmitBRFALSE(pNullRefLabel);
847 EmitLoadManagedValue(pslILEmit);
848 EmitLoadNativeValue(pslILEmit);
850 pslILEmit->EmitDUP();
851 // static int System.String.wcslen(char *ptr)
852 pslILEmit->EmitCALL(METHOD__STRING__WCSLEN, 1, 1);
854 // void System.Text.StringBuilder.ReplaceBuffer(char* newBuffer, int newLength);
855 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__REPLACE_BUFFER_INTERNAL, 3, 0);
856 pslILEmit->EmitLabel(pNullRefLabel);
859 LocalDesc ILCSTRBufferMarshaler::GetManagedType()
861 STANDARD_VM_CONTRACT;
863 return LocalDesc(MscorlibBinder::GetClass(CLASS__STRING_BUILDER));
866 void ILCSTRBufferMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
868 STANDARD_VM_CONTRACT;
870 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
872 pslILEmit->EmitLoadNullPtr();
873 EmitStoreNativeValue(pslILEmit);
875 EmitLoadManagedValue(pslILEmit);
876 pslILEmit->EmitBRFALSE(pNullRefLabel);
878 EmitLoadManagedValue(pslILEmit);
879 // int System.Text.StringBuilder.get_Capacity()
880 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__GET_CAPACITY, 1, 1);
881 pslILEmit->EmitDUP();
883 // static void StubHelpers.CheckStringLength(int length)
884 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
888 pslILEmit->EmitLDSFLD(pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__MARSHAL__SYSTEM_MAX_DBCS_CHAR_SIZE)));
889 pslILEmit->EmitMUL_OVF();
891 // stack: capacity_in_bytes
893 pslILEmit->EmitLDC(1);
894 pslILEmit->EmitADD_OVF();
896 // stack: offset_of_secret_null
898 DWORD dwTmpOffsetOfSecretNull = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
899 pslILEmit->EmitDUP();
900 pslILEmit->EmitSTLOC(dwTmpOffsetOfSecretNull); // make sure the stack is empty for localloc
902 pslILEmit->EmitLDC(3);
903 pslILEmit->EmitADD_OVF();
905 // stack: alloc_size_in_bytes
906 ILCodeLabel *pAllocRejoin = pslILEmit->NewCodeLabel();
907 if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags))
909 ILCodeLabel *pNoOptimize = pslILEmit->NewCodeLabel();
910 m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
913 pslILEmit->EmitLoadNullPtr();
914 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
916 // if (alloc_size_in_bytes > MAX_LOCAL_BUFFER_LENGTH) goto NoOptimize
917 pslILEmit->EmitDUP();
918 pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
919 pslILEmit->EmitCGT_UN();
920 pslILEmit->EmitBRTRUE(pNoOptimize);
922 pslILEmit->EmitLOCALLOC();
923 pslILEmit->EmitDUP();
924 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
925 pslILEmit->EmitBR(pAllocRejoin);
927 pslILEmit->EmitLabel(pNoOptimize);
930 // static IntPtr AllocCoTaskMem(int cb)
931 pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
933 pslILEmit->EmitLabel(pAllocRejoin);
935 // stack: native_addr
937 pslILEmit->EmitDUP();
938 EmitStoreNativeValue(pslILEmit);
940 pslILEmit->EmitLDLOC(dwTmpOffsetOfSecretNull);
942 // stack: native_addr offset_of_secret_null
944 pslILEmit->EmitADD();
946 // stack: addr_of_secret_null0
948 pslILEmit->EmitDUP();
949 pslILEmit->EmitLDC(0);
950 pslILEmit->EmitSTIND_I1();
952 // stack: addr_of_secret_null0
954 pslILEmit->EmitDUP();
955 pslILEmit->EmitLDC(1);
956 pslILEmit->EmitADD();
957 pslILEmit->EmitLDC(0);
958 pslILEmit->EmitSTIND_I1();
960 // stack: addr_of_secret_null0
962 pslILEmit->EmitLDC(2);
963 pslILEmit->EmitADD();
964 pslILEmit->EmitLDC(0);
965 pslILEmit->EmitSTIND_I1();
967 pslILEmit->EmitLabel(pNullRefLabel);
970 void ILCSTRBufferMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
972 STANDARD_VM_CONTRACT;
974 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
975 DWORD dwNumBytesLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
976 DWORD dwSrcLocal = pslILEmit->NewLocal(ELEMENT_TYPE_OBJECT);
978 EmitLoadNativeValue(pslILEmit);
979 pslILEmit->EmitBRFALSE(pNullRefLabel);
981 EmitLoadManagedValue(pslILEmit);
982 // int System.Text.StringBuilder.get_Length()
983 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__GET_LENGTH, 1, 1);
984 // static void StubHelpers.CheckStringLength(int length)
985 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
987 EmitLoadManagedValue(pslILEmit);
988 // String System.Text.StringBuilder.ToString()
989 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__TO_STRING, 1, 1);
990 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetBestFitMapping());
991 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar());
992 pslILEmit->EmitLDLOCA(dwNumBytesLocalNum);
994 // static byte[] DoAnsiConversion(string str, bool fBestFit, bool fThrowOnUnmappableChar, out int cbLength)
995 pslILEmit->EmitCALL(METHOD__ANSICHARMARSHALER__DO_ANSI_CONVERSION, 4, 1);
996 pslILEmit->EmitSTLOC(dwSrcLocal);
997 EmitLoadNativeValue(pslILEmit); // pDest
998 pslILEmit->EmitLDC(0); // destIndex
999 pslILEmit->EmitLDLOC(dwSrcLocal); // src[]
1000 pslILEmit->EmitLDC(0); // srcIndex
1001 pslILEmit->EmitLDLOC(dwNumBytesLocalNum); // len
1003 // static void Memcpy(byte* pDest, int destIndex, byte[] src, int srcIndex, int len)
1004 pslILEmit->EmitCALL(METHOD__BUFFER__MEMCPY_PTRBYTE_ARRBYTE, 5, 0);
1006 // null terminate the string
1007 EmitLoadNativeValue(pslILEmit);
1008 pslILEmit->EmitLDLOC(dwNumBytesLocalNum);
1009 pslILEmit->EmitADD();
1010 pslILEmit->EmitLDC(0);
1011 pslILEmit->EmitSTIND_I1();
1013 pslILEmit->EmitLabel(pNullRefLabel);
1016 void ILCSTRBufferMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
1018 STANDARD_VM_CONTRACT;
1020 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
1022 EmitLoadNativeValue(pslILEmit);
1023 pslILEmit->EmitBRFALSE(pNullRefLabel);
1025 if (IsIn(m_dwMarshalFlags) || IsCLRToNative(m_dwMarshalFlags))
1027 EmitLoadNativeValue(pslILEmit);
1028 // static int System.String.strlen(byte* ptr)
1029 pslILEmit->EmitCALL(METHOD__STRING__STRLEN, 1, 1);
1033 // don't touch the native buffer in the native->CLR out-only case
1034 pslILEmit->EmitLDC(0);
1037 // System.Text.StringBuilder..ctor(int capacity)
1038 pslILEmit->EmitNEWOBJ(METHOD__STRING_BUILDER__CTOR_INT, 1);
1039 EmitStoreManagedValue(pslILEmit);
1041 pslILEmit->EmitLabel(pNullRefLabel);
1044 void ILCSTRBufferMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1046 STANDARD_VM_CONTRACT;
1048 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
1050 EmitLoadNativeValue(pslILEmit);
1051 pslILEmit->EmitBRFALSE(pNullRefLabel);
1053 EmitLoadManagedValue(pslILEmit);
1054 EmitLoadNativeValue(pslILEmit);
1056 pslILEmit->EmitDUP();
1057 // static int System.String.strlen(byte* ptr)
1058 pslILEmit->EmitCALL(METHOD__STRING__STRLEN, 1, 1);
1060 // void System.Text.StringBuilder.ReplaceBuffer(sbyte* newBuffer, int newLength);
1061 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__REPLACE_BUFFER_ANSI_INTERNAL, 3, 0);
1063 pslILEmit->EmitLabel(pNullRefLabel);
1068 LocalDesc ILValueClassMarshaler::GetNativeType()
1070 STANDARD_VM_CONTRACT;
1072 return LocalDesc(TypeHandle(m_pargs->m_pMT).MakeNativeValueType());
1075 LocalDesc ILValueClassMarshaler::GetManagedType()
1077 LIMITED_METHOD_CONTRACT;
1079 return LocalDesc(m_pargs->m_pMT);
1082 void ILValueClassMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
1084 STANDARD_VM_CONTRACT;
1086 EmitLoadNativeHomeAddr(pslILEmit);
1087 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(TypeHandle(m_pargs->m_pMT).MakeNativeValueType()));
1090 bool ILValueClassMarshaler::NeedsClearNative()
1095 void ILValueClassMarshaler::EmitClearNative(ILCodeStream * pslILEmit)
1097 STANDARD_VM_CONTRACT;
1099 mdToken managedVCToken = pslILEmit->GetToken(m_pargs->m_pMT);
1101 EmitLoadNativeHomeAddr(pslILEmit);
1102 pslILEmit->EmitLDTOKEN(managedVCToken); // pMT
1103 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1104 pslILEmit->EmitCALL(METHOD__VALUECLASSMARSHALER__CLEAR_NATIVE, 2, 0);
1108 void ILValueClassMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1110 STANDARD_VM_CONTRACT;
1112 mdToken managedVCToken = pslILEmit->GetToken(m_pargs->m_pMT);
1114 EmitLoadNativeHomeAddr(pslILEmit); // dst
1115 EmitLoadManagedHomeAddr(pslILEmit); // src
1116 pslILEmit->EmitLDTOKEN(managedVCToken); // pMT
1117 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1); // Convert RTH to IntPtr
1119 m_pslNDirect->LoadCleanupWorkList(pslILEmit);
1120 pslILEmit->EmitCALL(METHOD__VALUECLASSMARSHALER__CONVERT_TO_NATIVE, 4, 0); // void ConvertToNative(IntPtr dst, IntPtr src, IntPtr pMT, ref CleanupWorkListElement pCleanupWorkList)
1123 void ILValueClassMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1125 STANDARD_VM_CONTRACT;
1127 mdToken managedVCToken = pslILEmit->GetToken(m_pargs->m_pMT);
1129 EmitLoadManagedHomeAddr(pslILEmit); // dst
1130 EmitLoadNativeHomeAddr(pslILEmit); // src
1131 pslILEmit->EmitLDTOKEN(managedVCToken); // pMT
1132 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1133 pslILEmit->EmitCALL(METHOD__VALUECLASSMARSHALER__CONVERT_TO_MANAGED, 3, 0); // void ConvertToManaged(IntPtr dst, IntPtr src, IntPtr pMT)
1137 #ifdef FEATURE_COMINTEROP
1138 LocalDesc ILObjectMarshaler::GetNativeType()
1140 STANDARD_VM_CONTRACT;
1142 return LocalDesc(TypeHandle(MscorlibBinder::GetClass(CLASS__NATIVEVARIANT)));
1145 LocalDesc ILObjectMarshaler::GetManagedType()
1147 LIMITED_METHOD_CONTRACT;
1149 return LocalDesc(ELEMENT_TYPE_OBJECT);
1152 void ILObjectMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1154 STANDARD_VM_CONTRACT;
1156 if (!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
1158 // Keep the VARIANT as it is - the stubhelper will do a VT_BYREF check on it.
1162 // V_VT(pDest) = VT_EMPTY
1163 EmitReInitNative(pslILEmit);
1166 EmitLoadManagedValue(pslILEmit); // load src
1167 EmitLoadNativeHomeAddr(pslILEmit); // load dst
1168 pslILEmit->EmitCALL(METHOD__OBJECTMARSHALER__CONVERT_TO_NATIVE, 2, 0); // void ConvertToNative(object objSrc, IntPtr pDstVariant)
1171 void ILObjectMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1173 STANDARD_VM_CONTRACT;
1175 EmitLoadNativeHomeAddr(pslILEmit);
1176 pslILEmit->EmitCALL(METHOD__OBJECTMARSHALER__CONVERT_TO_MANAGED, 1, 1); // object ConvertToManaged(IntPtr pSrcVariant);
1177 EmitStoreManagedValue(pslILEmit);
1180 bool ILObjectMarshaler::NeedsClearNative()
1182 LIMITED_METHOD_CONTRACT;
1186 void ILObjectMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1188 STANDARD_VM_CONTRACT;
1190 if (!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
1192 // We don't want to clear variants passed from native by-ref here as we
1193 // want to be able to detect the VT_BYREF case during backpropagation.
1195 // @TODO: We shouldn't be skipping the call if pslILEmit is ILStubLinker::kExceptionCleanup
1196 // because we always want to do real cleanup in this stream.
1200 EmitLoadNativeHomeAddr(pslILEmit);
1201 pslILEmit->EmitCALL(METHOD__OBJECTMARSHALER__CLEAR_NATIVE, 1, 0);
1205 void ILObjectMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
1210 CONSISTENCY_CHECK(offsetof(VARIANT, vt) == 0);
1214 if (!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
1216 // We don't want to clear variants passed from native by-ref here as we
1217 // want to be able to detect the VT_BYREF case during backpropagation.
1221 EmitLoadNativeHomeAddr(pslILEmit);
1222 pslILEmit->EmitLDC(VT_EMPTY);
1223 pslILEmit->EmitSTIND_I2();
1226 #endif // FEATURE_COMINTEROP
1228 LocalDesc ILDateMarshaler::GetNativeType()
1230 LIMITED_METHOD_CONTRACT;
1232 return LocalDesc(ELEMENT_TYPE_R8);
1235 LocalDesc ILDateMarshaler::GetManagedType()
1237 STANDARD_VM_CONTRACT;
1239 return LocalDesc(MscorlibBinder::GetClass(CLASS__DATE_TIME));
1242 void ILDateMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1244 STANDARD_VM_CONTRACT;
1246 EmitLoadManagedValue(pslILEmit);
1247 // double ConvertToNative(INT64 managedDate)
1248 pslILEmit->EmitCALL(METHOD__DATEMARSHALER__CONVERT_TO_NATIVE, 1, 1);
1249 EmitStoreNativeValue(pslILEmit);
1252 void ILDateMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1254 STANDARD_VM_CONTRACT;
1256 // will call DateTime constructor on managed home
1257 EmitLoadManagedHomeAddr(pslILEmit);
1259 EmitLoadNativeValue(pslILEmit);
1260 // long ConvertToNative(double nativeData)
1261 pslILEmit->EmitCALL(METHOD__DATEMARSHALER__CONVERT_TO_MANAGED, 1, 1);
1263 pslILEmit->EmitCALL(METHOD__DATE_TIME__LONG_CTOR, 2, 0);
1266 void ILDateMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
1268 STANDARD_VM_CONTRACT;
1270 // ldc.i4.0, conv.r8 is shorter than ldc.r8 0.0
1271 pslILEmit->EmitLDC(0);
1272 pslILEmit->EmitCONV_R8();
1273 EmitStoreNativeValue(pslILEmit);
1276 LocalDesc ILCurrencyMarshaler::GetNativeType()
1278 STANDARD_VM_CONTRACT;
1280 return LocalDesc(TypeHandle(MscorlibBinder::GetClass(CLASS__CURRENCY)));
1283 LocalDesc ILCurrencyMarshaler::GetManagedType()
1285 STANDARD_VM_CONTRACT;
1287 return LocalDesc(TypeHandle(MscorlibBinder::GetClass(CLASS__DECIMAL)));
1291 void ILCurrencyMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
1293 STANDARD_VM_CONTRACT;
1295 EmitLoadNativeHomeAddr(pslILEmit);
1296 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(TypeHandle(MscorlibBinder::GetClass(CLASS__CURRENCY))));
1299 void ILCurrencyMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1301 STANDARD_VM_CONTRACT;
1303 EmitLoadNativeHomeAddr(pslILEmit);
1304 EmitLoadManagedValue(pslILEmit);
1306 pslILEmit->EmitCALL(METHOD__CURRENCY__DECIMAL_CTOR, 2, 0);
1309 void ILCurrencyMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1311 STANDARD_VM_CONTRACT;
1313 EmitLoadManagedHomeAddr(pslILEmit);
1314 EmitLoadNativeValue(pslILEmit);
1316 pslILEmit->EmitCALL(METHOD__DECIMAL__CURRENCY_CTOR, 2, 0);
1320 #ifdef FEATURE_COMINTEROP
1321 LocalDesc ILInterfaceMarshaler::GetNativeType()
1323 LIMITED_METHOD_CONTRACT;
1325 return LocalDesc(ELEMENT_TYPE_I);
1328 LocalDesc ILInterfaceMarshaler::GetManagedType()
1330 LIMITED_METHOD_CONTRACT;
1332 return LocalDesc(ELEMENT_TYPE_OBJECT);
1335 void ILInterfaceMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1337 STANDARD_VM_CONTRACT;
1339 ItfMarshalInfo itfInfo;
1340 m_pargs->m_pMarshalInfo->GetItfMarshalInfo(&itfInfo);
1342 EmitLoadManagedValue(pslILEmit);
1344 if (itfInfo.thNativeItf.GetMethodTable())
1346 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(itfInfo.thNativeItf.GetMethodTable()));
1347 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1351 pslILEmit->EmitLoadNullPtr();
1354 if (itfInfo.thClass.GetMethodTable())
1356 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(itfInfo.thClass.GetMethodTable()));
1357 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1361 pslILEmit->EmitLoadNullPtr();
1363 pslILEmit->EmitLDC(itfInfo.dwFlags);
1365 // static IntPtr ConvertToNative(object objSrc, IntPtr itfMT, IntPtr classMT, int flags);
1366 pslILEmit->EmitCALL(METHOD__INTERFACEMARSHALER__CONVERT_TO_NATIVE, 4, 1);
1368 EmitStoreNativeValue(pslILEmit);
1370 if (IsCLRToNative(m_dwMarshalFlags) &&
1371 m_pargs->m_pMarshalInfo->IsWinRTScenario())
1373 // If we are calling from CLR into WinRT and we are passing an interface to WinRT, we need to
1374 // keep the object alive across unmanaged call because Jupiter might need to add this
1375 // RCW into their live tree and whatever CCWs referenced by this RCW could get collected
1376 // before the call to native, for example:
1378 // Button btn = new Button();
1379 // btn.OnClick += ...
1380 // m_grid.Children.Add(btn)
1382 // In this case, btn could be collected and takes the delegate CCW with it, before Children.add
1383 // native method is called, and as a result Jupiter will add the neutered CCW into the tree
1385 // The fix is to extend the lifetime of the argument across the call to native by doing a GC.KeepAlive
1386 // keep the delegate ref alive across the call-out to native
1387 EmitLoadManagedValue(m_pcsUnmarshal);
1388 m_pcsUnmarshal->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
1392 void ILInterfaceMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1394 STANDARD_VM_CONTRACT;
1396 ItfMarshalInfo itfInfo;
1397 m_pargs->m_pMarshalInfo->GetItfMarshalInfo(&itfInfo);
1399 // the helper may assign NULL to the home (see below)
1400 EmitLoadNativeHomeAddr(pslILEmit);
1402 if (IsCLRToNative(m_dwMarshalFlags) && m_pargs->m_pMarshalInfo->IsWinRTScenario())
1404 // We are converting an interface pointer to object in a CLR->native stub which means
1405 // that the interface pointer has been AddRef'ed for us by the callee. If we end up
1406 // wrapping it with a new RCW, we can omit another AddRef/Release pair. Note that if
1407 // a new RCW is created the native home will be zeroed out by the helper so the call
1408 // to InterfaceMarshaler__ClearNative will become a no-op.
1410 // Note that we are only doing this for WinRT scenarios to reduce the risk of this change
1411 itfInfo.dwFlags |= ItfMarshalInfo::ITF_MARSHAL_SUPPRESS_ADDREF;
1414 if (itfInfo.thItf.GetMethodTable())
1416 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(itfInfo.thItf.GetMethodTable()));
1417 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1421 pslILEmit->EmitLoadNullPtr();
1424 if (itfInfo.thClass.GetMethodTable())
1426 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(itfInfo.thClass.GetMethodTable()));
1427 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1431 pslILEmit->EmitLoadNullPtr();
1433 pslILEmit->EmitLDC(itfInfo.dwFlags);
1435 // static object ConvertToManaged(IntPtr pUnk, IntPtr itfMT, IntPtr classMT, int flags);
1436 pslILEmit->EmitCALL(METHOD__INTERFACEMARSHALER__CONVERT_TO_MANAGED, 4, 1);
1438 EmitStoreManagedValue(pslILEmit);
1441 bool ILInterfaceMarshaler::NeedsClearNative()
1443 LIMITED_METHOD_CONTRACT;
1447 void ILMarshaler::EmitInterfaceClearNative(ILCodeStream* pslILEmit)
1449 STANDARD_VM_CONTRACT;
1451 ILCodeLabel *pSkipClearNativeLabel = pslILEmit->NewCodeLabel();
1452 EmitLoadNativeValue(pslILEmit);
1453 pslILEmit->EmitBRFALSE(pSkipClearNativeLabel);
1454 EmitLoadNativeValue(pslILEmit);
1455 // static void ClearNative(IntPtr pUnk);
1456 pslILEmit->EmitCALL(METHOD__INTERFACEMARSHALER__CLEAR_NATIVE, 1, 0);
1457 pslILEmit->EmitLabel(pSkipClearNativeLabel);
1460 void ILInterfaceMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1462 STANDARD_VM_CONTRACT;
1463 EmitInterfaceClearNative(pslILEmit);
1465 #endif // FEATURE_COMINTEROP
1468 LocalDesc ILAnsiCharMarshaler::GetNativeType()
1470 LIMITED_METHOD_CONTRACT;
1472 return LocalDesc(ELEMENT_TYPE_U1);
1475 LocalDesc ILAnsiCharMarshaler::GetManagedType()
1477 LIMITED_METHOD_CONTRACT;
1479 return LocalDesc(ELEMENT_TYPE_CHAR);
1482 void ILAnsiCharMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1484 STANDARD_VM_CONTRACT;
1486 EmitLoadManagedValue(pslILEmit);
1487 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetBestFitMapping());
1488 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar());
1489 pslILEmit->EmitCALL(METHOD__ANSICHARMARSHALER__CONVERT_TO_NATIVE, 3, 1);
1490 EmitStoreNativeValue(pslILEmit);
1493 void ILAnsiCharMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1495 STANDARD_VM_CONTRACT;
1497 EmitLoadNativeValue(pslILEmit);
1498 pslILEmit->EmitCALL(METHOD__ANSICHARMARSHALER__CONVERT_TO_MANAGED, 1, 1);
1499 EmitStoreManagedValue(pslILEmit);
1502 #ifdef FEATURE_COMINTEROP
1503 LocalDesc ILOleColorMarshaler::GetNativeType()
1505 LIMITED_METHOD_CONTRACT;
1507 return LocalDesc(ELEMENT_TYPE_I4);
1510 LocalDesc ILOleColorMarshaler::GetManagedType()
1512 STANDARD_VM_CONTRACT;
1514 BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
1515 TypeHandle hndColorType = pDomain->GetMarshalingData()->GetOleColorMarshalingInfo()->GetColorType();
1520 return LocalDesc(hndColorType); // System.Drawing.Color
1523 void ILOleColorMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1525 STANDARD_VM_CONTRACT;
1527 BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
1528 MethodDesc* pConvertMD = pDomain->GetMarshalingData()->GetOleColorMarshalingInfo()->GetSystemColorToOleColorMD();
1530 EmitLoadManagedValue(pslILEmit);
1531 // int System.Drawing.ColorTranslator.ToOle(System.Drawing.Color c)
1532 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
1533 EmitStoreNativeValue(pslILEmit);
1536 void ILOleColorMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1538 STANDARD_VM_CONTRACT;
1540 BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
1541 MethodDesc* pConvertMD = pDomain->GetMarshalingData()->GetOleColorMarshalingInfo()->GetOleColorToSystemColorMD();
1543 EmitLoadNativeValue(pslILEmit);
1544 // System.Drawing.Color System.Drawing.ColorTranslator.FromOle(int oleColor)
1545 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
1546 EmitStoreManagedValue(pslILEmit);
1549 bool ILVBByValStrWMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
1551 LIMITED_METHOD_CONTRACT;
1552 if (IsCLRToNative(dwMarshalFlags) && IsByref(dwMarshalFlags) && IsIn(dwMarshalFlags) && IsOut(dwMarshalFlags))
1557 *pErrorResID = IDS_EE_BADMARSHAL_VBBYVALSTRRESTRICTION;
1561 bool ILVBByValStrWMarshaler::SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
1563 LIMITED_METHOD_CONTRACT;
1564 *pErrorResID = IDS_EE_BADMARSHAL_VBBYVALSTRRESTRICTION;
1568 LocalDesc ILVBByValStrWMarshaler::GetNativeType()
1570 LIMITED_METHOD_CONTRACT;
1572 return LocalDesc(ELEMENT_TYPE_I); // BSTR
1575 LocalDesc ILVBByValStrWMarshaler::GetManagedType()
1577 LIMITED_METHOD_CONTRACT;
1579 return LocalDesc(ELEMENT_TYPE_STRING);
1582 bool ILVBByValStrWMarshaler::IsNativePassedByRef()
1584 LIMITED_METHOD_CONTRACT;
1588 void ILVBByValStrWMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1590 STANDARD_VM_CONTRACT;
1592 ILCodeStream *pcsSetup = m_pslNDirect->GetSetupCodeStream();
1593 m_dwLocalBuffer = pcsSetup->NewLocal(ELEMENT_TYPE_I);
1594 pcsSetup->EmitLoadNullPtr();
1595 pcsSetup->EmitSTLOC(m_dwLocalBuffer);
1598 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
1599 m_dwCCHLocal = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
1600 DWORD dwNumBytesLocal = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
1602 pslILEmit->EmitLoadNullPtr();
1603 EmitStoreNativeValue(pslILEmit);
1605 EmitLoadManagedValue(pslILEmit);
1606 pslILEmit->EmitBRFALSE(pNullRefLabel);
1608 EmitLoadManagedValue(pslILEmit);
1609 pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
1610 pslILEmit->EmitDUP();
1611 pslILEmit->EmitSTLOC(m_dwCCHLocal);
1615 pslILEmit->EmitLDC(1);
1616 pslILEmit->EmitADD();
1617 pslILEmit->EmitDUP();
1618 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
1619 pslILEmit->EmitDUP();
1620 pslILEmit->EmitADD(); // (length+1) * sizeof(WCHAR)
1621 pslILEmit->EmitDUP();
1622 pslILEmit->EmitSTLOC(dwNumBytesLocal); // len <- doesn't include size of the DWORD preceeding the string
1623 pslILEmit->EmitLDC(sizeof(DWORD));
1624 pslILEmit->EmitADD(); // (length+1) * sizeof(WCHAR) + sizeof(DWORD)
1628 ILCodeLabel* pNoOptimizeLabel = pslILEmit->NewCodeLabel();
1629 ILCodeLabel* pAllocRejoinLabel = pslILEmit->NewCodeLabel();
1630 pslILEmit->EmitDUP();
1631 pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
1632 pslILEmit->EmitCGT_UN();
1633 pslILEmit->EmitBRTRUE(pNoOptimizeLabel);
1635 pslILEmit->EmitLOCALLOC();
1636 pslILEmit->EmitBR(pAllocRejoinLabel);
1638 pslILEmit->EmitLabel(pNoOptimizeLabel);
1639 pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
1640 pslILEmit->EmitDUP();
1641 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
1643 pslILEmit->EmitLabel(pAllocRejoinLabel);
1644 pslILEmit->EmitDUP();
1645 pslILEmit->EmitLDLOC(m_dwCCHLocal);
1646 pslILEmit->EmitSTIND_I4();
1647 pslILEmit->EmitLDC(sizeof(DWORD));
1648 pslILEmit->EmitADD();
1649 EmitStoreNativeValue(pslILEmit);
1653 EmitLoadManagedValue(pslILEmit); // src
1654 EmitLoadNativeValue(pslILEmit); // dest
1655 pslILEmit->EmitLDLOC(dwNumBytesLocal); // len
1657 // static void System.String.InternalCopy(String src, IntPtr dest,int len)
1658 pslILEmit->EmitCALL(METHOD__STRING__INTERNAL_COPY, 3, 0);
1660 pslILEmit->EmitLabel(pNullRefLabel);
1663 void ILVBByValStrWMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1665 STANDARD_VM_CONTRACT;
1667 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
1668 EmitLoadNativeValue(pslILEmit);
1669 pslILEmit->EmitBRFALSE(pNullRefLabel);
1671 pslILEmit->EmitLDNULL(); // this
1672 EmitLoadNativeValue(pslILEmit); // ptr
1673 pslILEmit->EmitLDC(0); // startIndex
1674 pslILEmit->EmitLDLOC(m_dwCCHLocal); // length
1676 // String CtorCharPtrStartLength(char *ptr, int startIndex, int length)
1677 // TODO Phase5: Why do we call this weirdo?
1678 pslILEmit->EmitCALL(METHOD__STRING__CTORF_CHARPTR_START_LEN, 4, 1);
1680 EmitStoreManagedValue(pslILEmit);
1681 pslILEmit->EmitLabel(pNullRefLabel);
1685 bool ILVBByValStrWMarshaler::NeedsClearNative()
1687 LIMITED_METHOD_CONTRACT;
1691 void ILVBByValStrWMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1693 STANDARD_VM_CONTRACT;
1695 ILCodeLabel* pExitLabel = pslILEmit->NewCodeLabel();
1696 pslILEmit->EmitLDLOC(m_dwLocalBuffer);
1697 pslILEmit->EmitBRFALSE(pExitLabel);
1698 pslILEmit->EmitLDLOC(m_dwLocalBuffer);
1699 pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
1700 pslILEmit->EmitLabel(pExitLabel);
1704 bool ILVBByValStrMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
1706 if (IsCLRToNative(dwMarshalFlags) && IsByref(dwMarshalFlags) && IsIn(dwMarshalFlags) && IsOut(dwMarshalFlags))
1711 *pErrorResID = IDS_EE_BADMARSHAL_VBBYVALSTRRESTRICTION;
1715 bool ILVBByValStrMarshaler::SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
1717 *pErrorResID = IDS_EE_BADMARSHAL_VBBYVALSTRRESTRICTION;
1721 LocalDesc ILVBByValStrMarshaler::GetNativeType()
1723 LIMITED_METHOD_CONTRACT;
1725 return LocalDesc(ELEMENT_TYPE_I); // BSTR
1728 LocalDesc ILVBByValStrMarshaler::GetManagedType()
1730 LIMITED_METHOD_CONTRACT;
1732 return LocalDesc(ELEMENT_TYPE_STRING);
1735 bool ILVBByValStrMarshaler::IsNativePassedByRef()
1737 LIMITED_METHOD_CONTRACT;
1741 void ILVBByValStrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1743 STANDARD_VM_CONTRACT;
1745 m_dwCCHLocal = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
1747 EmitLoadManagedValue(pslILEmit);
1748 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetBestFitMapping());
1749 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar());
1750 pslILEmit->EmitLDLOCA(m_dwCCHLocal);
1752 // static IntPtr ConvertToNative(string strManaged, bool fBestFit, bool fThrowOnUnmappableChar, ref int cch)
1753 pslILEmit->EmitCALL(METHOD__VBBYVALSTRMARSHALER__CONVERT_TO_NATIVE, 4, 1);
1755 EmitStoreNativeValue(pslILEmit);
1758 void ILVBByValStrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1760 STANDARD_VM_CONTRACT;
1762 EmitLoadNativeValue(pslILEmit); // pNative
1763 pslILEmit->EmitLDLOC(m_dwCCHLocal); // cch
1765 // static string ConvertToManaged(IntPtr pNative, int cch)
1766 pslILEmit->EmitCALL(METHOD__VBBYVALSTRMARSHALER__CONVERT_TO_MANAGED, 2, 1);
1768 EmitStoreManagedValue(pslILEmit);
1771 bool ILVBByValStrMarshaler::NeedsClearNative()
1773 LIMITED_METHOD_CONTRACT;
1777 void ILVBByValStrMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1779 STANDARD_VM_CONTRACT;
1781 EmitLoadNativeValue(pslILEmit); // pNative
1783 // static void ClearNative(IntPtr pNative);
1784 pslILEmit->EmitCALL(METHOD__VBBYVALSTRMARSHALER__CLEAR_NATIVE, 1, 0);
1786 #endif // FEATURE_COMINTEROP
1788 LocalDesc ILBSTRMarshaler::GetManagedType()
1790 LIMITED_METHOD_CONTRACT;
1792 return LocalDesc(ELEMENT_TYPE_STRING);
1795 void ILBSTRMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1797 STANDARD_VM_CONTRACT;
1799 ILCodeLabel* pRejoinLabel = pslILEmit->NewCodeLabel();
1801 EmitLoadManagedValue(pslILEmit);
1803 if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags))
1805 ILCodeLabel *pNoOptimizeLabel = pslILEmit->NewCodeLabel();
1806 m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
1809 pslILEmit->EmitLoadNullPtr();
1810 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
1812 pslILEmit->EmitDUP();
1813 pslILEmit->EmitBRFALSE(pNoOptimizeLabel);
1816 pslILEmit->EmitDUP();
1817 pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
1819 // if (length > (MAX_LOCAL_BUFFER_LENGTH - 6) / 2) goto NoOptimize
1820 pslILEmit->EmitLDC((MAX_LOCAL_BUFFER_LENGTH - 6) / 2); // number of Unicode characters - terminator - length dword
1821 pslILEmit->EmitCGT_UN();
1822 pslILEmit->EmitBRTRUE(pNoOptimizeLabel);
1824 // LocalBuffer = localloc[(String.Length * 2) + 6]
1825 pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
1826 pslILEmit->EmitLDC(2);
1827 pslILEmit->EmitMUL();
1828 pslILEmit->EmitLDC(7); // + length (4B) + terminator (2B) + possible trailing byte (1B)
1829 pslILEmit->EmitADD();
1832 // Save the buffer length
1833 DWORD dwTmpAllocSize = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
1834 pslILEmit->EmitDUP();
1835 pslILEmit->EmitSTLOC(dwTmpAllocSize);
1838 pslILEmit->EmitLOCALLOC();
1841 // Pass buffer length in the first DWORD so the helper is able to assert that
1842 // the buffer is large enough.
1843 pslILEmit->EmitDUP();
1844 pslILEmit->EmitLDLOC(dwTmpAllocSize);
1845 pslILEmit->EmitSTIND_I4();
1848 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
1850 // load string and LocalBuffer
1851 EmitLoadManagedValue(pslILEmit);
1852 pslILEmit->EmitLDLOC(m_dwLocalBuffer);
1853 pslILEmit->EmitBR(pRejoinLabel);
1855 pslILEmit->EmitLabel(pNoOptimizeLabel);
1857 pslILEmit->EmitLoadNullPtr();
1859 pslILEmit->EmitLabel(pRejoinLabel);
1860 pslILEmit->EmitCALL(METHOD__BSTRMARSHALER__CONVERT_TO_NATIVE, 2, 1);
1861 EmitStoreNativeValue(pslILEmit);
1864 void ILBSTRMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1866 STANDARD_VM_CONTRACT;
1868 EmitLoadNativeValue(pslILEmit);
1869 pslILEmit->EmitCALL(METHOD__BSTRMARSHALER__CONVERT_TO_MANAGED, 1, 1);
1870 EmitStoreManagedValue(pslILEmit);
1873 LocalDesc ILAnsiBSTRMarshaler::GetNativeType()
1875 LIMITED_METHOD_CONTRACT;
1877 return LocalDesc(ELEMENT_TYPE_I); // BSTR
1880 LocalDesc ILAnsiBSTRMarshaler::GetManagedType()
1882 LIMITED_METHOD_CONTRACT;
1884 return LocalDesc(ELEMENT_TYPE_STRING);
1887 void ILAnsiBSTRMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1889 STANDARD_VM_CONTRACT;
1891 DWORD dwAnsiMarshalFlags =
1892 (m_pargs->m_pMarshalInfo->GetBestFitMapping() & 0xFF) |
1893 (m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar() << 8);
1895 pslILEmit->EmitLDC(dwAnsiMarshalFlags);
1896 EmitLoadManagedValue(pslILEmit);
1897 pslILEmit->EmitCALL(METHOD__ANSIBSTRMARSHALER__CONVERT_TO_NATIVE, 2, 1);
1898 EmitStoreNativeValue(pslILEmit);
1901 void ILAnsiBSTRMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1903 STANDARD_VM_CONTRACT;
1905 EmitLoadNativeValue(pslILEmit);
1906 pslILEmit->EmitCALL(METHOD__ANSIBSTRMARSHALER__CONVERT_TO_MANAGED, 1, 1);
1907 EmitStoreManagedValue(pslILEmit);
1910 bool ILAnsiBSTRMarshaler::NeedsClearNative()
1912 LIMITED_METHOD_CONTRACT;
1916 void ILAnsiBSTRMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1918 STANDARD_VM_CONTRACT;
1920 EmitLoadNativeValue(pslILEmit);
1921 pslILEmit->EmitCALL(METHOD__ANSIBSTRMARSHALER__CLEAR_NATIVE, 1, 0);
1924 #ifdef FEATURE_COMINTEROP
1926 LocalDesc ILHSTRINGMarshaler::GetNativeType()
1928 LIMITED_METHOD_CONTRACT;
1929 return LocalDesc(ELEMENT_TYPE_I); // HSTRING
1932 LocalDesc ILHSTRINGMarshaler::GetManagedType()
1934 LIMITED_METHOD_CONTRACT;
1935 return LocalDesc(ELEMENT_TYPE_STRING);
1938 bool ILHSTRINGMarshaler::NeedsClearNative()
1940 LIMITED_METHOD_CONTRACT;
1944 void ILHSTRINGMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1949 PRECONDITION(CheckPointer(pslILEmit));
1953 // If we're only going into native code, then we can optimize and create a HSTRING reference over
1954 // the pinned System.String. However, if the parameter will remain in native code as an out
1955 // value, then we need to create a real HSTRING.
1956 if (!IsOut(m_dwMarshalFlags) && !IsRetval(m_dwMarshalFlags))
1958 EmitConvertCLRToHSTRINGReference(pslILEmit);
1962 EmitConvertCLRToHSTRING(pslILEmit);
1966 void ILHSTRINGMarshaler::EmitConvertCLRToHSTRINGReference(ILCodeStream* pslILEmit)
1971 PRECONDITION(CheckPointer(pslILEmit));
1972 PRECONDITION(!IsOut(m_dwMarshalFlags));
1973 PRECONDITION(!IsRetval(m_dwMarshalFlags));
1978 // The general strategy for fast path marshaling a short lived System.String -> HSTRING is:
1979 // 1. Pin the System.String
1980 // 2. Create an HSTRING Reference over the pinned string
1981 // 3. Pass that reference to native code
1984 // Local to hold the HSTRING_HEADER of the HSTRING reference
1985 MethodTable *pHStringHeaderMT = MscorlibBinder::GetClass(CLASS__HSTRING_HEADER_MANAGED);
1986 DWORD dwHStringHeaderLocal = pslILEmit->NewLocal(pHStringHeaderMT);
1988 // Local to hold the pinned input string
1989 LocalDesc pinnedStringDesc = GetManagedType();
1990 pinnedStringDesc.MakePinned();
1991 DWORD dwPinnedStringLocal = pslILEmit->NewLocal(pinnedStringDesc);
1993 // pinnedString = managed
1994 EmitLoadManagedValue(pslILEmit);
1995 pslILEmit->EmitSTLOC(dwPinnedStringLocal);
1997 // hstring = HSTRINGMarshaler.ConvertManagedToNativeReference(pinnedString, out HStringHeader)
1998 pslILEmit->EmitLDLOC(dwPinnedStringLocal);
1999 pslILEmit->EmitLDLOCA(dwHStringHeaderLocal);
2000 pslILEmit->EmitCALL(METHOD__HSTRINGMARSHALER__CONVERT_TO_NATIVE_REFERENCE, 2, 1);
2002 if (g_pConfig->InteropLogArguments())
2004 m_pslNDirect->EmitLogNativeArgument(pslILEmit, dwPinnedStringLocal);
2007 EmitStoreNativeValue(pslILEmit);
2010 void ILHSTRINGMarshaler::EmitConvertCLRToHSTRING(ILCodeStream* pslILEmit)
2015 PRECONDITION(CheckPointer(pslILEmit));
2019 // hstring = HSTRINGMarshaler.ConvertManagedToNative(managed);
2020 EmitLoadManagedValue(pslILEmit);
2021 pslILEmit->EmitCALL(METHOD__HSTRINGMARSHALER__CONVERT_TO_NATIVE, 1, 1);
2022 EmitStoreNativeValue(pslILEmit);
2025 void ILHSTRINGMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2027 STANDARD_VM_CONTRACT;
2030 // To convert an HSTRING to a CLR String:
2031 // 1. WindowsGetStringRawBuffer() to get the raw string data
2032 // 2. WindowsGetStringLen() to get the string length
2033 // 3. Construct a System.String from these parameters
2034 // 4. Release the HSTRING
2037 // string = HSTRINGMarshaler.ConvertNativeToManaged(native);
2038 EmitLoadNativeValue(pslILEmit);
2039 pslILEmit->EmitCALL(METHOD__HSTRINGMARSHALER__CONVERT_TO_MANAGED, 1, 1);
2040 EmitStoreManagedValue(pslILEmit);
2044 void ILHSTRINGMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
2046 STANDARD_VM_CONTRACT;
2048 // HStringMarshaler.ClearNative(hstring)
2049 EmitLoadNativeValue(pslILEmit);
2050 pslILEmit->EmitCALL(METHOD__HSTRINGMARSHALER__CLEAR_NATIVE, 1, 0);
2053 #endif // FEATURE_COMINTEROP
2055 LocalDesc ILCUTF8Marshaler::GetManagedType()
2057 LIMITED_METHOD_CONTRACT;
2059 return LocalDesc(ELEMENT_TYPE_STRING);
2062 void ILCUTF8Marshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2064 STANDARD_VM_CONTRACT;
2066 DWORD dwUtf8MarshalFlags =
2067 (m_pargs->m_pMarshalInfo->GetBestFitMapping() & 0xFF) |
2068 (m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar() << 8);
2070 bool bPassByValueInOnly = IsIn(m_dwMarshalFlags) && !IsOut(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags);
2071 if (bPassByValueInOnly)
2073 DWORD dwBufSize = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
2074 m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
2077 pslILEmit->EmitLoadNullPtr();
2078 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
2080 ILCodeLabel* pNoOptimize = pslILEmit->NewCodeLabel();
2082 // if == NULL, goto NoOptimize
2083 EmitLoadManagedValue(pslILEmit);
2084 pslILEmit->EmitBRFALSE(pNoOptimize);
2086 // (String.Length + 1)
2087 // Characters would be # of characters + 1 in case left over high surrogate is ?
2088 EmitLoadManagedValue(pslILEmit);
2089 pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
2090 pslILEmit->EmitLDC(1);
2091 pslILEmit->EmitADD();
2093 // Max 3 bytes per char.
2094 // (String.Length + 1) * 3
2095 pslILEmit->EmitLDC(3);
2096 pslILEmit->EmitMUL();
2098 // +1 for the 0x0 that we put in.
2099 // ((String.Length + 1) * 3) + 1
2100 pslILEmit->EmitLDC(1);
2101 pslILEmit->EmitADD();
2103 // BufSize = ( (String.Length+1) * 3) + 1
2104 pslILEmit->EmitSTLOC(dwBufSize);
2106 // if (MAX_LOCAL_BUFFER_LENGTH < BufSize ) goto NoOptimize
2107 pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
2108 pslILEmit->EmitLDLOC(dwBufSize);
2109 pslILEmit->EmitCLT();
2110 pslILEmit->EmitBRTRUE(pNoOptimize);
2112 // LocalBuffer = localloc(BufSize);
2113 pslILEmit->EmitLDLOC(dwBufSize);
2114 pslILEmit->EmitLOCALLOC();
2115 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
2118 pslILEmit->EmitLabel(pNoOptimize);
2121 // UTF8Marshaler.ConvertToNative(dwUtf8MarshalFlags,pManaged, pLocalBuffer)
2122 pslILEmit->EmitLDC(dwUtf8MarshalFlags);
2123 EmitLoadManagedValue(pslILEmit);
2125 if (m_dwLocalBuffer != LOCAL_NUM_UNUSED)
2127 pslILEmit->EmitLDLOC(m_dwLocalBuffer);
2131 pslILEmit->EmitLoadNullPtr();
2134 pslILEmit->EmitCALL(METHOD__CUTF8MARSHALER__CONVERT_TO_NATIVE, 3, 1);
2136 EmitStoreNativeValue(pslILEmit);
2139 void ILCUTF8Marshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2141 STANDARD_VM_CONTRACT;
2143 EmitLoadNativeValue(pslILEmit);
2144 pslILEmit->EmitCALL(METHOD__CUTF8MARSHALER__CONVERT_TO_MANAGED, 1, 1);
2145 EmitStoreManagedValue(pslILEmit);
2149 LocalDesc ILCSTRMarshaler::GetManagedType()
2151 LIMITED_METHOD_CONTRACT;
2153 return LocalDesc(ELEMENT_TYPE_STRING);
2156 void ILCSTRMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2158 STANDARD_VM_CONTRACT;
2160 DWORD dwAnsiMarshalFlags =
2161 (m_pargs->m_pMarshalInfo->GetBestFitMapping() & 0xFF) |
2162 (m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar() << 8);
2164 bool bPassByValueInOnly = IsIn(m_dwMarshalFlags) && !IsOut(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags);
2165 if (bPassByValueInOnly)
2167 DWORD dwBufSize = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
2168 m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
2171 pslILEmit->EmitLoadNullPtr();
2172 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
2174 ILCodeLabel* pNoOptimize = pslILEmit->NewCodeLabel();
2176 // if == NULL, goto NoOptimize
2177 EmitLoadManagedValue(pslILEmit);
2178 pslILEmit->EmitBRFALSE(pNoOptimize);
2180 // String.Length + 2
2181 EmitLoadManagedValue(pslILEmit);
2182 pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
2183 pslILEmit->EmitLDC(2);
2184 pslILEmit->EmitADD();
2186 // (String.Length + 2) * GetMaxDBCSCharByteSize()
2187 pslILEmit->EmitLDSFLD(pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__MARSHAL__SYSTEM_MAX_DBCS_CHAR_SIZE)));
2188 pslILEmit->EmitMUL_OVF();
2190 // BufSize = (String.Length + 2) * GetMaxDBCSCharByteSize()
2191 pslILEmit->EmitSTLOC(dwBufSize);
2193 // if (MAX_LOCAL_BUFFER_LENGTH < BufSize ) goto NoOptimize
2194 pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
2195 pslILEmit->EmitLDLOC(dwBufSize);
2196 pslILEmit->EmitCLT();
2197 pslILEmit->EmitBRTRUE(pNoOptimize);
2199 // LocalBuffer = localloc(BufSize);
2200 pslILEmit->EmitLDLOC(dwBufSize);
2201 pslILEmit->EmitLOCALLOC();
2202 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
2205 pslILEmit->EmitLabel(pNoOptimize);
2208 // CSTRMarshaler.ConvertToNative pManaged, dwAnsiMarshalFlags, pLocalBuffer
2209 pslILEmit->EmitLDC(dwAnsiMarshalFlags);
2210 EmitLoadManagedValue(pslILEmit);
2212 if (m_dwLocalBuffer != LOCAL_NUM_UNUSED)
2214 pslILEmit->EmitLDLOC(m_dwLocalBuffer);
2218 pslILEmit->EmitLoadNullPtr();
2221 pslILEmit->EmitCALL(METHOD__CSTRMARSHALER__CONVERT_TO_NATIVE, 3, 1);
2223 EmitStoreNativeValue(pslILEmit);
2226 void ILCSTRMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2228 STANDARD_VM_CONTRACT;
2230 EmitLoadNativeValue(pslILEmit);
2231 pslILEmit->EmitCALL(METHOD__CSTRMARSHALER__CONVERT_TO_MANAGED, 1, 1);
2232 EmitStoreManagedValue(pslILEmit);
2235 LocalDesc ILLayoutClassPtrMarshalerBase::GetNativeType()
2237 LIMITED_METHOD_CONTRACT;
2239 return LocalDesc(ELEMENT_TYPE_I); // ptr to struct
2242 LocalDesc ILLayoutClassPtrMarshalerBase::GetManagedType()
2244 LIMITED_METHOD_CONTRACT;
2246 return LocalDesc(m_pargs->m_pMT);
2249 void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
2251 STANDARD_VM_CONTRACT;
2253 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2254 UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2256 pslILEmit->EmitLoadNullPtr();
2257 EmitStoreNativeValue(pslILEmit);
2259 EmitLoadManagedValue(pslILEmit);
2260 pslILEmit->EmitBRFALSE(pNullRefLabel);
2261 pslILEmit->EmitLDC(uNativeSize);
2262 pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
2263 pslILEmit->EmitDUP(); // for INITBLK
2264 EmitStoreNativeValue(pslILEmit);
2266 // initialize local block we just allocated
2267 pslILEmit->EmitLDC(0);
2268 pslILEmit->EmitLDC(uNativeSize);
2269 pslILEmit->EmitINITBLK();
2271 pslILEmit->EmitLabel(pNullRefLabel);
2274 void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceCLRToNativeTemp(ILCodeStream* pslILEmit)
2276 STANDARD_VM_CONTRACT;
2278 UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2279 if (uNativeSize > s_cbStackAllocThreshold)
2281 EmitConvertSpaceCLRToNative(pslILEmit);
2285 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2287 pslILEmit->EmitLoadNullPtr();
2288 EmitStoreNativeValue(pslILEmit);
2290 EmitLoadManagedValue(pslILEmit);
2291 pslILEmit->EmitBRFALSE(pNullRefLabel);
2293 pslILEmit->EmitLDC(uNativeSize);
2294 pslILEmit->EmitLOCALLOC();
2295 pslILEmit->EmitDUP(); // for INITBLK
2296 EmitStoreNativeValue(pslILEmit);
2298 // initialize local block we just allocated
2299 pslILEmit->EmitLDC(0);
2300 pslILEmit->EmitLDC(uNativeSize);
2301 pslILEmit->EmitINITBLK();
2303 pslILEmit->EmitLabel(pNullRefLabel);
2307 void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
2309 STANDARD_VM_CONTRACT;
2311 EmitConvertSpaceCLRToNativeTemp(pslILEmit);
2312 EmitConvertContentsCLRToNative(pslILEmit);
2315 void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
2317 STANDARD_VM_CONTRACT;
2319 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2321 EmitLoadNativeValue(pslILEmit);
2322 pslILEmit->EmitBRFALSE(pNullRefLabel);
2324 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(m_pargs->m_pMT));
2325 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
2326 // static object AllocateInternal(IntPtr typeHandle);
2327 pslILEmit->EmitCALL(METHOD__STUBHELPERS__ALLOCATE_INTERNAL, 1, 1);
2328 EmitStoreManagedValue(pslILEmit);
2329 pslILEmit->EmitLabel(pNullRefLabel);
2333 bool ILLayoutClassPtrMarshalerBase::NeedsClearNative()
2335 LIMITED_METHOD_CONTRACT;
2339 void ILLayoutClassPtrMarshalerBase::EmitClearNative(ILCodeStream* pslILEmit)
2341 STANDARD_VM_CONTRACT;
2343 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2345 EmitLoadNativeValue(pslILEmit);
2346 pslILEmit->EmitBRFALSE(pNullRefLabel);
2348 EmitClearNativeContents(pslILEmit);
2349 EmitLoadNativeValue(pslILEmit);
2350 pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
2352 pslILEmit->EmitLabel(pNullRefLabel);
2355 void ILLayoutClassPtrMarshalerBase::EmitClearNativeTemp(ILCodeStream* pslILEmit)
2357 STANDARD_VM_CONTRACT;
2359 UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2360 if (uNativeSize > s_cbStackAllocThreshold)
2362 EmitClearNative(pslILEmit);
2366 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2367 EmitLoadNativeValue(pslILEmit);
2368 pslILEmit->EmitBRFALSE(pNullRefLabel);
2370 EmitClearNativeContents(pslILEmit);
2372 pslILEmit->EmitLabel(pNullRefLabel);
2378 void ILLayoutClassPtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2380 STANDARD_VM_CONTRACT;
2382 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2383 UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2385 EmitLoadNativeValue(pslILEmit);
2386 pslILEmit->EmitBRFALSE(pNullRefLabel);
2388 EmitLoadNativeValue(pslILEmit);
2389 pslILEmit->EmitLDC(0);
2390 pslILEmit->EmitLDC(uNativeSize);
2391 pslILEmit->EmitINITBLK();
2393 EmitLoadManagedValue(pslILEmit);
2394 EmitLoadNativeValue(pslILEmit);
2396 m_pslNDirect->LoadCleanupWorkList(pslILEmit);
2398 // static void FmtClassUpdateNativeInternal(object obj, byte* pNative, IntPtr pOptionalCleanupList);
2400 pslILEmit->EmitCALL(METHOD__STUBHELPERS__FMT_CLASS_UPDATE_NATIVE_INTERNAL, 3, 0);
2401 pslILEmit->EmitLabel(pNullRefLabel);
2404 void ILLayoutClassPtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2406 STANDARD_VM_CONTRACT;
2408 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2410 EmitLoadManagedValue(pslILEmit);
2411 pslILEmit->EmitBRFALSE(pNullRefLabel);
2413 EmitLoadManagedValue(pslILEmit);
2414 EmitLoadNativeValue(pslILEmit);
2416 // static void FmtClassUpdateCLRInternal(object obj, byte* pNative);
2417 pslILEmit->EmitCALL(METHOD__STUBHELPERS__FMT_CLASS_UPDATE_CLR_INTERNAL, 2, 0);
2418 pslILEmit->EmitLabel(pNullRefLabel);
2421 void ILLayoutClassPtrMarshaler::EmitClearNativeContents(ILCodeStream * pslILEmit)
2423 STANDARD_VM_CONTRACT;
2425 int tokManagedType = pslILEmit->GetToken(m_pargs->m_pMT);
2427 EmitLoadNativeValue(pslILEmit);
2428 pslILEmit->EmitLDTOKEN(tokManagedType);
2429 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
2431 // static void LayoutDestroyNativeInternal(byte* pNative, IntPtr pMT);
2432 pslILEmit->EmitCALL(METHOD__STUBHELPERS__LAYOUT_DESTROY_NATIVE_INTERNAL, 2, 0);
2436 void ILBlittablePtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2438 STANDARD_VM_CONTRACT;
2440 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2441 UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2442 int fieldDef = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__RAW_DATA__DATA));
2444 EmitLoadNativeValue(pslILEmit);
2445 pslILEmit->EmitBRFALSE(pNullRefLabel);
2447 EmitLoadNativeValue(pslILEmit); // dest
2449 EmitLoadManagedValue(pslILEmit);
2450 pslILEmit->EmitLDFLDA(fieldDef); // src
2452 pslILEmit->EmitLDC(uNativeSize); // size
2454 pslILEmit->EmitCPBLK();
2455 pslILEmit->EmitLabel(pNullRefLabel);
2458 void ILBlittablePtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2460 STANDARD_VM_CONTRACT;
2462 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2463 UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2464 int fieldDef = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__RAW_DATA__DATA));
2466 EmitLoadManagedValue(pslILEmit);
2467 pslILEmit->EmitBRFALSE(pNullRefLabel);
2469 EmitLoadManagedValue(pslILEmit);
2470 pslILEmit->EmitLDFLDA(fieldDef); // dest
2472 EmitLoadNativeValue(pslILEmit); // src
2474 pslILEmit->EmitLDC(uNativeSize); // size
2476 pslILEmit->EmitCPBLK();
2477 pslILEmit->EmitLabel(pNullRefLabel);
2480 void ILBlittablePtrMarshaler::EmitMarshalArgumentCLRToNative()
2485 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
2489 EmitSetupSigAndDefaultHomesCLRToNative();
2495 ILCodeLabel* pSkipAddLabel = m_pcsMarshal->NewCodeLabel();
2496 LocalDesc managedTypePinned = GetManagedType();
2497 managedTypePinned.MakePinned();
2498 DWORD dwPinnedLocal = m_pcsMarshal->NewLocal(managedTypePinned);
2500 EmitLoadManagedValue(m_pcsMarshal);
2502 m_pcsMarshal->EmitSTLOC(dwPinnedLocal);
2503 m_pcsMarshal->EmitLDLOC(dwPinnedLocal);
2504 m_pcsMarshal->EmitCONV_U();
2505 m_pcsMarshal->EmitDUP();
2506 m_pcsMarshal->EmitBRFALSE(pSkipAddLabel);
2507 m_pcsMarshal->EmitLDC(Object::GetOffsetOfFirstField());
2508 m_pcsMarshal->EmitADD();
2509 m_pcsMarshal->EmitLabel(pSkipAddLabel);
2511 if (g_pConfig->InteropLogArguments())
2513 m_pslNDirect->EmitLogNativeArgument(m_pcsMarshal, dwPinnedLocal);
2516 EmitStoreNativeValue(m_pcsMarshal);
2522 MarshalerOverrideStatus ILHandleRefMarshaler::ArgumentOverride(NDirectStubLinker* psl,
2526 BOOL fManagedToNative,
2527 OverrideProcArgs* pargs,
2530 UINT nativeStackOffset)
2540 ILCodeStream* pcsMarshal = psl->GetMarshalCodeStream();
2541 ILCodeStream* pcsDispatch = psl->GetDispatchCodeStream();
2542 ILCodeStream* pcsUnmarshal = psl->GetUnmarshalCodeStream();
2544 if (fManagedToNative && !byref)
2546 pcsMarshal->SetStubTargetArgType(ELEMENT_TYPE_I);
2549 // HandleRefs are valuetypes, so pinning is not needed.
2550 // The argument address is on the stack and will not move.
2551 mdFieldDef handleField = pcsDispatch->GetToken(MscorlibBinder::GetField(FIELD__HANDLE_REF__HANDLE));
2552 pcsDispatch->EmitLDARG(argidx);
2553 pcsDispatch->EmitLDFLD(handleField);
2555 mdFieldDef wrapperField = pcsUnmarshal->GetToken(MscorlibBinder::GetField(FIELD__HANDLE_REF__WRAPPER));
2556 pcsUnmarshal->EmitLDARG(argidx);
2557 pcsUnmarshal->EmitLDFLD(wrapperField);
2558 pcsUnmarshal->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
2564 *pResID = IDS_EE_BADMARSHAL_HANDLEREFRESTRICTION;
2569 MarshalerOverrideStatus ILHandleRefMarshaler::ReturnOverride(NDirectStubLinker* psl,
2570 BOOL fManagedToNative,
2572 OverrideProcArgs* pargs,
2583 *pResID = IDS_EE_BADMARSHAL_HANDLEREFRESTRICTION;
2587 LocalDesc ILSafeHandleMarshaler::GetManagedType()
2589 STANDARD_VM_CONTRACT;
2591 return LocalDesc(MscorlibBinder::GetClass(CLASS__SAFE_HANDLE));
2594 LocalDesc ILSafeHandleMarshaler::GetNativeType()
2596 LIMITED_METHOD_CONTRACT;
2598 return LocalDesc(ELEMENT_TYPE_I);
2601 bool ILSafeHandleMarshaler::NeedsClearNative()
2603 LIMITED_METHOD_CONTRACT;
2607 void ILSafeHandleMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
2609 STANDARD_VM_CONTRACT;
2611 _ASSERTE(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
2613 // call StubHelpers::SafeHandleRelease
2614 EmitLoadManagedValue(pslILEmit);
2615 pslILEmit->EmitCALL(METHOD__STUBHELPERS__SAFE_HANDLE_RELEASE, 1, 0);
2618 void ILSafeHandleMarshaler::EmitMarshalArgumentCLRToNative()
2623 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
2627 EmitSetupSigAndDefaultHomesCLRToNative();
2629 // by-value CLR-to-native SafeHandle is always passed in-only regardless of [In], [Out]
2630 // marshal and cleanup communicate via an extra local and are both emitted in this method
2632 // bool <dwHandleAddRefedLocalNum> = false
2633 ILCodeStream *pcsSetup = m_pslNDirect->GetSetupCodeStream();
2634 DWORD dwHandleAddRefedLocalNum = pcsSetup->NewLocal(ELEMENT_TYPE_BOOLEAN);
2636 pcsSetup->EmitLDC(0);
2637 pcsSetup->EmitSTLOC(dwHandleAddRefedLocalNum);
2639 // <nativeHandle> = StubHelpers::SafeHandleAddRef(<managedSH>, ref <dwHandleAddRefedLocalNum>)
2640 EmitLoadManagedValue(m_pcsMarshal);
2641 m_pcsMarshal->EmitLDLOCA(dwHandleAddRefedLocalNum);
2642 m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__SAFE_HANDLE_ADD_REF, 2, 1);
2643 EmitStoreNativeValue(m_pcsMarshal);
2646 // if (<dwHandleAddRefedLocalNum>) StubHelpers.SafeHandleRelease(<managedSH>)
2647 ILCodeStream *pcsCleanup = m_pslNDirect->GetCleanupCodeStream();
2648 ILCodeLabel *pSkipClearNativeLabel = pcsCleanup->NewCodeLabel();
2650 pcsCleanup->EmitLDLOC(dwHandleAddRefedLocalNum);
2651 pcsCleanup->EmitBRFALSE(pSkipClearNativeLabel);
2653 EmitClearNativeTemp(pcsCleanup);
2654 m_pslNDirect->SetCleanupNeeded();
2656 pcsCleanup->EmitLabel(pSkipClearNativeLabel);
2659 MarshalerOverrideStatus ILSafeHandleMarshaler::ArgumentOverride(NDirectStubLinker* psl,
2663 BOOL fManagedToNative,
2664 OverrideProcArgs* pargs,
2667 UINT nativeStackOffset)
2677 ILCodeStream* pslIL = psl->GetMarshalCodeStream();
2678 ILCodeStream* pslILDispatch = psl->GetDispatchCodeStream();
2680 if (fManagedToNative)
2684 pslIL->SetStubTargetArgType(ELEMENT_TYPE_I);
2686 // The specific SafeHandle subtype we're dealing with here.
2687 MethodTable *pHandleType = pargs->m_pMT;
2689 // Out SafeHandle parameters must not be abstract.
2690 if (fout && pHandleType->IsAbstract())
2692 *pResID = IDS_EE_BADMARSHAL_ABSTRACTOUTSAFEHANDLE;
2696 // We rely on the SafeHandle having a default constructor.
2697 if (!pHandleType->HasDefaultConstructor())
2699 MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
2700 COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
2703 // Grab the token for the native handle field embedded inside the SafeHandle. We'll be using it to direct access the
2704 // native handle later.
2705 mdToken tkNativeHandleField = pslIL->GetToken(MscorlibBinder::GetField(FIELD__SAFE_HANDLE__HANDLE));
2707 // The high level logic (note that the parameter may be in, out or both):
2708 // 1) If this is an input parameter we need to AddRef the SafeHandle and schedule a Release cleanup item.
2709 // 2) If this is an output parameter we need to preallocate a SafeHandle to wrap the new native handle value. We
2710 // must allocate this before the native call to avoid a failure point when we already have a native resource
2711 // allocated. We must allocate a new SafeHandle even if we have one on input since both input and output native
2712 // handles need to be tracked and released by a SafeHandle.
2713 // 3) Initialize a local IntPtr that will be passed to the native call. If we have an input SafeHandle the value
2714 // comes from there otherwise we get it from the new SafeHandle (which is guaranteed to be initialized to an
2715 // invalid handle value).
2716 // 4) If this is a out parameter we also store the original handle value (that we just computed above) in a local
2718 // 5) After the native call, if this is an output parameter and the handle value we passed to native differs from
2719 // the local copy we made then the new handle value is written into the output SafeHandle and that SafeHandle
2720 // is propagated back to the caller.
2723 DWORD dwInputHandleLocal = 0; // The input safe handle (in only)
2724 DWORD dwOutputHandleLocal = 0; // The output safe handle (out only)
2725 DWORD dwOldNativeHandleLocal = 0; // The original native handle value for comparison (out only)
2726 DWORD dwNativeHandleLocal; // The input (and possibly updated) native handle value
2730 LocalDesc locInputHandle(pHandleType);
2731 dwInputHandleLocal = pslIL->NewLocal(locInputHandle);
2735 LocalDesc locOutputHandle(pHandleType);
2736 dwOutputHandleLocal = pslIL->NewLocal(locOutputHandle);
2738 dwOldNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
2741 dwNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
2743 // Call StubHelpers.AddToCleanupList to atomically AddRef incoming SafeHandle and schedule a cleanup work item to
2744 // perform Release after the call. The helper also returns the native handle value to us so take the opportunity
2745 // to store this in the NativeHandle local we've allocated.
2748 pslIL->EmitLDARG(argidx);
2749 pslIL->EmitLDIND_REF();
2751 pslIL->EmitSTLOC(dwInputHandleLocal);
2753 // Release the original input SafeHandle after the call.
2754 psl->LoadCleanupWorkList(pslIL);
2755 pslIL->EmitLDLOC(dwInputHandleLocal);
2757 // This is realiable, i.e. the cleanup will happen if and only if the SH was actually AddRef'ed.
2758 pslIL->EmitCALL(METHOD__STUBHELPERS__ADD_TO_CLEANUP_LIST_SAFEHANDLE, 2, 1);
2760 pslIL->EmitSTLOC(dwNativeHandleLocal);
2764 // For output parameters we need to allocate a new SafeHandle to hold the result.
2767 MethodDesc* pMDCtor = pHandleType->GetDefaultConstructor();
2768 pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
2769 pslIL->EmitSTLOC(dwOutputHandleLocal);
2771 // If we didn't provide an input handle then we initialize the NativeHandle local with the (initially invalid)
2772 // handle field set up inside the output handle by the constructor.
2775 pslIL->EmitLDLOC(dwOutputHandleLocal);
2776 pslIL->EmitLDFLD(tkNativeHandleField);
2777 pslIL->EmitSTLOC(dwNativeHandleLocal);
2780 // Remember the handle value we start out with so we know whether to back propagate after the native call.
2781 pslIL->EmitLDLOC(dwNativeHandleLocal);
2782 pslIL->EmitSTLOC(dwOldNativeHandleLocal);
2785 // Leave the address of the native handle local as the argument to the native method.
2786 pslILDispatch->EmitLDLOCA(dwNativeHandleLocal);
2788 // On the output side we only backpropagate the native handle into the output SafeHandle and the output SafeHandle
2789 // to the caller if the native handle actually changed (otherwise we can end up with two SafeHandles wrapping the
2790 // same native handle, which is bad).
2793 // We will use cleanup stream to avoid leaking the handle on thread abort.
2794 psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx);
2796 psl->SetCleanupNeeded();
2797 ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
2799 ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
2801 psl->EmitCheckForArgCleanup(pslCleanupIL,
2802 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx,
2803 NDirectStubLinker::BranchIfNotMarshaled,
2806 // If this is an [in, out] handle check if the native handles have changed. If not we're finished.
2809 pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
2810 pslCleanupIL->EmitLDLOC(dwOldNativeHandleLocal);
2811 pslCleanupIL->EmitCEQ();
2812 pslCleanupIL->EmitBRTRUE(pDoneLabel);
2815 // Propagate the native handle into the output SafeHandle.
2816 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
2817 pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
2818 pslCleanupIL->EmitSTFLD(tkNativeHandleField);
2820 // Propagate the output SafeHandle back to the caller.
2821 pslCleanupIL->EmitLDARG(argidx);
2822 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
2823 pslCleanupIL->EmitSTIND_REF();
2825 pslCleanupIL->EmitLabel(pDoneLabel);
2830 // Avoid using the cleanup list in this common case for perf reasons (cleanup list is
2831 // unmanaged and destroying it means excessive managed<->native transitions; in addition,
2832 // as X86 IL stubs do not use interop frames, there's nothing protecting the cleanup list
2833 // and the SafeHandle references must be GC handles which does not help perf either).
2835 // This code path generates calls to StubHelpers.SafeHandleAddRef and SafeHandleRelease.
2836 // NICE: Could SafeHandle.DangerousAddRef and DangerousRelease be implemented in managed?
2837 return HANDLEASNORMAL;
2844 *pResID = IDS_EE_BADMARSHAL_SAFEHANDLENATIVETOCOM;
2849 //---------------------------------------------------------------------------------------
2851 MarshalerOverrideStatus
2852 ILSafeHandleMarshaler::ReturnOverride(
2853 NDirectStubLinker * psl,
2854 BOOL fManagedToNative,
2856 OverrideProcArgs * pargs,
2864 PRECONDITION(CheckPointer(psl));
2865 PRECONDITION(CheckPointer(pargs));
2866 PRECONDITION(CheckPointer(pResID));
2870 ILCodeStream * pslIL = psl->GetMarshalCodeStream();
2871 ILCodeStream * pslPostIL = psl->GetReturnUnmarshalCodeStream();
2872 ILCodeStream * pslILDispatch = psl->GetDispatchCodeStream();
2874 if (!fManagedToNative)
2876 *pResID = IDS_EE_BADMARSHAL_RETURNSHCOMTONATIVE;
2880 // Returned SafeHandle parameters must not be abstract.
2881 if (pargs->m_pMT->IsAbstract())
2883 *pResID = IDS_EE_BADMARSHAL_ABSTRACTRETSAFEHANDLE;
2887 // 1) create local for new safehandle
2888 // 2) prealloc a safehandle
2889 // 3) create local to hold returned handle
2890 // 4) [byref] add byref IntPtr to native sig
2891 // 5) [byref] pass address of local as last arg
2892 // 6) store return value in safehandle
2894 // 1) create local for new safehandle
2895 MethodTable * pMT = pargs->m_pMT;
2896 LocalDesc locDescReturnHandle(pMT);
2897 DWORD dwReturnHandleLocal;
2899 dwReturnHandleLocal = pslIL->NewLocal(locDescReturnHandle);
2901 if (!pMT->HasDefaultConstructor())
2903 MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
2904 COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
2907 // 2) prealloc a safehandle
2908 MethodDesc* pMDCtor = pMT->GetDefaultConstructor();
2909 pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
2910 pslIL->EmitSTLOC(dwReturnHandleLocal);
2912 mdToken tkNativeHandleField = pslPostIL->GetToken(MscorlibBinder::GetField(FIELD__SAFE_HANDLE__HANDLE));
2914 // 3) create local to hold returned handle
2915 DWORD dwReturnNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
2919 // initialize the native handle
2920 pslIL->EmitLDLOC(dwReturnHandleLocal);
2921 pslIL->EmitLDFLD(tkNativeHandleField);
2922 pslIL->EmitSTLOC(dwReturnNativeHandleLocal);
2924 pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I4); // native method returns an HRESULT
2926 // 4) [byref] add byref IntPtr to native sig
2927 locDescReturnHandle.ElementType[0] = ELEMENT_TYPE_BYREF;
2928 locDescReturnHandle.ElementType[1] = ELEMENT_TYPE_I;
2929 locDescReturnHandle.cbType = 2;
2930 pslIL->SetStubTargetArgType(&locDescReturnHandle, false); // extra arg is a byref IntPtr
2932 // 5) [byref] pass address of local as last arg
2933 pslILDispatch->EmitLDLOCA(dwReturnNativeHandleLocal);
2935 // We will use cleanup stream to avoid leaking the handle on thread abort.
2936 psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL);
2938 psl->SetCleanupNeeded();
2939 ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
2940 ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
2942 psl->EmitCheckForArgCleanup(pslCleanupIL,
2943 NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL,
2944 NDirectStubLinker::BranchIfNotMarshaled,
2947 // 6) store return value in safehandle
2948 pslCleanupIL->EmitLDLOC(dwReturnHandleLocal);
2949 pslCleanupIL->EmitLDLOC(dwReturnNativeHandleLocal);
2950 pslCleanupIL->EmitSTFLD(tkNativeHandleField);
2951 pslCleanupIL->EmitLabel(pDoneLabel);
2953 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
2957 pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I);
2958 pslPostIL->EmitSTLOC(dwReturnNativeHandleLocal);
2960 // 6) store return value in safehandle
2961 // The thread abort logic knows that it must not interrupt the stub so we will
2962 // always be able to execute this sequence after returning from the call.
2963 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
2964 pslPostIL->EmitLDLOC(dwReturnNativeHandleLocal);
2965 pslPostIL->EmitSTFLD(tkNativeHandleField);
2966 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
2970 } // ILSafeHandleMarshaler::ReturnOverride
2973 //---------------------------------------------------------------------------------------
2975 MarshalerOverrideStatus ILCriticalHandleMarshaler::ArgumentOverride(NDirectStubLinker* psl,
2979 BOOL fManagedToNative,
2980 OverrideProcArgs* pargs,
2983 UINT nativeStackOffset)
2993 ILCodeStream* pslIL = psl->GetMarshalCodeStream();
2994 ILCodeStream* pslPostIL = psl->GetUnmarshalCodeStream();
2995 ILCodeStream* pslILDispatch = psl->GetDispatchCodeStream();
2997 if (fManagedToNative)
2999 pslIL->SetStubTargetArgType(ELEMENT_TYPE_I);
3001 // Grab the token for the native handle field embedded inside the CriticalHandle. We'll be using it to direct access
3002 // the native handle later.
3003 mdToken tkNativeHandleField = pslIL->GetToken(MscorlibBinder::GetField(FIELD__CRITICAL_HANDLE__HANDLE));
3007 // The specific CriticalHandle subtype we're dealing with here.
3008 MethodTable *pHandleType = pargs->m_pMT;
3010 // Out CriticalHandle parameters must not be abstract.
3011 if (fout && pHandleType->IsAbstract())
3013 *pResID = IDS_EE_BADMARSHAL_ABSTRACTOUTCRITICALHANDLE;
3017 // We rely on the CriticalHandle having a default constructor.
3018 if (!pHandleType->HasDefaultConstructor())
3020 MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
3021 COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
3024 // The high level logic (note that the parameter may be in, out or both):
3025 // 1) If this is an output parameter we need to preallocate a CriticalHandle to wrap the new native handle value. We
3026 // must allocate this before the native call to avoid a failure point when we already have a native resource
3027 // allocated. We must allocate a new CriticalHandle even if we have one on input since both input and output native
3028 // handles need to be tracked and released by a CriticalHandle.
3029 // 2) Initialize a local IntPtr that will be passed to the native call. If we have an input CriticalHandle the value
3030 // comes from there otherwise we get it from the new CriticalHandle (which is guaranteed to be initialized to an
3031 // invalid handle value).
3032 // 3) If this is a out parameter we also store the original handle value (that we just computed above) in a local
3034 // 4) After the native call, if this is an output parameter and the handle value we passed to native differs from
3035 // the local copy we made then the new handle value is written into the output CriticalHandle and that
3036 // CriticalHandle is propagated back to the caller.
3039 LocalDesc locOutputHandle;
3040 DWORD dwOutputHandleLocal = 0; // The output critical handle (out only)
3041 DWORD dwOldNativeHandleLocal = 0; // The original native handle value for comparison (out only)
3042 DWORD dwNativeHandleLocal; // The input (and possibly updated) native handle value
3046 locOutputHandle.ElementType[0] = ELEMENT_TYPE_INTERNAL;
3047 locOutputHandle.cbType = 1;
3048 locOutputHandle.InternalToken = pHandleType;
3050 dwOutputHandleLocal = pslIL->NewLocal(locOutputHandle);
3052 dwOldNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
3055 dwNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
3058 // If we have an input CriticalHandle then initialize our NativeHandle local with it.
3061 pslIL->EmitLDARG(argidx);
3062 pslIL->EmitLDIND_REF();
3063 pslIL->EmitLDFLD(tkNativeHandleField);
3064 pslIL->EmitSTLOC(dwNativeHandleLocal);
3067 // For output parameters we need to allocate a new CriticalHandle to hold the result.
3070 MethodDesc* pMDCtor = pHandleType->GetDefaultConstructor();
3071 pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
3072 pslIL->EmitSTLOC(dwOutputHandleLocal);
3074 // If we didn't provide an input handle then we initialize the NativeHandle local with the (initially invalid)
3075 // handle field set up inside the output handle by the constructor.
3078 pslIL->EmitLDLOC(dwOutputHandleLocal);
3079 pslIL->EmitLDFLD(tkNativeHandleField);
3080 pslIL->EmitSTLOC(dwNativeHandleLocal);
3083 // Remember the handle value we start out with so we know whether to back propagate after the native call.
3084 pslIL->EmitLDLOC(dwNativeHandleLocal);
3085 pslIL->EmitSTLOC(dwOldNativeHandleLocal);
3088 // Leave the address of the native handle local as the argument to the native method.
3089 pslILDispatch->EmitLDLOCA(dwNativeHandleLocal);
3093 // prevent the CriticalHandle from being finalized during the call-out to native
3094 pslPostIL->EmitLDARG(argidx);
3095 pslPostIL->EmitLDIND_REF();
3096 pslPostIL->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
3099 // On the output side we only backpropagate the native handle into the output CriticalHandle and the output
3100 // CriticalHandle to the caller if the native handle actually changed (otherwise we can end up with two
3101 // CriticalHandles wrapping the same native handle, which is bad).
3104 // We will use cleanup stream to avoid leaking the handle on thread abort.
3105 psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx);
3107 psl->SetCleanupNeeded();
3108 ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
3110 ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
3112 psl->EmitCheckForArgCleanup(pslCleanupIL,
3113 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx,
3114 NDirectStubLinker::BranchIfNotMarshaled,
3117 // If this is an [in, out] handle check if the native handles have changed. If not we're finished.
3120 pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
3121 pslCleanupIL->EmitLDLOC(dwOldNativeHandleLocal);
3122 pslCleanupIL->EmitCEQ();
3123 pslCleanupIL->EmitBRTRUE(pDoneLabel);
3126 // Propagate the native handle into the output CriticalHandle.
3127 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
3128 pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
3129 pslCleanupIL->EmitSTFLD(tkNativeHandleField);
3131 // Propagate the output CriticalHandle back to the caller.
3132 pslCleanupIL->EmitLDARG(argidx);
3133 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
3134 pslCleanupIL->EmitSTIND_REF();
3136 pslCleanupIL->EmitLabel(pDoneLabel);
3141 pslILDispatch->EmitLDARG(argidx);
3142 pslILDispatch->EmitLDFLD(tkNativeHandleField);
3144 // prevent the CriticalHandle from being finalized during the call-out to native
3145 pslPostIL->EmitLDARG(argidx);
3146 pslPostIL->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
3153 *pResID = IDS_EE_BADMARSHAL_CRITICALHANDLENATIVETOCOM;
3158 //---------------------------------------------------------------------------------------
3160 MarshalerOverrideStatus
3161 ILCriticalHandleMarshaler::ReturnOverride(
3162 NDirectStubLinker * psl,
3163 BOOL fManagedToNative,
3165 OverrideProcArgs * pargs,
3173 PRECONDITION(CheckPointer(psl));
3174 PRECONDITION(CheckPointer(pargs));
3175 PRECONDITION(CheckPointer(pResID));
3179 if (!fManagedToNative)
3181 *pResID = IDS_EE_BADMARSHAL_RETURNSHCOMTONATIVE;
3185 // Returned CriticalHandle parameters must not be abstract.
3186 if (pargs->m_pMT->IsAbstract())
3188 *pResID = IDS_EE_BADMARSHAL_ABSTRACTRETCRITICALHANDLE;
3192 ILCodeStream * pslIL = psl->GetMarshalCodeStream();
3193 ILCodeStream * pslPostIL = psl->GetReturnUnmarshalCodeStream();
3194 ILCodeStream * pslILDispatch = psl->GetDispatchCodeStream();
3196 // 1) create local for new criticalhandle
3197 // 2) prealloc a criticalhandle
3198 // 3) create local to hold returned handle
3199 // 4) [byref] add byref IntPtr to native sig
3200 // 5) [byref] pass address of local as last arg
3201 // 6) store return value in criticalhandle
3203 // 1) create local for new criticalhandle
3204 MethodTable * pMT = pargs->m_pMT;
3205 LocalDesc locDescReturnHandle(pMT);
3206 DWORD dwReturnHandleLocal;
3208 dwReturnHandleLocal = pslIL->NewLocal(locDescReturnHandle);
3210 if (!pMT->HasDefaultConstructor())
3212 MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
3213 COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
3216 // 2) prealloc a criticalhandle
3217 MethodDesc * pMDCtor = pMT->GetDefaultConstructor();
3218 pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
3219 pslIL->EmitSTLOC(dwReturnHandleLocal);
3221 mdToken tkNativeHandleField = pslPostIL->GetToken(MscorlibBinder::GetField(FIELD__CRITICAL_HANDLE__HANDLE));
3223 // 3) create local to hold returned handle
3224 DWORD dwReturnNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
3228 // initialize the native handle
3229 pslIL->EmitLDLOC(dwReturnHandleLocal);
3230 pslIL->EmitLDFLD(tkNativeHandleField);
3231 pslIL->EmitSTLOC(dwReturnNativeHandleLocal);
3233 pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I4); // native method returns an HRESULT
3235 // 4) [byref] add byref IntPtr to native sig
3236 locDescReturnHandle.ElementType[0] = ELEMENT_TYPE_BYREF;
3237 locDescReturnHandle.ElementType[1] = ELEMENT_TYPE_I;
3238 locDescReturnHandle.cbType = 2;
3239 pslIL->SetStubTargetArgType(&locDescReturnHandle, false); // extra arg is a byref IntPtr
3241 // 5) [byref] pass address of local as last arg
3242 pslILDispatch->EmitLDLOCA(dwReturnNativeHandleLocal);
3244 // We will use cleanup stream to avoid leaking the handle on thread abort.
3245 psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL);
3247 psl->SetCleanupNeeded();
3248 ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
3249 ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
3251 // 6) store return value in criticalhandle
3252 psl->EmitCheckForArgCleanup(pslCleanupIL,
3253 NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL,
3254 NDirectStubLinker::BranchIfNotMarshaled,
3257 pslCleanupIL->EmitLDLOC(dwReturnHandleLocal);
3258 pslCleanupIL->EmitLDLOC(dwReturnNativeHandleLocal);
3259 pslCleanupIL->EmitSTFLD(tkNativeHandleField);
3260 pslCleanupIL->EmitLabel(pDoneLabel);
3262 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
3266 pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I);
3267 pslPostIL->EmitSTLOC(dwReturnNativeHandleLocal);
3269 // 6) store return value in criticalhandle
3270 // The thread abort logic knows that it must not interrupt the stub so we will
3271 // always be able to execute this sequence after returning from the call.
3272 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
3273 pslPostIL->EmitLDLOC(dwReturnNativeHandleLocal);
3274 pslPostIL->EmitSTFLD(tkNativeHandleField);
3275 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
3279 } // ILCriticalHandleMarshaler::ReturnOverride
3282 LocalDesc ILArgIteratorMarshaler::GetNativeType()
3284 LIMITED_METHOD_CONTRACT;
3286 return LocalDesc(ELEMENT_TYPE_I); // va_list
3289 LocalDesc ILArgIteratorMarshaler::GetManagedType()
3291 STANDARD_VM_CONTRACT;
3293 return LocalDesc(MscorlibBinder::GetClass(CLASS__ARG_ITERATOR));
3296 bool ILArgIteratorMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3298 LIMITED_METHOD_CONTRACT;
3300 if (IsByref(dwMarshalFlags))
3302 *pErrorResID = IDS_EE_BADMARSHAL_ARGITERATORRESTRICTION;
3309 void ILArgIteratorMarshaler::EmitMarshalArgumentCLRToNative()
3314 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3318 EmitSetupSigAndDefaultHomesCLRToNative();
3324 // Allocate enough memory for va_list
3325 DWORD dwVaListSizeLocal = m_pcsMarshal->NewLocal(LocalDesc(ELEMENT_TYPE_U4));
3326 EmitLoadManagedHomeAddr(m_pcsMarshal);
3327 m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__CALC_VA_LIST_SIZE, 1, 1);
3328 m_pcsMarshal->EmitSTLOC(dwVaListSizeLocal);
3329 m_pcsMarshal->EmitLDLOC(dwVaListSizeLocal);
3330 m_pcsMarshal->EmitLOCALLOC();
3331 EmitStoreNativeValue(m_pcsMarshal);
3333 // void MarshalToUnmanagedVaListInternal(cbVaListSize, va_list, VARARGS* data)
3334 EmitLoadNativeValue(m_pcsMarshal);
3335 m_pcsMarshal->EmitLDLOC(dwVaListSizeLocal);
3336 EmitLoadManagedHomeAddr(m_pcsMarshal);
3337 m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__MARSHAL_TO_UNMANAGED_VA_LIST_INTERNAL, 3, 0);
3340 void ILArgIteratorMarshaler::EmitMarshalArgumentNativeToCLR()
3345 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3349 EmitSetupSigAndDefaultHomesNativeToCLR();
3351 EmitLoadNativeValue(m_pcsMarshal);
3352 EmitLoadManagedHomeAddr(m_pcsMarshal);
3354 // void MarshalToManagedVaList(va_list va, VARARGS *dataout)
3355 m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__MARSHAL_TO_MANAGED_VA_LIST_INTERNAL, 2, 0);
3359 LocalDesc ILArrayWithOffsetMarshaler::GetNativeType()
3361 LIMITED_METHOD_CONTRACT;
3363 return LocalDesc(ELEMENT_TYPE_I);
3366 LocalDesc ILArrayWithOffsetMarshaler::GetManagedType()
3368 STANDARD_VM_CONTRACT;
3370 return LocalDesc(MscorlibBinder::GetClass(CLASS__ARRAY_WITH_OFFSET));
3373 bool ILArrayWithOffsetMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3375 LIMITED_METHOD_CONTRACT;
3377 if (IsCLRToNative(dwMarshalFlags) && !IsByref(dwMarshalFlags) && IsIn(dwMarshalFlags) && IsOut(dwMarshalFlags))
3382 *pErrorResID = IDS_EE_BADMARSHAL_AWORESTRICTION;
3387 void ILArrayWithOffsetMarshaler::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
3393 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwCountLocalNum);
3394 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwOffsetLocalNum);
3395 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwPinnedLocalNum);
3399 int tokArrayWithOffset_m_array = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_ARRAY));
3400 int tokArrayWithOffset_m_count = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_COUNT));
3402 ILCodeLabel* pNonNullLabel = pslILEmit->NewCodeLabel();
3403 ILCodeLabel* pSlowAllocPathLabel = pslILEmit->NewCodeLabel();
3404 ILCodeLabel* pDoneLabel = pslILEmit->NewCodeLabel();
3406 m_dwCountLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
3409 // Convert the space
3412 EmitLoadManagedValue(pslILEmit);
3413 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3414 pslILEmit->EmitBRTRUE(pNonNullLabel);
3416 pslILEmit->EmitLoadNullPtr();
3417 pslILEmit->EmitBR(pDoneLabel);
3418 pslILEmit->EmitLabel(pNonNullLabel);
3420 EmitLoadManagedValue(pslILEmit);
3421 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_count);
3422 pslILEmit->EmitDUP();
3423 pslILEmit->EmitSTLOC(m_dwCountLocalNum);
3424 pslILEmit->EmitDUP();
3425 pslILEmit->EmitLDC(s_cbStackAllocThreshold);
3426 pslILEmit->EmitCGT_UN();
3427 pslILEmit->EmitBRTRUE(pSlowAllocPathLabel);
3430 pslILEmit->EmitLOCALLOC();
3432 pslILEmit->EmitBR(pDoneLabel);
3433 pslILEmit->EmitLabel(pSlowAllocPathLabel);
3436 pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
3438 pslILEmit->EmitLabel(pDoneLabel);
3439 EmitStoreNativeValue(pslILEmit);
3442 // Convert the contents
3445 int tokArrayWithOffset_m_offset = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_OFFSET));
3447 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
3449 LocalDesc locDescPinned;
3450 locDescPinned.cbType = 2;
3451 locDescPinned.ElementType[0] = ELEMENT_TYPE_PINNED;
3452 locDescPinned.ElementType[1] = ELEMENT_TYPE_OBJECT;
3453 m_dwPinnedLocalNum = pslILEmit->NewLocal(locDescPinned);
3454 m_dwOffsetLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
3456 EmitLoadManagedValue(pslILEmit);
3457 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3458 pslILEmit->EmitBRFALSE(pNullRefLabel);
3460 EmitLoadManagedValue(pslILEmit);
3461 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3462 pslILEmit->EmitSTLOC(m_dwPinnedLocalNum);
3464 EmitLoadNativeValue(pslILEmit); // dest
3466 pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3467 pslILEmit->EmitCONV_I();
3468 pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3469 pslILEmit->EmitCALL(METHOD__ARRAY__GET_DATA_PTR_OFFSET_INTERNAL, 1, 1);
3470 pslILEmit->EmitADD(); // TODO Phase5: Use UnsafeAddrOfPinnedArrayElement
3472 EmitLoadManagedValue(pslILEmit);
3473 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_offset);
3474 pslILEmit->EmitDUP();
3475 pslILEmit->EmitSTLOC(m_dwOffsetLocalNum);
3476 pslILEmit->EmitADD(); // src
3477 pslILEmit->EmitLDLOC(m_dwCountLocalNum); // len
3479 // static void Memcpy(byte* dest, byte* src, int len)
3480 pslILEmit->EmitCALL(METHOD__BUFFER__MEMCPY, 3, 0);
3482 pslILEmit->EmitLDNULL();
3483 pslILEmit->EmitSTLOC(m_dwPinnedLocalNum);
3485 pslILEmit->EmitLabel(pNullRefLabel);
3488 void ILArrayWithOffsetMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
3494 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED != m_dwCountLocalNum);
3495 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED != m_dwOffsetLocalNum);
3496 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED != m_dwPinnedLocalNum);
3500 int tokArrayWithOffset_m_array = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_ARRAY));
3502 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
3504 EmitLoadManagedValue(pslILEmit);
3505 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3506 pslILEmit->EmitBRFALSE(pNullRefLabel);
3508 EmitLoadManagedValue(pslILEmit);
3509 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3510 pslILEmit->EmitSTLOC(m_dwPinnedLocalNum);
3512 pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3513 pslILEmit->EmitCONV_I();
3514 pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3515 pslILEmit->EmitCALL(METHOD__ARRAY__GET_DATA_PTR_OFFSET_INTERNAL, 1, 1);
3516 pslILEmit->EmitADD(); // TODO Phase5: Use UnsafeAddrOfPinnedArrayElement
3518 pslILEmit->EmitLDLOC(m_dwOffsetLocalNum);
3519 pslILEmit->EmitADD(); // dest
3521 EmitLoadNativeValue(pslILEmit); // src
3523 pslILEmit->EmitLDLOC(m_dwCountLocalNum); // len
3525 // static void Memcpy(byte* dest, byte* src, int len)
3526 pslILEmit->EmitCALL(METHOD__BUFFER__MEMCPY, 3, 0);
3528 pslILEmit->EmitLDNULL();
3529 pslILEmit->EmitSTLOC(m_dwPinnedLocalNum);
3531 pslILEmit->EmitLabel(pNullRefLabel);
3534 void ILArrayWithOffsetMarshaler::EmitClearNativeTemp(ILCodeStream* pslILEmit)
3536 STANDARD_VM_CONTRACT;
3538 ILCodeLabel* pDoneLabel = pslILEmit->NewCodeLabel();
3540 pslILEmit->EmitLDLOC(m_dwCountLocalNum);
3541 pslILEmit->EmitLDC(s_cbStackAllocThreshold);
3542 pslILEmit->EmitCGT_UN();
3543 pslILEmit->EmitBRFALSE(pDoneLabel);
3546 EmitLoadNativeValue(pslILEmit);
3547 pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
3549 pslILEmit->EmitLabel(pDoneLabel);
3552 LocalDesc ILAsAnyMarshalerBase::GetNativeType()
3554 LIMITED_METHOD_CONTRACT;
3556 return LocalDesc(ELEMENT_TYPE_I);
3559 LocalDesc ILAsAnyMarshalerBase::GetManagedType()
3561 LIMITED_METHOD_CONTRACT;
3563 return LocalDesc(ELEMENT_TYPE_OBJECT);
3566 bool ILAsAnyMarshalerBase::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3568 WRAPPER_NO_CONTRACT;
3570 if (IsCLRToNative(dwMarshalFlags) && !IsByref(dwMarshalFlags))
3575 *pErrorResID = IDS_EE_BADMARSHAL_ASANYRESTRICTION;
3579 bool ILAsAnyMarshalerBase::SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3581 LIMITED_METHOD_CONTRACT;
3582 *pErrorResID = IDS_EE_BADMARSHAL_ASANYRESTRICTION;
3586 void ILAsAnyMarshalerBase::EmitMarshalArgumentCLRToNative()
3591 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3592 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwMarshalerLocalNum);
3596 EmitSetupSigAndDefaultHomesCLRToNative();
3598 BYTE inout = (IsIn(m_dwMarshalFlags) ? ML_IN : 0) | (IsOut(m_dwMarshalFlags) ? ML_OUT : 0);
3599 BYTE fIsAnsi = IsAnsi() ? 1 : 0;
3600 BYTE fBestFit = m_pargs->m_pMarshalInfo->GetBestFitMapping();
3601 BYTE fThrow = m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar();
3605 dwFlags |= inout << 24;
3606 dwFlags |= fIsAnsi << 16;
3607 dwFlags |= fThrow << 8;
3608 dwFlags |= fBestFit << 0;
3614 LocalDesc marshalerType(MscorlibBinder::GetClass(CLASS__ASANY_MARSHALER));
3615 m_dwMarshalerLocalNum = m_pcsMarshal->NewLocal(marshalerType);
3616 DWORD dwTmpLocalNum = m_pcsMarshal->NewLocal(ELEMENT_TYPE_I);
3618 m_pcsMarshal->EmitLDC(sizeof(MngdNativeArrayMarshaler));
3619 m_pcsMarshal->EmitLOCALLOC();
3620 m_pcsMarshal->EmitSTLOC(dwTmpLocalNum);
3622 // marshaler = new AsAnyMarshaler(local_buffer)
3623 m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3624 m_pcsMarshal->EmitINITOBJ(m_pcsMarshal->GetToken(marshalerType.InternalToken));
3626 m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3627 m_pcsMarshal->EmitLDLOC(dwTmpLocalNum);
3628 m_pcsMarshal->EmitCALL(METHOD__ASANY_MARSHALER__CTOR, 2, 0);
3630 // nativeValue = marshaler.ConvertToNative(managedValue, flags);
3631 m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3632 EmitLoadManagedValue(m_pcsMarshal);
3633 m_pcsMarshal->EmitLDC(dwFlags);
3634 m_pcsMarshal->EmitCALL(METHOD__ASANY_MARSHALER__CONVERT_TO_NATIVE, 3, 1);
3635 EmitStoreNativeValue(m_pcsMarshal);
3640 if (IsOut(m_dwMarshalFlags))
3642 // marshaler.ConvertToManaged(managedValue, nativeValue)
3643 m_pcsUnmarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3644 EmitLoadManagedValue(m_pcsUnmarshal);
3645 EmitLoadNativeValue(m_pcsUnmarshal);
3646 m_pcsUnmarshal->EmitCALL(METHOD__ASANY_MARSHALER__CONVERT_TO_MANAGED, 3, 0);
3652 EmitCleanupCLRToNativeTemp();
3655 bool ILAsAnyMarshalerBase::NeedsClearNative()
3657 LIMITED_METHOD_CONTRACT;
3661 void ILAsAnyMarshalerBase::EmitClearNativeTemp(ILCodeStream* pslILEmit)
3663 STANDARD_VM_CONTRACT;
3665 // marshaler.ClearNative(nativeHome)
3666 pslILEmit->EmitLDLOCA(m_dwMarshalerLocalNum);
3667 EmitLoadNativeValue(pslILEmit);
3668 pslILEmit->EmitCALL(METHOD__ASANY_MARSHALER__CLEAR_NATIVE, 2, 0);
3671 // we can get away with putting the GetManagedType and GetNativeType on ILMngdMarshaler because
3672 // currently it is only used for reference marshaling where this is appropriate. If it became
3673 // used for something else, we would want to move this down in the inheritence tree..
3674 LocalDesc ILMngdMarshaler::GetNativeType()
3676 LIMITED_METHOD_CONTRACT;
3678 return LocalDesc(ELEMENT_TYPE_I);
3681 LocalDesc ILMngdMarshaler::GetManagedType()
3683 LIMITED_METHOD_CONTRACT;
3685 return LocalDesc(ELEMENT_TYPE_OBJECT);
3688 void ILMngdMarshaler::EmitCallMngdMarshalerMethod(ILCodeStream* pslILEmit, MethodDesc *pMD)
3690 STANDARD_VM_CONTRACT;
3695 UINT numArgs = sig.NumFixedArgs();
3699 EmitLoadMngdMarshaler(pslILEmit);
3703 _ASSERTE(numArgs == 2);
3706 EmitLoadManagedHomeAddr(pslILEmit);
3707 EmitLoadNativeHomeAddr(pslILEmit);
3709 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), numArgs, 0);
3713 bool ILNativeArrayMarshaler::UsePinnedArraySpecialCase()
3715 if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags) && (NULL == OleVariant::GetMarshalerForVarType(m_pargs->na.m_vt, TRUE)))
3723 void ILNativeArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
3725 STANDARD_VM_CONTRACT;
3727 if (UsePinnedArraySpecialCase())
3732 m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
3734 pslILEmit->EmitLDC(sizeof(MngdNativeArrayMarshaler));
3735 pslILEmit->EmitLOCALLOC();
3736 pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
3738 CREATE_MARSHALER_CARRAY_OPERANDS mops;
3739 m_pargs->m_pMarshalInfo->GetMops(&mops);
3741 pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
3743 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(mops.methodTable));
3744 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
3746 DWORD dwFlags = mops.elementType;
3747 dwFlags |= (((DWORD)mops.bestfitmapping) << 16);
3748 dwFlags |= (((DWORD)mops.throwonunmappablechar) << 24);
3750 if (!IsCLRToNative(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
3752 // Unmanaged->managed in/out is the only case where we expect the native buffer to contain valid data.
3753 _ASSERTE((dwFlags & MngdNativeArrayMarshaler::FLAG_NATIVE_DATA_VALID) == 0);
3754 dwFlags |= MngdNativeArrayMarshaler::FLAG_NATIVE_DATA_VALID;
3757 pslILEmit->EmitLDC(dwFlags);
3759 pslILEmit->EmitCALL(METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CREATE_MARSHALER, 3, 0);
3763 void ILNativeArrayMarshaler::EmitMarshalArgumentCLRToNative()
3768 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3772 if (UsePinnedArraySpecialCase())
3775 // Replicate ML_PINNEDISOMORPHICARRAY_C2N_EXPRESS behavior -- note that this
3776 // gives in/out semantics "for free" even if the app doesn't specify one or
3777 // the other. Since there is no enforcement of this, apps blithely depend
3781 // The base offset should only be 0 for System.Array parameters for which
3782 // OleVariant::GetMarshalerForVarType(vt) should never return NULL.
3783 _ASSERTE(m_pargs->na.m_optionalbaseoffset != 0);
3785 EmitSetupSigAndDefaultHomesCLRToNative();
3787 LocalDesc managedType = GetManagedType();
3788 managedType.MakePinned();
3790 DWORD dwPinnedLocal = m_pcsMarshal->NewLocal(managedType);
3791 ILCodeLabel* pNullRefLabel = m_pcsMarshal->NewCodeLabel();
3793 m_pcsMarshal->EmitLoadNullPtr();
3794 EmitStoreNativeValue(m_pcsMarshal);
3796 EmitLoadManagedValue(m_pcsMarshal);
3797 m_pcsMarshal->EmitBRFALSE(pNullRefLabel);
3799 EmitLoadManagedValue(m_pcsMarshal);
3800 m_pcsMarshal->EmitSTLOC(dwPinnedLocal);
3801 m_pcsMarshal->EmitLDLOC(dwPinnedLocal);
3802 m_pcsMarshal->EmitCONV_I();
3803 m_pcsMarshal->EmitLDC(m_pargs->na.m_optionalbaseoffset);
3804 m_pcsMarshal->EmitADD();
3805 EmitStoreNativeValue(m_pcsMarshal);
3807 if (g_pConfig->InteropLogArguments())
3809 m_pslNDirect->EmitLogNativeArgument(m_pcsMarshal, dwPinnedLocal);
3812 m_pcsMarshal->EmitLabel(pNullRefLabel);
3816 ILMngdMarshaler::EmitMarshalArgumentCLRToNative();
3821 // Peek at the SizeParamIndex argument
3822 // 1) See if the SizeParamIndex argument is being passed by ref
3823 // 2) Get the element type of SizeParamIndex argument
3825 BOOL ILNativeArrayMarshaler::CheckSizeParamIndexArg(
3826 const CREATE_MARSHALER_CARRAY_OPERANDS &mops,
3827 CorElementType *pElementType)
3834 PRECONDITION(m_pargs != NULL);
3835 PRECONDITION(m_pargs->m_pMarshalInfo != NULL);
3839 MethodDesc *pMD = m_pargs->m_pMarshalInfo->GetMethodDesc();
3842 Module *pModule = m_pargs->m_pMarshalInfo->GetModule();
3845 SigTypeContext emptyTypeContext; // this is an empty type context: ndirect and COM calls are guaranteed to not be generics.
3846 MetaSig msig(pMD->GetSignature(),
3851 // Go to the SizeParamIndex argument
3852 // Note that we already have check in place to make sure SizeParamIndex is within range
3854 if (msig.HasExplicitThis())
3857 for (int i = 0; i < mops.countParamIdx; ++i)
3862 SigPointer sigPointer = msig.GetArgProps();
3864 // Peek into the SizeParamIndex argument
3865 CorElementType elementType;
3866 IfFailThrow(sigPointer.PeekElemType(&elementType));
3868 if (elementType != ELEMENT_TYPE_BYREF)
3870 if (elementType == ELEMENT_TYPE_STRING ||
3871 elementType == ELEMENT_TYPE_ARRAY ||
3872 elementType == ELEMENT_TYPE_FNPTR ||
3873 elementType == ELEMENT_TYPE_OBJECT ||
3874 elementType == ELEMENT_TYPE_SZARRAY ||
3875 elementType == ELEMENT_TYPE_TYPEDBYREF)
3877 COMPlusThrow(kMarshalDirectiveException, IDS_EE_SIZECONTROLBADTYPE);
3880 *pElementType = elementType;
3884 // Get the real type
3885 IfFailThrow(sigPointer.GetElemType(NULL));
3886 IfFailThrow(sigPointer.PeekElemType(&elementType));
3888 // All the integral types are supported
3891 case ELEMENT_TYPE_I1:
3892 case ELEMENT_TYPE_U1:
3893 case ELEMENT_TYPE_I2:
3894 case ELEMENT_TYPE_U2:
3895 case ELEMENT_TYPE_I4:
3896 case ELEMENT_TYPE_U4:
3897 case ELEMENT_TYPE_I8:
3898 case ELEMENT_TYPE_U8:
3899 case ELEMENT_TYPE_I:
3900 case ELEMENT_TYPE_U:
3904 COMPlusThrow(kMarshalDirectiveException, IDS_EE_SIZECONTROLBADTYPE);
3907 *pElementType = elementType;
3912 // Calculate the number of elements and load it into stack
3914 void ILNativeArrayMarshaler::EmitLoadElementCount(ILCodeStream* pslILEmit)
3916 STANDARD_VM_CONTRACT;
3919 // Determine the element count and load into evaluation stack
3921 CREATE_MARSHALER_CARRAY_OPERANDS mops;
3922 m_pargs->m_pMarshalInfo->GetMops(&mops);
3924 if (mops.multiplier != 0)
3927 // SizeParamIndex arg fix up for LCID
3929 unsigned countParamIdx = mops.countParamIdx;
3930 if (!IsCLRToNative(m_dwMarshalFlags))
3932 int lcidParamIdx = m_pslNDirect->GetLCIDParamIdx();
3934 if (lcidParamIdx >= 0 && (unsigned)lcidParamIdx <= countParamIdx)
3936 // the LCID is injected before the count parameter so the index
3937 // has to be incremented to get the unmanaged parameter number
3943 // Load SizeParamIndex argument
3945 pslILEmit->EmitLDARG(countParamIdx);
3951 // Is the SizeParamIndex points to a by-ref parameter?
3952 CorElementType sizeParamIndexArgType;
3953 if (CheckSizeParamIndexArg(mops, &sizeParamIndexArgType))
3955 // Load the by-ref parameter
3956 switch (sizeParamIndexArgType)
3958 case ELEMENT_TYPE_I1:
3959 pslILEmit->EmitLDIND_I1();
3962 case ELEMENT_TYPE_U1:
3963 pslILEmit->EmitLDIND_U1();
3966 case ELEMENT_TYPE_I2:
3967 pslILEmit->EmitLDIND_I2();
3970 case ELEMENT_TYPE_U2:
3971 pslILEmit->EmitLDIND_U2();
3974 case ELEMENT_TYPE_I4:
3975 pslILEmit->EmitLDIND_I4();
3978 case ELEMENT_TYPE_U4:
3979 pslILEmit->EmitLDIND_U4();
3982 case ELEMENT_TYPE_U8:
3983 case ELEMENT_TYPE_I8:
3984 pslILEmit->EmitLDIND_I8();
3987 case ELEMENT_TYPE_I:
3988 case ELEMENT_TYPE_U:
3989 pslILEmit->EmitLDIND_I();
3993 // Should not go here because we should've thrown exception
3999 pslILEmit->EmitCONV_OVF_I4();
4001 // multiplier * arg + additive
4002 pslILEmit->EmitLDC(mops.multiplier);
4003 pslILEmit->EmitMUL_OVF();
4004 pslILEmit->EmitLDC(mops.additive);
4005 pslILEmit->EmitADD_OVF();
4009 pslILEmit->EmitLDC((int)mops.additive);
4013 void ILNativeArrayMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
4015 STANDARD_VM_CONTRACT;
4017 EmitLoadMngdMarshaler(pslILEmit);
4018 EmitLoadManagedHomeAddr(pslILEmit);
4019 EmitLoadNativeHomeAddr(pslILEmit);
4021 if (IsByref(m_dwMarshalFlags))
4024 // Reset the element count just in case there is an exception thrown in the code emitted by
4025 // EmitLoadElementCount. The best thing we can do here is to avoid a crash.
4027 _ASSERTE(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4028 pslILEmit->EmitLDC(0);
4029 pslILEmit->EmitSTLOC(m_dwSavedSizeArg);
4032 // Dynamically calculate element count using SizeParamIndex argument
4033 EmitLoadElementCount(pslILEmit);
4035 if (IsByref(m_dwMarshalFlags))
4038 // Save the native array size before converting it to managed and load it again
4040 _ASSERTE(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4041 pslILEmit->EmitSTLOC(m_dwSavedSizeArg);
4042 pslILEmit->EmitLDLOC(m_dwSavedSizeArg);
4045 // MngdNativeArrayMarshaler::ConvertSpaceToManaged
4046 pslILEmit->EmitCALL(pslILEmit->GetToken(GetConvertSpaceToManagedMethod()), 4, 0);
4049 void ILNativeArrayMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
4051 STANDARD_VM_CONTRACT;
4053 if (IsByref(m_dwMarshalFlags))
4055 _ASSERTE(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4058 // Save the array size before converting it to native
4060 EmitLoadManagedValue(pslILEmit);
4061 ILCodeLabel *pManagedHomeIsNull = pslILEmit->NewCodeLabel();
4062 pslILEmit->EmitBRFALSE(pManagedHomeIsNull);
4063 EmitLoadManagedValue(pslILEmit);
4064 pslILEmit->EmitLDLEN();
4065 pslILEmit->EmitSTLOC(m_dwSavedSizeArg);
4066 pslILEmit->EmitLabel(pManagedHomeIsNull);
4070 ILMngdMarshaler::EmitConvertSpaceCLRToNative(pslILEmit);
4073 void ILNativeArrayMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
4075 STANDARD_VM_CONTRACT;
4077 EmitLoadMngdMarshaler(pslILEmit);
4078 EmitLoadNativeHomeAddr(pslILEmit);
4079 EmitLoadNativeSize(pslILEmit);
4081 pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeMethod()), 3, 0);
4084 void ILNativeArrayMarshaler::EmitLoadNativeSize(ILCodeStream* pslILEmit)
4086 STANDARD_VM_CONTRACT;
4088 if (IsByref(m_dwMarshalFlags))
4090 _ASSERT(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4091 pslILEmit->EmitLDLOC(m_dwSavedSizeArg);
4095 pslILEmit->EmitLDC(0);
4096 EmitLoadManagedValue(pslILEmit);
4097 ILCodeLabel *pManagedHomeIsNull = pslILEmit->NewCodeLabel();
4098 pslILEmit->EmitBRFALSE(pManagedHomeIsNull);
4099 pslILEmit->EmitPOP(); // Pop the 0 on the stack
4100 EmitLoadManagedValue(pslILEmit);
4101 pslILEmit->EmitLDLEN();
4102 pslILEmit->EmitCONV_OVF_I4();
4103 pslILEmit->EmitLabel(pManagedHomeIsNull); // Keep the 0 on the stack
4107 void ILNativeArrayMarshaler::EmitClearNativeContents(ILCodeStream* pslILEmit)
4109 STANDARD_VM_CONTRACT;
4111 EmitLoadMngdMarshaler(pslILEmit);
4112 EmitLoadNativeHomeAddr(pslILEmit);
4113 EmitLoadNativeSize(pslILEmit);
4115 pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeContentsMethod()), 3, 0);
4118 void ILNativeArrayMarshaler::EmitNewSavedSizeArgLocal()
4120 STANDARD_VM_CONTRACT;
4122 _ASSERTE(m_dwSavedSizeArg == LOCAL_NUM_UNUSED);
4123 ILCodeStream *pcsSetup = m_pslNDirect->GetSetupCodeStream();
4124 m_dwSavedSizeArg = pcsSetup->NewLocal(ELEMENT_TYPE_I4);
4125 pcsSetup->EmitLDC(0);
4126 pcsSetup->EmitSTLOC(m_dwSavedSizeArg);
4129 void ILNativeArrayMarshaler::EmitMarshalArgumentNativeToCLRByref()
4131 STANDARD_VM_CONTRACT;
4133 if (IsByref(m_dwMarshalFlags))
4135 EmitNewSavedSizeArgLocal();
4138 ILMngdMarshaler::EmitMarshalArgumentNativeToCLRByref();
4141 void ILNativeArrayMarshaler::EmitMarshalArgumentCLRToNativeByref()
4143 STANDARD_VM_CONTRACT;
4145 if (IsByref(m_dwMarshalFlags))
4147 EmitNewSavedSizeArgLocal();
4150 ILMngdMarshaler::EmitMarshalArgumentCLRToNativeByref();
4154 #ifndef CROSSGEN_COMPILE
4156 FCIMPL3(void, MngdNativeArrayMarshaler::CreateMarshaler, MngdNativeArrayMarshaler* pThis, MethodTable* pMT, UINT32 dwFlags)
4160 // Don't check whether the input values are negative - passing negative size-controlling
4161 // arguments and compensating them with a positive SizeConst has always worked.
4162 pThis->m_pElementMT = pMT;
4163 pThis->m_vt = (VARTYPE)(dwFlags);
4164 pThis->m_NativeDataValid = (BYTE)((dwFlags & FLAG_NATIVE_DATA_VALID) != 0);
4165 dwFlags &= ~FLAG_NATIVE_DATA_VALID;
4166 pThis->m_BestFitMap = (BYTE)(dwFlags >> 16);
4167 pThis->m_ThrowOnUnmappableChar = (BYTE)(dwFlags >> 24);
4168 pThis->m_Array = TypeHandle();
4172 FCIMPL3(void, MngdNativeArrayMarshaler::ConvertSpaceToNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4176 HELPER_METHOD_FRAME_BEGIN_0();
4178 BASEARRAYREF arrayRef = (BASEARRAYREF) *pManagedHome;
4180 if (arrayRef == NULL)
4182 *pNativeHome = NULL;
4186 SIZE_T cElements = arrayRef->GetNumComponents();
4187 SIZE_T cbElement = OleVariant::GetElementSizeForVarType(pThis->m_vt, pThis->m_pElementMT);
4190 COMPlusThrow(kArgumentException, IDS_EE_COM_UNSUPPORTED_SIG);
4192 SIZE_T cbArray = cElements;
4193 if ( (!SafeMulSIZE_T(&cbArray, cbElement)) || cbArray > MAX_SIZE_FOR_INTEROP)
4194 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
4196 *pNativeHome = CoTaskMemAlloc(cbArray);
4197 if (*pNativeHome == NULL)
4200 // initialize the array
4201 FillMemory(*pNativeHome, cbArray, 0);
4204 HELPER_METHOD_FRAME_END();
4208 FCIMPL3(void, MngdNativeArrayMarshaler::ConvertContentsToNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4212 HELPER_METHOD_FRAME_BEGIN_0();
4214 BASEARRAYREF* pArrayRef = (BASEARRAYREF *) pManagedHome;
4216 if (*pArrayRef != NULL)
4218 const OleVariant::Marshaler* pMarshaler = OleVariant::GetMarshalerForVarType(pThis->m_vt, TRUE);
4219 SIZE_T cElements = (*pArrayRef)->GetNumComponents();
4220 if (pMarshaler == NULL || pMarshaler->ComToOleArray == NULL)
4222 if ( (!SafeMulSIZE_T(&cElements, OleVariant::GetElementSizeForVarType(pThis->m_vt, pThis->m_pElementMT))) || cElements > MAX_SIZE_FOR_INTEROP)
4223 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
4225 _ASSERTE(!GetTypeHandleForCVType(OleVariant::GetCVTypeForVarType(pThis->m_vt)).GetMethodTable()->ContainsPointers());
4226 memcpyNoGCRefs(*pNativeHome, (*pArrayRef)->GetDataPtr(), cElements);
4230 pMarshaler->ComToOleArray(pArrayRef, *pNativeHome, pThis->m_pElementMT, pThis->m_BestFitMap,
4231 pThis->m_ThrowOnUnmappableChar, pThis->m_NativeDataValid, cElements);
4234 HELPER_METHOD_FRAME_END();
4238 FCIMPL4(void, MngdNativeArrayMarshaler::ConvertSpaceToManaged, MngdNativeArrayMarshaler* pThis,
4239 OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements)
4243 HELPER_METHOD_FRAME_BEGIN_0();
4245 if (*pNativeHome == NULL)
4247 SetObjectReference(pManagedHome, NULL, GetAppDomain());
4251 // <TODO>@todo: lookup this class before marshal time</TODO>
4252 if (pThis->m_Array.IsNull())
4254 // Get proper array class name & type
4255 pThis->m_Array = OleVariant::GetArrayForVarType(pThis->m_vt, TypeHandle(pThis->m_pElementMT));
4256 if (pThis->m_Array.IsNull())
4257 COMPlusThrow(kTypeLoadException);
4262 SetObjectReference(pManagedHome, AllocateArrayEx(pThis->m_Array, &cElements, 1), GetAppDomain());
4264 HELPER_METHOD_FRAME_END();
4268 FCIMPL3(void, MngdNativeArrayMarshaler::ConvertContentsToManaged, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4272 HELPER_METHOD_FRAME_BEGIN_0();
4274 if (*pNativeHome != NULL)
4276 const OleVariant::Marshaler *pMarshaler = OleVariant::GetMarshalerForVarType(pThis->m_vt, TRUE);
4278 BASEARRAYREF* pArrayRef = (BASEARRAYREF*) pManagedHome;
4280 if (pMarshaler == NULL || pMarshaler->OleToComArray == NULL)
4282 SIZE_T cElements = (*pArrayRef)->GetNumComponents();
4283 if ( (!SafeMulSIZE_T(&cElements, OleVariant::GetElementSizeForVarType(pThis->m_vt, pThis->m_pElementMT))) || cElements > MAX_SIZE_FOR_INTEROP)
4284 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
4286 // If we are copying variants, strings, etc, we need to use write barrier
4287 _ASSERTE(!GetTypeHandleForCVType(OleVariant::GetCVTypeForVarType(pThis->m_vt)).GetMethodTable()->ContainsPointers());
4288 memcpyNoGCRefs((*pArrayRef)->GetDataPtr(), *pNativeHome, cElements);
4292 pMarshaler->OleToComArray(*pNativeHome, pArrayRef, pThis->m_pElementMT);
4296 HELPER_METHOD_FRAME_END();
4300 FCIMPL3(void, MngdNativeArrayMarshaler::ClearNative, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
4304 HELPER_METHOD_FRAME_BEGIN_0();
4306 if (*pNativeHome != NULL)
4308 DoClearNativeContents(pThis, pNativeHome, cElements);
4309 CoTaskMemFree(*pNativeHome);
4312 HELPER_METHOD_FRAME_END();
4316 FCIMPL3(void, MngdNativeArrayMarshaler::ClearNativeContents, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
4320 HELPER_METHOD_FRAME_BEGIN_0();
4322 DoClearNativeContents(pThis, pNativeHome, cElements);
4324 HELPER_METHOD_FRAME_END();
4328 void MngdNativeArrayMarshaler::DoClearNativeContents(MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
4338 if (*pNativeHome != NULL)
4340 const OleVariant::Marshaler *pMarshaler = OleVariant::GetMarshalerForVarType(pThis->m_vt, FALSE);
4342 if (pMarshaler != NULL && pMarshaler->ClearOleArray != NULL)
4344 pMarshaler->ClearOleArray(*pNativeHome, cElements, pThis->m_pElementMT);
4349 #endif // CROSSGEN_COMPILE
4352 #ifdef FEATURE_COMINTEROP
4353 void ILSafeArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
4355 STANDARD_VM_CONTRACT;
4357 m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4359 pslILEmit->EmitLDC(sizeof(MngdSafeArrayMarshaler));
4360 pslILEmit->EmitLOCALLOC();
4361 pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
4363 CREATE_MARSHALER_CARRAY_OPERANDS mops;
4364 m_pargs->m_pMarshalInfo->GetMops(&mops);
4366 DWORD dwFlags = mops.elementType;
4369 if (NeedsCheckForStatic())
4371 fStatic |= MngdSafeArrayMarshaler::SCSF_CheckForStatic;
4374 if (!IsCLRToNative(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
4376 // Unmanaged->managed in/out is the only case where we expect the native buffer to contain valid data.
4377 fStatic |= MngdSafeArrayMarshaler::SCSF_NativeDataValid;
4380 dwFlags |= fStatic << 16;
4381 dwFlags |= ((BYTE)!!m_pargs->m_pMarshalInfo->GetNoLowerBounds()) << 24;
4383 pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
4384 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(mops.methodTable));
4385 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
4386 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetArrayRank());
4387 pslILEmit->EmitLDC(dwFlags);
4389 pslILEmit->EmitCALL(METHOD__MNGD_SAFE_ARRAY_MARSHALER__CREATE_MARSHALER, 4, 0);
4392 void ILSafeArrayMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
4394 STANDARD_VM_CONTRACT;
4396 ILMngdMarshaler::EmitConvertContentsNativeToCLR(pslILEmit);
4398 if (NeedsCheckForStatic())
4400 CONSISTENCY_CHECK(-1 == m_dwOriginalManagedLocalNum);
4401 m_dwOriginalManagedLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_OBJECT);
4402 EmitLoadManagedValue(pslILEmit);
4403 pslILEmit->EmitSTLOC(m_dwOriginalManagedLocalNum);
4407 void ILSafeArrayMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
4409 STANDARD_VM_CONTRACT;
4411 EmitLoadMngdMarshaler(pslILEmit);
4412 EmitLoadManagedHomeAddr(pslILEmit);
4413 EmitLoadNativeHomeAddr(pslILEmit);
4414 if (NeedsCheckForStatic())
4416 CONSISTENCY_CHECK(-1 != m_dwOriginalManagedLocalNum);
4417 pslILEmit->EmitLDLOC(m_dwOriginalManagedLocalNum);
4421 pslILEmit->EmitLDNULL();
4423 pslILEmit->EmitCALL(METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE, 4, 0);
4427 #ifndef CROSSGEN_COMPILE
4429 FCIMPL4(void, MngdSafeArrayMarshaler::CreateMarshaler, MngdSafeArrayMarshaler* pThis, MethodTable* pMT, UINT32 iRank, UINT32 dwFlags)
4433 pThis->m_pElementMT = pMT;
4434 pThis->m_iRank = iRank;
4435 pThis->m_vt = (VARTYPE)dwFlags;
4436 pThis->m_fStatic = (BYTE)(dwFlags >> 16);
4437 pThis->m_nolowerbounds = (BYTE)(dwFlags >> 24);
4441 FCIMPL3(void, MngdSafeArrayMarshaler::ConvertSpaceToNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4445 if (pThis->m_fStatic & SCSF_IsStatic)
4448 HELPER_METHOD_FRAME_BEGIN_0();
4455 PRECONDITION(pThis->m_vt != VT_EMPTY);
4456 PRECONDITION(CheckPointer(pThis->m_pElementMT));
4460 if (*pManagedHome != NULL)
4462 *pNativeHome = (void *) OleVariant::CreateSafeArrayForArrayRef((BASEARRAYREF*) pManagedHome, pThis->m_vt, pThis->m_pElementMT);
4466 *pNativeHome = NULL;
4469 HELPER_METHOD_FRAME_END();
4473 FCIMPL4(void, MngdSafeArrayMarshaler::ConvertContentsToNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, Object* pOriginalManagedUNSAFE)
4478 PRECONDITION(pThis->m_vt != VT_EMPTY);
4479 PRECONDITION(CheckPointer(pThis->m_pElementMT));
4483 OBJECTREF pOriginalManaged = ObjectToOBJECTREF(pOriginalManagedUNSAFE);
4484 HELPER_METHOD_FRAME_BEGIN_1(pOriginalManaged);
4486 if ((pThis->m_fStatic & SCSF_IsStatic) &&
4487 (*pManagedHome != pOriginalManaged))
4489 COMPlusThrow(kInvalidOperationException, IDS_INVALID_REDIM);
4492 if (*pManagedHome != NULL)
4494 OleVariant::MarshalSafeArrayForArrayRef((BASEARRAYREF *) pManagedHome,
4495 (SAFEARRAY*)*pNativeHome,
4497 pThis->m_pElementMT,
4498 (pThis->m_fStatic & SCSF_NativeDataValid));
4501 HELPER_METHOD_FRAME_END();
4505 FCIMPL3(void, MngdSafeArrayMarshaler::ConvertSpaceToManaged, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4510 PRECONDITION(pThis->m_vt != VT_EMPTY);
4511 PRECONDITION(CheckPointer(pThis->m_pElementMT));
4515 HELPER_METHOD_FRAME_BEGIN_0();
4517 if (*pNativeHome != NULL)
4519 // If the managed array has a rank defined then make sure the rank of the
4520 // SafeArray matches the defined rank.
4521 if (pThis->m_iRank != -1)
4523 int iSafeArrayRank = SafeArrayGetDim((SAFEARRAY*) *pNativeHome);
4524 if (pThis->m_iRank != iSafeArrayRank)
4526 WCHAR strExpectedRank[64];
4527 WCHAR strActualRank[64];
4528 _ltow_s(pThis->m_iRank, strExpectedRank, COUNTOF(strExpectedRank), 10);
4529 _ltow_s(iSafeArrayRank, strActualRank, COUNTOF(strActualRank), 10);
4530 COMPlusThrow(kSafeArrayRankMismatchException, IDS_EE_SAFEARRAYRANKMISMATCH, strActualRank, strExpectedRank);
4534 if (pThis->m_nolowerbounds)
4537 if ( (SafeArrayGetDim( (SAFEARRAY*)*pNativeHome ) != 1) ||
4538 (FAILED(SafeArrayGetLBound( (SAFEARRAY*)*pNativeHome, 1, &lowerbound))) ||
4541 COMPlusThrow(kSafeArrayRankMismatchException, IDS_EE_SAFEARRAYSZARRAYMISMATCH);
4545 SetObjectReference(pManagedHome,
4546 (OBJECTREF) OleVariant::CreateArrayRefForSafeArray((SAFEARRAY*) *pNativeHome,
4548 pThis->m_pElementMT), GetAppDomain());
4552 SetObjectReference(pManagedHome, NULL, GetAppDomain());
4555 HELPER_METHOD_FRAME_END();
4559 FCIMPL3(void, MngdSafeArrayMarshaler::ConvertContentsToManaged, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4564 PRECONDITION(pThis->m_vt != VT_EMPTY);
4565 PRECONDITION(CheckPointer(pThis->m_pElementMT));
4569 SAFEARRAY* pNative = *(SAFEARRAY**)pNativeHome;
4570 HELPER_METHOD_FRAME_BEGIN_0();
4572 if (pNative && pNative->fFeatures & FADF_STATIC)
4574 pThis->m_fStatic |= SCSF_IsStatic;
4577 if (*pNativeHome != NULL)
4579 OleVariant::MarshalArrayRefForSafeArray((SAFEARRAY*)*pNativeHome,
4580 (BASEARRAYREF *) pManagedHome,
4582 pThis->m_pElementMT);
4585 HELPER_METHOD_FRAME_END();
4589 FCIMPL3(void, MngdSafeArrayMarshaler::ClearNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4593 if (pThis->m_fStatic & SCSF_IsStatic)
4596 HELPER_METHOD_FRAME_BEGIN_0();
4598 if (*pNativeHome != NULL)
4601 _ASSERTE(GetModuleHandleA("oleaut32.dll") != NULL);
4602 // SafeArray has been created. Oleaut32.dll must have been loaded.
4603 CONTRACT_VIOLATION(ThrowsViolation);
4604 SafeArrayDestroy((SAFEARRAY*)*pNativeHome);
4607 HELPER_METHOD_FRAME_END();
4611 #endif // CROSSGEN_COMPILE
4614 LocalDesc ILHiddenLengthArrayMarshaler::GetNativeType()
4616 LIMITED_METHOD_CONTRACT;
4617 return LocalDesc(ELEMENT_TYPE_I);
4620 LocalDesc ILHiddenLengthArrayMarshaler::GetManagedType()
4622 LIMITED_METHOD_CONTRACT;
4623 return LocalDesc(ELEMENT_TYPE_OBJECT);
4626 void ILHiddenLengthArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
4628 STANDARD_VM_CONTRACT;
4630 if (!CanUsePinnedArray())
4632 m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4634 pslILEmit->EmitLDC(sizeof(MngdHiddenLengthArrayMarshaler));
4635 pslILEmit->EmitLOCALLOC();
4636 pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
4638 MethodTable *pElementMT = m_pargs->m_pMarshalInfo->GetArrayElementTypeHandle().GetMethodTable();
4639 pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
4640 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(pElementMT));
4641 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
4643 pslILEmit->EmitLDC(m_pargs->na.m_cbElementSize);
4644 pslILEmit->EmitLDC(m_pargs->na.m_vt);
4646 pslILEmit->EmitCALL(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CREATE_MARSHALER, 4, 0);
4650 void ILHiddenLengthArrayMarshaler::EmitMarshalArgumentCLRToNative()
4652 STANDARD_VM_CONTRACT;
4654 // If we can pin the array, then do that rather than marshaling it in a more heavy weight way
4655 // Otherwise, fall back to doing a full marshal
4656 if (CanUsePinnedArray())
4658 EmitSetupSigAndDefaultHomesCLRToNative();
4660 LocalDesc managedType = GetManagedType();
4661 managedType.MakePinned();
4662 DWORD dwPinnedLocal = m_pcsMarshal->NewLocal(managedType);
4664 ILCodeLabel* pMarshalDoneLabel = m_pcsMarshal->NewCodeLabel();
4667 m_pcsMarshal->EmitLoadNullPtr();
4668 EmitStoreNativeValue(m_pcsMarshal);
4670 // if (managed == null) goto MarshalDone
4671 EmitLoadManagedValue(m_pcsMarshal);
4672 m_pcsMarshal->EmitBRFALSE(pMarshalDoneLabel);
4674 // pinnedLocal = managed;
4675 EmitLoadManagedValue(m_pcsMarshal);
4676 m_pcsMarshal->EmitSTLOC(dwPinnedLocal);
4678 // native = pinnedLocal + dataOffset
4679 m_pcsMarshal->EmitLDLOC(dwPinnedLocal);
4680 m_pcsMarshal->EmitCONV_I();
4681 m_pcsMarshal->EmitLDC(m_pargs->na.m_optionalbaseoffset);
4682 m_pcsMarshal->EmitADD();
4683 EmitStoreNativeValue(m_pcsMarshal);
4685 if (g_pConfig->InteropLogArguments())
4687 m_pslNDirect->EmitLogNativeArgument(m_pcsMarshal, dwPinnedLocal);
4691 m_pcsMarshal->EmitLabel(pMarshalDoneLabel);
4695 ILMngdMarshaler::EmitMarshalArgumentCLRToNative();
4700 void ILHiddenLengthArrayMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
4702 STANDARD_VM_CONTRACT;
4704 if (!CanUsePinnedArray())
4706 EmitLoadMngdMarshaler(pslILEmit);
4707 EmitLoadManagedHomeAddr(pslILEmit);
4708 EmitLoadNativeHomeAddr(pslILEmit);
4709 EmitLoadNativeArrayLength(pslILEmit);
4711 // MngdHiddenLengthArrayMarshaler::ConvertSpaceToManaged
4712 pslILEmit->EmitCALL(pslILEmit->GetToken(GetConvertSpaceToManagedMethod()), 4, 0);
4716 void ILHiddenLengthArrayMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
4718 STANDARD_VM_CONTRACT;
4720 // If we're marshaling out to native code, then we need to set the length out parameter
4721 if (!IsCLRToNative(m_dwMarshalFlags))
4723 if (IsByref(m_dwMarshalFlags) || IsRetval(m_dwMarshalFlags) || IsOut(m_dwMarshalFlags))
4725 ILCodeLabel *pSkipGetLengthLabel = m_pcsMarshal->NewCodeLabel();
4728 pslILEmit->EmitLDC(0);
4729 pslILEmit->EmitCONV_T(m_pargs->m_pMarshalInfo->GetHiddenLengthParamElementType());
4730 pslILEmit->EmitSTLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
4732 // if (array == null) goto SkipGetLength
4733 EmitLoadManagedValue(pslILEmit);
4734 pslILEmit->EmitBRFALSE(pSkipGetLengthLabel);
4736 // nativeLen = array.Length
4738 EmitLoadManagedValue(pslILEmit);
4739 pslILEmit->EmitLDLEN();
4740 pslILEmit->EmitCONV_T(m_pargs->m_pMarshalInfo->GetHiddenLengthParamElementType());
4741 pslILEmit->EmitSTLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
4742 pslILEmit->EmitLabel(pSkipGetLengthLabel);
4744 // nativeLenParam = nativeLen
4745 LocalDesc nativeParamType(m_pargs->m_pMarshalInfo->GetHiddenLengthParamElementType());
4746 pslILEmit->EmitLDARG(m_pargs->m_pMarshalInfo->HiddenLengthParamIndex());
4747 pslILEmit->EmitLDLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
4748 pslILEmit->EmitSTIND_T(&nativeParamType);
4752 if (!CanUsePinnedArray())
4754 ILMngdMarshaler::EmitConvertSpaceCLRToNative(pslILEmit);
4758 void ILHiddenLengthArrayMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
4760 STANDARD_VM_CONTRACT;
4762 if (!CanUsePinnedArray())
4764 if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE &&
4765 (m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Uri ||
4766 m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs ||
4767 m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs))
4769 // System.Uri/NotifyCollectionChangedEventArgs don't live in mscorlib so there's no marshaling helper to call - inline the loop
4770 DWORD dwLoopCounterLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
4771 DWORD dwNativePtrLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4772 ILCodeLabel *pConditionLabel = pslILEmit->NewCodeLabel();
4773 ILCodeLabel *pLoopBodyLabel = pslILEmit->NewCodeLabel();
4775 // for (IntPtr ptr = pNative, int i = 0; ...
4776 pslILEmit->EmitLDC(0);
4777 pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4778 EmitLoadNativeValue(pslILEmit);
4779 pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4780 pslILEmit->EmitBR(pConditionLabel);
4782 // *ptr = EmitConvertCLR*ToWinRT*(pManaged[i]);
4783 pslILEmit->EmitLabel(pLoopBodyLabel);
4784 pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4785 EmitLoadManagedValue(pslILEmit);
4786 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4787 pslILEmit->EmitLDELEM_REF();
4789 switch (m_pargs->na.m_redirectedTypeIndex)
4791 case WinMDAdapter::RedirectedTypeIndex_System_Uri:
4792 ILUriMarshaler::EmitConvertCLRUriToWinRTUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4795 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
4796 ILNCCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4799 case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
4800 ILPCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4803 default: UNREACHABLE();
4806 pslILEmit->EmitSTIND_I();
4808 // ... i++, ptr += IntPtr.Size ...
4809 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4810 pslILEmit->EmitLDC(1);
4811 pslILEmit->EmitADD();
4812 pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4813 pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4814 pslILEmit->EmitLDC(sizeof(LPVOID));
4815 pslILEmit->EmitADD();
4816 pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4818 // ... i < pManaged.Length; ...
4819 pslILEmit->EmitLabel(pConditionLabel);
4820 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4821 EmitLoadNativeArrayLength(pslILEmit);
4822 pslILEmit->EmitBLT(pLoopBodyLabel);
4826 ILMngdMarshaler::EmitConvertContentsCLRToNative(pslILEmit);
4831 void ILHiddenLengthArrayMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
4833 STANDARD_VM_CONTRACT;
4835 if (!CanUsePinnedArray())
4837 if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE &&
4838 (m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Uri ||
4839 m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs ||
4840 m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs))
4842 // System.Uri/NotifyCollectionChangedEventArgs don't live in mscorlib so there's no marshaling helper to call - inline the loop
4843 DWORD dwLoopCounterLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
4844 DWORD dwNativePtrLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4845 ILCodeLabel *pConditionLabel = pslILEmit->NewCodeLabel();
4846 ILCodeLabel *pLoopBodyLabel = pslILEmit->NewCodeLabel();
4848 // for (IntPtr ptr = pNative, int i = 0; ...
4849 pslILEmit->EmitLDC(0);
4850 pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4851 EmitLoadNativeValue(pslILEmit);
4852 pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4853 pslILEmit->EmitBR(pConditionLabel);
4855 // pManaged[i] = EmitConvertWinRT*ToCLR*(*ptr);
4856 pslILEmit->EmitLabel(pLoopBodyLabel);
4857 EmitLoadManagedValue(pslILEmit);
4858 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4859 pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4860 pslILEmit->EmitLDIND_I();
4862 switch (m_pargs->na.m_redirectedTypeIndex)
4864 case WinMDAdapter::RedirectedTypeIndex_System_Uri:
4865 ILUriMarshaler::EmitConvertWinRTUriToCLRUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4868 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
4869 ILNCCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4872 case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
4873 ILPCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4876 default: UNREACHABLE();
4879 pslILEmit->EmitSTELEM_REF();
4881 // ... i++, ptr += IntPtr.Size)
4882 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4883 pslILEmit->EmitLDC(1);
4884 pslILEmit->EmitADD();
4885 pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4886 pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4887 pslILEmit->EmitLDC(sizeof(LPVOID));
4888 pslILEmit->EmitADD();
4889 pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4891 // ... i < pManaged.Length; ...
4892 pslILEmit->EmitLabel(pConditionLabel);
4893 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4894 EmitLoadNativeArrayLength(pslILEmit);
4895 pslILEmit->EmitBLT(pLoopBodyLabel);
4899 ILMngdMarshaler::EmitConvertContentsNativeToCLR(pslILEmit);
4904 void ILHiddenLengthArrayMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
4906 STANDARD_VM_CONTRACT;
4908 EmitClearNativeContents(pslILEmit);
4910 if (!CanUsePinnedArray())
4912 EmitLoadNativeValue(pslILEmit);
4913 pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeMethod()), 1, 0);
4917 void ILHiddenLengthArrayMarshaler::EmitClearNativeContents(ILCodeStream* pslILEmit)
4919 STANDARD_VM_CONTRACT;
4921 if (!CanUsePinnedArray())
4923 MethodDesc *pMD = GetClearNativeContentsMethod();
4927 UINT numArgs = sig.NumFixedArgs();
4931 EmitLoadMngdMarshaler(pslILEmit);
4935 _ASSERTE(numArgs == 2);
4938 EmitLoadNativeHomeAddr(pslILEmit);
4939 EmitLoadNativeArrayLength(pslILEmit);
4940 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), numArgs, 0);
4945 // Determine if we can simply pin the managed array, rather than doing a full marshal
4946 bool ILHiddenLengthArrayMarshaler::CanUsePinnedArray()
4948 STANDARD_VM_CONTRACT;
4950 // If the array is only going from managed to native, and it contains only blittable data, and
4951 // we know where that data is located in the array then we can take the fast path
4952 if (!IsCLRToNative(m_dwMarshalFlags))
4957 if (m_pargs->na.m_vt != VTHACK_BLITTABLERECORD)
4962 if (IsByref(m_dwMarshalFlags))
4967 if (!IsIn(m_dwMarshalFlags))
4972 if (IsRetval(m_dwMarshalFlags))
4977 if (m_pargs->na.m_optionalbaseoffset == 0)
4985 void ILHiddenLengthArrayMarshaler::EmitLoadNativeArrayLength(ILCodeStream *pslILEmit)
4987 STANDARD_VM_CONTRACT;
4989 // For return values, the native length won't yet be marshaled back to its managed home
4990 // so it needs to be read directly
4991 if (IsRetval(m_dwMarshalFlags))
4993 pslILEmit->EmitLDLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
4997 pslILEmit->EmitLDLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthManagedHome());
5000 pslILEmit->EmitCONV_OVF_I4();
5003 MethodDesc *ILHiddenLengthArrayMarshaler::GetConvertContentsToManagedMethod()
5005 STANDARD_VM_CONTRACT;
5007 if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE)
5009 switch (m_pargs->na.m_redirectedTypeIndex)
5011 case WinMDAdapter::RedirectedTypeIndex_System_DateTimeOffset:
5012 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_DATETIME);
5014 case WinMDAdapter::RedirectedTypeIndex_System_Type:
5015 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_TYPE);
5017 case WinMDAdapter::RedirectedTypeIndex_System_Exception:
5018 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_EXCEPTION);
5020 case WinMDAdapter::RedirectedTypeIndex_System_Nullable:
5022 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_NULLABLE);
5023 return GetExactMarshalerMethod(pMD);
5026 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_KeyValuePair:
5028 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_KEYVALUEPAIR);
5029 return GetExactMarshalerMethod(pMD);
5033 UNREACHABLE_MSG("Unrecognized redirected type.");
5036 return ILMngdMarshaler::GetConvertContentsToManagedMethod();
5039 MethodDesc *ILHiddenLengthArrayMarshaler::GetConvertContentsToNativeMethod()
5041 STANDARD_VM_CONTRACT;
5043 if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE)
5045 switch (m_pargs->na.m_redirectedTypeIndex)
5047 case WinMDAdapter::RedirectedTypeIndex_System_DateTimeOffset:
5048 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_DATETIME);
5050 case WinMDAdapter::RedirectedTypeIndex_System_Type:
5051 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_TYPE);
5053 case WinMDAdapter::RedirectedTypeIndex_System_Exception:
5054 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_EXCEPTION);
5056 case WinMDAdapter::RedirectedTypeIndex_System_Nullable:
5058 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_NULLABLE);
5059 return GetExactMarshalerMethod(pMD);
5062 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_KeyValuePair:
5064 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_KEYVALUEPAIR);
5065 return GetExactMarshalerMethod(pMD);
5069 UNREACHABLE_MSG("Unrecognized redirected type.");
5072 return ILMngdMarshaler::GetConvertContentsToNativeMethod();
5075 MethodDesc *ILHiddenLengthArrayMarshaler::GetClearNativeContentsMethod()
5077 switch (m_pargs->na.m_vt)
5079 // HSTRINGs, interface pointers, and non-blittable structs need contents cleanup
5080 case VTHACK_HSTRING:
5081 case VTHACK_INSPECTABLE:
5082 case VTHACK_NONBLITTABLERECORD:
5085 // blittable structs don't need contents cleanup
5086 case VTHACK_BLITTABLERECORD:
5089 case VTHACK_REDIRECTEDTYPE:
5091 switch (m_pargs->na.m_redirectedTypeIndex)
5093 // System.Type, Uri, Nullable, KeyValuePair, NCCEventArgs, and PCEventArgs need cleanup
5094 case WinMDAdapter::RedirectedTypeIndex_System_Type:
5095 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CLEAR_NATIVE_CONTENTS_TYPE);
5097 case WinMDAdapter::RedirectedTypeIndex_System_Uri:
5098 case WinMDAdapter::RedirectedTypeIndex_System_Nullable:
5099 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_KeyValuePair:
5100 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
5101 case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
5104 // other redirected types don't
5112 UNREACHABLE_MSG("Unexpected hidden-length array element VT");
5115 return ILMngdMarshaler::GetClearNativeContentsMethod();
5118 MethodDesc *ILHiddenLengthArrayMarshaler::GetExactMarshalerMethod(MethodDesc *pGenericMD)
5120 STANDARD_VM_CONTRACT;
5122 return MethodDesc::FindOrCreateAssociatedMethodDesc(
5124 pGenericMD->GetMethodTable(),
5125 FALSE, // forceBoxedEntryPoint
5126 m_pargs->na.m_pMT->GetInstantiation(), // methodInst
5127 FALSE, // allowInstParam
5128 TRUE); // forceRemotableMethod
5131 #ifndef CROSSGEN_COMPILE
5133 FCIMPL4(void, MngdHiddenLengthArrayMarshaler::CreateMarshaler, MngdHiddenLengthArrayMarshaler* pThis, MethodTable* pMT, SIZE_T cbElementSize, UINT16 vt)
5137 pThis->m_pElementMT = pMT;
5138 pThis->m_cbElementSize = cbElementSize;
5139 pThis->m_vt = (VARTYPE)vt;
5143 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ConvertSpaceToNative, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5147 BASEARRAYREF arrayRef = (BASEARRAYREF) *pManagedHome;
5148 HELPER_METHOD_FRAME_BEGIN_1(arrayRef);
5150 if (arrayRef == NULL)
5152 *pNativeHome = NULL;
5156 SIZE_T cbArray = pThis->GetArraySize(arrayRef->GetNumComponents());
5158 *pNativeHome = CoTaskMemAlloc(cbArray);
5159 if (*pNativeHome == NULL)
5164 // initialize the array
5165 FillMemory(*pNativeHome, cbArray, 0);
5168 HELPER_METHOD_FRAME_END();
5172 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ConvertContentsToNative, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5178 PTRARRAYREF arrayRef;
5179 STRINGREF currentStringRef;
5180 OBJECTREF currentObjectRef;
5183 ZeroMemory(&gc, sizeof(gc));
5184 gc.arrayRef = (PTRARRAYREF)*pManagedHome;
5186 HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
5188 if (gc.arrayRef != NULL)
5190 // There are these choices:
5191 // * the array is made up of entirely blittable data, in which case we can directly copy it,
5192 // * it is an array of strings that need to be marshaled as HSTRING,
5193 // * it is an array of non-blittable structures
5194 // * it is an array of interface pointers (interface, runtime class, delegate, System.Object)
5195 switch (pThis->m_vt)
5197 case VTHACK_BLITTABLERECORD:
5199 // Just do a raw memcpy into the array
5200 SIZE_T cbArray = pThis->GetArraySize(gc.arrayRef->GetNumComponents());
5201 memcpyNoGCRefs(*pNativeHome, gc.arrayRef->GetDataPtr(), cbArray);
5205 case VTHACK_HSTRING:
5207 // Marshal a string array as an array of HSTRINGs
5208 if (!WinRTSupported())
5210 COMPlusThrow(kPlatformNotSupportedException, W("PlatformNotSupported_WinRT"));
5213 HSTRING *pDestinationStrings = reinterpret_cast<HSTRING *>(*pNativeHome);
5215 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5217 gc.currentStringRef = (STRINGREF)gc.arrayRef->GetAt(i);
5218 if (gc.currentStringRef == NULL)
5220 StackSString ssIndex;
5221 ssIndex.Printf(W("%d"), i);
5222 COMPlusThrow(kMarshalDirectiveException, IDS_EE_BADMARSHALARRAY_NULL_HSTRING, ssIndex.GetUnicode());
5225 IfFailThrow(WindowsCreateString(gc.currentStringRef->GetBuffer(), gc.currentStringRef->GetStringLength(), &(pDestinationStrings[i])));
5230 case VTHACK_NONBLITTABLERECORD:
5232 BYTE *pNativeStart = reinterpret_cast<BYTE *>(*pNativeHome);
5233 SIZE_T managedOffset = ArrayBase::GetDataPtrOffset(gc.arrayRef->GetMethodTable());
5234 SIZE_T nativeOffset = 0;
5235 SIZE_T managedSize = gc.arrayRef->GetComponentSize();
5236 SIZE_T nativeSize = pThis->m_pElementMT->GetNativeSize();
5237 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5239 LayoutUpdateNative(reinterpret_cast<LPVOID *>(&gc.arrayRef), managedOffset, pThis->m_pElementMT, pNativeStart + nativeOffset, NULL);
5240 managedOffset += managedSize;
5241 nativeOffset += nativeSize;
5246 case VTHACK_INSPECTABLE:
5248 // interface pointers
5249 IUnknown **pDestinationIPs = reinterpret_cast<IUnknown **>(*pNativeHome);
5251 // If this turns out to be a perf issue, we can precompute the ItfMarshalInfo
5252 // and generate code that passes it to the marshaler at creation time.
5253 ItfMarshalInfo itfInfo;
5254 MarshalInfo::GetItfMarshalInfo(TypeHandle(pThis->m_pElementMT), TypeHandle(), FALSE, TRUE, MarshalInfo::MARSHAL_SCENARIO_WINRT, &itfInfo);
5256 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5258 gc.currentObjectRef = gc.arrayRef->GetAt(i);
5259 pDestinationIPs[i] = MarshalObjectToInterface(
5260 &gc.currentObjectRef,
5261 itfInfo.thNativeItf.GetMethodTable(),
5262 itfInfo.thClass.GetMethodTable(),
5269 UNREACHABLE_MSG("Unrecognized array element VARTYPE");
5273 HELPER_METHOD_FRAME_END();
5277 FCIMPL4(void, MngdHiddenLengthArrayMarshaler::ConvertSpaceToManaged, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements)
5281 HELPER_METHOD_FRAME_BEGIN_0();
5283 if (*pNativeHome == NULL)
5285 SetObjectReference(pManagedHome, NULL, GetAppDomain());
5289 TypeHandle elementType(pThis->m_pElementMT);
5290 TypeHandle arrayType = ClassLoader::LoadArrayTypeThrowing(elementType);
5291 SetObjectReference(pManagedHome, AllocateArrayEx(arrayType, &cElements, 1), GetAppDomain());
5294 HELPER_METHOD_FRAME_END();
5298 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ConvertContentsToManaged, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5304 PTRARRAYREF arrayRef;
5305 STRINGREF stringRef;
5306 OBJECTREF objectRef;
5309 ZeroMemory(&gc, sizeof(gc));
5310 gc.arrayRef = (PTRARRAYREF)*pManagedHome;
5312 HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
5314 if (*pNativeHome != NULL)
5316 // There are these choices:
5317 // * the array is made up of entirely blittable data, in which case we can directly copy it,
5318 // * it is an array of strings that need to be marshaled as HSTRING,
5319 // * it is an array of non-blittable structures
5320 // * it is an array of interface pointers (interface, runtime class, delegate, System.Object)
5321 switch (pThis->m_vt)
5323 case VTHACK_BLITTABLERECORD:
5325 // Just do a raw memcpy into the array
5326 SIZE_T cbArray = pThis->GetArraySize(gc.arrayRef->GetNumComponents());
5327 memcpyNoGCRefs(gc.arrayRef->GetDataPtr(), *pNativeHome, cbArray);
5331 case VTHACK_HSTRING:
5333 // Strings are in HSRING format on the native side
5334 if (!WinRTSupported())
5336 COMPlusThrow(kPlatformNotSupportedException, W("PlatformNotSupported_WinRT"));
5339 HSTRING *pSourceStrings = reinterpret_cast<HSTRING *>(*pNativeHome);
5341 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5343 // NULL HSTRINGS are equivilent to empty strings
5344 UINT32 cchString = 0;
5345 LPCWSTR pwszString = W("");
5347 if (pSourceStrings[i] != NULL)
5349 pwszString = WindowsGetStringRawBuffer(pSourceStrings[i], &cchString);
5352 gc.stringRef = StringObject::NewString(pwszString, cchString);
5353 gc.arrayRef->SetAt(i, gc.stringRef);
5358 case VTHACK_NONBLITTABLERECORD:
5360 // Defer to the field marshaler to handle structures
5361 BYTE *pNativeStart = reinterpret_cast<BYTE *>(*pNativeHome);
5362 SIZE_T managedOffset = ArrayBase::GetDataPtrOffset(gc.arrayRef->GetMethodTable());
5363 SIZE_T nativeOffset = 0;
5364 SIZE_T managedSize = gc.arrayRef->GetComponentSize();
5365 SIZE_T nativeSize = pThis->m_pElementMT->GetNativeSize();
5366 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5368 LayoutUpdateCLR(reinterpret_cast<LPVOID *>(&gc.arrayRef), managedOffset, pThis->m_pElementMT, pNativeStart + nativeOffset);
5369 managedOffset += managedSize;
5370 nativeOffset += nativeSize;
5375 case VTHACK_INSPECTABLE:
5377 // interface pointers
5378 IUnknown **pSourceIPs = reinterpret_cast<IUnknown **>(*pNativeHome);
5380 // If this turns out to be a perf issue, we can precompute the ItfMarshalInfo
5381 // and generate code that passes it to the marshaler at creation time.
5382 ItfMarshalInfo itfInfo;
5383 MarshalInfo::GetItfMarshalInfo(TypeHandle(pThis->m_pElementMT), TypeHandle(), FALSE, TRUE, MarshalInfo::MARSHAL_SCENARIO_WINRT, &itfInfo);
5385 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5387 gc.objectRef = gc.arrayRef->GetAt(i);
5388 UnmarshalObjectFromInterface(
5391 itfInfo.thItf.GetMethodTable(),
5392 itfInfo.thClass.GetMethodTable(),
5394 gc.arrayRef->SetAt(i, gc.objectRef);
5400 UNREACHABLE_MSG("Unrecognized array element VARTYPE");
5404 HELPER_METHOD_FRAME_END();
5408 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ClearNativeContents, MngdHiddenLengthArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
5412 HELPER_METHOD_FRAME_BEGIN_0();
5414 if (*pNativeHome != NULL)
5416 pThis->DoClearNativeContents(pNativeHome, cElements);
5419 HELPER_METHOD_FRAME_END();
5423 #endif // CROSSGEN_COMPILE
5426 SIZE_T MngdHiddenLengthArrayMarshaler::GetArraySize(SIZE_T elements)
5436 _ASSERTE_MSG(m_cbElementSize != 0, "You have to set the native size for your array element type");
5440 if (!ClrSafeInt<SIZE_T>::multiply(elements, m_cbElementSize, cbArray))
5442 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
5445 // This array size limit is carried over from the equivilent limit for other array marshaling code
5446 if (cbArray > MAX_SIZE_FOR_INTEROP)
5448 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
5454 #ifndef CROSSGEN_COMPILE
5455 void MngdHiddenLengthArrayMarshaler::DoClearNativeContents(void** pNativeHome, INT32 cElements)
5462 PRECONDITION(pNativeHome != NULL);
5467 if (vt == VTHACK_REDIRECTEDTYPE)
5469 // the redirected types that use this helper are interface pointers on the WinRT side
5470 vt = VTHACK_INSPECTABLE;
5475 case VTHACK_HSTRING:
5477 if (WinRTSupported())
5479 HSTRING *pStrings = reinterpret_cast<HSTRING *>(*pNativeHome);
5480 for (INT32 i = 0; i < cElements; ++i)
5482 if (pStrings[i] != NULL)
5484 WindowsDeleteString(pStrings[i]);
5491 case VTHACK_NONBLITTABLERECORD:
5493 SIZE_T cbArray = GetArraySize(cElements);
5494 BYTE *pNativeCurrent = reinterpret_cast<BYTE *>(*pNativeHome);
5495 BYTE *pNativeEnd = pNativeCurrent + cbArray;
5497 while (pNativeCurrent < pNativeEnd)
5499 LayoutDestroyNative(pNativeCurrent, m_pElementMT);
5500 pNativeCurrent += m_pElementMT->GetNativeSize();
5505 case VTHACK_INSPECTABLE:
5507 IInspectable **pIPs = reinterpret_cast<IInspectable **>(*pNativeHome);
5508 for (INT32 i = 0; i < cElements; ++i)
5510 if (pIPs[i] != NULL)
5512 SafeRelease(pIPs[i]);
5519 UNREACHABLE_MSG("Unexpected hidden-length array element VT");
5522 #endif //CROSSGEN_COMPILE
5523 #endif // FEATURE_COMINTEROP
5525 void ILReferenceCustomMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
5530 PRECONDITION(-1 == m_dwMngdMarshalerLocalNum);
5535 // allocate space for marshaler
5538 m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
5540 pslILEmit->EmitLDC(sizeof(MngdRefCustomMarshaler));
5541 pslILEmit->EmitLOCALLOC();
5542 pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
5544 pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum); // arg to CreateMarshaler
5547 // call CreateCustomMarshalerHelper
5550 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(m_pargs->rcm.m_pMD));
5551 pslILEmit->EmitCALL(METHOD__METHOD_HANDLE__GETVALUEINTERNAL, 1, 1);
5553 pslILEmit->EmitLDC(m_pargs->rcm.m_paramToken);
5555 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(TypeHandle::FromPtr(m_pargs->rcm.m_hndManagedType)));
5556 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
5558 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CREATE_CUSTOM_MARSHALER_HELPER, 3, 1); // arg to CreateMarshaler
5561 // call MngdRefCustomMarshaler::CreateMarshaler
5564 pslILEmit->EmitCALL(METHOD__MNGD_REF_CUSTOM_MARSHALER__CREATE_MARSHALER, 2, 0);
5568 #ifndef CROSSGEN_COMPILE
5570 FCIMPL2(void, MngdRefCustomMarshaler::CreateMarshaler, MngdRefCustomMarshaler* pThis, void* pCMHelper)
5574 pThis->m_pCMHelper = (CustomMarshalerHelper*)pCMHelper;
5579 FCIMPL3(void, MngdRefCustomMarshaler::ConvertContentsToNative, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5584 PRECONDITION(CheckPointer(pManagedHome));
5588 HELPER_METHOD_FRAME_BEGIN_0();
5590 *pNativeHome = pThis->m_pCMHelper->InvokeMarshalManagedToNativeMeth(*pManagedHome);
5592 HELPER_METHOD_FRAME_END();
5597 FCIMPL3(void, MngdRefCustomMarshaler::ConvertContentsToManaged, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5602 PRECONDITION(CheckPointer(pManagedHome));
5606 HELPER_METHOD_FRAME_BEGIN_0();
5608 SetObjectReference(pManagedHome, pThis->m_pCMHelper->InvokeMarshalNativeToManagedMeth(*pNativeHome), GetAppDomain());
5610 HELPER_METHOD_FRAME_END();
5614 FCIMPL3(void, MngdRefCustomMarshaler::ClearNative, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5618 HELPER_METHOD_FRAME_BEGIN_0();
5628 pThis->m_pCMHelper->InvokeCleanUpNativeMeth(*pNativeHome);
5630 HELPER_METHOD_FRAME_END();
5634 FCIMPL3(void, MngdRefCustomMarshaler::ClearManaged, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5639 PRECONDITION(CheckPointer(pManagedHome));
5643 HELPER_METHOD_FRAME_BEGIN_0();
5645 pThis->m_pCMHelper->InvokeCleanUpManagedMeth(*pManagedHome);
5647 HELPER_METHOD_FRAME_END();
5651 #endif // CROSSGEN_COMPILE
5654 #ifdef FEATURE_COMINTEROP
5656 ///////////////////////////////////////////////////////////////////////////////////////////////////
5657 // ILUriMarshaler implementation
5658 ///////////////////////////////////////////////////////////////////////////////////////////////////
5660 LocalDesc ILUriMarshaler::GetNativeType()
5662 LIMITED_METHOD_CONTRACT;
5663 return LocalDesc(ELEMENT_TYPE_I);
5666 LocalDesc ILUriMarshaler::GetManagedType()
5668 STANDARD_VM_CONTRACT;;
5669 BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
5670 TypeHandle hndUriType = pDomain->GetMarshalingData()->GetUriMarshalingInfo()->GetSystemUriType();
5672 return LocalDesc(hndUriType); // System.Uri
5675 bool ILUriMarshaler::NeedsClearNative()
5677 LIMITED_METHOD_CONTRACT;
5681 // Note that this method expects the CLR Uri on top of the evaluation stack and leaves the WinRT Uri there.
5683 void ILUriMarshaler::EmitConvertCLRUriToWinRTUri(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5685 STANDARD_VM_CONTRACT;
5687 UriMarshalingInfo* marshalingInfo = pDomain->GetMarshalingData()->GetUriMarshalingInfo();
5689 ILCodeLabel *pNotNullLabel = pslILEmit->NewCodeLabel();
5690 ILCodeLabel *pDoneLabel = pslILEmit->NewCodeLabel();
5692 pslILEmit->EmitDUP();
5693 pslILEmit->EmitBRTRUE(pNotNullLabel);
5695 pslILEmit->EmitPOP();
5696 pslILEmit->EmitLoadNullPtr();
5697 pslILEmit->EmitBR(pDoneLabel);
5699 pslILEmit->EmitLabel(pNotNullLabel);
5701 // System.Uri.get_OriginalString()
5702 MethodDesc* pSystemUriOriginalStringMD = marshalingInfo->GetSystemUriOriginalStringMD();
5703 pslILEmit->EmitCALL(pslILEmit->GetToken(pSystemUriOriginalStringMD), 1, 1);
5705 pslILEmit->EmitCALL(METHOD__URIMARSHALER__CREATE_NATIVE_URI_INSTANCE, 1, 1);
5707 pslILEmit->EmitLabel(pDoneLabel);
5710 void ILUriMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
5712 STANDARD_VM_CONTRACT;
5714 EmitLoadManagedValue(pslILEmit);
5715 EmitConvertCLRUriToWinRTUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5716 EmitStoreNativeValue(pslILEmit);
5719 // Note that this method expects the WinRT Uri on top of the evaluation stack and leaves the CLR Uri there.
5721 void ILUriMarshaler::EmitConvertWinRTUriToCLRUri(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5723 STANDARD_VM_CONTRACT;
5725 MethodDesc* pSystemUriCtorMD = pDomain->GetMarshalingData()->GetUriMarshalingInfo()->GetSystemUriCtorMD();
5727 ILCodeLabel *pNotNullLabel = pslILEmit->NewCodeLabel();
5728 ILCodeLabel *pDoneLabel = pslILEmit->NewCodeLabel();
5730 pslILEmit->EmitDUP();
5731 pslILEmit->EmitBRTRUE(pNotNullLabel);
5733 pslILEmit->EmitPOP();
5734 pslILEmit->EmitLDNULL();
5735 pslILEmit->EmitBR(pDoneLabel);
5737 pslILEmit->EmitLabel(pNotNullLabel);
5739 // string UriMarshaler.GetRawUriFromNative(IntPtr)
5740 pslILEmit->EmitCALL(METHOD__URIMARSHALER__GET_RAWURI_FROM_NATIVE, 1, 1);
5742 // System.Uri..ctor(string)
5743 pslILEmit->EmitNEWOBJ(pslILEmit->GetToken(pSystemUriCtorMD), 1);
5745 pslILEmit->EmitLabel(pDoneLabel);
5748 void ILUriMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5750 STANDARD_VM_CONTRACT;
5752 EmitLoadNativeValue(pslILEmit);
5753 EmitConvertWinRTUriToCLRUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5754 EmitStoreManagedValue(pslILEmit);
5757 void ILUriMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
5759 STANDARD_VM_CONTRACT;
5760 EmitInterfaceClearNative(pslILEmit);
5763 ///////////////////////////////////////////////////////////////////////////////////////////////////
5764 // ILNCCEventArgsMarshaler implementation
5765 ///////////////////////////////////////////////////////////////////////////////////////////////////
5767 LocalDesc ILNCCEventArgsMarshaler::GetNativeType()
5769 LIMITED_METHOD_CONTRACT;
5770 return LocalDesc(ELEMENT_TYPE_I);
5773 LocalDesc ILNCCEventArgsMarshaler::GetManagedType()
5775 STANDARD_VM_CONTRACT;;
5777 BaseDomain *pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
5778 TypeHandle hndNCCEventArgType = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemNCCEventArgsType();
5780 return LocalDesc(hndNCCEventArgType); // System.Collections.Specialized.NotifyCollectionChangedEventArgs
5783 bool ILNCCEventArgsMarshaler::NeedsClearNative()
5785 LIMITED_METHOD_CONTRACT;
5789 // Note that this method expects the CLR NotifyCollectionChangedEventArgs on top of the evaluation stack and
5790 // leaves the WinRT NotifyCollectionChangedEventArgs IP there.
5792 void ILNCCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream *pslILEmit, BaseDomain *pDomain)
5794 STANDARD_VM_CONTRACT;
5796 MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemNCCEventArgsToWinRTNCCEventArgsMD();
5798 // IntPtr System.Runtime.InteropServices.WindowsRuntime.NotifyCollectionChangedEventArgsMarshaler.ConvertToNative(NotifyCollectionChangedEventArgs)
5799 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5802 void ILNCCEventArgsMarshaler::EmitConvertContentsCLRToNative(ILCodeStream *pslILEmit)
5804 STANDARD_VM_CONTRACT;
5806 EmitLoadManagedValue(pslILEmit);
5807 EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5808 EmitStoreNativeValue(pslILEmit);
5811 // Note that this method expects the WinRT NotifyCollectionChangedEventArgs on top of the evaluation stack and
5812 // leaves the CLR NotifyCollectionChangedEventArgs there.
5814 void ILNCCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5816 STANDARD_VM_CONTRACT;
5818 MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetWinRTNCCEventArgsToSystemNCCEventArgsMD();
5820 // NotifyCollectionChangedEventArgs System.Runtime.InteropServices.WindowsRuntime.NotifyCollectionChangedEventArgsMarshaler.ConvertToManaged(IntPtr)
5821 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5824 void ILNCCEventArgsMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5826 STANDARD_VM_CONTRACT;
5828 EmitLoadNativeValue(pslILEmit);
5829 EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5830 EmitStoreManagedValue(pslILEmit);
5833 void ILNCCEventArgsMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
5835 STANDARD_VM_CONTRACT;
5836 EmitInterfaceClearNative(pslILEmit);
5839 ///////////////////////////////////////////////////////////////////////////////////////////////////
5840 // ILPCEventArgsMarshaler implementation
5841 ///////////////////////////////////////////////////////////////////////////////////////////////////
5843 LocalDesc ILPCEventArgsMarshaler::GetNativeType()
5845 LIMITED_METHOD_CONTRACT;
5846 return LocalDesc(ELEMENT_TYPE_I);
5849 LocalDesc ILPCEventArgsMarshaler::GetManagedType()
5851 STANDARD_VM_CONTRACT;;
5853 BaseDomain *pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
5854 TypeHandle hndPCEventArgType = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemPCEventArgsType();
5856 return LocalDesc(hndPCEventArgType); // System.ComponentModel.PropertyChangedEventArgs
5859 bool ILPCEventArgsMarshaler::NeedsClearNative()
5861 LIMITED_METHOD_CONTRACT;
5865 // Note that this method expects the CLR PropertyChangedEventArgs on top of the evaluation stack and
5866 // leaves the WinRT PropertyChangedEventArgs IP there.
5868 void ILPCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream *pslILEmit, BaseDomain *pDomain)
5870 STANDARD_VM_CONTRACT;
5872 MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemPCEventArgsToWinRTPCEventArgsMD();
5874 // IntPtr System.Runtime.InteropServices.WindowsRuntime.PropertyChangedEventArgsMarshaler.ConvertToNative(PropertyChangedEventArgs)
5875 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5878 void ILPCEventArgsMarshaler::EmitConvertContentsCLRToNative(ILCodeStream *pslILEmit)
5880 STANDARD_VM_CONTRACT;
5882 EmitLoadManagedValue(pslILEmit);
5883 EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5884 EmitStoreNativeValue(pslILEmit);
5887 // Note that this method expects the WinRT PropertyChangedEventArgs on top of the evaluation stack and
5888 // leaves the CLR PropertyChangedEventArgs there.
5890 void ILPCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5892 STANDARD_VM_CONTRACT;
5894 MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetWinRTPCEventArgsToSystemPCEventArgsMD();
5896 // PropertyChangedEventArgs System.Runtime.InteropServices.WindowsRuntime.PropertyChangedEventArgsMarshaler.ConvertToManaged(IntPtr)
5897 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5900 void ILPCEventArgsMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5902 STANDARD_VM_CONTRACT;
5904 EmitLoadNativeValue(pslILEmit);
5905 EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5906 EmitStoreManagedValue(pslILEmit);
5909 void ILPCEventArgsMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
5911 STANDARD_VM_CONTRACT;
5912 EmitInterfaceClearNative(pslILEmit);
5915 ///////////////////////////////////////////////////////////////////////////////////////////////////
5916 // ILDateTimeMarshaler implementation
5917 ///////////////////////////////////////////////////////////////////////////////////////////////////
5919 LocalDesc ILDateTimeMarshaler::GetNativeType()
5921 STANDARD_VM_CONTRACT;;
5922 return LocalDesc(MscorlibBinder::GetClass(CLASS__DATETIMENATIVE));
5925 LocalDesc ILDateTimeMarshaler::GetManagedType()
5927 STANDARD_VM_CONTRACT;;
5928 return LocalDesc(MscorlibBinder::GetClass(CLASS__DATE_TIME_OFFSET));
5931 bool ILDateTimeMarshaler::NeedsClearNative()
5933 LIMITED_METHOD_CONTRACT;
5937 void ILDateTimeMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
5942 PRECONDITION(CheckPointer(pslILEmit));
5946 // DateTimeOffsetMarshaler.ConvertManagedToNative(ref managedDTO, out nativeTicks);
5947 EmitLoadManagedHomeAddr(pslILEmit);
5948 EmitLoadNativeHomeAddr(pslILEmit);
5949 pslILEmit->EmitCALL(METHOD__DATETIMEOFFSETMARSHALER__CONVERT_TO_NATIVE, 2, 0);
5952 void ILDateTimeMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5954 STANDARD_VM_CONTRACT;
5956 // DateTimeOffsetMarshaler.ConvertNativeToManaged(out managedLocalDTO, ref nativeTicks);
5957 EmitLoadManagedHomeAddr(pslILEmit);
5958 EmitLoadNativeHomeAddr(pslILEmit);
5959 pslILEmit->EmitCALL(METHOD__DATETIMEOFFSETMARSHALER__CONVERT_TO_MANAGED, 2, 0);
5962 void ILDateTimeMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
5964 STANDARD_VM_CONTRACT;
5966 EmitLoadNativeHomeAddr(pslILEmit);
5967 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__DATETIMENATIVE)));
5970 ///////////////////////////////////////////////////////////////////////////////////////////////////
5971 // ILNullableMarshaler implementation
5972 ///////////////////////////////////////////////////////////////////////////////////////////////////
5974 LocalDesc ILNullableMarshaler::GetNativeType()
5976 LIMITED_METHOD_CONTRACT;
5977 return LocalDesc(ELEMENT_TYPE_I);
5980 LocalDesc ILNullableMarshaler::GetManagedType()
5982 LIMITED_METHOD_CONTRACT;;
5983 return LocalDesc(m_pargs->m_pMT);
5986 bool ILNullableMarshaler::NeedsClearNative()
5988 LIMITED_METHOD_CONTRACT;
5992 void ILNullableMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
5997 PRECONDITION(CheckPointer(pslILEmit));
6001 // pNative = NullableMarshaler<T>.ConvertToNative(ref pManaged);
6002 EmitLoadManagedHomeAddr(pslILEmit);
6004 MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__NULLABLEMARSHALER__CONVERT_TO_NATIVE));
6005 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6007 EmitStoreNativeValue(pslILEmit);
6010 void ILNullableMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
6012 STANDARD_VM_CONTRACT;
6014 // pManaged = NullableMarshaler.ConvertToManaged(pNative);
6015 EmitLoadNativeValue(pslILEmit);
6017 MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__NULLABLEMARSHALER__CONVERT_TO_MANAGED));
6018 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6020 EmitStoreManagedValue(pslILEmit);
6023 void ILNullableMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
6025 STANDARD_VM_CONTRACT;
6026 EmitInterfaceClearNative(pslILEmit);
6029 MethodDesc *ILNullableMarshaler::GetExactMarshalerMethod(MethodDesc *pGenericMD)
6031 STANDARD_VM_CONTRACT;
6033 return MethodDesc::FindOrCreateAssociatedMethodDesc(
6035 pGenericMD->GetMethodTable(),
6036 FALSE, // forceBoxedEntryPoint
6037 m_pargs->m_pMT->GetInstantiation(), // methodInst
6038 FALSE, // allowInstParam
6039 TRUE); // forceRemotableMethod
6042 ///////////////////////////////////////////////////////////////////////////////////////////////////
6043 // ILSystemTypeMarshaler implementation
6044 ///////////////////////////////////////////////////////////////////////////////////////////////////
6046 LocalDesc ILSystemTypeMarshaler::GetNativeType()
6048 STANDARD_VM_CONTRACT;
6050 return LocalDesc(MscorlibBinder::GetClass(CLASS__TYPENAMENATIVE));
6053 LocalDesc ILSystemTypeMarshaler::GetManagedType()
6055 STANDARD_VM_CONTRACT;
6057 return LocalDesc(MscorlibBinder::GetClass(CLASS__TYPE));
6060 bool ILSystemTypeMarshaler::NeedsClearNative()
6062 LIMITED_METHOD_CONTRACT;
6066 void ILSystemTypeMarshaler::EmitConvertContentsCLRToNative(ILCodeStream * pslILEmit)
6068 STANDARD_VM_CONTRACT;
6070 // SystemTypeMarshaler.ConvertToNative(Type, pTypeName);
6071 EmitLoadManagedValue(pslILEmit);
6072 EmitLoadNativeHomeAddr(pslILEmit);
6073 pslILEmit->EmitCALL(METHOD__SYSTEMTYPEMARSHALER__CONVERT_TO_NATIVE, 2, 0);
6076 void ILSystemTypeMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream * pslILEmit)
6078 STANDARD_VM_CONTRACT;
6080 // type = SystemTypeMarshaler.ConvertNativeToManaged(pTypeName, ref Type);
6081 EmitLoadNativeHomeAddr(pslILEmit);
6082 EmitLoadManagedHomeAddr(pslILEmit);
6083 pslILEmit->EmitCALL(METHOD__SYSTEMTYPEMARSHALER__CONVERT_TO_MANAGED, 2, 0);
6087 void ILSystemTypeMarshaler::EmitClearNative(ILCodeStream * pslILEmit)
6089 STANDARD_VM_CONTRACT;
6091 // SystemTypeMarshaler.ClearNative(pTypeName)
6092 EmitLoadNativeHomeAddr(pslILEmit);
6093 pslILEmit->EmitCALL(METHOD__SYSTEMTYPEMARSHALER__CLEAR_NATIVE, 1, 0);
6096 void ILSystemTypeMarshaler::EmitReInitNative(ILCodeStream * pslILEmit)
6098 EmitLoadNativeHomeAddr(pslILEmit);
6099 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__TYPENAMENATIVE)));
6102 ///////////////////////////////////////////////////////////////////////////////////////////////////
6103 // ILHResultExceptionMarshaler implementation
6104 ///////////////////////////////////////////////////////////////////////////////////////////////////
6106 LocalDesc ILHResultExceptionMarshaler::GetNativeType()
6108 LIMITED_METHOD_CONTRACT;
6109 return LocalDesc(ELEMENT_TYPE_I4);
6112 LocalDesc ILHResultExceptionMarshaler::GetManagedType()
6114 LIMITED_METHOD_CONTRACT;
6115 _ASSERTE(m_pargs->m_pMT != NULL);
6116 return LocalDesc(m_pargs->m_pMT);
6119 bool ILHResultExceptionMarshaler::NeedsClearNative()
6121 LIMITED_METHOD_CONTRACT;
6125 void ILHResultExceptionMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
6130 PRECONDITION(CheckPointer(pslILEmit));
6134 // int HResultExceptionMarshaler.ConvertManagedToNative(Exception);
6135 EmitLoadManagedValue(pslILEmit);
6136 pslILEmit->EmitCALL(METHOD__HRESULTEXCEPTIONMARSHALER__CONVERT_TO_NATIVE, 1, 1);
6137 EmitStoreNativeValue(pslILEmit);
6140 void ILHResultExceptionMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
6145 PRECONDITION(CheckPointer(pslILEmit));
6149 // Exception HResultExceptionMarshaler.ConvertNativeToManaged(int hr);
6150 EmitLoadNativeValue(pslILEmit);
6151 pslILEmit->EmitCALL(METHOD__HRESULTEXCEPTIONMARSHALER__CONVERT_TO_MANAGED, 1, 1);
6152 EmitStoreManagedValue(pslILEmit);
6155 ///////////////////////////////////////////////////////////////////////////////////////////////////
6156 // ILKeyValuePairMarshaler implementation
6157 ///////////////////////////////////////////////////////////////////////////////////////////////////
6159 LocalDesc ILKeyValuePairMarshaler::GetNativeType()
6161 LIMITED_METHOD_CONTRACT;
6162 return LocalDesc(ELEMENT_TYPE_I);
6165 LocalDesc ILKeyValuePairMarshaler::GetManagedType()
6167 LIMITED_METHOD_CONTRACT;;
6168 return LocalDesc(m_pargs->m_pMT);
6171 bool ILKeyValuePairMarshaler::NeedsClearNative()
6173 LIMITED_METHOD_CONTRACT;
6177 void ILKeyValuePairMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
6179 STANDARD_VM_CONTRACT;
6181 // Native = KeyValueMarshaler<K, V>.ConvertToNative([In] ref Managed);
6182 EmitLoadManagedHomeAddr(pslILEmit);
6184 MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__KEYVALUEPAIRMARSHALER__CONVERT_TO_NATIVE));
6185 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6187 EmitStoreNativeValue(pslILEmit);
6190 void ILKeyValuePairMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
6192 STANDARD_VM_CONTRACT;
6194 // Managed = KeyValuePairMarshaler<K, V>.ConvertToManaged(Native);
6195 EmitLoadNativeValue(pslILEmit);
6197 MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__KEYVALUEPAIRMARSHALER__CONVERT_TO_MANAGED));
6198 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6200 EmitStoreManagedValue(pslILEmit);
6203 void ILKeyValuePairMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
6205 STANDARD_VM_CONTRACT;
6206 EmitInterfaceClearNative(pslILEmit);
6209 MethodDesc *ILKeyValuePairMarshaler::GetExactMarshalerMethod(MethodDesc *pGenericMD)
6211 STANDARD_VM_CONTRACT;
6213 // KeyValuePairMarshaler methods are generic - find/create the exact method.
6214 return MethodDesc::FindOrCreateAssociatedMethodDesc(
6216 pGenericMD->GetMethodTable(),
6217 FALSE, // forceBoxedEntryPoint
6218 m_pargs->m_pMT->GetInstantiation(), // methodInst
6219 FALSE, // allowInstParam
6220 TRUE); // forceRemotableMethod
6223 #endif // FEATURE_COMINTEROP