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 pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
320 pslILEmit->EmitLDC(1);
321 pslILEmit->EmitADD();
322 pslILEmit->EmitDUP();
323 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
324 pslILEmit->EmitDUP();
325 pslILEmit->EmitADD(); // (length+1) * sizeof(WCHAR)
328 void ILWSTRMarshaler::EmitConvertSpaceAndContentsCLRToNative(ILCodeStream* pslILEmit)
330 STANDARD_VM_CONTRACT;
332 INDEBUG(m_fCoMemoryAllocated = true);
334 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
335 DWORD dwLengthLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
337 pslILEmit->EmitLoadNullPtr();
338 EmitStoreNativeValue(pslILEmit);
340 EmitLoadManagedValue(pslILEmit);
341 pslILEmit->EmitBRFALSE(pNullRefLabel);
343 EmitLoadManagedValue(pslILEmit);
344 EmitCheckManagedStringLength(pslILEmit);
348 pslILEmit->EmitDUP();
349 pslILEmit->EmitSTLOC(dwLengthLocalNum);
353 // static IntPtr AllocCoTaskMem(int cb)
354 pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
355 EmitStoreNativeValue(pslILEmit);
357 EmitLoadManagedValue(pslILEmit);
358 EmitLoadNativeValue(pslILEmit);
362 pslILEmit->EmitLDLOC(dwLengthLocalNum); // length
364 // static void System.String.InternalCopy(String src, IntPtr dest,int len)
365 pslILEmit->EmitCALL(METHOD__STRING__INTERNAL_COPY, 3, 0);
366 pslILEmit->EmitLabel(pNullRefLabel);
369 void ILWSTRMarshaler::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
371 STANDARD_VM_CONTRACT;
373 if (CanUsePinnedManagedString(m_dwMarshalFlags))
375 LocalDesc locDesc = GetManagedType();
376 locDesc.MakePinned();
377 DWORD dwPinnedLocal = pslILEmit->NewLocal(locDesc);
378 int fieldDef = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__STRING__M_FIRST_CHAR));
379 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
381 pslILEmit->EmitLoadNullPtr();
382 EmitStoreNativeValue(pslILEmit);
384 EmitLoadManagedValue(pslILEmit);
385 pslILEmit->EmitBRFALSE(pNullRefLabel);
387 EmitLoadManagedValue(pslILEmit);
388 pslILEmit->EmitSTLOC(dwPinnedLocal);
389 pslILEmit->EmitLDLOC(dwPinnedLocal);
390 pslILEmit->EmitLDFLDA(fieldDef);
391 EmitStoreNativeValue(pslILEmit);
393 if (g_pConfig->InteropLogArguments())
395 m_pslNDirect->EmitLogNativeArgument(pslILEmit, dwPinnedLocal);
398 pslILEmit->EmitLabel(pNullRefLabel);
403 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
404 DWORD dwLengthLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
406 pslILEmit->EmitLoadNullPtr();
407 EmitStoreNativeValue(pslILEmit);
409 EmitLoadManagedValue(pslILEmit);
410 pslILEmit->EmitBRFALSE(pNullRefLabel);
412 EmitLoadManagedValue(pslILEmit);
413 EmitCheckManagedStringLength(pslILEmit);
417 pslILEmit->EmitDUP();
418 pslILEmit->EmitSTLOC(dwLengthLocalNum);
422 pslILEmit->EmitLOCALLOC(); // @TODO: add a non-localloc path for large strings
423 EmitStoreNativeValue(pslILEmit);
425 EmitLoadManagedValue(pslILEmit);
426 EmitLoadNativeValue(pslILEmit);
430 pslILEmit->EmitLDLOC(dwLengthLocalNum); // length
432 // static void System.String.InternalCopy(String src, IntPtr dest,int len)
433 pslILEmit->EmitCALL(METHOD__STRING__INTERNAL_COPY, 3, 0);
434 pslILEmit->EmitLabel(pNullRefLabel);
439 // input stack: 0: native string
440 // output stack: 0: num chars, no null
442 void ILWSTRMarshaler::EmitCheckNativeStringLength(ILCodeStream* pslILEmit)
444 STANDARD_VM_CONTRACT;
446 pslILEmit->EmitCALL(METHOD__STRING__WCSLEN, 1, 1);
447 pslILEmit->EmitDUP();
448 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
451 void ILWSTRMarshaler::EmitConvertSpaceAndContentsNativeToCLR(ILCodeStream* pslILEmit)
453 STANDARD_VM_CONTRACT;
455 ILCodeLabel* pIsNullLabelByref = pslILEmit->NewCodeLabel();
457 EmitLoadNativeValue(pslILEmit);
458 pslILEmit->EmitBRFALSE(pIsNullLabelByref);
460 EmitLoadNativeValue(pslILEmit);
461 pslILEmit->EmitDUP();
462 EmitCheckNativeStringLength(pslILEmit);
463 pslILEmit->EmitPOP(); // pop num chars
465 pslILEmit->EmitNEWOBJ(METHOD__STRING__CTOR_CHARPTR, 1);
466 EmitStoreManagedValue(pslILEmit);
468 pslILEmit->EmitLabel(pIsNullLabelByref);
472 LocalDesc ILOptimizedAllocMarshaler::GetNativeType()
474 LIMITED_METHOD_CONTRACT;
475 return LocalDesc(ELEMENT_TYPE_I);
478 bool ILOptimizedAllocMarshaler::NeedsClearNative()
480 LIMITED_METHOD_CONTRACT;
484 void ILOptimizedAllocMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
486 STANDARD_VM_CONTRACT;
488 ILCodeLabel *pOptimize = NULL;
490 if (m_dwLocalBuffer != LOCAL_NUM_UNUSED)
492 pOptimize = pslILEmit->NewCodeLabel();
494 // if (m_dwLocalBuffer) goto Optimize
495 pslILEmit->EmitLDLOC(m_dwLocalBuffer);
496 pslILEmit->EmitBRTRUE(pOptimize);
499 EmitLoadNativeValue(pslILEmit);
500 // static void m_idClearNative(IntPtr ptr)
501 pslILEmit->EmitCALL(m_idClearNative, 1, 0);
504 if (m_dwLocalBuffer != LOCAL_NUM_UNUSED)
506 pslILEmit->EmitLabel(pOptimize);
510 LocalDesc ILUTF8BufferMarshaler::GetManagedType()
512 STANDARD_VM_CONTRACT;
513 return LocalDesc(MscorlibBinder::GetClass(CLASS__STRING_BUILDER));
516 void ILUTF8BufferMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
518 STANDARD_VM_CONTRACT;
520 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
522 pslILEmit->EmitLoadNullPtr();
523 EmitStoreNativeValue(pslILEmit);
525 EmitLoadManagedValue(pslILEmit);
526 pslILEmit->EmitBRFALSE(pNullRefLabel);
528 EmitLoadManagedValue(pslILEmit);
529 // int System.Text.StringBuilder.get_Capacity()
530 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__GET_CAPACITY, 1, 1);
531 pslILEmit->EmitDUP();
533 // static void StubHelpers.CheckStringLength(int length)
534 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
536 // Max number of bytes for UTF8 string in BMP plane is ( StringBuilder.Capacity + 1 ) * 3 + 1
537 // first +1 if the high surrogate is '?' and second +1 for null byte.
539 // stack: capacity_in_bytes
540 pslILEmit->EmitLDC(1);
541 pslILEmit->EmitADD();
544 pslILEmit->EmitLDC(3);
545 pslILEmit->EmitMUL();
547 // stack: offset_of_null
548 DWORD dwTmpOffsetOfSecretNull = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
549 pslILEmit->EmitDUP();
550 pslILEmit->EmitSTLOC(dwTmpOffsetOfSecretNull); // make sure the stack is empty for localloc
552 // make space for '\0'
553 pslILEmit->EmitLDC(1);
554 pslILEmit->EmitADD();
556 // stack: alloc_size_in_bytes
557 ILCodeLabel *pAllocRejoin = pslILEmit->NewCodeLabel();
558 if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags))
560 ILCodeLabel *pNoOptimize = pslILEmit->NewCodeLabel();
561 m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
564 pslILEmit->EmitLoadNullPtr();
565 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
567 // if (alloc_size_in_bytes > MAX_LOCAL_BUFFER_LENGTH) goto NoOptimize
568 pslILEmit->EmitDUP();
569 pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
570 pslILEmit->EmitCGT_UN();
571 pslILEmit->EmitBRTRUE(pNoOptimize);
573 pslILEmit->EmitLOCALLOC();
574 pslILEmit->EmitDUP();
575 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
576 pslILEmit->EmitBR(pAllocRejoin);
578 pslILEmit->EmitLabel(pNoOptimize);
581 // static IntPtr AllocCoTaskMem(int cb)
582 pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
584 pslILEmit->EmitLabel(pAllocRejoin);
586 // stack: native_addr
588 pslILEmit->EmitDUP();
589 EmitStoreNativeValue(pslILEmit);
591 pslILEmit->EmitLDLOC(dwTmpOffsetOfSecretNull);
593 // stack: native_addr offset_of_null
594 pslILEmit->EmitADD();
596 // stack: addr_of_null0
597 pslILEmit->EmitLDC(0);
598 pslILEmit->EmitSTIND_I1();
600 pslILEmit->EmitLabel(pNullRefLabel);
603 void ILUTF8BufferMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
605 STANDARD_VM_CONTRACT;
606 DWORD dwUtf8MarshalFlags =
607 (m_pargs->m_pMarshalInfo->GetBestFitMapping() & 0xFF) |
608 (m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar() << 8);
610 // setup to call UTF8BufferMarshaler.ConvertToNative
611 EmitLoadManagedValue(pslILEmit);
612 EmitLoadNativeValue(pslILEmit);
613 pslILEmit->EmitLDC(dwUtf8MarshalFlags);
615 //ConvertToNative(StringBuilder sb,IntPtr pNativeBuffer, int flags)
616 pslILEmit->EmitCALL(METHOD__UTF8BUFFERMARSHALER__CONVERT_TO_NATIVE, 3, 1);
617 EmitStoreNativeValue(pslILEmit);
620 void ILUTF8BufferMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
622 STANDARD_VM_CONTRACT;
624 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
626 EmitLoadNativeValue(pslILEmit);
627 pslILEmit->EmitBRFALSE(pNullRefLabel);
629 if (IsIn(m_dwMarshalFlags) || IsCLRToNative(m_dwMarshalFlags))
631 EmitLoadNativeValue(pslILEmit);
632 // static int System.StubHelpers.StubHelpers.strlen(sbyte* ptr)
633 pslILEmit->EmitCALL(METHOD__STUBHELPERS__STRLEN, 1, 1);
637 // don't touch the native buffer in the native->CLR out-only case
638 pslILEmit->EmitLDC(0);
640 // Convert to UTF8 and then call
641 // System.Text.StringBuilder..ctor(int capacity)
642 pslILEmit->EmitNEWOBJ(METHOD__STRING_BUILDER__CTOR_INT, 1);
643 EmitStoreManagedValue(pslILEmit);
644 pslILEmit->EmitLabel(pNullRefLabel);
647 void ILUTF8BufferMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
649 STANDARD_VM_CONTRACT;
651 EmitLoadManagedValue(pslILEmit);
652 EmitLoadNativeValue(pslILEmit);
654 //void UTF8BufferMarshaler.ConvertToManaged(StringBuilder sb, IntPtr pNative)
655 pslILEmit->EmitCALL(METHOD__UTF8BUFFERMARSHALER__CONVERT_TO_MANAGED, 2, 0);
659 LocalDesc ILWSTRBufferMarshaler::GetManagedType()
661 STANDARD_VM_CONTRACT;
663 return LocalDesc(MscorlibBinder::GetClass(CLASS__STRING_BUILDER));
666 void ILWSTRBufferMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
668 STANDARD_VM_CONTRACT;
670 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
672 pslILEmit->EmitLoadNullPtr();
673 EmitStoreNativeValue(pslILEmit);
675 EmitLoadManagedValue(pslILEmit);
676 pslILEmit->EmitBRFALSE(pNullRefLabel);
678 EmitLoadManagedValue(pslILEmit);
679 // int System.Text.StringBuilder.get_Capacity()
680 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__GET_CAPACITY, 1, 1);
681 pslILEmit->EmitDUP();
683 // static void StubHelpers.CheckStringLength(int length)
684 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
688 pslILEmit->EmitLDC(2);
689 pslILEmit->EmitMUL();
691 // stack: capacity_in_bytes
693 pslILEmit->EmitLDC(2);
694 pslILEmit->EmitADD();
696 // stack: offset_of_secret_null
698 DWORD dwTmpOffsetOfSecretNull = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
699 pslILEmit->EmitDUP();
700 pslILEmit->EmitSTLOC(dwTmpOffsetOfSecretNull); // make sure the stack is empty for localloc
702 pslILEmit->EmitLDC(2);
703 pslILEmit->EmitADD();
705 // stack: alloc_size_in_bytes
706 ILCodeLabel *pAllocRejoin = pslILEmit->NewCodeLabel();
707 if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags))
709 ILCodeLabel *pNoOptimize = pslILEmit->NewCodeLabel();
710 m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
713 pslILEmit->EmitLoadNullPtr();
714 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
716 // if (alloc_size_in_bytes > MAX_LOCAL_BUFFER_LENGTH) goto NoOptimize
717 pslILEmit->EmitDUP();
718 pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
719 pslILEmit->EmitCGT_UN();
720 pslILEmit->EmitBRTRUE(pNoOptimize);
722 pslILEmit->EmitLOCALLOC();
723 pslILEmit->EmitDUP();
724 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
725 pslILEmit->EmitBR(pAllocRejoin);
727 pslILEmit->EmitLabel(pNoOptimize);
730 // static IntPtr AllocCoTaskMem(int cb)
731 pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
733 pslILEmit->EmitLabel(pAllocRejoin);
735 // stack: native_addr
737 pslILEmit->EmitDUP();
738 EmitStoreNativeValue(pslILEmit);
740 pslILEmit->EmitLDLOC(dwTmpOffsetOfSecretNull);
742 // stack: offset_of_secret_null native_addr
744 pslILEmit->EmitADD();
746 // stack: addr_of_secret_null
748 pslILEmit->EmitLDC(0);
750 // stack: addr_of_secret_null 0
752 pslILEmit->EmitSTIND_I2();
753 pslILEmit->EmitLabel(pNullRefLabel);
756 void ILWSTRBufferMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
758 STANDARD_VM_CONTRACT;
760 DWORD dwTempNumBytesLocal = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
762 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
764 EmitLoadNativeValue(pslILEmit);
765 pslILEmit->EmitBRFALSE(pNullRefLabel);
767 EmitLoadManagedValue(pslILEmit);
768 pslILEmit->EmitDUP();
770 // stack: StringBuilder StringBuilder
772 // int System.Text.StringBuilder.get_Length()
773 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__GET_LENGTH, 1, 1);
775 // stack: StringBuilder length
777 // if (!fConvertSpaceJustCalled)
779 // we don't need to double-check the length because the length
780 // must be smaller than the capacity and the capacity was already
781 // checked by EmitConvertSpaceCLRToNative
783 pslILEmit->EmitDUP();
784 // static void StubHelpers.CheckStringLength(int length)
785 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
788 // stack: StringBuilder length
790 pslILEmit->EmitDUP();
791 pslILEmit->EmitADD();
793 // stack: StringBuilder cb
795 pslILEmit->EmitSTLOC(dwTempNumBytesLocal);
797 // stack: StringBuilder
799 EmitLoadNativeValue(pslILEmit);
800 pslILEmit->EmitLDLOC(dwTempNumBytesLocal);
802 // stack: stringbuilder native_buffer cb
804 // void System.Text.StringBuilder.InternalCopy(IntPtr dest,int len)
805 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__INTERNAL_COPY, 3, 0);
808 // null-terminate the native string
810 EmitLoadNativeValue(pslILEmit);
811 pslILEmit->EmitLDLOC(dwTempNumBytesLocal);
812 pslILEmit->EmitADD();
813 pslILEmit->EmitLDC(0);
814 pslILEmit->EmitSTIND_I2();
816 pslILEmit->EmitLabel(pNullRefLabel);
819 void ILWSTRBufferMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
821 STANDARD_VM_CONTRACT;
823 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
825 EmitLoadNativeValue(pslILEmit);
826 pslILEmit->EmitBRFALSE(pNullRefLabel);
828 if (IsIn(m_dwMarshalFlags) || IsCLRToNative(m_dwMarshalFlags))
830 EmitLoadNativeValue(pslILEmit);
831 // static int System.String.wcslen(char *ptr)
832 pslILEmit->EmitCALL(METHOD__STRING__WCSLEN, 1, 1);
836 // don't touch the native buffer in the native->CLR out-only case
837 pslILEmit->EmitLDC(0);
840 // System.Text.StringBuilder..ctor(int capacity)
841 pslILEmit->EmitNEWOBJ(METHOD__STRING_BUILDER__CTOR_INT, 1);
842 EmitStoreManagedValue(pslILEmit);
844 pslILEmit->EmitLabel(pNullRefLabel);
847 void ILWSTRBufferMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
849 STANDARD_VM_CONTRACT;
851 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
853 EmitLoadNativeValue(pslILEmit);
854 pslILEmit->EmitBRFALSE(pNullRefLabel);
856 EmitLoadManagedValue(pslILEmit);
857 EmitLoadNativeValue(pslILEmit);
859 pslILEmit->EmitDUP();
860 // static int System.String.wcslen(char *ptr)
861 pslILEmit->EmitCALL(METHOD__STRING__WCSLEN, 1, 1);
863 // void System.Text.StringBuilder.ReplaceBuffer(char* newBuffer, int newLength);
864 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__REPLACE_BUFFER_INTERNAL, 3, 0);
865 pslILEmit->EmitLabel(pNullRefLabel);
868 LocalDesc ILCSTRBufferMarshaler::GetManagedType()
870 STANDARD_VM_CONTRACT;
872 return LocalDesc(MscorlibBinder::GetClass(CLASS__STRING_BUILDER));
875 void ILCSTRBufferMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
877 STANDARD_VM_CONTRACT;
879 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
881 pslILEmit->EmitLoadNullPtr();
882 EmitStoreNativeValue(pslILEmit);
884 EmitLoadManagedValue(pslILEmit);
885 pslILEmit->EmitBRFALSE(pNullRefLabel);
887 EmitLoadManagedValue(pslILEmit);
888 // int System.Text.StringBuilder.get_Capacity()
889 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__GET_CAPACITY, 1, 1);
890 pslILEmit->EmitDUP();
892 // static void StubHelpers.CheckStringLength(int length)
893 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
897 pslILEmit->EmitLDSFLD(pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__MARSHAL__SYSTEM_MAX_DBCS_CHAR_SIZE)));
898 pslILEmit->EmitMUL();
900 // stack: capacity_in_bytes
902 pslILEmit->EmitLDC(1);
903 pslILEmit->EmitADD();
905 // stack: offset_of_secret_null
907 DWORD dwTmpOffsetOfSecretNull = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
908 pslILEmit->EmitDUP();
909 pslILEmit->EmitSTLOC(dwTmpOffsetOfSecretNull); // make sure the stack is empty for localloc
911 pslILEmit->EmitLDC(3);
912 pslILEmit->EmitADD();
914 // stack: alloc_size_in_bytes
915 ILCodeLabel *pAllocRejoin = pslILEmit->NewCodeLabel();
916 if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags))
918 ILCodeLabel *pNoOptimize = pslILEmit->NewCodeLabel();
919 m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
922 pslILEmit->EmitLoadNullPtr();
923 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
925 // if (alloc_size_in_bytes > MAX_LOCAL_BUFFER_LENGTH) goto NoOptimize
926 pslILEmit->EmitDUP();
927 pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
928 pslILEmit->EmitCGT_UN();
929 pslILEmit->EmitBRTRUE(pNoOptimize);
931 pslILEmit->EmitLOCALLOC();
932 pslILEmit->EmitDUP();
933 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
934 pslILEmit->EmitBR(pAllocRejoin);
936 pslILEmit->EmitLabel(pNoOptimize);
939 // static IntPtr AllocCoTaskMem(int cb)
940 pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
942 pslILEmit->EmitLabel(pAllocRejoin);
944 // stack: native_addr
946 pslILEmit->EmitDUP();
947 EmitStoreNativeValue(pslILEmit);
949 pslILEmit->EmitLDLOC(dwTmpOffsetOfSecretNull);
951 // stack: native_addr offset_of_secret_null
953 pslILEmit->EmitADD();
955 // stack: addr_of_secret_null0
957 pslILEmit->EmitDUP();
958 pslILEmit->EmitLDC(0);
959 pslILEmit->EmitSTIND_I1();
961 // stack: addr_of_secret_null0
963 pslILEmit->EmitDUP();
964 pslILEmit->EmitLDC(1);
965 pslILEmit->EmitADD();
966 pslILEmit->EmitLDC(0);
967 pslILEmit->EmitSTIND_I1();
969 // stack: addr_of_secret_null0
971 pslILEmit->EmitLDC(2);
972 pslILEmit->EmitADD();
973 pslILEmit->EmitLDC(0);
974 pslILEmit->EmitSTIND_I1();
976 pslILEmit->EmitLabel(pNullRefLabel);
979 void ILCSTRBufferMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
981 STANDARD_VM_CONTRACT;
983 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
984 DWORD dwNumBytesLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
985 DWORD dwSrcLocal = pslILEmit->NewLocal(ELEMENT_TYPE_OBJECT);
987 EmitLoadNativeValue(pslILEmit);
988 pslILEmit->EmitBRFALSE(pNullRefLabel);
990 EmitLoadManagedValue(pslILEmit);
991 // int System.Text.StringBuilder.get_Length()
992 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__GET_LENGTH, 1, 1);
993 // static void StubHelpers.CheckStringLength(int length)
994 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
996 EmitLoadManagedValue(pslILEmit);
997 // String System.Text.StringBuilder.ToString()
998 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__TO_STRING, 1, 1);
999 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetBestFitMapping());
1000 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar());
1001 pslILEmit->EmitLDLOCA(dwNumBytesLocalNum);
1003 // static byte[] DoAnsiConversion(string str, bool fBestFit, bool fThrowOnUnmappableChar, out int cbLength)
1004 pslILEmit->EmitCALL(METHOD__ANSICHARMARSHALER__DO_ANSI_CONVERSION, 4, 1);
1005 pslILEmit->EmitSTLOC(dwSrcLocal);
1006 EmitLoadNativeValue(pslILEmit); // pDest
1007 pslILEmit->EmitLDC(0); // destIndex
1008 pslILEmit->EmitLDLOC(dwSrcLocal); // src[]
1009 pslILEmit->EmitLDC(0); // srcIndex
1010 pslILEmit->EmitLDLOC(dwNumBytesLocalNum); // len
1012 // static void Memcpy(byte* pDest, int destIndex, byte[] src, int srcIndex, int len)
1013 pslILEmit->EmitCALL(METHOD__BUFFER__MEMCPY_PTRBYTE_ARRBYTE, 5, 0);
1015 // null terminate the string
1016 EmitLoadNativeValue(pslILEmit);
1017 pslILEmit->EmitLDLOC(dwNumBytesLocalNum);
1018 pslILEmit->EmitADD();
1019 pslILEmit->EmitLDC(0);
1020 pslILEmit->EmitSTIND_I1();
1022 pslILEmit->EmitLabel(pNullRefLabel);
1025 void ILCSTRBufferMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
1027 STANDARD_VM_CONTRACT;
1029 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
1031 EmitLoadNativeValue(pslILEmit);
1032 pslILEmit->EmitBRFALSE(pNullRefLabel);
1034 if (IsIn(m_dwMarshalFlags) || IsCLRToNative(m_dwMarshalFlags))
1036 EmitLoadNativeValue(pslILEmit);
1037 // static int System.StubHelpers.StubHelpers.strlen(sbyte* ptr)
1038 pslILEmit->EmitCALL(METHOD__STUBHELPERS__STRLEN, 1, 1);
1042 // don't touch the native buffer in the native->CLR out-only case
1043 pslILEmit->EmitLDC(0);
1046 // System.Text.StringBuilder..ctor(int capacity)
1047 pslILEmit->EmitNEWOBJ(METHOD__STRING_BUILDER__CTOR_INT, 1);
1048 EmitStoreManagedValue(pslILEmit);
1050 pslILEmit->EmitLabel(pNullRefLabel);
1053 void ILCSTRBufferMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1055 STANDARD_VM_CONTRACT;
1057 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
1059 EmitLoadNativeValue(pslILEmit);
1060 pslILEmit->EmitBRFALSE(pNullRefLabel);
1062 EmitLoadManagedValue(pslILEmit);
1063 EmitLoadNativeValue(pslILEmit);
1065 pslILEmit->EmitDUP();
1066 // static int System.StubHelpers.StubHelpers.strlen(sbyte* ptr)
1067 pslILEmit->EmitCALL(METHOD__STUBHELPERS__STRLEN, 1, 1);
1069 // void System.Text.StringBuilder.ReplaceBuffer(sbyte* newBuffer, int newLength);
1070 pslILEmit->EmitCALL(METHOD__STRING_BUILDER__REPLACE_BUFFER_ANSI_INTERNAL, 3, 0);
1072 pslILEmit->EmitLabel(pNullRefLabel);
1077 LocalDesc ILValueClassMarshaler::GetNativeType()
1079 STANDARD_VM_CONTRACT;
1081 return LocalDesc(TypeHandle(m_pargs->m_pMT).MakeNativeValueType());
1084 LocalDesc ILValueClassMarshaler::GetManagedType()
1086 LIMITED_METHOD_CONTRACT;
1088 return LocalDesc(m_pargs->m_pMT);
1091 void ILValueClassMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
1093 STANDARD_VM_CONTRACT;
1095 EmitLoadNativeHomeAddr(pslILEmit);
1096 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(TypeHandle(m_pargs->m_pMT).MakeNativeValueType()));
1099 bool ILValueClassMarshaler::NeedsClearNative()
1104 void ILValueClassMarshaler::EmitClearNative(ILCodeStream * pslILEmit)
1106 STANDARD_VM_CONTRACT;
1108 mdToken managedVCToken = pslILEmit->GetToken(m_pargs->m_pMT);
1110 EmitLoadNativeHomeAddr(pslILEmit);
1111 pslILEmit->EmitLDTOKEN(managedVCToken); // pMT
1112 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1113 pslILEmit->EmitCALL(METHOD__VALUECLASSMARSHALER__CLEAR_NATIVE, 2, 0);
1117 void ILValueClassMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1119 STANDARD_VM_CONTRACT;
1121 mdToken managedVCToken = pslILEmit->GetToken(m_pargs->m_pMT);
1123 EmitLoadNativeHomeAddr(pslILEmit); // dst
1124 EmitLoadManagedHomeAddr(pslILEmit); // src
1125 pslILEmit->EmitLDTOKEN(managedVCToken); // pMT
1126 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1); // Convert RTH to IntPtr
1128 m_pslNDirect->LoadCleanupWorkList(pslILEmit);
1129 pslILEmit->EmitCALL(METHOD__VALUECLASSMARSHALER__CONVERT_TO_NATIVE, 4, 0); // void ConvertToNative(IntPtr dst, IntPtr src, IntPtr pMT, ref CleanupWorkListElement pCleanupWorkList)
1132 void ILValueClassMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1134 STANDARD_VM_CONTRACT;
1136 mdToken managedVCToken = pslILEmit->GetToken(m_pargs->m_pMT);
1138 EmitLoadManagedHomeAddr(pslILEmit); // dst
1139 EmitLoadNativeHomeAddr(pslILEmit); // src
1140 pslILEmit->EmitLDTOKEN(managedVCToken); // pMT
1141 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1142 pslILEmit->EmitCALL(METHOD__VALUECLASSMARSHALER__CONVERT_TO_MANAGED, 3, 0); // void ConvertToManaged(IntPtr dst, IntPtr src, IntPtr pMT)
1146 #ifdef FEATURE_COMINTEROP
1147 LocalDesc ILObjectMarshaler::GetNativeType()
1149 STANDARD_VM_CONTRACT;
1151 return LocalDesc(TypeHandle(MscorlibBinder::GetClass(CLASS__NATIVEVARIANT)));
1154 LocalDesc ILObjectMarshaler::GetManagedType()
1156 LIMITED_METHOD_CONTRACT;
1158 return LocalDesc(ELEMENT_TYPE_OBJECT);
1161 void ILObjectMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1163 STANDARD_VM_CONTRACT;
1165 if (!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
1167 // Keep the VARIANT as it is - the stubhelper will do a VT_BYREF check on it.
1171 // V_VT(pDest) = VT_EMPTY
1172 EmitReInitNative(pslILEmit);
1175 EmitLoadManagedValue(pslILEmit); // load src
1176 EmitLoadNativeHomeAddr(pslILEmit); // load dst
1177 pslILEmit->EmitCALL(METHOD__OBJECTMARSHALER__CONVERT_TO_NATIVE, 2, 0); // void ConvertToNative(object objSrc, IntPtr pDstVariant)
1180 void ILObjectMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1182 STANDARD_VM_CONTRACT;
1184 EmitLoadNativeHomeAddr(pslILEmit);
1185 pslILEmit->EmitCALL(METHOD__OBJECTMARSHALER__CONVERT_TO_MANAGED, 1, 1); // object ConvertToManaged(IntPtr pSrcVariant);
1186 EmitStoreManagedValue(pslILEmit);
1189 bool ILObjectMarshaler::NeedsClearNative()
1191 LIMITED_METHOD_CONTRACT;
1195 void ILObjectMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1197 STANDARD_VM_CONTRACT;
1199 if (!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
1201 // We don't want to clear variants passed from native by-ref here as we
1202 // want to be able to detect the VT_BYREF case during backpropagation.
1204 // @TODO: We shouldn't be skipping the call if pslILEmit is ILStubLinker::kExceptionCleanup
1205 // because we always want to do real cleanup in this stream.
1209 EmitLoadNativeHomeAddr(pslILEmit);
1210 pslILEmit->EmitCALL(METHOD__OBJECTMARSHALER__CLEAR_NATIVE, 1, 0);
1214 void ILObjectMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
1219 CONSISTENCY_CHECK(offsetof(VARIANT, vt) == 0);
1223 if (!IsCLRToNative(m_dwMarshalFlags) && IsByref(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
1225 // We don't want to clear variants passed from native by-ref here as we
1226 // want to be able to detect the VT_BYREF case during backpropagation.
1230 EmitLoadNativeHomeAddr(pslILEmit);
1231 pslILEmit->EmitLDC(VT_EMPTY);
1232 pslILEmit->EmitSTIND_I2();
1235 #endif // FEATURE_COMINTEROP
1237 LocalDesc ILDateMarshaler::GetNativeType()
1239 LIMITED_METHOD_CONTRACT;
1241 return LocalDesc(ELEMENT_TYPE_R8);
1244 LocalDesc ILDateMarshaler::GetManagedType()
1246 STANDARD_VM_CONTRACT;
1248 return LocalDesc(MscorlibBinder::GetClass(CLASS__DATE_TIME));
1251 void ILDateMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1253 STANDARD_VM_CONTRACT;
1255 EmitLoadManagedValue(pslILEmit);
1256 // double ConvertToNative(INT64 managedDate)
1257 pslILEmit->EmitCALL(METHOD__DATEMARSHALER__CONVERT_TO_NATIVE, 1, 1);
1258 EmitStoreNativeValue(pslILEmit);
1261 void ILDateMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1263 STANDARD_VM_CONTRACT;
1265 // will call DateTime constructor on managed home
1266 EmitLoadManagedHomeAddr(pslILEmit);
1268 EmitLoadNativeValue(pslILEmit);
1269 // long ConvertToNative(double nativeData)
1270 pslILEmit->EmitCALL(METHOD__DATEMARSHALER__CONVERT_TO_MANAGED, 1, 1);
1272 pslILEmit->EmitCALL(METHOD__DATE_TIME__LONG_CTOR, 2, 0);
1275 void ILDateMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
1277 STANDARD_VM_CONTRACT;
1279 // ldc.i4.0, conv.r8 is shorter than ldc.r8 0.0
1280 pslILEmit->EmitLDC(0);
1281 pslILEmit->EmitCONV_R8();
1282 EmitStoreNativeValue(pslILEmit);
1285 LocalDesc ILCurrencyMarshaler::GetNativeType()
1287 STANDARD_VM_CONTRACT;
1289 return LocalDesc(TypeHandle(MscorlibBinder::GetClass(CLASS__CURRENCY)));
1292 LocalDesc ILCurrencyMarshaler::GetManagedType()
1294 STANDARD_VM_CONTRACT;
1296 return LocalDesc(TypeHandle(MscorlibBinder::GetClass(CLASS__DECIMAL)));
1300 void ILCurrencyMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
1302 STANDARD_VM_CONTRACT;
1304 EmitLoadNativeHomeAddr(pslILEmit);
1305 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(TypeHandle(MscorlibBinder::GetClass(CLASS__CURRENCY))));
1308 void ILCurrencyMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1310 STANDARD_VM_CONTRACT;
1312 EmitLoadNativeHomeAddr(pslILEmit);
1313 EmitLoadManagedValue(pslILEmit);
1315 pslILEmit->EmitCALL(METHOD__CURRENCY__DECIMAL_CTOR, 2, 0);
1318 void ILCurrencyMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1320 STANDARD_VM_CONTRACT;
1322 EmitLoadManagedHomeAddr(pslILEmit);
1323 EmitLoadNativeValue(pslILEmit);
1325 pslILEmit->EmitCALL(METHOD__DECIMAL__CURRENCY_CTOR, 2, 0);
1329 #ifdef FEATURE_COMINTEROP
1330 LocalDesc ILInterfaceMarshaler::GetNativeType()
1332 LIMITED_METHOD_CONTRACT;
1334 return LocalDesc(ELEMENT_TYPE_I);
1337 LocalDesc ILInterfaceMarshaler::GetManagedType()
1339 LIMITED_METHOD_CONTRACT;
1341 return LocalDesc(ELEMENT_TYPE_OBJECT);
1344 void ILInterfaceMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1346 STANDARD_VM_CONTRACT;
1348 ItfMarshalInfo itfInfo;
1349 m_pargs->m_pMarshalInfo->GetItfMarshalInfo(&itfInfo);
1351 EmitLoadManagedValue(pslILEmit);
1353 if (itfInfo.thNativeItf.GetMethodTable())
1355 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(itfInfo.thNativeItf.GetMethodTable()));
1356 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1360 pslILEmit->EmitLoadNullPtr();
1363 if (itfInfo.thClass.GetMethodTable())
1365 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(itfInfo.thClass.GetMethodTable()));
1366 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1370 pslILEmit->EmitLoadNullPtr();
1372 pslILEmit->EmitLDC(itfInfo.dwFlags);
1374 // static IntPtr ConvertToNative(object objSrc, IntPtr itfMT, IntPtr classMT, int flags);
1375 pslILEmit->EmitCALL(METHOD__INTERFACEMARSHALER__CONVERT_TO_NATIVE, 4, 1);
1377 EmitStoreNativeValue(pslILEmit);
1379 if (IsCLRToNative(m_dwMarshalFlags) &&
1380 m_pargs->m_pMarshalInfo->IsWinRTScenario())
1382 // If we are calling from CLR into WinRT and we are passing an interface to WinRT, we need to
1383 // keep the object alive across unmanaged call because Jupiter might need to add this
1384 // RCW into their live tree and whatever CCWs referenced by this RCW could get collected
1385 // before the call to native, for example:
1387 // Button btn = new Button();
1388 // btn.OnClick += ...
1389 // m_grid.Children.Add(btn)
1391 // In this case, btn could be collected and takes the delegate CCW with it, before Children.add
1392 // native method is called, and as a result Jupiter will add the neutered CCW into the tree
1394 // The fix is to extend the lifetime of the argument across the call to native by doing a GC.KeepAlive
1395 // keep the delegate ref alive across the call-out to native
1396 EmitLoadManagedValue(m_pcsUnmarshal);
1397 m_pcsUnmarshal->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
1401 void ILInterfaceMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1403 STANDARD_VM_CONTRACT;
1405 ItfMarshalInfo itfInfo;
1406 m_pargs->m_pMarshalInfo->GetItfMarshalInfo(&itfInfo);
1408 // the helper may assign NULL to the home (see below)
1409 EmitLoadNativeHomeAddr(pslILEmit);
1411 if (IsCLRToNative(m_dwMarshalFlags) && m_pargs->m_pMarshalInfo->IsWinRTScenario())
1413 // We are converting an interface pointer to object in a CLR->native stub which means
1414 // that the interface pointer has been AddRef'ed for us by the callee. If we end up
1415 // wrapping it with a new RCW, we can omit another AddRef/Release pair. Note that if
1416 // a new RCW is created the native home will be zeroed out by the helper so the call
1417 // to InterfaceMarshaler__ClearNative will become a no-op.
1419 // Note that we are only doing this for WinRT scenarios to reduce the risk of this change
1420 itfInfo.dwFlags |= ItfMarshalInfo::ITF_MARSHAL_SUPPRESS_ADDREF;
1423 if (itfInfo.thItf.GetMethodTable())
1425 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(itfInfo.thItf.GetMethodTable()));
1426 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1430 pslILEmit->EmitLoadNullPtr();
1433 if (itfInfo.thClass.GetMethodTable())
1435 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(itfInfo.thClass.GetMethodTable()));
1436 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
1440 pslILEmit->EmitLoadNullPtr();
1442 pslILEmit->EmitLDC(itfInfo.dwFlags);
1444 // static object ConvertToManaged(IntPtr pUnk, IntPtr itfMT, IntPtr classMT, int flags);
1445 pslILEmit->EmitCALL(METHOD__INTERFACEMARSHALER__CONVERT_TO_MANAGED, 4, 1);
1447 EmitStoreManagedValue(pslILEmit);
1450 bool ILInterfaceMarshaler::NeedsClearNative()
1452 LIMITED_METHOD_CONTRACT;
1456 void ILMarshaler::EmitInterfaceClearNative(ILCodeStream* pslILEmit)
1458 STANDARD_VM_CONTRACT;
1460 ILCodeLabel *pSkipClearNativeLabel = pslILEmit->NewCodeLabel();
1461 EmitLoadNativeValue(pslILEmit);
1462 pslILEmit->EmitBRFALSE(pSkipClearNativeLabel);
1463 EmitLoadNativeValue(pslILEmit);
1464 // static void ClearNative(IntPtr pUnk);
1465 pslILEmit->EmitCALL(METHOD__INTERFACEMARSHALER__CLEAR_NATIVE, 1, 0);
1466 pslILEmit->EmitLabel(pSkipClearNativeLabel);
1469 void ILInterfaceMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1471 STANDARD_VM_CONTRACT;
1472 EmitInterfaceClearNative(pslILEmit);
1474 #endif // FEATURE_COMINTEROP
1477 LocalDesc ILAnsiCharMarshaler::GetNativeType()
1479 LIMITED_METHOD_CONTRACT;
1481 return LocalDesc(ELEMENT_TYPE_U1);
1484 LocalDesc ILAnsiCharMarshaler::GetManagedType()
1486 LIMITED_METHOD_CONTRACT;
1488 return LocalDesc(ELEMENT_TYPE_CHAR);
1491 void ILAnsiCharMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1493 STANDARD_VM_CONTRACT;
1495 EmitLoadManagedValue(pslILEmit);
1496 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetBestFitMapping());
1497 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar());
1498 pslILEmit->EmitCALL(METHOD__ANSICHARMARSHALER__CONVERT_TO_NATIVE, 3, 1);
1499 EmitStoreNativeValue(pslILEmit);
1502 void ILAnsiCharMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1504 STANDARD_VM_CONTRACT;
1506 EmitLoadNativeValue(pslILEmit);
1507 pslILEmit->EmitCALL(METHOD__ANSICHARMARSHALER__CONVERT_TO_MANAGED, 1, 1);
1508 EmitStoreManagedValue(pslILEmit);
1511 #ifdef FEATURE_COMINTEROP
1512 LocalDesc ILOleColorMarshaler::GetNativeType()
1514 LIMITED_METHOD_CONTRACT;
1516 return LocalDesc(ELEMENT_TYPE_I4);
1519 LocalDesc ILOleColorMarshaler::GetManagedType()
1521 STANDARD_VM_CONTRACT;
1523 BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
1524 TypeHandle hndColorType = pDomain->GetMarshalingData()->GetOleColorMarshalingInfo()->GetColorType();
1529 return LocalDesc(hndColorType); // System.Drawing.Color
1532 void ILOleColorMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1534 STANDARD_VM_CONTRACT;
1536 BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
1537 MethodDesc* pConvertMD = pDomain->GetMarshalingData()->GetOleColorMarshalingInfo()->GetSystemColorToOleColorMD();
1539 EmitLoadManagedValue(pslILEmit);
1540 // int System.Drawing.ColorTranslator.ToOle(System.Drawing.Color c)
1541 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
1542 EmitStoreNativeValue(pslILEmit);
1545 void ILOleColorMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1547 STANDARD_VM_CONTRACT;
1549 BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
1550 MethodDesc* pConvertMD = pDomain->GetMarshalingData()->GetOleColorMarshalingInfo()->GetOleColorToSystemColorMD();
1552 EmitLoadNativeValue(pslILEmit);
1553 // System.Drawing.Color System.Drawing.ColorTranslator.FromOle(int oleColor)
1554 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
1555 EmitStoreManagedValue(pslILEmit);
1558 bool ILVBByValStrWMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
1560 LIMITED_METHOD_CONTRACT;
1561 if (IsCLRToNative(dwMarshalFlags) && IsByref(dwMarshalFlags) && IsIn(dwMarshalFlags) && IsOut(dwMarshalFlags))
1566 *pErrorResID = IDS_EE_BADMARSHAL_VBBYVALSTRRESTRICTION;
1570 bool ILVBByValStrWMarshaler::SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
1572 LIMITED_METHOD_CONTRACT;
1573 *pErrorResID = IDS_EE_BADMARSHAL_VBBYVALSTRRESTRICTION;
1577 LocalDesc ILVBByValStrWMarshaler::GetNativeType()
1579 LIMITED_METHOD_CONTRACT;
1581 return LocalDesc(ELEMENT_TYPE_I); // BSTR
1584 LocalDesc ILVBByValStrWMarshaler::GetManagedType()
1586 LIMITED_METHOD_CONTRACT;
1588 return LocalDesc(ELEMENT_TYPE_STRING);
1591 bool ILVBByValStrWMarshaler::IsNativePassedByRef()
1593 LIMITED_METHOD_CONTRACT;
1597 void ILVBByValStrWMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1599 STANDARD_VM_CONTRACT;
1601 ILCodeStream *pcsSetup = m_pslNDirect->GetSetupCodeStream();
1602 m_dwLocalBuffer = pcsSetup->NewLocal(ELEMENT_TYPE_I);
1603 pcsSetup->EmitLoadNullPtr();
1604 pcsSetup->EmitSTLOC(m_dwLocalBuffer);
1607 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
1608 m_dwCCHLocal = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
1609 DWORD dwNumBytesLocal = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
1611 pslILEmit->EmitLoadNullPtr();
1612 EmitStoreNativeValue(pslILEmit);
1614 EmitLoadManagedValue(pslILEmit);
1615 pslILEmit->EmitBRFALSE(pNullRefLabel);
1617 EmitLoadManagedValue(pslILEmit);
1618 pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
1619 pslILEmit->EmitDUP();
1620 pslILEmit->EmitSTLOC(m_dwCCHLocal);
1624 pslILEmit->EmitLDC(1);
1625 pslILEmit->EmitADD();
1626 pslILEmit->EmitDUP();
1627 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);
1628 pslILEmit->EmitDUP();
1629 pslILEmit->EmitADD(); // (length+1) * sizeof(WCHAR)
1630 pslILEmit->EmitDUP();
1631 pslILEmit->EmitSTLOC(dwNumBytesLocal); // len <- doesn't include size of the DWORD preceeding the string
1632 pslILEmit->EmitLDC(sizeof(DWORD));
1633 pslILEmit->EmitADD(); // (length+1) * sizeof(WCHAR) + sizeof(DWORD)
1637 ILCodeLabel* pNoOptimizeLabel = pslILEmit->NewCodeLabel();
1638 ILCodeLabel* pAllocRejoinLabel = pslILEmit->NewCodeLabel();
1639 pslILEmit->EmitDUP();
1640 pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
1641 pslILEmit->EmitCGT_UN();
1642 pslILEmit->EmitBRTRUE(pNoOptimizeLabel);
1644 pslILEmit->EmitLOCALLOC();
1645 pslILEmit->EmitBR(pAllocRejoinLabel);
1647 pslILEmit->EmitLabel(pNoOptimizeLabel);
1648 pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
1649 pslILEmit->EmitDUP();
1650 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
1652 pslILEmit->EmitLabel(pAllocRejoinLabel);
1653 pslILEmit->EmitDUP();
1654 pslILEmit->EmitLDLOC(m_dwCCHLocal);
1655 pslILEmit->EmitSTIND_I4();
1656 pslILEmit->EmitLDC(sizeof(DWORD));
1657 pslILEmit->EmitADD();
1658 EmitStoreNativeValue(pslILEmit);
1662 EmitLoadManagedValue(pslILEmit); // src
1663 EmitLoadNativeValue(pslILEmit); // dest
1664 pslILEmit->EmitLDLOC(dwNumBytesLocal); // len
1666 // static void System.String.InternalCopy(String src, IntPtr dest,int len)
1667 pslILEmit->EmitCALL(METHOD__STRING__INTERNAL_COPY, 3, 0);
1669 pslILEmit->EmitLabel(pNullRefLabel);
1672 void ILVBByValStrWMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1674 STANDARD_VM_CONTRACT;
1676 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
1677 EmitLoadNativeValue(pslILEmit);
1678 pslILEmit->EmitBRFALSE(pNullRefLabel);
1680 pslILEmit->EmitLDNULL(); // this
1681 EmitLoadNativeValue(pslILEmit); // ptr
1682 pslILEmit->EmitLDC(0); // startIndex
1683 pslILEmit->EmitLDLOC(m_dwCCHLocal); // length
1685 // String CtorCharPtrStartLength(char *ptr, int startIndex, int length)
1686 // TODO Phase5: Why do we call this weirdo?
1687 pslILEmit->EmitCALL(METHOD__STRING__CTORF_CHARPTR_START_LEN, 4, 1);
1689 EmitStoreManagedValue(pslILEmit);
1690 pslILEmit->EmitLabel(pNullRefLabel);
1694 bool ILVBByValStrWMarshaler::NeedsClearNative()
1696 LIMITED_METHOD_CONTRACT;
1700 void ILVBByValStrWMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1702 STANDARD_VM_CONTRACT;
1704 ILCodeLabel* pExitLabel = pslILEmit->NewCodeLabel();
1705 pslILEmit->EmitLDLOC(m_dwLocalBuffer);
1706 pslILEmit->EmitBRFALSE(pExitLabel);
1707 pslILEmit->EmitLDLOC(m_dwLocalBuffer);
1708 pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
1709 pslILEmit->EmitLabel(pExitLabel);
1713 bool ILVBByValStrMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
1715 if (IsCLRToNative(dwMarshalFlags) && IsByref(dwMarshalFlags) && IsIn(dwMarshalFlags) && IsOut(dwMarshalFlags))
1720 *pErrorResID = IDS_EE_BADMARSHAL_VBBYVALSTRRESTRICTION;
1724 bool ILVBByValStrMarshaler::SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
1726 *pErrorResID = IDS_EE_BADMARSHAL_VBBYVALSTRRESTRICTION;
1730 LocalDesc ILVBByValStrMarshaler::GetNativeType()
1732 LIMITED_METHOD_CONTRACT;
1734 return LocalDesc(ELEMENT_TYPE_I); // BSTR
1737 LocalDesc ILVBByValStrMarshaler::GetManagedType()
1739 LIMITED_METHOD_CONTRACT;
1741 return LocalDesc(ELEMENT_TYPE_STRING);
1744 bool ILVBByValStrMarshaler::IsNativePassedByRef()
1746 LIMITED_METHOD_CONTRACT;
1750 void ILVBByValStrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1752 STANDARD_VM_CONTRACT;
1754 m_dwCCHLocal = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
1756 EmitLoadManagedValue(pslILEmit);
1757 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetBestFitMapping());
1758 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar());
1759 pslILEmit->EmitLDLOCA(m_dwCCHLocal);
1761 // static IntPtr ConvertToNative(string strManaged, bool fBestFit, bool fThrowOnUnmappableChar, ref int cch)
1762 pslILEmit->EmitCALL(METHOD__VBBYVALSTRMARSHALER__CONVERT_TO_NATIVE, 4, 1);
1764 EmitStoreNativeValue(pslILEmit);
1767 void ILVBByValStrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1769 STANDARD_VM_CONTRACT;
1771 EmitLoadNativeValue(pslILEmit); // pNative
1772 pslILEmit->EmitLDLOC(m_dwCCHLocal); // cch
1774 // static string ConvertToManaged(IntPtr pNative, int cch)
1775 pslILEmit->EmitCALL(METHOD__VBBYVALSTRMARSHALER__CONVERT_TO_MANAGED, 2, 1);
1777 EmitStoreManagedValue(pslILEmit);
1780 bool ILVBByValStrMarshaler::NeedsClearNative()
1782 LIMITED_METHOD_CONTRACT;
1786 void ILVBByValStrMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1788 STANDARD_VM_CONTRACT;
1790 EmitLoadNativeValue(pslILEmit); // pNative
1792 // static void ClearNative(IntPtr pNative);
1793 pslILEmit->EmitCALL(METHOD__VBBYVALSTRMARSHALER__CLEAR_NATIVE, 1, 0);
1795 #endif // FEATURE_COMINTEROP
1797 LocalDesc ILBSTRMarshaler::GetManagedType()
1799 LIMITED_METHOD_CONTRACT;
1801 return LocalDesc(ELEMENT_TYPE_STRING);
1804 void ILBSTRMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1806 STANDARD_VM_CONTRACT;
1808 ILCodeLabel* pRejoinLabel = pslILEmit->NewCodeLabel();
1810 EmitLoadManagedValue(pslILEmit);
1812 if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags))
1814 ILCodeLabel *pNoOptimizeLabel = pslILEmit->NewCodeLabel();
1815 m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
1818 pslILEmit->EmitLoadNullPtr();
1819 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
1821 pslILEmit->EmitDUP();
1822 pslILEmit->EmitBRFALSE(pNoOptimizeLabel);
1825 pslILEmit->EmitDUP();
1826 pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
1828 // if (length > (MAX_LOCAL_BUFFER_LENGTH - 6) / 2) goto NoOptimize
1829 pslILEmit->EmitLDC((MAX_LOCAL_BUFFER_LENGTH - 6) / 2); // number of Unicode characters - terminator - length dword
1830 pslILEmit->EmitCGT_UN();
1831 pslILEmit->EmitBRTRUE(pNoOptimizeLabel);
1833 // LocalBuffer = localloc[(String.Length * 2) + 6]
1834 pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
1835 pslILEmit->EmitLDC(2);
1836 pslILEmit->EmitMUL();
1837 pslILEmit->EmitLDC(7); // + length (4B) + terminator (2B) + possible trailing byte (1B)
1838 pslILEmit->EmitADD();
1841 // Save the buffer length
1842 DWORD dwTmpAllocSize = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
1843 pslILEmit->EmitDUP();
1844 pslILEmit->EmitSTLOC(dwTmpAllocSize);
1847 pslILEmit->EmitLOCALLOC();
1850 // Pass buffer length in the first DWORD so the helper is able to assert that
1851 // the buffer is large enough.
1852 pslILEmit->EmitDUP();
1853 pslILEmit->EmitLDLOC(dwTmpAllocSize);
1854 pslILEmit->EmitSTIND_I4();
1857 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
1859 // load string and LocalBuffer
1860 EmitLoadManagedValue(pslILEmit);
1861 pslILEmit->EmitLDLOC(m_dwLocalBuffer);
1862 pslILEmit->EmitBR(pRejoinLabel);
1864 pslILEmit->EmitLabel(pNoOptimizeLabel);
1866 pslILEmit->EmitLoadNullPtr();
1868 pslILEmit->EmitLabel(pRejoinLabel);
1869 pslILEmit->EmitCALL(METHOD__BSTRMARSHALER__CONVERT_TO_NATIVE, 2, 1);
1870 EmitStoreNativeValue(pslILEmit);
1873 void ILBSTRMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1875 STANDARD_VM_CONTRACT;
1877 EmitLoadNativeValue(pslILEmit);
1878 pslILEmit->EmitCALL(METHOD__BSTRMARSHALER__CONVERT_TO_MANAGED, 1, 1);
1879 EmitStoreManagedValue(pslILEmit);
1882 LocalDesc ILAnsiBSTRMarshaler::GetNativeType()
1884 LIMITED_METHOD_CONTRACT;
1886 return LocalDesc(ELEMENT_TYPE_I); // BSTR
1889 LocalDesc ILAnsiBSTRMarshaler::GetManagedType()
1891 LIMITED_METHOD_CONTRACT;
1893 return LocalDesc(ELEMENT_TYPE_STRING);
1896 void ILAnsiBSTRMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1898 STANDARD_VM_CONTRACT;
1900 DWORD dwAnsiMarshalFlags =
1901 (m_pargs->m_pMarshalInfo->GetBestFitMapping() & 0xFF) |
1902 (m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar() << 8);
1904 pslILEmit->EmitLDC(dwAnsiMarshalFlags);
1905 EmitLoadManagedValue(pslILEmit);
1906 pslILEmit->EmitCALL(METHOD__ANSIBSTRMARSHALER__CONVERT_TO_NATIVE, 2, 1);
1907 EmitStoreNativeValue(pslILEmit);
1910 void ILAnsiBSTRMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
1912 STANDARD_VM_CONTRACT;
1914 EmitLoadNativeValue(pslILEmit);
1915 pslILEmit->EmitCALL(METHOD__ANSIBSTRMARSHALER__CONVERT_TO_MANAGED, 1, 1);
1916 EmitStoreManagedValue(pslILEmit);
1919 bool ILAnsiBSTRMarshaler::NeedsClearNative()
1921 LIMITED_METHOD_CONTRACT;
1925 void ILAnsiBSTRMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
1927 STANDARD_VM_CONTRACT;
1929 EmitLoadNativeValue(pslILEmit);
1930 pslILEmit->EmitCALL(METHOD__ANSIBSTRMARSHALER__CLEAR_NATIVE, 1, 0);
1933 #ifdef FEATURE_COMINTEROP
1935 LocalDesc ILHSTRINGMarshaler::GetNativeType()
1937 LIMITED_METHOD_CONTRACT;
1938 return LocalDesc(ELEMENT_TYPE_I); // HSTRING
1941 LocalDesc ILHSTRINGMarshaler::GetManagedType()
1943 LIMITED_METHOD_CONTRACT;
1944 return LocalDesc(ELEMENT_TYPE_STRING);
1947 bool ILHSTRINGMarshaler::NeedsClearNative()
1949 LIMITED_METHOD_CONTRACT;
1953 void ILHSTRINGMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
1958 PRECONDITION(CheckPointer(pslILEmit));
1962 // If we're only going into native code, then we can optimize and create a HSTRING reference over
1963 // the pinned System.String. However, if the parameter will remain in native code as an out
1964 // value, then we need to create a real HSTRING.
1965 if (!IsOut(m_dwMarshalFlags) && !IsRetval(m_dwMarshalFlags))
1967 EmitConvertCLRToHSTRINGReference(pslILEmit);
1971 EmitConvertCLRToHSTRING(pslILEmit);
1975 void ILHSTRINGMarshaler::EmitConvertCLRToHSTRINGReference(ILCodeStream* pslILEmit)
1980 PRECONDITION(CheckPointer(pslILEmit));
1981 PRECONDITION(!IsOut(m_dwMarshalFlags));
1982 PRECONDITION(!IsRetval(m_dwMarshalFlags));
1987 // The general strategy for fast path marshaling a short lived System.String -> HSTRING is:
1988 // 1. Pin the System.String
1989 // 2. Create an HSTRING Reference over the pinned string
1990 // 3. Pass that reference to native code
1993 // Local to hold the HSTRING_HEADER of the HSTRING reference
1994 MethodTable *pHStringHeaderMT = MscorlibBinder::GetClass(CLASS__HSTRING_HEADER_MANAGED);
1995 DWORD dwHStringHeaderLocal = pslILEmit->NewLocal(pHStringHeaderMT);
1997 // Local to hold the pinned input string
1998 LocalDesc pinnedStringDesc = GetManagedType();
1999 pinnedStringDesc.MakePinned();
2000 DWORD dwPinnedStringLocal = pslILEmit->NewLocal(pinnedStringDesc);
2002 // pinnedString = managed
2003 EmitLoadManagedValue(pslILEmit);
2004 pslILEmit->EmitSTLOC(dwPinnedStringLocal);
2006 // hstring = HSTRINGMarshaler.ConvertManagedToNativeReference(pinnedString, out HStringHeader)
2007 pslILEmit->EmitLDLOC(dwPinnedStringLocal);
2008 pslILEmit->EmitLDLOCA(dwHStringHeaderLocal);
2009 pslILEmit->EmitCALL(METHOD__HSTRINGMARSHALER__CONVERT_TO_NATIVE_REFERENCE, 2, 1);
2011 if (g_pConfig->InteropLogArguments())
2013 m_pslNDirect->EmitLogNativeArgument(pslILEmit, dwPinnedStringLocal);
2016 EmitStoreNativeValue(pslILEmit);
2019 void ILHSTRINGMarshaler::EmitConvertCLRToHSTRING(ILCodeStream* pslILEmit)
2024 PRECONDITION(CheckPointer(pslILEmit));
2028 // hstring = HSTRINGMarshaler.ConvertManagedToNative(managed);
2029 EmitLoadManagedValue(pslILEmit);
2030 pslILEmit->EmitCALL(METHOD__HSTRINGMARSHALER__CONVERT_TO_NATIVE, 1, 1);
2031 EmitStoreNativeValue(pslILEmit);
2034 void ILHSTRINGMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2036 STANDARD_VM_CONTRACT;
2039 // To convert an HSTRING to a CLR String:
2040 // 1. WindowsGetStringRawBuffer() to get the raw string data
2041 // 2. WindowsGetStringLen() to get the string length
2042 // 3. Construct a System.String from these parameters
2043 // 4. Release the HSTRING
2046 // string = HSTRINGMarshaler.ConvertNativeToManaged(native);
2047 EmitLoadNativeValue(pslILEmit);
2048 pslILEmit->EmitCALL(METHOD__HSTRINGMARSHALER__CONVERT_TO_MANAGED, 1, 1);
2049 EmitStoreManagedValue(pslILEmit);
2053 void ILHSTRINGMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
2055 STANDARD_VM_CONTRACT;
2057 // HStringMarshaler.ClearNative(hstring)
2058 EmitLoadNativeValue(pslILEmit);
2059 pslILEmit->EmitCALL(METHOD__HSTRINGMARSHALER__CLEAR_NATIVE, 1, 0);
2062 #endif // FEATURE_COMINTEROP
2064 LocalDesc ILCUTF8Marshaler::GetManagedType()
2066 LIMITED_METHOD_CONTRACT;
2068 return LocalDesc(ELEMENT_TYPE_STRING);
2071 void ILCUTF8Marshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2073 STANDARD_VM_CONTRACT;
2075 DWORD dwUtf8MarshalFlags =
2076 (m_pargs->m_pMarshalInfo->GetBestFitMapping() & 0xFF) |
2077 (m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar() << 8);
2079 bool bPassByValueInOnly = IsIn(m_dwMarshalFlags) && !IsOut(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags);
2080 if (bPassByValueInOnly)
2082 DWORD dwBufSize = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
2083 m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
2086 pslILEmit->EmitLoadNullPtr();
2087 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
2089 ILCodeLabel* pNoOptimize = pslILEmit->NewCodeLabel();
2091 // if == NULL, goto NoOptimize
2092 EmitLoadManagedValue(pslILEmit);
2093 pslILEmit->EmitBRFALSE(pNoOptimize);
2095 // (String.Length + 1)
2096 // Characters would be # of characters + 1 in case left over high surrogate is ?
2097 EmitLoadManagedValue(pslILEmit);
2098 pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
2099 pslILEmit->EmitLDC(1);
2100 pslILEmit->EmitADD();
2102 // Max 3 bytes per char.
2103 // (String.Length + 1) * 3
2104 pslILEmit->EmitLDC(3);
2105 pslILEmit->EmitMUL();
2107 // +1 for the 0x0 that we put in.
2108 // ((String.Length + 1) * 3) + 1
2109 pslILEmit->EmitLDC(1);
2110 pslILEmit->EmitADD();
2112 // BufSize = ( (String.Length+1) * 3) + 1
2113 pslILEmit->EmitSTLOC(dwBufSize);
2115 // if (MAX_LOCAL_BUFFER_LENGTH < BufSize ) goto NoOptimize
2116 pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
2117 pslILEmit->EmitLDLOC(dwBufSize);
2118 pslILEmit->EmitCLT();
2119 pslILEmit->EmitBRTRUE(pNoOptimize);
2121 // LocalBuffer = localloc(BufSize);
2122 pslILEmit->EmitLDLOC(dwBufSize);
2123 pslILEmit->EmitLOCALLOC();
2124 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
2127 pslILEmit->EmitLabel(pNoOptimize);
2130 // UTF8Marshaler.ConvertToNative(dwUtf8MarshalFlags,pManaged, pLocalBuffer)
2131 pslILEmit->EmitLDC(dwUtf8MarshalFlags);
2132 EmitLoadManagedValue(pslILEmit);
2134 if (m_dwLocalBuffer != LOCAL_NUM_UNUSED)
2136 pslILEmit->EmitLDLOC(m_dwLocalBuffer);
2140 pslILEmit->EmitLoadNullPtr();
2143 pslILEmit->EmitCALL(METHOD__CUTF8MARSHALER__CONVERT_TO_NATIVE, 3, 1);
2145 EmitStoreNativeValue(pslILEmit);
2148 void ILCUTF8Marshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2150 STANDARD_VM_CONTRACT;
2152 EmitLoadNativeValue(pslILEmit);
2153 pslILEmit->EmitCALL(METHOD__CUTF8MARSHALER__CONVERT_TO_MANAGED, 1, 1);
2154 EmitStoreManagedValue(pslILEmit);
2158 LocalDesc ILCSTRMarshaler::GetManagedType()
2160 LIMITED_METHOD_CONTRACT;
2162 return LocalDesc(ELEMENT_TYPE_STRING);
2165 void ILCSTRMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2167 STANDARD_VM_CONTRACT;
2169 DWORD dwAnsiMarshalFlags =
2170 (m_pargs->m_pMarshalInfo->GetBestFitMapping() & 0xFF) |
2171 (m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar() << 8);
2173 bool bPassByValueInOnly = IsIn(m_dwMarshalFlags) && !IsOut(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags);
2174 if (bPassByValueInOnly)
2176 DWORD dwBufSize = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
2177 m_dwLocalBuffer = pslILEmit->NewLocal(ELEMENT_TYPE_I);
2180 pslILEmit->EmitLoadNullPtr();
2181 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
2183 ILCodeLabel* pNoOptimize = pslILEmit->NewCodeLabel();
2185 // if == NULL, goto NoOptimize
2186 EmitLoadManagedValue(pslILEmit);
2187 pslILEmit->EmitBRFALSE(pNoOptimize);
2189 // String.Length + 2
2190 EmitLoadManagedValue(pslILEmit);
2191 pslILEmit->EmitCALL(METHOD__STRING__GET_LENGTH, 1, 1);
2192 pslILEmit->EmitLDC(2);
2193 pslILEmit->EmitADD();
2195 // (String.Length + 2) * GetMaxDBCSCharByteSize()
2196 pslILEmit->EmitLDSFLD(pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__MARSHAL__SYSTEM_MAX_DBCS_CHAR_SIZE)));
2197 pslILEmit->EmitMUL();
2199 // BufSize = (String.Length + 2) * GetMaxDBCSCharByteSize()
2200 pslILEmit->EmitSTLOC(dwBufSize);
2202 // if (MAX_LOCAL_BUFFER_LENGTH < BufSize ) goto NoOptimize
2203 pslILEmit->EmitLDC(MAX_LOCAL_BUFFER_LENGTH);
2204 pslILEmit->EmitLDLOC(dwBufSize);
2205 pslILEmit->EmitCLT();
2206 pslILEmit->EmitBRTRUE(pNoOptimize);
2208 // LocalBuffer = localloc(BufSize);
2209 pslILEmit->EmitLDLOC(dwBufSize);
2210 pslILEmit->EmitLOCALLOC();
2211 pslILEmit->EmitSTLOC(m_dwLocalBuffer);
2214 pslILEmit->EmitLabel(pNoOptimize);
2217 // CSTRMarshaler.ConvertToNative pManaged, dwAnsiMarshalFlags, pLocalBuffer
2218 pslILEmit->EmitLDC(dwAnsiMarshalFlags);
2219 EmitLoadManagedValue(pslILEmit);
2221 if (m_dwLocalBuffer != LOCAL_NUM_UNUSED)
2223 pslILEmit->EmitLDLOC(m_dwLocalBuffer);
2227 pslILEmit->EmitLoadNullPtr();
2230 pslILEmit->EmitCALL(METHOD__CSTRMARSHALER__CONVERT_TO_NATIVE, 3, 1);
2232 EmitStoreNativeValue(pslILEmit);
2235 void ILCSTRMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2237 STANDARD_VM_CONTRACT;
2239 EmitLoadNativeValue(pslILEmit);
2240 pslILEmit->EmitCALL(METHOD__CSTRMARSHALER__CONVERT_TO_MANAGED, 1, 1);
2241 EmitStoreManagedValue(pslILEmit);
2244 LocalDesc ILLayoutClassPtrMarshalerBase::GetNativeType()
2246 LIMITED_METHOD_CONTRACT;
2248 return LocalDesc(ELEMENT_TYPE_I); // ptr to struct
2251 LocalDesc ILLayoutClassPtrMarshalerBase::GetManagedType()
2253 LIMITED_METHOD_CONTRACT;
2255 return LocalDesc(m_pargs->m_pMT);
2258 void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
2260 STANDARD_VM_CONTRACT;
2262 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2263 UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2265 pslILEmit->EmitLoadNullPtr();
2266 EmitStoreNativeValue(pslILEmit);
2268 EmitLoadManagedValue(pslILEmit);
2269 pslILEmit->EmitBRFALSE(pNullRefLabel);
2270 pslILEmit->EmitLDC(uNativeSize);
2271 pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
2272 pslILEmit->EmitDUP(); // for INITBLK
2273 EmitStoreNativeValue(pslILEmit);
2275 // initialize local block we just allocated
2276 pslILEmit->EmitLDC(0);
2277 pslILEmit->EmitLDC(uNativeSize);
2278 pslILEmit->EmitINITBLK();
2280 pslILEmit->EmitLabel(pNullRefLabel);
2283 void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceCLRToNativeTemp(ILCodeStream* pslILEmit)
2285 STANDARD_VM_CONTRACT;
2287 UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2288 if (uNativeSize > s_cbStackAllocThreshold)
2290 EmitConvertSpaceCLRToNative(pslILEmit);
2294 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2296 pslILEmit->EmitLoadNullPtr();
2297 EmitStoreNativeValue(pslILEmit);
2299 EmitLoadManagedValue(pslILEmit);
2300 pslILEmit->EmitBRFALSE(pNullRefLabel);
2302 pslILEmit->EmitLDC(uNativeSize);
2303 pslILEmit->EmitLOCALLOC();
2304 pslILEmit->EmitDUP(); // for INITBLK
2305 EmitStoreNativeValue(pslILEmit);
2307 // initialize local block we just allocated
2308 pslILEmit->EmitLDC(0);
2309 pslILEmit->EmitLDC(uNativeSize);
2310 pslILEmit->EmitINITBLK();
2312 pslILEmit->EmitLabel(pNullRefLabel);
2316 void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
2318 STANDARD_VM_CONTRACT;
2320 EmitConvertSpaceCLRToNativeTemp(pslILEmit);
2321 EmitConvertContentsCLRToNative(pslILEmit);
2324 void ILLayoutClassPtrMarshalerBase::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
2326 STANDARD_VM_CONTRACT;
2328 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2330 EmitLoadNativeValue(pslILEmit);
2331 pslILEmit->EmitBRFALSE(pNullRefLabel);
2333 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(m_pargs->m_pMT));
2334 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
2335 // static object AllocateInternal(IntPtr typeHandle);
2336 pslILEmit->EmitCALL(METHOD__STUBHELPERS__ALLOCATE_INTERNAL, 1, 1);
2337 EmitStoreManagedValue(pslILEmit);
2338 pslILEmit->EmitLabel(pNullRefLabel);
2342 bool ILLayoutClassPtrMarshalerBase::NeedsClearNative()
2344 LIMITED_METHOD_CONTRACT;
2348 void ILLayoutClassPtrMarshalerBase::EmitClearNative(ILCodeStream* pslILEmit)
2350 STANDARD_VM_CONTRACT;
2352 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2354 EmitLoadNativeValue(pslILEmit);
2355 pslILEmit->EmitBRFALSE(pNullRefLabel);
2357 EmitClearNativeContents(pslILEmit);
2358 EmitLoadNativeValue(pslILEmit);
2359 pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
2361 pslILEmit->EmitLabel(pNullRefLabel);
2364 void ILLayoutClassPtrMarshalerBase::EmitClearNativeTemp(ILCodeStream* pslILEmit)
2366 STANDARD_VM_CONTRACT;
2368 UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2369 if (uNativeSize > s_cbStackAllocThreshold)
2371 EmitClearNative(pslILEmit);
2375 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2376 EmitLoadNativeValue(pslILEmit);
2377 pslILEmit->EmitBRFALSE(pNullRefLabel);
2379 EmitClearNativeContents(pslILEmit);
2381 pslILEmit->EmitLabel(pNullRefLabel);
2387 void ILLayoutClassPtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2389 STANDARD_VM_CONTRACT;
2391 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2392 UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2394 EmitLoadNativeValue(pslILEmit);
2395 pslILEmit->EmitBRFALSE(pNullRefLabel);
2397 EmitLoadNativeValue(pslILEmit);
2398 pslILEmit->EmitLDC(0);
2399 pslILEmit->EmitLDC(uNativeSize);
2400 pslILEmit->EmitINITBLK();
2402 EmitLoadManagedValue(pslILEmit);
2403 EmitLoadNativeValue(pslILEmit);
2405 m_pslNDirect->LoadCleanupWorkList(pslILEmit);
2407 // static void FmtClassUpdateNativeInternal(object obj, byte* pNative, IntPtr pOptionalCleanupList);
2409 pslILEmit->EmitCALL(METHOD__STUBHELPERS__FMT_CLASS_UPDATE_NATIVE_INTERNAL, 3, 0);
2410 pslILEmit->EmitLabel(pNullRefLabel);
2413 void ILLayoutClassPtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2415 STANDARD_VM_CONTRACT;
2417 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2419 EmitLoadManagedValue(pslILEmit);
2420 pslILEmit->EmitBRFALSE(pNullRefLabel);
2422 EmitLoadManagedValue(pslILEmit);
2423 EmitLoadNativeValue(pslILEmit);
2425 // static void FmtClassUpdateCLRInternal(object obj, byte* pNative);
2426 pslILEmit->EmitCALL(METHOD__STUBHELPERS__FMT_CLASS_UPDATE_CLR_INTERNAL, 2, 0);
2427 pslILEmit->EmitLabel(pNullRefLabel);
2430 void ILLayoutClassPtrMarshaler::EmitClearNativeContents(ILCodeStream * pslILEmit)
2432 STANDARD_VM_CONTRACT;
2434 int tokManagedType = pslILEmit->GetToken(m_pargs->m_pMT);
2436 EmitLoadNativeValue(pslILEmit);
2437 pslILEmit->EmitLDTOKEN(tokManagedType);
2438 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
2440 // static void LayoutDestroyNativeInternal(byte* pNative, IntPtr pMT);
2441 pslILEmit->EmitCALL(METHOD__STUBHELPERS__LAYOUT_DESTROY_NATIVE_INTERNAL, 2, 0);
2445 void ILBlittablePtrMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
2447 STANDARD_VM_CONTRACT;
2449 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2450 UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2451 int fieldDef = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__PINNING_HELPER__M_DATA));
2453 EmitLoadNativeValue(pslILEmit);
2454 pslILEmit->EmitBRFALSE(pNullRefLabel);
2456 EmitLoadNativeValue(pslILEmit); // dest
2458 EmitLoadManagedValue(pslILEmit);
2459 pslILEmit->EmitLDFLDA(fieldDef); // src
2461 pslILEmit->EmitLDC(uNativeSize); // size
2463 pslILEmit->EmitCPBLK();
2464 pslILEmit->EmitLabel(pNullRefLabel);
2467 void ILBlittablePtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
2469 STANDARD_VM_CONTRACT;
2471 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
2472 UINT uNativeSize = m_pargs->m_pMT->GetNativeSize();
2473 int fieldDef = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__PINNING_HELPER__M_DATA));
2475 EmitLoadManagedValue(pslILEmit);
2476 pslILEmit->EmitBRFALSE(pNullRefLabel);
2478 EmitLoadManagedValue(pslILEmit);
2479 pslILEmit->EmitLDFLDA(fieldDef); // dest
2481 EmitLoadNativeValue(pslILEmit); // src
2483 pslILEmit->EmitLDC(uNativeSize); // size
2485 pslILEmit->EmitCPBLK();
2486 pslILEmit->EmitLabel(pNullRefLabel);
2489 void ILBlittablePtrMarshaler::EmitMarshalArgumentCLRToNative()
2494 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
2498 EmitSetupSigAndDefaultHomesCLRToNative();
2504 ILCodeLabel* pSkipAddLabel = m_pcsMarshal->NewCodeLabel();
2505 LocalDesc managedTypePinned = GetManagedType();
2506 managedTypePinned.MakePinned();
2507 DWORD dwPinnedLocal = m_pcsMarshal->NewLocal(managedTypePinned);
2509 EmitLoadManagedValue(m_pcsMarshal);
2511 m_pcsMarshal->EmitSTLOC(dwPinnedLocal);
2512 m_pcsMarshal->EmitLDLOC(dwPinnedLocal);
2513 m_pcsMarshal->EmitCONV_U();
2514 m_pcsMarshal->EmitDUP();
2515 m_pcsMarshal->EmitBRFALSE(pSkipAddLabel);
2516 m_pcsMarshal->EmitLDC(Object::GetOffsetOfFirstField());
2517 m_pcsMarshal->EmitADD();
2518 m_pcsMarshal->EmitLabel(pSkipAddLabel);
2520 if (g_pConfig->InteropLogArguments())
2522 m_pslNDirect->EmitLogNativeArgument(m_pcsMarshal, dwPinnedLocal);
2525 EmitStoreNativeValue(m_pcsMarshal);
2531 MarshalerOverrideStatus ILHandleRefMarshaler::ArgumentOverride(NDirectStubLinker* psl,
2535 BOOL fManagedToNative,
2536 OverrideProcArgs* pargs,
2539 UINT nativeStackOffset)
2549 ILCodeStream* pcsMarshal = psl->GetMarshalCodeStream();
2550 ILCodeStream* pcsDispatch = psl->GetDispatchCodeStream();
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 pcsDispatch->EmitLDARGA(argidx);
2560 pcsDispatch->EmitLDC(offsetof(HANDLEREF, m_handle));
2561 pcsDispatch->EmitADD();
2562 pcsDispatch->EmitLDIND_I();
2567 *pResID = IDS_EE_BADMARSHAL_HANDLEREFRESTRICTION;
2572 MarshalerOverrideStatus ILHandleRefMarshaler::ReturnOverride(NDirectStubLinker* psl,
2573 BOOL fManagedToNative,
2575 OverrideProcArgs* pargs,
2586 *pResID = IDS_EE_BADMARSHAL_HANDLEREFRESTRICTION;
2590 LocalDesc ILSafeHandleMarshaler::GetManagedType()
2592 STANDARD_VM_CONTRACT;
2594 return LocalDesc(MscorlibBinder::GetClass(CLASS__SAFE_HANDLE));
2597 LocalDesc ILSafeHandleMarshaler::GetNativeType()
2599 LIMITED_METHOD_CONTRACT;
2601 return LocalDesc(ELEMENT_TYPE_I);
2604 bool ILSafeHandleMarshaler::NeedsClearNative()
2606 LIMITED_METHOD_CONTRACT;
2610 void ILSafeHandleMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
2612 STANDARD_VM_CONTRACT;
2614 _ASSERTE(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
2616 // call StubHelpers::SafeHandleRelease
2617 EmitLoadManagedValue(pslILEmit);
2618 pslILEmit->EmitCALL(METHOD__STUBHELPERS__SAFE_HANDLE_RELEASE, 1, 0);
2621 void ILSafeHandleMarshaler::EmitMarshalArgumentCLRToNative()
2626 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
2630 EmitSetupSigAndDefaultHomesCLRToNative();
2632 // by-value CLR-to-native SafeHandle is always passed in-only regardless of [In], [Out]
2633 // marshal and cleanup communicate via an extra local and are both emitted in this method
2635 // bool <dwHandleAddRefedLocalNum> = false
2636 ILCodeStream *pcsSetup = m_pslNDirect->GetSetupCodeStream();
2637 DWORD dwHandleAddRefedLocalNum = pcsSetup->NewLocal(ELEMENT_TYPE_BOOLEAN);
2639 pcsSetup->EmitLDC(0);
2640 pcsSetup->EmitSTLOC(dwHandleAddRefedLocalNum);
2642 // <nativeHandle> = StubHelpers::SafeHandleAddRef(<managedSH>, ref <dwHandleAddRefedLocalNum>)
2643 EmitLoadManagedValue(m_pcsMarshal);
2644 m_pcsMarshal->EmitLDLOCA(dwHandleAddRefedLocalNum);
2645 m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__SAFE_HANDLE_ADD_REF, 2, 1);
2646 EmitStoreNativeValue(m_pcsMarshal);
2649 // if (<dwHandleAddRefedLocalNum>) StubHelpers.SafeHandleRelease(<managedSH>)
2650 ILCodeStream *pcsCleanup = m_pslNDirect->GetCleanupCodeStream();
2651 ILCodeLabel *pSkipClearNativeLabel = pcsCleanup->NewCodeLabel();
2653 pcsCleanup->EmitLDLOC(dwHandleAddRefedLocalNum);
2654 pcsCleanup->EmitBRFALSE(pSkipClearNativeLabel);
2656 EmitClearNativeTemp(pcsCleanup);
2657 m_pslNDirect->SetCleanupNeeded();
2659 pcsCleanup->EmitLabel(pSkipClearNativeLabel);
2662 MarshalerOverrideStatus ILSafeHandleMarshaler::ArgumentOverride(NDirectStubLinker* psl,
2666 BOOL fManagedToNative,
2667 OverrideProcArgs* pargs,
2670 UINT nativeStackOffset)
2680 ILCodeStream* pslIL = psl->GetMarshalCodeStream();
2681 ILCodeStream* pslILDispatch = psl->GetDispatchCodeStream();
2683 if (fManagedToNative)
2687 pslIL->SetStubTargetArgType(ELEMENT_TYPE_I);
2689 // The specific SafeHandle subtype we're dealing with here.
2690 MethodTable *pHandleType = pargs->m_pMT;
2692 // Out SafeHandle parameters must not be abstract.
2693 if (fout && pHandleType->IsAbstract())
2695 *pResID = IDS_EE_BADMARSHAL_ABSTRACTOUTSAFEHANDLE;
2699 // We rely on the SafeHandle having a default constructor.
2700 if (!pHandleType->HasDefaultConstructor())
2702 MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
2703 COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
2706 // Grab the token for the native handle field embedded inside the SafeHandle. We'll be using it to direct access the
2707 // native handle later.
2708 mdToken tkNativeHandleField = pslIL->GetToken(MscorlibBinder::GetField(FIELD__SAFE_HANDLE__HANDLE));
2710 // The high level logic (note that the parameter may be in, out or both):
2711 // 1) If this is an input parameter we need to AddRef the SafeHandle and schedule a Release cleanup item.
2712 // 2) If this is an output parameter we need to preallocate a SafeHandle to wrap the new native handle value. We
2713 // must allocate this before the native call to avoid a failure point when we already have a native resource
2714 // allocated. We must allocate a new SafeHandle even if we have one on input since both input and output native
2715 // handles need to be tracked and released by a SafeHandle.
2716 // 3) Initialize a local IntPtr that will be passed to the native call. If we have an input SafeHandle the value
2717 // comes from there otherwise we get it from the new SafeHandle (which is guaranteed to be initialized to an
2718 // invalid handle value).
2719 // 4) If this is a out parameter we also store the original handle value (that we just computed above) in a local
2721 // 5) After the native call, if this is an output parameter and the handle value we passed to native differs from
2722 // the local copy we made then the new handle value is written into the output SafeHandle and that SafeHandle
2723 // is propagated back to the caller.
2726 DWORD dwInputHandleLocal = 0; // The input safe handle (in only)
2727 DWORD dwOutputHandleLocal = 0; // The output safe handle (out only)
2728 DWORD dwOldNativeHandleLocal = 0; // The original native handle value for comparison (out only)
2729 DWORD dwNativeHandleLocal; // The input (and possibly updated) native handle value
2733 LocalDesc locInputHandle(pHandleType);
2734 dwInputHandleLocal = pslIL->NewLocal(locInputHandle);
2738 LocalDesc locOutputHandle(pHandleType);
2739 dwOutputHandleLocal = pslIL->NewLocal(locOutputHandle);
2741 dwOldNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
2744 dwNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
2746 // Call StubHelpers.AddToCleanupList to atomically AddRef incoming SafeHandle and schedule a cleanup work item to
2747 // perform Release after the call. The helper also returns the native handle value to us so take the opportunity
2748 // to store this in the NativeHandle local we've allocated.
2751 pslIL->EmitLDARG(argidx);
2752 pslIL->EmitLDIND_REF();
2754 pslIL->EmitSTLOC(dwInputHandleLocal);
2756 // Release the original input SafeHandle after the call.
2757 psl->LoadCleanupWorkList(pslIL);
2758 pslIL->EmitLDLOC(dwInputHandleLocal);
2760 // This is realiable, i.e. the cleanup will happen if and only if the SH was actually AddRef'ed.
2761 pslIL->EmitCALL(METHOD__STUBHELPERS__ADD_TO_CLEANUP_LIST_SAFEHANDLE, 2, 1);
2763 pslIL->EmitSTLOC(dwNativeHandleLocal);
2767 // For output parameters we need to allocate a new SafeHandle to hold the result.
2770 MethodDesc* pMDCtor = pHandleType->GetDefaultConstructor();
2771 pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
2772 pslIL->EmitSTLOC(dwOutputHandleLocal);
2774 // If we didn't provide an input handle then we initialize the NativeHandle local with the (initially invalid)
2775 // handle field set up inside the output handle by the constructor.
2778 pslIL->EmitLDLOC(dwOutputHandleLocal);
2779 pslIL->EmitLDFLD(tkNativeHandleField);
2780 pslIL->EmitSTLOC(dwNativeHandleLocal);
2783 // Remember the handle value we start out with so we know whether to back propagate after the native call.
2784 pslIL->EmitLDLOC(dwNativeHandleLocal);
2785 pslIL->EmitSTLOC(dwOldNativeHandleLocal);
2788 // Leave the address of the native handle local as the argument to the native method.
2789 pslILDispatch->EmitLDLOCA(dwNativeHandleLocal);
2791 // On the output side we only backpropagate the native handle into the output SafeHandle and the output SafeHandle
2792 // to the caller if the native handle actually changed (otherwise we can end up with two SafeHandles wrapping the
2793 // same native handle, which is bad).
2796 // We will use cleanup stream to avoid leaking the handle on thread abort.
2797 psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx);
2799 psl->SetCleanupNeeded();
2800 ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
2802 ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
2804 psl->EmitCheckForArgCleanup(pslCleanupIL,
2805 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx,
2806 NDirectStubLinker::BranchIfNotMarshaled,
2809 // If this is an [in, out] handle check if the native handles have changed. If not we're finished.
2812 pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
2813 pslCleanupIL->EmitLDLOC(dwOldNativeHandleLocal);
2814 pslCleanupIL->EmitCEQ();
2815 pslCleanupIL->EmitBRTRUE(pDoneLabel);
2818 // Propagate the native handle into the output SafeHandle.
2819 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
2820 pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
2821 pslCleanupIL->EmitSTFLD(tkNativeHandleField);
2823 // Propagate the output SafeHandle back to the caller.
2824 pslCleanupIL->EmitLDARG(argidx);
2825 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
2826 pslCleanupIL->EmitSTIND_REF();
2828 pslCleanupIL->EmitLabel(pDoneLabel);
2833 // Avoid using the cleanup list in this common case for perf reasons (cleanup list is
2834 // unmanaged and destroying it means excessive managed<->native transitions; in addition,
2835 // as X86 IL stubs do not use interop frames, there's nothing protecting the cleanup list
2836 // and the SafeHandle references must be GC handles which does not help perf either).
2838 // This code path generates calls to StubHelpers.SafeHandleAddRef and SafeHandleRelease.
2839 // NICE: Could SafeHandle.DangerousAddRef and DangerousRelease be implemented in managed?
2840 return HANDLEASNORMAL;
2847 *pResID = IDS_EE_BADMARSHAL_SAFEHANDLENATIVETOCOM;
2852 //---------------------------------------------------------------------------------------
2854 MarshalerOverrideStatus
2855 ILSafeHandleMarshaler::ReturnOverride(
2856 NDirectStubLinker * psl,
2857 BOOL fManagedToNative,
2859 OverrideProcArgs * pargs,
2867 PRECONDITION(CheckPointer(psl));
2868 PRECONDITION(CheckPointer(pargs));
2869 PRECONDITION(CheckPointer(pResID));
2873 ILCodeStream * pslIL = psl->GetMarshalCodeStream();
2874 ILCodeStream * pslPostIL = psl->GetReturnUnmarshalCodeStream();
2875 ILCodeStream * pslILDispatch = psl->GetDispatchCodeStream();
2877 if (!fManagedToNative)
2879 *pResID = IDS_EE_BADMARSHAL_RETURNSHCOMTONATIVE;
2883 // Returned SafeHandle parameters must not be abstract.
2884 if (pargs->m_pMT->IsAbstract())
2886 *pResID = IDS_EE_BADMARSHAL_ABSTRACTRETSAFEHANDLE;
2890 // 1) create local for new safehandle
2891 // 2) prealloc a safehandle
2892 // 3) create local to hold returned handle
2893 // 4) [byref] add byref IntPtr to native sig
2894 // 5) [byref] pass address of local as last arg
2895 // 6) store return value in safehandle
2897 // 1) create local for new safehandle
2898 MethodTable * pMT = pargs->m_pMT;
2899 LocalDesc locDescReturnHandle(pMT);
2900 DWORD dwReturnHandleLocal;
2902 dwReturnHandleLocal = pslIL->NewLocal(locDescReturnHandle);
2904 if (!pMT->HasDefaultConstructor())
2906 MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
2907 COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
2910 // 2) prealloc a safehandle
2911 MethodDesc* pMDCtor = pMT->GetDefaultConstructor();
2912 pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
2913 pslIL->EmitSTLOC(dwReturnHandleLocal);
2915 mdToken tkNativeHandleField = pslPostIL->GetToken(MscorlibBinder::GetField(FIELD__SAFE_HANDLE__HANDLE));
2917 // 3) create local to hold returned handle
2918 DWORD dwReturnNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
2922 // initialize the native handle
2923 pslIL->EmitLDLOC(dwReturnHandleLocal);
2924 pslIL->EmitLDFLD(tkNativeHandleField);
2925 pslIL->EmitSTLOC(dwReturnNativeHandleLocal);
2927 pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I4); // native method returns an HRESULT
2929 // 4) [byref] add byref IntPtr to native sig
2930 locDescReturnHandle.ElementType[0] = ELEMENT_TYPE_BYREF;
2931 locDescReturnHandle.ElementType[1] = ELEMENT_TYPE_I;
2932 locDescReturnHandle.cbType = 2;
2933 pslIL->SetStubTargetArgType(&locDescReturnHandle, false); // extra arg is a byref IntPtr
2935 // 5) [byref] pass address of local as last arg
2936 pslILDispatch->EmitLDLOCA(dwReturnNativeHandleLocal);
2938 // We will use cleanup stream to avoid leaking the handle on thread abort.
2939 psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL);
2941 psl->SetCleanupNeeded();
2942 ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
2943 ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
2945 psl->EmitCheckForArgCleanup(pslCleanupIL,
2946 NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL,
2947 NDirectStubLinker::BranchIfNotMarshaled,
2950 // 6) store return value in safehandle
2951 pslCleanupIL->EmitLDLOC(dwReturnHandleLocal);
2952 pslCleanupIL->EmitLDLOC(dwReturnNativeHandleLocal);
2953 pslCleanupIL->EmitSTFLD(tkNativeHandleField);
2954 pslCleanupIL->EmitLabel(pDoneLabel);
2956 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
2960 pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I);
2961 pslPostIL->EmitSTLOC(dwReturnNativeHandleLocal);
2963 // 6) store return value in safehandle
2964 // The thread abort logic knows that it must not interrupt the stub so we will
2965 // always be able to execute this sequence after returning from the call.
2966 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
2967 pslPostIL->EmitLDLOC(dwReturnNativeHandleLocal);
2968 pslPostIL->EmitSTFLD(tkNativeHandleField);
2969 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
2973 } // ILSafeHandleMarshaler::ReturnOverride
2976 //---------------------------------------------------------------------------------------
2978 MarshalerOverrideStatus ILCriticalHandleMarshaler::ArgumentOverride(NDirectStubLinker* psl,
2982 BOOL fManagedToNative,
2983 OverrideProcArgs* pargs,
2986 UINT nativeStackOffset)
2996 ILCodeStream* pslIL = psl->GetMarshalCodeStream();
2997 ILCodeStream* pslPostIL = psl->GetUnmarshalCodeStream();
2998 ILCodeStream* pslILDispatch = psl->GetDispatchCodeStream();
3000 if (fManagedToNative)
3002 pslIL->SetStubTargetArgType(ELEMENT_TYPE_I);
3004 // Grab the token for the native handle field embedded inside the CriticalHandle. We'll be using it to direct access
3005 // the native handle later.
3006 mdToken tkNativeHandleField = pslIL->GetToken(MscorlibBinder::GetField(FIELD__CRITICAL_HANDLE__HANDLE));
3010 // The specific CriticalHandle subtype we're dealing with here.
3011 MethodTable *pHandleType = pargs->m_pMT;
3013 // Out CriticalHandle parameters must not be abstract.
3014 if (fout && pHandleType->IsAbstract())
3016 *pResID = IDS_EE_BADMARSHAL_ABSTRACTOUTCRITICALHANDLE;
3020 // We rely on the CriticalHandle having a default constructor.
3021 if (!pHandleType->HasDefaultConstructor())
3023 MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
3024 COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
3027 // The high level logic (note that the parameter may be in, out or both):
3028 // 1) If this is an output parameter we need to preallocate a CriticalHandle to wrap the new native handle value. We
3029 // must allocate this before the native call to avoid a failure point when we already have a native resource
3030 // allocated. We must allocate a new CriticalHandle even if we have one on input since both input and output native
3031 // handles need to be tracked and released by a CriticalHandle.
3032 // 2) Initialize a local IntPtr that will be passed to the native call. If we have an input CriticalHandle the value
3033 // comes from there otherwise we get it from the new CriticalHandle (which is guaranteed to be initialized to an
3034 // invalid handle value).
3035 // 3) If this is a out parameter we also store the original handle value (that we just computed above) in a local
3037 // 4) After the native call, if this is an output parameter and the handle value we passed to native differs from
3038 // the local copy we made then the new handle value is written into the output CriticalHandle and that
3039 // CriticalHandle is propagated back to the caller.
3042 LocalDesc locOutputHandle;
3043 DWORD dwOutputHandleLocal = 0; // The output critical handle (out only)
3044 DWORD dwOldNativeHandleLocal = 0; // The original native handle value for comparison (out only)
3045 DWORD dwNativeHandleLocal; // The input (and possibly updated) native handle value
3049 locOutputHandle.ElementType[0] = ELEMENT_TYPE_INTERNAL;
3050 locOutputHandle.cbType = 1;
3051 locOutputHandle.InternalToken = pHandleType;
3053 dwOutputHandleLocal = pslIL->NewLocal(locOutputHandle);
3055 dwOldNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
3058 dwNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
3061 // If we have an input CriticalHandle then initialize our NativeHandle local with it.
3064 pslIL->EmitLDARG(argidx);
3065 pslIL->EmitLDIND_REF();
3066 pslIL->EmitLDFLD(tkNativeHandleField);
3067 pslIL->EmitSTLOC(dwNativeHandleLocal);
3070 // For output parameters we need to allocate a new CriticalHandle to hold the result.
3073 MethodDesc* pMDCtor = pHandleType->GetDefaultConstructor();
3074 pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
3075 pslIL->EmitSTLOC(dwOutputHandleLocal);
3077 // If we didn't provide an input handle then we initialize the NativeHandle local with the (initially invalid)
3078 // handle field set up inside the output handle by the constructor.
3081 pslIL->EmitLDLOC(dwOutputHandleLocal);
3082 pslIL->EmitLDFLD(tkNativeHandleField);
3083 pslIL->EmitSTLOC(dwNativeHandleLocal);
3086 // Remember the handle value we start out with so we know whether to back propagate after the native call.
3087 pslIL->EmitLDLOC(dwNativeHandleLocal);
3088 pslIL->EmitSTLOC(dwOldNativeHandleLocal);
3091 // Leave the address of the native handle local as the argument to the native method.
3092 pslILDispatch->EmitLDLOCA(dwNativeHandleLocal);
3096 // prevent the CriticalHandle from being finalized during the call-out to native
3097 pslPostIL->EmitLDARG(argidx);
3098 pslPostIL->EmitLDIND_REF();
3099 pslPostIL->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
3102 // On the output side we only backpropagate the native handle into the output CriticalHandle and the output
3103 // CriticalHandle to the caller if the native handle actually changed (otherwise we can end up with two
3104 // CriticalHandles wrapping the same native handle, which is bad).
3107 // We will use cleanup stream to avoid leaking the handle on thread abort.
3108 psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx);
3110 psl->SetCleanupNeeded();
3111 ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
3113 ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
3115 psl->EmitCheckForArgCleanup(pslCleanupIL,
3116 NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + argidx,
3117 NDirectStubLinker::BranchIfNotMarshaled,
3120 // If this is an [in, out] handle check if the native handles have changed. If not we're finished.
3123 pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
3124 pslCleanupIL->EmitLDLOC(dwOldNativeHandleLocal);
3125 pslCleanupIL->EmitCEQ();
3126 pslCleanupIL->EmitBRTRUE(pDoneLabel);
3129 // Propagate the native handle into the output CriticalHandle.
3130 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
3131 pslCleanupIL->EmitLDLOC(dwNativeHandleLocal);
3132 pslCleanupIL->EmitSTFLD(tkNativeHandleField);
3134 // Propagate the output CriticalHandle back to the caller.
3135 pslCleanupIL->EmitLDARG(argidx);
3136 pslCleanupIL->EmitLDLOC(dwOutputHandleLocal);
3137 pslCleanupIL->EmitSTIND_REF();
3139 pslCleanupIL->EmitLabel(pDoneLabel);
3144 pslILDispatch->EmitLDARG(argidx);
3145 pslILDispatch->EmitLDFLD(tkNativeHandleField);
3147 // prevent the CriticalHandle from being finalized during the call-out to native
3148 pslPostIL->EmitLDARG(argidx);
3149 pslPostIL->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
3156 *pResID = IDS_EE_BADMARSHAL_CRITICALHANDLENATIVETOCOM;
3161 //---------------------------------------------------------------------------------------
3163 MarshalerOverrideStatus
3164 ILCriticalHandleMarshaler::ReturnOverride(
3165 NDirectStubLinker * psl,
3166 BOOL fManagedToNative,
3168 OverrideProcArgs * pargs,
3176 PRECONDITION(CheckPointer(psl));
3177 PRECONDITION(CheckPointer(pargs));
3178 PRECONDITION(CheckPointer(pResID));
3182 if (!fManagedToNative)
3184 *pResID = IDS_EE_BADMARSHAL_RETURNSHCOMTONATIVE;
3188 // Returned CriticalHandle parameters must not be abstract.
3189 if (pargs->m_pMT->IsAbstract())
3191 *pResID = IDS_EE_BADMARSHAL_ABSTRACTRETCRITICALHANDLE;
3195 ILCodeStream * pslIL = psl->GetMarshalCodeStream();
3196 ILCodeStream * pslPostIL = psl->GetReturnUnmarshalCodeStream();
3197 ILCodeStream * pslILDispatch = psl->GetDispatchCodeStream();
3199 // 1) create local for new criticalhandle
3200 // 2) prealloc a criticalhandle
3201 // 3) create local to hold returned handle
3202 // 4) [byref] add byref IntPtr to native sig
3203 // 5) [byref] pass address of local as last arg
3204 // 6) store return value in criticalhandle
3206 // 1) create local for new criticalhandle
3207 MethodTable * pMT = pargs->m_pMT;
3208 LocalDesc locDescReturnHandle(pMT);
3209 DWORD dwReturnHandleLocal;
3211 dwReturnHandleLocal = pslIL->NewLocal(locDescReturnHandle);
3213 if (!pMT->HasDefaultConstructor())
3215 MAKE_WIDEPTR_FROMUTF8(wzMethodName, COR_CTOR_METHOD_NAME);
3216 COMPlusThrowNonLocalized(kMissingMethodException, wzMethodName);
3219 // 2) prealloc a criticalhandle
3220 MethodDesc * pMDCtor = pMT->GetDefaultConstructor();
3221 pslIL->EmitNEWOBJ(pslIL->GetToken(pMDCtor), 0);
3222 pslIL->EmitSTLOC(dwReturnHandleLocal);
3224 mdToken tkNativeHandleField = pslPostIL->GetToken(MscorlibBinder::GetField(FIELD__CRITICAL_HANDLE__HANDLE));
3226 // 3) create local to hold returned handle
3227 DWORD dwReturnNativeHandleLocal = pslIL->NewLocal(ELEMENT_TYPE_I);
3231 // initialize the native handle
3232 pslIL->EmitLDLOC(dwReturnHandleLocal);
3233 pslIL->EmitLDFLD(tkNativeHandleField);
3234 pslIL->EmitSTLOC(dwReturnNativeHandleLocal);
3236 pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I4); // native method returns an HRESULT
3238 // 4) [byref] add byref IntPtr to native sig
3239 locDescReturnHandle.ElementType[0] = ELEMENT_TYPE_BYREF;
3240 locDescReturnHandle.ElementType[1] = ELEMENT_TYPE_I;
3241 locDescReturnHandle.cbType = 2;
3242 pslIL->SetStubTargetArgType(&locDescReturnHandle, false); // extra arg is a byref IntPtr
3244 // 5) [byref] pass address of local as last arg
3245 pslILDispatch->EmitLDLOCA(dwReturnNativeHandleLocal);
3247 // We will use cleanup stream to avoid leaking the handle on thread abort.
3248 psl->EmitSetArgMarshalIndex(pslIL, NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL);
3250 psl->SetCleanupNeeded();
3251 ILCodeStream *pslCleanupIL = psl->GetCleanupCodeStream();
3252 ILCodeLabel *pDoneLabel = pslCleanupIL->NewCodeLabel();
3254 // 6) store return value in criticalhandle
3255 psl->EmitCheckForArgCleanup(pslCleanupIL,
3256 NDirectStubLinker::CLEANUP_INDEX_RETVAL_UNMARSHAL,
3257 NDirectStubLinker::BranchIfNotMarshaled,
3260 pslCleanupIL->EmitLDLOC(dwReturnHandleLocal);
3261 pslCleanupIL->EmitLDLOC(dwReturnNativeHandleLocal);
3262 pslCleanupIL->EmitSTFLD(tkNativeHandleField);
3263 pslCleanupIL->EmitLabel(pDoneLabel);
3265 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
3269 pslIL->SetStubTargetReturnType(ELEMENT_TYPE_I);
3270 pslPostIL->EmitSTLOC(dwReturnNativeHandleLocal);
3272 // 6) store return value in criticalhandle
3273 // The thread abort logic knows that it must not interrupt the stub so we will
3274 // always be able to execute this sequence after returning from the call.
3275 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
3276 pslPostIL->EmitLDLOC(dwReturnNativeHandleLocal);
3277 pslPostIL->EmitSTFLD(tkNativeHandleField);
3278 pslPostIL->EmitLDLOC(dwReturnHandleLocal);
3282 } // ILCriticalHandleMarshaler::ReturnOverride
3285 LocalDesc ILArgIteratorMarshaler::GetNativeType()
3287 LIMITED_METHOD_CONTRACT;
3289 return LocalDesc(ELEMENT_TYPE_I); // va_list
3292 LocalDesc ILArgIteratorMarshaler::GetManagedType()
3294 STANDARD_VM_CONTRACT;
3296 return LocalDesc(MscorlibBinder::GetClass(CLASS__ARG_ITERATOR));
3299 bool ILArgIteratorMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3301 LIMITED_METHOD_CONTRACT;
3303 if (IsByref(dwMarshalFlags))
3305 *pErrorResID = IDS_EE_BADMARSHAL_ARGITERATORRESTRICTION;
3312 void ILArgIteratorMarshaler::EmitMarshalArgumentCLRToNative()
3317 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3321 EmitSetupSigAndDefaultHomesCLRToNative();
3327 // Allocate enough memory for va_list
3328 DWORD dwVaListSizeLocal = m_pcsMarshal->NewLocal(LocalDesc(ELEMENT_TYPE_U4));
3329 EmitLoadManagedHomeAddr(m_pcsMarshal);
3330 m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__CALC_VA_LIST_SIZE, 1, 1);
3331 m_pcsMarshal->EmitSTLOC(dwVaListSizeLocal);
3332 m_pcsMarshal->EmitLDLOC(dwVaListSizeLocal);
3333 m_pcsMarshal->EmitLOCALLOC();
3334 EmitStoreNativeValue(m_pcsMarshal);
3336 // void MarshalToUnmanagedVaListInternal(cbVaListSize, va_list, VARARGS* data)
3337 EmitLoadNativeValue(m_pcsMarshal);
3338 m_pcsMarshal->EmitLDLOC(dwVaListSizeLocal);
3339 EmitLoadManagedHomeAddr(m_pcsMarshal);
3340 m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__MARSHAL_TO_UNMANAGED_VA_LIST_INTERNAL, 3, 0);
3343 void ILArgIteratorMarshaler::EmitMarshalArgumentNativeToCLR()
3348 PRECONDITION(!IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3352 EmitSetupSigAndDefaultHomesNativeToCLR();
3354 EmitLoadNativeValue(m_pcsMarshal);
3355 EmitLoadManagedHomeAddr(m_pcsMarshal);
3357 // void MarshalToManagedVaList(va_list va, VARARGS *dataout)
3358 m_pcsMarshal->EmitCALL(METHOD__STUBHELPERS__MARSHAL_TO_MANAGED_VA_LIST_INTERNAL, 2, 0);
3362 LocalDesc ILArrayWithOffsetMarshaler::GetNativeType()
3364 LIMITED_METHOD_CONTRACT;
3366 return LocalDesc(ELEMENT_TYPE_I);
3369 LocalDesc ILArrayWithOffsetMarshaler::GetManagedType()
3371 STANDARD_VM_CONTRACT;
3373 return LocalDesc(MscorlibBinder::GetClass(CLASS__ARRAY_WITH_OFFSET));
3376 bool ILArrayWithOffsetMarshaler::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3378 LIMITED_METHOD_CONTRACT;
3380 if (IsCLRToNative(dwMarshalFlags) && !IsByref(dwMarshalFlags) && IsIn(dwMarshalFlags) && IsOut(dwMarshalFlags))
3385 *pErrorResID = IDS_EE_BADMARSHAL_AWORESTRICTION;
3390 void ILArrayWithOffsetMarshaler::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
3396 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwCountLocalNum);
3397 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwOffsetLocalNum);
3398 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwPinnedLocalNum);
3402 int tokArrayWithOffset_m_array = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_ARRAY));
3403 int tokArrayWithOffset_m_count = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_COUNT));
3405 ILCodeLabel* pNonNullLabel = pslILEmit->NewCodeLabel();
3406 ILCodeLabel* pSlowAllocPathLabel = pslILEmit->NewCodeLabel();
3407 ILCodeLabel* pDoneLabel = pslILEmit->NewCodeLabel();
3409 m_dwCountLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
3412 // Convert the space
3415 EmitLoadManagedValue(pslILEmit);
3416 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3417 pslILEmit->EmitBRTRUE(pNonNullLabel);
3419 pslILEmit->EmitLoadNullPtr();
3420 pslILEmit->EmitBR(pDoneLabel);
3421 pslILEmit->EmitLabel(pNonNullLabel);
3423 EmitLoadManagedValue(pslILEmit);
3424 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_count);
3425 pslILEmit->EmitDUP();
3426 pslILEmit->EmitSTLOC(m_dwCountLocalNum);
3427 pslILEmit->EmitDUP();
3428 pslILEmit->EmitLDC(s_cbStackAllocThreshold);
3429 pslILEmit->EmitCGT_UN();
3430 pslILEmit->EmitBRTRUE(pSlowAllocPathLabel);
3433 pslILEmit->EmitLOCALLOC();
3435 pslILEmit->EmitBR(pDoneLabel);
3436 pslILEmit->EmitLabel(pSlowAllocPathLabel);
3439 pslILEmit->EmitCALL(METHOD__MARSHAL__ALLOC_CO_TASK_MEM, 1, 1);
3441 pslILEmit->EmitLabel(pDoneLabel);
3442 EmitStoreNativeValue(pslILEmit);
3445 // Convert the contents
3448 int tokArrayWithOffset_m_offset = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_OFFSET));
3450 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
3452 LocalDesc locDescPinned;
3453 locDescPinned.cbType = 2;
3454 locDescPinned.ElementType[0] = ELEMENT_TYPE_PINNED;
3455 locDescPinned.ElementType[1] = ELEMENT_TYPE_OBJECT;
3456 m_dwPinnedLocalNum = pslILEmit->NewLocal(locDescPinned);
3457 m_dwOffsetLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
3459 EmitLoadManagedValue(pslILEmit);
3460 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3461 pslILEmit->EmitBRFALSE(pNullRefLabel);
3463 EmitLoadManagedValue(pslILEmit);
3464 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3465 pslILEmit->EmitSTLOC(m_dwPinnedLocalNum);
3467 EmitLoadNativeValue(pslILEmit); // dest
3469 pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3470 pslILEmit->EmitCONV_I();
3471 pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3472 pslILEmit->EmitCALL(METHOD__ARRAY__GET_DATA_PTR_OFFSET_INTERNAL, 1, 1);
3473 pslILEmit->EmitADD(); // TODO Phase5: Use UnsafeAddrOfPinnedArrayElement
3475 EmitLoadManagedValue(pslILEmit);
3476 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_offset);
3477 pslILEmit->EmitDUP();
3478 pslILEmit->EmitSTLOC(m_dwOffsetLocalNum);
3479 pslILEmit->EmitADD(); // src
3480 pslILEmit->EmitLDLOC(m_dwCountLocalNum); // len
3482 // static void Memcpy(byte* dest, byte* src, int len)
3483 pslILEmit->EmitCALL(METHOD__BUFFER__MEMCPY, 3, 0);
3485 pslILEmit->EmitLDNULL();
3486 pslILEmit->EmitSTLOC(m_dwPinnedLocalNum);
3488 pslILEmit->EmitLabel(pNullRefLabel);
3491 void ILArrayWithOffsetMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
3497 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED != m_dwCountLocalNum);
3498 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED != m_dwOffsetLocalNum);
3499 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED != m_dwPinnedLocalNum);
3503 int tokArrayWithOffset_m_array = pslILEmit->GetToken(MscorlibBinder::GetField(FIELD__ARRAY_WITH_OFFSET__M_ARRAY));
3505 ILCodeLabel* pNullRefLabel = pslILEmit->NewCodeLabel();
3507 EmitLoadManagedValue(pslILEmit);
3508 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3509 pslILEmit->EmitBRFALSE(pNullRefLabel);
3511 EmitLoadManagedValue(pslILEmit);
3512 pslILEmit->EmitLDFLD(tokArrayWithOffset_m_array);
3513 pslILEmit->EmitSTLOC(m_dwPinnedLocalNum);
3515 pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3516 pslILEmit->EmitCONV_I();
3517 pslILEmit->EmitLDLOC(m_dwPinnedLocalNum);
3518 pslILEmit->EmitCALL(METHOD__ARRAY__GET_DATA_PTR_OFFSET_INTERNAL, 1, 1);
3519 pslILEmit->EmitADD(); // TODO Phase5: Use UnsafeAddrOfPinnedArrayElement
3521 pslILEmit->EmitLDLOC(m_dwOffsetLocalNum);
3522 pslILEmit->EmitADD(); // dest
3524 EmitLoadNativeValue(pslILEmit); // src
3526 pslILEmit->EmitLDLOC(m_dwCountLocalNum); // len
3528 // static void Memcpy(byte* dest, byte* src, int len)
3529 pslILEmit->EmitCALL(METHOD__BUFFER__MEMCPY, 3, 0);
3531 pslILEmit->EmitLDNULL();
3532 pslILEmit->EmitSTLOC(m_dwPinnedLocalNum);
3534 pslILEmit->EmitLabel(pNullRefLabel);
3537 void ILArrayWithOffsetMarshaler::EmitClearNativeTemp(ILCodeStream* pslILEmit)
3539 STANDARD_VM_CONTRACT;
3541 ILCodeLabel* pDoneLabel = pslILEmit->NewCodeLabel();
3543 pslILEmit->EmitLDLOC(m_dwCountLocalNum);
3544 pslILEmit->EmitLDC(s_cbStackAllocThreshold);
3545 pslILEmit->EmitCGT_UN();
3546 pslILEmit->EmitBRFALSE(pDoneLabel);
3549 EmitLoadNativeValue(pslILEmit);
3550 pslILEmit->EmitCALL(METHOD__WIN32NATIVE__COTASKMEMFREE, 1, 0);
3552 pslILEmit->EmitLabel(pDoneLabel);
3555 LocalDesc ILAsAnyMarshalerBase::GetNativeType()
3557 LIMITED_METHOD_CONTRACT;
3559 return LocalDesc(ELEMENT_TYPE_I);
3562 LocalDesc ILAsAnyMarshalerBase::GetManagedType()
3564 LIMITED_METHOD_CONTRACT;
3566 return LocalDesc(ELEMENT_TYPE_OBJECT);
3569 bool ILAsAnyMarshalerBase::SupportsArgumentMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3571 WRAPPER_NO_CONTRACT;
3573 if (IsCLRToNative(dwMarshalFlags) && !IsByref(dwMarshalFlags))
3578 *pErrorResID = IDS_EE_BADMARSHAL_ASANYRESTRICTION;
3582 bool ILAsAnyMarshalerBase::SupportsReturnMarshal(DWORD dwMarshalFlags, UINT* pErrorResID)
3584 LIMITED_METHOD_CONTRACT;
3585 *pErrorResID = IDS_EE_BADMARSHAL_ASANYRESTRICTION;
3589 void ILAsAnyMarshalerBase::EmitMarshalArgumentCLRToNative()
3594 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3595 CONSISTENCY_CHECK(LOCAL_NUM_UNUSED == m_dwMarshalerLocalNum);
3599 EmitSetupSigAndDefaultHomesCLRToNative();
3601 BYTE inout = (IsIn(m_dwMarshalFlags) ? ML_IN : 0) | (IsOut(m_dwMarshalFlags) ? ML_OUT : 0);
3602 BYTE fIsAnsi = IsAnsi() ? 1 : 0;
3603 BYTE fBestFit = m_pargs->m_pMarshalInfo->GetBestFitMapping();
3604 BYTE fThrow = m_pargs->m_pMarshalInfo->GetThrowOnUnmappableChar();
3608 dwFlags |= inout << 24;
3609 dwFlags |= fIsAnsi << 16;
3610 dwFlags |= fThrow << 8;
3611 dwFlags |= fBestFit << 0;
3617 LocalDesc marshalerType(MscorlibBinder::GetClass(CLASS__ASANY_MARSHALER));
3618 m_dwMarshalerLocalNum = m_pcsMarshal->NewLocal(marshalerType);
3619 DWORD dwTmpLocalNum = m_pcsMarshal->NewLocal(ELEMENT_TYPE_I);
3621 m_pcsMarshal->EmitLDC(sizeof(MngdNativeArrayMarshaler));
3622 m_pcsMarshal->EmitLOCALLOC();
3623 m_pcsMarshal->EmitSTLOC(dwTmpLocalNum);
3625 // marshaler = new AsAnyMarshaler(local_buffer)
3626 m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3627 m_pcsMarshal->EmitINITOBJ(m_pcsMarshal->GetToken(marshalerType.InternalToken));
3629 m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3630 m_pcsMarshal->EmitLDLOC(dwTmpLocalNum);
3631 m_pcsMarshal->EmitCALL(METHOD__ASANY_MARSHALER__CTOR, 2, 0);
3633 // nativeValue = marshaler.ConvertToNative(managedValue, flags);
3634 m_pcsMarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3635 EmitLoadManagedValue(m_pcsMarshal);
3636 m_pcsMarshal->EmitLDC(dwFlags);
3637 m_pcsMarshal->EmitCALL(METHOD__ASANY_MARSHALER__CONVERT_TO_NATIVE, 3, 1);
3638 EmitStoreNativeValue(m_pcsMarshal);
3643 if (IsOut(m_dwMarshalFlags))
3645 // marshaler.ConvertToManaged(managedValue, nativeValue)
3646 m_pcsUnmarshal->EmitLDLOCA(m_dwMarshalerLocalNum);
3647 EmitLoadManagedValue(m_pcsUnmarshal);
3648 EmitLoadNativeValue(m_pcsUnmarshal);
3649 m_pcsUnmarshal->EmitCALL(METHOD__ASANY_MARSHALER__CONVERT_TO_MANAGED, 3, 0);
3655 EmitCleanupCLRToNativeTemp();
3658 bool ILAsAnyMarshalerBase::NeedsClearNative()
3660 LIMITED_METHOD_CONTRACT;
3664 void ILAsAnyMarshalerBase::EmitClearNativeTemp(ILCodeStream* pslILEmit)
3666 STANDARD_VM_CONTRACT;
3668 // marshaler.ClearNative(nativeHome)
3669 pslILEmit->EmitLDLOCA(m_dwMarshalerLocalNum);
3670 EmitLoadNativeValue(pslILEmit);
3671 pslILEmit->EmitCALL(METHOD__ASANY_MARSHALER__CLEAR_NATIVE, 2, 0);
3674 // we can get away with putting the GetManagedType and GetNativeType on ILMngdMarshaler because
3675 // currently it is only used for reference marshaling where this is appropriate. If it became
3676 // used for something else, we would want to move this down in the inheritence tree..
3677 LocalDesc ILMngdMarshaler::GetNativeType()
3679 LIMITED_METHOD_CONTRACT;
3681 return LocalDesc(ELEMENT_TYPE_I);
3684 LocalDesc ILMngdMarshaler::GetManagedType()
3686 LIMITED_METHOD_CONTRACT;
3688 return LocalDesc(ELEMENT_TYPE_OBJECT);
3691 void ILMngdMarshaler::EmitCallMngdMarshalerMethod(ILCodeStream* pslILEmit, MethodDesc *pMD)
3693 STANDARD_VM_CONTRACT;
3698 UINT numArgs = sig.NumFixedArgs();
3702 EmitLoadMngdMarshaler(pslILEmit);
3706 _ASSERTE(numArgs == 2);
3709 EmitLoadManagedHomeAddr(pslILEmit);
3710 EmitLoadNativeHomeAddr(pslILEmit);
3712 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), numArgs, 0);
3716 bool ILNativeArrayMarshaler::UsePinnedArraySpecialCase()
3718 if (IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags) && (NULL == OleVariant::GetMarshalerForVarType(m_pargs->na.m_vt, TRUE)))
3726 void ILNativeArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
3728 STANDARD_VM_CONTRACT;
3730 if (UsePinnedArraySpecialCase())
3735 m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
3737 pslILEmit->EmitLDC(sizeof(MngdNativeArrayMarshaler));
3738 pslILEmit->EmitLOCALLOC();
3739 pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
3741 CREATE_MARSHALER_CARRAY_OPERANDS mops;
3742 m_pargs->m_pMarshalInfo->GetMops(&mops);
3744 pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
3746 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(mops.methodTable));
3747 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
3749 DWORD dwFlags = mops.elementType;
3750 dwFlags |= (((DWORD)mops.bestfitmapping) << 16);
3751 dwFlags |= (((DWORD)mops.throwonunmappablechar) << 24);
3753 if (!IsCLRToNative(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
3755 // Unmanaged->managed in/out is the only case where we expect the native buffer to contain valid data.
3756 _ASSERTE((dwFlags & MngdNativeArrayMarshaler::FLAG_NATIVE_DATA_VALID) == 0);
3757 dwFlags |= MngdNativeArrayMarshaler::FLAG_NATIVE_DATA_VALID;
3760 pslILEmit->EmitLDC(dwFlags);
3762 pslILEmit->EmitCALL(METHOD__MNGD_NATIVE_ARRAY_MARSHALER__CREATE_MARSHALER, 3, 0);
3766 void ILNativeArrayMarshaler::EmitMarshalArgumentCLRToNative()
3771 PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
3775 if (UsePinnedArraySpecialCase())
3778 // Replicate ML_PINNEDISOMORPHICARRAY_C2N_EXPRESS behavior -- note that this
3779 // gives in/out semantics "for free" even if the app doesn't specify one or
3780 // the other. Since there is no enforcement of this, apps blithely depend
3784 // The base offset should only be 0 for System.Array parameters for which
3785 // OleVariant::GetMarshalerForVarType(vt) should never return NULL.
3786 _ASSERTE(m_pargs->na.m_optionalbaseoffset != 0);
3788 EmitSetupSigAndDefaultHomesCLRToNative();
3790 LocalDesc managedType = GetManagedType();
3791 managedType.MakePinned();
3793 DWORD dwPinnedLocal = m_pcsMarshal->NewLocal(managedType);
3794 ILCodeLabel* pNullRefLabel = m_pcsMarshal->NewCodeLabel();
3796 m_pcsMarshal->EmitLoadNullPtr();
3797 EmitStoreNativeValue(m_pcsMarshal);
3799 EmitLoadManagedValue(m_pcsMarshal);
3800 m_pcsMarshal->EmitBRFALSE(pNullRefLabel);
3802 EmitLoadManagedValue(m_pcsMarshal);
3803 m_pcsMarshal->EmitSTLOC(dwPinnedLocal);
3804 m_pcsMarshal->EmitLDLOC(dwPinnedLocal);
3805 m_pcsMarshal->EmitCONV_I();
3806 m_pcsMarshal->EmitLDC(m_pargs->na.m_optionalbaseoffset);
3807 m_pcsMarshal->EmitADD();
3808 EmitStoreNativeValue(m_pcsMarshal);
3810 if (g_pConfig->InteropLogArguments())
3812 m_pslNDirect->EmitLogNativeArgument(m_pcsMarshal, dwPinnedLocal);
3815 m_pcsMarshal->EmitLabel(pNullRefLabel);
3819 ILMngdMarshaler::EmitMarshalArgumentCLRToNative();
3824 // Peek at the SizeParamIndex argument
3825 // 1) See if the SizeParamIndex argument is being passed by ref
3826 // 2) Get the element type of SizeParamIndex argument
3828 BOOL ILNativeArrayMarshaler::CheckSizeParamIndexArg(
3829 const CREATE_MARSHALER_CARRAY_OPERANDS &mops,
3830 CorElementType *pElementType)
3837 PRECONDITION(m_pargs != NULL);
3838 PRECONDITION(m_pargs->m_pMarshalInfo != NULL);
3842 MethodDesc *pMD = m_pargs->m_pMarshalInfo->GetMethodDesc();
3845 Module *pModule = m_pargs->m_pMarshalInfo->GetModule();
3848 SigTypeContext emptyTypeContext; // this is an empty type context: ndirect and COM calls are guaranteed to not be generics.
3849 MetaSig msig(pMD->GetSignature(),
3854 // Go to the SizeParamIndex argument
3855 // Note that we already have check in place to make sure SizeParamIndex is within range
3857 if (msig.HasExplicitThis())
3860 for (int i = 0; i < mops.countParamIdx; ++i)
3865 SigPointer sigPointer = msig.GetArgProps();
3867 // Peek into the SizeParamIndex argument
3868 CorElementType elementType;
3869 IfFailThrow(sigPointer.PeekElemType(&elementType));
3871 if (elementType != ELEMENT_TYPE_BYREF)
3873 if (elementType == ELEMENT_TYPE_STRING ||
3874 elementType == ELEMENT_TYPE_ARRAY ||
3875 elementType == ELEMENT_TYPE_FNPTR ||
3876 elementType == ELEMENT_TYPE_OBJECT ||
3877 elementType == ELEMENT_TYPE_SZARRAY ||
3878 elementType == ELEMENT_TYPE_TYPEDBYREF)
3880 COMPlusThrow(kMarshalDirectiveException, IDS_EE_SIZECONTROLBADTYPE);
3883 *pElementType = elementType;
3887 // Get the real type
3888 IfFailThrow(sigPointer.GetElemType(NULL));
3889 IfFailThrow(sigPointer.PeekElemType(&elementType));
3891 // All the integral types are supported
3894 case ELEMENT_TYPE_I1:
3895 case ELEMENT_TYPE_U1:
3896 case ELEMENT_TYPE_I2:
3897 case ELEMENT_TYPE_U2:
3898 case ELEMENT_TYPE_I4:
3899 case ELEMENT_TYPE_U4:
3900 case ELEMENT_TYPE_I8:
3901 case ELEMENT_TYPE_U8:
3902 case ELEMENT_TYPE_I:
3903 case ELEMENT_TYPE_U:
3907 COMPlusThrow(kMarshalDirectiveException, IDS_EE_SIZECONTROLBADTYPE);
3910 *pElementType = elementType;
3915 // Calculate the number of elements and load it into stack
3917 void ILNativeArrayMarshaler::EmitLoadElementCount(ILCodeStream* pslILEmit)
3919 STANDARD_VM_CONTRACT;
3922 // Determine the element count and load into evaluation stack
3924 CREATE_MARSHALER_CARRAY_OPERANDS mops;
3925 m_pargs->m_pMarshalInfo->GetMops(&mops);
3927 if (mops.multiplier != 0)
3930 // SizeParamIndex arg fix up for LCID
3932 unsigned countParamIdx = mops.countParamIdx;
3933 if (!IsCLRToNative(m_dwMarshalFlags))
3935 int lcidParamIdx = m_pslNDirect->GetLCIDParamIdx();
3937 if (lcidParamIdx >= 0 && (unsigned)lcidParamIdx <= countParamIdx)
3939 // the LCID is injected before the count parameter so the index
3940 // has to be incremented to get the unmanaged parameter number
3946 // Load SizeParamIndex argument
3948 pslILEmit->EmitLDARG(countParamIdx);
3954 // Is the SizeParamIndex points to a by-ref parameter?
3955 CorElementType sizeParamIndexArgType;
3956 if (CheckSizeParamIndexArg(mops, &sizeParamIndexArgType))
3958 // Load the by-ref parameter
3959 switch (sizeParamIndexArgType)
3961 case ELEMENT_TYPE_I1:
3962 pslILEmit->EmitLDIND_I1();
3965 case ELEMENT_TYPE_U1:
3966 pslILEmit->EmitLDIND_U1();
3969 case ELEMENT_TYPE_I2:
3970 pslILEmit->EmitLDIND_I2();
3973 case ELEMENT_TYPE_U2:
3974 pslILEmit->EmitLDIND_U2();
3977 case ELEMENT_TYPE_I4:
3978 pslILEmit->EmitLDIND_I4();
3981 case ELEMENT_TYPE_U4:
3982 pslILEmit->EmitLDIND_U4();
3985 case ELEMENT_TYPE_U8:
3986 case ELEMENT_TYPE_I8:
3987 pslILEmit->EmitLDIND_I8();
3990 case ELEMENT_TYPE_I:
3991 case ELEMENT_TYPE_U:
3992 pslILEmit->EmitLDIND_I();
3996 // Should not go here because we should've thrown exception
4002 pslILEmit->EmitCONV_OVF_I4();
4004 // multiplier * arg + additive
4005 pslILEmit->EmitLDC(mops.multiplier);
4006 pslILEmit->EmitMUL_OVF();
4007 pslILEmit->EmitLDC(mops.additive);
4008 pslILEmit->EmitADD_OVF();
4012 pslILEmit->EmitLDC((int)mops.additive);
4016 void ILNativeArrayMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
4018 STANDARD_VM_CONTRACT;
4020 EmitLoadMngdMarshaler(pslILEmit);
4021 EmitLoadManagedHomeAddr(pslILEmit);
4022 EmitLoadNativeHomeAddr(pslILEmit);
4024 if (IsByref(m_dwMarshalFlags))
4027 // Reset the element count just in case there is an exception thrown in the code emitted by
4028 // EmitLoadElementCount. The best thing we can do here is to avoid a crash.
4030 _ASSERTE(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4031 pslILEmit->EmitLDC(0);
4032 pslILEmit->EmitSTLOC(m_dwSavedSizeArg);
4035 // Dynamically calculate element count using SizeParamIndex argument
4036 EmitLoadElementCount(pslILEmit);
4038 if (IsByref(m_dwMarshalFlags))
4041 // Save the native array size before converting it to managed and load it again
4043 _ASSERTE(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4044 pslILEmit->EmitSTLOC(m_dwSavedSizeArg);
4045 pslILEmit->EmitLDLOC(m_dwSavedSizeArg);
4048 // MngdNativeArrayMarshaler::ConvertSpaceToManaged
4049 pslILEmit->EmitCALL(pslILEmit->GetToken(GetConvertSpaceToManagedMethod()), 4, 0);
4052 void ILNativeArrayMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
4054 STANDARD_VM_CONTRACT;
4056 if (IsByref(m_dwMarshalFlags))
4058 _ASSERTE(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4061 // Save the array size before converting it to native
4063 EmitLoadManagedValue(pslILEmit);
4064 ILCodeLabel *pManagedHomeIsNull = pslILEmit->NewCodeLabel();
4065 pslILEmit->EmitBRFALSE(pManagedHomeIsNull);
4066 EmitLoadManagedValue(pslILEmit);
4067 pslILEmit->EmitLDLEN();
4068 pslILEmit->EmitSTLOC(m_dwSavedSizeArg);
4069 pslILEmit->EmitLabel(pManagedHomeIsNull);
4073 ILMngdMarshaler::EmitConvertSpaceCLRToNative(pslILEmit);
4076 void ILNativeArrayMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
4078 STANDARD_VM_CONTRACT;
4080 EmitLoadMngdMarshaler(pslILEmit);
4081 EmitLoadNativeHomeAddr(pslILEmit);
4082 EmitLoadNativeSize(pslILEmit);
4084 pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeMethod()), 3, 0);
4087 void ILNativeArrayMarshaler::EmitLoadNativeSize(ILCodeStream* pslILEmit)
4089 STANDARD_VM_CONTRACT;
4091 if (IsByref(m_dwMarshalFlags))
4093 _ASSERT(m_dwSavedSizeArg != LOCAL_NUM_UNUSED);
4094 pslILEmit->EmitLDLOC(m_dwSavedSizeArg);
4098 pslILEmit->EmitLDC(0);
4099 EmitLoadManagedValue(pslILEmit);
4100 ILCodeLabel *pManagedHomeIsNull = pslILEmit->NewCodeLabel();
4101 pslILEmit->EmitBRFALSE(pManagedHomeIsNull);
4102 pslILEmit->EmitPOP(); // Pop the 0 on the stack
4103 EmitLoadManagedValue(pslILEmit);
4104 pslILEmit->EmitLDLEN();
4105 pslILEmit->EmitCONV_OVF_I4();
4106 pslILEmit->EmitLabel(pManagedHomeIsNull); // Keep the 0 on the stack
4110 void ILNativeArrayMarshaler::EmitClearNativeContents(ILCodeStream* pslILEmit)
4112 STANDARD_VM_CONTRACT;
4114 EmitLoadMngdMarshaler(pslILEmit);
4115 EmitLoadNativeHomeAddr(pslILEmit);
4116 EmitLoadNativeSize(pslILEmit);
4118 pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeContentsMethod()), 3, 0);
4121 void ILNativeArrayMarshaler::EmitNewSavedSizeArgLocal()
4123 STANDARD_VM_CONTRACT;
4125 _ASSERTE(m_dwSavedSizeArg == LOCAL_NUM_UNUSED);
4126 ILCodeStream *pcsSetup = m_pslNDirect->GetSetupCodeStream();
4127 m_dwSavedSizeArg = pcsSetup->NewLocal(ELEMENT_TYPE_I4);
4128 pcsSetup->EmitLDC(0);
4129 pcsSetup->EmitSTLOC(m_dwSavedSizeArg);
4132 void ILNativeArrayMarshaler::EmitMarshalArgumentNativeToCLRByref()
4134 STANDARD_VM_CONTRACT;
4136 if (IsByref(m_dwMarshalFlags))
4138 EmitNewSavedSizeArgLocal();
4141 ILMngdMarshaler::EmitMarshalArgumentNativeToCLRByref();
4144 void ILNativeArrayMarshaler::EmitMarshalArgumentCLRToNativeByref()
4146 STANDARD_VM_CONTRACT;
4148 if (IsByref(m_dwMarshalFlags))
4150 EmitNewSavedSizeArgLocal();
4153 ILMngdMarshaler::EmitMarshalArgumentCLRToNativeByref();
4157 #ifndef CROSSGEN_COMPILE
4159 FCIMPL3(void, MngdNativeArrayMarshaler::CreateMarshaler, MngdNativeArrayMarshaler* pThis, MethodTable* pMT, UINT32 dwFlags)
4163 // Don't check whether the input values are negative - passing negative size-controlling
4164 // arguments and compensating them with a positive SizeConst has always worked.
4165 pThis->m_pElementMT = pMT;
4166 pThis->m_vt = (VARTYPE)(dwFlags);
4167 pThis->m_NativeDataValid = (BYTE)((dwFlags & FLAG_NATIVE_DATA_VALID) != 0);
4168 dwFlags &= ~FLAG_NATIVE_DATA_VALID;
4169 pThis->m_BestFitMap = (BYTE)(dwFlags >> 16);
4170 pThis->m_ThrowOnUnmappableChar = (BYTE)(dwFlags >> 24);
4171 pThis->m_Array = TypeHandle();
4175 FCIMPL3(void, MngdNativeArrayMarshaler::ConvertSpaceToNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4179 HELPER_METHOD_FRAME_BEGIN_0();
4181 BASEARRAYREF arrayRef = (BASEARRAYREF) *pManagedHome;
4183 if (arrayRef == NULL)
4185 *pNativeHome = NULL;
4189 SIZE_T cElements = arrayRef->GetNumComponents();
4190 SIZE_T cbElement = OleVariant::GetElementSizeForVarType(pThis->m_vt, pThis->m_pElementMT);
4193 COMPlusThrow(kArgumentException, IDS_EE_COM_UNSUPPORTED_SIG);
4195 SIZE_T cbArray = cElements;
4196 if ( (!SafeMulSIZE_T(&cbArray, cbElement)) || cbArray > MAX_SIZE_FOR_INTEROP)
4197 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
4199 *pNativeHome = CoTaskMemAlloc(cbArray);
4200 if (*pNativeHome == NULL)
4203 // initialize the array
4204 FillMemory(*pNativeHome, cbArray, 0);
4207 HELPER_METHOD_FRAME_END();
4211 FCIMPL3(void, MngdNativeArrayMarshaler::ConvertContentsToNative, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4215 HELPER_METHOD_FRAME_BEGIN_0();
4217 BASEARRAYREF* pArrayRef = (BASEARRAYREF *) pManagedHome;
4219 if (*pArrayRef != NULL)
4221 const OleVariant::Marshaler* pMarshaler = OleVariant::GetMarshalerForVarType(pThis->m_vt, TRUE);
4222 SIZE_T cElements = (*pArrayRef)->GetNumComponents();
4223 if (pMarshaler == NULL || pMarshaler->ComToOleArray == NULL)
4225 if ( (!SafeMulSIZE_T(&cElements, OleVariant::GetElementSizeForVarType(pThis->m_vt, pThis->m_pElementMT))) || cElements > MAX_SIZE_FOR_INTEROP)
4226 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
4228 _ASSERTE(!GetTypeHandleForCVType(OleVariant::GetCVTypeForVarType(pThis->m_vt)).GetMethodTable()->ContainsPointers());
4229 memcpyNoGCRefs(*pNativeHome, (*pArrayRef)->GetDataPtr(), cElements);
4233 pMarshaler->ComToOleArray(pArrayRef, *pNativeHome, pThis->m_pElementMT, pThis->m_BestFitMap,
4234 pThis->m_ThrowOnUnmappableChar, pThis->m_NativeDataValid, cElements);
4237 HELPER_METHOD_FRAME_END();
4241 FCIMPL4(void, MngdNativeArrayMarshaler::ConvertSpaceToManaged, MngdNativeArrayMarshaler* pThis,
4242 OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements)
4246 HELPER_METHOD_FRAME_BEGIN_0();
4248 if (*pNativeHome == NULL)
4250 SetObjectReference(pManagedHome, NULL, GetAppDomain());
4254 // <TODO>@todo: lookup this class before marshal time</TODO>
4255 if (pThis->m_Array.IsNull())
4257 // Get proper array class name & type
4258 pThis->m_Array = OleVariant::GetArrayForVarType(pThis->m_vt, TypeHandle(pThis->m_pElementMT));
4259 if (pThis->m_Array.IsNull())
4260 COMPlusThrow(kTypeLoadException);
4265 SetObjectReference(pManagedHome, AllocateArrayEx(pThis->m_Array, &cElements, 1), GetAppDomain());
4267 HELPER_METHOD_FRAME_END();
4271 FCIMPL3(void, MngdNativeArrayMarshaler::ConvertContentsToManaged, MngdNativeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4275 HELPER_METHOD_FRAME_BEGIN_0();
4277 if (*pNativeHome != NULL)
4279 const OleVariant::Marshaler *pMarshaler = OleVariant::GetMarshalerForVarType(pThis->m_vt, TRUE);
4281 BASEARRAYREF* pArrayRef = (BASEARRAYREF*) pManagedHome;
4283 if (pMarshaler == NULL || pMarshaler->OleToComArray == NULL)
4285 SIZE_T cElements = (*pArrayRef)->GetNumComponents();
4286 if ( (!SafeMulSIZE_T(&cElements, OleVariant::GetElementSizeForVarType(pThis->m_vt, pThis->m_pElementMT))) || cElements > MAX_SIZE_FOR_INTEROP)
4287 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
4289 // If we are copying variants, strings, etc, we need to use write barrier
4290 _ASSERTE(!GetTypeHandleForCVType(OleVariant::GetCVTypeForVarType(pThis->m_vt)).GetMethodTable()->ContainsPointers());
4291 memcpyNoGCRefs((*pArrayRef)->GetDataPtr(), *pNativeHome, cElements);
4295 pMarshaler->OleToComArray(*pNativeHome, pArrayRef, pThis->m_pElementMT);
4299 HELPER_METHOD_FRAME_END();
4303 FCIMPL3(void, MngdNativeArrayMarshaler::ClearNative, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
4307 HELPER_METHOD_FRAME_BEGIN_0();
4309 if (*pNativeHome != NULL)
4311 DoClearNativeContents(pThis, pNativeHome, cElements);
4312 CoTaskMemFree(*pNativeHome);
4315 HELPER_METHOD_FRAME_END();
4319 FCIMPL3(void, MngdNativeArrayMarshaler::ClearNativeContents, MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
4323 HELPER_METHOD_FRAME_BEGIN_0();
4325 DoClearNativeContents(pThis, pNativeHome, cElements);
4327 HELPER_METHOD_FRAME_END();
4331 void MngdNativeArrayMarshaler::DoClearNativeContents(MngdNativeArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
4341 if (*pNativeHome != NULL)
4343 const OleVariant::Marshaler *pMarshaler = OleVariant::GetMarshalerForVarType(pThis->m_vt, FALSE);
4345 if (pMarshaler != NULL && pMarshaler->ClearOleArray != NULL)
4347 pMarshaler->ClearOleArray(*pNativeHome, cElements, pThis->m_pElementMT);
4352 #endif // CROSSGEN_COMPILE
4355 #ifdef FEATURE_COMINTEROP
4356 void ILSafeArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
4358 STANDARD_VM_CONTRACT;
4360 m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4362 pslILEmit->EmitLDC(sizeof(MngdSafeArrayMarshaler));
4363 pslILEmit->EmitLOCALLOC();
4364 pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
4366 CREATE_MARSHALER_CARRAY_OPERANDS mops;
4367 m_pargs->m_pMarshalInfo->GetMops(&mops);
4369 DWORD dwFlags = mops.elementType;
4372 if (NeedsCheckForStatic())
4374 fStatic |= MngdSafeArrayMarshaler::SCSF_CheckForStatic;
4377 if (!IsCLRToNative(m_dwMarshalFlags) && IsOut(m_dwMarshalFlags) && IsIn(m_dwMarshalFlags))
4379 // Unmanaged->managed in/out is the only case where we expect the native buffer to contain valid data.
4380 fStatic |= MngdSafeArrayMarshaler::SCSF_NativeDataValid;
4383 dwFlags |= fStatic << 16;
4384 dwFlags |= ((BYTE)!!m_pargs->m_pMarshalInfo->GetNoLowerBounds()) << 24;
4386 pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
4387 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(mops.methodTable));
4388 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
4389 pslILEmit->EmitLDC(m_pargs->m_pMarshalInfo->GetArrayRank());
4390 pslILEmit->EmitLDC(dwFlags);
4392 pslILEmit->EmitCALL(METHOD__MNGD_SAFE_ARRAY_MARSHALER__CREATE_MARSHALER, 4, 0);
4395 void ILSafeArrayMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
4397 STANDARD_VM_CONTRACT;
4399 ILMngdMarshaler::EmitConvertContentsNativeToCLR(pslILEmit);
4401 if (NeedsCheckForStatic())
4403 CONSISTENCY_CHECK(-1 == m_dwOriginalManagedLocalNum);
4404 m_dwOriginalManagedLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_OBJECT);
4405 EmitLoadManagedValue(pslILEmit);
4406 pslILEmit->EmitSTLOC(m_dwOriginalManagedLocalNum);
4410 void ILSafeArrayMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
4412 STANDARD_VM_CONTRACT;
4414 EmitLoadMngdMarshaler(pslILEmit);
4415 EmitLoadManagedHomeAddr(pslILEmit);
4416 EmitLoadNativeHomeAddr(pslILEmit);
4417 if (NeedsCheckForStatic())
4419 CONSISTENCY_CHECK(-1 != m_dwOriginalManagedLocalNum);
4420 pslILEmit->EmitLDLOC(m_dwOriginalManagedLocalNum);
4424 pslILEmit->EmitLDNULL();
4426 pslILEmit->EmitCALL(METHOD__MNGD_SAFE_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE, 4, 0);
4430 #ifndef CROSSGEN_COMPILE
4432 FCIMPL4(void, MngdSafeArrayMarshaler::CreateMarshaler, MngdSafeArrayMarshaler* pThis, MethodTable* pMT, UINT32 iRank, UINT32 dwFlags)
4436 pThis->m_pElementMT = pMT;
4437 pThis->m_iRank = iRank;
4438 pThis->m_vt = (VARTYPE)dwFlags;
4439 pThis->m_fStatic = (BYTE)(dwFlags >> 16);
4440 pThis->m_nolowerbounds = (BYTE)(dwFlags >> 24);
4444 FCIMPL3(void, MngdSafeArrayMarshaler::ConvertSpaceToNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4448 if (pThis->m_fStatic & SCSF_IsStatic)
4451 HELPER_METHOD_FRAME_BEGIN_0();
4458 PRECONDITION(pThis->m_vt != VT_EMPTY);
4459 PRECONDITION(CheckPointer(pThis->m_pElementMT));
4463 if (*pManagedHome != NULL)
4465 *pNativeHome = (void *) OleVariant::CreateSafeArrayForArrayRef((BASEARRAYREF*) pManagedHome, pThis->m_vt, pThis->m_pElementMT);
4469 *pNativeHome = NULL;
4472 HELPER_METHOD_FRAME_END();
4476 FCIMPL4(void, MngdSafeArrayMarshaler::ConvertContentsToNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, Object* pOriginalManagedUNSAFE)
4481 PRECONDITION(pThis->m_vt != VT_EMPTY);
4482 PRECONDITION(CheckPointer(pThis->m_pElementMT));
4486 OBJECTREF pOriginalManaged = ObjectToOBJECTREF(pOriginalManagedUNSAFE);
4487 HELPER_METHOD_FRAME_BEGIN_1(pOriginalManaged);
4489 if ((pThis->m_fStatic & SCSF_IsStatic) &&
4490 (*pManagedHome != pOriginalManaged))
4492 COMPlusThrow(kInvalidOperationException, IDS_INVALID_REDIM);
4495 if (*pManagedHome != NULL)
4497 OleVariant::MarshalSafeArrayForArrayRef((BASEARRAYREF *) pManagedHome,
4498 (SAFEARRAY*)*pNativeHome,
4500 pThis->m_pElementMT,
4501 (pThis->m_fStatic & SCSF_NativeDataValid));
4504 HELPER_METHOD_FRAME_END();
4508 FCIMPL3(void, MngdSafeArrayMarshaler::ConvertSpaceToManaged, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4513 PRECONDITION(pThis->m_vt != VT_EMPTY);
4514 PRECONDITION(CheckPointer(pThis->m_pElementMT));
4518 HELPER_METHOD_FRAME_BEGIN_0();
4520 if (*pNativeHome != NULL)
4522 // If the managed array has a rank defined then make sure the rank of the
4523 // SafeArray matches the defined rank.
4524 if (pThis->m_iRank != -1)
4526 int iSafeArrayRank = SafeArrayGetDim((SAFEARRAY*) *pNativeHome);
4527 if (pThis->m_iRank != iSafeArrayRank)
4529 WCHAR strExpectedRank[64];
4530 WCHAR strActualRank[64];
4531 _ltow_s(pThis->m_iRank, strExpectedRank, COUNTOF(strExpectedRank), 10);
4532 _ltow_s(iSafeArrayRank, strActualRank, COUNTOF(strActualRank), 10);
4533 COMPlusThrow(kSafeArrayRankMismatchException, IDS_EE_SAFEARRAYRANKMISMATCH, strActualRank, strExpectedRank);
4537 if (pThis->m_nolowerbounds)
4540 if ( (SafeArrayGetDim( (SAFEARRAY*)*pNativeHome ) != 1) ||
4541 (FAILED(SafeArrayGetLBound( (SAFEARRAY*)*pNativeHome, 1, &lowerbound))) ||
4544 COMPlusThrow(kSafeArrayRankMismatchException, IDS_EE_SAFEARRAYSZARRAYMISMATCH);
4548 SetObjectReference(pManagedHome,
4549 (OBJECTREF) OleVariant::CreateArrayRefForSafeArray((SAFEARRAY*) *pNativeHome,
4551 pThis->m_pElementMT), GetAppDomain());
4555 SetObjectReference(pManagedHome, NULL, GetAppDomain());
4558 HELPER_METHOD_FRAME_END();
4562 FCIMPL3(void, MngdSafeArrayMarshaler::ConvertContentsToManaged, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4567 PRECONDITION(pThis->m_vt != VT_EMPTY);
4568 PRECONDITION(CheckPointer(pThis->m_pElementMT));
4572 SAFEARRAY* pNative = *(SAFEARRAY**)pNativeHome;
4573 HELPER_METHOD_FRAME_BEGIN_0();
4575 if (pNative && pNative->fFeatures & FADF_STATIC)
4577 pThis->m_fStatic |= SCSF_IsStatic;
4580 if (*pNativeHome != NULL)
4582 OleVariant::MarshalArrayRefForSafeArray((SAFEARRAY*)*pNativeHome,
4583 (BASEARRAYREF *) pManagedHome,
4585 pThis->m_pElementMT);
4588 HELPER_METHOD_FRAME_END();
4592 FCIMPL3(void, MngdSafeArrayMarshaler::ClearNative, MngdSafeArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
4596 if (pThis->m_fStatic & SCSF_IsStatic)
4599 HELPER_METHOD_FRAME_BEGIN_0();
4601 if (*pNativeHome != NULL)
4604 _ASSERTE(GetModuleHandleA("oleaut32.dll") != NULL);
4605 // SafeArray has been created. Oleaut32.dll must have been loaded.
4606 CONTRACT_VIOLATION(ThrowsViolation);
4607 SafeArrayDestroy((SAFEARRAY*)*pNativeHome);
4610 HELPER_METHOD_FRAME_END();
4614 #endif // CROSSGEN_COMPILE
4617 LocalDesc ILHiddenLengthArrayMarshaler::GetNativeType()
4619 LIMITED_METHOD_CONTRACT;
4620 return LocalDesc(ELEMENT_TYPE_I);
4623 LocalDesc ILHiddenLengthArrayMarshaler::GetManagedType()
4625 LIMITED_METHOD_CONTRACT;
4626 return LocalDesc(ELEMENT_TYPE_OBJECT);
4629 void ILHiddenLengthArrayMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
4631 STANDARD_VM_CONTRACT;
4633 if (!CanUsePinnedArray())
4635 m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4637 pslILEmit->EmitLDC(sizeof(MngdHiddenLengthArrayMarshaler));
4638 pslILEmit->EmitLOCALLOC();
4639 pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
4641 MethodTable *pElementMT = m_pargs->m_pMarshalInfo->GetArrayElementTypeHandle().GetMethodTable();
4642 pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum);
4643 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(pElementMT));
4644 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
4646 pslILEmit->EmitLDC(m_pargs->na.m_cbElementSize);
4647 pslILEmit->EmitLDC(m_pargs->na.m_vt);
4649 pslILEmit->EmitCALL(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CREATE_MARSHALER, 4, 0);
4653 void ILHiddenLengthArrayMarshaler::EmitMarshalArgumentCLRToNative()
4655 STANDARD_VM_CONTRACT;
4657 // If we can pin the array, then do that rather than marshaling it in a more heavy weight way
4658 // Otherwise, fall back to doing a full marshal
4659 if (CanUsePinnedArray())
4661 EmitSetupSigAndDefaultHomesCLRToNative();
4663 LocalDesc managedType = GetManagedType();
4664 managedType.MakePinned();
4665 DWORD dwPinnedLocal = m_pcsMarshal->NewLocal(managedType);
4667 ILCodeLabel* pMarshalDoneLabel = m_pcsMarshal->NewCodeLabel();
4670 m_pcsMarshal->EmitLoadNullPtr();
4671 EmitStoreNativeValue(m_pcsMarshal);
4673 // if (managed == null) goto MarshalDone
4674 EmitLoadManagedValue(m_pcsMarshal);
4675 m_pcsMarshal->EmitBRFALSE(pMarshalDoneLabel);
4677 // pinnedLocal = managed;
4678 EmitLoadManagedValue(m_pcsMarshal);
4679 m_pcsMarshal->EmitSTLOC(dwPinnedLocal);
4681 // native = pinnedLocal + dataOffset
4682 m_pcsMarshal->EmitLDLOC(dwPinnedLocal);
4683 m_pcsMarshal->EmitCONV_I();
4684 m_pcsMarshal->EmitLDC(m_pargs->na.m_optionalbaseoffset);
4685 m_pcsMarshal->EmitADD();
4686 EmitStoreNativeValue(m_pcsMarshal);
4688 if (g_pConfig->InteropLogArguments())
4690 m_pslNDirect->EmitLogNativeArgument(m_pcsMarshal, dwPinnedLocal);
4694 m_pcsMarshal->EmitLabel(pMarshalDoneLabel);
4698 ILMngdMarshaler::EmitMarshalArgumentCLRToNative();
4703 void ILHiddenLengthArrayMarshaler::EmitConvertSpaceNativeToCLR(ILCodeStream* pslILEmit)
4705 STANDARD_VM_CONTRACT;
4707 if (!CanUsePinnedArray())
4709 EmitLoadMngdMarshaler(pslILEmit);
4710 EmitLoadManagedHomeAddr(pslILEmit);
4711 EmitLoadNativeHomeAddr(pslILEmit);
4712 EmitLoadNativeArrayLength(pslILEmit);
4714 // MngdHiddenLengthArrayMarshaler::ConvertSpaceToManaged
4715 pslILEmit->EmitCALL(pslILEmit->GetToken(GetConvertSpaceToManagedMethod()), 4, 0);
4719 void ILHiddenLengthArrayMarshaler::EmitConvertSpaceCLRToNative(ILCodeStream* pslILEmit)
4721 STANDARD_VM_CONTRACT;
4723 // If we're marshaling out to native code, then we need to set the length out parameter
4724 if (!IsCLRToNative(m_dwMarshalFlags))
4726 if (IsByref(m_dwMarshalFlags) || IsRetval(m_dwMarshalFlags) || IsOut(m_dwMarshalFlags))
4728 ILCodeLabel *pSkipGetLengthLabel = m_pcsMarshal->NewCodeLabel();
4731 pslILEmit->EmitLDC(0);
4732 pslILEmit->EmitCONV_T(m_pargs->m_pMarshalInfo->GetHiddenLengthParamElementType());
4733 pslILEmit->EmitSTLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
4735 // if (array == null) goto SkipGetLength
4736 EmitLoadManagedValue(pslILEmit);
4737 pslILEmit->EmitBRFALSE(pSkipGetLengthLabel);
4739 // nativeLen = array.Length
4741 EmitLoadManagedValue(pslILEmit);
4742 pslILEmit->EmitLDLEN();
4743 pslILEmit->EmitCONV_T(m_pargs->m_pMarshalInfo->GetHiddenLengthParamElementType());
4744 pslILEmit->EmitSTLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
4745 pslILEmit->EmitLabel(pSkipGetLengthLabel);
4747 // nativeLenParam = nativeLen
4748 LocalDesc nativeParamType(m_pargs->m_pMarshalInfo->GetHiddenLengthParamElementType());
4749 pslILEmit->EmitLDARG(m_pargs->m_pMarshalInfo->HiddenLengthParamIndex());
4750 pslILEmit->EmitLDLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
4751 pslILEmit->EmitSTIND_T(&nativeParamType);
4755 if (!CanUsePinnedArray())
4757 ILMngdMarshaler::EmitConvertSpaceCLRToNative(pslILEmit);
4761 void ILHiddenLengthArrayMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
4763 STANDARD_VM_CONTRACT;
4765 if (!CanUsePinnedArray())
4767 if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE &&
4768 (m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Uri ||
4769 m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs ||
4770 m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs))
4772 // System.Uri/NotifyCollectionChangedEventArgs don't live in mscorlib so there's no marshaling helper to call - inline the loop
4773 DWORD dwLoopCounterLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
4774 DWORD dwNativePtrLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4775 ILCodeLabel *pConditionLabel = pslILEmit->NewCodeLabel();
4776 ILCodeLabel *pLoopBodyLabel = pslILEmit->NewCodeLabel();
4778 // for (IntPtr ptr = pNative, int i = 0; ...
4779 pslILEmit->EmitLDC(0);
4780 pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4781 EmitLoadNativeValue(pslILEmit);
4782 pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4783 pslILEmit->EmitBR(pConditionLabel);
4785 // *ptr = EmitConvertCLR*ToWinRT*(pManaged[i]);
4786 pslILEmit->EmitLabel(pLoopBodyLabel);
4787 pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4788 EmitLoadManagedValue(pslILEmit);
4789 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4790 pslILEmit->EmitLDELEM_REF();
4792 switch (m_pargs->na.m_redirectedTypeIndex)
4794 case WinMDAdapter::RedirectedTypeIndex_System_Uri:
4795 ILUriMarshaler::EmitConvertCLRUriToWinRTUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4798 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
4799 ILNCCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4802 case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
4803 ILPCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4806 default: UNREACHABLE();
4809 pslILEmit->EmitSTIND_I();
4811 // ... i++, ptr += IntPtr.Size ...
4812 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4813 pslILEmit->EmitLDC(1);
4814 pslILEmit->EmitADD();
4815 pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4816 pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4817 pslILEmit->EmitLDC(sizeof(LPVOID));
4818 pslILEmit->EmitADD();
4819 pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4821 // ... i < pManaged.Length; ...
4822 pslILEmit->EmitLabel(pConditionLabel);
4823 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4824 EmitLoadNativeArrayLength(pslILEmit);
4825 pslILEmit->EmitBLT(pLoopBodyLabel);
4829 ILMngdMarshaler::EmitConvertContentsCLRToNative(pslILEmit);
4834 void ILHiddenLengthArrayMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
4836 STANDARD_VM_CONTRACT;
4838 if (!CanUsePinnedArray())
4840 if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE &&
4841 (m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Uri ||
4842 m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs ||
4843 m_pargs->na.m_redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs))
4845 // System.Uri/NotifyCollectionChangedEventArgs don't live in mscorlib so there's no marshaling helper to call - inline the loop
4846 DWORD dwLoopCounterLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I4);
4847 DWORD dwNativePtrLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
4848 ILCodeLabel *pConditionLabel = pslILEmit->NewCodeLabel();
4849 ILCodeLabel *pLoopBodyLabel = pslILEmit->NewCodeLabel();
4851 // for (IntPtr ptr = pNative, int i = 0; ...
4852 pslILEmit->EmitLDC(0);
4853 pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4854 EmitLoadNativeValue(pslILEmit);
4855 pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4856 pslILEmit->EmitBR(pConditionLabel);
4858 // pManaged[i] = EmitConvertWinRT*ToCLR*(*ptr);
4859 pslILEmit->EmitLabel(pLoopBodyLabel);
4860 EmitLoadManagedValue(pslILEmit);
4861 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4862 pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4863 pslILEmit->EmitLDIND_I();
4865 switch (m_pargs->na.m_redirectedTypeIndex)
4867 case WinMDAdapter::RedirectedTypeIndex_System_Uri:
4868 ILUriMarshaler::EmitConvertWinRTUriToCLRUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4871 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
4872 ILNCCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4875 case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
4876 ILPCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
4879 default: UNREACHABLE();
4882 pslILEmit->EmitSTELEM_REF();
4884 // ... i++, ptr += IntPtr.Size)
4885 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4886 pslILEmit->EmitLDC(1);
4887 pslILEmit->EmitADD();
4888 pslILEmit->EmitSTLOC(dwLoopCounterLocalNum);
4889 pslILEmit->EmitLDLOC(dwNativePtrLocalNum);
4890 pslILEmit->EmitLDC(sizeof(LPVOID));
4891 pslILEmit->EmitADD();
4892 pslILEmit->EmitSTLOC(dwNativePtrLocalNum);
4894 // ... i < pManaged.Length; ...
4895 pslILEmit->EmitLabel(pConditionLabel);
4896 pslILEmit->EmitLDLOC(dwLoopCounterLocalNum);
4897 EmitLoadNativeArrayLength(pslILEmit);
4898 pslILEmit->EmitBLT(pLoopBodyLabel);
4902 ILMngdMarshaler::EmitConvertContentsNativeToCLR(pslILEmit);
4907 void ILHiddenLengthArrayMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
4909 STANDARD_VM_CONTRACT;
4911 EmitClearNativeContents(pslILEmit);
4913 if (!CanUsePinnedArray())
4915 EmitLoadNativeValue(pslILEmit);
4916 pslILEmit->EmitCALL(pslILEmit->GetToken(GetClearNativeMethod()), 1, 0);
4920 void ILHiddenLengthArrayMarshaler::EmitClearNativeContents(ILCodeStream* pslILEmit)
4922 STANDARD_VM_CONTRACT;
4924 if (!CanUsePinnedArray())
4926 MethodDesc *pMD = GetClearNativeContentsMethod();
4930 UINT numArgs = sig.NumFixedArgs();
4934 EmitLoadMngdMarshaler(pslILEmit);
4938 _ASSERTE(numArgs == 2);
4941 EmitLoadNativeHomeAddr(pslILEmit);
4942 EmitLoadNativeArrayLength(pslILEmit);
4943 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), numArgs, 0);
4948 // Determine if we can simply pin the managed array, rather than doing a full marshal
4949 bool ILHiddenLengthArrayMarshaler::CanUsePinnedArray()
4951 STANDARD_VM_CONTRACT;
4953 // If the array is only going from managed to native, and it contains only blittable data, and
4954 // we know where that data is located in the array then we can take the fast path
4955 if (!IsCLRToNative(m_dwMarshalFlags))
4960 if (m_pargs->na.m_vt != VTHACK_BLITTABLERECORD)
4965 if (IsByref(m_dwMarshalFlags))
4970 if (!IsIn(m_dwMarshalFlags))
4975 if (IsRetval(m_dwMarshalFlags))
4980 if (m_pargs->na.m_optionalbaseoffset == 0)
4988 void ILHiddenLengthArrayMarshaler::EmitLoadNativeArrayLength(ILCodeStream *pslILEmit)
4990 STANDARD_VM_CONTRACT;
4992 // For return values, the native length won't yet be marshaled back to its managed home
4993 // so it needs to be read directly
4994 if (IsRetval(m_dwMarshalFlags))
4996 pslILEmit->EmitLDLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthNativeHome());
5000 pslILEmit->EmitLDLOC(m_pargs->m_pMarshalInfo->GetHiddenLengthManagedHome());
5003 pslILEmit->EmitCONV_OVF_I4();
5006 MethodDesc *ILHiddenLengthArrayMarshaler::GetConvertContentsToManagedMethod()
5008 STANDARD_VM_CONTRACT;
5010 if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE)
5012 switch (m_pargs->na.m_redirectedTypeIndex)
5014 case WinMDAdapter::RedirectedTypeIndex_System_DateTimeOffset:
5015 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_DATETIME);
5017 case WinMDAdapter::RedirectedTypeIndex_System_Type:
5018 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_TYPE);
5020 case WinMDAdapter::RedirectedTypeIndex_System_Exception:
5021 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_EXCEPTION);
5023 case WinMDAdapter::RedirectedTypeIndex_System_Nullable:
5025 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_NULLABLE);
5026 return GetExactMarshalerMethod(pMD);
5029 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_KeyValuePair:
5031 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_MANAGED_KEYVALUEPAIR);
5032 return GetExactMarshalerMethod(pMD);
5036 UNREACHABLE_MSG("Unrecognized redirected type.");
5039 return ILMngdMarshaler::GetConvertContentsToManagedMethod();
5042 MethodDesc *ILHiddenLengthArrayMarshaler::GetConvertContentsToNativeMethod()
5044 STANDARD_VM_CONTRACT;
5046 if (m_pargs->na.m_vt == VTHACK_REDIRECTEDTYPE)
5048 switch (m_pargs->na.m_redirectedTypeIndex)
5050 case WinMDAdapter::RedirectedTypeIndex_System_DateTimeOffset:
5051 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_DATETIME);
5053 case WinMDAdapter::RedirectedTypeIndex_System_Type:
5054 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_TYPE);
5056 case WinMDAdapter::RedirectedTypeIndex_System_Exception:
5057 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_EXCEPTION);
5059 case WinMDAdapter::RedirectedTypeIndex_System_Nullable:
5061 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_NULLABLE);
5062 return GetExactMarshalerMethod(pMD);
5065 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_KeyValuePair:
5067 MethodDesc *pMD = MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CONVERT_CONTENTS_TO_NATIVE_KEYVALUEPAIR);
5068 return GetExactMarshalerMethod(pMD);
5072 UNREACHABLE_MSG("Unrecognized redirected type.");
5075 return ILMngdMarshaler::GetConvertContentsToNativeMethod();
5078 MethodDesc *ILHiddenLengthArrayMarshaler::GetClearNativeContentsMethod()
5080 switch (m_pargs->na.m_vt)
5082 // HSTRINGs, interface pointers, and non-blittable structs need contents cleanup
5083 case VTHACK_HSTRING:
5084 case VTHACK_INSPECTABLE:
5085 case VTHACK_NONBLITTABLERECORD:
5088 // blittable structs don't need contents cleanup
5089 case VTHACK_BLITTABLERECORD:
5092 case VTHACK_REDIRECTEDTYPE:
5094 switch (m_pargs->na.m_redirectedTypeIndex)
5096 // System.Type, Uri, Nullable, KeyValuePair, NCCEventArgs, and PCEventArgs need cleanup
5097 case WinMDAdapter::RedirectedTypeIndex_System_Type:
5098 return MscorlibBinder::GetMethod(METHOD__MNGD_HIDDEN_LENGTH_ARRAY_MARSHALER__CLEAR_NATIVE_CONTENTS_TYPE);
5100 case WinMDAdapter::RedirectedTypeIndex_System_Uri:
5101 case WinMDAdapter::RedirectedTypeIndex_System_Nullable:
5102 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_KeyValuePair:
5103 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
5104 case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
5107 // other redirected types don't
5115 UNREACHABLE_MSG("Unexpected hidden-length array element VT");
5118 return ILMngdMarshaler::GetClearNativeContentsMethod();
5121 MethodDesc *ILHiddenLengthArrayMarshaler::GetExactMarshalerMethod(MethodDesc *pGenericMD)
5123 STANDARD_VM_CONTRACT;
5125 return MethodDesc::FindOrCreateAssociatedMethodDesc(
5127 pGenericMD->GetMethodTable(),
5128 FALSE, // forceBoxedEntryPoint
5129 m_pargs->na.m_pMT->GetInstantiation(), // methodInst
5130 FALSE, // allowInstParam
5131 TRUE); // forceRemotableMethod
5134 #ifndef CROSSGEN_COMPILE
5136 FCIMPL4(void, MngdHiddenLengthArrayMarshaler::CreateMarshaler, MngdHiddenLengthArrayMarshaler* pThis, MethodTable* pMT, SIZE_T cbElementSize, UINT16 vt)
5140 pThis->m_pElementMT = pMT;
5141 pThis->m_cbElementSize = cbElementSize;
5142 pThis->m_vt = (VARTYPE)vt;
5146 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ConvertSpaceToNative, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5150 BASEARRAYREF arrayRef = (BASEARRAYREF) *pManagedHome;
5151 HELPER_METHOD_FRAME_BEGIN_1(arrayRef);
5153 if (arrayRef == NULL)
5155 *pNativeHome = NULL;
5159 SIZE_T cbArray = pThis->GetArraySize(arrayRef->GetNumComponents());
5161 *pNativeHome = CoTaskMemAlloc(cbArray);
5162 if (*pNativeHome == NULL)
5167 // initialize the array
5168 FillMemory(*pNativeHome, cbArray, 0);
5171 HELPER_METHOD_FRAME_END();
5175 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ConvertContentsToNative, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5181 PTRARRAYREF arrayRef;
5182 STRINGREF currentStringRef;
5183 OBJECTREF currentObjectRef;
5186 ZeroMemory(&gc, sizeof(gc));
5187 gc.arrayRef = (PTRARRAYREF)*pManagedHome;
5189 HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
5191 if (gc.arrayRef != NULL)
5193 // There are these choices:
5194 // * the array is made up of entirely blittable data, in which case we can directly copy it,
5195 // * it is an array of strings that need to be marshaled as HSTRING,
5196 // * it is an array of non-blittable structures
5197 // * it is an array of interface pointers (interface, runtime class, delegate, System.Object)
5198 switch (pThis->m_vt)
5200 case VTHACK_BLITTABLERECORD:
5202 // Just do a raw memcpy into the array
5203 SIZE_T cbArray = pThis->GetArraySize(gc.arrayRef->GetNumComponents());
5204 memcpyNoGCRefs(*pNativeHome, gc.arrayRef->GetDataPtr(), cbArray);
5208 case VTHACK_HSTRING:
5210 // Marshal a string array as an array of HSTRINGs
5211 if (!WinRTSupported())
5213 COMPlusThrow(kPlatformNotSupportedException, W("PlatformNotSupported_WinRT"));
5216 HSTRING *pDestinationStrings = reinterpret_cast<HSTRING *>(*pNativeHome);
5218 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5220 gc.currentStringRef = (STRINGREF)gc.arrayRef->GetAt(i);
5221 if (gc.currentStringRef == NULL)
5223 StackSString ssIndex;
5224 ssIndex.Printf(W("%d"), i);
5225 COMPlusThrow(kMarshalDirectiveException, IDS_EE_BADMARSHALARRAY_NULL_HSTRING, ssIndex.GetUnicode());
5228 IfFailThrow(WindowsCreateString(gc.currentStringRef->GetBuffer(), gc.currentStringRef->GetStringLength(), &(pDestinationStrings[i])));
5233 case VTHACK_NONBLITTABLERECORD:
5235 BYTE *pNativeStart = reinterpret_cast<BYTE *>(*pNativeHome);
5236 SIZE_T managedOffset = ArrayBase::GetDataPtrOffset(gc.arrayRef->GetMethodTable());
5237 SIZE_T nativeOffset = 0;
5238 SIZE_T managedSize = gc.arrayRef->GetComponentSize();
5239 SIZE_T nativeSize = pThis->m_pElementMT->GetNativeSize();
5240 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5242 LayoutUpdateNative(reinterpret_cast<LPVOID *>(&gc.arrayRef), managedOffset, pThis->m_pElementMT, pNativeStart + nativeOffset, NULL);
5243 managedOffset += managedSize;
5244 nativeOffset += nativeSize;
5249 case VTHACK_INSPECTABLE:
5251 // interface pointers
5252 IUnknown **pDestinationIPs = reinterpret_cast<IUnknown **>(*pNativeHome);
5254 // If this turns out to be a perf issue, we can precompute the ItfMarshalInfo
5255 // and generate code that passes it to the marshaler at creation time.
5256 ItfMarshalInfo itfInfo;
5257 MarshalInfo::GetItfMarshalInfo(TypeHandle(pThis->m_pElementMT), TypeHandle(), FALSE, TRUE, MarshalInfo::MARSHAL_SCENARIO_WINRT, &itfInfo);
5259 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5261 gc.currentObjectRef = gc.arrayRef->GetAt(i);
5262 pDestinationIPs[i] = MarshalObjectToInterface(
5263 &gc.currentObjectRef,
5264 itfInfo.thNativeItf.GetMethodTable(),
5265 itfInfo.thClass.GetMethodTable(),
5272 UNREACHABLE_MSG("Unrecognized array element VARTYPE");
5276 HELPER_METHOD_FRAME_END();
5280 FCIMPL4(void, MngdHiddenLengthArrayMarshaler::ConvertSpaceToManaged, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome, INT32 cElements)
5284 HELPER_METHOD_FRAME_BEGIN_0();
5286 if (*pNativeHome == NULL)
5288 SetObjectReference(pManagedHome, NULL, GetAppDomain());
5292 TypeHandle elementType(pThis->m_pElementMT);
5293 TypeHandle arrayType = ClassLoader::LoadArrayTypeThrowing(elementType);
5294 SetObjectReference(pManagedHome, AllocateArrayEx(arrayType, &cElements, 1), GetAppDomain());
5297 HELPER_METHOD_FRAME_END();
5301 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ConvertContentsToManaged, MngdHiddenLengthArrayMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5307 PTRARRAYREF arrayRef;
5308 STRINGREF stringRef;
5309 OBJECTREF objectRef;
5312 ZeroMemory(&gc, sizeof(gc));
5313 gc.arrayRef = (PTRARRAYREF)*pManagedHome;
5315 HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
5317 if (*pNativeHome != NULL)
5319 // There are these choices:
5320 // * the array is made up of entirely blittable data, in which case we can directly copy it,
5321 // * it is an array of strings that need to be marshaled as HSTRING,
5322 // * it is an array of non-blittable structures
5323 // * it is an array of interface pointers (interface, runtime class, delegate, System.Object)
5324 switch (pThis->m_vt)
5326 case VTHACK_BLITTABLERECORD:
5328 // Just do a raw memcpy into the array
5329 SIZE_T cbArray = pThis->GetArraySize(gc.arrayRef->GetNumComponents());
5330 memcpyNoGCRefs(gc.arrayRef->GetDataPtr(), *pNativeHome, cbArray);
5334 case VTHACK_HSTRING:
5336 // Strings are in HSRING format on the native side
5337 if (!WinRTSupported())
5339 COMPlusThrow(kPlatformNotSupportedException, W("PlatformNotSupported_WinRT"));
5342 HSTRING *pSourceStrings = reinterpret_cast<HSTRING *>(*pNativeHome);
5344 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5346 // NULL HSTRINGS are equivilent to empty strings
5347 UINT32 cchString = 0;
5348 LPCWSTR pwszString = W("");
5350 if (pSourceStrings[i] != NULL)
5352 pwszString = WindowsGetStringRawBuffer(pSourceStrings[i], &cchString);
5355 gc.stringRef = StringObject::NewString(pwszString, cchString);
5356 gc.arrayRef->SetAt(i, gc.stringRef);
5361 case VTHACK_NONBLITTABLERECORD:
5363 // Defer to the field marshaler to handle structures
5364 BYTE *pNativeStart = reinterpret_cast<BYTE *>(*pNativeHome);
5365 SIZE_T managedOffset = ArrayBase::GetDataPtrOffset(gc.arrayRef->GetMethodTable());
5366 SIZE_T nativeOffset = 0;
5367 SIZE_T managedSize = gc.arrayRef->GetComponentSize();
5368 SIZE_T nativeSize = pThis->m_pElementMT->GetNativeSize();
5369 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5371 LayoutUpdateCLR(reinterpret_cast<LPVOID *>(&gc.arrayRef), managedOffset, pThis->m_pElementMT, pNativeStart + nativeOffset);
5372 managedOffset += managedSize;
5373 nativeOffset += nativeSize;
5378 case VTHACK_INSPECTABLE:
5380 // interface pointers
5381 IUnknown **pSourceIPs = reinterpret_cast<IUnknown **>(*pNativeHome);
5383 // If this turns out to be a perf issue, we can precompute the ItfMarshalInfo
5384 // and generate code that passes it to the marshaler at creation time.
5385 ItfMarshalInfo itfInfo;
5386 MarshalInfo::GetItfMarshalInfo(TypeHandle(pThis->m_pElementMT), TypeHandle(), FALSE, TRUE, MarshalInfo::MARSHAL_SCENARIO_WINRT, &itfInfo);
5388 for (SIZE_T i = 0; i < gc.arrayRef->GetNumComponents(); ++i)
5390 gc.objectRef = gc.arrayRef->GetAt(i);
5391 UnmarshalObjectFromInterface(
5394 itfInfo.thItf.GetMethodTable(),
5395 itfInfo.thClass.GetMethodTable(),
5397 gc.arrayRef->SetAt(i, gc.objectRef);
5403 UNREACHABLE_MSG("Unrecognized array element VARTYPE");
5407 HELPER_METHOD_FRAME_END();
5411 FCIMPL3(void, MngdHiddenLengthArrayMarshaler::ClearNativeContents, MngdHiddenLengthArrayMarshaler* pThis, void** pNativeHome, INT32 cElements)
5415 HELPER_METHOD_FRAME_BEGIN_0();
5417 if (*pNativeHome != NULL)
5419 pThis->DoClearNativeContents(pNativeHome, cElements);
5422 HELPER_METHOD_FRAME_END();
5426 #endif // CROSSGEN_COMPILE
5429 SIZE_T MngdHiddenLengthArrayMarshaler::GetArraySize(SIZE_T elements)
5439 _ASSERTE_MSG(m_cbElementSize != 0, "You have to set the native size for your array element type");
5443 if (!ClrSafeInt<SIZE_T>::multiply(elements, m_cbElementSize, cbArray))
5445 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
5448 // This array size limit is carried over from the equivilent limit for other array marshaling code
5449 if (cbArray > MAX_SIZE_FOR_INTEROP)
5451 COMPlusThrow(kArgumentException, IDS_EE_STRUCTARRAYTOOLARGE);
5457 #ifndef CROSSGEN_COMPILE
5458 void MngdHiddenLengthArrayMarshaler::DoClearNativeContents(void** pNativeHome, INT32 cElements)
5465 PRECONDITION(pNativeHome != NULL);
5470 if (vt == VTHACK_REDIRECTEDTYPE)
5472 // the redirected types that use this helper are interface pointers on the WinRT side
5473 vt = VTHACK_INSPECTABLE;
5478 case VTHACK_HSTRING:
5480 if (WinRTSupported())
5482 HSTRING *pStrings = reinterpret_cast<HSTRING *>(*pNativeHome);
5483 for (INT32 i = 0; i < cElements; ++i)
5485 if (pStrings[i] != NULL)
5487 WindowsDeleteString(pStrings[i]);
5494 case VTHACK_NONBLITTABLERECORD:
5496 SIZE_T cbArray = GetArraySize(cElements);
5497 BYTE *pNativeCurrent = reinterpret_cast<BYTE *>(*pNativeHome);
5498 BYTE *pNativeEnd = pNativeCurrent + cbArray;
5500 while (pNativeCurrent < pNativeEnd)
5502 LayoutDestroyNative(pNativeCurrent, m_pElementMT);
5503 pNativeCurrent += m_pElementMT->GetNativeSize();
5508 case VTHACK_INSPECTABLE:
5510 IInspectable **pIPs = reinterpret_cast<IInspectable **>(*pNativeHome);
5511 for (INT32 i = 0; i < cElements; ++i)
5513 if (pIPs[i] != NULL)
5515 SafeRelease(pIPs[i]);
5522 UNREACHABLE_MSG("Unexpected hidden-length array element VT");
5525 #endif //CROSSGEN_COMPILE
5526 #endif // FEATURE_COMINTEROP
5528 void ILReferenceCustomMarshaler::EmitCreateMngdMarshaler(ILCodeStream* pslILEmit)
5533 PRECONDITION(-1 == m_dwMngdMarshalerLocalNum);
5538 // allocate space for marshaler
5541 m_dwMngdMarshalerLocalNum = pslILEmit->NewLocal(ELEMENT_TYPE_I);
5543 pslILEmit->EmitLDC(sizeof(MngdRefCustomMarshaler));
5544 pslILEmit->EmitLOCALLOC();
5545 pslILEmit->EmitSTLOC(m_dwMngdMarshalerLocalNum);
5547 pslILEmit->EmitLDLOC(m_dwMngdMarshalerLocalNum); // arg to CreateMarshaler
5550 // call CreateCustomMarshalerHelper
5553 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(m_pargs->rcm.m_pMD));
5554 pslILEmit->EmitCALL(METHOD__METHOD_HANDLE__GETVALUEINTERNAL, 1, 1);
5556 pslILEmit->EmitLDC(m_pargs->rcm.m_paramToken);
5558 pslILEmit->EmitLDTOKEN(pslILEmit->GetToken(TypeHandle::FromPtr(m_pargs->rcm.m_hndManagedType)));
5559 pslILEmit->EmitCALL(METHOD__RT_TYPE_HANDLE__GETVALUEINTERNAL, 1, 1);
5561 pslILEmit->EmitCALL(METHOD__STUBHELPERS__CREATE_CUSTOM_MARSHALER_HELPER, 3, 1); // arg to CreateMarshaler
5564 // call MngdRefCustomMarshaler::CreateMarshaler
5567 pslILEmit->EmitCALL(METHOD__MNGD_REF_CUSTOM_MARSHALER__CREATE_MARSHALER, 2, 0);
5571 #ifndef CROSSGEN_COMPILE
5573 FCIMPL2(void, MngdRefCustomMarshaler::CreateMarshaler, MngdRefCustomMarshaler* pThis, void* pCMHelper)
5577 pThis->m_pCMHelper = (CustomMarshalerHelper*)pCMHelper;
5582 FCIMPL3(void, MngdRefCustomMarshaler::ConvertContentsToNative, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5587 PRECONDITION(CheckPointer(pManagedHome));
5591 HELPER_METHOD_FRAME_BEGIN_0();
5593 *pNativeHome = pThis->m_pCMHelper->InvokeMarshalManagedToNativeMeth(*pManagedHome);
5595 HELPER_METHOD_FRAME_END();
5600 FCIMPL3(void, MngdRefCustomMarshaler::ConvertContentsToManaged, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5605 PRECONDITION(CheckPointer(pManagedHome));
5609 HELPER_METHOD_FRAME_BEGIN_0();
5611 SetObjectReference(pManagedHome, pThis->m_pCMHelper->InvokeMarshalNativeToManagedMeth(*pNativeHome), GetAppDomain());
5613 HELPER_METHOD_FRAME_END();
5617 FCIMPL3(void, MngdRefCustomMarshaler::ClearNative, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5621 HELPER_METHOD_FRAME_BEGIN_0();
5631 pThis->m_pCMHelper->InvokeCleanUpNativeMeth(*pNativeHome);
5633 HELPER_METHOD_FRAME_END();
5637 FCIMPL3(void, MngdRefCustomMarshaler::ClearManaged, MngdRefCustomMarshaler* pThis, OBJECTREF* pManagedHome, void** pNativeHome)
5642 PRECONDITION(CheckPointer(pManagedHome));
5646 HELPER_METHOD_FRAME_BEGIN_0();
5648 pThis->m_pCMHelper->InvokeCleanUpManagedMeth(*pManagedHome);
5650 HELPER_METHOD_FRAME_END();
5654 #endif // CROSSGEN_COMPILE
5657 #ifdef FEATURE_COMINTEROP
5659 ///////////////////////////////////////////////////////////////////////////////////////////////////
5660 // ILUriMarshaler implementation
5661 ///////////////////////////////////////////////////////////////////////////////////////////////////
5663 LocalDesc ILUriMarshaler::GetNativeType()
5665 LIMITED_METHOD_CONTRACT;
5666 return LocalDesc(ELEMENT_TYPE_I);
5669 LocalDesc ILUriMarshaler::GetManagedType()
5671 STANDARD_VM_CONTRACT;;
5672 BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
5673 TypeHandle hndUriType = pDomain->GetMarshalingData()->GetUriMarshalingInfo()->GetSystemUriType();
5675 return LocalDesc(hndUriType); // System.Uri
5678 bool ILUriMarshaler::NeedsClearNative()
5680 LIMITED_METHOD_CONTRACT;
5684 // Note that this method expects the CLR Uri on top of the evaluation stack and leaves the WinRT Uri there.
5686 void ILUriMarshaler::EmitConvertCLRUriToWinRTUri(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5688 STANDARD_VM_CONTRACT;
5690 UriMarshalingInfo* marshalingInfo = pDomain->GetMarshalingData()->GetUriMarshalingInfo();
5692 ILCodeLabel *pNotNullLabel = pslILEmit->NewCodeLabel();
5693 ILCodeLabel *pDoneLabel = pslILEmit->NewCodeLabel();
5695 pslILEmit->EmitDUP();
5696 pslILEmit->EmitBRTRUE(pNotNullLabel);
5698 pslILEmit->EmitPOP();
5699 pslILEmit->EmitLoadNullPtr();
5700 pslILEmit->EmitBR(pDoneLabel);
5702 pslILEmit->EmitLabel(pNotNullLabel);
5704 // System.Uri.get_OriginalString()
5705 MethodDesc* pSystemUriOriginalStringMD = marshalingInfo->GetSystemUriOriginalStringMD();
5706 pslILEmit->EmitCALL(pslILEmit->GetToken(pSystemUriOriginalStringMD), 1, 1);
5708 pslILEmit->EmitCALL(METHOD__URIMARSHALER__CREATE_NATIVE_URI_INSTANCE, 1, 1);
5710 pslILEmit->EmitLabel(pDoneLabel);
5713 void ILUriMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
5715 STANDARD_VM_CONTRACT;
5717 EmitLoadManagedValue(pslILEmit);
5718 EmitConvertCLRUriToWinRTUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5719 EmitStoreNativeValue(pslILEmit);
5722 // Note that this method expects the WinRT Uri on top of the evaluation stack and leaves the CLR Uri there.
5724 void ILUriMarshaler::EmitConvertWinRTUriToCLRUri(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5726 STANDARD_VM_CONTRACT;
5728 MethodDesc* pSystemUriCtorMD = pDomain->GetMarshalingData()->GetUriMarshalingInfo()->GetSystemUriCtorMD();
5730 ILCodeLabel *pNotNullLabel = pslILEmit->NewCodeLabel();
5731 ILCodeLabel *pDoneLabel = pslILEmit->NewCodeLabel();
5733 pslILEmit->EmitDUP();
5734 pslILEmit->EmitBRTRUE(pNotNullLabel);
5736 pslILEmit->EmitPOP();
5737 pslILEmit->EmitLDNULL();
5738 pslILEmit->EmitBR(pDoneLabel);
5740 pslILEmit->EmitLabel(pNotNullLabel);
5742 // string UriMarshaler.GetRawUriFromNative(IntPtr)
5743 pslILEmit->EmitCALL(METHOD__URIMARSHALER__GET_RAWURI_FROM_NATIVE, 1, 1);
5745 // System.Uri..ctor(string)
5746 pslILEmit->EmitNEWOBJ(pslILEmit->GetToken(pSystemUriCtorMD), 1);
5748 pslILEmit->EmitLabel(pDoneLabel);
5751 void ILUriMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5753 STANDARD_VM_CONTRACT;
5755 EmitLoadNativeValue(pslILEmit);
5756 EmitConvertWinRTUriToCLRUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5757 EmitStoreManagedValue(pslILEmit);
5760 void ILUriMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
5762 STANDARD_VM_CONTRACT;
5763 EmitInterfaceClearNative(pslILEmit);
5766 ///////////////////////////////////////////////////////////////////////////////////////////////////
5767 // ILNCCEventArgsMarshaler implementation
5768 ///////////////////////////////////////////////////////////////////////////////////////////////////
5770 LocalDesc ILNCCEventArgsMarshaler::GetNativeType()
5772 LIMITED_METHOD_CONTRACT;
5773 return LocalDesc(ELEMENT_TYPE_I);
5776 LocalDesc ILNCCEventArgsMarshaler::GetManagedType()
5778 STANDARD_VM_CONTRACT;;
5780 BaseDomain *pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
5781 TypeHandle hndNCCEventArgType = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemNCCEventArgsType();
5783 return LocalDesc(hndNCCEventArgType); // System.Collections.Specialized.NotifyCollectionChangedEventArgs
5786 bool ILNCCEventArgsMarshaler::NeedsClearNative()
5788 LIMITED_METHOD_CONTRACT;
5792 // Note that this method expects the CLR NotifyCollectionChangedEventArgs on top of the evaluation stack and
5793 // leaves the WinRT NotifyCollectionChangedEventArgs IP there.
5795 void ILNCCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream *pslILEmit, BaseDomain *pDomain)
5797 STANDARD_VM_CONTRACT;
5799 MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemNCCEventArgsToWinRTNCCEventArgsMD();
5801 // IntPtr System.Runtime.InteropServices.WindowsRuntime.NotifyCollectionChangedEventArgsMarshaler.ConvertToNative(NotifyCollectionChangedEventArgs)
5802 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5805 void ILNCCEventArgsMarshaler::EmitConvertContentsCLRToNative(ILCodeStream *pslILEmit)
5807 STANDARD_VM_CONTRACT;
5809 EmitLoadManagedValue(pslILEmit);
5810 EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5811 EmitStoreNativeValue(pslILEmit);
5814 // Note that this method expects the WinRT NotifyCollectionChangedEventArgs on top of the evaluation stack and
5815 // leaves the CLR NotifyCollectionChangedEventArgs there.
5817 void ILNCCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5819 STANDARD_VM_CONTRACT;
5821 MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetWinRTNCCEventArgsToSystemNCCEventArgsMD();
5823 // NotifyCollectionChangedEventArgs System.Runtime.InteropServices.WindowsRuntime.NotifyCollectionChangedEventArgsMarshaler.ConvertToManaged(IntPtr)
5824 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5827 void ILNCCEventArgsMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5829 STANDARD_VM_CONTRACT;
5831 EmitLoadNativeValue(pslILEmit);
5832 EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5833 EmitStoreManagedValue(pslILEmit);
5836 void ILNCCEventArgsMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
5838 STANDARD_VM_CONTRACT;
5839 EmitInterfaceClearNative(pslILEmit);
5842 ///////////////////////////////////////////////////////////////////////////////////////////////////
5843 // ILPCEventArgsMarshaler implementation
5844 ///////////////////////////////////////////////////////////////////////////////////////////////////
5846 LocalDesc ILPCEventArgsMarshaler::GetNativeType()
5848 LIMITED_METHOD_CONTRACT;
5849 return LocalDesc(ELEMENT_TYPE_I);
5852 LocalDesc ILPCEventArgsMarshaler::GetManagedType()
5854 STANDARD_VM_CONTRACT;;
5856 BaseDomain *pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain();
5857 TypeHandle hndPCEventArgType = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemPCEventArgsType();
5859 return LocalDesc(hndPCEventArgType); // System.ComponentModel.PropertyChangedEventArgs
5862 bool ILPCEventArgsMarshaler::NeedsClearNative()
5864 LIMITED_METHOD_CONTRACT;
5868 // Note that this method expects the CLR PropertyChangedEventArgs on top of the evaluation stack and
5869 // leaves the WinRT PropertyChangedEventArgs IP there.
5871 void ILPCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream *pslILEmit, BaseDomain *pDomain)
5873 STANDARD_VM_CONTRACT;
5875 MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemPCEventArgsToWinRTPCEventArgsMD();
5877 // IntPtr System.Runtime.InteropServices.WindowsRuntime.PropertyChangedEventArgsMarshaler.ConvertToNative(PropertyChangedEventArgs)
5878 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5881 void ILPCEventArgsMarshaler::EmitConvertContentsCLRToNative(ILCodeStream *pslILEmit)
5883 STANDARD_VM_CONTRACT;
5885 EmitLoadManagedValue(pslILEmit);
5886 EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5887 EmitStoreNativeValue(pslILEmit);
5890 // Note that this method expects the WinRT PropertyChangedEventArgs on top of the evaluation stack and
5891 // leaves the CLR PropertyChangedEventArgs there.
5893 void ILPCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain)
5895 STANDARD_VM_CONTRACT;
5897 MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetWinRTPCEventArgsToSystemPCEventArgsMD();
5899 // PropertyChangedEventArgs System.Runtime.InteropServices.WindowsRuntime.PropertyChangedEventArgsMarshaler.ConvertToManaged(IntPtr)
5900 pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1);
5903 void ILPCEventArgsMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5905 STANDARD_VM_CONTRACT;
5907 EmitLoadNativeValue(pslILEmit);
5908 EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain());
5909 EmitStoreManagedValue(pslILEmit);
5912 void ILPCEventArgsMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
5914 STANDARD_VM_CONTRACT;
5915 EmitInterfaceClearNative(pslILEmit);
5918 ///////////////////////////////////////////////////////////////////////////////////////////////////
5919 // ILDateTimeMarshaler implementation
5920 ///////////////////////////////////////////////////////////////////////////////////////////////////
5922 LocalDesc ILDateTimeMarshaler::GetNativeType()
5924 STANDARD_VM_CONTRACT;;
5925 return LocalDesc(MscorlibBinder::GetClass(CLASS__DATETIMENATIVE));
5928 LocalDesc ILDateTimeMarshaler::GetManagedType()
5930 STANDARD_VM_CONTRACT;;
5931 return LocalDesc(MscorlibBinder::GetClass(CLASS__DATE_TIME_OFFSET));
5934 bool ILDateTimeMarshaler::NeedsClearNative()
5936 LIMITED_METHOD_CONTRACT;
5940 void ILDateTimeMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
5945 PRECONDITION(CheckPointer(pslILEmit));
5949 // DateTimeOffsetMarshaler.ConvertManagedToNative(ref managedDTO, out nativeTicks);
5950 EmitLoadManagedHomeAddr(pslILEmit);
5951 EmitLoadNativeHomeAddr(pslILEmit);
5952 pslILEmit->EmitCALL(METHOD__DATETIMEOFFSETMARSHALER__CONVERT_TO_NATIVE, 2, 0);
5955 void ILDateTimeMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
5957 STANDARD_VM_CONTRACT;
5959 // DateTimeOffsetMarshaler.ConvertNativeToManaged(out managedLocalDTO, ref nativeTicks);
5960 EmitLoadManagedHomeAddr(pslILEmit);
5961 EmitLoadNativeHomeAddr(pslILEmit);
5962 pslILEmit->EmitCALL(METHOD__DATETIMEOFFSETMARSHALER__CONVERT_TO_MANAGED, 2, 0);
5965 void ILDateTimeMarshaler::EmitReInitNative(ILCodeStream* pslILEmit)
5967 STANDARD_VM_CONTRACT;
5969 EmitLoadNativeHomeAddr(pslILEmit);
5970 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__DATETIMENATIVE)));
5973 ///////////////////////////////////////////////////////////////////////////////////////////////////
5974 // ILNullableMarshaler implementation
5975 ///////////////////////////////////////////////////////////////////////////////////////////////////
5977 LocalDesc ILNullableMarshaler::GetNativeType()
5979 LIMITED_METHOD_CONTRACT;
5980 return LocalDesc(ELEMENT_TYPE_I);
5983 LocalDesc ILNullableMarshaler::GetManagedType()
5985 LIMITED_METHOD_CONTRACT;;
5986 return LocalDesc(m_pargs->m_pMT);
5989 bool ILNullableMarshaler::NeedsClearNative()
5991 LIMITED_METHOD_CONTRACT;
5995 void ILNullableMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
6000 PRECONDITION(CheckPointer(pslILEmit));
6004 // pNative = NullableMarshaler<T>.ConvertToNative(ref pManaged);
6005 EmitLoadManagedHomeAddr(pslILEmit);
6007 MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__NULLABLEMARSHALER__CONVERT_TO_NATIVE));
6008 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6010 EmitStoreNativeValue(pslILEmit);
6013 void ILNullableMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
6015 STANDARD_VM_CONTRACT;
6017 // pManaged = NullableMarshaler.ConvertToManaged(pNative);
6018 EmitLoadNativeValue(pslILEmit);
6020 MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__NULLABLEMARSHALER__CONVERT_TO_MANAGED));
6021 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6023 EmitStoreManagedValue(pslILEmit);
6026 void ILNullableMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
6028 STANDARD_VM_CONTRACT;
6029 EmitInterfaceClearNative(pslILEmit);
6032 MethodDesc *ILNullableMarshaler::GetExactMarshalerMethod(MethodDesc *pGenericMD)
6034 STANDARD_VM_CONTRACT;
6036 return MethodDesc::FindOrCreateAssociatedMethodDesc(
6038 pGenericMD->GetMethodTable(),
6039 FALSE, // forceBoxedEntryPoint
6040 m_pargs->m_pMT->GetInstantiation(), // methodInst
6041 FALSE, // allowInstParam
6042 TRUE); // forceRemotableMethod
6045 ///////////////////////////////////////////////////////////////////////////////////////////////////
6046 // ILSystemTypeMarshaler implementation
6047 ///////////////////////////////////////////////////////////////////////////////////////////////////
6049 LocalDesc ILSystemTypeMarshaler::GetNativeType()
6051 STANDARD_VM_CONTRACT;
6053 return LocalDesc(MscorlibBinder::GetClass(CLASS__TYPENAMENATIVE));
6056 LocalDesc ILSystemTypeMarshaler::GetManagedType()
6058 STANDARD_VM_CONTRACT;
6060 return LocalDesc(MscorlibBinder::GetClass(CLASS__TYPE));
6063 bool ILSystemTypeMarshaler::NeedsClearNative()
6065 LIMITED_METHOD_CONTRACT;
6069 void ILSystemTypeMarshaler::EmitConvertContentsCLRToNative(ILCodeStream * pslILEmit)
6071 STANDARD_VM_CONTRACT;
6073 // SystemTypeMarshaler.ConvertToNative(Type, pTypeName);
6074 EmitLoadManagedValue(pslILEmit);
6075 EmitLoadNativeHomeAddr(pslILEmit);
6076 pslILEmit->EmitCALL(METHOD__SYSTEMTYPEMARSHALER__CONVERT_TO_NATIVE, 2, 0);
6079 void ILSystemTypeMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream * pslILEmit)
6081 STANDARD_VM_CONTRACT;
6083 // type = SystemTypeMarshaler.ConvertNativeToManaged(pTypeName, ref Type);
6084 EmitLoadNativeHomeAddr(pslILEmit);
6085 EmitLoadManagedHomeAddr(pslILEmit);
6086 pslILEmit->EmitCALL(METHOD__SYSTEMTYPEMARSHALER__CONVERT_TO_MANAGED, 2, 0);
6090 void ILSystemTypeMarshaler::EmitClearNative(ILCodeStream * pslILEmit)
6092 STANDARD_VM_CONTRACT;
6094 // SystemTypeMarshaler.ClearNative(pTypeName)
6095 EmitLoadNativeHomeAddr(pslILEmit);
6096 pslILEmit->EmitCALL(METHOD__SYSTEMTYPEMARSHALER__CLEAR_NATIVE, 1, 0);
6099 void ILSystemTypeMarshaler::EmitReInitNative(ILCodeStream * pslILEmit)
6101 EmitLoadNativeHomeAddr(pslILEmit);
6102 pslILEmit->EmitINITOBJ(pslILEmit->GetToken(MscorlibBinder::GetClass(CLASS__TYPENAMENATIVE)));
6105 ///////////////////////////////////////////////////////////////////////////////////////////////////
6106 // ILHResultExceptionMarshaler implementation
6107 ///////////////////////////////////////////////////////////////////////////////////////////////////
6109 LocalDesc ILHResultExceptionMarshaler::GetNativeType()
6111 LIMITED_METHOD_CONTRACT;
6112 return LocalDesc(ELEMENT_TYPE_I4);
6115 LocalDesc ILHResultExceptionMarshaler::GetManagedType()
6117 LIMITED_METHOD_CONTRACT;
6118 _ASSERTE(m_pargs->m_pMT != NULL);
6119 return LocalDesc(m_pargs->m_pMT);
6122 bool ILHResultExceptionMarshaler::NeedsClearNative()
6124 LIMITED_METHOD_CONTRACT;
6128 void ILHResultExceptionMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
6133 PRECONDITION(CheckPointer(pslILEmit));
6137 // int HResultExceptionMarshaler.ConvertManagedToNative(Exception);
6138 EmitLoadManagedValue(pslILEmit);
6139 pslILEmit->EmitCALL(METHOD__HRESULTEXCEPTIONMARSHALER__CONVERT_TO_NATIVE, 1, 1);
6140 EmitStoreNativeValue(pslILEmit);
6143 void ILHResultExceptionMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
6148 PRECONDITION(CheckPointer(pslILEmit));
6152 // Exception HResultExceptionMarshaler.ConvertNativeToManaged(int hr);
6153 EmitLoadNativeValue(pslILEmit);
6154 pslILEmit->EmitCALL(METHOD__HRESULTEXCEPTIONMARSHALER__CONVERT_TO_MANAGED, 1, 1);
6155 EmitStoreManagedValue(pslILEmit);
6158 ///////////////////////////////////////////////////////////////////////////////////////////////////
6159 // ILKeyValuePairMarshaler implementation
6160 ///////////////////////////////////////////////////////////////////////////////////////////////////
6162 LocalDesc ILKeyValuePairMarshaler::GetNativeType()
6164 LIMITED_METHOD_CONTRACT;
6165 return LocalDesc(ELEMENT_TYPE_I);
6168 LocalDesc ILKeyValuePairMarshaler::GetManagedType()
6170 LIMITED_METHOD_CONTRACT;;
6171 return LocalDesc(m_pargs->m_pMT);
6174 bool ILKeyValuePairMarshaler::NeedsClearNative()
6176 LIMITED_METHOD_CONTRACT;
6180 void ILKeyValuePairMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit)
6182 STANDARD_VM_CONTRACT;
6184 // Native = KeyValueMarshaler<K, V>.ConvertToNative([In] ref Managed);
6185 EmitLoadManagedHomeAddr(pslILEmit);
6187 MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__KEYVALUEPAIRMARSHALER__CONVERT_TO_NATIVE));
6188 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6190 EmitStoreNativeValue(pslILEmit);
6193 void ILKeyValuePairMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit)
6195 STANDARD_VM_CONTRACT;
6197 // Managed = KeyValuePairMarshaler<K, V>.ConvertToManaged(Native);
6198 EmitLoadNativeValue(pslILEmit);
6200 MethodDesc *pMD = GetExactMarshalerMethod(MscorlibBinder::GetMethod(METHOD__KEYVALUEPAIRMARSHALER__CONVERT_TO_MANAGED));
6201 pslILEmit->EmitCALL(pslILEmit->GetToken(pMD), 1, 1);
6203 EmitStoreManagedValue(pslILEmit);
6206 void ILKeyValuePairMarshaler::EmitClearNative(ILCodeStream* pslILEmit)
6208 STANDARD_VM_CONTRACT;
6209 EmitInterfaceClearNative(pslILEmit);
6212 MethodDesc *ILKeyValuePairMarshaler::GetExactMarshalerMethod(MethodDesc *pGenericMD)
6214 STANDARD_VM_CONTRACT;
6216 // KeyValuePairMarshaler methods are generic - find/create the exact method.
6217 return MethodDesc::FindOrCreateAssociatedMethodDesc(
6219 pGenericMD->GetMethodTable(),
6220 FALSE, // forceBoxedEntryPoint
6221 m_pargs->m_pMT->GetInstantiation(), // methodInst
6222 FALSE, // allowInstParam
6223 TRUE); // forceRemotableMethod
6226 #endif // FEATURE_COMINTEROP