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
776 // if (!fConvertSpaceJustCalled)
778 // we don't need to double-check the length because the length
779 // must be smaller than the capacity and the capacity was already
780 // checked by EmitConvertSpaceCLRToNative
782 pslILEmit->EmitDUP();
783 // static void StubHelpers.CheckStringLength(int length)
784 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
787 // stack: StringBuilder length
789 pslILEmit->EmitDUP();
790 pslILEmit->EmitADD();
792 // stack: StringBuilder cb
794 pslILEmit->EmitSTLOC(dwTempNumBytesLocal);
796 // stack: StringBuilder
798 EmitLoadNativeValue(pslILEmit);
799 pslILEmit->EmitLDLOC(dwTempNumBytesLocal);
801 // stack: stringbuilder native_buffer cb
803 // void System.Text.StringBuilder.InternalCopy(IntPtr dest,int len)
804 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__INTERNAL_COPY, 3, 0);
807 // null-terminate the native string
809 EmitLoadNativeValue(pslILEmit);
810 pslILEmit->EmitLDLOC(dwTempNumBytesLocal);
811 pslILEmit->EmitADD();
812 pslILEmit->EmitLDC(0);
813 pslILEmit->EmitSTIND_I2();
815 pslILEmit->EmitLabel(pNullRefLabel);
818 void ILWSTRBufferMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
820 STANDARD_VM_CONTRACT;
822 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
824 EmitLoadNativeValue(pslILEmit);
825 pslILEmit->EmitBRFALSE(pNullRefLabel);
827 if (IsIn(m_dwMarshalFlags) || IsCLRToNative(m_dwMarshalFlags))
829 EmitLoadNativeValue(pslILEmit);
830 // static int System.String.wcslen(char *ptr)
831 pslILEmit->EmitCALL(METHOD__STRING__WCSLEN, 1, 1);
835 // don't touch the native buffer in the native->CLR out-only case
836 pslILEmit->EmitLDC(0);
839 // System.Text.StringBuilder..ctor(int capacity)
840 pslILEmit->EmitNEWOBJ(METHOD__STRING_BUILDER__CTOR_INT, 1);
841 EmitStoreManagedValue(pslILEmit);
843 pslILEmit->EmitLabel(pNullRefLabel);
846 void ILWSTRBufferMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
848 STANDARD_VM_CONTRACT;
850 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
852 EmitLoadNativeValue(pslILEmit);
853 pslILEmit->EmitBRFALSE(pNullRefLabel);
855 EmitLoadManagedValue(pslILEmit);
856 EmitLoadNativeValue(pslILEmit);
858 pslILEmit->EmitDUP();
859 // static int System.String.wcslen(char *ptr)
860 pslILEmit->EmitCALL(METHOD__STRING__WCSLEN, 1, 1);
862 // void System.Text.StringBuilder.ReplaceBuffer(char* newBuffer, int newLength);
863 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__REPLACE_BUFFER_INTERNAL, 3, 0);
864 pslILEmit->EmitLabel(pNullRefLabel);
867 LocalDesc ILCSTRBufferMarshaler::GetManagedType()
869 STANDARD_VM_CONTRACT;
871 return LocalDesc(MscorlibBinder::GetClass(CLASS__STRING_BUILDER));
874 void ILCSTRBufferMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
876 STANDARD_VM_CONTRACT;
878 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
880 pslILEmit->EmitLoadNullPtr();
881 EmitStoreNativeValue(pslILEmit);
883 EmitLoadManagedValue(pslILEmit);
884 pslILEmit->EmitBRFALSE(pNullRefLabel);
886 EmitLoadManagedValue(pslILEmit);
887 // int System.Text.StringBuilder.get_Capacity()
888 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__GET_CAPACITY, 1, 1);
889 pslILEmit->EmitDUP();
891 // static void StubHelpers.CheckStringLength(int length)
892 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
896 pslILEmit->EmitLDSFLD(pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__MARSHAL__SYSTEM_MAX_DBCS_CHAR_SIZE)));
897 pslILEmit->EmitMUL_OVF();
899 // stack: capacity_in_bytes
901 pslILEmit->EmitLDC(1);
902 pslILEmit->EmitADD_OVF();
904 // stack: offset_of_secret_null
906 DWORD dwTmpOffsetOfSecretNull = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
907 pslILEmit->EmitDUP();
908 pslILEmit->EmitSTLOC(dwTmpOffsetOfSecretNull); // make sure the stack is empty for localloc
910 pslILEmit->EmitLDC(3);
911 pslILEmit->EmitADD_OVF();
913 // stack: alloc_size_in_bytes
914 ILCodeLabel *pAllocRejoin = pslILEmit->NewCodeLabel();
915 if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags))
917 ILCodeLabel *pNoOptimize = pslILEmit->NewCodeLabel();
918 m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
921 pslILEmit->EmitLoadNullPtr();
922 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
924 // if (alloc_size_in_bytes > MAX_LOCAL_BUFFER_LENGTH) goto NoOptimize
925 pslILEmit->EmitDUP();
926 pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
927 pslILEmit->EmitCGT_UN();
928 pslILEmit->EmitBRTRUE(pNoOptimize);
930 pslILEmit->EmitLOCALLOC();
931 pslILEmit->EmitDUP();
932 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
933 pslILEmit->EmitBR(pAllocRejoin);
935 pslILEmit->EmitLabel(pNoOptimize);
938 // static IntPtr AllocCoTaskMem(int cb)
939 pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
941 pslILEmit->EmitLabel(pAllocRejoin);
943 // stack: native_addr
945 pslILEmit->EmitDUP();
946 EmitStoreNativeValue(pslILEmit);
948 pslILEmit->EmitLDLOC(dwTmpOffsetOfSecretNull);
950 // stack: native_addr offset_of_secret_null
952 pslILEmit->EmitADD();
954 // stack: addr_of_secret_null0
956 pslILEmit->EmitDUP();
957 pslILEmit->EmitLDC(0);
958 pslILEmit->EmitSTIND_I1();
960 // stack: addr_of_secret_null0
962 pslILEmit->EmitDUP();
963 pslILEmit->EmitLDC(1);
964 pslILEmit->EmitADD();
965 pslILEmit->EmitLDC(0);
966 pslILEmit->EmitSTIND_I1();
968 // stack: addr_of_secret_null0
970 pslILEmit->EmitLDC(2);
971 pslILEmit->EmitADD();
972 pslILEmit->EmitLDC(0);
973 pslILEmit->EmitSTIND_I1();
975 pslILEmit->EmitLabel(pNullRefLabel);
978 void ILCSTRBufferMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
980 STANDARD_VM_CONTRACT;
982 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
983 DWORD dwNumBytesLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
984 DWORD dwSrcLocal = pslILEmit->NewLocal(ELEMENT_TYPE_OBJECT);
986 EmitLoadNativeValue(pslILEmit);
987 pslILEmit->EmitBRFALSE(pNullRefLabel);
989 EmitLoadManagedValue(pslILEmit);
990 // int System.Text.StringBuilder.get_Length()
991 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__GET_LENGTH, 1, 1);
992 // static void StubHelpers.CheckStringLength(int length)
993 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
995 EmitLoadManagedValue(pslILEmit);
996 // String System.Text.StringBuilder.ToString()
997 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__TO_STRING, 1, 1);
998 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetBestFitMapping());
999 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar());
1000 pslILEmit->EmitLDLOCA(dwNumBytesLocalNum);
1002 // static byte[] DoAnsiConversion(string str, bool fBestFit, bool fThrowOnUnmappableChar, out int cbLength)
1003 pslILEmit->EmitCALL(METHOD__ANSICHARMARSHALER__DO_ANSI_CONVERSION, 4, 1);
1004 pslILEmit->EmitSTLOC(dwSrcLocal);
1005 EmitLoadNativeValue(pslILEmit); // pDest
1006 pslILEmit->EmitLDC(0); // destIndex
1007 pslILEmit->EmitLDLOC(dwSrcLocal); // src[]
1008 pslILEmit->EmitLDC(0); // srcIndex
1009 pslILEmit->EmitLDLOC(dwNumBytesLocalNum); // len
1011 // static void Memcpy(byte* pDest, int destIndex, byte[] src, int srcIndex, int len)
1012 pslILEmit->EmitCALL(METHOD__BUFFER__MEMCPY_PTRBYTE_ARRBYTE, 5, 0);
1014 // null terminate the string
1015 EmitLoadNativeValue(pslILEmit);
1016 pslILEmit->EmitLDLOC(dwNumBytesLocalNum);
1017 pslILEmit->EmitADD();
1018 pslILEmit->EmitLDC(0);
1019 pslILEmit->EmitSTIND_I1();
1021 pslILEmit->EmitLabel(pNullRefLabel);
1024 void ILCSTRBufferMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
1026 STANDARD_VM_CONTRACT;
1028 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
1030 EmitLoadNativeValue(pslILEmit);
1031 pslILEmit->EmitBRFALSE(pNullRefLabel);
1033 if (IsIn(m_dwMarshalFlags) || IsCLRToNative(m_dwMarshalFlags))
1035 EmitLoadNativeValue(pslILEmit);
1036 // static int System.String.strlen(byte* ptr)
1037 pslILEmit->EmitCALL(METHOD__STRING__STRLEN, 1, 1);
1041 // don't touch the native buffer in the native->CLR out-only case
1042 pslILEmit->EmitLDC(0);
1045 // System.Text.StringBuilder..ctor(int capacity)
1046 pslILEmit->EmitNEWOBJ(METHOD__STRING_BUILDER__CTOR_INT, 1);
1047 EmitStoreManagedValue(pslILEmit);
1049 pslILEmit->EmitLabel(pNullRefLabel);
1052 void ILCSTRBufferMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1054 STANDARD_VM_CONTRACT;
1056 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
1058 EmitLoadNativeValue(pslILEmit);
1059 pslILEmit->EmitBRFALSE(pNullRefLabel);
1061 EmitLoadManagedValue(pslILEmit);
1062 EmitLoadNativeValue(pslILEmit);
1064 pslILEmit->EmitDUP();
1065 // static int System.String.strlen(byte* ptr)
1066 pslILEmit->EmitCALL(METHOD__STRING__STRLEN, 1, 1);
1068 // void System.Text.StringBuilder.ReplaceBuffer(sbyte* newBuffer, int newLength);
1069 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__REPLACE_BUFFER_ANSI_INTERNAL, 3, 0);
1071 pslILEmit->EmitLabel(pNullRefLabel);
1076 LocalDesc ILValueClassMarshaler::GetNativeType()
1078 STANDARD_VM_CONTRACT;
1080 return LocalDesc(TypeHandle(m_pargs->m_pMT).MakeNativeValueType());
1083 LocalDesc ILValueClassMarshaler::GetManagedType()
1085 LIMITED_METHOD_CONTRACT;
1087 return LocalDesc(m_pargs->m_pMT);
1090 void ILValueClassMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
1092 STANDARD_VM_CONTRACT;
1094 EmitLoadNativeHomeAddr(pslILEmit);
1095 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(TypeHandle(m_pargs->m_pMT).MakeNativeValueType()));
1098 bool ILValueClassMarshaler::NeedsClearNative()
1103 void ILValueClassMarshaler::EmitClearNative(ILCodeStream * pslILEmit)
1105 STANDARD_VM_CONTRACT;
1107 mdToken managedVCToken = pslILEmit->GetToken(m_pargs->m_pMT);
1109 EmitLoadNativeHomeAddr(pslILEmit);
1110 pslILEmit->EmitLDTOKEN(managedVCToken); // pMT
1111 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1112 pslILEmit->EmitCALL(METHOD__VALUECLASSMARSHALER__CLEAR_NATIVE, 2, 0);
1116 void ILValueClassMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1118 STANDARD_VM_CONTRACT;
1120 mdToken managedVCToken = pslILEmit->GetToken(m_pargs->m_pMT);
1122 EmitLoadNativeHomeAddr(pslILEmit); // dst
1123 EmitLoadManagedHomeAddr(pslILEmit); // src
1124 pslILEmit->EmitLDTOKEN(managedVCToken); // pMT
1125 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1); // Convert RTH to IntPtr
1127 m_pslNDirect->LoadCleanupWorkList(pslILEmit);
1128 pslILEmit->EmitCALL(METHOD__VALUECLASSMARSHALER__CONVERT_TO_NATIVE, 4, 0); // void ConvertToNative(IntPtr dst, IntPtr src, IntPtr pMT, ref CleanupWorkListElement pCleanupWorkList)
1131 void ILValueClassMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1133 STANDARD_VM_CONTRACT;
1135 mdToken managedVCToken = pslILEmit->GetToken(m_pargs->m_pMT);
1137 EmitLoadManagedHomeAddr(pslILEmit); // dst
1138 EmitLoadNativeHomeAddr(pslILEmit); // src
1139 pslILEmit->EmitLDTOKEN(managedVCToken); // pMT
1140 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1141 pslILEmit->EmitCALL(METHOD__VALUECLASSMARSHALER__CONVERT_TO_MANAGED, 3, 0); // void ConvertToManaged(IntPtr dst, IntPtr src, IntPtr pMT)
1145 #ifdef FEATURE_COMINTEROP
1146 LocalDesc ILObjectMarshaler::GetNativeType()
1148 STANDARD_VM_CONTRACT;
1150 return LocalDesc(TypeHandle(MscorlibBinder::GetClass(CLASS__NATIVEVARIANT)));
1153 LocalDesc ILObjectMarshaler::GetManagedType()
1155 LIMITED_METHOD_CONTRACT;
1157 return LocalDesc(ELEMENT_TYPE_OBJECT);
1160 void ILObjectMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1162 STANDARD_VM_CONTRACT;
1164 if (!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
1166 // Keep the VARIANT as it is - the stubhelper will do a VT_BYREF check on it.
1170 // V_VT(pDest) = VT_EMPTY
1171 EmitReInitNative(pslILEmit);
1174 EmitLoadManagedValue(pslILEmit); // load src
1175 EmitLoadNativeHomeAddr(pslILEmit); // load dst
1176 pslILEmit->EmitCALL(METHOD__OBJECTMARSHALER__CONVERT_TO_NATIVE, 2, 0); // void ConvertToNative(object objSrc, IntPtr pDstVariant)
1179 void ILObjectMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1181 STANDARD_VM_CONTRACT;
1183 EmitLoadNativeHomeAddr(pslILEmit);
1184 pslILEmit->EmitCALL(METHOD__OBJECTMARSHALER__CONVERT_TO_MANAGED, 1, 1); // object ConvertToManaged(IntPtr pSrcVariant);
1185 EmitStoreManagedValue(pslILEmit);
1188 bool ILObjectMarshaler::NeedsClearNative()
1190 LIMITED_METHOD_CONTRACT;
1194 void ILObjectMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1196 STANDARD_VM_CONTRACT;
1198 if (!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
1200 // We don't want to clear variants passed from native by-ref here as we
1201 // want to be able to detect the VT_BYREF case during backpropagation.
1203 // @TODO: We shouldn't be skipping the call if pslILEmit is ILStubLinker::kExceptionCleanup
1204 // because we always want to do real cleanup in this stream.
1208 EmitLoadNativeHomeAddr(pslILEmit);
1209 pslILEmit->EmitCALL(METHOD__OBJECTMARSHALER__CLEAR_NATIVE, 1, 0);
1213 void ILObjectMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
1218 CONSISTENCY_CHECK(offsetof(VARIANT, vt) == 0);
1222 if (!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
1224 // We don't want to clear variants passed from native by-ref here as we
1225 // want to be able to detect the VT_BYREF case during backpropagation.
1229 EmitLoadNativeHomeAddr(pslILEmit);
1230 pslILEmit->EmitLDC(VT_EMPTY);
1231 pslILEmit->EmitSTIND_I2();
1234 #endif // FEATURE_COMINTEROP
1236 LocalDesc ILDateMarshaler::GetNativeType()
1238 LIMITED_METHOD_CONTRACT;
1240 return LocalDesc(ELEMENT_TYPE_R8);
1243 LocalDesc ILDateMarshaler::GetManagedType()
1245 STANDARD_VM_CONTRACT;
1247 return LocalDesc(MscorlibBinder::GetClass(CLASS__DATE_TIME));
1250 void ILDateMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1252 STANDARD_VM_CONTRACT;
1254 EmitLoadManagedValue(pslILEmit);
1255 // double ConvertToNative(INT64 managedDate)
1256 pslILEmit->EmitCALL(METHOD__DATEMARSHALER__CONVERT_TO_NATIVE, 1, 1);
1257 EmitStoreNativeValue(pslILEmit);
1260 void ILDateMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1262 STANDARD_VM_CONTRACT;
1264 // will call DateTime constructor on managed home
1265 EmitLoadManagedHomeAddr(pslILEmit);
1267 EmitLoadNativeValue(pslILEmit);
1268 // long ConvertToNative(double nativeData)
1269 pslILEmit->EmitCALL(METHOD__DATEMARSHALER__CONVERT_TO_MANAGED, 1, 1);
1271 pslILEmit->EmitCALL(METHOD__DATE_TIME__LONG_CTOR, 2, 0);
1274 void ILDateMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
1276 STANDARD_VM_CONTRACT;
1278 // ldc.i4.0, conv.r8 is shorter than ldc.r8 0.0
1279 pslILEmit->EmitLDC(0);
1280 pslILEmit->EmitCONV_R8();
1281 EmitStoreNativeValue(pslILEmit);
1284 LocalDesc ILCurrencyMarshaler::GetNativeType()
1286 STANDARD_VM_CONTRACT;
1288 return LocalDesc(TypeHandle(MscorlibBinder::GetClass(CLASS__CURRENCY)));
1291 LocalDesc ILCurrencyMarshaler::GetManagedType()
1293 STANDARD_VM_CONTRACT;
1295 return LocalDesc(TypeHandle(MscorlibBinder::GetClass(CLASS__DECIMAL)));
1299 void ILCurrencyMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
1301 STANDARD_VM_CONTRACT;
1303 EmitLoadNativeHomeAddr(pslILEmit);
1304 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(TypeHandle(MscorlibBinder::GetClass(CLASS__CURRENCY))));
1307 void ILCurrencyMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1309 STANDARD_VM_CONTRACT;
1311 EmitLoadNativeHomeAddr(pslILEmit);
1312 EmitLoadManagedValue(pslILEmit);
1314 pslILEmit->EmitCALL(METHOD__CURRENCY__DECIMAL_CTOR, 2, 0);
1317 void ILCurrencyMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1319 STANDARD_VM_CONTRACT;
1321 EmitLoadManagedHomeAddr(pslILEmit);
1322 EmitLoadNativeValue(pslILEmit);
1324 pslILEmit->EmitCALL(METHOD__DECIMAL__CURRENCY_CTOR, 2, 0);
1328 #ifdef FEATURE_COMINTEROP
1329 LocalDesc ILInterfaceMarshaler::GetNativeType()
1331 LIMITED_METHOD_CONTRACT;
1333 return LocalDesc(ELEMENT_TYPE_I);
1336 LocalDesc ILInterfaceMarshaler::GetManagedType()
1338 LIMITED_METHOD_CONTRACT;
1340 return LocalDesc(ELEMENT_TYPE_OBJECT);
1343 void ILInterfaceMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1345 STANDARD_VM_CONTRACT;
1347 ItfMarshalInfo itfInfo;
1348 m_pargs->m_pMarshalInfo->GetItfMarshalInfo(&itfInfo);
1350 EmitLoadManagedValue(pslILEmit);
1352 if (itfInfo.thNativeItf.GetMethodTable())
1354 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(itfInfo.thNativeItf.GetMethodTable()));
1355 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1359 pslILEmit->EmitLoadNullPtr();
1362 if (itfInfo.thClass.GetMethodTable())
1364 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(itfInfo.thClass.GetMethodTable()));
1365 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1369 pslILEmit->EmitLoadNullPtr();
1371 pslILEmit->EmitLDC(itfInfo.dwFlags);
1373 // static IntPtr ConvertToNative(object objSrc, IntPtr itfMT, IntPtr classMT, int flags);
1374 pslILEmit->EmitCALL(METHOD__INTERFACEMARSHALER__CONVERT_TO_NATIVE, 4, 1);
1376 EmitStoreNativeValue(pslILEmit);
1378 if (IsCLRToNative(m_dwMarshalFlags) &&
1379 m_pargs->m_pMarshalInfo->IsWinRTScenario())
1381 // If we are calling from CLR into WinRT and we are passing an interface to WinRT, we need to
1382 // keep the object alive across unmanaged call because Jupiter might need to add this
1383 // RCW into their live tree and whatever CCWs referenced by this RCW could get collected
1384 // before the call to native, for example:
1386 // Button btn = new Button();
1387 // btn.OnClick += ...
1388 // m_grid.Children.Add(btn)
1390 // In this case, btn could be collected and takes the delegate CCW with it, before Children.add
1391 // native method is called, and as a result Jupiter will add the neutered CCW into the tree
1393 // The fix is to extend the lifetime of the argument across the call to native by doing a GC.KeepAlive
1394 // keep the delegate ref alive across the call-out to native
1395 EmitLoadManagedValue(m_pcsUnmarshal);
1396 m_pcsUnmarshal->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
1400 void ILInterfaceMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1402 STANDARD_VM_CONTRACT;
1404 ItfMarshalInfo itfInfo;
1405 m_pargs->m_pMarshalInfo->GetItfMarshalInfo(&itfInfo);
1407 // the helper may assign NULL to the home (see below)
1408 EmitLoadNativeHomeAddr(pslILEmit);
1410 if (IsCLRToNative(m_dwMarshalFlags) && m_pargs->m_pMarshalInfo->IsWinRTScenario())
1412 // We are converting an interface pointer to object in a CLR->native stub which means
1413 // that the interface pointer has been AddRef'ed for us by the callee. If we end up
1414 // wrapping it with a new RCW, we can omit another AddRef/Release pair. Note that if
1415 // a new RCW is created the native home will be zeroed out by the helper so the call
1416 // to InterfaceMarshaler__ClearNative will become a no-op.
1418 // Note that we are only doing this for WinRT scenarios to reduce the risk of this change
1419 itfInfo.dwFlags |= ItfMarshalInfo::ITF_MARSHAL_SUPPRESS_ADDREF;
1422 if (itfInfo.thItf.GetMethodTable())
1424 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(itfInfo.thItf.GetMethodTable()));
1425 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1429 pslILEmit->EmitLoadNullPtr();
1432 if (itfInfo.thClass.GetMethodTable())
1434 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(itfInfo.thClass.GetMethodTable()));
1435 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1439 pslILEmit->EmitLoadNullPtr();
1441 pslILEmit->EmitLDC(itfInfo.dwFlags);
1443 // static object ConvertToManaged(IntPtr pUnk, IntPtr itfMT, IntPtr classMT, int flags);
1444 pslILEmit->EmitCALL(METHOD__INTERFACEMARSHALER__CONVERT_TO_MANAGED, 4, 1);
1446 EmitStoreManagedValue(pslILEmit);
1449 bool ILInterfaceMarshaler::NeedsClearNative()
1451 LIMITED_METHOD_CONTRACT;
1455 void ILMarshaler::EmitInterfaceClearNative(ILCodeStream* pslILEmit)
1457 STANDARD_VM_CONTRACT;
1459 ILCodeLabel *pSkipClearNativeLabel = pslILEmit->NewCodeLabel();
1460 EmitLoadNativeValue(pslILEmit);
1461 pslILEmit->EmitBRFALSE(pSkipClearNativeLabel);
1462 EmitLoadNativeValue(pslILEmit);
1463 // static void ClearNative(IntPtr pUnk);
1464 pslILEmit->EmitCALL(METHOD__INTERFACEMARSHALER__CLEAR_NATIVE, 1, 0);
1465 pslILEmit->EmitLabel(pSkipClearNativeLabel);
1468 void ILInterfaceMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1470 STANDARD_VM_CONTRACT;
1471 EmitInterfaceClearNative(pslILEmit);
1473 #endif // FEATURE_COMINTEROP
1476 LocalDesc ILAnsiCharMarshaler::GetNativeType()
1478 LIMITED_METHOD_CONTRACT;
1480 return LocalDesc(ELEMENT_TYPE_U1);
1483 LocalDesc ILAnsiCharMarshaler::GetManagedType()
1485 LIMITED_METHOD_CONTRACT;
1487 return LocalDesc(ELEMENT_TYPE_CHAR);
1490 void ILAnsiCharMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1492 STANDARD_VM_CONTRACT;
1494 EmitLoadManagedValue(pslILEmit);
1495 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetBestFitMapping());
1496 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar());
1497 pslILEmit->EmitCALL(METHOD__ANSICHARMARSHALER__CONVERT_TO_NATIVE, 3, 1);
1498 EmitStoreNativeValue(pslILEmit);
1501 void ILAnsiCharMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1503 STANDARD_VM_CONTRACT;
1505 EmitLoadNativeValue(pslILEmit);
1506 pslILEmit->EmitCALL(METHOD__ANSICHARMARSHALER__CONVERT_TO_MANAGED, 1, 1);
1507 EmitStoreManagedValue(pslILEmit);
1510 #ifdef FEATURE_COMINTEROP
1511 LocalDesc ILOleColorMarshaler::GetNativeType()
1513 LIMITED_METHOD_CONTRACT;
1515 return LocalDesc(ELEMENT_TYPE_I4);
1518 LocalDesc ILOleColorMarshaler::GetManagedType()
1520 STANDARD_VM_CONTRACT;
1522 BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
1523 TypeHandle hndColorType = pDomain->GetMarshalingData()->GetOleColorMarshalingInfo()->GetColorType();
1528 return LocalDesc(hndColorType); // System.Drawing.Color
1531 void ILOleColorMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1533 STANDARD_VM_CONTRACT;
1535 BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
1536 MethodDesc* pConvertMD = pDomain->GetMarshalingData()->GetOleColorMarshalingInfo()->GetSystemColorToOleColorMD();
1538 EmitLoadManagedValue(pslILEmit);
1539 // int System.Drawing.ColorTranslator.ToOle(System.Drawing.Color c)
1540 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
1541 EmitStoreNativeValue(pslILEmit);
1544 void ILOleColorMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1546 STANDARD_VM_CONTRACT;
1548 BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
1549 MethodDesc* pConvertMD = pDomain->GetMarshalingData()->GetOleColorMarshalingInfo()->GetOleColorToSystemColorMD();
1551 EmitLoadNativeValue(pslILEmit);
1552 // System.Drawing.Color System.Drawing.ColorTranslator.FromOle(int oleColor)
1553 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
1554 EmitStoreManagedValue(pslILEmit);
1557 bool ILVBByValStrWMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
1559 LIMITED_METHOD_CONTRACT;
1560 if (IsCLRToNative(dwMarshalFlags) && IsByref(dwMarshalFlags) && IsIn(dwMarshalFlags) && IsOut(dwMarshalFlags))
1565 *pErrorResID = IDS_EE_BADMARSHAL_VBBYVALSTRRESTRICTION;
1569 bool ILVBByValStrWMarshaler::SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
1571 LIMITED_METHOD_CONTRACT;
1572 *pErrorResID = IDS_EE_BADMARSHAL_VBBYVALSTRRESTRICTION;
1576 LocalDesc ILVBByValStrWMarshaler::GetNativeType()
1578 LIMITED_METHOD_CONTRACT;
1580 return LocalDesc(ELEMENT_TYPE_I); // BSTR
1583 LocalDesc ILVBByValStrWMarshaler::GetManagedType()
1585 LIMITED_METHOD_CONTRACT;
1587 return LocalDesc(ELEMENT_TYPE_STRING);
1590 bool ILVBByValStrWMarshaler::IsNativePassedByRef()
1592 LIMITED_METHOD_CONTRACT;
1596 void ILVBByValStrWMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1598 STANDARD_VM_CONTRACT;
1600 ILCodeStream *pcsSetup = m_pslNDirect->GetSetupCodeStream();
1601 m_dwLocalBuffer = pcsSetup->NewLocal(ELEMENT_TYPE_I);
1602 pcsSetup->EmitLoadNullPtr();
1603 pcsSetup->EmitSTLOC(m_dwLocalBuffer);
1606 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
1607 m_dwCCHLocal = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
1608 DWORD dwNumBytesLocal = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
1610 pslILEmit->EmitLoadNullPtr();
1611 EmitStoreNativeValue(pslILEmit);
1613 EmitLoadManagedValue(pslILEmit);
1614 pslILEmit->EmitBRFALSE(pNullRefLabel);
1616 EmitLoadManagedValue(pslILEmit);
1617 pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
1618 pslILEmit->EmitDUP();
1619 pslILEmit->EmitSTLOC(m_dwCCHLocal);
1623 pslILEmit->EmitLDC(1);
1624 pslILEmit->EmitADD();
1625 pslILEmit->EmitDUP();
1626 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
1627 pslILEmit->EmitDUP();
1628 pslILEmit->EmitADD(); // (length+1) * sizeof(WCHAR)
1629 pslILEmit->EmitDUP();
1630 pslILEmit->EmitSTLOC(dwNumBytesLocal); // len <- doesn't include size of the DWORD preceeding the string
1631 pslILEmit->EmitLDC(sizeof(DWORD));
1632 pslILEmit->EmitADD(); // (length+1) * sizeof(WCHAR) + sizeof(DWORD)
1636 ILCodeLabel* pNoOptimizeLabel = pslILEmit->NewCodeLabel();
1637 ILCodeLabel* pAllocRejoinLabel = pslILEmit->NewCodeLabel();
1638 pslILEmit->EmitDUP();
1639 pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
1640 pslILEmit->EmitCGT_UN();
1641 pslILEmit->EmitBRTRUE(pNoOptimizeLabel);
1643 pslILEmit->EmitLOCALLOC();
1644 pslILEmit->EmitBR(pAllocRejoinLabel);
1646 pslILEmit->EmitLabel(pNoOptimizeLabel);
1647 pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
1648 pslILEmit->EmitDUP();
1649 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
1651 pslILEmit->EmitLabel(pAllocRejoinLabel);
1652 pslILEmit->EmitDUP();
1653 pslILEmit->EmitLDLOC(m_dwCCHLocal);
1654 pslILEmit->EmitSTIND_I4();
1655 pslILEmit->EmitLDC(sizeof(DWORD));
1656 pslILEmit->EmitADD();
1657 EmitStoreNativeValue(pslILEmit);
1661 EmitLoadManagedValue(pslILEmit); // src
1662 EmitLoadNativeValue(pslILEmit); // dest
1663 pslILEmit->EmitLDLOC(dwNumBytesLocal); // len
1665 // static void System.String.InternalCopy(String src, IntPtr dest,int len)
1666 pslILEmit->EmitCALL(METHOD__STRING__INTERNAL_COPY, 3, 0);
1668 pslILEmit->EmitLabel(pNullRefLabel);
1671 void ILVBByValStrWMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1673 STANDARD_VM_CONTRACT;
1675 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
1676 EmitLoadNativeValue(pslILEmit);
1677 pslILEmit->EmitBRFALSE(pNullRefLabel);
1679 pslILEmit->EmitLDNULL(); // this
1680 EmitLoadNativeValue(pslILEmit); // ptr
1681 pslILEmit->EmitLDC(0); // startIndex
1682 pslILEmit->EmitLDLOC(m_dwCCHLocal); // length
1684 // String CtorCharPtrStartLength(char *ptr, int startIndex, int length)
1685 // TODO Phase5: Why do we call this weirdo?
1686 pslILEmit->EmitCALL(METHOD__STRING__CTORF_CHARPTR_START_LEN, 4, 1);
1688 EmitStoreManagedValue(pslILEmit);
1689 pslILEmit->EmitLabel(pNullRefLabel);
1693 bool ILVBByValStrWMarshaler::NeedsClearNative()
1695 LIMITED_METHOD_CONTRACT;
1699 void ILVBByValStrWMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1701 STANDARD_VM_CONTRACT;
1703 ILCodeLabel* pExitLabel = pslILEmit->NewCodeLabel();
1704 pslILEmit->EmitLDLOC(m_dwLocalBuffer);
1705 pslILEmit->EmitBRFALSE(pExitLabel);
1706 pslILEmit->EmitLDLOC(m_dwLocalBuffer);
1707 pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
1708 pslILEmit->EmitLabel(pExitLabel);
1712 bool ILVBByValStrMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
1714 if (IsCLRToNative(dwMarshalFlags) && IsByref(dwMarshalFlags) && IsIn(dwMarshalFlags) && IsOut(dwMarshalFlags))
1719 *pErrorResID = IDS_EE_BADMARSHAL_VBBYVALSTRRESTRICTION;
1723 bool ILVBByValStrMarshaler::SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
1725 *pErrorResID = IDS_EE_BADMARSHAL_VBBYVALSTRRESTRICTION;
1729 LocalDesc ILVBByValStrMarshaler::GetNativeType()
1731 LIMITED_METHOD_CONTRACT;
1733 return LocalDesc(ELEMENT_TYPE_I); // BSTR
1736 LocalDesc ILVBByValStrMarshaler::GetManagedType()
1738 LIMITED_METHOD_CONTRACT;
1740 return LocalDesc(ELEMENT_TYPE_STRING);
1743 bool ILVBByValStrMarshaler::IsNativePassedByRef()
1745 LIMITED_METHOD_CONTRACT;
1749 void ILVBByValStrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1751 STANDARD_VM_CONTRACT;
1753 m_dwCCHLocal = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
1755 EmitLoadManagedValue(pslILEmit);
1756 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetBestFitMapping());
1757 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar());
1758 pslILEmit->EmitLDLOCA(m_dwCCHLocal);
1760 // static IntPtr ConvertToNative(string strManaged, bool fBestFit, bool fThrowOnUnmappableChar, ref int cch)
1761 pslILEmit->EmitCALL(METHOD__VBBYVALSTRMARSHALER__CONVERT_TO_NATIVE, 4, 1);
1763 EmitStoreNativeValue(pslILEmit);
1766 void ILVBByValStrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1768 STANDARD_VM_CONTRACT;
1770 EmitLoadNativeValue(pslILEmit); // pNative
1771 pslILEmit->EmitLDLOC(m_dwCCHLocal); // cch
1773 // static string ConvertToManaged(IntPtr pNative, int cch)
1774 pslILEmit->EmitCALL(METHOD__VBBYVALSTRMARSHALER__CONVERT_TO_MANAGED, 2, 1);
1776 EmitStoreManagedValue(pslILEmit);
1779 bool ILVBByValStrMarshaler::NeedsClearNative()
1781 LIMITED_METHOD_CONTRACT;
1785 void ILVBByValStrMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1787 STANDARD_VM_CONTRACT;
1789 EmitLoadNativeValue(pslILEmit); // pNative
1791 // static void ClearNative(IntPtr pNative);
1792 pslILEmit->EmitCALL(METHOD__VBBYVALSTRMARSHALER__CLEAR_NATIVE, 1, 0);
1794 #endif // FEATURE_COMINTEROP
1796 LocalDesc ILBSTRMarshaler::GetManagedType()
1798 LIMITED_METHOD_CONTRACT;
1800 return LocalDesc(ELEMENT_TYPE_STRING);
1803 void ILBSTRMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1805 STANDARD_VM_CONTRACT;
1807 ILCodeLabel* pRejoinLabel = pslILEmit->NewCodeLabel();
1809 EmitLoadManagedValue(pslILEmit);
1811 if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags))
1813 ILCodeLabel *pNoOptimizeLabel = pslILEmit->NewCodeLabel();
1814 m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
1817 pslILEmit->EmitLoadNullPtr();
1818 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
1820 pslILEmit->EmitDUP();
1821 pslILEmit->EmitBRFALSE(pNoOptimizeLabel);
1824 pslILEmit->EmitDUP();
1825 pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
1827 // if (length > (MAX_LOCAL_BUFFER_LENGTH - 6) / 2) goto NoOptimize
1828 pslILEmit->EmitLDC((MAX_LOCAL_BUFFER_LENGTH - 6) / 2); // number of Unicode characters - terminator - length dword
1829 pslILEmit->EmitCGT_UN();
1830 pslILEmit->EmitBRTRUE(pNoOptimizeLabel);
1832 // LocalBuffer = localloc[(String.Length * 2) + 6]
1833 pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
1834 pslILEmit->EmitLDC(2);
1835 pslILEmit->EmitMUL();
1836 pslILEmit->EmitLDC(7); // + length (4B) + terminator (2B) + possible trailing byte (1B)
1837 pslILEmit->EmitADD();
1840 // Save the buffer length
1841 DWORD dwTmpAllocSize = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
1842 pslILEmit->EmitDUP();
1843 pslILEmit->EmitSTLOC(dwTmpAllocSize);
1846 pslILEmit->EmitLOCALLOC();
1849 // Pass buffer length in the first DWORD so the helper is able to assert that
1850 // the buffer is large enough.
1851 pslILEmit->EmitDUP();
1852 pslILEmit->EmitLDLOC(dwTmpAllocSize);
1853 pslILEmit->EmitSTIND_I4();
1856 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
1858 // load string and LocalBuffer
1859 EmitLoadManagedValue(pslILEmit);
1860 pslILEmit->EmitLDLOC(m_dwLocalBuffer);
1861 pslILEmit->EmitBR(pRejoinLabel);
1863 pslILEmit->EmitLabel(pNoOptimizeLabel);
1865 pslILEmit->EmitLoadNullPtr();
1867 pslILEmit->EmitLabel(pRejoinLabel);
1868 pslILEmit->EmitCALL(METHOD__BSTRMARSHALER__CONVERT_TO_NATIVE, 2, 1);
1869 EmitStoreNativeValue(pslILEmit);
1872 void ILBSTRMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1874 STANDARD_VM_CONTRACT;
1876 EmitLoadNativeValue(pslILEmit);
1877 pslILEmit->EmitCALL(METHOD__BSTRMARSHALER__CONVERT_TO_MANAGED, 1, 1);
1878 EmitStoreManagedValue(pslILEmit);
1881 LocalDesc ILAnsiBSTRMarshaler::GetNativeType()
1883 LIMITED_METHOD_CONTRACT;
1885 return LocalDesc(ELEMENT_TYPE_I); // BSTR
1888 LocalDesc ILAnsiBSTRMarshaler::GetManagedType()
1890 LIMITED_METHOD_CONTRACT;
1892 return LocalDesc(ELEMENT_TYPE_STRING);
1895 void ILAnsiBSTRMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1897 STANDARD_VM_CONTRACT;
1899 DWORD dwAnsiMarshalFlags =
1900 (m_pargs->m_pMarshalInfo->GetBestFitMapping() & 0xFF) |
1901 (m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar() << 8);
1903 pslILEmit->EmitLDC(dwAnsiMarshalFlags);
1904 EmitLoadManagedValue(pslILEmit);
1905 pslILEmit->EmitCALL(METHOD__ANSIBSTRMARSHALER__CONVERT_TO_NATIVE, 2, 1);
1906 EmitStoreNativeValue(pslILEmit);
1909 void ILAnsiBSTRMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1911 STANDARD_VM_CONTRACT;
1913 EmitLoadNativeValue(pslILEmit);
1914 pslILEmit->EmitCALL(METHOD__ANSIBSTRMARSHALER__CONVERT_TO_MANAGED, 1, 1);
1915 EmitStoreManagedValue(pslILEmit);
1918 bool ILAnsiBSTRMarshaler::NeedsClearNative()
1920 LIMITED_METHOD_CONTRACT;
1924 void ILAnsiBSTRMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1926 STANDARD_VM_CONTRACT;
1928 EmitLoadNativeValue(pslILEmit);
1929 pslILEmit->EmitCALL(METHOD__ANSIBSTRMARSHALER__CLEAR_NATIVE, 1, 0);
1932 #ifdef FEATURE_COMINTEROP
1934 LocalDesc ILHSTRINGMarshaler::GetNativeType()
1936 LIMITED_METHOD_CONTRACT;
1937 return LocalDesc(ELEMENT_TYPE_I); // HSTRING
1940 LocalDesc ILHSTRINGMarshaler::GetManagedType()
1942 LIMITED_METHOD_CONTRACT;
1943 return LocalDesc(ELEMENT_TYPE_STRING);
1946 bool ILHSTRINGMarshaler::NeedsClearNative()
1948 LIMITED_METHOD_CONTRACT;
1952 void ILHSTRINGMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1957 PRECONDITION(CheckPointer(pslILEmit));
1961 // If we're only going into native code, then we can optimize and create a HSTRING reference over
1962 // the pinned System.String. However, if the parameter will remain in native code as an out
1963 // value, then we need to create a real HSTRING.
1964 if (!IsOut(m_dwMarshalFlags) && !IsRetval(m_dwMarshalFlags))
1966 EmitConvertCLRToHSTRINGReference(pslILEmit);
1970 EmitConvertCLRToHSTRING(pslILEmit);
1974 void ILHSTRINGMarshaler::EmitConvertCLRToHSTRINGReference(ILCodeStream* pslILEmit)
1979 PRECONDITION(CheckPointer(pslILEmit));
1980 PRECONDITION(!IsOut(m_dwMarshalFlags));
1981 PRECONDITION(!IsRetval(m_dwMarshalFlags));
1986 // The general strategy for fast path marshaling a short lived System.String -> HSTRING is:
1987 // 1. Pin the System.String
1988 // 2. Create an HSTRING Reference over the pinned string
1989 // 3. Pass that reference to native code
1992 // Local to hold the HSTRING_HEADER of the HSTRING reference
1993 MethodTable *pHStringHeaderMT = MscorlibBinder::GetClass(CLASS__HSTRING_HEADER_MANAGED);
1994 DWORD dwHStringHeaderLocal = pslILEmit->NewLocal(pHStringHeaderMT);
1996 // Local to hold the pinned input string
1997 LocalDesc pinnedStringDesc = GetManagedType();
1998 pinnedStringDesc.MakePinned();
1999 DWORD dwPinnedStringLocal = pslILEmit->NewLocal(pinnedStringDesc);
2001 // pinnedString = managed
2002 EmitLoadManagedValue(pslILEmit);
2003 pslILEmit->EmitSTLOC(dwPinnedStringLocal);
2005 // hstring = HSTRINGMarshaler.ConvertManagedToNativeReference(pinnedString, out HStringHeader)
2006 pslILEmit->EmitLDLOC(dwPinnedStringLocal);
2007 pslILEmit->EmitLDLOCA(dwHStringHeaderLocal);
2008 pslILEmit->EmitCALL(METHOD__HSTRINGMARSHALER__CONVERT_TO_NATIVE_REFERENCE, 2, 1);
2010 if (g_pConfig->InteropLogArguments())
2012 m_pslNDirect->EmitLogNativeArgument(pslILEmit, dwPinnedStringLocal);
2015 EmitStoreNativeValue(pslILEmit);
2018 void ILHSTRINGMarshaler::EmitConvertCLRToHSTRING(ILCodeStream* pslILEmit)
2023 PRECONDITION(CheckPointer(pslILEmit));
2027 // hstring = HSTRINGMarshaler.ConvertManagedToNative(managed);
2028 EmitLoadManagedValue(pslILEmit);
2029 pslILEmit->EmitCALL(METHOD__HSTRINGMARSHALER__CONVERT_TO_NATIVE, 1, 1);
2030 EmitStoreNativeValue(pslILEmit);
2033 void ILHSTRINGMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2035 STANDARD_VM_CONTRACT;
2038 // To convert an HSTRING to a CLR String:
2039 // 1. WindowsGetStringRawBuffer() to get the raw string data
2040 // 2. WindowsGetStringLen() to get the string length
2041 // 3. Construct a System.String from these parameters
2042 // 4. Release the HSTRING
2045 // string = HSTRINGMarshaler.ConvertNativeToManaged(native);
2046 EmitLoadNativeValue(pslILEmit);
2047 pslILEmit->EmitCALL(METHOD__HSTRINGMARSHALER__CONVERT_TO_MANAGED, 1, 1);
2048 EmitStoreManagedValue(pslILEmit);
2052 void ILHSTRINGMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
2054 STANDARD_VM_CONTRACT;
2056 // HStringMarshaler.ClearNative(hstring)
2057 EmitLoadNativeValue(pslILEmit);
2058 pslILEmit->EmitCALL(METHOD__HSTRINGMARSHALER__CLEAR_NATIVE, 1, 0);
2061 #endif // FEATURE_COMINTEROP
2063 LocalDesc ILCUTF8Marshaler::GetManagedType()
2065 LIMITED_METHOD_CONTRACT;
2067 return LocalDesc(ELEMENT_TYPE_STRING);
2070 void ILCUTF8Marshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2072 STANDARD_VM_CONTRACT;
2074 DWORD dwUtf8MarshalFlags =
2075 (m_pargs->m_pMarshalInfo->GetBestFitMapping() & 0xFF) |
2076 (m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar() << 8);
2078 bool bPassByValueInOnly = IsIn(m_dwMarshalFlags) && !IsOut(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags);
2079 if (bPassByValueInOnly)
2081 DWORD dwBufSize = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
2082 m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
2085 pslILEmit->EmitLoadNullPtr();
2086 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
2088 ILCodeLabel* pNoOptimize = pslILEmit->NewCodeLabel();
2090 // if == NULL, goto NoOptimize
2091 EmitLoadManagedValue(pslILEmit);
2092 pslILEmit->EmitBRFALSE(pNoOptimize);
2094 // (String.Length + 1)
2095 // Characters would be # of characters + 1 in case left over high surrogate is ?
2096 EmitLoadManagedValue(pslILEmit);
2097 pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
2098 pslILEmit->EmitLDC(1);
2099 pslILEmit->EmitADD();
2101 // Max 3 bytes per char.
2102 // (String.Length + 1) * 3
2103 pslILEmit->EmitLDC(3);
2104 pslILEmit->EmitMUL();
2106 // +1 for the 0x0 that we put in.
2107 // ((String.Length + 1) * 3) + 1
2108 pslILEmit->EmitLDC(1);
2109 pslILEmit->EmitADD();
2111 // BufSize = ( (String.Length+1) * 3) + 1
2112 pslILEmit->EmitSTLOC(dwBufSize);
2114 // if (MAX_LOCAL_BUFFER_LENGTH < BufSize ) goto NoOptimize
2115 pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
2116 pslILEmit->EmitLDLOC(dwBufSize);
2117 pslILEmit->EmitCLT();
2118 pslILEmit->EmitBRTRUE(pNoOptimize);
2120 // LocalBuffer = localloc(BufSize);
2121 pslILEmit->EmitLDLOC(dwBufSize);
2122 pslILEmit->EmitLOCALLOC();
2123 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
2126 pslILEmit->EmitLabel(pNoOptimize);
2129 // UTF8Marshaler.ConvertToNative(dwUtf8MarshalFlags,pManaged, pLocalBuffer)
2130 pslILEmit->EmitLDC(dwUtf8MarshalFlags);
2131 EmitLoadManagedValue(pslILEmit);
2133 if (m_dwLocalBuffer != LOCAL_NUM_UNUSED)
2135 pslILEmit->EmitLDLOC(m_dwLocalBuffer);
2139 pslILEmit->EmitLoadNullPtr();
2142 pslILEmit->EmitCALL(METHOD__CUTF8MARSHALER__CONVERT_TO_NATIVE, 3, 1);
2144 EmitStoreNativeValue(pslILEmit);
2147 void ILCUTF8Marshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2149 STANDARD_VM_CONTRACT;
2151 EmitLoadNativeValue(pslILEmit);
2152 pslILEmit->EmitCALL(METHOD__CUTF8MARSHALER__CONVERT_TO_MANAGED, 1, 1);
2153 EmitStoreManagedValue(pslILEmit);
2157 LocalDesc ILCSTRMarshaler::GetManagedType()
2159 LIMITED_METHOD_CONTRACT;
2161 return LocalDesc(ELEMENT_TYPE_STRING);
2164 void ILCSTRMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2166 STANDARD_VM_CONTRACT;
2168 DWORD dwAnsiMarshalFlags =
2169 (m_pargs->m_pMarshalInfo->GetBestFitMapping() & 0xFF) |
2170 (m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar() << 8);
2172 bool bPassByValueInOnly = IsIn(m_dwMarshalFlags) && !IsOut(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags);
2173 if (bPassByValueInOnly)
2175 DWORD dwBufSize = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
2176 m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
2179 pslILEmit->EmitLoadNullPtr();
2180 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
2182 ILCodeLabel* pNoOptimize = pslILEmit->NewCodeLabel();
2184 // if == NULL, goto NoOptimize
2185 EmitLoadManagedValue(pslILEmit);
2186 pslILEmit->EmitBRFALSE(pNoOptimize);
2188 // String.Length + 2
2189 EmitLoadManagedValue(pslILEmit);
2190 pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
2191 pslILEmit->EmitLDC(2);
2192 pslILEmit->EmitADD();
2194 // (String.Length + 2) * GetMaxDBCSCharByteSize()
2195 pslILEmit->EmitLDSFLD(pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__MARSHAL__SYSTEM_MAX_DBCS_CHAR_SIZE)));
2196 pslILEmit->EmitMUL_OVF();
2198 // BufSize = (String.Length + 2) * GetMaxDBCSCharByteSize()
2199 pslILEmit->EmitSTLOC(dwBufSize);
2201 // if (MAX_LOCAL_BUFFER_LENGTH < BufSize ) goto NoOptimize
2202 pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
2203 pslILEmit->EmitLDLOC(dwBufSize);
2204 pslILEmit->EmitCLT();
2205 pslILEmit->EmitBRTRUE(pNoOptimize);
2207 // LocalBuffer = localloc(BufSize);
2208 pslILEmit->EmitLDLOC(dwBufSize);
2209 pslILEmit->EmitLOCALLOC();
2210 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
2213 pslILEmit->EmitLabel(pNoOptimize);
2216 // CSTRMarshaler.ConvertToNative pManaged, dwAnsiMarshalFlags, pLocalBuffer
2217 pslILEmit->EmitLDC(dwAnsiMarshalFlags);
2218 EmitLoadManagedValue(pslILEmit);
2220 if (m_dwLocalBuffer != LOCAL_NUM_UNUSED)
2222 pslILEmit->EmitLDLOC(m_dwLocalBuffer);
2226 pslILEmit->EmitLoadNullPtr();
2229 pslILEmit->EmitCALL(METHOD__CSTRMARSHALER__CONVERT_TO_NATIVE, 3, 1);
2231 EmitStoreNativeValue(pslILEmit);
2234 void ILCSTRMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2236 STANDARD_VM_CONTRACT;
2238 EmitLoadNativeValue(pslILEmit);
2239 pslILEmit->EmitCALL(METHOD__CSTRMARSHALER__CONVERT_TO_MANAGED, 1, 1);
2240 EmitStoreManagedValue(pslILEmit);
2243 LocalDesc ILLayoutClassPtrMarshalerBase::GetNativeType()
2245 LIMITED_METHOD_CONTRACT;
2247 return LocalDesc(ELEMENT_TYPE_I); // ptr to struct
2250 LocalDesc ILLayoutClassPtrMarshalerBase::GetManagedType()
2252 LIMITED_METHOD_CONTRACT;
2254 return LocalDesc(m_pargs->m_pMT);
2257 void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
2259 STANDARD_VM_CONTRACT;
2261 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2262 UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2264 pslILEmit->EmitLoadNullPtr();
2265 EmitStoreNativeValue(pslILEmit);
2267 EmitLoadManagedValue(pslILEmit);
2268 pslILEmit->EmitBRFALSE(pNullRefLabel);
2269 pslILEmit->EmitLDC(uNativeSize);
2270 pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
2271 pslILEmit->EmitDUP(); // for INITBLK
2272 EmitStoreNativeValue(pslILEmit);
2274 // initialize local block we just allocated
2275 pslILEmit->EmitLDC(0);
2276 pslILEmit->EmitLDC(uNativeSize);
2277 pslILEmit->EmitINITBLK();
2279 pslILEmit->EmitLabel(pNullRefLabel);
2282 void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceCLRToNativeTemp(ILCodeStream* pslILEmit)
2284 STANDARD_VM_CONTRACT;
2286 UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2287 if (uNativeSize > s_cbStackAllocThreshold)
2289 EmitConvertSpaceCLRToNative(pslILEmit);
2293 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2295 pslILEmit->EmitLoadNullPtr();
2296 EmitStoreNativeValue(pslILEmit);
2298 EmitLoadManagedValue(pslILEmit);
2299 pslILEmit->EmitBRFALSE(pNullRefLabel);
2301 pslILEmit->EmitLDC(uNativeSize);
2302 pslILEmit->EmitLOCALLOC();
2303 pslILEmit->EmitDUP(); // for INITBLK
2304 EmitStoreNativeValue(pslILEmit);
2306 // initialize local block we just allocated
2307 pslILEmit->EmitLDC(0);
2308 pslILEmit->EmitLDC(uNativeSize);
2309 pslILEmit->EmitINITBLK();
2311 pslILEmit->EmitLabel(pNullRefLabel);
2315 void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
2317 STANDARD_VM_CONTRACT;
2319 EmitConvertSpaceCLRToNativeTemp(pslILEmit);
2320 EmitConvertContentsCLRToNative(pslILEmit);
2323 void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
2325 STANDARD_VM_CONTRACT;
2327 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2329 EmitLoadNativeValue(pslILEmit);
2330 pslILEmit->EmitBRFALSE(pNullRefLabel);
2332 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(m_pargs->m_pMT));
2333 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
2334 // static object AllocateInternal(IntPtr typeHandle);
2335 pslILEmit->EmitCALL(METHOD__STUBHELPERS__ALLOCATE_INTERNAL, 1, 1);
2336 EmitStoreManagedValue(pslILEmit);
2337 pslILEmit->EmitLabel(pNullRefLabel);
2341 bool ILLayoutClassPtrMarshalerBase::NeedsClearNative()
2343 LIMITED_METHOD_CONTRACT;
2347 void ILLayoutClassPtrMarshalerBase::EmitClearNative(ILCodeStream* pslILEmit)
2349 STANDARD_VM_CONTRACT;
2351 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2353 EmitLoadNativeValue(pslILEmit);
2354 pslILEmit->EmitBRFALSE(pNullRefLabel);
2356 EmitClearNativeContents(pslILEmit);
2357 EmitLoadNativeValue(pslILEmit);
2358 pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
2360 pslILEmit->EmitLabel(pNullRefLabel);
2363 void ILLayoutClassPtrMarshalerBase::EmitClearNativeTemp(ILCodeStream* pslILEmit)
2365 STANDARD_VM_CONTRACT;
2367 UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2368 if (uNativeSize > s_cbStackAllocThreshold)
2370 EmitClearNative(pslILEmit);
2374 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2375 EmitLoadNativeValue(pslILEmit);
2376 pslILEmit->EmitBRFALSE(pNullRefLabel);
2378 EmitClearNativeContents(pslILEmit);
2380 pslILEmit->EmitLabel(pNullRefLabel);
2386 void ILLayoutClassPtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2388 STANDARD_VM_CONTRACT;
2390 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2391 UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2393 EmitLoadNativeValue(pslILEmit);
2394 pslILEmit->EmitBRFALSE(pNullRefLabel);
2396 EmitLoadNativeValue(pslILEmit);
2397 pslILEmit->EmitLDC(0);
2398 pslILEmit->EmitLDC(uNativeSize);
2399 pslILEmit->EmitINITBLK();
2401 EmitLoadManagedValue(pslILEmit);
2402 EmitLoadNativeValue(pslILEmit);
2404 m_pslNDirect->LoadCleanupWorkList(pslILEmit);
2406 // static void FmtClassUpdateNativeInternal(object obj, byte* pNative, IntPtr pOptionalCleanupList);
2408 pslILEmit->EmitCALL(METHOD__STUBHELPERS__FMT_CLASS_UPDATE_NATIVE_INTERNAL, 3, 0);
2409 pslILEmit->EmitLabel(pNullRefLabel);
2412 void ILLayoutClassPtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2414 STANDARD_VM_CONTRACT;
2416 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2418 EmitLoadManagedValue(pslILEmit);
2419 pslILEmit->EmitBRFALSE(pNullRefLabel);
2421 EmitLoadManagedValue(pslILEmit);
2422 EmitLoadNativeValue(pslILEmit);
2424 // static void FmtClassUpdateCLRInternal(object obj, byte* pNative);
2425 pslILEmit->EmitCALL(METHOD__STUBHELPERS__FMT_CLASS_UPDATE_CLR_INTERNAL, 2, 0);
2426 pslILEmit->EmitLabel(pNullRefLabel);
2429 void ILLayoutClassPtrMarshaler::EmitClearNativeContents(ILCodeStream * pslILEmit)
2431 STANDARD_VM_CONTRACT;
2433 int tokManagedType = pslILEmit->GetToken(m_pargs->m_pMT);
2435 EmitLoadNativeValue(pslILEmit);
2436 pslILEmit->EmitLDTOKEN(tokManagedType);
2437 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
2439 // static void LayoutDestroyNativeInternal(byte* pNative, IntPtr pMT);
2440 pslILEmit->EmitCALL(METHOD__STUBHELPERS__LAYOUT_DESTROY_NATIVE_INTERNAL, 2, 0);
2444 void ILBlittablePtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2446 STANDARD_VM_CONTRACT;
2448 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2449 UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2450 int fieldDef = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__RAW_DATA__DATA));
2452 EmitLoadNativeValue(pslILEmit);
2453 pslILEmit->EmitBRFALSE(pNullRefLabel);
2455 EmitLoadNativeValue(pslILEmit); // dest
2457 EmitLoadManagedValue(pslILEmit);
2458 pslILEmit->EmitLDFLDA(fieldDef); // src
2460 pslILEmit->EmitLDC(uNativeSize); // size
2462 pslILEmit->EmitCPBLK();
2463 pslILEmit->EmitLabel(pNullRefLabel);
2466 void ILBlittablePtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2468 STANDARD_VM_CONTRACT;
2470 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2471 UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2472 int fieldDef = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__RAW_DATA__DATA));
2474 EmitLoadManagedValue(pslILEmit);
2475 pslILEmit->EmitBRFALSE(pNullRefLabel);
2477 EmitLoadManagedValue(pslILEmit);
2478 pslILEmit->EmitLDFLDA(fieldDef); // dest
2480 EmitLoadNativeValue(pslILEmit); // src
2482 pslILEmit->EmitLDC(uNativeSize); // size
2484 pslILEmit->EmitCPBLK();
2485 pslILEmit->EmitLabel(pNullRefLabel);
2488 void ILBlittablePtrMarshaler::EmitMarshalArgumentCLRToNative()
2493 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
2497 EmitSetupSigAndDefaultHomesCLRToNative();
2503 ILCodeLabel* pSkipAddLabel = m_pcsMarshal->NewCodeLabel();
2504 LocalDesc managedTypePinned = GetManagedType();
2505 managedTypePinned.MakePinned();
2506 DWORD dwPinnedLocal = m_pcsMarshal->NewLocal(managedTypePinned);
2508 EmitLoadManagedValue(m_pcsMarshal);
2510 m_pcsMarshal->EmitSTLOC(dwPinnedLocal);
2511 m_pcsMarshal->EmitLDLOC(dwPinnedLocal);
2512 m_pcsMarshal->EmitCONV_U();
2513 m_pcsMarshal->EmitDUP();
2514 m_pcsMarshal->EmitBRFALSE(pSkipAddLabel);
2515 m_pcsMarshal->EmitLDC(Object::GetOffsetOfFirstField());
2516 m_pcsMarshal->EmitADD();
2517 m_pcsMarshal->EmitLabel(pSkipAddLabel);
2519 if (g_pConfig->InteropLogArguments())
2521 m_pslNDirect->EmitLogNativeArgument(m_pcsMarshal, dwPinnedLocal);
2524 EmitStoreNativeValue(m_pcsMarshal);
2530 MarshalerOverrideStatus ILHandleRefMarshaler::ArgumentOverride(NDirectStubLinker* psl,
2534 BOOL fManagedToNative,
2535 OverrideProcArgs* pargs,
2538 UINT nativeStackOffset)
2548 ILCodeStream* pcsMarshal = psl->GetMarshalCodeStream();
2549 ILCodeStream* pcsDispatch = psl->GetDispatchCodeStream();
2550 ILCodeStream* pcsUnmarshal = psl->GetUnmarshalCodeStream();
2552 if (fManagedToNative && !byref)
2554 pcsMarshal->SetStubTargetArgType(ELEMENT_TYPE_I);
2557 // HandleRefs are valuetypes, so pinning is not needed.
2558 // The argument address is on the stack and will not move.
2559 mdFieldDef handleField = pcsDispatch->GetToken(MscorlibBinder::GetField(FIELD__HANDLE_REF__HANDLE));
2560 pcsDispatch->EmitLDARG(argidx);
2561 pcsDispatch->EmitLDFLD(handleField);
2563 mdFieldDef wrapperField = pcsUnmarshal->GetToken(MscorlibBinder::GetField(FIELD__HANDLE_REF__WRAPPER));
2564 pcsUnmarshal->EmitLDARG(argidx);
2565 pcsUnmarshal->EmitLDFLD(wrapperField);
2566 pcsUnmarshal->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
2572 *pResID = IDS_EE_BADMARSHAL_HANDLEREFRESTRICTION;
2577 MarshalerOverrideStatus ILHandleRefMarshaler::ReturnOverride(NDirectStubLinker* psl,
2578 BOOL fManagedToNative,
2580 OverrideProcArgs* pargs,
2591 *pResID = IDS_EE_BADMARSHAL_HANDLEREFRESTRICTION;
2595 LocalDesc ILSafeHandleMarshaler::GetManagedType()
2597 STANDARD_VM_CONTRACT;
2599 return LocalDesc(MscorlibBinder::GetClass(CLASS__SAFE_HANDLE));
2602 LocalDesc ILSafeHandleMarshaler::GetNativeType()
2604 LIMITED_METHOD_CONTRACT;
2606 return LocalDesc(ELEMENT_TYPE_I);
2609 bool ILSafeHandleMarshaler::NeedsClearNative()
2611 LIMITED_METHOD_CONTRACT;
2615 void ILSafeHandleMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
2617 STANDARD_VM_CONTRACT;
2619 _ASSERTE(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
2621 // call StubHelpers::SafeHandleRelease
2622 EmitLoadManagedValue(pslILEmit);
2623 pslILEmit->EmitCALL(METHOD__STUBHELPERS__SAFE_HANDLE_RELEASE, 1, 0);
2626 void ILSafeHandleMarshaler::EmitMarshalArgumentCLRToNative()
2631 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
2635 EmitSetupSigAndDefaultHomesCLRToNative();
2637 // by-value CLR-to-native SafeHandle is always passed in-only regardless of [In], [Out]
2638 // marshal and cleanup communicate via an extra local and are both emitted in this method
2640 // bool <dwHandleAddRefedLocalNum> = false
2641 ILCodeStream *pcsSetup = m_pslNDirect->GetSetupCodeStream();
2642 DWORD dwHandleAddRefedLocalNum = pcsSetup->NewLocal(ELEMENT_TYPE_BOOLEAN);
2644 pcsSetup->EmitLDC(0);
2645 pcsSetup->EmitSTLOC(dwHandleAddRefedLocalNum);
2647 // <nativeHandle> = StubHelpers::SafeHandleAddRef(<managedSH>, ref <dwHandleAddRefedLocalNum>)
2648 EmitLoadManagedValue(m_pcsMarshal);
2649 m_pcsMarshal->EmitLDLOCA(dwHandleAddRefedLocalNum);
2650 m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__SAFE_HANDLE_ADD_REF, 2, 1);
2651 EmitStoreNativeValue(m_pcsMarshal);
2654 // if (<dwHandleAddRefedLocalNum>) StubHelpers.SafeHandleRelease(<managedSH>)
2655 ILCodeStream *pcsCleanup = m_pslNDirect->GetCleanupCodeStream();
2656 ILCodeLabel *pSkipClearNativeLabel = pcsCleanup->NewCodeLabel();
2658 pcsCleanup->EmitLDLOC(dwHandleAddRefedLocalNum);
2659 pcsCleanup->EmitBRFALSE(pSkipClearNativeLabel);
2661 EmitClearNativeTemp(pcsCleanup);
2662 m_pslNDirect->SetCleanupNeeded();
2664 pcsCleanup->EmitLabel(pSkipClearNativeLabel);
2667 MarshalerOverrideStatus ILSafeHandleMarshaler::ArgumentOverride(NDirectStubLinker* psl,
2671 BOOL fManagedToNative,
2672 OverrideProcArgs* pargs,
2675 UINT nativeStackOffset)
2685 ILCodeStream* pslIL = psl->GetMarshalCodeStream();
2686 ILCodeStream* pslILDispatch = psl->GetDispatchCodeStream();
2688 if (fManagedToNative)
2692 pslIL->SetStubTargetArgType(ELEMENT_TYPE_I);
2694 // The specific SafeHandle subtype we're dealing with here.
2695 MethodTable *pHandleType = pargs->m_pMT;
2697 // Out SafeHandle parameters must not be abstract.
2698 if (fout && pHandleType->IsAbstract())
2700 *pResID = IDS_EE_BADMARSHAL_ABSTRACTOUTSAFEHANDLE;
2704 // We rely on the SafeHandle having a default constructor.
2705 if (!pHandleType->HasDefaultConstructor())
2707 MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
2708 COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
2711 // Grab the token for the native handle field embedded inside the SafeHandle. We'll be using it to direct access the
2712 // native handle later.
2713 mdToken tkNativeHandleField = pslIL->GetToken(MscorlibBinder::GetField(FIELD__SAFE_HANDLE__HANDLE));
2715 // The high level logic (note that the parameter may be in, out or both):
2716 // 1) If this is an input parameter we need to AddRef the SafeHandle and schedule a Release cleanup item.
2717 // 2) If this is an output parameter we need to preallocate a SafeHandle to wrap the new native handle value. We
2718 // must allocate this before the native call to avoid a failure point when we already have a native resource
2719 // allocated. We must allocate a new SafeHandle even if we have one on input since both input and output native
2720 // handles need to be tracked and released by a SafeHandle.
2721 // 3) Initialize a local IntPtr that will be passed to the native call. If we have an input SafeHandle the value
2722 // comes from there otherwise we get it from the new SafeHandle (which is guaranteed to be initialized to an
2723 // invalid handle value).
2724 // 4) If this is a out parameter we also store the original handle value (that we just computed above) in a local
2726 // 5) After the native call, if this is an output parameter and the handle value we passed to native differs from
2727 // the local copy we made then the new handle value is written into the output SafeHandle and that SafeHandle
2728 // is propagated back to the caller.
2731 DWORD dwInputHandleLocal = 0; // The input safe handle (in only)
2732 DWORD dwOutputHandleLocal = 0; // The output safe handle (out only)
2733 DWORD dwOldNativeHandleLocal = 0; // The original native handle value for comparison (out only)
2734 DWORD dwNativeHandleLocal; // The input (and possibly updated) native handle value
2738 LocalDesc locInputHandle(pHandleType);
2739 dwInputHandleLocal = pslIL->NewLocal(locInputHandle);
2743 LocalDesc locOutputHandle(pHandleType);
2744 dwOutputHandleLocal = pslIL->NewLocal(locOutputHandle);
2746 dwOldNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
2749 dwNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
2751 // Call StubHelpers.AddToCleanupList to atomically AddRef incoming SafeHandle and schedule a cleanup work item to
2752 // perform Release after the call. The helper also returns the native handle value to us so take the opportunity
2753 // to store this in the NativeHandle local we've allocated.
2756 pslIL->EmitLDARG(argidx);
2757 pslIL->EmitLDIND_REF();
2759 pslIL->EmitSTLOC(dwInputHandleLocal);
2761 // Release the original input SafeHandle after the call.
2762 psl->LoadCleanupWorkList(pslIL);
2763 pslIL->EmitLDLOC(dwInputHandleLocal);
2765 // This is realiable, i.e. the cleanup will happen if and only if the SH was actually AddRef'ed.
2766 pslIL->EmitCALL(METHOD__STUBHELPERS__ADD_TO_CLEANUP_LIST_SAFEHANDLE, 2, 1);
2768 pslIL->EmitSTLOC(dwNativeHandleLocal);
2772 // For output parameters we need to allocate a new SafeHandle to hold the result.
2775 MethodDesc* pMDCtor = pHandleType->GetDefaultConstructor();
2776 pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
2777 pslIL->EmitSTLOC(dwOutputHandleLocal);
2779 // If we didn't provide an input handle then we initialize the NativeHandle local with the (initially invalid)
2780 // handle field set up inside the output handle by the constructor.
2783 pslIL->EmitLDLOC(dwOutputHandleLocal);
2784 pslIL->EmitLDFLD(tkNativeHandleField);
2785 pslIL->EmitSTLOC(dwNativeHandleLocal);
2788 // Remember the handle value we start out with so we know whether to back propagate after the native call.
2789 pslIL->EmitLDLOC(dwNativeHandleLocal);
2790 pslIL->EmitSTLOC(dwOldNativeHandleLocal);
2793 // Leave the address of the native handle local as the argument to the native method.
2794 pslILDispatch->EmitLDLOCA(dwNativeHandleLocal);
2796 // On the output side we only backpropagate the native handle into the output SafeHandle and the output SafeHandle
2797 // to the caller if the native handle actually changed (otherwise we can end up with two SafeHandles wrapping the
2798 // same native handle, which is bad).
2801 // We will use cleanup stream to avoid leaking the handle on thread abort.
2802 psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx);
2804 psl->SetCleanupNeeded();
2805 ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
2807 ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
2809 psl->EmitCheckForArgCleanup(pslCleanupIL,
2810 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx,
2811 NDirectStubLinker::BranchIfNotMarshaled,
2814 // If this is an [in, out] handle check if the native handles have changed. If not we're finished.
2817 pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
2818 pslCleanupIL->EmitLDLOC(dwOldNativeHandleLocal);
2819 pslCleanupIL->EmitCEQ();
2820 pslCleanupIL->EmitBRTRUE(pDoneLabel);
2823 // Propagate the native handle into the output SafeHandle.
2824 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
2825 pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
2826 pslCleanupIL->EmitSTFLD(tkNativeHandleField);
2828 // Propagate the output SafeHandle back to the caller.
2829 pslCleanupIL->EmitLDARG(argidx);
2830 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
2831 pslCleanupIL->EmitSTIND_REF();
2833 pslCleanupIL->EmitLabel(pDoneLabel);
2838 // Avoid using the cleanup list in this common case for perf reasons (cleanup list is
2839 // unmanaged and destroying it means excessive managed<->native transitions; in addition,
2840 // as X86 IL stubs do not use interop frames, there's nothing protecting the cleanup list
2841 // and the SafeHandle references must be GC handles which does not help perf either).
2843 // This code path generates calls to StubHelpers.SafeHandleAddRef and SafeHandleRelease.
2844 // NICE: Could SafeHandle.DangerousAddRef and DangerousRelease be implemented in managed?
2845 return HANDLEASNORMAL;
2852 *pResID = IDS_EE_BADMARSHAL_SAFEHANDLENATIVETOCOM;
2857 //---------------------------------------------------------------------------------------
2859 MarshalerOverrideStatus
2860 ILSafeHandleMarshaler::ReturnOverride(
2861 NDirectStubLinker * psl,
2862 BOOL fManagedToNative,
2864 OverrideProcArgs * pargs,
2872 PRECONDITION(CheckPointer(psl));
2873 PRECONDITION(CheckPointer(pargs));
2874 PRECONDITION(CheckPointer(pResID));
2878 ILCodeStream * pslIL = psl->GetMarshalCodeStream();
2879 ILCodeStream * pslPostIL = psl->GetReturnUnmarshalCodeStream();
2880 ILCodeStream * pslILDispatch = psl->GetDispatchCodeStream();
2882 if (!fManagedToNative)
2884 *pResID = IDS_EE_BADMARSHAL_RETURNSHCOMTONATIVE;
2888 // Returned SafeHandle parameters must not be abstract.
2889 if (pargs->m_pMT->IsAbstract())
2891 *pResID = IDS_EE_BADMARSHAL_ABSTRACTRETSAFEHANDLE;
2895 // 1) create local for new safehandle
2896 // 2) prealloc a safehandle
2897 // 3) create local to hold returned handle
2898 // 4) [byref] add byref IntPtr to native sig
2899 // 5) [byref] pass address of local as last arg
2900 // 6) store return value in safehandle
2902 // 1) create local for new safehandle
2903 MethodTable * pMT = pargs->m_pMT;
2904 LocalDesc locDescReturnHandle(pMT);
2905 DWORD dwReturnHandleLocal;
2907 dwReturnHandleLocal = pslIL->NewLocal(locDescReturnHandle);
2909 if (!pMT->HasDefaultConstructor())
2911 MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
2912 COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
2915 // 2) prealloc a safehandle
2916 MethodDesc* pMDCtor = pMT->GetDefaultConstructor();
2917 pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
2918 pslIL->EmitSTLOC(dwReturnHandleLocal);
2920 mdToken tkNativeHandleField = pslPostIL->GetToken(MscorlibBinder::GetField(FIELD__SAFE_HANDLE__HANDLE));
2922 // 3) create local to hold returned handle
2923 DWORD dwReturnNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
2927 // initialize the native handle
2928 pslIL->EmitLDLOC(dwReturnHandleLocal);
2929 pslIL->EmitLDFLD(tkNativeHandleField);
2930 pslIL->EmitSTLOC(dwReturnNativeHandleLocal);
2932 pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I4); // native method returns an HRESULT
2934 // 4) [byref] add byref IntPtr to native sig
2935 locDescReturnHandle.ElementType[0] = ELEMENT_TYPE_BYREF;
2936 locDescReturnHandle.ElementType[1] = ELEMENT_TYPE_I;
2937 locDescReturnHandle.cbType = 2;
2938 pslIL->SetStubTargetArgType(&locDescReturnHandle, false); // extra arg is a byref IntPtr
2940 // 5) [byref] pass address of local as last arg
2941 pslILDispatch->EmitLDLOCA(dwReturnNativeHandleLocal);
2943 // We will use cleanup stream to avoid leaking the handle on thread abort.
2944 psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL);
2946 psl->SetCleanupNeeded();
2947 ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
2948 ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
2950 psl->EmitCheckForArgCleanup(pslCleanupIL,
2951 NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL,
2952 NDirectStubLinker::BranchIfNotMarshaled,
2955 // 6) store return value in safehandle
2956 pslCleanupIL->EmitLDLOC(dwReturnHandleLocal);
2957 pslCleanupIL->EmitLDLOC(dwReturnNativeHandleLocal);
2958 pslCleanupIL->EmitSTFLD(tkNativeHandleField);
2959 pslCleanupIL->EmitLabel(pDoneLabel);
2961 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
2965 pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I);
2966 pslPostIL->EmitSTLOC(dwReturnNativeHandleLocal);
2968 // 6) store return value in safehandle
2969 // The thread abort logic knows that it must not interrupt the stub so we will
2970 // always be able to execute this sequence after returning from the call.
2971 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
2972 pslPostIL->EmitLDLOC(dwReturnNativeHandleLocal);
2973 pslPostIL->EmitSTFLD(tkNativeHandleField);
2974 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
2978 } // ILSafeHandleMarshaler::ReturnOverride
2981 //---------------------------------------------------------------------------------------
2983 MarshalerOverrideStatus ILCriticalHandleMarshaler::ArgumentOverride(NDirectStubLinker* psl,
2987 BOOL fManagedToNative,
2988 OverrideProcArgs* pargs,
2991 UINT nativeStackOffset)
3001 ILCodeStream* pslIL = psl->GetMarshalCodeStream();
3002 ILCodeStream* pslPostIL = psl->GetUnmarshalCodeStream();
3003 ILCodeStream* pslILDispatch = psl->GetDispatchCodeStream();
3005 if (fManagedToNative)
3007 pslIL->SetStubTargetArgType(ELEMENT_TYPE_I);
3009 // Grab the token for the native handle field embedded inside the CriticalHandle. We'll be using it to direct access
3010 // the native handle later.
3011 mdToken tkNativeHandleField = pslIL->GetToken(MscorlibBinder::GetField(FIELD__CRITICAL_HANDLE__HANDLE));
3015 // The specific CriticalHandle subtype we're dealing with here.
3016 MethodTable *pHandleType = pargs->m_pMT;
3018 // Out CriticalHandle parameters must not be abstract.
3019 if (fout && pHandleType->IsAbstract())
3021 *pResID = IDS_EE_BADMARSHAL_ABSTRACTOUTCRITICALHANDLE;
3025 // We rely on the CriticalHandle having a default constructor.
3026 if (!pHandleType->HasDefaultConstructor())
3028 MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
3029 COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
3032 // The high level logic (note that the parameter may be in, out or both):
3033 // 1) If this is an output parameter we need to preallocate a CriticalHandle to wrap the new native handle value. We
3034 // must allocate this before the native call to avoid a failure point when we already have a native resource
3035 // allocated. We must allocate a new CriticalHandle even if we have one on input since both input and output native
3036 // handles need to be tracked and released by a CriticalHandle.
3037 // 2) Initialize a local IntPtr that will be passed to the native call. If we have an input CriticalHandle the value
3038 // comes from there otherwise we get it from the new CriticalHandle (which is guaranteed to be initialized to an
3039 // invalid handle value).
3040 // 3) If this is a out parameter we also store the original handle value (that we just computed above) in a local
3042 // 4) After the native call, if this is an output parameter and the handle value we passed to native differs from
3043 // the local copy we made then the new handle value is written into the output CriticalHandle and that
3044 // CriticalHandle is propagated back to the caller.
3047 LocalDesc locOutputHandle;
3048 DWORD dwOutputHandleLocal = 0; // The output critical handle (out only)
3049 DWORD dwOldNativeHandleLocal = 0; // The original native handle value for comparison (out only)
3050 DWORD dwNativeHandleLocal; // The input (and possibly updated) native handle value
3054 locOutputHandle.ElementType[0] = ELEMENT_TYPE_INTERNAL;
3055 locOutputHandle.cbType = 1;
3056 locOutputHandle.InternalToken = pHandleType;
3058 dwOutputHandleLocal = pslIL->NewLocal(locOutputHandle);
3060 dwOldNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
3063 dwNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
3066 // If we have an input CriticalHandle then initialize our NativeHandle local with it.
3069 pslIL->EmitLDARG(argidx);
3070 pslIL->EmitLDIND_REF();
3071 pslIL->EmitLDFLD(tkNativeHandleField);
3072 pslIL->EmitSTLOC(dwNativeHandleLocal);
3075 // For output parameters we need to allocate a new CriticalHandle to hold the result.
3078 MethodDesc* pMDCtor = pHandleType->GetDefaultConstructor();
3079 pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
3080 pslIL->EmitSTLOC(dwOutputHandleLocal);
3082 // If we didn't provide an input handle then we initialize the NativeHandle local with the (initially invalid)
3083 // handle field set up inside the output handle by the constructor.
3086 pslIL->EmitLDLOC(dwOutputHandleLocal);
3087 pslIL->EmitLDFLD(tkNativeHandleField);
3088 pslIL->EmitSTLOC(dwNativeHandleLocal);
3091 // Remember the handle value we start out with so we know whether to back propagate after the native call.
3092 pslIL->EmitLDLOC(dwNativeHandleLocal);
3093 pslIL->EmitSTLOC(dwOldNativeHandleLocal);
3096 // Leave the address of the native handle local as the argument to the native method.
3097 pslILDispatch->EmitLDLOCA(dwNativeHandleLocal);
3101 // prevent the CriticalHandle from being finalized during the call-out to native
3102 pslPostIL->EmitLDARG(argidx);
3103 pslPostIL->EmitLDIND_REF();
3104 pslPostIL->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
3107 // On the output side we only backpropagate the native handle into the output CriticalHandle and the output
3108 // CriticalHandle to the caller if the native handle actually changed (otherwise we can end up with two
3109 // CriticalHandles wrapping the same native handle, which is bad).
3112 // We will use cleanup stream to avoid leaking the handle on thread abort.
3113 psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx);
3115 psl->SetCleanupNeeded();
3116 ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
3118 ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
3120 psl->EmitCheckForArgCleanup(pslCleanupIL,
3121 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx,
3122 NDirectStubLinker::BranchIfNotMarshaled,
3125 // If this is an [in, out] handle check if the native handles have changed. If not we're finished.
3128 pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
3129 pslCleanupIL->EmitLDLOC(dwOldNativeHandleLocal);
3130 pslCleanupIL->EmitCEQ();
3131 pslCleanupIL->EmitBRTRUE(pDoneLabel);
3134 // Propagate the native handle into the output CriticalHandle.
3135 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
3136 pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
3137 pslCleanupIL->EmitSTFLD(tkNativeHandleField);
3139 // Propagate the output CriticalHandle back to the caller.
3140 pslCleanupIL->EmitLDARG(argidx);
3141 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
3142 pslCleanupIL->EmitSTIND_REF();
3144 pslCleanupIL->EmitLabel(pDoneLabel);
3149 pslILDispatch->EmitLDARG(argidx);
3150 pslILDispatch->EmitLDFLD(tkNativeHandleField);
3152 // prevent the CriticalHandle from being finalized during the call-out to native
3153 pslPostIL->EmitLDARG(argidx);
3154 pslPostIL->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
3161 *pResID = IDS_EE_BADMARSHAL_CRITICALHANDLENATIVETOCOM;
3166 //---------------------------------------------------------------------------------------
3168 MarshalerOverrideStatus
3169 ILCriticalHandleMarshaler::ReturnOverride(
3170 NDirectStubLinker * psl,
3171 BOOL fManagedToNative,
3173 OverrideProcArgs * pargs,
3181 PRECONDITION(CheckPointer(psl));
3182 PRECONDITION(CheckPointer(pargs));
3183 PRECONDITION(CheckPointer(pResID));
3187 if (!fManagedToNative)
3189 *pResID = IDS_EE_BADMARSHAL_RETURNSHCOMTONATIVE;
3193 // Returned CriticalHandle parameters must not be abstract.
3194 if (pargs->m_pMT->IsAbstract())
3196 *pResID = IDS_EE_BADMARSHAL_ABSTRACTRETCRITICALHANDLE;
3200 ILCodeStream * pslIL = psl->GetMarshalCodeStream();
3201 ILCodeStream * pslPostIL = psl->GetReturnUnmarshalCodeStream();
3202 ILCodeStream * pslILDispatch = psl->GetDispatchCodeStream();
3204 // 1) create local for new criticalhandle
3205 // 2) prealloc a criticalhandle
3206 // 3) create local to hold returned handle
3207 // 4) [byref] add byref IntPtr to native sig
3208 // 5) [byref] pass address of local as last arg
3209 // 6) store return value in criticalhandle
3211 // 1) create local for new criticalhandle
3212 MethodTable * pMT = pargs->m_pMT;
3213 LocalDesc locDescReturnHandle(pMT);
3214 DWORD dwReturnHandleLocal;
3216 dwReturnHandleLocal = pslIL->NewLocal(locDescReturnHandle);
3218 if (!pMT->HasDefaultConstructor())
3220 MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
3221 COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
3224 // 2) prealloc a criticalhandle
3225 MethodDesc * pMDCtor = pMT->GetDefaultConstructor();
3226 pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
3227 pslIL->EmitSTLOC(dwReturnHandleLocal);
3229 mdToken tkNativeHandleField = pslPostIL->GetToken(MscorlibBinder::GetField(FIELD__CRITICAL_HANDLE__HANDLE));
3231 // 3) create local to hold returned handle
3232 DWORD dwReturnNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
3236 // initialize the native handle
3237 pslIL->EmitLDLOC(dwReturnHandleLocal);
3238 pslIL->EmitLDFLD(tkNativeHandleField);
3239 pslIL->EmitSTLOC(dwReturnNativeHandleLocal);
3241 pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I4); // native method returns an HRESULT
3243 // 4) [byref] add byref IntPtr to native sig
3244 locDescReturnHandle.ElementType[0] = ELEMENT_TYPE_BYREF;
3245 locDescReturnHandle.ElementType[1] = ELEMENT_TYPE_I;
3246 locDescReturnHandle.cbType = 2;
3247 pslIL->SetStubTargetArgType(&locDescReturnHandle, false); // extra arg is a byref IntPtr
3249 // 5) [byref] pass address of local as last arg
3250 pslILDispatch->EmitLDLOCA(dwReturnNativeHandleLocal);
3252 // We will use cleanup stream to avoid leaking the handle on thread abort.
3253 psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL);
3255 psl->SetCleanupNeeded();
3256 ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
3257 ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
3259 // 6) store return value in criticalhandle
3260 psl->EmitCheckForArgCleanup(pslCleanupIL,
3261 NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL,
3262 NDirectStubLinker::BranchIfNotMarshaled,
3265 pslCleanupIL->EmitLDLOC(dwReturnHandleLocal);
3266 pslCleanupIL->EmitLDLOC(dwReturnNativeHandleLocal);
3267 pslCleanupIL->EmitSTFLD(tkNativeHandleField);
3268 pslCleanupIL->EmitLabel(pDoneLabel);
3270 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
3274 pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I);
3275 pslPostIL->EmitSTLOC(dwReturnNativeHandleLocal);
3277 // 6) store return value in criticalhandle
3278 // The thread abort logic knows that it must not interrupt the stub so we will
3279 // always be able to execute this sequence after returning from the call.
3280 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
3281 pslPostIL->EmitLDLOC(dwReturnNativeHandleLocal);
3282 pslPostIL->EmitSTFLD(tkNativeHandleField);
3283 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
3287 } // ILCriticalHandleMarshaler::ReturnOverride
3290 LocalDesc ILArgIteratorMarshaler::GetNativeType()
3292 LIMITED_METHOD_CONTRACT;
3294 return LocalDesc(ELEMENT_TYPE_I); // va_list
3297 LocalDesc ILArgIteratorMarshaler::GetManagedType()
3299 STANDARD_VM_CONTRACT;
3301 return LocalDesc(MscorlibBinder::GetClass(CLASS__ARG_ITERATOR));
3304 bool ILArgIteratorMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3306 LIMITED_METHOD_CONTRACT;
3308 if (IsByref(dwMarshalFlags))
3310 *pErrorResID = IDS_EE_BADMARSHAL_ARGITERATORRESTRICTION;
3317 void ILArgIteratorMarshaler::EmitMarshalArgumentCLRToNative()
3322 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3326 EmitSetupSigAndDefaultHomesCLRToNative();
3332 // Allocate enough memory for va_list
3333 DWORD dwVaListSizeLocal = m_pcsMarshal->NewLocal(LocalDesc(ELEMENT_TYPE_U4));
3334 EmitLoadManagedHomeAddr(m_pcsMarshal);
3335 m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__CALC_VA_LIST_SIZE, 1, 1);
3336 m_pcsMarshal->EmitSTLOC(dwVaListSizeLocal);
3337 m_pcsMarshal->EmitLDLOC(dwVaListSizeLocal);
3338 m_pcsMarshal->EmitLOCALLOC();
3339 EmitStoreNativeValue(m_pcsMarshal);
3341 // void MarshalToUnmanagedVaListInternal(cbVaListSize, va_list, VARARGS* data)
3342 EmitLoadNativeValue(m_pcsMarshal);
3343 m_pcsMarshal->EmitLDLOC(dwVaListSizeLocal);
3344 EmitLoadManagedHomeAddr(m_pcsMarshal);
3345 m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__MARSHAL_TO_UNMANAGED_VA_LIST_INTERNAL, 3, 0);
3348 void ILArgIteratorMarshaler::EmitMarshalArgumentNativeToCLR()
3353 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3357 EmitSetupSigAndDefaultHomesNativeToCLR();
3359 EmitLoadNativeValue(m_pcsMarshal);
3360 EmitLoadManagedHomeAddr(m_pcsMarshal);
3362 // void MarshalToManagedVaList(va_list va, VARARGS *dataout)
3363 m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__MARSHAL_TO_MANAGED_VA_LIST_INTERNAL, 2, 0);
3367 LocalDesc ILArrayWithOffsetMarshaler::GetNativeType()
3369 LIMITED_METHOD_CONTRACT;
3371 return LocalDesc(ELEMENT_TYPE_I);
3374 LocalDesc ILArrayWithOffsetMarshaler::GetManagedType()
3376 STANDARD_VM_CONTRACT;
3378 return LocalDesc(MscorlibBinder::GetClass(CLASS__ARRAY_WITH_OFFSET));
3381 bool ILArrayWithOffsetMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3383 LIMITED_METHOD_CONTRACT;
3385 if (IsCLRToNative(dwMarshalFlags) && !IsByref(dwMarshalFlags) && IsIn(dwMarshalFlags) && IsOut(dwMarshalFlags))
3390 *pErrorResID = IDS_EE_BADMARSHAL_AWORESTRICTION;
3395 void ILArrayWithOffsetMarshaler::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
3401 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwCountLocalNum);
3402 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwOffsetLocalNum);
3403 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwPinnedLocalNum);
3407 int tokArrayWithOffset_m_array = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_ARRAY));
3408 int tokArrayWithOffset_m_count = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_COUNT));
3410 ILCodeLabel* pNonNullLabel = pslILEmit->NewCodeLabel();
3411 ILCodeLabel* pSlowAllocPathLabel = pslILEmit->NewCodeLabel();
3412 ILCodeLabel* pDoneLabel = pslILEmit->NewCodeLabel();
3414 m_dwCountLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
3417 // Convert the space
3420 EmitLoadManagedValue(pslILEmit);
3421 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3422 pslILEmit->EmitBRTRUE(pNonNullLabel);
3424 pslILEmit->EmitLoadNullPtr();
3425 pslILEmit->EmitBR(pDoneLabel);
3426 pslILEmit->EmitLabel(pNonNullLabel);
3428 EmitLoadManagedValue(pslILEmit);
3429 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_count);
3430 pslILEmit->EmitDUP();
3431 pslILEmit->EmitSTLOC(m_dwCountLocalNum);
3432 pslILEmit->EmitDUP();
3433 pslILEmit->EmitLDC(s_cbStackAllocThreshold);
3434 pslILEmit->EmitCGT_UN();
3435 pslILEmit->EmitBRTRUE(pSlowAllocPathLabel);
3438 pslILEmit->EmitLOCALLOC();
3440 pslILEmit->EmitBR(pDoneLabel);
3441 pslILEmit->EmitLabel(pSlowAllocPathLabel);
3444 pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
3446 pslILEmit->EmitLabel(pDoneLabel);
3447 EmitStoreNativeValue(pslILEmit);
3450 // Convert the contents
3453 int tokArrayWithOffset_m_offset = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_OFFSET));
3455 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
3457 LocalDesc locDescPinned;
3458 locDescPinned.cbType = 2;
3459 locDescPinned.ElementType[0] = ELEMENT_TYPE_PINNED;
3460 locDescPinned.ElementType[1] = ELEMENT_TYPE_OBJECT;
3461 m_dwPinnedLocalNum = pslILEmit->NewLocal(locDescPinned);
3462 m_dwOffsetLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
3464 EmitLoadManagedValue(pslILEmit);
3465 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3466 pslILEmit->EmitBRFALSE(pNullRefLabel);
3468 EmitLoadManagedValue(pslILEmit);
3469 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3470 pslILEmit->EmitSTLOC(m_dwPinnedLocalNum);
3472 EmitLoadNativeValue(pslILEmit); // dest
3474 pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3475 pslILEmit->EmitCONV_I();
3476 pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3477 pslILEmit->EmitCALL(METHOD__ARRAY__GET_DATA_PTR_OFFSET_INTERNAL, 1, 1);
3478 pslILEmit->EmitADD(); // TODO Phase5: Use UnsafeAddrOfPinnedArrayElement
3480 EmitLoadManagedValue(pslILEmit);
3481 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_offset);
3482 pslILEmit->EmitDUP();
3483 pslILEmit->EmitSTLOC(m_dwOffsetLocalNum);
3484 pslILEmit->EmitADD(); // src
3485 pslILEmit->EmitLDLOC(m_dwCountLocalNum); // len
3487 // static void Memcpy(byte* dest, byte* src, int len)
3488 pslILEmit->EmitCALL(METHOD__BUFFER__MEMCPY, 3, 0);
3490 pslILEmit->EmitLDNULL();
3491 pslILEmit->EmitSTLOC(m_dwPinnedLocalNum);
3493 pslILEmit->EmitLabel(pNullRefLabel);
3496 void ILArrayWithOffsetMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
3502 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED != m_dwCountLocalNum);
3503 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED != m_dwOffsetLocalNum);
3504 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED != m_dwPinnedLocalNum);
3508 int tokArrayWithOffset_m_array = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_ARRAY));
3510 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
3512 EmitLoadManagedValue(pslILEmit);
3513 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3514 pslILEmit->EmitBRFALSE(pNullRefLabel);
3516 EmitLoadManagedValue(pslILEmit);
3517 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3518 pslILEmit->EmitSTLOC(m_dwPinnedLocalNum);
3520 pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3521 pslILEmit->EmitCONV_I();
3522 pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3523 pslILEmit->EmitCALL(METHOD__ARRAY__GET_DATA_PTR_OFFSET_INTERNAL, 1, 1);
3524 pslILEmit->EmitADD(); // TODO Phase5: Use UnsafeAddrOfPinnedArrayElement
3526 pslILEmit->EmitLDLOC(m_dwOffsetLocalNum);
3527 pslILEmit->EmitADD(); // dest
3529 EmitLoadNativeValue(pslILEmit); // src
3531 pslILEmit->EmitLDLOC(m_dwCountLocalNum); // len
3533 // static void Memcpy(byte* dest, byte* src, int len)
3534 pslILEmit->EmitCALL(METHOD__BUFFER__MEMCPY, 3, 0);
3536 pslILEmit->EmitLDNULL();
3537 pslILEmit->EmitSTLOC(m_dwPinnedLocalNum);
3539 pslILEmit->EmitLabel(pNullRefLabel);
3542 void ILArrayWithOffsetMarshaler::EmitClearNativeTemp(ILCodeStream* pslILEmit)
3544 STANDARD_VM_CONTRACT;
3546 ILCodeLabel* pDoneLabel = pslILEmit->NewCodeLabel();
3548 pslILEmit->EmitLDLOC(m_dwCountLocalNum);
3549 pslILEmit->EmitLDC(s_cbStackAllocThreshold);
3550 pslILEmit->EmitCGT_UN();
3551 pslILEmit->EmitBRFALSE(pDoneLabel);
3554 EmitLoadNativeValue(pslILEmit);
3555 pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
3557 pslILEmit->EmitLabel(pDoneLabel);
3560 LocalDesc ILAsAnyMarshalerBase::GetNativeType()
3562 LIMITED_METHOD_CONTRACT;
3564 return LocalDesc(ELEMENT_TYPE_I);
3567 LocalDesc ILAsAnyMarshalerBase::GetManagedType()
3569 LIMITED_METHOD_CONTRACT;
3571 return LocalDesc(ELEMENT_TYPE_OBJECT);
3574 bool ILAsAnyMarshalerBase::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3576 WRAPPER_NO_CONTRACT;
3578 if (IsCLRToNative(dwMarshalFlags) && !IsByref(dwMarshalFlags))
3583 *pErrorResID = IDS_EE_BADMARSHAL_ASANYRESTRICTION;
3587 bool ILAsAnyMarshalerBase::SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3589 LIMITED_METHOD_CONTRACT;
3590 *pErrorResID = IDS_EE_BADMARSHAL_ASANYRESTRICTION;
3594 void ILAsAnyMarshalerBase::EmitMarshalArgumentCLRToNative()
3599 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3600 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwMarshalerLocalNum);
3604 EmitSetupSigAndDefaultHomesCLRToNative();
3606 BYTE inout = (IsIn(m_dwMarshalFlags) ? ML_IN : 0) | (IsOut(m_dwMarshalFlags) ? ML_OUT : 0);
3607 BYTE fIsAnsi = IsAnsi() ? 1 : 0;
3608 BYTE fBestFit = m_pargs->m_pMarshalInfo->GetBestFitMapping();
3609 BYTE fThrow = m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar();
3613 dwFlags |= inout << 24;
3614 dwFlags |= fIsAnsi << 16;
3615 dwFlags |= fThrow << 8;
3616 dwFlags |= fBestFit << 0;
3622 LocalDesc marshalerType(MscorlibBinder::GetClass(CLASS__ASANY_MARSHALER));
3623 m_dwMarshalerLocalNum = m_pcsMarshal->NewLocal(marshalerType);
3624 DWORD dwTmpLocalNum = m_pcsMarshal->NewLocal(ELEMENT_TYPE_I);
3626 m_pcsMarshal->EmitLDC(sizeof(MngdNativeArrayMarshaler));
3627 m_pcsMarshal->EmitLOCALLOC();
3628 m_pcsMarshal->EmitSTLOC(dwTmpLocalNum);
3630 // marshaler = new AsAnyMarshaler(local_buffer)
3631 m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3632 m_pcsMarshal->EmitINITOBJ(m_pcsMarshal->GetToken(marshalerType.InternalToken));
3634 m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3635 m_pcsMarshal->EmitLDLOC(dwTmpLocalNum);
3636 m_pcsMarshal->EmitCALL(METHOD__ASANY_MARSHALER__CTOR, 2, 0);
3638 // nativeValue = marshaler.ConvertToNative(managedValue, flags);
3639 m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3640 EmitLoadManagedValue(m_pcsMarshal);
3641 m_pcsMarshal->EmitLDC(dwFlags);
3642 m_pcsMarshal->EmitCALL(METHOD__ASANY_MARSHALER__CONVERT_TO_NATIVE, 3, 1);
3643 EmitStoreNativeValue(m_pcsMarshal);
3648 if (IsOut(m_dwMarshalFlags))
3650 // marshaler.ConvertToManaged(managedValue, nativeValue)
3651 m_pcsUnmarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3652 EmitLoadManagedValue(m_pcsUnmarshal);
3653 EmitLoadNativeValue(m_pcsUnmarshal);
3654 m_pcsUnmarshal->EmitCALL(METHOD__ASANY_MARSHALER__CONVERT_TO_MANAGED, 3, 0);
3660 EmitCleanupCLRToNativeTemp();
3663 bool ILAsAnyMarshalerBase::NeedsClearNative()
3665 LIMITED_METHOD_CONTRACT;
3669 void ILAsAnyMarshalerBase::EmitClearNativeTemp(ILCodeStream* pslILEmit)
3671 STANDARD_VM_CONTRACT;
3673 // marshaler.ClearNative(nativeHome)
3674 pslILEmit->EmitLDLOCA(m_dwMarshalerLocalNum);
3675 EmitLoadNativeValue(pslILEmit);
3676 pslILEmit->EmitCALL(METHOD__ASANY_MARSHALER__CLEAR_NATIVE, 2, 0);
3679 // we can get away with putting the GetManagedType and GetNativeType on ILMngdMarshaler because
3680 // currently it is only used for reference marshaling where this is appropriate. If it became
3681 // used for something else, we would want to move this down in the inheritence tree..
3682 LocalDesc ILMngdMarshaler::GetNativeType()
3684 LIMITED_METHOD_CONTRACT;
3686 return LocalDesc(ELEMENT_TYPE_I);
3689 LocalDesc ILMngdMarshaler::GetManagedType()
3691 LIMITED_METHOD_CONTRACT;
3693 return LocalDesc(ELEMENT_TYPE_OBJECT);
3696 void ILMngdMarshaler::EmitCallMngdMarshalerMethod(ILCodeStream* pslILEmit, MethodDesc *pMD)
3698 STANDARD_VM_CONTRACT;
3703 UINT numArgs = sig.NumFixedArgs();
3707 EmitLoadMngdMarshaler(pslILEmit);
3711 _ASSERTE(numArgs == 2);
3714 EmitLoadManagedHomeAddr(pslILEmit);
3715 EmitLoadNativeHomeAddr(pslILEmit);
3717 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), numArgs, 0);
3721 bool ILNativeArrayMarshaler::UsePinnedArraySpecialCase()
3723 if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags) && (NULL == OleVariant::GetMarshalerForVarType(m_pargs->na.m_vt, TRUE)))
3731 void ILNativeArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
3733 STANDARD_VM_CONTRACT;
3735 if (UsePinnedArraySpecialCase())
3740 m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
3742 pslILEmit->EmitLDC(sizeof(MngdNativeArrayMarshaler));
3743 pslILEmit->EmitLOCALLOC();
3744 pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
3746 CREATE_MARSHALER_CARRAY_OPERANDS mops;
3747 m_pargs->m_pMarshalInfo->GetMops(&mops);
3749 pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
3751 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(mops.methodTable));
3752 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
3754 DWORD dwFlags = mops.elementType;
3755 dwFlags |= (((DWORD)mops.bestfitmapping) << 16);
3756 dwFlags |= (((DWORD)mops.throwonunmappablechar) << 24);
3758 if (!IsCLRToNative(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
3760 // Unmanaged->managed in/out is the only case where we expect the native buffer to contain valid data.
3761 _ASSERTE((dwFlags & MngdNativeArrayMarshaler::FLAG_NATIVE_DATA_VALID) == 0);
3762 dwFlags |= MngdNativeArrayMarshaler::FLAG_NATIVE_DATA_VALID;
3765 pslILEmit->EmitLDC(dwFlags);
3767 pslILEmit->EmitCALL(METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CREATE_MARSHALER, 3, 0);
3771 void ILNativeArrayMarshaler::EmitMarshalArgumentCLRToNative()
3776 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3780 if (UsePinnedArraySpecialCase())
3783 // Replicate ML_PINNEDISOMORPHICARRAY_C2N_EXPRESS behavior -- note that this
3784 // gives in/out semantics "for free" even if the app doesn't specify one or
3785 // the other. Since there is no enforcement of this, apps blithely depend
3789 // The base offset should only be 0 for System.Array parameters for which
3790 // OleVariant::GetMarshalerForVarType(vt) should never return NULL.
3791 _ASSERTE(m_pargs->na.m_optionalbaseoffset != 0);
3793 EmitSetupSigAndDefaultHomesCLRToNative();
3795 LocalDesc managedType = GetManagedType();
3796 managedType.MakePinned();
3798 DWORD dwPinnedLocal = m_pcsMarshal->NewLocal(managedType);
3799 ILCodeLabel* pNullRefLabel = m_pcsMarshal->NewCodeLabel();
3801 m_pcsMarshal->EmitLoadNullPtr();
3802 EmitStoreNativeValue(m_pcsMarshal);
3804 EmitLoadManagedValue(m_pcsMarshal);
3805 m_pcsMarshal->EmitBRFALSE(pNullRefLabel);
3807 EmitLoadManagedValue(m_pcsMarshal);
3808 m_pcsMarshal->EmitSTLOC(dwPinnedLocal);
3809 m_pcsMarshal->EmitLDLOC(dwPinnedLocal);
3810 m_pcsMarshal->EmitCONV_I();
3811 m_pcsMarshal->EmitLDC(m_pargs->na.m_optionalbaseoffset);
3812 m_pcsMarshal->EmitADD();
3813 EmitStoreNativeValue(m_pcsMarshal);
3815 if (g_pConfig->InteropLogArguments())
3817 m_pslNDirect->EmitLogNativeArgument(m_pcsMarshal, dwPinnedLocal);
3820 m_pcsMarshal->EmitLabel(pNullRefLabel);
3824 ILMngdMarshaler::EmitMarshalArgumentCLRToNative();
3829 // Peek at the SizeParamIndex argument
3830 // 1) See if the SizeParamIndex argument is being passed by ref
3831 // 2) Get the element type of SizeParamIndex argument
3833 BOOL ILNativeArrayMarshaler::CheckSizeParamIndexArg(
3834 const CREATE_MARSHALER_CARRAY_OPERANDS &mops,
3835 CorElementType *pElementType)
3842 PRECONDITION(m_pargs != NULL);
3843 PRECONDITION(m_pargs->m_pMarshalInfo != NULL);
3847 MethodDesc *pMD = m_pargs->m_pMarshalInfo->GetMethodDesc();
3850 Module *pModule = m_pargs->m_pMarshalInfo->GetModule();
3853 SigTypeContext emptyTypeContext; // this is an empty type context: ndirect and COM calls are guaranteed to not be generics.
3854 MetaSig msig(pMD->GetSignature(),
3859 // Go to the SizeParamIndex argument
3860 // Note that we already have check in place to make sure SizeParamIndex is within range
3862 if (msig.HasExplicitThis())
3865 for (int i = 0; i < mops.countParamIdx; ++i)
3870 SigPointer sigPointer = msig.GetArgProps();
3872 // Peek into the SizeParamIndex argument
3873 CorElementType elementType;
3874 IfFailThrow(sigPointer.PeekElemType(&elementType));
3876 if (elementType != ELEMENT_TYPE_BYREF)
3878 if (elementType == ELEMENT_TYPE_STRING ||
3879 elementType == ELEMENT_TYPE_ARRAY ||
3880 elementType == ELEMENT_TYPE_FNPTR ||
3881 elementType == ELEMENT_TYPE_OBJECT ||
3882 elementType == ELEMENT_TYPE_SZARRAY ||
3883 elementType == ELEMENT_TYPE_TYPEDBYREF)
3885 COMPlusThrow(kMarshalDirectiveException, IDS_EE_SIZECONTROLBADTYPE);
3888 *pElementType = elementType;
3892 // Get the real type
3893 IfFailThrow(sigPointer.GetElemType(NULL));
3894 IfFailThrow(sigPointer.PeekElemType(&elementType));
3896 // All the integral types are supported
3899 case ELEMENT_TYPE_I1:
3900 case ELEMENT_TYPE_U1:
3901 case ELEMENT_TYPE_I2:
3902 case ELEMENT_TYPE_U2:
3903 case ELEMENT_TYPE_I4:
3904 case ELEMENT_TYPE_U4:
3905 case ELEMENT_TYPE_I8:
3906 case ELEMENT_TYPE_U8:
3907 case ELEMENT_TYPE_I:
3908 case ELEMENT_TYPE_U:
3912 COMPlusThrow(kMarshalDirectiveException, IDS_EE_SIZECONTROLBADTYPE);
3915 *pElementType = elementType;
3920 // Calculate the number of elements and load it into stack
3922 void ILNativeArrayMarshaler::EmitLoadElementCount(ILCodeStream* pslILEmit)
3924 STANDARD_VM_CONTRACT;
3927 // Determine the element count and load into evaluation stack
3929 CREATE_MARSHALER_CARRAY_OPERANDS mops;
3930 m_pargs->m_pMarshalInfo->GetMops(&mops);
3932 if (mops.multiplier != 0)
3935 // SizeParamIndex arg fix up for LCID
3937 unsigned countParamIdx = mops.countParamIdx;
3938 if (!IsCLRToNative(m_dwMarshalFlags))
3940 int lcidParamIdx = m_pslNDirect->GetLCIDParamIdx();
3942 if (lcidParamIdx >= 0 && (unsigned)lcidParamIdx <= countParamIdx)
3944 // the LCID is injected before the count parameter so the index
3945 // has to be incremented to get the unmanaged parameter number
3951 // Load SizeParamIndex argument
3953 pslILEmit->EmitLDARG(countParamIdx);
3959 // Is the SizeParamIndex points to a by-ref parameter?
3960 CorElementType sizeParamIndexArgType;
3961 if (CheckSizeParamIndexArg(mops, &sizeParamIndexArgType))
3963 // Load the by-ref parameter
3964 switch (sizeParamIndexArgType)
3966 case ELEMENT_TYPE_I1:
3967 pslILEmit->EmitLDIND_I1();
3970 case ELEMENT_TYPE_U1:
3971 pslILEmit->EmitLDIND_U1();
3974 case ELEMENT_TYPE_I2:
3975 pslILEmit->EmitLDIND_I2();
3978 case ELEMENT_TYPE_U2:
3979 pslILEmit->EmitLDIND_U2();
3982 case ELEMENT_TYPE_I4:
3983 pslILEmit->EmitLDIND_I4();
3986 case ELEMENT_TYPE_U4:
3987 pslILEmit->EmitLDIND_U4();
3990 case ELEMENT_TYPE_U8:
3991 case ELEMENT_TYPE_I8:
3992 pslILEmit->EmitLDIND_I8();
3995 case ELEMENT_TYPE_I:
3996 case ELEMENT_TYPE_U:
3997 pslILEmit->EmitLDIND_I();
4001 // Should not go here because we should've thrown exception
4007 pslILEmit->EmitCONV_OVF_I4();
4009 // multiplier * arg + additive
4010 pslILEmit->EmitLDC(mops.multiplier);
4011 pslILEmit->EmitMUL_OVF();
4012 pslILEmit->EmitLDC(mops.additive);
4013 pslILEmit->EmitADD_OVF();
4017 pslILEmit->EmitLDC((int)mops.additive);
4021 void ILNativeArrayMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
4023 STANDARD_VM_CONTRACT;
4025 EmitLoadMngdMarshaler(pslILEmit);
4026 EmitLoadManagedHomeAddr(pslILEmit);
4027 EmitLoadNativeHomeAddr(pslILEmit);
4029 if (IsByref(m_dwMarshalFlags))
4032 // Reset the element count just in case there is an exception thrown in the code emitted by
4033 // EmitLoadElementCount. The best thing we can do here is to avoid a crash.
4035 _ASSERTE(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4036 pslILEmit->EmitLDC(0);
4037 pslILEmit->EmitSTLOC(m_dwSavedSizeArg);
4040 // Dynamically calculate element count using SizeParamIndex argument
4041 EmitLoadElementCount(pslILEmit);
4043 if (IsByref(m_dwMarshalFlags))
4046 // Save the native array size before converting it to managed and load it again
4048 _ASSERTE(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4049 pslILEmit->EmitSTLOC(m_dwSavedSizeArg);
4050 pslILEmit->EmitLDLOC(m_dwSavedSizeArg);
4053 // MngdNativeArrayMarshaler::ConvertSpaceToManaged
4054 pslILEmit->EmitCALL(pslILEmit->GetToken(GetConvertSpaceToManagedMethod()), 4, 0);
4057 void ILNativeArrayMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
4059 STANDARD_VM_CONTRACT;
4061 if (IsByref(m_dwMarshalFlags))
4063 _ASSERTE(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4066 // Save the array size before converting it to native
4068 EmitLoadManagedValue(pslILEmit);
4069 ILCodeLabel *pManagedHomeIsNull = pslILEmit->NewCodeLabel();
4070 pslILEmit->EmitBRFALSE(pManagedHomeIsNull);
4071 EmitLoadManagedValue(pslILEmit);
4072 pslILEmit->EmitLDLEN();
4073 pslILEmit->EmitSTLOC(m_dwSavedSizeArg);
4074 pslILEmit->EmitLabel(pManagedHomeIsNull);
4078 ILMngdMarshaler::EmitConvertSpaceCLRToNative(pslILEmit);
4081 void ILNativeArrayMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
4083 STANDARD_VM_CONTRACT;
4085 EmitLoadMngdMarshaler(pslILEmit);
4086 EmitLoadNativeHomeAddr(pslILEmit);
4087 EmitLoadNativeSize(pslILEmit);
4089 pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeMethod()), 3, 0);
4092 void ILNativeArrayMarshaler::EmitLoadNativeSize(ILCodeStream* pslILEmit)
4094 STANDARD_VM_CONTRACT;
4096 if (IsByref(m_dwMarshalFlags))
4098 _ASSERT(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4099 pslILEmit->EmitLDLOC(m_dwSavedSizeArg);
4103 pslILEmit->EmitLDC(0);
4104 EmitLoadManagedValue(pslILEmit);
4105 ILCodeLabel *pManagedHomeIsNull = pslILEmit->NewCodeLabel();
4106 pslILEmit->EmitBRFALSE(pManagedHomeIsNull);
4107 pslILEmit->EmitPOP(); // Pop the 0 on the stack
4108 EmitLoadManagedValue(pslILEmit);
4109 pslILEmit->EmitLDLEN();
4110 pslILEmit->EmitCONV_OVF_I4();
4111 pslILEmit->EmitLabel(pManagedHomeIsNull); // Keep the 0 on the stack
4115 void ILNativeArrayMarshaler::EmitClearNativeContents(ILCodeStream* pslILEmit)
4117 STANDARD_VM_CONTRACT;
4119 EmitLoadMngdMarshaler(pslILEmit);
4120 EmitLoadNativeHomeAddr(pslILEmit);
4121 EmitLoadNativeSize(pslILEmit);
4123 pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeContentsMethod()), 3, 0);
4126 void ILNativeArrayMarshaler::EmitNewSavedSizeArgLocal()
4128 STANDARD_VM_CONTRACT;
4130 _ASSERTE(m_dwSavedSizeArg == LOCAL_NUM_UNUSED);
4131 ILCodeStream *pcsSetup = m_pslNDirect->GetSetupCodeStream();
4132 m_dwSavedSizeArg = pcsSetup->NewLocal(ELEMENT_TYPE_I4);
4133 pcsSetup->EmitLDC(0);
4134 pcsSetup->EmitSTLOC(m_dwSavedSizeArg);
4137 void ILNativeArrayMarshaler::EmitMarshalArgumentNativeToCLRByref()
4139 STANDARD_VM_CONTRACT;
4141 if (IsByref(m_dwMarshalFlags))
4143 EmitNewSavedSizeArgLocal();
4146 ILMngdMarshaler::EmitMarshalArgumentNativeToCLRByref();
4149 void ILNativeArrayMarshaler::EmitMarshalArgumentCLRToNativeByref()
4151 STANDARD_VM_CONTRACT;
4153 if (IsByref(m_dwMarshalFlags))
4155 EmitNewSavedSizeArgLocal();
4158 ILMngdMarshaler::EmitMarshalArgumentCLRToNativeByref();
4162 #ifndef CROSSGEN_COMPILE
4164 FCIMPL3(void, MngdNativeArrayMarshaler::CreateMarshaler, MngdNativeArrayMarshaler* pThis, MethodTable* pMT, UINT32 dwFlags)
4168 // Don't check whether the input values are negative - passing negative size-controlling
4169 // arguments and compensating them with a positive SizeConst has always worked.
4170 pThis->m_pElementMT = pMT;
4171 pThis->m_vt = (VARTYPE)(dwFlags);
4172 pThis->m_NativeDataValid = (BYTE)((dwFlags & FLAG_NATIVE_DATA_VALID) != 0);
4173 dwFlags &= ~FLAG_NATIVE_DATA_VALID;
4174 pThis->m_BestFitMap = (BYTE)(dwFlags >> 16);
4175 pThis->m_ThrowOnUnmappableChar = (BYTE)(dwFlags >> 24);
4176 pThis->m_Array = TypeHandle();
4180 FCIMPL3(void, MngdNativeArrayMarshaler::ConvertSpaceToNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4184 HELPER_METHOD_FRAME_BEGIN_0();
4186 BASEARRAYREF arrayRef = (BASEARRAYREF) *pManagedHome;
4188 if (arrayRef == NULL)
4190 *pNativeHome = NULL;
4194 SIZE_T cElements = arrayRef->GetNumComponents();
4195 SIZE_T cbElement = OleVariant::GetElementSizeForVarType(pThis->m_vt, pThis->m_pElementMT);
4198 COMPlusThrow(kArgumentException, IDS_EE_COM_UNSUPPORTED_SIG);
4200 SIZE_T cbArray = cElements;
4201 if ( (!SafeMulSIZE_T(&cbArray, cbElement)) || cbArray > MAX_SIZE_FOR_INTEROP)
4202 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
4204 *pNativeHome = CoTaskMemAlloc(cbArray);
4205 if (*pNativeHome == NULL)
4208 // initialize the array
4209 FillMemory(*pNativeHome, cbArray, 0);
4212 HELPER_METHOD_FRAME_END();
4216 FCIMPL3(void, MngdNativeArrayMarshaler::ConvertContentsToNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4220 HELPER_METHOD_FRAME_BEGIN_0();
4222 BASEARRAYREF* pArrayRef = (BASEARRAYREF *) pManagedHome;
4224 if (*pArrayRef != NULL)
4226 const OleVariant::Marshaler* pMarshaler = OleVariant::GetMarshalerForVarType(pThis->m_vt, TRUE);
4227 SIZE_T cElements = (*pArrayRef)->GetNumComponents();
4228 if (pMarshaler == NULL || pMarshaler->ComToOleArray == NULL)
4230 if ( (!SafeMulSIZE_T(&cElements, OleVariant::GetElementSizeForVarType(pThis->m_vt, pThis->m_pElementMT))) || cElements > MAX_SIZE_FOR_INTEROP)
4231 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
4233 _ASSERTE(!GetTypeHandleForCVType(OleVariant::GetCVTypeForVarType(pThis->m_vt)).GetMethodTable()->ContainsPointers());
4234 memcpyNoGCRefs(*pNativeHome, (*pArrayRef)->GetDataPtr(), cElements);
4238 pMarshaler->ComToOleArray(pArrayRef, *pNativeHome, pThis->m_pElementMT, pThis->m_BestFitMap,
4239 pThis->m_ThrowOnUnmappableChar, pThis->m_NativeDataValid, cElements);
4242 HELPER_METHOD_FRAME_END();
4246 FCIMPL4(void, MngdNativeArrayMarshaler::ConvertSpaceToManaged, MngdNativeArrayMarshaler* pThis,
4247 OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements)
4251 HELPER_METHOD_FRAME_BEGIN_0();
4253 if (*pNativeHome == NULL)
4255 SetObjectReference(pManagedHome, NULL, GetAppDomain());
4259 // <TODO>@todo: lookup this class before marshal time</TODO>
4260 if (pThis->m_Array.IsNull())
4262 // Get proper array class name & type
4263 pThis->m_Array = OleVariant::GetArrayForVarType(pThis->m_vt, TypeHandle(pThis->m_pElementMT));
4264 if (pThis->m_Array.IsNull())
4265 COMPlusThrow(kTypeLoadException);
4270 SetObjectReference(pManagedHome, AllocateArrayEx(pThis->m_Array, &cElements, 1), GetAppDomain());
4272 HELPER_METHOD_FRAME_END();
4276 FCIMPL3(void, MngdNativeArrayMarshaler::ConvertContentsToManaged, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4280 HELPER_METHOD_FRAME_BEGIN_0();
4282 if (*pNativeHome != NULL)
4284 const OleVariant::Marshaler *pMarshaler = OleVariant::GetMarshalerForVarType(pThis->m_vt, TRUE);
4286 BASEARRAYREF* pArrayRef = (BASEARRAYREF*) pManagedHome;
4288 if (pMarshaler == NULL || pMarshaler->OleToComArray == NULL)
4290 SIZE_T cElements = (*pArrayRef)->GetNumComponents();
4291 if ( (!SafeMulSIZE_T(&cElements, OleVariant::GetElementSizeForVarType(pThis->m_vt, pThis->m_pElementMT))) || cElements > MAX_SIZE_FOR_INTEROP)
4292 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
4294 // If we are copying variants, strings, etc, we need to use write barrier
4295 _ASSERTE(!GetTypeHandleForCVType(OleVariant::GetCVTypeForVarType(pThis->m_vt)).GetMethodTable()->ContainsPointers());
4296 memcpyNoGCRefs((*pArrayRef)->GetDataPtr(), *pNativeHome, cElements);
4300 pMarshaler->OleToComArray(*pNativeHome, pArrayRef, pThis->m_pElementMT);
4304 HELPER_METHOD_FRAME_END();
4308 FCIMPL3(void, MngdNativeArrayMarshaler::ClearNative, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
4312 HELPER_METHOD_FRAME_BEGIN_0();
4314 if (*pNativeHome != NULL)
4316 DoClearNativeContents(pThis, pNativeHome, cElements);
4317 CoTaskMemFree(*pNativeHome);
4320 HELPER_METHOD_FRAME_END();
4324 FCIMPL3(void, MngdNativeArrayMarshaler::ClearNativeContents, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
4328 HELPER_METHOD_FRAME_BEGIN_0();
4330 DoClearNativeContents(pThis, pNativeHome, cElements);
4332 HELPER_METHOD_FRAME_END();
4336 void MngdNativeArrayMarshaler::DoClearNativeContents(MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
4346 if (*pNativeHome != NULL)
4348 const OleVariant::Marshaler *pMarshaler = OleVariant::GetMarshalerForVarType(pThis->m_vt, FALSE);
4350 if (pMarshaler != NULL && pMarshaler->ClearOleArray != NULL)
4352 pMarshaler->ClearOleArray(*pNativeHome, cElements, pThis->m_pElementMT);
4357 #endif // CROSSGEN_COMPILE
4360 #ifdef FEATURE_COMINTEROP
4361 void ILSafeArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
4363 STANDARD_VM_CONTRACT;
4365 m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4367 pslILEmit->EmitLDC(sizeof(MngdSafeArrayMarshaler));
4368 pslILEmit->EmitLOCALLOC();
4369 pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
4371 CREATE_MARSHALER_CARRAY_OPERANDS mops;
4372 m_pargs->m_pMarshalInfo->GetMops(&mops);
4374 DWORD dwFlags = mops.elementType;
4377 if (NeedsCheckForStatic())
4379 fStatic |= MngdSafeArrayMarshaler::SCSF_CheckForStatic;
4382 if (!IsCLRToNative(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
4384 // Unmanaged->managed in/out is the only case where we expect the native buffer to contain valid data.
4385 fStatic |= MngdSafeArrayMarshaler::SCSF_NativeDataValid;
4388 dwFlags |= fStatic << 16;
4389 dwFlags |= ((BYTE)!!m_pargs->m_pMarshalInfo->GetNoLowerBounds()) << 24;
4391 pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
4392 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(mops.methodTable));
4393 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
4394 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetArrayRank());
4395 pslILEmit->EmitLDC(dwFlags);
4397 pslILEmit->EmitCALL(METHOD__MNGD_SAFE_ARRAY_MARSHALER__CREATE_MARSHALER, 4, 0);
4400 void ILSafeArrayMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
4402 STANDARD_VM_CONTRACT;
4404 ILMngdMarshaler::EmitConvertContentsNativeToCLR(pslILEmit);
4406 if (NeedsCheckForStatic())
4408 CONSISTENCY_CHECK(-1 == m_dwOriginalManagedLocalNum);
4409 m_dwOriginalManagedLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_OBJECT);
4410 EmitLoadManagedValue(pslILEmit);
4411 pslILEmit->EmitSTLOC(m_dwOriginalManagedLocalNum);
4415 void ILSafeArrayMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
4417 STANDARD_VM_CONTRACT;
4419 EmitLoadMngdMarshaler(pslILEmit);
4420 EmitLoadManagedHomeAddr(pslILEmit);
4421 EmitLoadNativeHomeAddr(pslILEmit);
4422 if (NeedsCheckForStatic())
4424 CONSISTENCY_CHECK(-1 != m_dwOriginalManagedLocalNum);
4425 pslILEmit->EmitLDLOC(m_dwOriginalManagedLocalNum);
4429 pslILEmit->EmitLDNULL();
4431 pslILEmit->EmitCALL(METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE, 4, 0);
4435 #ifndef CROSSGEN_COMPILE
4437 FCIMPL4(void, MngdSafeArrayMarshaler::CreateMarshaler, MngdSafeArrayMarshaler* pThis, MethodTable* pMT, UINT32 iRank, UINT32 dwFlags)
4441 pThis->m_pElementMT = pMT;
4442 pThis->m_iRank = iRank;
4443 pThis->m_vt = (VARTYPE)dwFlags;
4444 pThis->m_fStatic = (BYTE)(dwFlags >> 16);
4445 pThis->m_nolowerbounds = (BYTE)(dwFlags >> 24);
4449 FCIMPL3(void, MngdSafeArrayMarshaler::ConvertSpaceToNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4453 if (pThis->m_fStatic & SCSF_IsStatic)
4456 HELPER_METHOD_FRAME_BEGIN_0();
4463 PRECONDITION(pThis->m_vt != VT_EMPTY);
4464 PRECONDITION(CheckPointer(pThis->m_pElementMT));
4468 if (*pManagedHome != NULL)
4470 *pNativeHome = (void *) OleVariant::CreateSafeArrayForArrayRef((BASEARRAYREF*) pManagedHome, pThis->m_vt, pThis->m_pElementMT);
4474 *pNativeHome = NULL;
4477 HELPER_METHOD_FRAME_END();
4481 FCIMPL4(void, MngdSafeArrayMarshaler::ConvertContentsToNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, Object* pOriginalManagedUNSAFE)
4486 PRECONDITION(pThis->m_vt != VT_EMPTY);
4487 PRECONDITION(CheckPointer(pThis->m_pElementMT));
4491 OBJECTREF pOriginalManaged = ObjectToOBJECTREF(pOriginalManagedUNSAFE);
4492 HELPER_METHOD_FRAME_BEGIN_1(pOriginalManaged);
4494 if ((pThis->m_fStatic & SCSF_IsStatic) &&
4495 (*pManagedHome != pOriginalManaged))
4497 COMPlusThrow(kInvalidOperationException, IDS_INVALID_REDIM);
4500 if (*pManagedHome != NULL)
4502 OleVariant::MarshalSafeArrayForArrayRef((BASEARRAYREF *) pManagedHome,
4503 (SAFEARRAY*)*pNativeHome,
4505 pThis->m_pElementMT,
4506 (pThis->m_fStatic & SCSF_NativeDataValid));
4509 HELPER_METHOD_FRAME_END();
4513 FCIMPL3(void, MngdSafeArrayMarshaler::ConvertSpaceToManaged, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4518 PRECONDITION(pThis->m_vt != VT_EMPTY);
4519 PRECONDITION(CheckPointer(pThis->m_pElementMT));
4523 HELPER_METHOD_FRAME_BEGIN_0();
4525 if (*pNativeHome != NULL)
4527 // If the managed array has a rank defined then make sure the rank of the
4528 // SafeArray matches the defined rank.
4529 if (pThis->m_iRank != -1)
4531 int iSafeArrayRank = SafeArrayGetDim((SAFEARRAY*) *pNativeHome);
4532 if (pThis->m_iRank != iSafeArrayRank)
4534 WCHAR strExpectedRank[64];
4535 WCHAR strActualRank[64];
4536 _ltow_s(pThis->m_iRank, strExpectedRank, COUNTOF(strExpectedRank), 10);
4537 _ltow_s(iSafeArrayRank, strActualRank, COUNTOF(strActualRank), 10);
4538 COMPlusThrow(kSafeArrayRankMismatchException, IDS_EE_SAFEARRAYRANKMISMATCH, strActualRank, strExpectedRank);
4542 if (pThis->m_nolowerbounds)
4545 if ( (SafeArrayGetDim( (SAFEARRAY*)*pNativeHome ) != 1) ||
4546 (FAILED(SafeArrayGetLBound( (SAFEARRAY*)*pNativeHome, 1, &lowerbound))) ||
4549 COMPlusThrow(kSafeArrayRankMismatchException, IDS_EE_SAFEARRAYSZARRAYMISMATCH);
4553 SetObjectReference(pManagedHome,
4554 (OBJECTREF) OleVariant::CreateArrayRefForSafeArray((SAFEARRAY*) *pNativeHome,
4556 pThis->m_pElementMT), GetAppDomain());
4560 SetObjectReference(pManagedHome, NULL, GetAppDomain());
4563 HELPER_METHOD_FRAME_END();
4567 FCIMPL3(void, MngdSafeArrayMarshaler::ConvertContentsToManaged, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4572 PRECONDITION(pThis->m_vt != VT_EMPTY);
4573 PRECONDITION(CheckPointer(pThis->m_pElementMT));
4577 SAFEARRAY* pNative = *(SAFEARRAY**)pNativeHome;
4578 HELPER_METHOD_FRAME_BEGIN_0();
4580 if (pNative && pNative->fFeatures & FADF_STATIC)
4582 pThis->m_fStatic |= SCSF_IsStatic;
4585 if (*pNativeHome != NULL)
4587 OleVariant::MarshalArrayRefForSafeArray((SAFEARRAY*)*pNativeHome,
4588 (BASEARRAYREF *) pManagedHome,
4590 pThis->m_pElementMT);
4593 HELPER_METHOD_FRAME_END();
4597 FCIMPL3(void, MngdSafeArrayMarshaler::ClearNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4601 if (pThis->m_fStatic & SCSF_IsStatic)
4604 HELPER_METHOD_FRAME_BEGIN_0();
4606 if (*pNativeHome != NULL)
4609 _ASSERTE(GetModuleHandleA("oleaut32.dll") != NULL);
4610 // SafeArray has been created. Oleaut32.dll must have been loaded.
4611 CONTRACT_VIOLATION(ThrowsViolation);
4612 SafeArrayDestroy((SAFEARRAY*)*pNativeHome);
4615 HELPER_METHOD_FRAME_END();
4619 #endif // CROSSGEN_COMPILE
4622 LocalDesc ILHiddenLengthArrayMarshaler::GetNativeType()
4624 LIMITED_METHOD_CONTRACT;
4625 return LocalDesc(ELEMENT_TYPE_I);
4628 LocalDesc ILHiddenLengthArrayMarshaler::GetManagedType()
4630 LIMITED_METHOD_CONTRACT;
4631 return LocalDesc(ELEMENT_TYPE_OBJECT);
4634 void ILHiddenLengthArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
4636 STANDARD_VM_CONTRACT;
4638 if (!CanUsePinnedArray())
4640 m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4642 pslILEmit->EmitLDC(sizeof(MngdHiddenLengthArrayMarshaler));
4643 pslILEmit->EmitLOCALLOC();
4644 pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
4646 MethodTable *pElementMT = m_pargs->m_pMarshalInfo->GetArrayElementTypeHandle().GetMethodTable();
4647 pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
4648 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(pElementMT));
4649 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
4651 pslILEmit->EmitLDC(m_pargs->na.m_cbElementSize);
4652 pslILEmit->EmitLDC(m_pargs->na.m_vt);
4654 pslILEmit->EmitCALL(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CREATE_MARSHALER, 4, 0);
4658 void ILHiddenLengthArrayMarshaler::EmitMarshalArgumentCLRToNative()
4660 STANDARD_VM_CONTRACT;
4662 // If we can pin the array, then do that rather than marshaling it in a more heavy weight way
4663 // Otherwise, fall back to doing a full marshal
4664 if (CanUsePinnedArray())
4666 EmitSetupSigAndDefaultHomesCLRToNative();
4668 LocalDesc managedType = GetManagedType();
4669 managedType.MakePinned();
4670 DWORD dwPinnedLocal = m_pcsMarshal->NewLocal(managedType);
4672 ILCodeLabel* pMarshalDoneLabel = m_pcsMarshal->NewCodeLabel();
4675 m_pcsMarshal->EmitLoadNullPtr();
4676 EmitStoreNativeValue(m_pcsMarshal);
4678 // if (managed == null) goto MarshalDone
4679 EmitLoadManagedValue(m_pcsMarshal);
4680 m_pcsMarshal->EmitBRFALSE(pMarshalDoneLabel);
4682 // pinnedLocal = managed;
4683 EmitLoadManagedValue(m_pcsMarshal);
4684 m_pcsMarshal->EmitSTLOC(dwPinnedLocal);
4686 // native = pinnedLocal + dataOffset
4687 m_pcsMarshal->EmitLDLOC(dwPinnedLocal);
4688 m_pcsMarshal->EmitCONV_I();
4689 m_pcsMarshal->EmitLDC(m_pargs->na.m_optionalbaseoffset);
4690 m_pcsMarshal->EmitADD();
4691 EmitStoreNativeValue(m_pcsMarshal);
4693 if (g_pConfig->InteropLogArguments())
4695 m_pslNDirect->EmitLogNativeArgument(m_pcsMarshal, dwPinnedLocal);
4699 m_pcsMarshal->EmitLabel(pMarshalDoneLabel);
4703 ILMngdMarshaler::EmitMarshalArgumentCLRToNative();
4708 void ILHiddenLengthArrayMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
4710 STANDARD_VM_CONTRACT;
4712 if (!CanUsePinnedArray())
4714 EmitLoadMngdMarshaler(pslILEmit);
4715 EmitLoadManagedHomeAddr(pslILEmit);
4716 EmitLoadNativeHomeAddr(pslILEmit);
4717 EmitLoadNativeArrayLength(pslILEmit);
4719 // MngdHiddenLengthArrayMarshaler::ConvertSpaceToManaged
4720 pslILEmit->EmitCALL(pslILEmit->GetToken(GetConvertSpaceToManagedMethod()), 4, 0);
4724 void ILHiddenLengthArrayMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
4726 STANDARD_VM_CONTRACT;
4728 // If we're marshaling out to native code, then we need to set the length out parameter
4729 if (!IsCLRToNative(m_dwMarshalFlags))
4731 if (IsByref(m_dwMarshalFlags) || IsRetval(m_dwMarshalFlags) || IsOut(m_dwMarshalFlags))
4733 ILCodeLabel *pSkipGetLengthLabel = m_pcsMarshal->NewCodeLabel();
4736 pslILEmit->EmitLDC(0);
4737 pslILEmit->EmitCONV_T(m_pargs->m_pMarshalInfo->GetHiddenLengthParamElementType());
4738 pslILEmit->EmitSTLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
4740 // if (array == null) goto SkipGetLength
4741 EmitLoadManagedValue(pslILEmit);
4742 pslILEmit->EmitBRFALSE(pSkipGetLengthLabel);
4744 // nativeLen = array.Length
4746 EmitLoadManagedValue(pslILEmit);
4747 pslILEmit->EmitLDLEN();
4748 pslILEmit->EmitCONV_T(m_pargs->m_pMarshalInfo->GetHiddenLengthParamElementType());
4749 pslILEmit->EmitSTLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
4750 pslILEmit->EmitLabel(pSkipGetLengthLabel);
4752 // nativeLenParam = nativeLen
4753 LocalDesc nativeParamType(m_pargs->m_pMarshalInfo->GetHiddenLengthParamElementType());
4754 pslILEmit->EmitLDARG(m_pargs->m_pMarshalInfo->HiddenLengthParamIndex());
4755 pslILEmit->EmitLDLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
4756 pslILEmit->EmitSTIND_T(&nativeParamType);
4760 if (!CanUsePinnedArray())
4762 ILMngdMarshaler::EmitConvertSpaceCLRToNative(pslILEmit);
4766 void ILHiddenLengthArrayMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
4768 STANDARD_VM_CONTRACT;
4770 if (!CanUsePinnedArray())
4772 if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE &&
4773 (m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Uri ||
4774 m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs ||
4775 m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs))
4777 // System.Uri/NotifyCollectionChangedEventArgs don't live in mscorlib so there's no marshaling helper to call - inline the loop
4778 DWORD dwLoopCounterLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
4779 DWORD dwNativePtrLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4780 ILCodeLabel *pConditionLabel = pslILEmit->NewCodeLabel();
4781 ILCodeLabel *pLoopBodyLabel = pslILEmit->NewCodeLabel();
4783 // for (IntPtr ptr = pNative, int i = 0; ...
4784 pslILEmit->EmitLDC(0);
4785 pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4786 EmitLoadNativeValue(pslILEmit);
4787 pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4788 pslILEmit->EmitBR(pConditionLabel);
4790 // *ptr = EmitConvertCLR*ToWinRT*(pManaged[i]);
4791 pslILEmit->EmitLabel(pLoopBodyLabel);
4792 pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4793 EmitLoadManagedValue(pslILEmit);
4794 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4795 pslILEmit->EmitLDELEM_REF();
4797 switch (m_pargs->na.m_redirectedTypeIndex)
4799 case WinMDAdapter::RedirectedTypeIndex_System_Uri:
4800 ILUriMarshaler::EmitConvertCLRUriToWinRTUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4803 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
4804 ILNCCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4807 case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
4808 ILPCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4811 default: UNREACHABLE();
4814 pslILEmit->EmitSTIND_I();
4816 // ... i++, ptr += IntPtr.Size ...
4817 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4818 pslILEmit->EmitLDC(1);
4819 pslILEmit->EmitADD();
4820 pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4821 pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4822 pslILEmit->EmitLDC(sizeof(LPVOID));
4823 pslILEmit->EmitADD();
4824 pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4826 // ... i < pManaged.Length; ...
4827 pslILEmit->EmitLabel(pConditionLabel);
4828 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4829 EmitLoadNativeArrayLength(pslILEmit);
4830 pslILEmit->EmitBLT(pLoopBodyLabel);
4834 ILMngdMarshaler::EmitConvertContentsCLRToNative(pslILEmit);
4839 void ILHiddenLengthArrayMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
4841 STANDARD_VM_CONTRACT;
4843 if (!CanUsePinnedArray())
4845 if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE &&
4846 (m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Uri ||
4847 m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs ||
4848 m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs))
4850 // System.Uri/NotifyCollectionChangedEventArgs don't live in mscorlib so there's no marshaling helper to call - inline the loop
4851 DWORD dwLoopCounterLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
4852 DWORD dwNativePtrLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4853 ILCodeLabel *pConditionLabel = pslILEmit->NewCodeLabel();
4854 ILCodeLabel *pLoopBodyLabel = pslILEmit->NewCodeLabel();
4856 // for (IntPtr ptr = pNative, int i = 0; ...
4857 pslILEmit->EmitLDC(0);
4858 pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4859 EmitLoadNativeValue(pslILEmit);
4860 pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4861 pslILEmit->EmitBR(pConditionLabel);
4863 // pManaged[i] = EmitConvertWinRT*ToCLR*(*ptr);
4864 pslILEmit->EmitLabel(pLoopBodyLabel);
4865 EmitLoadManagedValue(pslILEmit);
4866 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4867 pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4868 pslILEmit->EmitLDIND_I();
4870 switch (m_pargs->na.m_redirectedTypeIndex)
4872 case WinMDAdapter::RedirectedTypeIndex_System_Uri:
4873 ILUriMarshaler::EmitConvertWinRTUriToCLRUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4876 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
4877 ILNCCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4880 case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
4881 ILPCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4884 default: UNREACHABLE();
4887 pslILEmit->EmitSTELEM_REF();
4889 // ... i++, ptr += IntPtr.Size)
4890 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4891 pslILEmit->EmitLDC(1);
4892 pslILEmit->EmitADD();
4893 pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4894 pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4895 pslILEmit->EmitLDC(sizeof(LPVOID));
4896 pslILEmit->EmitADD();
4897 pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4899 // ... i < pManaged.Length; ...
4900 pslILEmit->EmitLabel(pConditionLabel);
4901 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4902 EmitLoadNativeArrayLength(pslILEmit);
4903 pslILEmit->EmitBLT(pLoopBodyLabel);
4907 ILMngdMarshaler::EmitConvertContentsNativeToCLR(pslILEmit);
4912 void ILHiddenLengthArrayMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
4914 STANDARD_VM_CONTRACT;
4916 EmitClearNativeContents(pslILEmit);
4918 if (!CanUsePinnedArray())
4920 EmitLoadNativeValue(pslILEmit);
4921 pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeMethod()), 1, 0);
4925 void ILHiddenLengthArrayMarshaler::EmitClearNativeContents(ILCodeStream* pslILEmit)
4927 STANDARD_VM_CONTRACT;
4929 if (!CanUsePinnedArray())
4931 MethodDesc *pMD = GetClearNativeContentsMethod();
4935 UINT numArgs = sig.NumFixedArgs();
4939 EmitLoadMngdMarshaler(pslILEmit);
4943 _ASSERTE(numArgs == 2);
4946 EmitLoadNativeHomeAddr(pslILEmit);
4947 EmitLoadNativeArrayLength(pslILEmit);
4948 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), numArgs, 0);
4953 // Determine if we can simply pin the managed array, rather than doing a full marshal
4954 bool ILHiddenLengthArrayMarshaler::CanUsePinnedArray()
4956 STANDARD_VM_CONTRACT;
4958 // If the array is only going from managed to native, and it contains only blittable data, and
4959 // we know where that data is located in the array then we can take the fast path
4960 if (!IsCLRToNative(m_dwMarshalFlags))
4965 if (m_pargs->na.m_vt != VTHACK_BLITTABLERECORD)
4970 if (IsByref(m_dwMarshalFlags))
4975 if (!IsIn(m_dwMarshalFlags))
4980 if (IsRetval(m_dwMarshalFlags))
4985 if (m_pargs->na.m_optionalbaseoffset == 0)
4993 void ILHiddenLengthArrayMarshaler::EmitLoadNativeArrayLength(ILCodeStream *pslILEmit)
4995 STANDARD_VM_CONTRACT;
4997 // For return values, the native length won't yet be marshaled back to its managed home
4998 // so it needs to be read directly
4999 if (IsRetval(m_dwMarshalFlags))
5001 pslILEmit->EmitLDLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
5005 pslILEmit->EmitLDLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthManagedHome());
5008 pslILEmit->EmitCONV_OVF_I4();
5011 MethodDesc *ILHiddenLengthArrayMarshaler::GetConvertContentsToManagedMethod()
5013 STANDARD_VM_CONTRACT;
5015 if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE)
5017 switch (m_pargs->na.m_redirectedTypeIndex)
5019 case WinMDAdapter::RedirectedTypeIndex_System_DateTimeOffset:
5020 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_DATETIME);
5022 case WinMDAdapter::RedirectedTypeIndex_System_Type:
5023 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_TYPE);
5025 case WinMDAdapter::RedirectedTypeIndex_System_Exception:
5026 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_EXCEPTION);
5028 case WinMDAdapter::RedirectedTypeIndex_System_Nullable:
5030 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_NULLABLE);
5031 return GetExactMarshalerMethod(pMD);
5034 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_KeyValuePair:
5036 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_KEYVALUEPAIR);
5037 return GetExactMarshalerMethod(pMD);
5041 UNREACHABLE_MSG("Unrecognized redirected type.");
5044 return ILMngdMarshaler::GetConvertContentsToManagedMethod();
5047 MethodDesc *ILHiddenLengthArrayMarshaler::GetConvertContentsToNativeMethod()
5049 STANDARD_VM_CONTRACT;
5051 if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE)
5053 switch (m_pargs->na.m_redirectedTypeIndex)
5055 case WinMDAdapter::RedirectedTypeIndex_System_DateTimeOffset:
5056 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_DATETIME);
5058 case WinMDAdapter::RedirectedTypeIndex_System_Type:
5059 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_TYPE);
5061 case WinMDAdapter::RedirectedTypeIndex_System_Exception:
5062 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_EXCEPTION);
5064 case WinMDAdapter::RedirectedTypeIndex_System_Nullable:
5066 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_NULLABLE);
5067 return GetExactMarshalerMethod(pMD);
5070 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_KeyValuePair:
5072 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_KEYVALUEPAIR);
5073 return GetExactMarshalerMethod(pMD);
5077 UNREACHABLE_MSG("Unrecognized redirected type.");
5080 return ILMngdMarshaler::GetConvertContentsToNativeMethod();
5083 MethodDesc *ILHiddenLengthArrayMarshaler::GetClearNativeContentsMethod()
5085 switch (m_pargs->na.m_vt)
5087 // HSTRINGs, interface pointers, and non-blittable structs need contents cleanup
5088 case VTHACK_HSTRING:
5089 case VTHACK_INSPECTABLE:
5090 case VTHACK_NONBLITTABLERECORD:
5093 // blittable structs don't need contents cleanup
5094 case VTHACK_BLITTABLERECORD:
5097 case VTHACK_REDIRECTEDTYPE:
5099 switch (m_pargs->na.m_redirectedTypeIndex)
5101 // System.Type, Uri, Nullable, KeyValuePair, NCCEventArgs, and PCEventArgs need cleanup
5102 case WinMDAdapter::RedirectedTypeIndex_System_Type:
5103 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CLEAR_NATIVE_CONTENTS_TYPE);
5105 case WinMDAdapter::RedirectedTypeIndex_System_Uri:
5106 case WinMDAdapter::RedirectedTypeIndex_System_Nullable:
5107 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_KeyValuePair:
5108 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
5109 case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
5112 // other redirected types don't
5120 UNREACHABLE_MSG("Unexpected hidden-length array element VT");
5123 return ILMngdMarshaler::GetClearNativeContentsMethod();
5126 MethodDesc *ILHiddenLengthArrayMarshaler::GetExactMarshalerMethod(MethodDesc *pGenericMD)
5128 STANDARD_VM_CONTRACT;
5130 return MethodDesc::FindOrCreateAssociatedMethodDesc(
5132 pGenericMD->GetMethodTable(),
5133 FALSE, // forceBoxedEntryPoint
5134 m_pargs->na.m_pMT->GetInstantiation(), // methodInst
5135 FALSE, // allowInstParam
5136 TRUE); // forceRemotableMethod
5139 #ifndef CROSSGEN_COMPILE
5141 FCIMPL4(void, MngdHiddenLengthArrayMarshaler::CreateMarshaler, MngdHiddenLengthArrayMarshaler* pThis, MethodTable* pMT, SIZE_T cbElementSize, UINT16 vt)
5145 pThis->m_pElementMT = pMT;
5146 pThis->m_cbElementSize = cbElementSize;
5147 pThis->m_vt = (VARTYPE)vt;
5151 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ConvertSpaceToNative, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5155 BASEARRAYREF arrayRef = (BASEARRAYREF) *pManagedHome;
5156 HELPER_METHOD_FRAME_BEGIN_1(arrayRef);
5158 if (arrayRef == NULL)
5160 *pNativeHome = NULL;
5164 SIZE_T cbArray = pThis->GetArraySize(arrayRef->GetNumComponents());
5166 *pNativeHome = CoTaskMemAlloc(cbArray);
5167 if (*pNativeHome == NULL)
5172 // initialize the array
5173 FillMemory(*pNativeHome, cbArray, 0);
5176 HELPER_METHOD_FRAME_END();
5180 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ConvertContentsToNative, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5186 PTRARRAYREF arrayRef;
5187 STRINGREF currentStringRef;
5188 OBJECTREF currentObjectRef;
5191 ZeroMemory(&gc, sizeof(gc));
5192 gc.arrayRef = (PTRARRAYREF)*pManagedHome;
5194 HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
5196 if (gc.arrayRef != NULL)
5198 // There are these choices:
5199 // * the array is made up of entirely blittable data, in which case we can directly copy it,
5200 // * it is an array of strings that need to be marshaled as HSTRING,
5201 // * it is an array of non-blittable structures
5202 // * it is an array of interface pointers (interface, runtime class, delegate, System.Object)
5203 switch (pThis->m_vt)
5205 case VTHACK_BLITTABLERECORD:
5207 // Just do a raw memcpy into the array
5208 SIZE_T cbArray = pThis->GetArraySize(gc.arrayRef->GetNumComponents());
5209 memcpyNoGCRefs(*pNativeHome, gc.arrayRef->GetDataPtr(), cbArray);
5213 case VTHACK_HSTRING:
5215 // Marshal a string array as an array of HSTRINGs
5216 if (!WinRTSupported())
5218 COMPlusThrow(kPlatformNotSupportedException, W("PlatformNotSupported_WinRT"));
5221 HSTRING *pDestinationStrings = reinterpret_cast<HSTRING *>(*pNativeHome);
5223 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5225 gc.currentStringRef = (STRINGREF)gc.arrayRef->GetAt(i);
5226 if (gc.currentStringRef == NULL)
5228 StackSString ssIndex;
5229 ssIndex.Printf(W("%d"), i);
5230 COMPlusThrow(kMarshalDirectiveException, IDS_EE_BADMARSHALARRAY_NULL_HSTRING, ssIndex.GetUnicode());
5233 IfFailThrow(WindowsCreateString(gc.currentStringRef->GetBuffer(), gc.currentStringRef->GetStringLength(), &(pDestinationStrings[i])));
5238 case VTHACK_NONBLITTABLERECORD:
5240 BYTE *pNativeStart = reinterpret_cast<BYTE *>(*pNativeHome);
5241 SIZE_T managedOffset = ArrayBase::GetDataPtrOffset(gc.arrayRef->GetMethodTable());
5242 SIZE_T nativeOffset = 0;
5243 SIZE_T managedSize = gc.arrayRef->GetComponentSize();
5244 SIZE_T nativeSize = pThis->m_pElementMT->GetNativeSize();
5245 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5247 LayoutUpdateNative(reinterpret_cast<LPVOID *>(&gc.arrayRef), managedOffset, pThis->m_pElementMT, pNativeStart + nativeOffset, NULL);
5248 managedOffset += managedSize;
5249 nativeOffset += nativeSize;
5254 case VTHACK_INSPECTABLE:
5256 // interface pointers
5257 IUnknown **pDestinationIPs = reinterpret_cast<IUnknown **>(*pNativeHome);
5259 // If this turns out to be a perf issue, we can precompute the ItfMarshalInfo
5260 // and generate code that passes it to the marshaler at creation time.
5261 ItfMarshalInfo itfInfo;
5262 MarshalInfo::GetItfMarshalInfo(TypeHandle(pThis->m_pElementMT), TypeHandle(), FALSE, TRUE, MarshalInfo::MARSHAL_SCENARIO_WINRT, &itfInfo);
5264 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5266 gc.currentObjectRef = gc.arrayRef->GetAt(i);
5267 pDestinationIPs[i] = MarshalObjectToInterface(
5268 &gc.currentObjectRef,
5269 itfInfo.thNativeItf.GetMethodTable(),
5270 itfInfo.thClass.GetMethodTable(),
5277 UNREACHABLE_MSG("Unrecognized array element VARTYPE");
5281 HELPER_METHOD_FRAME_END();
5285 FCIMPL4(void, MngdHiddenLengthArrayMarshaler::ConvertSpaceToManaged, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements)
5289 HELPER_METHOD_FRAME_BEGIN_0();
5291 if (*pNativeHome == NULL)
5293 SetObjectReference(pManagedHome, NULL, GetAppDomain());
5297 TypeHandle elementType(pThis->m_pElementMT);
5298 TypeHandle arrayType = ClassLoader::LoadArrayTypeThrowing(elementType);
5299 SetObjectReference(pManagedHome, AllocateArrayEx(arrayType, &cElements, 1), GetAppDomain());
5302 HELPER_METHOD_FRAME_END();
5306 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ConvertContentsToManaged, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5312 PTRARRAYREF arrayRef;
5313 STRINGREF stringRef;
5314 OBJECTREF objectRef;
5317 ZeroMemory(&gc, sizeof(gc));
5318 gc.arrayRef = (PTRARRAYREF)*pManagedHome;
5320 HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
5322 if (*pNativeHome != NULL)
5324 // There are these choices:
5325 // * the array is made up of entirely blittable data, in which case we can directly copy it,
5326 // * it is an array of strings that need to be marshaled as HSTRING,
5327 // * it is an array of non-blittable structures
5328 // * it is an array of interface pointers (interface, runtime class, delegate, System.Object)
5329 switch (pThis->m_vt)
5331 case VTHACK_BLITTABLERECORD:
5333 // Just do a raw memcpy into the array
5334 SIZE_T cbArray = pThis->GetArraySize(gc.arrayRef->GetNumComponents());
5335 memcpyNoGCRefs(gc.arrayRef->GetDataPtr(), *pNativeHome, cbArray);
5339 case VTHACK_HSTRING:
5341 // Strings are in HSRING format on the native side
5342 if (!WinRTSupported())
5344 COMPlusThrow(kPlatformNotSupportedException, W("PlatformNotSupported_WinRT"));
5347 HSTRING *pSourceStrings = reinterpret_cast<HSTRING *>(*pNativeHome);
5349 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5351 // NULL HSTRINGS are equivilent to empty strings
5352 UINT32 cchString = 0;
5353 LPCWSTR pwszString = W("");
5355 if (pSourceStrings[i] != NULL)
5357 pwszString = WindowsGetStringRawBuffer(pSourceStrings[i], &cchString);
5360 gc.stringRef = StringObject::NewString(pwszString, cchString);
5361 gc.arrayRef->SetAt(i, gc.stringRef);
5366 case VTHACK_NONBLITTABLERECORD:
5368 // Defer to the field marshaler to handle structures
5369 BYTE *pNativeStart = reinterpret_cast<BYTE *>(*pNativeHome);
5370 SIZE_T managedOffset = ArrayBase::GetDataPtrOffset(gc.arrayRef->GetMethodTable());
5371 SIZE_T nativeOffset = 0;
5372 SIZE_T managedSize = gc.arrayRef->GetComponentSize();
5373 SIZE_T nativeSize = pThis->m_pElementMT->GetNativeSize();
5374 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5376 LayoutUpdateCLR(reinterpret_cast<LPVOID *>(&gc.arrayRef), managedOffset, pThis->m_pElementMT, pNativeStart + nativeOffset);
5377 managedOffset += managedSize;
5378 nativeOffset += nativeSize;
5383 case VTHACK_INSPECTABLE:
5385 // interface pointers
5386 IUnknown **pSourceIPs = reinterpret_cast<IUnknown **>(*pNativeHome);
5388 // If this turns out to be a perf issue, we can precompute the ItfMarshalInfo
5389 // and generate code that passes it to the marshaler at creation time.
5390 ItfMarshalInfo itfInfo;
5391 MarshalInfo::GetItfMarshalInfo(TypeHandle(pThis->m_pElementMT), TypeHandle(), FALSE, TRUE, MarshalInfo::MARSHAL_SCENARIO_WINRT, &itfInfo);
5393 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5395 gc.objectRef = gc.arrayRef->GetAt(i);
5396 UnmarshalObjectFromInterface(
5399 itfInfo.thItf.GetMethodTable(),
5400 itfInfo.thClass.GetMethodTable(),
5402 gc.arrayRef->SetAt(i, gc.objectRef);
5408 UNREACHABLE_MSG("Unrecognized array element VARTYPE");
5412 HELPER_METHOD_FRAME_END();
5416 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ClearNativeContents, MngdHiddenLengthArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
5420 HELPER_METHOD_FRAME_BEGIN_0();
5422 if (*pNativeHome != NULL)
5424 pThis->DoClearNativeContents(pNativeHome, cElements);
5427 HELPER_METHOD_FRAME_END();
5431 #endif // CROSSGEN_COMPILE
5434 SIZE_T MngdHiddenLengthArrayMarshaler::GetArraySize(SIZE_T elements)
5444 _ASSERTE_MSG(m_cbElementSize != 0, "You have to set the native size for your array element type");
5448 if (!ClrSafeInt<SIZE_T>::multiply(elements, m_cbElementSize, cbArray))
5450 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
5453 // This array size limit is carried over from the equivilent limit for other array marshaling code
5454 if (cbArray > MAX_SIZE_FOR_INTEROP)
5456 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
5462 #ifndef CROSSGEN_COMPILE
5463 void MngdHiddenLengthArrayMarshaler::DoClearNativeContents(void** pNativeHome, INT32 cElements)
5470 PRECONDITION(pNativeHome != NULL);
5475 if (vt == VTHACK_REDIRECTEDTYPE)
5477 // the redirected types that use this helper are interface pointers on the WinRT side
5478 vt = VTHACK_INSPECTABLE;
5483 case VTHACK_HSTRING:
5485 if (WinRTSupported())
5487 HSTRING *pStrings = reinterpret_cast<HSTRING *>(*pNativeHome);
5488 for (INT32 i = 0; i < cElements; ++i)
5490 if (pStrings[i] != NULL)
5492 WindowsDeleteString(pStrings[i]);
5499 case VTHACK_NONBLITTABLERECORD:
5501 SIZE_T cbArray = GetArraySize(cElements);
5502 BYTE *pNativeCurrent = reinterpret_cast<BYTE *>(*pNativeHome);
5503 BYTE *pNativeEnd = pNativeCurrent + cbArray;
5505 while (pNativeCurrent < pNativeEnd)
5507 LayoutDestroyNative(pNativeCurrent, m_pElementMT);
5508 pNativeCurrent += m_pElementMT->GetNativeSize();
5513 case VTHACK_INSPECTABLE:
5515 IInspectable **pIPs = reinterpret_cast<IInspectable **>(*pNativeHome);
5516 for (INT32 i = 0; i < cElements; ++i)
5518 if (pIPs[i] != NULL)
5520 SafeRelease(pIPs[i]);
5527 UNREACHABLE_MSG("Unexpected hidden-length array element VT");
5530 #endif //CROSSGEN_COMPILE
5531 #endif // FEATURE_COMINTEROP
5533 void ILReferenceCustomMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
5538 PRECONDITION(-1 == m_dwMngdMarshalerLocalNum);
5543 // allocate space for marshaler
5546 m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
5548 pslILEmit->EmitLDC(sizeof(MngdRefCustomMarshaler));
5549 pslILEmit->EmitLOCALLOC();
5550 pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
5552 pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum); // arg to CreateMarshaler
5555 // call CreateCustomMarshalerHelper
5558 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(m_pargs->rcm.m_pMD));
5559 pslILEmit->EmitCALL(METHOD__METHOD_HANDLE__GETVALUEINTERNAL, 1, 1);
5561 pslILEmit->EmitLDC(m_pargs->rcm.m_paramToken);
5563 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(TypeHandle::FromPtr(m_pargs->rcm.m_hndManagedType)));
5564 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
5566 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CREATE_CUSTOM_MARSHALER_HELPER, 3, 1); // arg to CreateMarshaler
5569 // call MngdRefCustomMarshaler::CreateMarshaler
5572 pslILEmit->EmitCALL(METHOD__MNGD_REF_CUSTOM_MARSHALER__CREATE_MARSHALER, 2, 0);
5576 #ifndef CROSSGEN_COMPILE
5578 FCIMPL2(void, MngdRefCustomMarshaler::CreateMarshaler, MngdRefCustomMarshaler* pThis, void* pCMHelper)
5582 pThis->m_pCMHelper = (CustomMarshalerHelper*)pCMHelper;
5587 FCIMPL3(void, MngdRefCustomMarshaler::ConvertContentsToNative, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5592 PRECONDITION(CheckPointer(pManagedHome));
5596 HELPER_METHOD_FRAME_BEGIN_0();
5598 *pNativeHome = pThis->m_pCMHelper->InvokeMarshalManagedToNativeMeth(*pManagedHome);
5600 HELPER_METHOD_FRAME_END();
5605 FCIMPL3(void, MngdRefCustomMarshaler::ConvertContentsToManaged, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5610 PRECONDITION(CheckPointer(pManagedHome));
5614 HELPER_METHOD_FRAME_BEGIN_0();
5616 SetObjectReference(pManagedHome, pThis->m_pCMHelper->InvokeMarshalNativeToManagedMeth(*pNativeHome), GetAppDomain());
5618 HELPER_METHOD_FRAME_END();
5622 FCIMPL3(void, MngdRefCustomMarshaler::ClearNative, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5626 HELPER_METHOD_FRAME_BEGIN_0();
5636 pThis->m_pCMHelper->InvokeCleanUpNativeMeth(*pNativeHome);
5638 HELPER_METHOD_FRAME_END();
5642 FCIMPL3(void, MngdRefCustomMarshaler::ClearManaged, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5647 PRECONDITION(CheckPointer(pManagedHome));
5651 HELPER_METHOD_FRAME_BEGIN_0();
5653 pThis->m_pCMHelper->InvokeCleanUpManagedMeth(*pManagedHome);
5655 HELPER_METHOD_FRAME_END();
5659 #endif // CROSSGEN_COMPILE
5662 #ifdef FEATURE_COMINTEROP
5664 ///////////////////////////////////////////////////////////////////////////////////////////////////
5665 // ILUriMarshaler implementation
5666 ///////////////////////////////////////////////////////////////////////////////////////////////////
5668 LocalDesc ILUriMarshaler::GetNativeType()
5670 LIMITED_METHOD_CONTRACT;
5671 return LocalDesc(ELEMENT_TYPE_I);
5674 LocalDesc ILUriMarshaler::GetManagedType()
5676 STANDARD_VM_CONTRACT;;
5677 BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
5678 TypeHandle hndUriType = pDomain->GetMarshalingData()->GetUriMarshalingInfo()->GetSystemUriType();
5680 return LocalDesc(hndUriType); // System.Uri
5683 bool ILUriMarshaler::NeedsClearNative()
5685 LIMITED_METHOD_CONTRACT;
5689 // Note that this method expects the CLR Uri on top of the evaluation stack and leaves the WinRT Uri there.
5691 void ILUriMarshaler::EmitConvertCLRUriToWinRTUri(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5693 STANDARD_VM_CONTRACT;
5695 UriMarshalingInfo* marshalingInfo = pDomain->GetMarshalingData()->GetUriMarshalingInfo();
5697 ILCodeLabel *pNotNullLabel = pslILEmit->NewCodeLabel();
5698 ILCodeLabel *pDoneLabel = pslILEmit->NewCodeLabel();
5700 pslILEmit->EmitDUP();
5701 pslILEmit->EmitBRTRUE(pNotNullLabel);
5703 pslILEmit->EmitPOP();
5704 pslILEmit->EmitLoadNullPtr();
5705 pslILEmit->EmitBR(pDoneLabel);
5707 pslILEmit->EmitLabel(pNotNullLabel);
5709 // System.Uri.get_OriginalString()
5710 MethodDesc* pSystemUriOriginalStringMD = marshalingInfo->GetSystemUriOriginalStringMD();
5711 pslILEmit->EmitCALL(pslILEmit->GetToken(pSystemUriOriginalStringMD), 1, 1);
5713 pslILEmit->EmitCALL(METHOD__URIMARSHALER__CREATE_NATIVE_URI_INSTANCE, 1, 1);
5715 pslILEmit->EmitLabel(pDoneLabel);
5718 void ILUriMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
5720 STANDARD_VM_CONTRACT;
5722 EmitLoadManagedValue(pslILEmit);
5723 EmitConvertCLRUriToWinRTUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5724 EmitStoreNativeValue(pslILEmit);
5727 // Note that this method expects the WinRT Uri on top of the evaluation stack and leaves the CLR Uri there.
5729 void ILUriMarshaler::EmitConvertWinRTUriToCLRUri(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5731 STANDARD_VM_CONTRACT;
5733 MethodDesc* pSystemUriCtorMD = pDomain->GetMarshalingData()->GetUriMarshalingInfo()->GetSystemUriCtorMD();
5735 ILCodeLabel *pNotNullLabel = pslILEmit->NewCodeLabel();
5736 ILCodeLabel *pDoneLabel = pslILEmit->NewCodeLabel();
5738 pslILEmit->EmitDUP();
5739 pslILEmit->EmitBRTRUE(pNotNullLabel);
5741 pslILEmit->EmitPOP();
5742 pslILEmit->EmitLDNULL();
5743 pslILEmit->EmitBR(pDoneLabel);
5745 pslILEmit->EmitLabel(pNotNullLabel);
5747 // string UriMarshaler.GetRawUriFromNative(IntPtr)
5748 pslILEmit->EmitCALL(METHOD__URIMARSHALER__GET_RAWURI_FROM_NATIVE, 1, 1);
5750 // System.Uri..ctor(string)
5751 pslILEmit->EmitNEWOBJ(pslILEmit->GetToken(pSystemUriCtorMD), 1);
5753 pslILEmit->EmitLabel(pDoneLabel);
5756 void ILUriMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5758 STANDARD_VM_CONTRACT;
5760 EmitLoadNativeValue(pslILEmit);
5761 EmitConvertWinRTUriToCLRUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5762 EmitStoreManagedValue(pslILEmit);
5765 void ILUriMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
5767 STANDARD_VM_CONTRACT;
5768 EmitInterfaceClearNative(pslILEmit);
5771 ///////////////////////////////////////////////////////////////////////////////////////////////////
5772 // ILNCCEventArgsMarshaler implementation
5773 ///////////////////////////////////////////////////////////////////////////////////////////////////
5775 LocalDesc ILNCCEventArgsMarshaler::GetNativeType()
5777 LIMITED_METHOD_CONTRACT;
5778 return LocalDesc(ELEMENT_TYPE_I);
5781 LocalDesc ILNCCEventArgsMarshaler::GetManagedType()
5783 STANDARD_VM_CONTRACT;;
5785 BaseDomain *pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
5786 TypeHandle hndNCCEventArgType = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemNCCEventArgsType();
5788 return LocalDesc(hndNCCEventArgType); // System.Collections.Specialized.NotifyCollectionChangedEventArgs
5791 bool ILNCCEventArgsMarshaler::NeedsClearNative()
5793 LIMITED_METHOD_CONTRACT;
5797 // Note that this method expects the CLR NotifyCollectionChangedEventArgs on top of the evaluation stack and
5798 // leaves the WinRT NotifyCollectionChangedEventArgs IP there.
5800 void ILNCCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream *pslILEmit, BaseDomain *pDomain)
5802 STANDARD_VM_CONTRACT;
5804 MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemNCCEventArgsToWinRTNCCEventArgsMD();
5806 // IntPtr System.Runtime.InteropServices.WindowsRuntime.NotifyCollectionChangedEventArgsMarshaler.ConvertToNative(NotifyCollectionChangedEventArgs)
5807 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5810 void ILNCCEventArgsMarshaler::EmitConvertContentsCLRToNative(ILCodeStream *pslILEmit)
5812 STANDARD_VM_CONTRACT;
5814 EmitLoadManagedValue(pslILEmit);
5815 EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5816 EmitStoreNativeValue(pslILEmit);
5819 // Note that this method expects the WinRT NotifyCollectionChangedEventArgs on top of the evaluation stack and
5820 // leaves the CLR NotifyCollectionChangedEventArgs there.
5822 void ILNCCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5824 STANDARD_VM_CONTRACT;
5826 MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetWinRTNCCEventArgsToSystemNCCEventArgsMD();
5828 // NotifyCollectionChangedEventArgs System.Runtime.InteropServices.WindowsRuntime.NotifyCollectionChangedEventArgsMarshaler.ConvertToManaged(IntPtr)
5829 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5832 void ILNCCEventArgsMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5834 STANDARD_VM_CONTRACT;
5836 EmitLoadNativeValue(pslILEmit);
5837 EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5838 EmitStoreManagedValue(pslILEmit);
5841 void ILNCCEventArgsMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
5843 STANDARD_VM_CONTRACT;
5844 EmitInterfaceClearNative(pslILEmit);
5847 ///////////////////////////////////////////////////////////////////////////////////////////////////
5848 // ILPCEventArgsMarshaler implementation
5849 ///////////////////////////////////////////////////////////////////////////////////////////////////
5851 LocalDesc ILPCEventArgsMarshaler::GetNativeType()
5853 LIMITED_METHOD_CONTRACT;
5854 return LocalDesc(ELEMENT_TYPE_I);
5857 LocalDesc ILPCEventArgsMarshaler::GetManagedType()
5859 STANDARD_VM_CONTRACT;;
5861 BaseDomain *pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
5862 TypeHandle hndPCEventArgType = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemPCEventArgsType();
5864 return LocalDesc(hndPCEventArgType); // System.ComponentModel.PropertyChangedEventArgs
5867 bool ILPCEventArgsMarshaler::NeedsClearNative()
5869 LIMITED_METHOD_CONTRACT;
5873 // Note that this method expects the CLR PropertyChangedEventArgs on top of the evaluation stack and
5874 // leaves the WinRT PropertyChangedEventArgs IP there.
5876 void ILPCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream *pslILEmit, BaseDomain *pDomain)
5878 STANDARD_VM_CONTRACT;
5880 MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemPCEventArgsToWinRTPCEventArgsMD();
5882 // IntPtr System.Runtime.InteropServices.WindowsRuntime.PropertyChangedEventArgsMarshaler.ConvertToNative(PropertyChangedEventArgs)
5883 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5886 void ILPCEventArgsMarshaler::EmitConvertContentsCLRToNative(ILCodeStream *pslILEmit)
5888 STANDARD_VM_CONTRACT;
5890 EmitLoadManagedValue(pslILEmit);
5891 EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5892 EmitStoreNativeValue(pslILEmit);
5895 // Note that this method expects the WinRT PropertyChangedEventArgs on top of the evaluation stack and
5896 // leaves the CLR PropertyChangedEventArgs there.
5898 void ILPCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5900 STANDARD_VM_CONTRACT;
5902 MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetWinRTPCEventArgsToSystemPCEventArgsMD();
5904 // PropertyChangedEventArgs System.Runtime.InteropServices.WindowsRuntime.PropertyChangedEventArgsMarshaler.ConvertToManaged(IntPtr)
5905 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5908 void ILPCEventArgsMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5910 STANDARD_VM_CONTRACT;
5912 EmitLoadNativeValue(pslILEmit);
5913 EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5914 EmitStoreManagedValue(pslILEmit);
5917 void ILPCEventArgsMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
5919 STANDARD_VM_CONTRACT;
5920 EmitInterfaceClearNative(pslILEmit);
5923 ///////////////////////////////////////////////////////////////////////////////////////////////////
5924 // ILDateTimeMarshaler implementation
5925 ///////////////////////////////////////////////////////////////////////////////////////////////////
5927 LocalDesc ILDateTimeMarshaler::GetNativeType()
5929 STANDARD_VM_CONTRACT;;
5930 return LocalDesc(MscorlibBinder::GetClass(CLASS__DATETIMENATIVE));
5933 LocalDesc ILDateTimeMarshaler::GetManagedType()
5935 STANDARD_VM_CONTRACT;;
5936 return LocalDesc(MscorlibBinder::GetClass(CLASS__DATE_TIME_OFFSET));
5939 bool ILDateTimeMarshaler::NeedsClearNative()
5941 LIMITED_METHOD_CONTRACT;
5945 void ILDateTimeMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
5950 PRECONDITION(CheckPointer(pslILEmit));
5954 // DateTimeOffsetMarshaler.ConvertManagedToNative(ref managedDTO, out nativeTicks);
5955 EmitLoadManagedHomeAddr(pslILEmit);
5956 EmitLoadNativeHomeAddr(pslILEmit);
5957 pslILEmit->EmitCALL(METHOD__DATETIMEOFFSETMARSHALER__CONVERT_TO_NATIVE, 2, 0);
5960 void ILDateTimeMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5962 STANDARD_VM_CONTRACT;
5964 // DateTimeOffsetMarshaler.ConvertNativeToManaged(out managedLocalDTO, ref nativeTicks);
5965 EmitLoadManagedHomeAddr(pslILEmit);
5966 EmitLoadNativeHomeAddr(pslILEmit);
5967 pslILEmit->EmitCALL(METHOD__DATETIMEOFFSETMARSHALER__CONVERT_TO_MANAGED, 2, 0);
5970 void ILDateTimeMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
5972 STANDARD_VM_CONTRACT;
5974 EmitLoadNativeHomeAddr(pslILEmit);
5975 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__DATETIMENATIVE)));
5978 ///////////////////////////////////////////////////////////////////////////////////////////////////
5979 // ILNullableMarshaler implementation
5980 ///////////////////////////////////////////////////////////////////////////////////////////////////
5982 LocalDesc ILNullableMarshaler::GetNativeType()
5984 LIMITED_METHOD_CONTRACT;
5985 return LocalDesc(ELEMENT_TYPE_I);
5988 LocalDesc ILNullableMarshaler::GetManagedType()
5990 LIMITED_METHOD_CONTRACT;;
5991 return LocalDesc(m_pargs->m_pMT);
5994 bool ILNullableMarshaler::NeedsClearNative()
5996 LIMITED_METHOD_CONTRACT;
6000 void ILNullableMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
6005 PRECONDITION(CheckPointer(pslILEmit));
6009 // pNative = NullableMarshaler<T>.ConvertToNative(ref pManaged);
6010 EmitLoadManagedHomeAddr(pslILEmit);
6012 MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__NULLABLEMARSHALER__CONVERT_TO_NATIVE));
6013 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6015 EmitStoreNativeValue(pslILEmit);
6018 void ILNullableMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
6020 STANDARD_VM_CONTRACT;
6022 // pManaged = NullableMarshaler.ConvertToManaged(pNative);
6023 EmitLoadNativeValue(pslILEmit);
6025 MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__NULLABLEMARSHALER__CONVERT_TO_MANAGED));
6026 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6028 EmitStoreManagedValue(pslILEmit);
6031 void ILNullableMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
6033 STANDARD_VM_CONTRACT;
6034 EmitInterfaceClearNative(pslILEmit);
6037 MethodDesc *ILNullableMarshaler::GetExactMarshalerMethod(MethodDesc *pGenericMD)
6039 STANDARD_VM_CONTRACT;
6041 return MethodDesc::FindOrCreateAssociatedMethodDesc(
6043 pGenericMD->GetMethodTable(),
6044 FALSE, // forceBoxedEntryPoint
6045 m_pargs->m_pMT->GetInstantiation(), // methodInst
6046 FALSE, // allowInstParam
6047 TRUE); // forceRemotableMethod
6050 ///////////////////////////////////////////////////////////////////////////////////////////////////
6051 // ILSystemTypeMarshaler implementation
6052 ///////////////////////////////////////////////////////////////////////////////////////////////////
6054 LocalDesc ILSystemTypeMarshaler::GetNativeType()
6056 STANDARD_VM_CONTRACT;
6058 return LocalDesc(MscorlibBinder::GetClass(CLASS__TYPENAMENATIVE));
6061 LocalDesc ILSystemTypeMarshaler::GetManagedType()
6063 STANDARD_VM_CONTRACT;
6065 return LocalDesc(MscorlibBinder::GetClass(CLASS__TYPE));
6068 bool ILSystemTypeMarshaler::NeedsClearNative()
6070 LIMITED_METHOD_CONTRACT;
6074 void ILSystemTypeMarshaler::EmitConvertContentsCLRToNative(ILCodeStream * pslILEmit)
6076 STANDARD_VM_CONTRACT;
6078 // SystemTypeMarshaler.ConvertToNative(Type, pTypeName);
6079 EmitLoadManagedValue(pslILEmit);
6080 EmitLoadNativeHomeAddr(pslILEmit);
6081 pslILEmit->EmitCALL(METHOD__SYSTEMTYPEMARSHALER__CONVERT_TO_NATIVE, 2, 0);
6084 void ILSystemTypeMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream * pslILEmit)
6086 STANDARD_VM_CONTRACT;
6088 // type = SystemTypeMarshaler.ConvertNativeToManaged(pTypeName, ref Type);
6089 EmitLoadNativeHomeAddr(pslILEmit);
6090 EmitLoadManagedHomeAddr(pslILEmit);
6091 pslILEmit->EmitCALL(METHOD__SYSTEMTYPEMARSHALER__CONVERT_TO_MANAGED, 2, 0);
6095 void ILSystemTypeMarshaler::EmitClearNative(ILCodeStream * pslILEmit)
6097 STANDARD_VM_CONTRACT;
6099 // SystemTypeMarshaler.ClearNative(pTypeName)
6100 EmitLoadNativeHomeAddr(pslILEmit);
6101 pslILEmit->EmitCALL(METHOD__SYSTEMTYPEMARSHALER__CLEAR_NATIVE, 1, 0);
6104 void ILSystemTypeMarshaler::EmitReInitNative(ILCodeStream * pslILEmit)
6106 EmitLoadNativeHomeAddr(pslILEmit);
6107 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__TYPENAMENATIVE)));
6110 ///////////////////////////////////////////////////////////////////////////////////////////////////
6111 // ILHResultExceptionMarshaler implementation
6112 ///////////////////////////////////////////////////////////////////////////////////////////////////
6114 LocalDesc ILHResultExceptionMarshaler::GetNativeType()
6116 LIMITED_METHOD_CONTRACT;
6117 return LocalDesc(ELEMENT_TYPE_I4);
6120 LocalDesc ILHResultExceptionMarshaler::GetManagedType()
6122 LIMITED_METHOD_CONTRACT;
6123 _ASSERTE(m_pargs->m_pMT != NULL);
6124 return LocalDesc(m_pargs->m_pMT);
6127 bool ILHResultExceptionMarshaler::NeedsClearNative()
6129 LIMITED_METHOD_CONTRACT;
6133 void ILHResultExceptionMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
6138 PRECONDITION(CheckPointer(pslILEmit));
6142 // int HResultExceptionMarshaler.ConvertManagedToNative(Exception);
6143 EmitLoadManagedValue(pslILEmit);
6144 pslILEmit->EmitCALL(METHOD__HRESULTEXCEPTIONMARSHALER__CONVERT_TO_NATIVE, 1, 1);
6145 EmitStoreNativeValue(pslILEmit);
6148 void ILHResultExceptionMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
6153 PRECONDITION(CheckPointer(pslILEmit));
6157 // Exception HResultExceptionMarshaler.ConvertNativeToManaged(int hr);
6158 EmitLoadNativeValue(pslILEmit);
6159 pslILEmit->EmitCALL(METHOD__HRESULTEXCEPTIONMARSHALER__CONVERT_TO_MANAGED, 1, 1);
6160 EmitStoreManagedValue(pslILEmit);
6163 ///////////////////////////////////////////////////////////////////////////////////////////////////
6164 // ILKeyValuePairMarshaler implementation
6165 ///////////////////////////////////////////////////////////////////////////////////////////////////
6167 LocalDesc ILKeyValuePairMarshaler::GetNativeType()
6169 LIMITED_METHOD_CONTRACT;
6170 return LocalDesc(ELEMENT_TYPE_I);
6173 LocalDesc ILKeyValuePairMarshaler::GetManagedType()
6175 LIMITED_METHOD_CONTRACT;;
6176 return LocalDesc(m_pargs->m_pMT);
6179 bool ILKeyValuePairMarshaler::NeedsClearNative()
6181 LIMITED_METHOD_CONTRACT;
6185 void ILKeyValuePairMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
6187 STANDARD_VM_CONTRACT;
6189 // Native = KeyValueMarshaler<K, V>.ConvertToNative([In] ref Managed);
6190 EmitLoadManagedHomeAddr(pslILEmit);
6192 MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__KEYVALUEPAIRMARSHALER__CONVERT_TO_NATIVE));
6193 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6195 EmitStoreNativeValue(pslILEmit);
6198 void ILKeyValuePairMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
6200 STANDARD_VM_CONTRACT;
6202 // Managed = KeyValuePairMarshaler<K, V>.ConvertToManaged(Native);
6203 EmitLoadNativeValue(pslILEmit);
6205 MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__KEYVALUEPAIRMARSHALER__CONVERT_TO_MANAGED));
6206 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6208 EmitStoreManagedValue(pslILEmit);
6211 void ILKeyValuePairMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
6213 STANDARD_VM_CONTRACT;
6214 EmitInterfaceClearNative(pslILEmit);
6217 MethodDesc *ILKeyValuePairMarshaler::GetExactMarshalerMethod(MethodDesc *pGenericMD)
6219 STANDARD_VM_CONTRACT;
6221 // KeyValuePairMarshaler methods are generic - find/create the exact method.
6222 return MethodDesc::FindOrCreateAssociatedMethodDesc(
6224 pGenericMD->GetMethodTable(),
6225 FALSE, // forceBoxedEntryPoint
6226 m_pargs->m_pMT->GetInstantiation(), // methodInst
6227 FALSE, // allowInstParam
6228 TRUE); // forceRemotableMethod
6231 #endif // FEATURE_COMINTEROP